From 888a3bda515a214733bf748c5d6a7e7c923a301e Mon Sep 17 00:00:00 2001
From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com>
Date: Sat, 30 Mar 2024 17:17:53 +1300
Subject: [PATCH] Atmos device performance improvements (#26493)
* Atmos device performance improvements
* AtmosDirection perf improvements
* Fix errors
* Add GasTileOverlayComponent arguments
* Make excite no longer invalidate a tile
---
.../Atmos/EntitySystems/AirFilterSystem.cs | 10 +--
.../Atmos/EntitySystems/AtmosExposedSystem.cs | 12 +--
.../EntitySystems/AtmosphereSystem.API.cs | 86 +++++++++++--------
.../AtmosphereSystem.ExcitedGroup.cs | 12 ++-
.../AtmosphereSystem.GridAtmosphere.cs | 11 +--
.../EntitySystems/AtmosphereSystem.Hotspot.cs | 14 +--
.../EntitySystems/AtmosphereSystem.LINDA.cs | 18 ++--
.../AtmosphereSystem.Monstermos.cs | 40 +++++----
.../AtmosphereSystem.Processing.cs | 46 ++++++----
.../AtmosphereSystem.Superconductivity.cs | 2 +-
.../EntitySystems/AtmosphereSystem.Utils.cs | 12 ++-
.../Atmos/EntitySystems/AtmosphereSystem.cs | 2 +-
.../Atmos/EntitySystems/GasTankSystem.cs | 2 +-
.../EntitySystems/GasTileOverlaySystem.cs | 8 +-
.../EntitySystems/HeatExchangerSystem.cs | 20 ++---
.../Monitor/Systems/AtmosMonitoringSystem.cs | 6 +-
.../EntitySystems/GasPassiveGateSystem.cs | 6 +-
.../EntitySystems/GasPressurePumpSystem.cs | 4 +-
.../Binary/EntitySystems/GasRecyclerSystem.cs | 10 +--
.../Binary/EntitySystems/GasValveSystem.cs | 5 +-
.../EntitySystems/GasVolumePumpSystem.cs | 7 +-
.../Piping/Components/AtmosDeviceComponent.cs | 20 +++--
.../Piping/EntitySystems/AtmosDeviceSystem.cs | 3 +-
.../Other/EntitySystems/GasMinerSystem.cs | 4 +-
.../Trinary/EntitySystems/GasFilterSystem.cs | 15 ++--
.../Trinary/EntitySystems/GasMixerSystem.cs | 14 +--
.../PressureControlledValveSystem.cs | 6 +-
.../Unary/EntitySystems/GasCanisterSystem.cs | 4 +-
.../Unary/EntitySystems/GasCondenserSystem.cs | 5 +-
.../EntitySystems/GasOutletInjectorSystem.cs | 10 +--
.../EntitySystems/GasPassiveVentSystem.cs | 7 +-
.../Unary/EntitySystems/GasPortableSystem.cs | 5 +-
.../EntitySystems/GasThermoMachineSystem.cs | 5 +-
.../Unary/EntitySystems/GasVentPumpSystem.cs | 12 +--
.../EntitySystems/GasVentScrubberSystem.cs | 19 ++--
.../Atmos/Portable/PortableScrubberSystem.cs | 32 +++----
.../Atmos/Portable/SpaceHeaterSystem.cs | 2 +-
.../Electrocution/ElectrocutionNode.cs | 9 +-
.../EntitySystems/ExplosionGridTileFlood.cs | 4 +-
.../EntitySystems/ExplosionSpaceTileFlood.cs | 2 +-
Content.Server/Mech/Systems/MechSystem.cs | 11 ++-
Content.Server/Medical/CryoPodSystem.cs | 15 +---
.../EntitySystems/NodeContainerSystem.cs | 74 ++++++++++++++++
.../PneumaticCannon/PneumaticCannonSystem.cs | 2 +-
.../Power/Components/CableVisComponent.cs | 4 +-
.../Power/EntitySystems/CableVisSystem.cs | 7 +-
.../Power/Generator/GasPowerReceiverSystem.cs | 8 +-
Content.Server/Spreader/SpreaderSystem.cs | 7 +-
Content.Shared/Atmos/AtmosDirection.cs | 24 +++++-
.../Tools/Systems/WeldableSystem.cs | 32 +++----
.../Entities/Virtual/electrocution.yml | 2 +-
51 files changed, 373 insertions(+), 324 deletions(-)
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
--
2.51.2