From: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com> Date: Tue, 13 Jan 2026 23:06:59 +0000 (-0800) Subject: AirtightSystem Tests (#42190) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=60e172e12883fc10135a4cf09d42bdfcd0ba0026;p=space-station-14.git AirtightSystem Tests (#42190) --- diff --git a/Content.IntegrationTests/Tests/Atmos/AirtightTest.cs b/Content.IntegrationTests/Tests/Atmos/AirtightTest.cs new file mode 100644 index 0000000000..63e4d9f2d2 --- /dev/null +++ b/Content.IntegrationTests/Tests/Atmos/AirtightTest.cs @@ -0,0 +1,585 @@ +using System.Numerics; +using Content.Server.Atmos.Components; +using Content.Server.Atmos.EntitySystems; +using Content.Shared.Atmos; +using Robust.Shared.GameObjects; +using Robust.Shared.Map; +using Robust.Shared.Maths; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.IntegrationTests.Tests.Atmos; + +/// +/// Mega-testclass for testing and . +/// +[TestOf(typeof(AirtightSystem))] +[TestOf(typeof(AtmosphereSystem))] +public sealed class AirtightTest : AtmosTest +{ + // Load the same DeltaPressure test because it's quite a useful testmap for testing airtightness. + protected override ResPath? TestMapPath => new("Maps/Test/Atmospherics/DeltaPressure/deltapressuretest.yml"); + + private readonly EntProtoId _wallProto = new("WallSolid"); + + private EntityUid _targetWall = EntityUid.Invalid; + private EntityUid _targetRotationEnt = EntityUid.Invalid; + + #region Prototypes + + [TestPrototypes] + private const string Prototypes = @" +- type: entity + id: AirtightDirectionalRotationTest + parent: WindowDirectional + components: + - type: Airtight + airBlockedDirection: North + fixAirBlockedDirectionInitialize: true + noAirWhenFullyAirBlocked: false +"; + + #endregion + + #region Component and Helper Assertions + + /* + Tests for asserting that proper ComponentInit and other events properly work. + */ + + [Test] + public async Task Component_InitDataCorrect() + { + // Ensure grid/atmos is initialized. + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + await Server.WaitPost(delegate + { + var coords = new EntityCoordinates(RelevantAtmos.Owner, Vector2.Zero); + _targetWall = SEntMan.SpawnAtPosition(_wallProto, coords); + }); + + SEntMan.TryGetComponent(_targetWall, out var airtightComp); + Assert.That(airtightComp, Is.Not.Null, "Expected spawned wall entity to have AirtightComponent."); + + // The data on the component itself should reflect full blockage. + // It should also hold the proper last position. + using (Assert.EnterMultipleScope()) + { + Assert.That(airtightComp.AirBlockedDirection, Is.EqualTo(AtmosDirection.All)); + Assert.That(airtightComp.LastPosition, Is.EqualTo((RelevantAtmos.Owner, Vector2i.Zero))); + } + } + + [Test] + [TestCase(AtmosDirection.North)] + [TestCase(AtmosDirection.South)] + [TestCase(AtmosDirection.East)] + [TestCase(AtmosDirection.West)] + public async Task MultiTile_Component_InitDataCorrect(AtmosDirection direction) + { + // Ensure grid/atmos is initialized. + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + var offsetVec = Vector2i.Zero.Offset(direction); + await Server.WaitPost(delegate + { + var coords = new EntityCoordinates(RelevantAtmos.Owner, offsetVec); + _targetWall = SEntMan.SpawnAtPosition(_wallProto, coords); + }); + + SEntMan.TryGetComponent(_targetWall, out var airtightComp); + Assert.That(airtightComp, Is.Not.Null, "Expected spawned wall entity to have AirtightComponent."); + + // The data on the component itself should reflect full blockage. + // It should also hold the proper last position. + using (Assert.EnterMultipleScope()) + { + Assert.That(airtightComp.AirBlockedDirection, Is.EqualTo(AtmosDirection.All)); + Assert.That(airtightComp.LastPosition, Is.EqualTo((RelevantAtmos.Owner, offsetVec))); + } + } + + #endregion + + #region Single Tile Assertion + + /* + Tests for asserting single tile airtightness state on both reconstructed and cached data. + These tests just spawn a wall in the center and make sure that both reconstructed and cached + airtight data reflect the expected states both immediately after the action and after an atmos tick. + */ + + /// + /// Tests that the reconstructed airtight map reflects properly when an airtight entity is spawned. + /// + [Test] + public async Task Spawn_ReconstructedUpdatesImmediately() + { + // Ensure grid/atmos is initialized. + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + // Before an entity is spawned, the tile in question should be completely unblocked. + // This should be reflected in a reconstruction. + using (Assert.EnterMultipleScope()) + { + Assert.That( + SAtmos.IsTileAirBlocked(ProcessEnt.Owner, Vector2i.Zero, mapGridComp: ProcessEnt.Comp3), + Is.False, + "Expected no airtightness for reconstructed AirtightData before spawning an airtight entity."); + } + + // We cannot use the Spawn InteractionTest helper because it runs ticks, + // which invalidate testing for cached data (ticks would update the cache). + await Server.WaitPost(delegate + { + var coords = new EntityCoordinates(RelevantAtmos.Owner, Vector2.Zero); + _targetWall = SEntMan.SpawnAtPosition(_wallProto, coords); + }); + + // Now, immediately after spawn, the reconstructed data should reflect airtightness. + Assert.That( + SAtmos.IsTileAirBlocked(ProcessEnt.Owner, Vector2i.Zero, mapGridComp: ProcessEnt.Comp3), + Is.True, + "Expected airtightness for reconstructed AirtightData immediately after spawn."); + } + + /// + /// Tests that the AirtightData cache updates properly when an airtight entity is spawned. + /// + [Test] + public async Task Spawn_CacheUpdatesOnAtmosTick() + { + // Ensure grid/atmos is initialized. + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + // Space should be blank before spawn. + using (Assert.EnterMultipleScope()) + { + Assert.That( + SAtmos.IsTileAirBlockedCached(RelevantAtmos, Vector2i.Zero), + Is.False, + "Expected cached AirtightData to be unblocked before spawning an airtight entity."); + + var tile = RelevantAtmos.Comp.Tiles[Vector2i.Zero]; + Assert.That(tile.AdjacentBits, + Is.EqualTo(AtmosDirection.All), + "Expected tile to be completely unblocked before spawning an airtight entity."); + + Assert.That(tile.AirtightData.BlockedDirections, + Is.EqualTo(AtmosDirection.Invalid), + "Expected AirtightData to reflect non-airtight state before spawning an airtight entity."); + + for (var i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection)(1 << i); + var curTile = tile.AdjacentTiles[i]; + Assert.That(curTile, Is.Not.Null, $"Center tile does not hold expected reference to adjacent tile in direction {direction}."); + } + } + + await Server.WaitPost(delegate + { + var coords = new EntityCoordinates(RelevantAtmos.Owner, Vector2.Zero); + _targetWall = SEntMan.SpawnAtPosition(_wallProto, coords); + }); + + // Now, immediately after spawn, the reconstructed data should reflect airtightness, + // but the cached data should still be stale. + // This goes the same for the references, which haven't been updated, as well as the AirtightData. + using (Assert.EnterMultipleScope()) + { + Assert.That( + SAtmos.IsTileAirBlockedCached(RelevantAtmos, Vector2i.Zero), + Is.False, + "Expected cached AirtightData to remain stale immediately after spawn before atmos tick."); + + var tile = RelevantAtmos.Comp.Tiles[Vector2i.Zero]; + Assert.That(tile.AdjacentBits, + Is.EqualTo(AtmosDirection.All), + "Expected tile to still show non-airtight state before an atmos tick."); + + Assert.That(tile.AirtightData.BlockedDirections, + Is.EqualTo(AtmosDirection.Invalid), + "Expected AirtightData to reflect non-airtight state after spawn before an atmos tick."); + + for (var i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection)(1 << i); + var curTile = tile.AdjacentTiles[i]; + Assert.That(curTile, Is.Not.Null, $"Center tile does not hold expected reference to adjacent tile in direction {direction}."); + } + } + + // Tick to update cache. + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + using (Assert.EnterMultipleScope()) + { + Assert.That( + SAtmos.IsTileAirBlocked(ProcessEnt.Owner, Vector2i.Zero, mapGridComp: ProcessEnt.Comp3), + Is.True, + "Expected airtightness for reconstructed AirtightData after atmos tick."); + + Assert.That( + SAtmos.IsTileAirBlockedCached(RelevantAtmos, Vector2i.Zero), + Is.True, + "Expected cached AirtightData to reflect airtightness after atmos tick."); + + var tile = RelevantAtmos.Comp.Tiles[Vector2i.Zero]; + Assert.That(tile.AdjacentBits, + Is.EqualTo(AtmosDirection.Invalid), + "Expected tile to reflect airtight state after atmos tick."); + + Assert.That(tile.AirtightData.BlockedDirections, + Is.EqualTo(AtmosDirection.All), + "Expected AirtightData to reflect airtight state after spawn before an atmos tick."); + + for (var i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection)(1 << i); + var curTile = tile.AdjacentTiles[i]; + Assert.That(curTile, Is.Null, $"Center tile holds unexpected reference to adjacent tile in direction {direction}."); + } + } + } + + /// + /// Tests that an airtight reconstruction reflects properly after an entity is deleted. + /// + [Test] + public async Task Delete_ReconstructedUpdatesImmediately() + { + // Ensure grid/atmos is initialized. + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + await Server.WaitPost(delegate + { + var coords = new EntityCoordinates(RelevantAtmos.Owner, Vector2.Zero); + _targetWall = SEntMan.SpawnAtPosition(_wallProto, coords); + }); + + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + Assert.That( + SAtmos.IsTileAirBlocked(ProcessEnt.Owner, Vector2i.Zero, mapGridComp: ProcessEnt.Comp3), + Is.True, + "Expected airtightness for reconstructed AirtightData before deletion."); + + await Server.WaitPost(delegate + { + SEntMan.DeleteEntity(_targetWall); + }); + + Assert.That( + SAtmos.IsTileAirBlocked(ProcessEnt.Owner, Vector2i.Zero, mapGridComp: ProcessEnt.Comp3), + Is.False, + "Expected no airtightness for reconstructed AirtightData immediately after deletion."); + + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + Assert.That( + SAtmos.IsTileAirBlocked(ProcessEnt.Owner, Vector2i.Zero, mapGridComp: ProcessEnt.Comp3), + Is.False, + "Expected no airtightness for reconstructed AirtightData after atmos tick."); + } + + /// + /// Tests that the cached airtight map reflects properly when an entity is deleted + /// + [Test] + public async Task Delete_CacheUpdatesOnAtmosTick() + { + // Ensure grid/atmos is initialized. + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + await Server.WaitPost(delegate + { + var coords = new EntityCoordinates(RelevantAtmos.Owner, Vector2.Zero); + _targetWall = SEntMan.SpawnAtPosition(_wallProto, coords); + }); + + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + await Server.WaitPost(delegate + { + SEntMan.DeleteEntity(_targetWall); + }); + + using (Assert.EnterMultipleScope()) + { + Assert.That( + SAtmos.IsTileAirBlockedCached(RelevantAtmos, Vector2i.Zero), + Is.True, + "Expected cached AirtightData to remain stale immediately after deletion before atmos tick."); + + var tile = RelevantAtmos.Comp.Tiles[Vector2i.Zero]; + Assert.That(tile.AdjacentBits, + Is.EqualTo(AtmosDirection.Invalid), + "Expected tile to still show airtight state before atmos tick after deletion."); + + Assert.That(tile.AirtightData.BlockedDirections, + Is.EqualTo(AtmosDirection.All), + "Expected AirtightData to reflect non-airtight state before after deletion before an atmos tick."); + + for (var i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection)(1 << i); + var curTile = tile.AdjacentTiles[i]; + Assert.That(curTile, Is.Null, $"Center tile holds unexpected reference to adjacent tile in direction {direction}."); + } + } + + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + using (Assert.EnterMultipleScope()) + { + Assert.That( + SAtmos.IsTileAirBlockedCached(RelevantAtmos, Vector2i.Zero), + Is.False, + "Expected cached AirtightData to reflect deletion after atmos tick."); + + var tile = RelevantAtmos.Comp.Tiles[Vector2i.Zero]; + Assert.That(tile.AdjacentBits, + Is.EqualTo(AtmosDirection.All), + "Expected tile to reflect non-airtight state after atmos tick."); + + Assert.That(tile.AirtightData.BlockedDirections, + Is.EqualTo(AtmosDirection.Invalid), + "Expected AirtightData to reflect non-airtight state after atmos tick."); + + for (var i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection)(1 << i); + var curTile = tile.AdjacentTiles[i]; + Assert.That(curTile, Is.Not.Null, $"Center tile does not hold expected reference to adjacent tile in direction {direction}."); + } + } + } + + #endregion + + #region Multi-Tile Assertion + + /* + Tests for asserting multi-tile airtightness state on cached data. + These tests spawn multiple entities and check that the center unblocked entity + properly reflects partial airtightness states. + + Note that reconstruction won't save you in the case where you're surrounded by airtight entities, + as those don't show up in the reconstruction. Thus, only cached data tests are done here. + */ + + /// + /// Tests that the cached airtight map reflects properly when airtight entities are spawned + /// along the cardinal directions. + /// + /// The direction to spawn the airtight entity in. + [Test] + [TestCase(AtmosDirection.North)] + [TestCase(AtmosDirection.South)] + [TestCase(AtmosDirection.East)] + [TestCase(AtmosDirection.West)] + public async Task MultiTile_Spawn_CacheUpdatesOnAtmosTick(AtmosDirection atmosDirection) + { + // Ensure grid/atmos is initialized. + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + // Tile should be completely unblocked. + using (Assert.EnterMultipleScope()) + { + var tile = RelevantAtmos.Comp.Tiles[Vector2i.Zero]; + Assert.That(tile.AdjacentBits, + Is.EqualTo(AtmosDirection.All), + "Expected tile to be completely unblocked before spawning an airtight entity."); + + for (var i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection)(1 << i); + var curTile = tile.AdjacentTiles[i]; + Assert.That(curTile, Is.Not.Null, $"Center tile does not hold expected reference to adjacent tile in direction {direction}."); + } + } + + await Server.WaitPost(delegate + { + var offsetVec = Vector2i.Zero.Offset(atmosDirection); + var coords = new EntityCoordinates(RelevantAtmos.Owner, offsetVec); + _targetWall = SEntMan.SpawnAtPosition(_wallProto, coords); + }); + + using (Assert.EnterMultipleScope()) + { + var tile = RelevantAtmos.Comp.Tiles[Vector2i.Zero]; + Assert.That(tile.AdjacentBits, + Is.EqualTo(AtmosDirection.All), + "Expected tile to still show non-airtight state before an atmos tick."); + + for (var i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection)(1 << i); + var curTile = tile.AdjacentTiles[i]; + Assert.That(curTile, Is.Not.Null, $"Center tile does not hold expected reference to adjacent tile in direction {direction}."); + } + } + + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + using (Assert.EnterMultipleScope()) + { + var tile = RelevantAtmos.Comp.Tiles[Vector2i.Zero]; + Assert.That(tile.AdjacentBits, + Is.EqualTo(AtmosDirection.All & ~atmosDirection), + "Expected tile to reflect airtight state after atmos tick."); + + for (var i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection)(1 << i); + var curTile = tile.AdjacentTiles[i]; + if (direction == atmosDirection) + { + Assert.That(curTile, Is.Null, $"Center tile holds unexpected reference to adjacent tile in direction {direction}."); + } + else + { + Assert.That(curTile, Is.Not.Null, $"Center tile does not hold expected reference to adjacent tile in direction {direction}."); + } + } + } + } + + /// + /// Tests that the cached airtight map reflects properly when an airtight entity is deleted + /// along a cardinal direction. + /// + /// The direction the airtight entity is spawned and then deleted in. + [Test] + [TestCase(AtmosDirection.North)] + [TestCase(AtmosDirection.South)] + [TestCase(AtmosDirection.East)] + [TestCase(AtmosDirection.West)] + public async Task MultiTile_Delete_CacheUpdatesOnAtmosTick(AtmosDirection atmosDirection) + { + // Ensure grid/atmos is initialized. + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + await Server.WaitPost(delegate + { + var offsetVec = Vector2i.Zero.Offset(atmosDirection); + var coords = new EntityCoordinates(RelevantAtmos.Owner, offsetVec); + _targetWall = SEntMan.SpawnAtPosition(_wallProto, coords); + }); + + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + await Server.WaitPost(delegate + { + SEntMan.DeleteEntity(_targetWall); + }); + + using (Assert.EnterMultipleScope()) + { + var tile = RelevantAtmos.Comp.Tiles[Vector2i.Zero]; + Assert.That(tile.AdjacentBits, + Is.EqualTo(AtmosDirection.All & ~atmosDirection), + "Expected tile to remain stale immediately after deletion before an atmos tick."); + + for (var i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection)(1 << i); + var curTile = tile.AdjacentTiles[i]; + if (direction == atmosDirection) + { + Assert.That(curTile, Is.Null, $"Center tile holds unexpected reference to adjacent tile in direction {direction}."); + } + else + { + Assert.That(curTile, Is.Not.Null, $"Center tile does not hold expected reference to adjacent tile in direction {direction}."); + } + } + } + + // Tick to update cache after deletion. + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + using (Assert.EnterMultipleScope()) + { + var tile = RelevantAtmos.Comp.Tiles[Vector2i.Zero]; + Assert.That(tile.AdjacentBits, + Is.EqualTo(AtmosDirection.All), + "Expected tile to reflect non-airtight state after deletion after atmos tick."); + + for (var i = 0; i < Atmospherics.Directions; i++) + { + var direction = (AtmosDirection)(1 << i); + var curTile = tile.AdjacentTiles[i]; + Assert.That(curTile, Is.Not.Null, $"Center tile does not hold expected reference to adjacent tile in direction {direction}."); + } + } + } + + #endregion + + #region Rotation Assertion + + /// + /// Asserts that an airtight entity with a directional air blocked direction + /// properly reflects rotation on spawn. + /// + /// The degrees to rotate the entity on spawn. + /// The expected blocked direction after rotation. + /// Yeah, so here I learned that RT handles rotation directions + /// as positive == counterclockwise. + [Test] + [TestCase(0f, AtmosDirection.North)] + [TestCase(90f, AtmosDirection.West)] + [TestCase(180f, AtmosDirection.South)] + [TestCase(270f, AtmosDirection.East)] + [TestCase(-90f, AtmosDirection.East)] + [TestCase(-180f, AtmosDirection.South)] + [TestCase(-270f, AtmosDirection.West)] + public async Task Rotation_AirBlockedDirectionsOnSpawn(float degrees, AtmosDirection expected) + { + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + var rotation = Angle.FromDegrees(degrees); + + await Server.WaitPost(delegate + { + var coords = new EntityCoordinates(RelevantAtmos.Owner, Vector2.Zero); + _targetRotationEnt = SEntMan.SpawnAtPosition("AirtightDirectionalRotationTest", coords); + + Transform.SetLocalRotation(_targetRotationEnt, rotation); + }); + + SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate); + + await Server.WaitAssertion(delegate + { + using (Assert.EnterMultipleScope()) + { + SEntMan.TryGetComponent(_targetRotationEnt, out var airtight); + Assert.That(airtight, Is.Not.Null); + + var initial = (AtmosDirection)airtight.InitialAirBlockedDirection; + Assert.That(initial, + Is.EqualTo(AtmosDirection.North), + "Directional airtight entity should block North on spawn."); + + Assert.That(airtight.AirBlockedDirection, + Is.EqualTo(expected), + $"Expected AirBlockedDirection to be {expected} after rotating by {degrees} degrees on spawn."); + + // i dont trust you airtightsystem + if (degrees is 90f or 270f) + { + Assert.That(expected, + Is.Not.EqualTo(initial), + "Rotated directions should differ for 90/270 degrees."); + } + } + }); + } + + #endregion +} diff --git a/Content.Server/Atmos/Components/AirtightComponent.cs b/Content.Server/Atmos/Components/AirtightComponent.cs index 69488a7130..29c1f18af3 100644 --- a/Content.Server/Atmos/Components/AirtightComponent.cs +++ b/Content.Server/Atmos/Components/AirtightComponent.cs @@ -40,14 +40,23 @@ namespace Content.Server.Atmos.Components // depressurizing a room. However it can also effectively be used as a means of generating gasses for free // TODO ATMOS Mass conservation. Make it actually push/pull air from adjacent tiles instead of destroying & creating, - - // TODO ATMOS Do we need these two fields? + // TODO ATMOS slate for removal. Stuff doesn't use this. [DataField("rotateAirBlocked")] public bool RotateAirBlocked { get; set; } = true; - // TODO ATMOS remove this? What is this even for?? - [DataField("fixAirBlockedDirectionInitialize")] - public bool FixAirBlockedDirectionInitialize { get; set; } = true; + /// + /// Whether to fix the on initialization + /// to the entity's current rotation. + /// + /// This is an optimization routine for initializing airtight components. + /// If this entity doesn't have unique airtight directions + /// (ex. not all directions are blocked but some are), we can skip + /// a lot of event/transform business during initialization. + /// This field marks whether this is skipped or not. + /// If your entity only blocks air in one direction, + /// and that can depend on rotation, this needs to be set to true. + [DataField] + public bool FixAirBlockedDirectionInitialize = true; /// /// If true, then the tile that this entity is on will have no air at all if all directions are blocked. diff --git a/Content.Server/Atmos/EntitySystems/AirtightSystem.cs b/Content.Server/Atmos/EntitySystems/AirtightSystem.cs index 431707c835..78f61c80a4 100644 --- a/Content.Server/Atmos/EntitySystems/AirtightSystem.cs +++ b/Content.Server/Atmos/EntitySystems/AirtightSystem.cs @@ -25,7 +25,10 @@ namespace Content.Server.Atmos.EntitySystems private void OnAirtightInit(Entity airtight, ref ComponentInit args) { - // TODO AIRTIGHT what FixAirBlockedDirectionInitialize even for? + // If this entity has unique airtight directions that are affected by rotation, + // we need to fix up the current airtight directions based on its rotation. + // Otherwise, we can skip all of that logic (stuff adds up when you're initing + // a morbillion walls). if (!airtight.Comp.FixAirBlockedDirectionInitialize) { UpdatePosition(airtight); diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs index 5cce6075b7..e2e39abdda 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs @@ -300,6 +300,8 @@ public partial class AtmosphereSystem /// /// Checks if a tile on a grid is air-blocked in the specified directions. + /// This only checks for if the current tile, and only the current tile, is blocking + /// air. /// /// The grid to check. /// The tile on the grid to check. @@ -323,6 +325,8 @@ public partial class AtmosphereSystem /// /// Checks if a tile on a grid is air-blocked in the specified directions, using cached data. + /// This only checks for if the current tile, and only the current tile, is blocking + /// air. /// /// The grid to check. /// The tile on the grid to check.