better fluid spreading (#14529)
This commit is contained in:
@@ -3,13 +3,13 @@ using System.Linq;
|
|||||||
using Content.Server.Fluids.Components;
|
using Content.Server.Fluids.Components;
|
||||||
using Content.Shared;
|
using Content.Shared;
|
||||||
using Content.Shared.Directions;
|
using Content.Shared.Directions;
|
||||||
|
using Content.Shared.Maps;
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Map.Components;
|
using Robust.Shared.Map.Components;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Physics.Systems;
|
||||||
using Robust.Shared.Physics.Components;
|
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Server.Fluids.EntitySystems;
|
namespace Content.Server.Fluids.EntitySystems;
|
||||||
@@ -23,6 +23,8 @@ public sealed class FluidSpreaderSystem : EntitySystem
|
|||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
[Dependency] private readonly PuddleSystem _puddleSystem = default!;
|
[Dependency] private readonly PuddleSystem _puddleSystem = default!;
|
||||||
|
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||||
|
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds an overflow component to the map data component tracking overflowing puddles
|
/// Adds an overflow component to the map data component tracking overflowing puddles
|
||||||
@@ -72,20 +74,19 @@ public sealed class FluidSpreaderSystem : EntitySystem
|
|||||||
puddles.Clear();
|
puddles.Clear();
|
||||||
var pos = transform.Coordinates;
|
var pos = transform.Coordinates;
|
||||||
|
|
||||||
var totalVolume = _puddleSystem.CurrentVolume(puddle.Owner, puddle);
|
var totalVolume = _puddleSystem.CurrentVolume(puddleUid, puddle);
|
||||||
exploreDirections.Shuffle();
|
exploreDirections.Shuffle();
|
||||||
foreach (var direction in exploreDirections)
|
foreach (var direction in exploreDirections)
|
||||||
{
|
{
|
||||||
var newPos = pos.Offset(direction);
|
var newPos = pos.Offset(direction);
|
||||||
if (CheckTile(puddle.Owner, puddle, newPos, mapGrid,
|
if (CheckTile(puddleUid, puddle, newPos, mapGrid, puddleQuery, out var uid, out var component))
|
||||||
out var puddleComponent))
|
|
||||||
{
|
{
|
||||||
puddles.Add(puddleComponent);
|
puddles.Add(component);
|
||||||
totalVolume += _puddleSystem.CurrentVolume(puddleComponent.Owner, puddleComponent);
|
totalVolume += _puddleSystem.CurrentVolume(uid.Value, component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_puddleSystem.EqualizePuddles(puddle.Owner, puddles, totalVolume, newIteration, puddle);
|
_puddleSystem.EqualizePuddles(puddleUid, puddles, totalVolume, newIteration, puddle);
|
||||||
}
|
}
|
||||||
|
|
||||||
fluidMapData.Puddles.Clear();
|
fluidMapData.Puddles.Clear();
|
||||||
@@ -100,49 +101,57 @@ public sealed class FluidSpreaderSystem : EntitySystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="srcUid">Entity Uid of original puddle</param>
|
/// <param name="srcUid">Entity Uid of original puddle</param>
|
||||||
/// <param name="srcPuddle">PuddleComponent attached to srcUid</param>
|
/// <param name="srcPuddle">PuddleComponent attached to srcUid</param>
|
||||||
/// <param name="pos">at which to check tile</param>
|
/// <param name="dstPos">at which to check tile</param>
|
||||||
/// <param name="mapGrid">helper param needed to extract entities</param>
|
/// <param name="mapGrid">helper param needed to extract entities</param>
|
||||||
/// <param name="puddle">either found or newly created PuddleComponent.</param>
|
/// <param name="newPuddleUid">either found or newly created PuddleComponent.</param>
|
||||||
/// <returns>true if tile is empty or occupied by a non-overflowing puddle (or a puddle close to being overflowing)</returns>
|
/// <returns>true if tile is empty or occupied by a non-overflowing puddle (or a puddle close to being overflowing)</returns>
|
||||||
private bool CheckTile(EntityUid srcUid, PuddleComponent srcPuddle, EntityCoordinates pos, MapGridComponent mapGrid,
|
private bool CheckTile(EntityUid srcUid, PuddleComponent srcPuddle, EntityCoordinates dstPos,
|
||||||
[NotNullWhen(true)] out PuddleComponent? puddle)
|
MapGridComponent mapGrid, EntityQuery<PuddleComponent> puddleQuery,
|
||||||
|
[NotNullWhen(true)] out EntityUid? newPuddleUid, [NotNullWhen(true)] out PuddleComponent? newPuddleComp)
|
||||||
{
|
{
|
||||||
if (!mapGrid.TryGetTileRef(pos, out var tileRef)
|
if (!mapGrid.TryGetTileRef(dstPos, out var tileRef)
|
||||||
|| tileRef.Tile.IsEmpty)
|
|| tileRef.Tile.IsEmpty)
|
||||||
{
|
{
|
||||||
puddle = null;
|
newPuddleUid = null;
|
||||||
|
newPuddleComp = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if puddle can spread there at all
|
||||||
|
var dstMap = dstPos.ToMap(EntityManager, _transform);
|
||||||
|
var dst = dstMap.Position;
|
||||||
|
var src = Transform(srcUid).MapPosition.Position;
|
||||||
|
var dir = src - dst;
|
||||||
|
var ray = new CollisionRay(dst, dir.Normalized, (int) (CollisionGroup.Impassable | CollisionGroup.HighImpassable));
|
||||||
|
var mapId = dstMap.MapId;
|
||||||
|
var results = _physics.IntersectRay(mapId, ray, dir.Length, returnOnFirstHit: true);
|
||||||
|
if (results.Any())
|
||||||
|
{
|
||||||
|
newPuddleUid = null;
|
||||||
|
newPuddleComp = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var puddleCurrentVolume = _puddleSystem.CurrentVolume(srcUid, srcPuddle);
|
var puddleCurrentVolume = _puddleSystem.CurrentVolume(srcUid, srcPuddle);
|
||||||
|
foreach (var entity in dstPos.GetEntitiesInTile())
|
||||||
foreach (var entity in mapGrid.GetAnchoredEntities(pos))
|
|
||||||
{
|
{
|
||||||
// If this is valid puddle check if we spread to it.
|
if (puddleQuery.TryGetComponent(entity, out var existingPuddle))
|
||||||
if (TryComp(entity, out PuddleComponent? existingPuddle))
|
|
||||||
{
|
{
|
||||||
// If current puddle has more volume than current we skip that field
|
if (_puddleSystem.CurrentVolume(entity, existingPuddle) >= puddleCurrentVolume)
|
||||||
if (_puddleSystem.CurrentVolume(existingPuddle.Owner, existingPuddle) >= puddleCurrentVolume)
|
|
||||||
{
|
{
|
||||||
puddle = null;
|
newPuddleUid = null;
|
||||||
|
newPuddleComp = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
newPuddleUid = entity;
|
||||||
puddle = existingPuddle;
|
newPuddleComp = existingPuddle;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// if not puddle is this tile blocked by an object like wall or door
|
|
||||||
if (TryComp(entity, out PhysicsComponent? physComponent)
|
_puddleSystem.SpawnPuddle(srcUid, dstPos, srcPuddle, out var uid, out var comp);
|
||||||
&& physComponent.CanCollide
|
newPuddleUid = uid;
|
||||||
&& (physComponent.CollisionLayer & (int) CollisionGroup.MobMask) != 0)
|
newPuddleComp = comp;
|
||||||
{
|
|
||||||
puddle = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
puddle = _puddleSystem.SpawnPuddle(srcUid, pos, srcPuddle);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -266,17 +266,15 @@ namespace Content.Server.Fluids.EntitySystems
|
|||||||
return CurrentVolume(uid, puddle) > puddle.OverflowVolume;
|
return CurrentVolume(uid, puddle) > puddle.OverflowVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PuddleComponent SpawnPuddle(EntityUid srcUid, EntityCoordinates pos, PuddleComponent? srcPuddleComponent = null)
|
public void SpawnPuddle(EntityUid srcUid, EntityCoordinates pos, PuddleComponent srcPuddleComponent, out EntityUid uid, out PuddleComponent component)
|
||||||
{
|
{
|
||||||
MetaDataComponent? metadata = null;
|
MetaDataComponent? metadata = null;
|
||||||
Resolve(srcUid, ref srcPuddleComponent, ref metadata);
|
Resolve(srcUid, ref metadata);
|
||||||
|
|
||||||
var prototype = metadata?.EntityPrototype?.ID ?? "PuddleSmear"; // TODO Spawn a entity based on another entity
|
var prototype = metadata?.EntityPrototype?.ID ?? "PuddleSmear"; // TODO Spawn a entity based on another entity
|
||||||
|
|
||||||
var destUid = EntityManager.SpawnEntity(prototype, pos);
|
uid = EntityManager.SpawnEntity(prototype, pos);
|
||||||
var destPuddle = EntityManager.EnsureComponent<PuddleComponent>(destUid);
|
component = EntityManager.EnsureComponent<PuddleComponent>(uid);
|
||||||
|
|
||||||
return destPuddle;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user