From 101a5bbc9f664b6a24a17cfb8f8eaa53aa624811 Mon Sep 17 00:00:00 2001
From: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
Date: Sun, 2 Nov 2025 07:06:25 -0800
Subject: [PATCH] Cleanup and document AirtightData/MonstermosInfo (#41258)
cleanup and document airtightdata/monstermosinfo
---
.../EntitySystems/AtmosphereSystem.Utils.cs | 17 +-
Content.Server/Atmos/MonstermosInfo.cs | 186 ++++++++++++------
2 files changed, 143 insertions(+), 60 deletions(-)
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs
index 36355d7ba0..596368f000 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs
@@ -61,7 +61,22 @@ public partial class AtmosphereSystem
return Atmospherics.CellVolume * mapGrid.TileSize * tiles;
}
- public readonly record struct AirtightData(AtmosDirection BlockedDirections, bool NoAirWhenBlocked,
+ ///
+ /// Data on the airtightness of a .
+ /// Cached on the and updated during
+ /// if it was invalidated.
+ ///
+ /// The current directions blocked on this tile.
+ /// This is where air cannot flow to.
+ /// Whether the tile can have air when blocking directions.
+ /// Common for entities like thin windows which only block one face but can still have air in the residing tile.
+ /// If true, Atmospherics will generate air (yes, creating matter from nothing)
+ /// using the adjacent tiles as a seed if the airtightness is removed and the tile has no air.
+ /// This allows stuff like airlocks that void air when becoming airtight to keep opening/closing without
+ /// draining a room by continuously voiding air.
+ public readonly record struct AirtightData(
+ AtmosDirection BlockedDirections,
+ bool NoAirWhenBlocked,
bool FixVacuum);
private void UpdateAirtightData(EntityUid uid, GridAtmosphereComponent atmos, MapGridComponent grid, TileAtmosphere tile)
diff --git a/Content.Server/Atmos/MonstermosInfo.cs b/Content.Server/Atmos/MonstermosInfo.cs
index 810ce71d2c..67995b5fb5 100644
--- a/Content.Server/Atmos/MonstermosInfo.cs
+++ b/Content.Server/Atmos/MonstermosInfo.cs
@@ -1,80 +1,148 @@
using Content.Shared.Atmos;
-namespace Content.Server.Atmos
+namespace Content.Server.Atmos;
+
+///
+/// Atmospherics class that stores data on tiles for Monstermos calculations and operations.
+///
+public struct MonstermosInfo
{
- public struct MonstermosInfo
- {
- [ViewVariables]
- public int LastCycle;
+ ///
+ /// The last cycle this tile was processed for monstermos calculations.
+ /// Used to determine if Monstermos has already processed this tile in the
+ /// current tick's processing run.
+ ///
+ [ViewVariables]
+ public int LastCycle;
- [ViewVariables]
- public long LastQueueCycle;
+ ///
+ /// The last global cycle (on the GridAtmosphereComponent) this tile was processed for
+ /// monstermos calculations.
+ /// Monstermos can process multiple groups, and these groups may intersect with each other.
+ /// This allows Monstermos to check if a tile belongs to another group that has already been processed,
+ /// and skip processing it again.
+ ///
+ /// Used for exploring the current area for determining tiles that should be equalized
+ /// using a BFS fill (see https://en.wikipedia.org/wiki/Breadth-first_search)
+ ///
+ [ViewVariables]
+ public long LastQueueCycle;
- [ViewVariables]
- public long LastSlowQueueCycle;
+ ///
+ /// Similar to . Monstermos performs a second slow pass after the main
+ /// BFS fill in order to build a gradient map to determine transfer directions and amounts.
+ /// This field also tracks if we've already processed this tile in that slow pass so we don't re-queue it.
+ ///
+ [ViewVariables]
+ public long LastSlowQueueCycle;
- [ViewVariables]
- public float MoleDelta;
+ ///
+ /// Difference in the amount of moles in this tile compared to the tile's neighbors.
+ /// Used to determine "how strongly" air wants to flow in/out of this tile from/to its neighbors.
+ ///
+ [ViewVariables]
+ public float MoleDelta;
- [ViewVariables]
- public float TransferDirectionEast;
+ ///
+ /// Number of moles that are going to be transferred in this direction during final equalization.
+ ///
+ [ViewVariables]
+ public float TransferDirectionEast;
- [ViewVariables]
- public float TransferDirectionWest;
+ ///
+ /// Number of moles that are going to be transferred in this direction during final equalization.
+ ///
+ [ViewVariables]
+ public float TransferDirectionWest;
- [ViewVariables]
- public float TransferDirectionNorth;
+ ///
+ /// Number of moles that are going to be transferred in this direction during final equalization.
+ ///
+ [ViewVariables]
+ public float TransferDirectionNorth;
- [ViewVariables]
- public float TransferDirectionSouth;
+ ///
+ /// Number of moles that are going to be transferred in this direction during final equalization.
+ ///
+ [ViewVariables]
+ public float TransferDirectionSouth;
- [ViewVariables]
- public float CurrentTransferAmount;
+ ///
+ /// Number of moles that are going to be transferred to this tile during final equalization.
+ /// You can think of this as molar flow rate, or the amount of air currently flowing through this tile.
+ /// Used for space wind and airflow sounds during explosive decompression or big movements.
+ ///
+ /// During equalization calculations, Monstermos determines how much air is going to be transferred
+ /// between tiles, and sums that up into this field. It then either
+ ///
+ /// determines how many moles to transfer in the direction of , or
+ ///
+ /// determines how many moles to move in each direction using ,
+ /// setting the TransferDirection fields accordingly based on the ratio obtained
+ /// from .
+ ///
+ [ViewVariables]
+ public float CurrentTransferAmount;
- [ViewVariables]
- public AtmosDirection CurrentTransferDirection;
+ ///
+ /// A pointer from the current tile to the direction in which air is being transferred the most.
+ ///
+ [ViewVariables]
+ public AtmosDirection CurrentTransferDirection;
- [ViewVariables]
- public bool FastDone;
+ ///
+ /// Marks this tile as being equalized using the O(n log n) algorithm.
+ ///
+ [ViewVariables]
+ public bool FastDone;
- public float this[AtmosDirection direction]
- {
- get =>
- direction switch
- {
- AtmosDirection.East => TransferDirectionEast,
- AtmosDirection.West => TransferDirectionWest,
- AtmosDirection.North => TransferDirectionNorth,
- AtmosDirection.South => TransferDirectionSouth,
- _ => throw new ArgumentOutOfRangeException(nameof(direction))
- };
+ ///
+ /// Gets or sets the TransferDirection in the given direction.
+ ///
+ ///
+ /// Thrown when an invalid direction is given
+ /// (a non-cardinal direction)
+ public float this[AtmosDirection direction]
+ {
+ get =>
+ direction switch
+ {
+ AtmosDirection.East => TransferDirectionEast,
+ AtmosDirection.West => TransferDirectionWest,
+ AtmosDirection.North => TransferDirectionNorth,
+ AtmosDirection.South => TransferDirectionSouth,
+ _ => throw new ArgumentOutOfRangeException(nameof(direction))
+ };
- set
+ set
+ {
+ switch (direction)
{
- switch (direction)
- {
- case AtmosDirection.East:
- TransferDirectionEast = value;
- break;
- case AtmosDirection.West:
- TransferDirectionWest = value;
- break;
- case AtmosDirection.North:
- TransferDirectionNorth = value;
- break;
- case AtmosDirection.South:
- TransferDirectionSouth = value;
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(direction));
- }
+ case AtmosDirection.East:
+ TransferDirectionEast = value;
+ break;
+ case AtmosDirection.West:
+ TransferDirectionWest = value;
+ break;
+ case AtmosDirection.North:
+ TransferDirectionNorth = value;
+ break;
+ case AtmosDirection.South:
+ TransferDirectionSouth = value;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(direction));
}
}
+ }
- public float this[int index]
- {
- get => this[(AtmosDirection) (1 << index)];
- set => this[(AtmosDirection) (1 << index)] = value;
- }
+ ///
+ /// Gets or sets the TransferDirection by index.
+ ///
+ /// The index of the direction
+ public float this[int index]
+ {
+ get => this[(AtmosDirection) (1 << index)];
+ set => this[(AtmosDirection) (1 << index)] = value;
}
}
--
2.51.2