From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Sat, 30 Mar 2024 04:17:53 +0000 (+1300) Subject: Atmos device performance improvements (#26493) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=888a3bda515a214733bf748c5d6a7e7c923a301e;p=space-station-14.git Atmos device performance improvements (#26493) * Atmos device performance improvements * AtmosDirection perf improvements * Fix errors * Add GasTileOverlayComponent arguments * Make excite no longer invalidate a tile --- diff --git a/Content.Server/Atmos/EntitySystems/AirFilterSystem.cs b/Content.Server/Atmos/EntitySystems/AirFilterSystem.cs index d947e60b6d..2ab15cfb17 100644 --- a/Content.Server/Atmos/EntitySystems/AirFilterSystem.cs +++ b/Content.Server/Atmos/EntitySystems/AirFilterSystem.cs @@ -13,6 +13,7 @@ public sealed class AirFilterSystem : EntitySystem { [Dependency] private readonly AtmosphereSystem _atmosphere = default!; [Dependency] private readonly IMapManager _map = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; public override void Initialize() { @@ -31,7 +32,7 @@ public sealed class AirFilterSystem : EntitySystem if (air.Pressure >= intake.Pressure) return; - var environment = _atmosphere.GetContainingMixture(uid, true, true); + var environment = _atmosphere.GetContainingMixture(uid, args.Grid, args.Map, true, true); // nothing to intake from if (environment == null) return; @@ -63,12 +64,11 @@ public sealed class AirFilterSystem : EntitySystem var oxygen = air.GetMoles(filter.Oxygen) / air.TotalMoles; var gases = oxygen >= filter.TargetOxygen ? filter.Gases : filter.OverflowGases; - var coordinates = Transform(uid).MapPosition; GasMixture? destination = null; - if (_map.TryFindGridAt(coordinates, out _, out var grid)) + if (args.Grid is {} grid) { - var tile = grid.GetTileRef(coordinates); - destination = _atmosphere.GetTileMixture(tile.GridUid, null, tile.GridIndices, true); + var position = _transform.GetGridTilePositionOrDefault(uid); + destination = _atmosphere.GetTileMixture(grid, args.Map, position, true); } if (destination != null) diff --git a/Content.Server/Atmos/EntitySystems/AtmosExposedSystem.cs b/Content.Server/Atmos/EntitySystems/AtmosExposedSystem.cs index 4be4d8271f..9590b9aa54 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosExposedSystem.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosExposedSystem.cs @@ -24,6 +24,8 @@ namespace Content.Server.Atmos.EntitySystems /// /// Event that tries to query the mixture a certain entity is exposed to. + /// This is mainly intended for use with entities inside of containers. + /// This event is not raised for entities that are directly parented to the grid. /// [ByRefEvent] public struct AtmosExposedGetAirEvent @@ -31,7 +33,7 @@ namespace Content.Server.Atmos.EntitySystems /// /// The entity we want to query this for. /// - public readonly EntityUid Entity; + public readonly Entity Entity; /// /// The mixture that the entity is exposed to. Output parameter. @@ -39,9 +41,9 @@ namespace Content.Server.Atmos.EntitySystems public GasMixture? Gas = null; /// - /// Whether to invalidate the mixture, if possible. + /// Whether to excite the mixture, if possible. /// - public bool Invalidate = false; + public readonly bool Excite = false; /// /// Whether this event has been handled or not. @@ -49,10 +51,10 @@ namespace Content.Server.Atmos.EntitySystems /// public bool Handled = false; - public AtmosExposedGetAirEvent(EntityUid entity, bool invalidate = false) + public AtmosExposedGetAirEvent(Entity entity, bool excite = false) { Entity = entity; - Invalidate = invalidate; + Excite = excite; } } } diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs index fb94fe414b..614d550c2f 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs @@ -4,6 +4,7 @@ using Content.Server.Atmos.Piping.Components; using Content.Server.Atmos.Reactions; using Content.Server.NodeContainer.NodeGroups; using Content.Shared.Atmos; +using Content.Shared.Atmos.Components; using Robust.Shared.Map.Components; using Robust.Shared.Utility; @@ -11,41 +12,39 @@ namespace Content.Server.Atmos.EntitySystems; public partial class AtmosphereSystem { - public GasMixture? GetContainingMixture(EntityUid uid, bool ignoreExposed = false, bool excite = false, TransformComponent? transform = null) + public GasMixture? GetContainingMixture(Entity ent, bool ignoreExposed = false, bool excite = false) { - if (!ignoreExposed) - { - // Used for things like disposals/cryo to change which air people are exposed to. - var ev = new AtmosExposedGetAirEvent(uid, excite); - - // Give the entity itself a chance to handle this. - RaiseLocalEvent(uid, ref ev, false); - - if (ev.Handled) - return ev.Gas; + if (!Resolve(ent, ref ent.Comp)) + return null; - // We need to get the parent now, so we need the transform... If the parent is invalid, we can't do much else. - if(!Resolve(uid, ref transform) || !transform.ParentUid.IsValid() || transform.MapUid == null) - return GetTileMixture(null, null, Vector2i.Zero, excite); + return GetContainingMixture(ent, ent.Comp.GridUid, ent.Comp.MapUid, ignoreExposed, excite); + } - // Give the parent entity a chance to handle the event... - RaiseLocalEvent(transform.ParentUid, ref ev, false); + public GasMixture? GetContainingMixture( + Entity ent, + Entity? grid, + Entity? map, + bool ignoreExposed = false, + bool excite = false) + { + if (!Resolve(ent, ref ent.Comp)) + return null; + if (!ignoreExposed && !ent.Comp.Anchored) + { + // Used for things like disposals/cryo to change which air people are exposed to. + var ev = new AtmosExposedGetAirEvent((ent, ent.Comp), excite); + RaiseLocalEvent(ent, ref ev); if (ev.Handled) return ev.Gas; - } - // Oops, we did a little bit of code duplication... - else if(!Resolve(uid, ref transform)) - { - return GetTileMixture(null, null, Vector2i.Zero, excite); - } + // TODO ATMOS: recursively iterate up through parents + // This really needs recursive InContainer metadata flag for performance + // And ideally some fast way to get the innermost airtight container. + } - var gridUid = transform.GridUid; - var mapUid = transform.MapUid; - var position = _transformSystem.GetGridOrMapTilePosition(uid, transform); - - return GetTileMixture(gridUid, mapUid, position, excite); + var position = _transformSystem.GetGridTilePositionOrDefault((ent, ent.Comp)); + return GetTileMixture(grid, map, position, excite); } public bool HasAtmosphere(EntityUid gridUid) => _atmosQuery.HasComponent(gridUid); @@ -84,21 +83,28 @@ public partial class AtmosphereSystem entity.Comp.InvalidatedCoords.Add(tile); } - public GasMixture?[]? GetTileMixtures(Entity? grid, Entity? map, List tiles, bool excite = false) + public GasMixture?[]? GetTileMixtures( + Entity? grid, + Entity? map, + List tiles, + bool excite = false) { GasMixture?[]? mixtures = null; var handled = false; // If we've been passed a grid, try to let it handle it. - if (grid is {} gridEnt && Resolve(gridEnt, ref gridEnt.Comp)) + if (grid is {} gridEnt && Resolve(gridEnt, ref gridEnt.Comp1)) { + if (excite) + Resolve(gridEnt, ref gridEnt.Comp2); + handled = true; mixtures = new GasMixture?[tiles.Count]; for (var i = 0; i < tiles.Count; i++) { var tile = tiles[i]; - if (!gridEnt.Comp.Tiles.TryGetValue(tile, out var atmosTile)) + if (!gridEnt.Comp1.Tiles.TryGetValue(tile, out var atmosTile)) { // need to get map atmosphere handled = false; @@ -108,7 +114,10 @@ public partial class AtmosphereSystem mixtures[i] = atmosTile.Air; if (excite) - gridEnt.Comp.InvalidatedCoords.Add(tile); + { + AddActiveTile(gridEnt.Comp1, atmosTile); + InvalidateVisuals((gridEnt.Owner, gridEnt.Comp2), tile); + } } } @@ -146,15 +155,22 @@ public partial class AtmosphereSystem return GetTileMixture(entity.Comp.GridUid, entity.Comp.MapUid, indices, excite); } - public GasMixture? GetTileMixture(Entity? grid, Entity? map, Vector2i gridTile, bool excite = false) + public GasMixture? GetTileMixture( + Entity? grid, + Entity? map, + Vector2i gridTile, + bool excite = false) { // If we've been passed a grid, try to let it handle it. if (grid is {} gridEnt - && Resolve(gridEnt, ref gridEnt.Comp, false) - && gridEnt.Comp.Tiles.TryGetValue(gridTile, out var tile)) + && Resolve(gridEnt, ref gridEnt.Comp1, false) + && gridEnt.Comp1.Tiles.TryGetValue(gridTile, out var tile)) { if (excite) - gridEnt.Comp.InvalidatedCoords.Add(gridTile); + { + AddActiveTile(gridEnt.Comp1, tile); + InvalidateVisuals((grid.Value.Owner, grid.Value.Comp2), gridTile); + } return tile.Air; } diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.ExcitedGroup.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.ExcitedGroup.cs index de4c9199cf..c1b58f7a77 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.ExcitedGroup.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.ExcitedGroup.cs @@ -1,5 +1,7 @@ using Content.Server.Atmos.Components; using Content.Shared.Atmos; +using Content.Shared.Atmos.Components; +using Robust.Shared.Map.Components; using Robust.Shared.Utility; namespace Content.Server.Atmos.EntitySystems @@ -64,10 +66,12 @@ namespace Content.Server.Atmos.EntitySystems excitedGroup.DismantleCooldown = 0; } - private void ExcitedGroupSelfBreakdown(GridAtmosphereComponent gridAtmosphere, ExcitedGroup excitedGroup) + private void ExcitedGroupSelfBreakdown( + Entity ent, + ExcitedGroup excitedGroup) { DebugTools.Assert(!excitedGroup.Disposed, "Excited group is disposed!"); - DebugTools.Assert(gridAtmosphere.ExcitedGroups.Contains(excitedGroup), "Grid Atmosphere does not contain Excited Group!"); + DebugTools.Assert(ent.Comp1.ExcitedGroups.Contains(excitedGroup), "Grid Atmosphere does not contain Excited Group!"); var combined = new GasMixture(Atmospherics.CellVolume); var tileSize = excitedGroup.Tiles.Count; @@ -77,7 +81,7 @@ namespace Content.Server.Atmos.EntitySystems if (tileSize == 0) { - ExcitedGroupDispose(gridAtmosphere, excitedGroup); + ExcitedGroupDispose(ent.Comp1, excitedGroup); return; } @@ -103,7 +107,7 @@ namespace Content.Server.Atmos.EntitySystems continue; tile.Air.CopyFromMutable(combined); - InvalidateVisuals(tile.GridIndex, tile.GridIndices); + InvalidateVisuals(ent, tile); } excitedGroup.BreakdownCooldown = 0; diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.GridAtmosphere.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.GridAtmosphere.cs index bd45030896..4b9ef49a40 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.GridAtmosphere.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.GridAtmosphere.cs @@ -1,4 +1,3 @@ -using System.Linq; using Content.Server.Atmos.Components; using Content.Server.Atmos.Reactions; using Content.Shared.Atmos; @@ -160,7 +159,7 @@ public sealed partial class AtmosphereSystem } /// - /// Update array of adjacent tiles and the adjacency flags. Optionally activates all tiles with modified adjacencies. + /// Update array of adjacent tiles and the adjacency flags. /// private void UpdateAdjacentTiles( Entity ent, @@ -195,14 +194,16 @@ public sealed partial class AtmosphereSystem if (activate) AddActiveTile(atmos, adjacent); - var oppositeDirection = direction.GetOpposite(); + var oppositeIndex = i.ToOppositeIndex(); + var oppositeDirection = (AtmosDirection) (1 << oppositeIndex); + if (adjBlockDirs.IsFlagSet(oppositeDirection) || blockedDirs.IsFlagSet(direction)) { // Adjacency is blocked by some airtight entity. tile.AdjacentBits &= ~direction; adjacent.AdjacentBits &= ~oppositeDirection; tile.AdjacentTiles[i] = null; - adjacent.AdjacentTiles[oppositeDirection.ToIndex()] = null; + adjacent.AdjacentTiles[oppositeIndex] = null; } else { @@ -210,7 +211,7 @@ public sealed partial class AtmosphereSystem tile.AdjacentBits |= direction; adjacent.AdjacentBits |= oppositeDirection; tile.AdjacentTiles[i] = adjacent; - adjacent.AdjacentTiles[oppositeDirection.ToIndex()] = tile; + adjacent.AdjacentTiles[oppositeIndex] = tile; } DebugTools.Assert(!(tile.AdjacentBits.IsFlagSet(direction) ^ diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs index 713d1c4682..7163b4cd44 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Hotspot.cs @@ -1,10 +1,12 @@ using Content.Server.Atmos.Components; using Content.Server.Atmos.Reactions; using Content.Shared.Atmos; +using Content.Shared.Atmos.Components; using Content.Shared.Audio; using Content.Shared.Database; using Robust.Shared.Audio; using Robust.Shared.Map; +using Robust.Shared.Map.Components; using Robust.Shared.Player; namespace Content.Server.Atmos.EntitySystems @@ -18,18 +20,18 @@ namespace Content.Server.Atmos.EntitySystems [ViewVariables(VVAccess.ReadWrite)] public string? HotspotSound { get; private set; } = "/Audio/Effects/fire.ogg"; - private void ProcessHotspot(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile) + private void ProcessHotspot( + Entity ent, + TileAtmosphere tile) { + var gridAtmosphere = ent.Comp1; if (!tile.Hotspot.Valid) { gridAtmosphere.HotspotTiles.Remove(tile); return; } - if (!tile.Excited) - { - AddActiveTile(gridAtmosphere, tile); - } + AddActiveTile(gridAtmosphere, tile); if (!tile.Hotspot.SkippedFirstProcess) { @@ -44,7 +46,7 @@ namespace Content.Server.Atmos.EntitySystems || tile.Air == null || tile.Air.GetMoles(Gas.Oxygen) < 0.5f || (tile.Air.GetMoles(Gas.Plasma) < 0.5f && tile.Air.GetMoles(Gas.Tritium) < 0.5f)) { tile.Hotspot = new Hotspot(); - InvalidateVisuals(tile.GridIndex, tile.GridIndices); + InvalidateVisuals(ent, tile); return; } diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.LINDA.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.LINDA.cs index c27e18b55b..fb2375899d 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.LINDA.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.LINDA.cs @@ -1,14 +1,18 @@ using Content.Server.Atmos.Components; using Content.Shared.Atmos; using Content.Shared.Atmos.Components; +using Robust.Shared.Map.Components; using Robust.Shared.Utility; namespace Content.Server.Atmos.EntitySystems { public sealed partial class AtmosphereSystem { - private void ProcessCell(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, int fireCount, GasTileOverlayComponent visuals) + private void ProcessCell( + Entity ent, + TileAtmosphere tile, int fireCount) { + var gridAtmosphere = ent.Comp1; // Can't process a tile without air if (tile.Air == null) { @@ -52,11 +56,7 @@ namespace Content.Server.Atmos.EntitySystems shouldShareAir = true; } else if (CompareExchange(tile.Air, enemyTile.Air) != GasCompareResult.NoExchange) { - if (!enemyTile.Excited) - { - AddActiveTile(gridAtmosphere, enemyTile); - } - + AddActiveTile(gridAtmosphere, enemyTile); if (ExcitedGroups) { var excitedGroup = tile.ExcitedGroup; @@ -91,7 +91,7 @@ namespace Content.Server.Atmos.EntitySystems } else { - ConsiderPressureDifference(gridAtmosphere, enemyTile, direction.GetOpposite(), -difference); + ConsiderPressureDifference(gridAtmosphere, enemyTile, i.ToOppositeDir(), -difference); } } @@ -102,7 +102,7 @@ namespace Content.Server.Atmos.EntitySystems if(tile.Air != null) React(tile.Air, tile); - InvalidateVisuals(tile.GridIndex, tile.GridIndices, visuals); + InvalidateVisuals(ent, tile); var remove = true; @@ -146,7 +146,7 @@ namespace Content.Server.Atmos.EntitySystems /// Tile Atmosphere to be activated. private void AddActiveTile(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile) { - if (tile.Air == null) + if (tile.Air == null || tile.Excited) return; tile.Excited = true; diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Monstermos.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Monstermos.cs index dcbc1e86ee..08193027d6 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Monstermos.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Monstermos.cs @@ -230,7 +230,7 @@ namespace Content.Server.Atmos.EntitySystems if (otherTile2.MonstermosInfo.LastSlowQueueCycle == queueCycleSlow) continue; _equalizeQueue[queueLength++] = otherTile2; otherTile2.MonstermosInfo.LastSlowQueueCycle = queueCycleSlow; - otherTile2.MonstermosInfo.CurrentTransferDirection = direction.GetOpposite(); + otherTile2.MonstermosInfo.CurrentTransferDirection = k.ToOppositeDir(); otherTile2.MonstermosInfo.CurrentTransferAmount = 0; if (otherTile2.MonstermosInfo.MoleDelta < 0) { @@ -296,7 +296,7 @@ namespace Content.Server.Atmos.EntitySystems if (otherTile2.MonstermosInfo.LastSlowQueueCycle == queueCycleSlow) continue; _equalizeQueue[queueLength++] = otherTile2; otherTile2.MonstermosInfo.LastSlowQueueCycle = queueCycleSlow; - otherTile2.MonstermosInfo.CurrentTransferDirection = direction.GetOpposite(); + otherTile2.MonstermosInfo.CurrentTransferDirection = k.ToOppositeDir(); otherTile2.MonstermosInfo.CurrentTransferAmount = 0; if (otherTile2.MonstermosInfo.MoleDelta > 0) @@ -338,7 +338,7 @@ namespace Content.Server.Atmos.EntitySystems for (var i = 0; i < tileCount; i++) { var otherTile = _equalizeTiles[i]!; - FinalizeEq(gridAtmosphere, otherTile, ent); + FinalizeEq(ent, otherTile); } for (var i = 0; i < tileCount; i++) @@ -473,7 +473,7 @@ namespace Content.Server.Atmos.EntitySystems if(tile2.Space) continue; - tile2.MonstermosInfo.CurrentTransferDirection = direction.GetOpposite(); + tile2.MonstermosInfo.CurrentTransferDirection = j.ToOppositeDir(); tile2.MonstermosInfo.CurrentTransferAmount = 0.0f; tile2.PressureSpecificTarget = otherTile.PressureSpecificTarget; tile2.MonstermosInfo.LastSlowQueueCycle = queueCycleSlow; @@ -549,7 +549,7 @@ namespace Content.Server.Atmos.EntitySystems otherTile.Air.Temperature = Atmospherics.TCMB; } - InvalidateVisuals(otherTile.GridIndex, otherTile.GridIndices, visuals); + InvalidateVisuals(ent, otherTile); HandleDecompressionFloorRip(mapGrid, otherTile, otherTile.MonstermosInfo.CurrentTransferAmount); } @@ -598,11 +598,13 @@ namespace Content.Server.Atmos.EntitySystems UpdateAdjacentTiles(ent, tile); UpdateAdjacentTiles(ent, other); - InvalidateVisuals(tile.GridIndex, tile.GridIndices, ent); - InvalidateVisuals(other.GridIndex, other.GridIndices, ent); + InvalidateVisuals(ent, tile); + InvalidateVisuals(ent, other); } - private void FinalizeEq(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, GasTileOverlayComponent? visuals) + private void FinalizeEq( + Entity ent, + TileAtmosphere tile) { Span transferDirections = stackalloc float[Atmospherics.Directions]; var hasTransferDirs = false; @@ -629,17 +631,19 @@ namespace Content.Server.Atmos.EntitySystems // Everything that calls this method already ensures that Air will not be null. if (tile.Air!.TotalMoles < amount) - FinalizeEqNeighbors(gridAtmosphere, tile, transferDirections, visuals); + FinalizeEqNeighbors(ent, tile, transferDirections); - otherTile.MonstermosInfo[direction.GetOpposite()] = 0; + otherTile.MonstermosInfo[i.ToOppositeDir()] = 0; Merge(otherTile.Air, tile.Air.Remove(amount)); - InvalidateVisuals(tile.GridIndex, tile.GridIndices, visuals); - InvalidateVisuals(otherTile.GridIndex, otherTile.GridIndices, visuals); - ConsiderPressureDifference(gridAtmosphere, tile, direction, amount); + InvalidateVisuals(ent, tile); + InvalidateVisuals(ent, otherTile); + ConsiderPressureDifference(ent, tile, direction, amount); } } - private void FinalizeEqNeighbors(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, ReadOnlySpan transferDirs, GasTileOverlayComponent? visuals) + private void FinalizeEqNeighbors( + Entity ent, + TileAtmosphere tile, ReadOnlySpan transferDirs) { for (var i = 0; i < Atmospherics.Directions; i++) { @@ -647,7 +651,7 @@ namespace Content.Server.Atmos.EntitySystems var amount = transferDirs[i]; // Since AdjacentBits is set, AdjacentTiles[i] wouldn't be null, and neither would its air. if(amount < 0 && tile.AdjacentBits.IsFlagSet(direction)) - FinalizeEq(gridAtmosphere, tile.AdjacentTiles[i]!, visuals); // A bit of recursion if needed. + FinalizeEq(ent, tile.AdjacentTiles[i]!); // A bit of recursion if needed. } } @@ -664,7 +668,9 @@ namespace Content.Server.Atmos.EntitySystems Log.Error($"Encountered null-tile in {nameof(AdjustEqMovement)}. Trace: {Environment.StackTrace}"); return; } - var adj = tile.AdjacentTiles[direction.ToIndex()]; + + var idx = direction.ToIndex(); + var adj = tile.AdjacentTiles[idx]; if (adj == null) { var nonNull = tile.AdjacentTiles.Where(x => x != null).Count(); @@ -673,7 +679,7 @@ namespace Content.Server.Atmos.EntitySystems } tile.MonstermosInfo[direction] += amount; - adj.MonstermosInfo[direction.GetOpposite()] -= amount; + adj.MonstermosInfo[idx.ToOppositeDir()] -= amount; } private void HandleDecompressionFloorRip(MapGridComponent mapGrid, TileAtmosphere tile, float sum) diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs index eba398c182..bd023e8574 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs @@ -86,7 +86,7 @@ namespace Content.Server.Atmos.EntitySystems DebugTools.Assert(atmosphere.Tiles.GetValueOrDefault(tile.GridIndices) == tile); UpdateAdjacentTiles(ent, tile, activate: true); UpdateTileAir(ent, tile, volume); - InvalidateVisuals(uid, tile.GridIndices, visuals); + InvalidateVisuals(ent, tile); if (number++ < InvalidCoordinatesLagCheckIterations) continue; @@ -313,15 +313,17 @@ namespace Content.Server.Atmos.EntitySystems return true; } - private bool ProcessActiveTiles(GridAtmosphereComponent atmosphere, GasTileOverlayComponent visuals) + private bool ProcessActiveTiles( + Entity ent) { + var atmosphere = ent.Comp1; if(!atmosphere.ProcessingPaused) QueueRunTiles(atmosphere.CurrentRunTiles, atmosphere.ActiveTiles); var number = 0; while (atmosphere.CurrentRunTiles.TryDequeue(out var tile)) { - ProcessCell(atmosphere, tile, atmosphere.UpdateCounter, visuals); + ProcessCell(ent, tile, atmosphere.UpdateCounter); if (number++ < LagCheckIterations) continue; @@ -337,8 +339,10 @@ namespace Content.Server.Atmos.EntitySystems return true; } - private bool ProcessExcitedGroups(GridAtmosphereComponent gridAtmosphere) + private bool ProcessExcitedGroups( + Entity ent) { + var gridAtmosphere = ent.Comp1; if (!gridAtmosphere.ProcessingPaused) { gridAtmosphere.CurrentRunExcitedGroups.Clear(); @@ -356,7 +360,7 @@ namespace Content.Server.Atmos.EntitySystems excitedGroup.DismantleCooldown++; if (excitedGroup.BreakdownCooldown > Atmospherics.ExcitedGroupBreakdownCycles) - ExcitedGroupSelfBreakdown(gridAtmosphere, excitedGroup); + ExcitedGroupSelfBreakdown(ent, excitedGroup); else if (excitedGroup.DismantleCooldown > Atmospherics.ExcitedGroupsDismantleCycles) DeactivateGroupTiles(gridAtmosphere, excitedGroup); // TODO ATMOS. What is the point of this? why is this only de-exciting the group? Shouldn't it also dismantle it? @@ -411,15 +415,17 @@ namespace Content.Server.Atmos.EntitySystems return true; } - private bool ProcessHotspots(GridAtmosphereComponent atmosphere) + private bool ProcessHotspots( + Entity ent) { + var atmosphere = ent.Comp1; if(!atmosphere.ProcessingPaused) QueueRunTiles(atmosphere.CurrentRunTiles, atmosphere.HotspotTiles); var number = 0; while (atmosphere.CurrentRunTiles.TryDequeue(out var hotspot)) { - ProcessHotspot(atmosphere, hotspot); + ProcessHotspot(ent, hotspot); if (number++ < LagCheckIterations) continue; @@ -507,8 +513,11 @@ namespace Content.Server.Atmos.EntitySystems return num * AtmosTime; } - private bool ProcessAtmosDevices(GridAtmosphereComponent atmosphere) + private bool ProcessAtmosDevices( + Entity ent, + Entity map) { + var atmosphere = ent.Comp1; if (!atmosphere.ProcessingPaused) { atmosphere.CurrentRunAtmosDevices.Clear(); @@ -521,7 +530,7 @@ namespace Content.Server.Atmos.EntitySystems var time = _gameTiming.CurTime; var number = 0; - var ev = new AtmosDeviceUpdateEvent(RealAtmosTime()); + var ev = new AtmosDeviceUpdateEvent(RealAtmosTime(), (ent, ent.Comp1, ent.Comp2), map); while (atmosphere.CurrentRunAtmosDevices.TryDequeue(out var device)) { RaiseLocalEvent(device, ref ev); @@ -565,12 +574,11 @@ namespace Content.Server.Atmos.EntitySystems var ent = _currentRunAtmosphere[_currentRunAtmosphereIndex]; var (owner, atmosphere, visuals, grid, xform) = ent; - if (!TryComp(owner, out TransformComponent? x) - || x.MapUid == null - || TerminatingOrDeleted(x.MapUid.Value) - || x.MapID == MapId.Nullspace) + if (xform.MapUid == null + || TerminatingOrDeleted(xform.MapUid.Value) + || xform.MapID == MapId.Nullspace) { - Log.Error($"Attempted to process atmos without a map? Entity: {ToPrettyString(owner)}. Map: {ToPrettyString(x?.MapUid)}. MapId: {x?.MapID}"); + Log.Error($"Attempted to process atmos without a map? Entity: {ToPrettyString(owner)}. Map: {ToPrettyString(xform?.MapUid)}. MapId: {xform?.MapID}"); continue; } @@ -585,6 +593,8 @@ namespace Content.Server.Atmos.EntitySystems // We subtract it so it takes lost time into account. atmosphere.Timer -= AtmosTime; + var map = new Entity(xform.MapUid.Value, _mapAtmosQuery.CompOrNull(xform.MapUid.Value)); + switch (atmosphere.State) { case AtmosphereProcessingState.Revalidate: @@ -614,7 +624,7 @@ namespace Content.Server.Atmos.EntitySystems atmosphere.State = AtmosphereProcessingState.ActiveTiles; continue; case AtmosphereProcessingState.ActiveTiles: - if (!ProcessActiveTiles(ent, ent)) + if (!ProcessActiveTiles(ent)) { atmosphere.ProcessingPaused = true; return; @@ -625,7 +635,7 @@ namespace Content.Server.Atmos.EntitySystems atmosphere.State = ExcitedGroups ? AtmosphereProcessingState.ExcitedGroups : AtmosphereProcessingState.HighPressureDelta; continue; case AtmosphereProcessingState.ExcitedGroups: - if (!ProcessExcitedGroups(atmosphere)) + if (!ProcessExcitedGroups(ent)) { atmosphere.ProcessingPaused = true; return; @@ -645,7 +655,7 @@ namespace Content.Server.Atmos.EntitySystems atmosphere.State = AtmosphereProcessingState.Hotspots; continue; case AtmosphereProcessingState.Hotspots: - if (!ProcessHotspots(atmosphere)) + if (!ProcessHotspots(ent)) { atmosphere.ProcessingPaused = true; return; @@ -680,7 +690,7 @@ namespace Content.Server.Atmos.EntitySystems atmosphere.State = AtmosphereProcessingState.AtmosDevices; continue; case AtmosphereProcessingState.AtmosDevices: - if (!ProcessAtmosDevices(atmosphere)) + if (!ProcessAtmosDevices(ent, map)) { atmosphere.ProcessingPaused = true; return; diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Superconductivity.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Superconductivity.cs index 5c73cf1124..8ed92a9d0e 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Superconductivity.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Superconductivity.cs @@ -16,7 +16,7 @@ namespace Content.Server.Atmos.EntitySystems if (!directions.IsFlagSet(direction)) continue; - var adjacent = tile.AdjacentTiles[direction.ToIndex()]; + var adjacent = tile.AdjacentTiles[i]; // TODO ATMOS handle adjacent being null. if (adjacent == null || adjacent.ThermalConductivity == 0f) diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs index 67c6d5998d..cf4c73aa2f 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs @@ -36,9 +36,17 @@ public partial class AtmosphereSystem } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void InvalidateVisuals(EntityUid gridUid, Vector2i tile, GasTileOverlayComponent? comp = null) + public void InvalidateVisuals(Entity grid, Vector2i tile) { - _gasTileOverlaySystem.Invalidate(gridUid, tile, comp); + _gasTileOverlaySystem.Invalidate(grid, tile); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void InvalidateVisuals( + Entity ent, + TileAtmosphere tile) + { + _gasTileOverlaySystem.Invalidate((ent.Owner, ent.Comp2), tile.GridIndices); } /// diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs index a553766582..44bfa4cc10 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs @@ -96,7 +96,7 @@ public sealed partial class AtmosphereSystem : SharedAtmosphereSystem var query = EntityQueryEnumerator(); while (query.MoveNext(out var uid, out _, out var transform)) { - var air = GetContainingMixture(uid, transform:transform); + var air = GetContainingMixture((uid, transform)); if (air == null) continue; diff --git a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs b/Content.Server/Atmos/EntitySystems/GasTankSystem.cs index aed00432e1..80842416e8 100644 --- a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs +++ b/Content.Server/Atmos/EntitySystems/GasTankSystem.cs @@ -168,7 +168,7 @@ namespace Content.Server.Atmos.EntitySystems private void ReleaseGas(Entity gasTank) { var removed = RemoveAirVolume(gasTank, gasTank.Comp.ValveOutputRate * TimerDelay); - var environment = _atmosphereSystem.GetContainingMixture(gasTank, false, true); + var environment = _atmosphereSystem.GetContainingMixture(gasTank.Owner, false, true); if (environment != null) { _atmosphereSystem.Merge(environment, removed); diff --git a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs index 003eed59e0..c42cfd08da 100644 --- a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs +++ b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs @@ -60,6 +60,7 @@ namespace Content.Server.Atmos.EntitySystems private float _updateInterval; private int _thresholds; + private EntityQuery _query; public override void Initialize() { @@ -84,6 +85,7 @@ namespace Content.Server.Atmos.EntitySystems SubscribeLocalEvent(Reset); SubscribeLocalEvent(OnStartup); + _query = GetEntityQuery(); } private void OnStartup(EntityUid uid, GasTileOverlayComponent component, ComponentStartup args) @@ -132,10 +134,10 @@ namespace Content.Server.Atmos.EntitySystems private void UpdateThresholds(int value) => _thresholds = value; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Invalidate(EntityUid grid, Vector2i index, GasTileOverlayComponent? comp = null) + public void Invalidate(Entity grid, Vector2i index) { - if (Resolve(grid, ref comp)) - comp.InvalidTiles.Add(index); + if (_query.Resolve(grid.Owner, ref grid.Comp)) + grid.Comp.InvalidTiles.Add(index); } private void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs e) diff --git a/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs b/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs index 286b154e96..b3644e88b7 100644 --- a/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs +++ b/Content.Server/Atmos/EntitySystems/HeatExchangerSystem.cs @@ -40,24 +40,16 @@ public sealed class HeatExchangerSystem : EntitySystem private void OnAtmosUpdate(EntityUid uid, HeatExchangerComponent comp, ref AtmosDeviceUpdateEvent args) { - if (!TryComp(uid, out NodeContainerComponent? nodeContainer) - || !TryComp(uid, out AtmosDeviceComponent? device) - || !_nodeContainer.TryGetNode(nodeContainer, comp.InletName, out PipeNode? inlet) - || !_nodeContainer.TryGetNode(nodeContainer, comp.OutletName, out PipeNode? outlet)) + // make sure that the tile the device is on isn't blocked by a wall or something similar. + if (args.Grid is {} grid + && _transform.TryGetGridTilePosition(uid, out var tile) + && _atmosphereSystem.IsTileAirBlocked(grid, tile)) { return; } - // make sure that the tile the device is on isn't blocked by a wall or something similar. - var xform = Transform(uid); - if (_transform.TryGetGridTilePosition(uid, out var tile)) - { - // TryGetGridTilePosition() already returns false if GridUid is null, but the null checker isn't smart enough yet - if (xform.GridUid != null && _atmosphereSystem.IsTileAirBlocked(xform.GridUid.Value, tile)) - { - return; - } - } + if (!_nodeContainer.TryGetNodes(uid, comp.InletName, comp.OutletName, out PipeNode? inlet, out PipeNode? outlet)) + return; var dt = args.dt; diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs index 28a0a01c99..c1a5256fdd 100644 --- a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs @@ -204,11 +204,7 @@ public sealed class AtmosMonitorSystem : EntitySystem if (!this.IsPowered(uid, EntityManager)) return; - // can't hurt - // (in case something is making AtmosDeviceUpdateEvents - // outside the typical device loop) - if (!TryComp(uid, out var atmosDeviceComponent) - || atmosDeviceComponent.JoinedGrid == null) + if (args.Grid == null) return; // if we're not monitoring atmos, don't bother diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPassiveGateSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPassiveGateSystem.cs index 77bab4775c..fced4d7988 100644 --- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPassiveGateSystem.cs +++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPassiveGateSystem.cs @@ -26,11 +26,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems private void OnPassiveGateUpdated(EntityUid uid, GasPassiveGateComponent gate, ref AtmosDeviceUpdateEvent args) { - if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) - return; - - if (!_nodeContainer.TryGetNode(nodeContainer, gate.InletName, out PipeNode? inlet) - || !_nodeContainer.TryGetNode(nodeContainer, gate.OutletName, out PipeNode? outlet)) + if (!_nodeContainer.TryGetNodes(uid, gate.InletName, gate.OutletName, out PipeNode? inlet, out PipeNode? outlet)) return; var n1 = inlet.Air.TotalMoles; diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs index 49b69fc673..af25d04df9 100644 --- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs +++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs @@ -66,9 +66,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems private void OnPumpUpdated(EntityUid uid, GasPressurePumpComponent pump, ref AtmosDeviceUpdateEvent args) { if (!pump.Enabled - || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) - || !_nodeContainer.TryGetNode(nodeContainer, pump.InletName, out PipeNode? inlet) - || !_nodeContainer.TryGetNode(nodeContainer, pump.OutletName, out PipeNode? outlet)) + || !_nodeContainer.TryGetNodes(uid, pump.InletName, pump.OutletName, out PipeNode? inlet, out PipeNode? outlet)) { _ambientSoundSystem.SetAmbience(uid, false); return; diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasRecyclerSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasRecyclerSystem.cs index e14069b8a7..3ebc509492 100644 --- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasRecyclerSystem.cs +++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasRecyclerSystem.cs @@ -41,12 +41,8 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems if (!EntityManager.GetComponent(ent).Anchored || !args.IsInDetailsRange) // Not anchored? Out of range? No status. return; - if (!EntityManager.TryGetComponent(ent, out NodeContainerComponent? nodeContainer) - || !_nodeContainer.TryGetNode(nodeContainer, comp.InletName, out PipeNode? inlet) - || !_nodeContainer.TryGetNode(nodeContainer, comp.OutletName, out PipeNode? _)) - { + if (!_nodeContainer.TryGetNode(ent.Owner, comp.InletName, out PipeNode? inlet)) return; - } using (args.PushGroup(nameof(GasRecyclerComponent))) { @@ -72,9 +68,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems private void OnUpdate(Entity ent, ref AtmosDeviceUpdateEvent args) { var comp = ent.Comp; - if (!EntityManager.TryGetComponent(ent, out NodeContainerComponent? nodeContainer) - || !_nodeContainer.TryGetNode(nodeContainer, comp.InletName, out PipeNode? inlet) - || !_nodeContainer.TryGetNode(nodeContainer, comp.OutletName, out PipeNode? outlet)) + if (!_nodeContainer.TryGetNodes(ent.Owner, comp.InletName, comp.OutletName, out PipeNode? inlet, out PipeNode? outlet)) { _ambientSoundSystem.SetAmbience(ent, false); return; diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasValveSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasValveSystem.cs index 934ce8a7a4..ed7567428e 100644 --- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasValveSystem.cs +++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasValveSystem.cs @@ -59,9 +59,8 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems public void Set(EntityUid uid, GasValveComponent component, bool value) { component.Open = value; - if (TryComp(uid, out NodeContainerComponent? nodeContainer) - && _nodeContainer.TryGetNode(nodeContainer, component.InletName, out PipeNode? inlet) - && _nodeContainer.TryGetNode(nodeContainer, component.OutletName, out PipeNode? outlet)) + + if (_nodeContainer.TryGetNodes(uid, component.InletName, component.OutletName, out PipeNode? inlet, out PipeNode? outlet)) { if (TryComp(uid, out var appearance)) { diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs index 8e478bd2b5..e4767c4061 100644 --- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs +++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs @@ -71,11 +71,8 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems private void OnVolumePumpUpdated(EntityUid uid, GasVolumePumpComponent pump, ref AtmosDeviceUpdateEvent args) { - if (!pump.Enabled - || !TryComp(uid, out NodeContainerComponent? nodeContainer) - || !TryComp(uid, out AtmosDeviceComponent? device) - || !_nodeContainer.TryGetNode(nodeContainer, pump.InletName, out PipeNode? inlet) - || !_nodeContainer.TryGetNode(nodeContainer, pump.OutletName, out PipeNode? outlet)) + if (!pump.Enabled || + !_nodeContainer.TryGetNodes(uid, pump.InletName, pump.OutletName, out PipeNode? inlet, out PipeNode? outlet)) { _ambientSoundSystem.SetAmbience(uid, false); return; diff --git a/Content.Server/Atmos/Piping/Components/AtmosDeviceComponent.cs b/Content.Server/Atmos/Piping/Components/AtmosDeviceComponent.cs index 80461f1beb..b70262e857 100644 --- a/Content.Server/Atmos/Piping/Components/AtmosDeviceComponent.cs +++ b/Content.Server/Atmos/Piping/Components/AtmosDeviceComponent.cs @@ -1,4 +1,5 @@ using Content.Server.Atmos.Components; +using Content.Shared.Atmos.Components; namespace Content.Server.Atmos.Piping.Components; @@ -46,18 +47,25 @@ public sealed partial class AtmosDeviceComponent : Component /// Use this for atmos devices instead of . /// [ByRefEvent] -public readonly struct AtmosDeviceUpdateEvent +public readonly struct AtmosDeviceUpdateEvent(float dt, Entity? grid, Entity? map) { /// /// Time elapsed since last update, in seconds. Multiply values used in the update handler /// by this number to make them tickrate-invariant. Use this number instead of AtmosphereSystem.AtmosTime. /// - public readonly float dt; + public readonly float dt = dt; - public AtmosDeviceUpdateEvent(float dt) - { - this.dt = dt; - } + /// + /// The grid that this device is currently on. + /// + public readonly Entity? Grid = grid == null + ? null + : (grid.Value, grid.Value, grid.Value); + + /// + /// The map that the device & grid is on. + /// + public readonly Entity? Map = map; } /// diff --git a/Content.Server/Atmos/Piping/EntitySystems/AtmosDeviceSystem.cs b/Content.Server/Atmos/Piping/EntitySystems/AtmosDeviceSystem.cs index c15d31f7d6..3c73a8f64e 100644 --- a/Content.Server/Atmos/Piping/EntitySystems/AtmosDeviceSystem.cs +++ b/Content.Server/Atmos/Piping/EntitySystems/AtmosDeviceSystem.cs @@ -129,9 +129,10 @@ namespace Content.Server.Atmos.Piping.EntitySystems _timer -= _atmosphereSystem.AtmosTime; var time = _gameTiming.CurTime; - var ev = new AtmosDeviceUpdateEvent(_atmosphereSystem.AtmosTime); + var ev = new AtmosDeviceUpdateEvent(_atmosphereSystem.AtmosTime, null, null); foreach (var device in _joinedDevices) { + DebugTools.Assert(!HasComp(Transform(device).GridUid)); RaiseLocalEvent(device, ref ev); device.Comp.LastProcess = time; } diff --git a/Content.Server/Atmos/Piping/Other/EntitySystems/GasMinerSystem.cs b/Content.Server/Atmos/Piping/Other/EntitySystems/GasMinerSystem.cs index 9853a17f82..aa206dbc68 100644 --- a/Content.Server/Atmos/Piping/Other/EntitySystems/GasMinerSystem.cs +++ b/Content.Server/Atmos/Piping/Other/EntitySystems/GasMinerSystem.cs @@ -38,9 +38,9 @@ namespace Content.Server.Atmos.Piping.Other.EntitySystems private bool CheckMinerOperation(Entity ent, [NotNullWhen(true)] out GasMixture? environment) { var (uid, miner) = ent; - environment = _atmosphereSystem.GetContainingMixture(uid, true, true); - var transform = Transform(uid); + environment = _atmosphereSystem.GetContainingMixture((uid, transform), true, true); + var position = _transformSystem.GetGridOrMapTilePosition(uid, transform); // Space. diff --git a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs index faf06a6079..f856946a92 100644 --- a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs +++ b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs @@ -53,11 +53,7 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems private void OnFilterUpdated(EntityUid uid, GasFilterComponent filter, ref AtmosDeviceUpdateEvent args) { if (!filter.Enabled - || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) - || !EntityManager.TryGetComponent(uid, out AtmosDeviceComponent? device) - || !_nodeContainer.TryGetNode(nodeContainer, filter.InletName, out PipeNode? inletNode) - || !_nodeContainer.TryGetNode(nodeContainer, filter.FilterName, out PipeNode? filterNode) - || !_nodeContainer.TryGetNode(nodeContainer, filter.OutletName, out PipeNode? outletNode) + || !_nodeContainer.TryGetNodes(uid, filter.InletName, filter.OutletName, filter.FilterName, out PipeNode? inletNode, out PipeNode? filterNode, out PipeNode? outletNode) || outletNode.Air.Pressure >= Atmospherics.MaxOutputPressure) // No need to transfer if target is full. { _ambientSoundSystem.SetAmbience(uid, false); @@ -187,16 +183,15 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) return; - var gasMixDict = new Dictionary(); + args.GasMixtures ??= new Dictionary(); if(_nodeContainer.TryGetNode(nodeContainer, component.InletName, out PipeNode? inlet)) - gasMixDict.Add(Loc.GetString("gas-analyzer-window-text-inlet"), inlet.Air); + args.GasMixtures.Add(Loc.GetString("gas-analyzer-window-text-inlet"), inlet.Air); if(_nodeContainer.TryGetNode(nodeContainer, component.FilterName, out PipeNode? filterNode)) - gasMixDict.Add(Loc.GetString("gas-analyzer-window-text-filter"), filterNode.Air); + args.GasMixtures.Add(Loc.GetString("gas-analyzer-window-text-filter"), filterNode.Air); if(_nodeContainer.TryGetNode(nodeContainer, component.OutletName, out PipeNode? outlet)) - gasMixDict.Add(Loc.GetString("gas-analyzer-window-text-outlet"), outlet.Air); + args.GasMixtures.Add(Loc.GetString("gas-analyzer-window-text-outlet"), outlet.Air); - args.GasMixtures = gasMixDict; args.DeviceFlipped = inlet != null && filterNode != null && inlet.CurrentPipeDirection.ToDirection() == filterNode.CurrentPipeDirection.ToDirection().GetClockwise90Degrees(); } } diff --git a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs index fb65c17f61..ba8ebf3c9a 100644 --- a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs +++ b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs @@ -54,18 +54,8 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems { // TODO ATMOS: Cache total moles since it's expensive. - if (!mixer.Enabled) - { - _ambientSoundSystem.SetAmbience(uid, false); - return; - } - - if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) - return; - - if (!_nodeContainer.TryGetNode(nodeContainer, mixer.InletOneName, out PipeNode? inletOne) - || !_nodeContainer.TryGetNode(nodeContainer, mixer.InletTwoName, out PipeNode? inletTwo) - || !_nodeContainer.TryGetNode(nodeContainer, mixer.OutletName, out PipeNode? outlet)) + if (!mixer.Enabled + || !_nodeContainer.TryGetNodes(uid, mixer.InletOneName, mixer.InletTwoName, mixer.OutletName, out PipeNode? inletOne, out PipeNode? inletTwo, out PipeNode? outlet)) { _ambientSoundSystem.SetAmbience(uid, false); return; diff --git a/Content.Server/Atmos/Piping/Trinary/EntitySystems/PressureControlledValveSystem.cs b/Content.Server/Atmos/Piping/Trinary/EntitySystems/PressureControlledValveSystem.cs index 2c2f1584a5..1bab2abd8e 100644 --- a/Content.Server/Atmos/Piping/Trinary/EntitySystems/PressureControlledValveSystem.cs +++ b/Content.Server/Atmos/Piping/Trinary/EntitySystems/PressureControlledValveSystem.cs @@ -33,11 +33,7 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems private void OnUpdate(EntityUid uid, PressureControlledValveComponent comp, ref AtmosDeviceUpdateEvent args) { - if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) - || !EntityManager.TryGetComponent(uid, out AtmosDeviceComponent? device) - || !_nodeContainer.TryGetNode(nodeContainer, comp.InletName, out PipeNode? inletNode) - || !_nodeContainer.TryGetNode(nodeContainer, comp.ControlName, out PipeNode? controlNode) - || !_nodeContainer.TryGetNode(nodeContainer, comp.OutletName, out PipeNode? outletNode)) + if (!_nodeContainer.TryGetNodes(uid, comp.InletName, comp.ControlName, comp.OutletName, out PipeNode? inletNode, out PipeNode? controlNode, out PipeNode? outletNode)) { _ambientSoundSystem.SetAmbience(uid, false); comp.Enabled = false; diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs index 170586339d..3e4340bf1d 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs @@ -60,7 +60,7 @@ public sealed class GasCanisterSystem : EntitySystem if (!Resolve(uid, ref canister, ref transform)) return; - var environment = _atmos.GetContainingMixture(uid, false, true); + var environment = _atmos.GetContainingMixture((uid, transform), false, true); if (environment is not null) _atmos.Merge(environment, canister.Air); @@ -168,7 +168,7 @@ public sealed class GasCanisterSystem : EntitySystem } else { - var environment = _atmos.GetContainingMixture(uid, false, true); + var environment = _atmos.GetContainingMixture(uid, args.Grid, args.Map, false, true); _atmos.ReleaseGasTo(canister.Air, environment, canister.ReleasePressure); } } diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs index 852542ec6c..e903ceedaf 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCondenserSystem.cs @@ -30,9 +30,8 @@ public sealed class GasCondenserSystem : EntitySystem private void OnCondenserUpdated(Entity entity, ref AtmosDeviceUpdateEvent args) { - if (!(_power.IsPowered(entity) && TryComp(entity, out var receiver)) - || !TryComp(entity, out var nodeContainer) - || !_nodeContainer.TryGetNode(nodeContainer, entity.Comp.Inlet, out PipeNode? inlet) + if (!(TryComp(entity, out var receiver) && _power.IsPowered(entity, receiver)) + || !_nodeContainer.TryGetNode(entity.Owner, entity.Comp.Inlet, out PipeNode? inlet) || !_solution.ResolveSolution(entity.Owner, entity.Comp.SolutionId, ref entity.Comp.Solution, out var solution)) { return; diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasOutletInjectorSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasOutletInjectorSystem.cs index 8029a09556..834a1dfb0b 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasOutletInjectorSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasOutletInjectorSystem.cs @@ -50,16 +50,10 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems if (!injector.Enabled) return; - if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) + if (!_nodeContainer.TryGetNode(uid, injector.InletName, out PipeNode? inlet)) return; - if (!TryComp(uid, out AtmosDeviceComponent? device)) - return; - - if (!_nodeContainer.TryGetNode(nodeContainer, injector.InletName, out PipeNode? inlet)) - return; - - var environment = _atmosphereSystem.GetContainingMixture(uid, true, true); + var environment = _atmosphereSystem.GetContainingMixture(uid, args.Grid, args.Map, true, true); if (environment == null) return; diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPassiveVentSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPassiveVentSystem.cs index c8fd23d466..72812cb523 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPassiveVentSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPassiveVentSystem.cs @@ -24,15 +24,12 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems private void OnPassiveVentUpdated(EntityUid uid, GasPassiveVentComponent vent, ref AtmosDeviceUpdateEvent args) { - var environment = _atmosphereSystem.GetContainingMixture(uid, true, true); + var environment = _atmosphereSystem.GetContainingMixture(uid, args.Grid, args.Map, true, true); if (environment == null) return; - if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) - return; - - if (!_nodeContainer.TryGetNode(nodeContainer, vent.InletName, out PipeNode? inlet)) + if (!_nodeContainer.TryGetNode(uid, vent.InletName, out PipeNode? inlet)) return; var inletAir = inlet.Air.RemoveRatio(1f); diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPortableSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPortableSystem.cs index 4ddd19dd45..7cb8102a38 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPortableSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasPortableSystem.cs @@ -39,10 +39,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems private void OnAnchorChanged(EntityUid uid, GasPortableComponent portable, ref AnchorStateChangedEvent args) { - if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) - return; - - if (!_nodeContainer.TryGetNode(nodeContainer, portable.PortName, out PipeNode? portableNode)) + if (!_nodeContainer.TryGetNode(uid, portable.PortName, out PipeNode? portableNode)) return; portableNode.ConnectionsEnabled = args.Anchored; diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs index d4ddd65a8e..9b61044f03 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs @@ -110,7 +110,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems _atmosphereSystem.AddHeat(heatExchangeGasMixture, dQPipe); thermoMachine.LastEnergyDelta = dQPipe; - if (dQLeak != 0f && _atmosphereSystem.GetContainingMixture(uid, excite: true) is { } containingMixture) + if (dQLeak != 0f && _atmosphereSystem.GetContainingMixture(uid, args.Grid, args.Map, excite: true) is { } containingMixture) _atmosphereSystem.AddHeat(containingMixture, dQLeak); } @@ -130,8 +130,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems } else { - if (!TryComp(uid, out var nodeContainer) - || !_nodeContainer.TryGetNode(nodeContainer, thermoMachine.InletName, out PipeNode? inlet)) + if (!_nodeContainer.TryGetNode(uid, thermoMachine.InletName, out PipeNode? inlet)) return; heatExchangeGasMixture = inlet.Air; } diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs index 3a3ccf7523..a986385f5e 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs @@ -67,15 +67,12 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems _ => throw new ArgumentOutOfRangeException() }; - if (!vent.Enabled - || !TryComp(uid, out AtmosDeviceComponent? device) - || !TryComp(uid, out NodeContainerComponent? nodeContainer) - || !_nodeContainer.TryGetNode(nodeContainer, nodeName, out PipeNode? pipe)) + if (!vent.Enabled || !_nodeContainer.TryGetNode(uid, nodeName, out PipeNode? pipe)) { return; } - var environment = _atmosphereSystem.GetContainingMixture(uid, true, true); + var environment = _atmosphereSystem.GetContainingMixture(uid, args.Grid, args.Map, true, true); // We're in an air-blocked tile... Do nothing. if (environment == null) @@ -295,9 +292,6 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems /// private void OnAnalyzed(EntityUid uid, GasVentPumpComponent component, GasAnalyzerScanEvent args) { - if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) - return; - var gasMixDict = new Dictionary(); // these are both called pipe, above it switches using this so I duplicated that...? @@ -307,7 +301,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems VentPumpDirection.Siphoning => component.Outlet, _ => throw new ArgumentOutOfRangeException() }; - if (_nodeContainer.TryGetNode(nodeContainer, nodeName, out PipeNode? pipe)) + if (_nodeContainer.TryGetNode(uid, nodeName, out PipeNode? pipe)) gasMixDict.Add(nodeName, pipe.Air); args.GasMixtures = gasMixDict; diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs index 5afa007e5e..b27689ed58 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs @@ -49,27 +49,18 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems private void OnVentScrubberUpdated(EntityUid uid, GasVentScrubberComponent scrubber, ref AtmosDeviceUpdateEvent args) { if (_weldable.IsWelded(uid)) - { - return; - } - - if (!TryComp(uid, out AtmosDeviceComponent? device)) return; var timeDelta = args.dt; - if (!scrubber.Enabled - || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) - || !_nodeContainer.TryGetNode(nodeContainer, scrubber.OutletName, out PipeNode? outlet)) + if (!scrubber.Enabled || !_nodeContainer.TryGetNode(uid, scrubber.OutletName, out PipeNode? outlet)) return; - var xform = Transform(uid); - - if (xform.GridUid == null) + if (args.Grid is not {} grid) return; - var position = _transformSystem.GetGridTilePositionOrDefault((uid,xform)); - var environment = _atmosphereSystem.GetTileMixture(xform.GridUid, xform.MapUid, position, true); + var position = _transformSystem.GetGridTilePositionOrDefault(uid); + var environment = _atmosphereSystem.GetTileMixture(grid, args.Map, position, true); Scrub(timeDelta, scrubber, environment, outlet); @@ -77,7 +68,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems return; // Scrub adjacent tiles too. - var enumerator = _atmosphereSystem.GetAdjacentTileMixtures(xform.GridUid.Value, position, false, true); + var enumerator = _atmosphereSystem.GetAdjacentTileMixtures(grid, position, false, true); while (enumerator.MoveNext(out var adjacent)) { Scrub(timeDelta, scrubber, adjacent, outlet); diff --git a/Content.Server/Atmos/Portable/PortableScrubberSystem.cs b/Content.Server/Atmos/Portable/PortableScrubberSystem.cs index e986f8f991..f9043c091a 100644 --- a/Content.Server/Atmos/Portable/PortableScrubberSystem.cs +++ b/Content.Server/Atmos/Portable/PortableScrubberSystem.cs @@ -47,17 +47,13 @@ namespace Content.Server.Atmos.Portable private void OnDeviceUpdated(EntityUid uid, PortableScrubberComponent component, ref AtmosDeviceUpdateEvent args) { - if (!TryComp(uid, out AtmosDeviceComponent? device)) - return; - var timeDelta = args.dt; if (!component.Enabled) return; // If we are on top of a connector port, empty into it. - if (TryComp(uid, out var nodeContainer) - && _nodeContainer.TryGetNode(nodeContainer, component.PortName, out PortablePipeNode? portableNode) + if (_nodeContainer.TryGetNode(uid, component.PortName, out PortablePipeNode? portableNode) && portableNode.ConnectionsEnabled) { _atmosphereSystem.React(component.Air, portableNode); @@ -71,13 +67,11 @@ namespace Content.Server.Atmos.Portable return; } - var xform = Transform(uid); - - if (xform.GridUid == null) + if (args.Grid is not {} grid) return; - var position = _transformSystem.GetGridTilePositionOrDefault((uid,xform)); - var environment = _atmosphereSystem.GetTileMixture(xform.GridUid, xform.MapUid, position, true); + var position = _transformSystem.GetGridTilePositionOrDefault(uid); + var environment = _atmosphereSystem.GetTileMixture(grid, args.Map, position, true); var running = Scrub(timeDelta, component, environment); @@ -85,8 +79,9 @@ namespace Content.Server.Atmos.Portable // We scrub once to see if we can and set the animation if (!running) return; + // widenet - var enumerator = _atmosphereSystem.GetAdjacentTileMixtures(xform.GridUid.Value, position, false, true); + var enumerator = _atmosphereSystem.GetAdjacentTileMixtures(grid, position, false, true); while (enumerator.MoveNext(out var adjacent)) { Scrub(timeDelta, component, adjacent); @@ -98,10 +93,7 @@ namespace Content.Server.Atmos.Portable /// private void OnAnchorChanged(EntityUid uid, PortableScrubberComponent component, ref AnchorStateChangedEvent args) { - if (!TryComp(uid, out NodeContainerComponent? nodeContainer)) - return; - - if (!_nodeContainer.TryGetNode(nodeContainer, component.PortName, out PipeNode? portableNode)) + if (!_nodeContainer.TryGetNode(uid, component.PortName, out PipeNode? portableNode)) return; portableNode.ConnectionsEnabled = (args.Anchored && _gasPortableSystem.FindGasPortIn(Transform(uid).GridUid, Transform(uid).Coordinates, out _)); @@ -159,14 +151,10 @@ namespace Content.Server.Atmos.Portable /// private void OnScrubberAnalyzed(EntityUid uid, PortableScrubberComponent component, GasAnalyzerScanEvent args) { - var gasMixDict = new Dictionary { { Name(uid), component.Air } }; + args.GasMixtures ??= new Dictionary { { Name(uid), component.Air } }; // If it's connected to a port, include the port side - if (TryComp(uid, out NodeContainerComponent? nodeContainer)) - { - if (_nodeContainer.TryGetNode(nodeContainer, component.PortName, out PipeNode? port)) - gasMixDict.Add(component.PortName, port.Air); - } - args.GasMixtures = gasMixDict; + if (_nodeContainer.TryGetNode(uid, component.PortName, out PipeNode? port)) + args.GasMixtures.Add(component.PortName, port.Air); } } } diff --git a/Content.Server/Atmos/Portable/SpaceHeaterSystem.cs b/Content.Server/Atmos/Portable/SpaceHeaterSystem.cs index 1631132821..fff15f696c 100644 --- a/Content.Server/Atmos/Portable/SpaceHeaterSystem.cs +++ b/Content.Server/Atmos/Portable/SpaceHeaterSystem.cs @@ -71,7 +71,7 @@ public sealed class SpaceHeaterSystem : EntitySystem // If in automatic temperature mode, check if we need to adjust the heat exchange direction if (spaceHeater.Mode == SpaceHeaterMode.Auto) { - var environment = _atmosphereSystem.GetContainingMixture(uid); + var environment = _atmosphereSystem.GetContainingMixture(uid, args.Grid, args.Map); if (environment == null) return; diff --git a/Content.Server/Electrocution/ElectrocutionNode.cs b/Content.Server/Electrocution/ElectrocutionNode.cs index 7abcba7666..c8e437d353 100644 --- a/Content.Server/Electrocution/ElectrocutionNode.cs +++ b/Content.Server/Electrocution/ElectrocutionNode.cs @@ -9,7 +9,7 @@ namespace Content.Server.Electrocution public sealed partial class ElectrocutionNode : Node { [DataField("cable")] - public EntityUid CableEntity; + public EntityUid? CableEntity; [DataField("node")] public string? NodeName; @@ -19,12 +19,11 @@ namespace Content.Server.Electrocution MapGridComponent? grid, IEntityManager entMan) { - var _nodeContainer = entMan.System(); - - if (!nodeQuery.TryGetComponent(CableEntity, out var nodeContainer)) + if (CableEntity == null || NodeName == null) yield break; - if (_nodeContainer.TryGetNode(nodeContainer, NodeName, out Node? node)) + var _nodeContainer = entMan.System(); + if (_nodeContainer.TryGetNode(CableEntity.Value, NodeName, out Node? node)) yield return node; } } diff --git a/Content.Server/Explosion/EntitySystems/ExplosionGridTileFlood.cs b/Content.Server/Explosion/EntitySystems/ExplosionGridTileFlood.cs index 8d2a699de2..7db1f513f7 100644 --- a/Content.Server/Explosion/EntitySystems/ExplosionGridTileFlood.cs +++ b/Content.Server/Explosion/EntitySystems/ExplosionGridTileFlood.cs @@ -271,7 +271,7 @@ public sealed class ExplosionGridTileFlood : ExplosionTileFlood var direction = (AtmosDirection) (1 << i); if (ignoreTileBlockers || !blockedDirections.IsFlagSet(direction)) { - ProcessNewTile(iteration, tile.Offset(direction), direction.GetOpposite()); + ProcessNewTile(iteration, tile.Offset(direction), i.ToOppositeDir()); } } @@ -300,7 +300,7 @@ public sealed class ExplosionGridTileFlood : ExplosionTileFlood var direction = (AtmosDirection) (1 << i); if (blockedDirections.IsFlagSet(direction)) { - list.Add((tile.Offset(direction), direction.GetOpposite())); + list.Add((tile.Offset(direction), i.ToOppositeDir())); } } } diff --git a/Content.Server/Explosion/EntitySystems/ExplosionSpaceTileFlood.cs b/Content.Server/Explosion/EntitySystems/ExplosionSpaceTileFlood.cs index f8c917c1cd..313b03e03a 100644 --- a/Content.Server/Explosion/EntitySystems/ExplosionSpaceTileFlood.cs +++ b/Content.Server/Explosion/EntitySystems/ExplosionSpaceTileFlood.cs @@ -97,7 +97,7 @@ public sealed class ExplosionSpaceTileFlood : ExplosionTileFlood if (!unblockedDirections.IsFlagSet(direction)) continue; // explosion cannot propagate in this direction. Ever. - ProcessNewTile(iteration, tile.Offset(direction), direction.GetOpposite()); + ProcessNewTile(iteration, tile.Offset(direction), i.ToOppositeDir()); } } } diff --git a/Content.Server/Mech/Systems/MechSystem.cs b/Content.Server/Mech/Systems/MechSystem.cs index 78034e0fc3..9e546dc33f 100644 --- a/Content.Server/Mech/Systems/MechSystem.cs +++ b/Content.Server/Mech/Systems/MechSystem.cs @@ -404,14 +404,17 @@ public sealed partial class MechSystem : SharedMechSystem if (args.Handled) return; - if (!TryComp(component.Mech, out var mech) || - !TryComp(component.Mech, out var mechAir)) + if (!TryComp(component.Mech, out MechComponent? mech)) + return; + + if (mech.Airtight && TryComp(component.Mech, out MechAirComponent? air)) { + args.Handled = true; + args.Gas = air.Air; return; } - args.Gas = mech.Airtight ? mechAir.Air : _atmosphere.GetContainingMixture(component.Mech); - + args.Gas = _atmosphere.GetContainingMixture(component.Mech, excite: args.Excite); args.Handled = true; } diff --git a/Content.Server/Medical/CryoPodSystem.cs b/Content.Server/Medical/CryoPodSystem.cs index a7d12d9f0f..a949d980be 100644 --- a/Content.Server/Medical/CryoPodSystem.cs +++ b/Content.Server/Medical/CryoPodSystem.cs @@ -257,10 +257,7 @@ public sealed partial class CryoPodSystem : SharedCryoPodSystem private void OnCryoPodUpdateAtmosphere(Entity entity, ref AtmosDeviceUpdateEvent args) { - if (!TryComp(entity, out NodeContainerComponent? nodeContainer)) - return; - - if (!_nodeContainer.TryGetNode(nodeContainer, entity.Comp.PortName, out PortablePipeNode? portNode)) + if (!_nodeContainer.TryGetNode(entity.Owner, entity.Comp.PortName, out PortablePipeNode? portNode)) return; if (!TryComp(entity, out CryoPodAirComponent? cryoPodAir)) @@ -279,14 +276,10 @@ public sealed partial class CryoPodSystem : SharedCryoPodSystem if (!TryComp(entity, out CryoPodAirComponent? cryoPodAir)) return; - var gasMixDict = new Dictionary { { Name(entity.Owner), cryoPodAir.Air } }; + args.GasMixtures ??= new Dictionary { { Name(entity.Owner), cryoPodAir.Air } }; // If it's connected to a port, include the port side - if (TryComp(entity, out NodeContainerComponent? nodeContainer)) - { - if (_nodeContainer.TryGetNode(nodeContainer, entity.Comp.PortName, out PipeNode? port)) - gasMixDict.Add(entity.Comp.PortName, port.Air); - } - args.GasMixtures = gasMixDict; + if (_nodeContainer.TryGetNode(entity.Owner, entity.Comp.PortName, out PipeNode? port)) + args.GasMixtures.Add(entity.Comp.PortName, port.Air); } private void OnEjected(Entity cryoPod, ref EntRemovedFromContainerMessage args) diff --git a/Content.Server/NodeContainer/EntitySystems/NodeContainerSystem.cs b/Content.Server/NodeContainer/EntitySystems/NodeContainerSystem.cs index 99d18aeb3f..19b811a287 100644 --- a/Content.Server/NodeContainer/EntitySystems/NodeContainerSystem.cs +++ b/Content.Server/NodeContainer/EntitySystems/NodeContainerSystem.cs @@ -14,6 +14,7 @@ namespace Content.Server.NodeContainer.EntitySystems public sealed class NodeContainerSystem : EntitySystem { [Dependency] private readonly NodeGroupSystem _nodeGroupSystem = default!; + private EntityQuery _query; public override void Initialize() { @@ -26,6 +27,8 @@ namespace Content.Server.NodeContainer.EntitySystems SubscribeLocalEvent(OnReAnchor); SubscribeLocalEvent(OnMoveEvent); SubscribeLocalEvent(OnExamine); + + _query = GetEntityQuery(); } public bool TryGetNode(NodeContainerComponent component, string? identifier, [NotNullWhen(true)] out T? node) where T : Node @@ -46,6 +49,77 @@ namespace Content.Server.NodeContainer.EntitySystems return false; } + public bool TryGetNode(Entity ent, string identifier, [NotNullWhen(true)] out T? node) where T : Node + { + if (_query.Resolve(ent, ref ent.Comp, false) + && ent.Comp.Nodes.TryGetValue(identifier, out var n) + && n is T t) + { + node = t; + return true; + } + + node = null; + return false; + } + + public bool TryGetNodes( + Entity ent, + string id1, + string id2, + [NotNullWhen(true)] out T1? node1, + [NotNullWhen(true)] out T2? node2) + where T1 : Node + where T2 : Node + { + if (_query.Resolve(ent, ref ent.Comp, false) + && ent.Comp.Nodes.TryGetValue(id1, out var n1) + && n1 is T1 t1 + && ent.Comp.Nodes.TryGetValue(id2, out var n2) + && n2 is T2 t2) + { + node1 = t1; + node2 = t2; + return true; + } + + node1 = null; + node2 = null; + return false; + } + + public bool TryGetNodes( + Entity ent, + string id1, + string id2, + string id3, + [NotNullWhen(true)] out T1? node1, + [NotNullWhen(true)] out T2? node2, + [NotNullWhen(true)] out T3? node3) + where T1 : Node + where T2 : Node + where T3 : Node + { + if (_query.Resolve(ent, ref ent.Comp, false) + && ent.Comp.Nodes.TryGetValue(id1, out var n1) + && n1 is T1 t1 + && ent.Comp.Nodes.TryGetValue(id2, out var n2) + && n2 is T2 t2 + && ent.Comp.Nodes.TryGetValue(id3, out var n3) + && n2 is T3 t3) + { + node1 = t1; + node2 = t2; + node3 = t3; + return true; + } + + node1 = null; + node2 = null; + node3 = null; + return false; + } + private void OnInitEvent(EntityUid uid, NodeContainerComponent component, ComponentInit args) { foreach (var (key, node) in component.Nodes) diff --git a/Content.Server/PneumaticCannon/PneumaticCannonSystem.cs b/Content.Server/PneumaticCannon/PneumaticCannonSystem.cs index 60f0603074..6e0e0c503a 100644 --- a/Content.Server/PneumaticCannon/PneumaticCannonSystem.cs +++ b/Content.Server/PneumaticCannon/PneumaticCannonSystem.cs @@ -94,7 +94,7 @@ public sealed class PneumaticCannonSystem : SharedPneumaticCannonSystem return; // this should always be possible, as we'll eject the gas tank when it no longer is - var environment = _atmos.GetContainingMixture(cannon, false, true); + var environment = _atmos.GetContainingMixture(cannon.Owner, false, true); var removed = _gasTank.RemoveAir(gas.Value, component.GasUsage); if (environment != null && removed != null) { diff --git a/Content.Server/Power/Components/CableVisComponent.cs b/Content.Server/Power/Components/CableVisComponent.cs index bd9c62ba80..51d68b99fd 100644 --- a/Content.Server/Power/Components/CableVisComponent.cs +++ b/Content.Server/Power/Components/CableVisComponent.cs @@ -4,7 +4,7 @@ public sealed partial class CableVisComponent : Component { [ViewVariables(VVAccess.ReadWrite)] - [DataField("node")] - public string? Node; + [DataField("node", required:true)] + public string Node; } } diff --git a/Content.Server/Power/EntitySystems/CableVisSystem.cs b/Content.Server/Power/EntitySystems/CableVisSystem.cs index ec08523d44..1a68e87ad6 100644 --- a/Content.Server/Power/EntitySystems/CableVisSystem.cs +++ b/Content.Server/Power/EntitySystems/CableVisSystem.cs @@ -23,10 +23,7 @@ namespace Content.Server.Power.EntitySystems private void UpdateAppearance(EntityUid uid, CableVisComponent cableVis, ref NodeGroupsRebuilt args) { - if (!TryComp(uid, out NodeContainerComponent? nodeContainer) || !TryComp(uid, out AppearanceComponent? appearance)) - return; - - if (!_nodeContainer.TryGetNode(nodeContainer, cableVis.Node, out var node)) + if (!_nodeContainer.TryGetNode(uid, cableVis.Node, out CableNode? node)) return; var transform = Transform(uid); @@ -55,7 +52,7 @@ namespace Content.Server.Power.EntitySystems }; } - _appearance.SetData(uid, WireVisVisuals.ConnectedMask, mask, appearance); + _appearance.SetData(uid, WireVisVisuals.ConnectedMask, mask); } } } diff --git a/Content.Server/Power/Generator/GasPowerReceiverSystem.cs b/Content.Server/Power/Generator/GasPowerReceiverSystem.cs index 76cf90c369..5f79906c99 100644 --- a/Content.Server/Power/Generator/GasPowerReceiverSystem.cs +++ b/Content.Server/Power/Generator/GasPowerReceiverSystem.cs @@ -26,12 +26,8 @@ public sealed class GasPowerReceiverSystem : EntitySystem { var timeDelta = args.dt; - if (!HasComp(uid) - || !TryComp(uid, out var nodeContainer) - || !_nodeContainer.TryGetNode(nodeContainer, "pipe", out var pipe)) - { + if (!_nodeContainer.TryGetNode(uid, "pipe", out PipeNode? pipe)) return; - } // if we're below the max temperature, then we are simply consuming our target gas if (pipe.Air.Temperature <= component.MaxTemperature) @@ -57,7 +53,7 @@ public sealed class GasPowerReceiverSystem : EntitySystem if (component.OffVentGas) { // eject the gas into the atmosphere - var mix = _atmosphereSystem.GetContainingMixture(uid, false, true); + var mix = _atmosphereSystem.GetContainingMixture(uid, args.Grid, args.Map, false, true); if (mix is not null) _atmosphereSystem.Merge(res, mix); } diff --git a/Content.Server/Spreader/SpreaderSystem.cs b/Content.Server/Spreader/SpreaderSystem.cs index 671c281d1f..fe14d86aa1 100644 --- a/Content.Server/Spreader/SpreaderSystem.cs +++ b/Content.Server/Spreader/SpreaderSystem.cs @@ -231,10 +231,9 @@ public sealed class SpreaderSystem : EntitySystem // Add the normal neighbors. for (var i = 0; i < 4; i++) { - var direction = (Direction) (i * 2); - var atmosDir = direction.ToAtmosDirection(); - var neighborPos = SharedMapSystem.GetDirection(tile, direction); - neighborTiles.Add((comp.GridUid.Value, grid, neighborPos, atmosDir, atmosDir.GetOpposite())); + var atmosDir = (AtmosDirection) (1 << i); + var neighborPos = tile.Offset(atmosDir); + neighborTiles.Add((comp.GridUid.Value, grid, neighborPos, atmosDir, i.ToOppositeDir())); } foreach (var (neighborEnt, neighborGrid, neighborPos, ourAtmosDir, otherAtmosDir) in neighborTiles) diff --git a/Content.Shared/Atmos/AtmosDirection.cs b/Content.Shared/Atmos/AtmosDirection.cs index a25c9d553c..09ba521aa9 100644 --- a/Content.Shared/Atmos/AtmosDirection.cs +++ b/Content.Shared/Atmos/AtmosDirection.cs @@ -1,4 +1,5 @@ -using System.Runtime.CompilerServices; +using System.Numerics; +using System.Runtime.CompilerServices; using Robust.Shared.Serialization; namespace Content.Shared.Atmos @@ -15,6 +16,8 @@ namespace Content.Shared.Atmos South = 1 << 1, // 2 East = 1 << 2, // 4 West = 1 << 3, // 8 + // If more directions are added, note that AtmosDirectionHelpers.ToOppositeIndex() expects opposite directions + // to come in pairs NorthEast = North | East, // 5 SouthEast = South | East, // 6 @@ -42,6 +45,22 @@ namespace Content.Shared.Atmos }; } + /// + /// This returns the index that corresponds to the opposite direction of some other direction index. + /// I.e., 1<<OppositeIndex(i) == (1<<i).GetOpposite() + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ToOppositeIndex(this int index) + { + return index ^ 1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static AtmosDirection ToOppositeDir(this int index) + { + return (AtmosDirection) (1 << (index ^ 1)); + } + public static Direction ToDirection(this AtmosDirection direction) { return direction switch @@ -119,10 +138,11 @@ namespace Content.Shared.Atmos return angle.GetDir().ToAtmosDirection(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ToIndex(this AtmosDirection direction) { // This will throw if you pass an invalid direction. Not this method's fault, but yours! - return (int) Math.Log2((int) direction); + return BitOperations.Log2((uint)direction); } public static AtmosDirection WithFlag(this AtmosDirection direction, AtmosDirection other) diff --git a/Content.Shared/Tools/Systems/WeldableSystem.cs b/Content.Shared/Tools/Systems/WeldableSystem.cs index f887ed3049..b0ea68f713 100644 --- a/Content.Shared/Tools/Systems/WeldableSystem.cs +++ b/Content.Shared/Tools/Systems/WeldableSystem.cs @@ -15,14 +15,7 @@ public sealed class WeldableSystem : EntitySystem [Dependency] private readonly SharedToolSystem _toolSystem = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; - - public bool IsWelded(EntityUid uid, WeldableComponent? component = null) - { - if (!Resolve(uid, ref component, false)) - return false; - - return component.IsWelded; - } + private EntityQuery _query; public override void Initialize() { @@ -31,6 +24,13 @@ public sealed class WeldableSystem : EntitySystem SubscribeLocalEvent(OnWeldFinished); SubscribeLocalEvent(OnWeldChanged); SubscribeLocalEvent(OnExamine); + + _query = GetEntityQuery(); + } + + public bool IsWelded(EntityUid uid, WeldableComponent? component = null) + { + return _query.Resolve(uid, ref component, false) && component.IsWelded; } private void OnExamine(EntityUid uid, WeldableComponent component, ExaminedEvent args) @@ -49,7 +49,7 @@ public sealed class WeldableSystem : EntitySystem private bool CanWeld(EntityUid uid, EntityUid tool, EntityUid user, WeldableComponent? component = null) { - if (!Resolve(uid, ref component)) + if (!_query.Resolve(uid, ref component)) return false; // Other component systems @@ -63,7 +63,7 @@ public sealed class WeldableSystem : EntitySystem private bool TryWeld(EntityUid uid, EntityUid tool, EntityUid user, WeldableComponent? component = null) { - if (!Resolve(uid, ref component)) + if (!_query.Resolve(uid, ref component)) return false; if (!CanWeld(uid, tool, user, component)) @@ -115,17 +115,13 @@ public sealed class WeldableSystem : EntitySystem private void UpdateAppearance(EntityUid uid, WeldableComponent? component = null) { - if (!Resolve(uid, ref component)) - return; - - if (!TryComp(uid, out AppearanceComponent? appearance)) - return; - _appearance.SetData(uid, WeldableVisuals.IsWelded, component.IsWelded, appearance); + if (_query.Resolve(uid, ref component)) + _appearance.SetData(uid, WeldableVisuals.IsWelded, component.IsWelded); } public void SetWeldedState(EntityUid uid, bool state, WeldableComponent? component = null) { - if (!Resolve(uid, ref component)) + if (!_query.Resolve(uid, ref component)) return; if (component.IsWelded == state) @@ -141,7 +137,7 @@ public sealed class WeldableSystem : EntitySystem public void SetWeldingTime(EntityUid uid, TimeSpan time, WeldableComponent? component = null) { - if (!Resolve(uid, ref component)) + if (!_query.Resolve(uid, ref component)) return; if (component.WeldingTime.Equals(time)) diff --git a/Resources/Prototypes/Entities/Virtual/electrocution.yml b/Resources/Prototypes/Entities/Virtual/electrocution.yml index 497071ee93..ac65245191 100644 --- a/Resources/Prototypes/Entities/Virtual/electrocution.yml +++ b/Resources/Prototypes/Entities/Virtual/electrocution.yml @@ -1,7 +1,7 @@ # Special entity used to attach to power networks as load when somebody gets electrocuted. - type: entity id: VirtualElectrocutionLoadBase - noSpawn: true + abstract: true components: - type: Electrocution - type: Icon