From: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
Date: Mon, 10 Nov 2025 18:42:13 +0000 (-0800)
Subject: Document Atmospherics API (#41382)
X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=26d95b7944b63aa03001c52c432b9419347229ef;p=space-station-14.git
Document Atmospherics API (#41382)
* api docs
* rem using dir. linq in atmospherics not allowed.
* address review
---
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs
index 29f091f340..96a5c69457 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs
@@ -1,5 +1,4 @@
using System.Diagnostics;
-using System.Linq;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.Piping.Components;
using Content.Server.NodeContainer.NodeGroups;
@@ -14,6 +13,22 @@ namespace Content.Server.Atmos.EntitySystems;
public partial class AtmosphereSystem
{
+ /*
+ General API for interacting with AtmosphereSystem.
+
+ If you feel like you're stepping on eggshells because you can't access things in AtmosphereSystem,
+ consider adding a method here instead of making your own way to work around it.
+ */
+
+ ///
+ /// Gets the that an entity is contained within.
+ ///
+ /// The entity to get the mixture for.
+ /// If true, will ignore mixtures that the entity is contained in
+ /// (ex. lockers and cryopods) and just get the tile mixture.
+ /// If true, will mark the tile as active for atmosphere processing.
+ /// A if one could be found, null otherwise.
+ [PublicAPI]
public GasMixture? GetContainingMixture(Entity ent, bool ignoreExposed = false, bool excite = false)
{
if (!Resolve(ent, ref ent.Comp))
@@ -22,6 +37,17 @@ public partial class AtmosphereSystem
return GetContainingMixture(ent, ent.Comp.GridUid, ent.Comp.MapUid, ignoreExposed, excite);
}
+ ///
+ /// Gets the that an entity is contained within.
+ ///
+ /// The entity to get the mixture for.
+ /// The grid that the entity may be on.
+ /// The map that the entity may be on.
+ /// If true, will ignore mixtures that the entity is contained in
+ /// (ex. lockers and cryopods) and just get the tile mixture.
+ /// If true, will mark the tile as active for atmosphere processing.
+ /// A if one could be found, null otherwise.
+ [PublicAPI]
public GasMixture? GetContainingMixture(
Entity ent,
Entity? grid,
@@ -49,16 +75,38 @@ public partial class AtmosphereSystem
return GetTileMixture(grid, map, position, excite);
}
- public bool HasAtmosphere(EntityUid gridUid) => _atmosQuery.HasComponent(gridUid);
+ ///
+ /// Checks if a grid has an atmosphere.
+ ///
+ /// The grid to check.
+ /// True if the grid has an atmosphere, false otherwise.
+ [PublicAPI]
+ public bool HasAtmosphere(EntityUid gridUid)
+ {
+ return _atmosQuery.HasComponent(gridUid);
+ }
+ ///
+ /// Sets whether a grid is simulated by Atmospherics.
+ ///
+ /// The grid to set.
+ /// Whether the grid should be simulated.
+ /// >True if the grid's simulated state was changed, false otherwise.
+ [PublicAPI]
public bool SetSimulatedGrid(EntityUid gridUid, bool simulated)
{
+ // TODO ATMOS this event literally has no subscribers. Did this just get silently refactored out?
var ev = new SetSimulatedGridMethodEvent(gridUid, simulated);
RaiseLocalEvent(gridUid, ref ev);
return ev.Handled;
}
+ ///
+ /// Checks whether a grid is simulated by Atmospherics.
+ ///
+ /// The grid to check.
+ /// >True if the grid is simulated, false otherwise.
public bool IsSimulatedGrid(EntityUid gridUid)
{
var ev = new IsSimulatedGridMethodEvent(gridUid);
@@ -67,24 +115,53 @@ public partial class AtmosphereSystem
return ev.Simulated;
}
+ ///
+ /// Gets all s on a grid.
+ ///
+ /// The grid to get mixtures for.
+ /// Whether to mark all tiles as active for atmosphere processing.
+ /// An enumerable of all gas mixtures on the grid.
+ [PublicAPI]
public IEnumerable GetAllMixtures(EntityUid gridUid, bool excite = false)
{
var ev = new GetAllMixturesMethodEvent(gridUid, excite);
RaiseLocalEvent(gridUid, ref ev);
- if(!ev.Handled)
- return Enumerable.Empty();
+ if (!ev.Handled)
+ return [];
DebugTools.AssertNotNull(ev.Mixtures);
return ev.Mixtures!;
}
+ ///
+ /// Invalidates a tile on a grid, marking it for revalidation.
+ ///
+ /// Frequently used tile data like are determined once and cached.
+ /// If this tile's state changes, ex. being added or removed, then this position in the map needs to
+ /// be updated.
+ ///
+ /// Tiles that need to be updated are marked as invalid and revalidated before all other
+ /// processing stages.
+ ///
+ /// The grid entity.
+ /// The tile to invalidate.
+ [PublicAPI]
public void InvalidateTile(Entity entity, Vector2i tile)
{
if (_atmosQuery.Resolve(entity.Owner, ref entity.Comp, false))
entity.Comp.InvalidatedCoords.Add(tile);
}
+ ///
+ /// Gets the gas mixtures for a list of tiles on a grid or map.
+ ///
+ /// The grid to get mixtures from.
+ /// The map to get mixtures from.
+ /// The list of tiles to get mixtures for.
+ /// Whether to mark the tiles as active for atmosphere processing.
+ /// >An array of gas mixtures corresponding to the input tiles.
+ [PublicAPI]
public GasMixture?[]? GetTileMixtures(
Entity? grid,
Entity? map,
@@ -95,7 +172,7 @@ public partial class AtmosphereSystem
var handled = false;
// If we've been passed a grid, try to let it handle it.
- if (grid is {} gridEnt && Resolve(gridEnt, ref gridEnt.Comp1))
+ if (grid is { } gridEnt && _atmosQuery.Resolve(gridEnt, ref gridEnt.Comp1))
{
if (excite)
Resolve(gridEnt, ref gridEnt.Comp2);
@@ -128,7 +205,7 @@ public partial class AtmosphereSystem
// We either don't have a grid, or the event wasn't handled.
// Let the map handle it instead, and also broadcast the event.
- if (map is {} mapEnt && _mapAtmosQuery.Resolve(mapEnt, ref mapEnt.Comp))
+ if (map is { } mapEnt && _mapAtmosQuery.Resolve(mapEnt, ref mapEnt.Comp))
{
mixtures ??= new GasMixture?[tiles.Count];
for (var i = 0; i < tiles.Count; i++)
@@ -145,10 +222,21 @@ public partial class AtmosphereSystem
{
mixtures[i] ??= GasMixture.SpaceGas;
}
+
return mixtures;
}
- public GasMixture? GetTileMixture (Entity entity, bool excite = false)
+ ///
+ /// Gets the gas mixture for a specific tile that an entity is on.
+ ///
+ /// The entity to get the tile mixture for.
+ /// Whether to mark the tile as active for atmosphere processing.
+ /// A if one could be found, null otherwise.
+ /// This does not return the that the entity
+ /// may be contained in, ex. if the entity is currently in a locker/crate with its own
+ /// .
+ [PublicAPI]
+ public GasMixture? GetTileMixture(Entity entity, bool excite = false)
{
if (!Resolve(entity.Owner, ref entity.Comp))
return null;
@@ -157,6 +245,15 @@ public partial class AtmosphereSystem
return GetTileMixture(entity.Comp.GridUid, entity.Comp.MapUid, indices, excite);
}
+ ///
+ /// Gets the gas mixture for a specific tile on a grid or map.
+ ///
+ /// The grid to get the mixture from.
+ /// The map to get the mixture from.
+ /// The tile to get the mixture from.
+ /// Whether to mark the tile as active for atmosphere processing.
+ /// >A if one could be found, null otherwise.
+ [PublicAPI]
public GasMixture? GetTileMixture(
Entity? grid,
Entity? map,
@@ -164,8 +261,8 @@ public partial class AtmosphereSystem
bool excite = false)
{
// If we've been passed a grid, try to let it handle it.
- if (grid is {} gridEnt
- && Resolve(gridEnt, ref gridEnt.Comp1, false)
+ if (grid is { } gridEnt
+ && _atmosQuery.Resolve(gridEnt, ref gridEnt.Comp1, false)
&& gridEnt.Comp1.Tiles.TryGetValue(gridTile, out var tile))
{
if (excite)
@@ -177,13 +274,20 @@ public partial class AtmosphereSystem
return tile.Air;
}
- if (map is {} mapEnt && _mapAtmosQuery.Resolve(mapEnt, ref mapEnt.Comp, false))
+ if (map is { } mapEnt && _mapAtmosQuery.Resolve(mapEnt, ref mapEnt.Comp, false))
return mapEnt.Comp.Mixture;
// Default to a space mixture... This is a space game, after all!
return GasMixture.SpaceGas;
}
+ ///
+ /// Triggers a tile's to react.
+ ///
+ /// The grid to react the tile on.
+ /// The tile to react.
+ /// The result of the reaction.
+ [PublicAPI]
public ReactionResult ReactTile(EntityUid gridId, Vector2i tile)
{
var ev = new ReactTileMethodEvent(gridId, tile);
@@ -194,24 +298,49 @@ public partial class AtmosphereSystem
return ev.Result;
}
- public bool IsTileAirBlocked(EntityUid gridUid, Vector2i tile, AtmosDirection directions = AtmosDirection.All, MapGridComponent? mapGridComp = null)
+ ///
+ /// Checks if a tile on a grid is air-blocked in the specified directions.
+ ///
+ /// The grid to check.
+ /// The tile on the grid to check.
+ /// The directions to check for air-blockage.
+ /// Optional map grid component associated with the grid.
+ /// True if the tile is air-blocked in the specified directions, false otherwise.
+ [PublicAPI]
+ public bool IsTileAirBlocked(EntityUid gridUid,
+ Vector2i tile,
+ AtmosDirection directions = AtmosDirection.All,
+ MapGridComponent? mapGridComp = null)
{
if (!Resolve(gridUid, ref mapGridComp, false))
return false;
+ // TODO ATMOS: This reconstructs the data instead of getting the cached version. Might want to include a method to get the cached version later.
var data = GetAirtightData(gridUid, mapGridComp, tile);
return data.BlockedDirections.IsFlagSet(directions);
}
+ ///
+ /// Checks if a tile on a grid or map is space as defined by a tile's definition of space.
+ /// Some tiles can hold back space and others cannot - for example, plating can hold
+ /// back space, whereas scaffolding cannot, exposing the map atmosphere beneath.
+ ///
+ /// This does not check if the on the tile is space,
+ /// it only checks the current tile's ability to hold back space.
+ /// The grid to check.
+ /// The map to check.
+ /// The tile to check.
+ /// True if the tile is space, false otherwise.
+ [PublicAPI]
public bool IsTileSpace(Entity? grid, Entity? map, Vector2i tile)
{
- if (grid is {} gridEnt && _atmosQuery.Resolve(gridEnt, ref gridEnt.Comp, false)
- && gridEnt.Comp.Tiles.TryGetValue(tile, out var tileAtmos))
+ if (grid is { } gridEnt && _atmosQuery.Resolve(gridEnt, ref gridEnt.Comp, false)
+ && gridEnt.Comp.Tiles.TryGetValue(tile, out var tileAtmos))
{
return tileAtmos.Space;
}
- if (map is {} mapEnt && _mapAtmosQuery.Resolve(mapEnt, ref mapEnt.Comp, false))
+ if (map is { } mapEnt && _mapAtmosQuery.Resolve(mapEnt, ref mapEnt.Comp, false))
return mapEnt.Comp.Space;
// If nothing handled the event, it'll default to true.
@@ -219,28 +348,77 @@ public partial class AtmosphereSystem
return true;
}
+ ///
+ /// Checks if the gas mixture on a tile is "probably safe".
+ /// Probably safe is defined as having at least air alarm-grade safe pressure and temperature.
+ /// (more than 260K, less than 360K, and between safe low and high pressure as defined in
+ /// and )
+ ///
+ /// The grid to check.
+ /// The map to check.
+ /// The tile to check.
+ /// True if the tile's mixture is probably safe, false otherwise.
+ [PublicAPI]
public bool IsTileMixtureProbablySafe(Entity? grid, Entity map, Vector2i tile)
{
return IsMixtureProbablySafe(GetTileMixture(grid, map, tile));
}
+ ///
+ /// Gets the heat capacity of the gas mixture on a tile.
+ ///
+ /// The grid to check.
+ /// The map to check.
+ /// The tile on the grid/map to check.
+ /// >The heat capacity of the tile's mixture, or the heat capacity of space if a mixture could not be found.
+ [PublicAPI]
public float GetTileHeatCapacity(Entity? grid, Entity map, Vector2i tile)
{
return GetHeatCapacity(GetTileMixture(grid, map, tile) ?? GasMixture.SpaceGas);
}
+ ///
+ /// Gets an enumerator for the adjacent tile mixtures of a tile on a grid.
+ ///
+ /// The grid to get adjacent tile mixtures from.
+ /// The tile to get adjacent mixtures for.
+ /// Whether to include blocked adjacent tiles.
+ /// Whether to mark the adjacent tiles as active for atmosphere processing.
+ /// An enumerator for the adjacent tile mixtures.
+ [PublicAPI]
public TileMixtureEnumerator GetAdjacentTileMixtures(Entity grid, Vector2i tile, bool includeBlocked = false, bool excite = false)
{
+ // TODO ATMOS includeBlocked and excite parameters are unhandled currently.
if (!_atmosQuery.Resolve(grid, ref grid.Comp, false))
return TileMixtureEnumerator.Empty;
return !grid.Comp.Tiles.TryGetValue(tile, out var atmosTile)
? TileMixtureEnumerator.Empty
- : new(atmosTile.AdjacentTiles);
+ : new TileMixtureEnumerator(atmosTile.AdjacentTiles);
}
- public void HotspotExpose(Entity grid, Vector2i tile, float exposedTemperature, float exposedVolume,
- EntityUid? sparkSourceUid = null, bool soh = false)
+ ///
+ /// Exposes a tile to a hotspot of given temperature and volume, igniting it if conditions are met.
+ ///
+ /// The grid to expose the tile on.
+ /// The tile to expose.
+ /// The temperature of the hotspot to expose.
+ /// You can think of this as exposing a temperature of a flame.
+ /// The volume of the hotspot to expose.
+ /// You can think of this as how big the flame is initially.
+ /// Bigger flames will ramp a fire faster.
+ /// Whether to "boost" a fire that's currently on the tile already.
+ /// Does nothing if the tile isn't already a hotspot.
+ /// This clamps the temperature and volume of the hotspot to the maximum
+ /// of the provided parameters and whatever's on the tile.
+ /// Entity that started the exposure for admin logging.
+ [PublicAPI]
+ public void HotspotExpose(Entity grid,
+ Vector2i tile,
+ float exposedTemperature,
+ float exposedVolume,
+ EntityUid? sparkSourceUid = null,
+ bool soh = false)
{
if (!_atmosQuery.Resolve(grid, ref grid.Comp, false))
return;
@@ -249,8 +427,26 @@ public partial class AtmosphereSystem
HotspotExpose(grid.Comp, atmosTile, exposedTemperature, exposedVolume, soh, sparkSourceUid);
}
- public void HotspotExpose(TileAtmosphere tile, float exposedTemperature, float exposedVolume,
- EntityUid? sparkSourceUid = null, bool soh = false)
+ ///
+ /// Exposes a tile to a hotspot of given temperature and volume, igniting it if conditions are met.
+ ///
+ /// The to expose.
+ /// The temperature of the hotspot to expose.
+ /// You can think of this as exposing a temperature of a flame.
+ /// The volume of the hotspot to expose.
+ /// You can think of this as how big the flame is initially.
+ /// Bigger flames will ramp a fire faster.
+ /// Whether to "boost" a fire that's currently on the tile already.
+ /// Does nothing if the tile isn't already a hotspot.
+ /// This clamps the temperature and volume of the hotspot to the maximum
+ /// of the provided parameters and whatever's on the tile.
+ /// Entity that started the exposure for admin logging.
+ [PublicAPI]
+ public void HotspotExpose(TileAtmosphere tile,
+ float exposedTemperature,
+ float exposedVolume,
+ EntityUid? sparkSourceUid = null,
+ bool soh = false)
{
if (!_atmosQuery.TryGetComponent(tile.GridIndex, out var atmos))
return;
@@ -259,12 +455,25 @@ public partial class AtmosphereSystem
HotspotExpose(atmos, tile, exposedTemperature, exposedVolume, soh, sparkSourceUid);
}
+ ///
+ /// Extinguishes a hotspot on a tile.
+ ///
+ /// The grid to extinguish the hotspot on.
+ /// The tile on the grid to extinguish the hotspot on.
+ [PublicAPI]
public void HotspotExtinguish(EntityUid gridUid, Vector2i tile)
{
var ev = new HotspotExtinguishMethodEvent(gridUid, tile);
RaiseLocalEvent(gridUid, ref ev);
}
+ ///
+ /// Checks if a hotspot is active on a tile.
+ ///
+ /// The grid to check.
+ /// The tile on the grid to check.
+ /// True if a hotspot is active on the tile, false otherwise.
+ [PublicAPI]
public bool IsHotspotActive(EntityUid gridUid, Vector2i tile)
{
var ev = new IsHotspotActiveMethodEvent(gridUid, tile);
@@ -274,11 +483,25 @@ public partial class AtmosphereSystem
return ev.Result;
}
+ ///
+ /// Adds a to a grid.
+ ///
+ /// The grid to add the pipe net to.
+ /// The pipe net to add.
+ /// True if the pipe net was added, false otherwise.
+ [PublicAPI]
public bool AddPipeNet(Entity grid, PipeNet pipeNet)
{
return _atmosQuery.Resolve(grid, ref grid.Comp, false) && grid.Comp.PipeNets.Add(pipeNet);
}
+ ///
+ /// Removes a from a grid.
+ ///
+ /// The grid to remove the pipe net from.
+ /// The pipe net to remove.
+ /// True if the pipe net was removed, false otherwise.
+ [PublicAPI]
public bool RemovePipeNet(Entity grid, PipeNet pipeNet)
{
// Technically this event can be fired even on grids that don't
@@ -292,6 +515,13 @@ public partial class AtmosphereSystem
return _atmosQuery.Resolve(grid, ref grid.Comp, false) && grid.Comp.PipeNets.Remove(pipeNet);
}
+ ///
+ /// Adds an entity with an to a grid's list of atmos devices.
+ ///
+ /// The grid to add the device to.
+ /// The device to add.
+ /// True if the device was added, false otherwise.
+ [PublicAPI]
public bool AddAtmosDevice(Entity grid, Entity device)
{
DebugTools.Assert(device.Comp.JoinedGrid == null);
@@ -307,6 +537,12 @@ public partial class AtmosphereSystem
return true;
}
+ ///
+ /// Removes an entity with an from a grid's list of atmos devices.
+ ///
+ /// The grid to remove the device from.
+ /// The device to remove.
+ /// True if the device was removed, false otherwise.
public bool RemoveAtmosDevice(Entity grid, Entity device)
{
DebugTools.Assert(device.Comp.JoinedGrid == grid);
@@ -418,23 +654,44 @@ public partial class AtmosphereSystem
return contains;
}
- [ByRefEvent] private record struct SetSimulatedGridMethodEvent
- (EntityUid Grid, bool Simulated, bool Handled = false);
-
- [ByRefEvent] private record struct IsSimulatedGridMethodEvent
- (EntityUid Grid, bool Simulated = false, bool Handled = false);
-
- [ByRefEvent] private record struct GetAllMixturesMethodEvent
- (EntityUid Grid, bool Excite = false, IEnumerable? Mixtures = null, bool Handled = false);
-
- [ByRefEvent] private record struct ReactTileMethodEvent
- (EntityUid GridId, Vector2i Tile, ReactionResult Result = default, bool Handled = false);
-
- [ByRefEvent] private record struct HotspotExtinguishMethodEvent
- (EntityUid Grid, Vector2i Tile, bool Handled = false);
-
- [ByRefEvent] private record struct IsHotspotActiveMethodEvent
- (EntityUid Grid, Vector2i Tile, bool Result = false, bool Handled = false);
+ [ByRefEvent]
+ private record struct SetSimulatedGridMethodEvent(
+ EntityUid Grid,
+ bool Simulated,
+ bool Handled = false);
+
+ [ByRefEvent]
+ private record struct IsSimulatedGridMethodEvent(
+ EntityUid Grid,
+ bool Simulated = false,
+ bool Handled = false);
+
+ [ByRefEvent]
+ private record struct GetAllMixturesMethodEvent(
+ EntityUid Grid,
+ bool Excite = false,
+ IEnumerable? Mixtures = null,
+ bool Handled = false);
+
+ [ByRefEvent]
+ private record struct ReactTileMethodEvent(
+ EntityUid GridId,
+ Vector2i Tile,
+ ReactionResult Result = default,
+ bool Handled = false);
+
+ [ByRefEvent]
+ private record struct HotspotExtinguishMethodEvent(
+ EntityUid Grid,
+ Vector2i Tile,
+ bool Handled = false);
+
+ [ByRefEvent]
+ private record struct IsHotspotActiveMethodEvent(
+ EntityUid Grid,
+ Vector2i Tile,
+ bool Result = false,
+ bool Handled = false);
}