diff --git a/Content.Server/Fluids/EntitySystems/FluidSpreaderSystem.cs b/Content.Server/Fluids/EntitySystems/FluidSpreaderSystem.cs index 84f0fc263d..20f786d6cd 100644 --- a/Content.Server/Fluids/EntitySystems/FluidSpreaderSystem.cs +++ b/Content.Server/Fluids/EntitySystems/FluidSpreaderSystem.cs @@ -3,13 +3,13 @@ using System.Linq; using Content.Server.Fluids.Components; using Content.Shared; using Content.Shared.Directions; +using Content.Shared.Maps; using Content.Shared.Physics; using JetBrains.Annotations; using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Physics; -using Robust.Shared.Utility; -using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Systems; using Robust.Shared.Timing; namespace Content.Server.Fluids.EntitySystems; @@ -23,6 +23,8 @@ public sealed class FluidSpreaderSystem : EntitySystem [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly PuddleSystem _puddleSystem = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; /// /// Adds an overflow component to the map data component tracking overflowing puddles @@ -72,20 +74,19 @@ public sealed class FluidSpreaderSystem : EntitySystem puddles.Clear(); var pos = transform.Coordinates; - var totalVolume = _puddleSystem.CurrentVolume(puddle.Owner, puddle); + var totalVolume = _puddleSystem.CurrentVolume(puddleUid, puddle); exploreDirections.Shuffle(); foreach (var direction in exploreDirections) { var newPos = pos.Offset(direction); - if (CheckTile(puddle.Owner, puddle, newPos, mapGrid, - out var puddleComponent)) + if (CheckTile(puddleUid, puddle, newPos, mapGrid, puddleQuery, out var uid, out var component)) { - puddles.Add(puddleComponent); - totalVolume += _puddleSystem.CurrentVolume(puddleComponent.Owner, puddleComponent); + puddles.Add(component); + totalVolume += _puddleSystem.CurrentVolume(uid.Value, component); } } - _puddleSystem.EqualizePuddles(puddle.Owner, puddles, totalVolume, newIteration, puddle); + _puddleSystem.EqualizePuddles(puddleUid, puddles, totalVolume, newIteration, puddle); } fluidMapData.Puddles.Clear(); @@ -100,49 +101,57 @@ public sealed class FluidSpreaderSystem : EntitySystem /// /// Entity Uid of original puddle /// PuddleComponent attached to srcUid - /// at which to check tile + /// at which to check tile /// helper param needed to extract entities - /// either found or newly created PuddleComponent. + /// either found or newly created PuddleComponent. /// true if tile is empty or occupied by a non-overflowing puddle (or a puddle close to being overflowing) - private bool CheckTile(EntityUid srcUid, PuddleComponent srcPuddle, EntityCoordinates pos, MapGridComponent mapGrid, - [NotNullWhen(true)] out PuddleComponent? puddle) + private bool CheckTile(EntityUid srcUid, PuddleComponent srcPuddle, EntityCoordinates dstPos, + MapGridComponent mapGrid, EntityQuery 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) { - 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; } var puddleCurrentVolume = _puddleSystem.CurrentVolume(srcUid, srcPuddle); - - foreach (var entity in mapGrid.GetAnchoredEntities(pos)) + foreach (var entity in dstPos.GetEntitiesInTile()) { - // If this is valid puddle check if we spread to it. - if (TryComp(entity, out PuddleComponent? existingPuddle)) + if (puddleQuery.TryGetComponent(entity, out var existingPuddle)) { - // If current puddle has more volume than current we skip that field - if (_puddleSystem.CurrentVolume(existingPuddle.Owner, existingPuddle) >= puddleCurrentVolume) + if (_puddleSystem.CurrentVolume(entity, existingPuddle) >= puddleCurrentVolume) { - puddle = null; + newPuddleUid = null; + newPuddleComp = null; return false; } - - puddle = existingPuddle; + newPuddleUid = entity; + newPuddleComp = existingPuddle; return true; } - - // if not puddle is this tile blocked by an object like wall or door - if (TryComp(entity, out PhysicsComponent? physComponent) - && physComponent.CanCollide - && (physComponent.CollisionLayer & (int) CollisionGroup.MobMask) != 0) - { - puddle = null; - return false; - } } - puddle = _puddleSystem.SpawnPuddle(srcUid, pos, srcPuddle); + _puddleSystem.SpawnPuddle(srcUid, dstPos, srcPuddle, out var uid, out var comp); + newPuddleUid = uid; + newPuddleComp = comp; return true; } } diff --git a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs index 7eb16ec0cb..0a9f8a8332 100644 --- a/Content.Server/Fluids/EntitySystems/PuddleSystem.cs +++ b/Content.Server/Fluids/EntitySystems/PuddleSystem.cs @@ -266,17 +266,15 @@ namespace Content.Server.Fluids.EntitySystems 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; - 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 destUid = EntityManager.SpawnEntity(prototype, pos); - var destPuddle = EntityManager.EnsureComponent(destUid); - - return destPuddle; + uid = EntityManager.SpawnEntity(prototype, pos); + component = EntityManager.EnsureComponent(uid); } } }