]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Add tile atmosphere tests (#41228)
authorpsykana <36602558+psykana@users.noreply.github.com>
Mon, 15 Dec 2025 23:18:10 +0000 (23:18 +0000)
committerGitHub <noreply@github.com>
Mon, 15 Dec 2025 23:18:10 +0000 (23:18 +0000)
* Tile atmosphere tests

* master markers

* TryLoadMap

* whoopsie

* Dirty

* Add new abstract class, room spacing tests

* review

Content.IntegrationTests/Tests/Atmos/AtmosTest.cs [new file with mode: 0644]
Content.IntegrationTests/Tests/Atmos/RoomSpacingTest.cs [new file with mode: 0644]
Content.IntegrationTests/Tests/Atmos/TileAtmosphereTest.cs [new file with mode: 0644]
Resources/Maps/Test/Atmospherics/tile_atmosphere_test_room.yml [new file with mode: 0644]
Resources/Maps/Test/Atmospherics/tile_atmosphere_test_snake.yml [new file with mode: 0644]
Resources/Maps/Test/Atmospherics/tile_atmosphere_test_x.yml [new file with mode: 0644]

diff --git a/Content.IntegrationTests/Tests/Atmos/AtmosTest.cs b/Content.IntegrationTests/Tests/Atmos/AtmosTest.cs
new file mode 100644 (file)
index 0000000..d50c4a2
--- /dev/null
@@ -0,0 +1,102 @@
+using Content.IntegrationTests.Tests.Interaction;
+using Content.Server.Atmos.Components;
+using Content.Server.Atmos.EntitySystems;
+using Content.Shared.Atmos;
+using Content.Shared.Atmos.Components;
+using Content.Shared.Tests;
+using Robust.Shared.GameObjects;
+using Robust.Shared.Map.Components;
+using Robust.Shared.Maths;
+
+namespace Content.IntegrationTests.Tests.Atmos;
+
+/// <summary>
+/// Helper class for atmospherics tests.
+/// See <see cref="TileAtmosphereTest"/> on how to add new tests with custom maps.
+/// </summary>
+[TestFixture]
+public abstract class AtmosTest : InteractionTest
+{
+    protected AtmosphereSystem SAtmos = default!;
+    protected EntityLookupSystem LookupSystem = default!;
+
+    protected Entity<GridAtmosphereComponent> RelevantAtmos = default!;
+
+    /// <summary>
+    /// Used in <see cref="AtmosphereSystem.RunProcessingFull"/>. Resolved during test setup.
+    /// </summary>
+    protected Entity<GridAtmosphereComponent, GasTileOverlayComponent, MapGridComponent, TransformComponent> ProcessEnt = default;
+
+    protected virtual float Moles => 1000.0f;
+
+    // 5% is a lot, but it can get this bad ATM...
+    protected virtual float Tolerance => 0.05f;
+
+    [SetUp]
+    public override async Task Setup()
+    {
+        await base.Setup();
+
+        SAtmos = SEntMan.System<AtmosphereSystem>();
+        LookupSystem = SEntMan.System<EntityLookupSystem>();
+
+        RelevantAtmos = (MapData.Grid, SEntMan.GetComponent<GridAtmosphereComponent>(MapData.Grid));
+
+        ProcessEnt = new Entity<GridAtmosphereComponent, GasTileOverlayComponent, MapGridComponent, TransformComponent>(
+            MapData.Grid.Owner,
+            SEntMan.GetComponent<GridAtmosphereComponent>(MapData.Grid.Owner),
+            SEntMan.GetComponent<GasTileOverlayComponent>(MapData.Grid.Owner),
+            SEntMan.GetComponent<MapGridComponent>(MapData.Grid.Owner),
+            SEntMan.GetComponent<TransformComponent>(MapData.Grid.Owner));
+    }
+
+    /// <summary>
+    /// Tries to get a mapped <see cref="TestMarkerComponent"/> marker with a given name.
+    /// </summary>
+    /// <param name="markers">Marker entities to look through</param>
+    /// <param name="id">Marker name to look up (set during mapping)</param>
+    /// <param name="marker">Found marker EntityUid or Invalid</param>
+    /// <returns>True if found</returns>
+    protected static bool GetMarker(Entity<TestMarkerComponent>[] markers, string id, out EntityUid marker)
+    {
+        foreach (var ent in markers)
+        {
+            if (ent.Comp.Id == id)
+            {
+                marker = ent;
+                return true;
+            }
+        }
+        marker = EntityUid.Invalid;
+        return false;
+    }
+
+    protected static float GetGridMoles(Entity<GridAtmosphereComponent> grid)
+    {
+        var moles = 0.0f;
+        foreach (var tile in grid.Comp.Tiles.Values)
+        {
+            moles += tile.Air?.TotalMoles ?? 0.0f;
+        }
+
+        return moles;
+    }
+
+    /// <summary>
+    /// Asserts that test grid has this many moles, within tolerance percentage.
+    /// </summary>
+    protected void AssertGridMoles(float moles, float tolerance)
+    {
+        var gridMoles = GetGridMoles(RelevantAtmos);
+        Assert.That(MathHelper.CloseToPercent(moles, gridMoles, tolerance), $"Grid has {gridMoles} moles, but {moles} was expected");
+    }
+
+    /// <summary>
+    /// Asserts that provided GasMixtures have same total moles, within tolerance percentage.
+    /// </summary>
+    protected void AssertMixMoles(GasMixture mix1, GasMixture mix2, float tolerance)
+    {
+        Assert.That(MathHelper.CloseToPercent(mix1.TotalMoles, mix2.TotalMoles, tolerance),
+            $"GasMixtures do not match. Got {mix1.TotalMoles} and {mix2.TotalMoles} moles");
+    }
+}
diff --git a/Content.IntegrationTests/Tests/Atmos/RoomSpacingTest.cs b/Content.IntegrationTests/Tests/Atmos/RoomSpacingTest.cs
new file mode 100644 (file)
index 0000000..4cdc089
--- /dev/null
@@ -0,0 +1,127 @@
+using Content.Shared.Atmos;
+using Content.Shared.Coordinates;
+using Content.Shared.Tests;
+using Robust.Shared.GameObjects;
+using Robust.Shared.Utility;
+
+namespace Content.IntegrationTests.Tests.Atmos;
+
+public sealed class RoomSpacingTest : AtmosTest
+{
+    protected override ResPath? TestMapPath => new("Maps/Test/Atmospherics/tile_atmosphere_test_room.yml");
+
+    /// <summary>
+    /// Checks that deleting an outer wall spaces the room.
+    /// </summary>
+    [Test]
+    public async Task DeleteWall()
+    {
+        var markers = SEntMan.AllEntities<TestMarkerComponent>();
+
+        EntityUid source, floor, wallPos;
+        source = floor = wallPos = EntityUid.Invalid;
+
+        Assert.Multiple(() =>
+        {
+            Assert.That(GetMarker(markers, "source", out source));
+            Assert.That(GetMarker(markers, "floor", out floor));
+            Assert.That(GetMarker(markers, "wall", out wallPos));
+        });
+
+        var lookup = LookupSystem.GetEntitiesIntersecting(wallPos);
+        var wall = lookup.FirstOrNull();
+        Assert.That(wall, Is.Not.Null);
+
+        Assert.That(GetGridMoles(RelevantAtmos), Is.EqualTo(0));
+
+        var sourceMix = SAtmos.GetTileMixture(source, true);
+        Assert.That(sourceMix, Is.Not.EqualTo(null));
+        sourceMix.AdjustMoles(Gas.Frezon, Moles);
+
+        await Server.WaitRunTicks(500);
+
+        var mix1 = SAtmos.GetTileMixture(floor);
+        Assert.That(mix1, Is.Not.EqualTo(null));
+
+        AssertMixMoles(sourceMix, mix1, Tolerance);
+        AssertGridMoles(Moles, Tolerance);
+
+        // Space the room
+        await Server.WaitAssertion(() =>
+        {
+            SEntMan.DeleteEntity(wall);
+        });
+
+        await Server.WaitRunTicks(10);
+
+        await Server.WaitPost(() =>
+        {
+            for (var i = 0; i < 50; i++)
+            {
+                SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate);
+            }
+        });
+
+        AssertMixMoles(sourceMix, mix1, Tolerance);
+        AssertGridMoles(0, Tolerance);
+    }
+
+    /// <summary>
+    /// Checks that exposing tile lattice spaces the room.
+    /// </summary>
+    [Test]
+    public async Task PryLattice()
+    {
+        var markers = SEntMan.AllEntities<TestMarkerComponent>();
+
+        EntityUid source, floor, wallPos;
+        source = floor = wallPos = EntityUid.Invalid;
+
+        Assert.Multiple(() =>
+        {
+            Assert.That(GetMarker(markers, "source", out source));
+            Assert.That(GetMarker(markers, "floor", out floor));
+            Assert.That(GetMarker(markers, "wall", out wallPos));
+        });
+
+        var lookup = LookupSystem.GetEntitiesIntersecting(wallPos);
+        var wall = lookup.FirstOrNull();
+        Assert.That(wall, Is.Not.Null);
+
+        Assert.That(GetGridMoles(RelevantAtmos), Is.EqualTo(0));
+
+        var sourceMix = SAtmos.GetTileMixture(source, true);
+        Assert.That(sourceMix, Is.Not.EqualTo(null));
+        sourceMix.AdjustMoles(Gas.Frezon, Moles);
+
+        await Server.WaitPost(() =>
+        {
+            SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate);
+        });
+
+        var mix1 = SAtmos.GetTileMixture(floor);
+        Assert.That(mix1, Is.Not.EqualTo(null));
+
+        AssertMixMoles(sourceMix, mix1, Tolerance);
+        AssertGridMoles(Moles, Tolerance);
+
+        // Space the room
+        await SetTile(Lattice, SEntMan.GetNetCoordinates(floor.ToCoordinates()), MapData.Grid);
+
+        await Server.WaitRunTicks(10);
+
+        await Server.WaitPost(() =>
+        {
+            for (var i = 0; i < 50; i++)
+            {
+                SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate);
+            }
+        });
+
+        mix1 = SAtmos.GetTileMixture(floor);
+        Assert.That(mix1, Is.Not.EqualTo(null));
+
+        AssertMixMoles(sourceMix, mix1, Tolerance);
+        AssertGridMoles(0, Tolerance);
+    }
+}
diff --git a/Content.IntegrationTests/Tests/Atmos/TileAtmosphereTest.cs b/Content.IntegrationTests/Tests/Atmos/TileAtmosphereTest.cs
new file mode 100644 (file)
index 0000000..368bb63
--- /dev/null
@@ -0,0 +1,159 @@
+using Content.Shared.Atmos;
+using Content.Shared.CCVar;
+using Content.Shared.Coordinates;
+using Content.Shared.Tests;
+using Robust.Shared.GameObjects;
+using Robust.Shared.Maths;
+using Robust.Shared.Utility;
+
+namespace Content.IntegrationTests.Tests.Atmos;
+
+[TestOf(typeof(Atmospherics))]
+public abstract class TileAtmosphereTest : AtmosTest
+{
+    /// <summary>
+    /// Spawns gas in an enclosed space and checks that pressure equalizes within reasonable time.
+    /// Checks that mole count stays the same.
+    /// </summary>
+    [Test]
+    public async Task GasSpreading()
+    {
+        var markers = SEntMan.AllEntities<TestMarkerComponent>();
+
+        EntityUid source, point1, point2;
+        source = point1 = point2 = EntityUid.Invalid;
+
+        Assert.Multiple(() =>
+        {
+            Assert.That(GetMarker(markers, "source", out source));
+            Assert.That(GetMarker(markers, "point1", out point1));
+            Assert.That(GetMarker(markers, "point2", out point2));
+        });
+
+        Assert.That(GetGridMoles(RelevantAtmos), Is.EqualTo(0.0f));
+
+        var sourceMix = SAtmos.GetTileMixture(source, true);
+        Assert.That(sourceMix, Is.Not.EqualTo(null));
+        sourceMix.AdjustMoles(Gas.Frezon, Moles);
+
+        await Pair.Server.WaitPost(() =>
+        {
+            SAtmos.RunProcessingFull(ProcessEnt, MapData.Grid.Owner, SAtmos.AtmosTickRate);
+        });
+
+        var mix1 = SAtmos.GetTileMixture(point1);
+        var mix2 = SAtmos.GetTileMixture(point2);
+
+        Assert.Multiple(() =>
+        {
+            Assert.That(mix1, Is.Not.EqualTo(null));
+            Assert.That(mix2, Is.Not.EqualTo(null));
+        });
+
+        AssertMixMoles(mix1, mix2, Tolerance);
+        AssertGridMoles(Moles, Tolerance);
+    }
+
+    /// <summary>
+    /// Spawns a combustible mixture and sets it ablaze.
+    /// Checks that fire propages through the entire grid.
+    /// </summary>
+    [Test]
+    public async Task FireSpreading()
+    {
+        var markers = SEntMan.AllEntities<TestMarkerComponent>();
+
+        EntityUid source, point1, point2;
+        source = point1 = point2 = EntityUid.Invalid;
+
+        Vector2i sourceXY, point1XY, point2XY;
+        sourceXY = point1XY = point2XY = Vector2i.Zero;
+
+        Assert.Multiple(() =>
+        {
+            Assert.That(GetMarker(markers, "source", out source));
+            Assert.That(GetMarker(markers, "point1", out point1));
+            Assert.That(GetMarker(markers, "point2", out point2));
+
+            Assert.That(Transform.TryGetGridTilePosition(source, out sourceXY, MapData.Grid));
+            Assert.That(Transform.TryGetGridTilePosition(source, out point1XY, MapData.Grid));
+            Assert.That(Transform.TryGetGridTilePosition(source, out point2XY, MapData.Grid));
+        });
+
+        Assert.That(GetGridMoles(RelevantAtmos), Is.EqualTo(0));
+
+        var sourceMix = SAtmos.GetTileMixture(source, true);
+        Assert.That(sourceMix, Is.Not.EqualTo(null));
+
+        sourceMix.AdjustMoles(Gas.Plasma, Moles / 10);
+        sourceMix.AdjustMoles(Gas.Oxygen, Moles - Moles / 10);
+        sourceMix.Temperature = Atmospherics.FireMinimumTemperatureToExist - 10;
+
+        Assert.Multiple(() =>
+        {
+            Assert.That(SAtmos.IsHotspotActive(MapData.Grid, sourceXY), Is.False);
+            Assert.That(SAtmos.IsHotspotActive(MapData.Grid, point1XY), Is.False);
+            Assert.That(SAtmos.IsHotspotActive(MapData.Grid, point2XY), Is.False);
+        });
+
+        await Server.WaitAssertion(() =>
+        {
+            var welder = SEntMan.SpawnEntity("Welder", source.ToCoordinates());
+            Assert.That(ItemToggleSys.TryActivate(welder));
+        });
+
+        await Server.WaitRunTicks(500);
+
+        Assert.Multiple(() =>
+        {
+            Assert.That(SAtmos.IsHotspotActive(MapData.Grid, sourceXY), Is.True);
+            Assert.That(SAtmos.IsHotspotActive(MapData.Grid, point1XY), Is.True);
+            Assert.That(SAtmos.IsHotspotActive(MapData.Grid, point2XY), Is.True);
+        });
+
+        var mix1 = SAtmos.GetTileMixture(point1);
+        var mix2 = SAtmos.GetTileMixture(point2);
+
+        Assert.Multiple(() =>
+        {
+            Assert.That(mix1, Is.Not.EqualTo(null));
+            Assert.That(mix2, Is.Not.EqualTo(null));
+        });
+
+        AssertMixMoles(mix1, mix2, Tolerance);
+        AssertGridMoles(Moles, Tolerance);
+    }
+}
+
+// Declare separate fixtures to override the TestMap and configure CVars
+public sealed class TileAtmosphereTest_X : TileAtmosphereTest
+{
+    protected override ResPath? TestMapPath => new("Maps/Test/Atmospherics/tile_atmosphere_test_x.yml");
+}
+
+public sealed class TileAtmosphereTest_Snake : TileAtmosphereTest
+{
+    protected override ResPath? TestMapPath => new("Maps/Test/Atmospherics/tile_atmosphere_test_snake.yml");
+}
+
+public sealed class TileAtmosphereTest_LINDA_X : TileAtmosphereTest
+{
+    protected override ResPath? TestMapPath => new("Maps/Test/Atmospherics/tile_atmosphere_test_x.yml");
+    public override async Task Setup()
+    {
+        await base.Setup();
+        Assert.That(Server.CfgMan.GetCVar(CCVars.MonstermosEqualization));
+        Server.CfgMan.SetCVar(CCVars.MonstermosEqualization, false);
+    }
+}
+
+public sealed class TileAtmosphereTest_LINDA_Snake : TileAtmosphereTest
+{
+    protected override ResPath? TestMapPath => new("Maps/Test/Atmospherics/tile_atmosphere_test_snake.yml");
+    public override async Task Setup()
+    {
+        await base.Setup();
+        Assert.That(Server.CfgMan.GetCVar(CCVars.MonstermosEqualization));
+        Server.CfgMan.SetCVar(CCVars.MonstermosEqualization, false);
+    }
+}
diff --git a/Resources/Maps/Test/Atmospherics/tile_atmosphere_test_room.yml b/Resources/Maps/Test/Atmospherics/tile_atmosphere_test_room.yml
new file mode 100644 (file)
index 0000000..63033a1
--- /dev/null
@@ -0,0 +1,231 @@
+meta:
+  format: 7
+  category: Map
+  engineVersion: 267.3.0
+  forkId: ""
+  forkVersion: ""
+  time: 11/02/2025 16:46:21
+  entityCount: 31
+maps:
+- 1
+grids:
+- 2
+orphans: []
+nullspace: []
+tilemap:
+  1: Space
+  0: Plating
+entities:
+- proto: ""
+  entities:
+  - uid: 1
+    components:
+    - type: MetaData
+      name: Map Entity
+    - type: Transform
+    - type: Map
+      mapPaused: True
+    - type: GridTree
+    - type: Broadphase
+    - type: OccluderTree
+  - uid: 2
+    components:
+    - type: MetaData
+      name: grid
+    - type: Transform
+      pos: -0.47916666,-0.49478912
+      parent: 1
+    - type: MapGrid
+      chunks:
+        0,0:
+          ind: 0,0
+          tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAA==
+          version: 7
+        0,-1:
+          ind: 0,-1
+          tiles: AQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAA==
+          version: 7
+    - type: Broadphase
+    - type: Physics
+      bodyStatus: InAir
+      fixedRotation: False
+      bodyType: Dynamic
+    - type: Fixtures
+      fixtures: {}
+    - type: OccluderTree
+    - type: SpreaderGrid
+    - type: Shuttle
+      dampingModifier: 0.25
+    - type: ImplicitRoof
+    - type: GridPathfinding
+    - type: Gravity
+      gravityShakeSound: !type:SoundPathSpecifier
+        path: /Audio/Effects/alert.ogg
+    - type: DecalGrid
+      chunkCollection:
+        version: 2
+        nodes: []
+    - type: GridAtmosphere
+      version: 2
+      data:
+        chunkSize: 4
+    - type: GasTileOverlay
+    - type: RadiationGridResistance
+- proto: IntegrationTestMarker
+  entities:
+  - uid: 29
+    components:
+    - type: Transform
+      pos: 0.5,-1.5
+      parent: 2
+    - type: TestMarker
+      id: wall
+  - uid: 30
+    components:
+    - type: Transform
+      pos: 5.5,-1.5
+      parent: 2
+    - type: TestMarker
+      id: source
+  - uid: 31
+    components:
+    - type: Transform
+      pos: 2.5,-0.5
+      parent: 2
+    - type: TestMarker
+      id: floor
+- proto: WallClown
+  entities:
+  - uid: 28
+    components:
+    - type: Transform
+      pos: 0.5,-1.5
+      parent: 2
+- proto: WallSolid
+  entities:
+  - uid: 3
+    components:
+    - type: Transform
+      pos: 4.5,0.5
+      parent: 2
+  - uid: 4
+    components:
+    - type: Transform
+      pos: 0.5,0.5
+      parent: 2
+  - uid: 5
+    components:
+    - type: Transform
+      pos: 1.5,0.5
+      parent: 2
+  - uid: 6
+    components:
+    - type: Transform
+      pos: 1.5,-0.5
+      parent: 2
+  - uid: 7
+    components:
+    - type: Transform
+      pos: 0.5,-0.5
+      parent: 2
+  - uid: 8
+    components:
+    - type: Transform
+      pos: 0.5,-2.5
+      parent: 2
+  - uid: 9
+    components:
+    - type: Transform
+      pos: 1.5,-2.5
+      parent: 2
+  - uid: 10
+    components:
+    - type: Transform
+      pos: 1.5,-3.5
+      parent: 2
+  - uid: 11
+    components:
+    - type: Transform
+      pos: 0.5,-3.5
+      parent: 2
+  - uid: 12
+    components:
+    - type: Transform
+      pos: 2.5,-3.5
+      parent: 2
+  - uid: 13
+    components:
+    - type: Transform
+      pos: 3.5,-3.5
+      parent: 2
+  - uid: 14
+    components:
+    - type: Transform
+      pos: 3.5,-2.5
+      parent: 2
+  - uid: 15
+    components:
+    - type: Transform
+      pos: 2.5,0.5
+      parent: 2
+  - uid: 16
+    components:
+    - type: Transform
+      pos: 3.5,0.5
+      parent: 2
+  - uid: 17
+    components:
+    - type: Transform
+      pos: 3.5,-0.5
+      parent: 2
+  - uid: 18
+    components:
+    - type: Transform
+      pos: 5.5,0.5
+      parent: 2
+  - uid: 19
+    components:
+    - type: Transform
+      pos: 4.5,-3.5
+      parent: 2
+  - uid: 20
+    components:
+    - type: Transform
+      pos: 5.5,-3.5
+      parent: 2
+  - uid: 21
+    components:
+    - type: Transform
+      pos: 6.5,0.5
+      parent: 2
+  - uid: 22
+    components:
+    - type: Transform
+      pos: 7.5,0.5
+      parent: 2
+  - uid: 23
+    components:
+    - type: Transform
+      pos: 7.5,-0.5
+      parent: 2
+  - uid: 24
+    components:
+    - type: Transform
+      pos: 7.5,-1.5
+      parent: 2
+  - uid: 25
+    components:
+    - type: Transform
+      pos: 7.5,-2.5
+      parent: 2
+  - uid: 26
+    components:
+    - type: Transform
+      pos: 7.5,-3.5
+      parent: 2
+  - uid: 27
+    components:
+    - type: Transform
+      pos: 6.5,-3.5
+      parent: 2
+...
diff --git a/Resources/Maps/Test/Atmospherics/tile_atmosphere_test_snake.yml b/Resources/Maps/Test/Atmospherics/tile_atmosphere_test_snake.yml
new file mode 100644 (file)
index 0000000..c55426d
--- /dev/null
@@ -0,0 +1,299 @@
+meta:
+  format: 7
+  category: Map
+  engineVersion: 267.3.0
+  forkId: ""
+  forkVersion: ""
+  time: 11/01/2025 12:21:19
+  entityCount: 45
+maps:
+- 1
+grids:
+- 2
+orphans: []
+nullspace: []
+tilemap:
+  1: Space
+  0: Plating
+entities:
+- proto: ""
+  entities:
+  - uid: 1
+    components:
+    - type: MetaData
+      name: Map Entity
+    - type: Transform
+    - type: Map
+      mapPaused: True
+    - type: GridTree
+    - type: Broadphase
+    - type: OccluderTree
+  - uid: 2
+    components:
+    - type: MetaData
+      name: grid
+    - type: Transform
+      pos: -0.48958334,-0.51563644
+      parent: 1
+    - type: MapGrid
+      chunks:
+        0,0:
+          ind: 0,0
+          tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAA==
+          version: 7
+        0,-1:
+          ind: 0,-1
+          tiles: AQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAA==
+          version: 7
+    - type: Broadphase
+    - type: Physics
+      bodyStatus: InAir
+      fixedRotation: False
+      bodyType: Dynamic
+    - type: Fixtures
+      fixtures: {}
+    - type: OccluderTree
+    - type: SpreaderGrid
+    - type: Shuttle
+      dampingModifier: 0.25
+    - type: ImplicitRoof
+    - type: GridPathfinding
+    - type: Gravity
+      gravityShakeSound: !type:SoundPathSpecifier
+        path: /Audio/Effects/alert.ogg
+    - type: DecalGrid
+      chunkCollection:
+        version: 2
+        nodes: []
+    - type: GridAtmosphere
+      version: 2
+      data:
+        chunkSize: 4
+    - type: GasTileOverlay
+    - type: RadiationGridResistance
+- proto: IntegrationTestMarker
+  entities:
+  - uid: 29
+    components:
+    - type: Transform
+      pos: 1.5,-0.5
+      parent: 2
+    - type: TestMarker
+      id: point1
+  - uid: 44
+    components:
+    - type: Transform
+      pos: 4.5,-0.5
+      parent: 2
+    - type: TestMarker
+      id: source
+  - uid: 45
+    components:
+    - type: Transform
+      pos: 7.5,-0.5
+      parent: 2
+    - type: TestMarker
+      id: point2
+- proto: WallSolid
+  entities:
+  - uid: 3
+    components:
+    - type: Transform
+      pos: 1.5,-5.5
+      parent: 2
+  - uid: 4
+    components:
+    - type: Transform
+      pos: 0.5,-5.5
+      parent: 2
+  - uid: 5
+    components:
+    - type: Transform
+      pos: 0.5,-4.5
+      parent: 2
+  - uid: 6
+    components:
+    - type: Transform
+      pos: 0.5,-3.5
+      parent: 2
+  - uid: 7
+    components:
+    - type: Transform
+      pos: 0.5,-2.5
+      parent: 2
+  - uid: 8
+    components:
+    - type: Transform
+      pos: 0.5,-1.5
+      parent: 2
+  - uid: 9
+    components:
+    - type: Transform
+      pos: 0.5,-0.5
+      parent: 2
+  - uid: 10
+    components:
+    - type: Transform
+      pos: 0.5,0.5
+      parent: 2
+  - uid: 11
+    components:
+    - type: Transform
+      pos: 1.5,0.5
+      parent: 2
+  - uid: 12
+    components:
+    - type: Transform
+      pos: 2.5,0.5
+      parent: 2
+  - uid: 13
+    components:
+    - type: Transform
+      pos: 2.5,-0.5
+      parent: 2
+  - uid: 14
+    components:
+    - type: Transform
+      pos: 2.5,-1.5
+      parent: 2
+  - uid: 15
+    components:
+    - type: Transform
+      pos: 2.5,-2.5
+      parent: 2
+  - uid: 16
+    components:
+    - type: Transform
+      pos: 2.5,-3.5
+      parent: 2
+  - uid: 17
+    components:
+    - type: Transform
+      pos: 2.5,-5.5
+      parent: 2
+  - uid: 18
+    components:
+    - type: Transform
+      pos: 3.5,-5.5
+      parent: 2
+  - uid: 19
+    components:
+    - type: Transform
+      pos: 4.5,-5.5
+      parent: 2
+  - uid: 20
+    components:
+    - type: Transform
+      pos: 4.5,-4.5
+      parent: 2
+  - uid: 21
+    components:
+    - type: Transform
+      pos: 4.5,-3.5
+      parent: 2
+  - uid: 22
+    components:
+    - type: Transform
+      pos: 4.5,-2.5
+      parent: 2
+  - uid: 23
+    components:
+    - type: Transform
+      pos: 4.5,-1.5
+      parent: 2
+  - uid: 24
+    components:
+    - type: Transform
+      pos: 3.5,0.5
+      parent: 2
+  - uid: 25
+    components:
+    - type: Transform
+      pos: 4.5,0.5
+      parent: 2
+  - uid: 26
+    components:
+    - type: Transform
+      pos: 5.5,0.5
+      parent: 2
+  - uid: 27
+    components:
+    - type: Transform
+      pos: 6.5,0.5
+      parent: 2
+  - uid: 28
+    components:
+    - type: Transform
+      pos: 6.5,-0.5
+      parent: 2
+  - uid: 30
+    components:
+    - type: Transform
+      pos: 7.5,0.5
+      parent: 2
+  - uid: 31
+    components:
+    - type: Transform
+      pos: 8.5,-5.5
+      parent: 2
+  - uid: 32
+    components:
+    - type: Transform
+      pos: 7.5,-5.5
+      parent: 2
+  - uid: 33
+    components:
+    - type: Transform
+      pos: 5.5,-5.5
+      parent: 2
+  - uid: 34
+    components:
+    - type: Transform
+      pos: 6.5,-5.5
+      parent: 2
+  - uid: 35
+    components:
+    - type: Transform
+      pos: 6.5,-1.5
+      parent: 2
+  - uid: 36
+    components:
+    - type: Transform
+      pos: 6.5,-2.5
+      parent: 2
+  - uid: 37
+    components:
+    - type: Transform
+      pos: 6.5,-3.5
+      parent: 2
+  - uid: 38
+    components:
+    - type: Transform
+      pos: 8.5,-3.5
+      parent: 2
+  - uid: 39
+    components:
+    - type: Transform
+      pos: 8.5,-2.5
+      parent: 2
+  - uid: 40
+    components:
+    - type: Transform
+      pos: 8.5,-1.5
+      parent: 2
+  - uid: 41
+    components:
+    - type: Transform
+      pos: 8.5,-0.5
+      parent: 2
+  - uid: 42
+    components:
+    - type: Transform
+      pos: 8.5,0.5
+      parent: 2
+  - uid: 43
+    components:
+    - type: Transform
+      pos: 8.5,-4.5
+      parent: 2
+...
diff --git a/Resources/Maps/Test/Atmospherics/tile_atmosphere_test_x.yml b/Resources/Maps/Test/Atmospherics/tile_atmosphere_test_x.yml
new file mode 100644 (file)
index 0000000..9e48c9e
--- /dev/null
@@ -0,0 +1,219 @@
+meta:
+  format: 7
+  category: Map
+  engineVersion: 267.3.0
+  forkId: ""
+  forkVersion: ""
+  time: 11/01/2025 12:20:35
+  entityCount: 29
+maps:
+- 1
+grids:
+- 2
+orphans: []
+nullspace: []
+tilemap:
+  1: Space
+  0: Plating
+entities:
+- proto: ""
+  entities:
+  - uid: 1
+    components:
+    - type: MetaData
+      name: Map Entity
+    - type: Transform
+    - type: Map
+      mapPaused: True
+    - type: GridTree
+    - type: Broadphase
+    - type: OccluderTree
+  - uid: 2
+    components:
+    - type: MetaData
+      name: grid
+    - type: Transform
+      pos: -0.5520833,-0.44266954
+      parent: 1
+    - type: MapGrid
+      chunks:
+        0,0:
+          ind: 0,0
+          tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAA==
+          version: 7
+        0,-1:
+          ind: 0,-1
+          tiles: AQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAAEAAAAAAAABAAAAAAAAAQAAAAAAAA==
+          version: 7
+    - type: Broadphase
+    - type: Physics
+      bodyStatus: InAir
+      fixedRotation: False
+      bodyType: Dynamic
+    - type: Fixtures
+      fixtures: {}
+    - type: OccluderTree
+    - type: SpreaderGrid
+    - type: Shuttle
+      dampingModifier: 0.25
+    - type: ImplicitRoof
+    - type: GridPathfinding
+    - type: Gravity
+      gravityShakeSound: !type:SoundPathSpecifier
+        path: /Audio/Effects/alert.ogg
+    - type: DecalGrid
+      chunkCollection:
+        version: 2
+        nodes: []
+    - type: GridAtmosphere
+      version: 2
+      data:
+        chunkSize: 4
+    - type: GasTileOverlay
+    - type: RadiationGridResistance
+- proto: IntegrationTestMarker
+  entities:
+  - uid: 36
+    components:
+    - type: Transform
+      pos: 3.5,-2.5
+      parent: 2
+    - type: TestMarker
+      id: source
+  - uid: 37
+    components:
+    - type: Transform
+      pos: 1.5,-2.5
+      parent: 2
+    - type: TestMarker
+      id: point1
+  - uid: 38
+    components:
+    - type: Transform
+      pos: 3.5,-0.5
+      parent: 2
+    - type: TestMarker
+      id: point2
+- proto: WallSolid
+  entities:
+  - uid: 3
+    components:
+    - type: Transform
+      pos: 0.5,-1.5
+      parent: 2
+  - uid: 4
+    components:
+    - type: Transform
+      pos: 1.5,-1.5
+      parent: 2
+  - uid: 5
+    components:
+    - type: Transform
+      pos: 2.5,-1.5
+      parent: 2
+  - uid: 6
+    components:
+    - type: Transform
+      pos: 2.5,-0.5
+      parent: 2
+  - uid: 7
+    components:
+    - type: Transform
+      pos: 2.5,0.5
+      parent: 2
+  - uid: 8
+    components:
+    - type: Transform
+      pos: 3.5,0.5
+      parent: 2
+  - uid: 9
+    components:
+    - type: Transform
+      pos: 4.5,0.5
+      parent: 2
+  - uid: 10
+    components:
+    - type: Transform
+      pos: 4.5,-0.5
+      parent: 2
+  - uid: 11
+    components:
+    - type: Transform
+      pos: 4.5,-1.5
+      parent: 2
+  - uid: 12
+    components:
+    - type: Transform
+      pos: 5.5,-1.5
+      parent: 2
+  - uid: 13
+    components:
+    - type: Transform
+      pos: 6.5,-1.5
+      parent: 2
+  - uid: 14
+    components:
+    - type: Transform
+      pos: 4.5,-3.5
+      parent: 2
+  - uid: 15
+    components:
+    - type: Transform
+      pos: 5.5,-3.5
+      parent: 2
+  - uid: 16
+    components:
+    - type: Transform
+      pos: 6.5,-3.5
+      parent: 2
+  - uid: 17
+    components:
+    - type: Transform
+      pos: 6.5,-2.5
+      parent: 2
+  - uid: 18
+    components:
+    - type: Transform
+      pos: 0.5,-2.5
+      parent: 2
+  - uid: 19
+    components:
+    - type: Transform
+      pos: 0.5,-3.5
+      parent: 2
+  - uid: 20
+    components:
+    - type: Transform
+      pos: 1.5,-3.5
+      parent: 2
+  - uid: 21
+    components:
+    - type: Transform
+      pos: 2.5,-3.5
+      parent: 2
+  - uid: 22
+    components:
+    - type: Transform
+      pos: 2.5,-4.5
+      parent: 2
+  - uid: 23
+    components:
+    - type: Transform
+      pos: 2.5,-5.5
+      parent: 2
+  - uid: 27
+    components:
+    - type: Transform
+      pos: 4.5,-5.5
+      parent: 2
+  - uid: 28
+    components:
+    - type: Transform
+      pos: 4.5,-4.5
+      parent: 2
+  - uid: 29
+    components:
+    - type: Transform
+      pos: 3.5,-5.5
+      parent: 2
+...