Move a metric fuckton of AtmosphereSystem to Shared. (#42989)

* AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

* fix the tests I broke

* Remove methods that the client shouldn't be calling. Hamburger.

* light cleanup for now

* review

* whoop

* docs updates and misc changes

---------

Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
This commit is contained in:
Princess Cheeseballs
2026-03-14 01:53:49 -07:00
committed by GitHub
parent dcbe5e08c8
commit a1d7406bf2
71 changed files with 723 additions and 603 deletions
+1 -2
View File
@@ -1,11 +1,10 @@
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
using Content.IntegrationTests;
using Content.IntegrationTests.Pair;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.CCVar;
using Robust.Shared;
using Robust.Shared.Analyzers;
@@ -1,9 +0,0 @@
using Content.Shared.Atmos.Components;
namespace Content.Client.Atmos.Components;
[RegisterComponent]
public sealed partial class MapAtmosphereComponent : SharedMapAtmosphereComponent
{
}
@@ -1,5 +1,6 @@
using System.Runtime.CompilerServices;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Reactions;
namespace Content.Client.Atmos.EntitySystems;
@@ -13,6 +14,15 @@ public sealed partial class AtmosphereSystem
implementation.
*/
/// <inheritdoc/>
/// <remarks>No-op on client as reactions aren't entirely in shared.
/// Don't call it. Smile.</remarks>
public override ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder)
{
// Reactions don't work on client so don't even try.
throw new NotImplementedException();
}
public override bool IsMixtureFuel(GasMixture mixture, float epsilon = Atmospherics.Epsilon)
{
var tmp = new float[Atmospherics.AdjustedNumberOfGases];
@@ -1,7 +1,6 @@
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.EntitySystems;
using Content.Shared.Atmos.Components;
using Robust.Shared.GameObjects;
namespace Content.IntegrationTests.Tests.Atmos;
@@ -1,4 +1,3 @@
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Components;
using Content.Shared.Body.Systems;
@@ -7,6 +6,7 @@ using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using System.Numerics;
using Content.Shared.Atmos.Components;
using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.Utility;
@@ -1,7 +1,7 @@
using Content.Server.Administration;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Shared.Administration;
using Content.Shared.Atmos.Components;
using Robust.Shared.Console;
using Robust.Shared.Map.Components;
@@ -1,7 +1,7 @@
using Content.Server.Administration;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Shared.Administration;
using Content.Shared.Atmos.Components;
using Robust.Shared.Console;
namespace Content.Server.Atmos.Commands;
@@ -1,8 +1,8 @@
using Content.Server.Administration;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Shared.Administration;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Robust.Shared.Console;
using Robust.Shared.Map;
@@ -1,135 +0,0 @@
using System.Collections.Concurrent;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Serialization;
using Content.Server.NodeContainer.NodeGroups;
using Content.Shared.Atmos.Components;
namespace Content.Server.Atmos.Components
{
/// <summary>
/// Internal Atmos class. Use <see cref="AtmosphereSystem"/> to interact with atmos instead.
/// </summary>
[RegisterComponent, Serializable,
Access(typeof(AtmosphereSystem), typeof(GasTileOverlaySystem), typeof(AtmosDebugOverlaySystem))]
public sealed partial class GridAtmosphereComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
public bool Simulated { get; set; } = true;
[ViewVariables]
public bool ProcessingPaused { get; set; } = false;
[ViewVariables]
public float Timer { get; set; } = 0f;
[ViewVariables]
public int UpdateCounter { get; set; } = 1; // DO NOT SET TO ZERO BY DEFAULT! It will break roundstart atmos...
[ViewVariables]
[IncludeDataField(customTypeSerializer:typeof(TileAtmosCollectionSerializer))]
public Dictionary<Vector2i, TileAtmosphere> Tiles = new(1000);
[ViewVariables]
public HashSet<TileAtmosphere> MapTiles = new(1000);
[ViewVariables]
public readonly HashSet<TileAtmosphere> ActiveTiles = new(1000);
[ViewVariables]
public int ActiveTilesCount => ActiveTiles.Count;
[ViewVariables]
public readonly HashSet<ExcitedGroup> ExcitedGroups = new(1000);
[ViewVariables]
public int ExcitedGroupCount => ExcitedGroups.Count;
[ViewVariables]
public readonly HashSet<TileAtmosphere> HotspotTiles = new(1000);
[ViewVariables]
public int HotspotTilesCount => HotspotTiles.Count;
[ViewVariables]
public readonly HashSet<TileAtmosphere> SuperconductivityTiles = new(1000);
[ViewVariables]
public int SuperconductivityTilesCount => SuperconductivityTiles.Count;
[ViewVariables]
public HashSet<TileAtmosphere> HighPressureDelta = new(1000);
[ViewVariables]
public int HighPressureDeltaCount => HighPressureDelta.Count;
/// <summary>
/// A list of entities that have a <see cref="DeltaPressureComponent"/> and are to
/// be processed by the <see cref="DeltaPressureSystem"/>, if enabled.
///
/// To prevent massive bookkeeping overhead, this list is processed in-place,
/// with add/remove/find operations helped via a dict.
/// </summary>
/// <remarks>If you want to add/remove/find entities in this list,
/// use the API methods in the Atmospherics API.</remarks>
[ViewVariables]
public readonly List<Entity<DeltaPressureComponent>> DeltaPressureEntities =
new(AtmosphereSystem.DeltaPressurePreAllocateLength);
/// <summary>
/// An index lookup for the <see cref="DeltaPressureEntities"/> list.
/// Used for add/remove/find operations to speed up processing.
/// </summary>
public readonly Dictionary<EntityUid, int> DeltaPressureEntityLookup =
new(AtmosphereSystem.DeltaPressurePreAllocateLength);
/// <summary>
/// Integer that indicates the current position in the
/// <see cref="DeltaPressureEntities"/> list that is being processed.
/// </summary>
[ViewVariables(VVAccess.ReadOnly)]
public int DeltaPressureCursor;
/// <summary>
/// Queue of entities that need to have damage applied to them.
/// </summary>
[ViewVariables]
public readonly ConcurrentQueue<AtmosphereSystem.DeltaPressureDamageResult> DeltaPressureDamageResults = new();
[ViewVariables]
public readonly HashSet<IPipeNet> PipeNets = new();
[ViewVariables]
public readonly HashSet<Entity<AtmosDeviceComponent>> AtmosDevices = new();
[ViewVariables]
public readonly Queue<TileAtmosphere> CurrentRunTiles = new();
[ViewVariables]
public readonly Queue<ExcitedGroup> CurrentRunExcitedGroups = new();
[ViewVariables]
public readonly Queue<IPipeNet> CurrentRunPipeNet = new();
[ViewVariables]
public readonly Queue<Entity<AtmosDeviceComponent>> CurrentRunAtmosDevices = new();
[ViewVariables]
public readonly HashSet<Vector2i> InvalidatedCoords = new(1000);
[ViewVariables]
public readonly Queue<TileAtmosphere> CurrentRunInvalidatedTiles = new();
[ViewVariables]
public readonly List<TileAtmosphere> PossiblyDisconnectedTiles = new(100);
[ViewVariables]
public int InvalidatedCoordsCount => InvalidatedCoords.Count;
[ViewVariables]
public long EqualizationQueueCycleControl { get; set; }
[ViewVariables]
public AtmosphereProcessingState State { get; set; } = AtmosphereProcessingState.Revalidate;
}
}
@@ -1,8 +1,7 @@
using Content.Server.Atmos.Components;
using Content.Server.Atmos.Piping.Components;
using Content.Shared.Atmos;
using Robust.Shared.Map;
using System.Diagnostics.CodeAnalysis;
using Content.Shared.Atmos.Components;
namespace Content.Server.Atmos.EntitySystems;
@@ -1,6 +1,6 @@
using System.Numerics;
using Content.Server.Atmos.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.CCVar;
using JetBrains.Annotations;
@@ -1,61 +0,0 @@
using Content.Shared.Atmos;
using Robust.Shared.Map;
namespace Content.Server.Atmos.EntitySystems
{
/* doesn't seem to be a use for this at the moment, so it's disabled
public sealed class AtmosExposedSystem : EntitySystem
{}
*/
[ByRefEvent]
public readonly struct AtmosExposedUpdateEvent
{
public readonly EntityCoordinates Coordinates;
public readonly GasMixture GasMixture;
public readonly TransformComponent Transform;
public AtmosExposedUpdateEvent(EntityCoordinates coordinates, GasMixture mixture, TransformComponent transform)
{
Coordinates = coordinates;
GasMixture = mixture;
Transform = transform;
}
}
/// <summary>
/// Event that tries to query the mixture a certain entity is exposed to.
/// This is mainly intended for use with entities inside of containers.
/// This event is not raised for entities that are directly parented to the grid.
/// </summary>
[ByRefEvent]
public struct AtmosExposedGetAirEvent
{
/// <summary>
/// The entity we want to query this for.
/// </summary>
public readonly Entity<TransformComponent> Entity;
/// <summary>
/// The mixture that the entity is exposed to. Output parameter.
/// </summary>
public GasMixture? Gas = null;
/// <summary>
/// Whether to excite the mixture, if possible.
/// </summary>
public readonly bool Excite = false;
/// <summary>
/// Whether this event has been handled or not.
/// Check this before changing anything.
/// </summary>
public bool Handled = false;
public AtmosExposedGetAirEvent(Entity<TransformComponent> entity, bool excite = false)
{
Entity = entity;
Excite = excite;
}
}
}
@@ -1,9 +1,8 @@
using System.Diagnostics;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.Piping.Components;
using Content.Server.NodeContainer.NodeGroups;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Atmos.Reactions;
using JetBrains.Annotations;
using Robust.Shared.Map.Components;
@@ -20,61 +19,6 @@ public partial class AtmosphereSystem
consider adding a method here instead of making your own way to work around it.
*/
/// <summary>
/// Gets the <see cref="GasMixture"/> that an entity is contained within.
/// </summary>
/// <param name="ent">The entity to get the mixture for.</param>
/// <param name="ignoreExposed">If true, will ignore mixtures that the entity is contained in
/// (ex. lockers and cryopods) and just get the tile mixture.</param>
/// <param name="excite">If true, will mark the tile as active for atmosphere processing.</param>
/// <returns>A <see cref="GasMixture"/> if one could be found, null otherwise.</returns>
[PublicAPI]
public GasMixture? GetContainingMixture(Entity<TransformComponent?> ent, bool ignoreExposed = false, bool excite = false)
{
if (!Resolve(ent, ref ent.Comp))
return null;
return GetContainingMixture(ent, ent.Comp.GridUid, ent.Comp.MapUid, ignoreExposed, excite);
}
/// <summary>
/// Gets the <see cref="GasMixture"/> that an entity is contained within.
/// </summary>
/// <param name="ent">The entity to get the mixture for.</param>
/// <param name="grid">The grid that the entity may be on.</param>
/// <param name="map">The map that the entity may be on.</param>
/// <param name="ignoreExposed">If true, will ignore mixtures that the entity is contained in
/// (ex. lockers and cryopods) and just get the tile mixture.</param>
/// <param name="excite">If true, will mark the tile as active for atmosphere processing.</param>
/// <returns>A <see cref="GasMixture"/> if one could be found, null otherwise.</returns>
[PublicAPI]
public GasMixture? GetContainingMixture(
Entity<TransformComponent?> ent,
Entity<GridAtmosphereComponent?, GasTileOverlayComponent?>? grid,
Entity<MapAtmosphereComponent?>? map,
bool ignoreExposed = false,
bool excite = false)
{
if (!Resolve(ent, ref ent.Comp))
return null;
if (!ignoreExposed && !ent.Comp.Anchored)
{
// Used for things like disposals/cryo to change which air people are exposed to.
var ev = new AtmosExposedGetAirEvent((ent, ent.Comp), excite);
RaiseLocalEvent(ent, ref ev);
if (ev.Handled)
return ev.Gas;
// TODO ATMOS: recursively iterate up through parents
// This really needs recursive InContainer metadata flag for performance
// And ideally some fast way to get the innermost airtight container.
}
var position = _transformSystem.GetGridTilePositionOrDefault((ent, ent.Comp));
return GetTileMixture(grid, map, position, excite);
}
/// <summary>
/// Checks if a grid has an atmosphere.
/// </summary>
@@ -153,6 +97,69 @@ public partial class AtmosphereSystem
entity.Comp.InvalidatedCoords.Add(tile);
}
/// <summary>
/// Gets the gas mixture for a specific tile that an entity is on.
/// </summary>
/// <param name="entity">The entity to get the tile mixture for.</param>
/// <param name="excite">Whether to mark the tile as active for atmosphere processing.</param>
/// <returns>A <see cref="GasMixture"/> if one could be found, null otherwise.</returns>
/// <remarks>This does not return the <see cref="GasMixture"/> that the entity
/// may be contained in, ex. if the entity is currently in a locker/crate with its own
/// <see cref="GasMixture"/>.</remarks>
[PublicAPI]
public GasMixture? GetTileMixture(Entity<TransformComponent?> entity, bool excite = false)
{
if (!Resolve(entity.Owner, ref entity.Comp))
return null;
var indices = XformSystem.GetGridTilePositionOrDefault(entity);
return GetTileMixture(entity.Comp.GridUid, entity.Comp.MapUid, indices, excite);
}
/// <summary>
/// Gets the <see cref="GasMixture"/> that an entity is contained within.
/// </summary>
/// <param name="ent">The entity to get the mixture for.</param>
/// <param name="ignoreExposed">If true, will ignore mixtures that the entity is contained in
/// (ex. lockers and cryopods) and just get the tile mixture.</param>
/// <param name="excite">If true, will mark the tile as active for atmosphere processing.</param>
/// <returns>A <see cref="GasMixture"/> if one could be found, null otherwise.</returns>
[PublicAPI]
public GasMixture? GetContainingMixture(Entity<TransformComponent?> ent, bool ignoreExposed = false, bool excite = false)
{
if (!Resolve(ent, ref ent.Comp))
return null;
return GetContainingMixture(ent, ent.Comp.GridUid, ent.Comp.MapUid, ignoreExposed, excite);
}
/// <summary>
/// Gets the <see cref="GasMixture"/> that an entity is contained within.
/// </summary>
/// <param name="ent">The entity to get the mixture for.</param>
/// <param name="grid">The grid that the entity may be on.</param>
/// <param name="map">The map that the entity may be on.</param>
/// <param name="ignoreExposed">If true, will ignore mixtures that the entity is contained in
/// (ex. lockers and cryopods) and just get the tile mixture.</param>
/// <param name="excite">If true, will mark the tile as active for atmosphere processing.</param>
/// <returns>A <see cref="GasMixture"/> if one could be found, null otherwise.</returns>
[PublicAPI]
public GasMixture? GetContainingMixture(Entity<TransformComponent?> ent,
Entity<GridAtmosphereComponent?, GasTileOverlayComponent?>? grid,
Entity<MapAtmosphereComponent?>? map,
bool ignoreExposed = false,
bool excite = false)
{
if (!Resolve(ent, ref ent.Comp))
return null;
if (!ignoreExposed && TryGetExposedMixture(ent, out var mixture))
return mixture;
var position = XformSystem.GetGridTilePositionOrDefault((ent, ent.Comp));
return GetTileMixture(grid, map, position, excite);
}
/// <summary>
/// Gets the gas mixtures for a list of tiles on a grid or map.
/// </summary>
@@ -226,33 +233,6 @@ public partial class AtmosphereSystem
return mixtures;
}
/// <summary>
/// Gets the gas mixture for a specific tile that an entity is on.
/// </summary>
/// <param name="entity">The entity to get the tile mixture for.</param>
/// <param name="excite">Whether to mark the tile as active for atmosphere processing.</param>
/// <returns>A <see cref="GasMixture"/> if one could be found, null otherwise.</returns>
/// <remarks>This does not return the <see cref="GasMixture"/> that the entity
/// may be contained in, ex. if the entity is currently in a locker/crate with its own
/// <see cref="GasMixture"/>.</remarks>
[PublicAPI]
public GasMixture? GetTileMixture(Entity<TransformComponent?> entity, bool excite = false)
{
if (!Resolve(entity.Owner, ref entity.Comp))
return null;
var indices = _transformSystem.GetGridTilePositionOrDefault(entity);
return GetTileMixture(entity.Comp.GridUid, entity.Comp.MapUid, indices, excite);
}
/// <summary>
/// Gets the gas mixture for a specific tile on a grid or map.
/// </summary>
/// <param name="grid">The grid to get the mixture from.</param>
/// <param name="map">The map to get the mixture from.</param>
/// <param name="gridTile">The tile to get the mixture from.</param>
/// <param name="excite">Whether to mark the tile as active for atmosphere processing.</param>
/// <returns>>A <see cref="GasMixture"/> if one could be found, null otherwise.</returns>
[PublicAPI]
public GasMixture? GetTileMixture(
Entity<GridAtmosphereComponent?, GasTileOverlayComponent?>? grid,
@@ -281,6 +261,34 @@ public partial class AtmosphereSystem
return GasMixture.SpaceGas;
}
public override void MergeContainingMixture(Entity<TransformComponent?> entity, GasMixture mixture, bool ignoreExposed = false, bool excite = false)
{
if (GetContainingMixture(entity, ignoreExposed, excite) is not { } containingMixture)
return;
Merge(containingMixture, mixture);
}
[PublicAPI]
public override void MergeTileMixture(Entity<TransformComponent?> entity, GasMixture mixture, bool excite = false)
{
if (GetTileMixture(entity, excite) is not { } tileMixture)
return;
Merge(tileMixture, mixture);
}
public override void AdjustContainingMixture(Entity<TransformComponent?> entity, Gas gas, float mols, bool ignoreExposed = false, bool excite = false)
{
GetContainingMixture(entity, ignoreExposed, excite)?.AdjustMoles(gas, mols);
}
[PublicAPI]
public override void AdjustTileMixture(Entity<TransformComponent?> entity, Gas gas, float mols, bool excite = false)
{
GetTileMixture(entity, excite)?.AdjustMoles(gas, mols);
}
/// <summary>
/// Triggers a tile's <see cref="GasMixture"/> to react.
/// </summary>
@@ -1,5 +1,6 @@
using Content.Server.Atmos.Components;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using Robust.Shared.Map.Components;
namespace Content.Server.Atmos.EntitySystems;
@@ -3,6 +3,7 @@ using System.Collections.Concurrent;
using Content.Server.Atmos.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Damage;
using Robust.Shared.Random;
using Robust.Shared.Threading;
@@ -31,11 +32,6 @@ public sealed partial class AtmosphereSystem
/// </summary>
private const int DeltaPressurePairCount = Atmospherics.Directions / 2;
/// <summary>
/// The length to pre-allocate list/dicts of delta pressure entities on a <see cref="GridAtmosphereComponent"/>.
/// </summary>
public const int DeltaPressurePreAllocateLength = 1000;
/// <summary>
/// Bulk processes a range of <see cref="DeltaPressureComponent"/> entities on a <see cref="GridAtmosphereComponent"/>
/// from a starting index to an ending index,
@@ -321,18 +317,6 @@ public sealed partial class AtmosphereSystem
}
}
/// <summary>
/// Struct that holds the result of delta pressure damage processing for an entity.
/// This is only created and enqueued when the entity needs to take damage.
/// </summary>
/// <param name="Ent">The entity to deal damage to.</param>
/// <param name="Pressure">The current absolute pressure the entity is experiencing.</param>
/// <param name="DeltaPressure">The current delta pressure the entity is experiencing.</param>
public readonly record struct DeltaPressureDamageResult(
Entity<DeltaPressureComponent> Ent,
float Pressure,
float DeltaPressure);
/// <summary>
/// Does damage to an entity depending on the pressure experienced by it, based on the
/// entity's <see cref="DeltaPressureComponent"/>.
@@ -66,22 +66,6 @@ namespace Content.Server.Atmos.EntitySystems
return Speedup;
}
/// <summary>
/// Calculates the thermal energy for a gas mixture.
/// </summary>
public float GetThermalEnergy(GasMixture mixture)
{
return mixture.Temperature * GetHeatCapacity(mixture);
}
/// <summary>
/// Calculates the thermal energy for a gas mixture, using a cached heat capacity value.
/// </summary>
public float GetThermalEnergy(GasMixture mixture, float cachedHeatCapacity)
{
return mixture.Temperature * cachedHeatCapacity;
}
/// <summary>
/// Add 'dQ' Joules of energy into 'mixture'.
/// </summary>
@@ -92,28 +76,6 @@ namespace Content.Server.Atmos.EntitySystems
mixture.Temperature += dT;
}
/// <summary>
/// Merges the <see cref="giver"/> gas mixture into the <see cref="receiver"/> gas mixture.
/// The <see cref="giver"/> gas mixture is not modified by this method.
/// </summary>
public void Merge(GasMixture receiver, GasMixture giver)
{
if (receiver.Immutable) return;
if (MathF.Abs(receiver.Temperature - giver.Temperature) > Atmospherics.MinimumTemperatureDeltaToConsider)
{
var receiverHeatCapacity = GetHeatCapacity(receiver);
var giverHeatCapacity = GetHeatCapacity(giver);
var combinedHeatCapacity = receiverHeatCapacity + giverHeatCapacity;
if (combinedHeatCapacity > Atmospherics.MinimumHeatCapacity)
{
receiver.Temperature = (GetThermalEnergy(giver, giverHeatCapacity) + GetThermalEnergy(receiver, receiverHeatCapacity)) / combinedHeatCapacity;
}
}
NumericsHelpers.Add(receiver.Moles, giver.Moles);
}
/// <summary>
/// Divides a source gas mixture into several recipient mixtures, scaled by their relative volumes. Does not
/// modify the source gas mixture. Used for pipe network splitting. Note that the total destination volume
@@ -506,10 +468,8 @@ namespace Content.Server.Atmos.EntitySystems
return GasCompareResult.NoExchange;
}
/// <summary>
/// Performs reactions for a given gas mixture on an optional holder.
/// </summary>
public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder)
[PublicAPI]
public override ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder)
{
var reaction = ReactionResult.NoReaction;
var temperature = mixture.Temperature;
@@ -1,4 +1,3 @@
using Content.Server.Atmos.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Mobs.Components;
@@ -129,7 +128,7 @@ namespace Content.Server.Atmos.EntitySystems
return;
// Used by ExperiencePressureDifference to correct push/throw directions from tile-relative to physics world.
var gridWorldRotation = _transformSystem.GetWorldRotation(gridAtmosphere);
var gridWorldRotation = XformSystem.GetWorldRotation(gridAtmosphere);
// If we're using monstermos, smooth out the yeet direction to follow the flow
if (MonstermosEqualization)
@@ -248,7 +247,7 @@ namespace Content.Server.Atmos.EntitySystems
// TODO: Technically these directions won't be correct but uhh I'm just here for optimisations buddy not to fix my old bugs.
if (throwTarget != EntityCoordinates.Invalid)
{
var pos = ((_transformSystem.ToMapCoordinates(throwTarget).Position - _transformSystem.GetWorldPosition(xform)).Normalized() + dirVec).Normalized();
var pos = ((XformSystem.ToMapCoordinates(throwTarget).Position - XformSystem.GetWorldPosition(xform)).Normalized() + dirVec).Normalized();
_physics.ApplyLinearImpulse(uid, pos * moveForce, body: physics);
}
else
@@ -1,7 +1,8 @@
using Content.Server.Atmos.Components;
using Content.Server.Atmos.Piping.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Atmos.Piping.Components;
using Content.Shared.Maps;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
@@ -851,19 +852,4 @@ namespace Content.Server.Atmos.EntitySystems
/// </summary>
Finished,
}
public enum AtmosphereProcessingState : byte
{
Revalidate,
TileEqualize,
ActiveTiles,
ExcitedGroups,
HighPressureDelta,
DeltaPressure,
Hotspots,
Superconductivity,
PipeNet,
AtmosDevices,
NumStates
}
}
@@ -1,5 +1,5 @@
using Content.Server.Atmos.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Robust.Shared.Map.Components;
namespace Content.Server.Atmos.EntitySystems
@@ -1,7 +1,7 @@
using System.Runtime.CompilerServices;
using Content.Server.Atmos.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Atmos.Piping.Components;
using Robust.Shared.Map.Components;
@@ -85,24 +85,6 @@ public partial class AtmosphereSystem
return Atmospherics.CellVolume * mapGrid.TileSize * tiles;
}
/// <summary>
/// Data on the airtightness of a <see cref="TileAtmosphere"/>.
/// Cached on the <see cref="TileAtmosphere"/> and updated during
/// <see cref="AtmosphereSystem.ProcessRevalidate"/> if it was invalidated.
/// </summary>
/// <param name="BlockedDirections">The current directions blocked on this tile.
/// This is where air cannot flow to.</param>
/// <param name="NoAirWhenBlocked">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.</param>
/// <param name="FixVacuum">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.</param>
public readonly record struct AirtightData(
AtmosDirection BlockedDirections,
bool NoAirWhenBlocked,
bool FixVacuum);
/// <summary>
/// Updates the <see cref="AirtightData"/> for a <see cref="TileAtmosphere"/>
/// immediately.
@@ -1,8 +1,12 @@
using System.Linq;
using Content.Server.Administration.Logs;
using Content.Server.Atmos.Components;
using Content.Server.Fluids.EntitySystems;
using Content.Server.NodeContainer.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Damage.Systems;
using Content.Shared.Decals;
using Content.Shared.Doors.Components;
using Content.Shared.Maps;
@@ -13,8 +17,6 @@ using Robust.Shared.Containers;
using Robust.Shared.Map;
using Robust.Shared.Physics.Systems;
using Robust.Shared.Prototypes;
using System.Linq;
using Content.Shared.Damage.Systems;
using Robust.Shared.Threading;
namespace Content.Server.Atmos.EntitySystems;
@@ -35,7 +37,6 @@ public sealed partial class AtmosphereSystem : SharedAtmosphereSystem
[Dependency] private readonly GasTileOverlaySystem _gasTileOverlaySystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
[Dependency] private readonly TileSystem _tile = default!;
[Dependency] private readonly MapSystem _map = default!;
[Dependency] public readonly PuddleSystem Puddle = default!;
@@ -125,6 +126,6 @@ public sealed partial class AtmosphereSystem : SharedAtmosphereSystem
private void CacheDecals()
{
_burntDecals = _protoMan.EnumeratePrototypes<DecalPrototype>().Where(x => x.Tags.Contains("burnt")).Select(x => x.ID).ToArray();
_burntDecals = ProtoMan.EnumeratePrototypes<DecalPrototype>().Where(x => x.Tags.Contains("burnt")).Select(x => x.ID).ToArray();
}
}
@@ -1,5 +1,5 @@
using Content.Server.Atmos.Components;
using Content.Server.Shuttles.Systems;
using Content.Shared.Atmos.Components;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Events;
@@ -1,8 +1,8 @@
using System.Diagnostics.CodeAnalysis;
using Content.Server.Atmos.Piping.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Atmos.Piping.Components;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
@@ -1,16 +1,9 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.Atmos;
using Content.Server.Atmos.Components;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Server.NodeContainer;
using Content.Shared.Atmos.Piping;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.CCVar;
using Content.Shared.Interaction;
using JetBrains.Annotations;
using Robust.Shared.Configuration;
namespace Content.Server.Atmos.EntitySystems;
@@ -1,5 +1,4 @@
using Content.Server.Atmos.Monitor.Components;
using Content.Server.Atmos.Piping.Components;
using Content.Server.DeviceLinking.Systems;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.Popups;
@@ -20,6 +19,7 @@ using Content.Shared.Power;
using Content.Shared.Wires;
using Robust.Server.GameObjects;
using System.Linq;
using Content.Shared.Atmos.Components;
using Content.Shared.DeviceNetwork.Events;
using Content.Shared.DeviceNetwork.Components;
@@ -1,16 +1,14 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Monitor.Components;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.EntitySystems;
using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.Administration.Logs;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Piping.Components;
using Content.Shared.Database;
@@ -1,10 +1,9 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Binary.Components;
using Content.Server.Atmos.Piping.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Examine;
using JetBrains.Annotations;
@@ -1,12 +1,11 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Atmos.Piping.Components;
using Content.Shared.Audio;
using JetBrains.Annotations;
@@ -1,8 +1,8 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Atmos.Piping;
using Content.Shared.Atmos.Piping.Binary.Components;
@@ -1,10 +1,9 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Binary.Components;
using Content.Server.Atmos.Piping.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping;
using Content.Shared.Atmos.Piping.Components;
using Content.Shared.Audio;
@@ -1,10 +1,10 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Monitor.Systems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.Components;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping.Binary.Components;
using Content.Shared.Atmos.Piping.Binary.Systems;
using Content.Shared.Atmos.Piping.Components;
@@ -1,6 +1,5 @@
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping.Components;
using JetBrains.Annotations;
using Robust.Shared.Timing;
@@ -1,11 +1,10 @@
using Content.Server.Administration.Logs;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Trinary.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping;
using Content.Shared.Atmos.Piping.Components;
using Content.Shared.Atmos.Piping.Trinary.Components;
@@ -1,11 +1,10 @@
using Content.Server.Administration.Logs;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Trinary.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping;
using Content.Shared.Atmos.Piping.Components;
using Content.Shared.Atmos.Piping.Trinary.Components;
@@ -1,9 +1,8 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Trinary.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping;
using Content.Shared.Atmos.Piping.Components;
using Content.Shared.Audio;
@@ -1,11 +1,11 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.NodeGroups;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping.Binary.Components;
using Content.Shared.Atmos.Piping.Components;
using Content.Shared.Atmos.Piping.Unary.Systems;
using Content.Shared.Cargo;
using Content.Shared.Database;
@@ -1,12 +1,11 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.FixedPoint;
using JetBrains.Annotations;
@@ -1,9 +1,8 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping;
using Content.Shared.Interaction;
using JetBrains.Annotations;
@@ -1,10 +1,9 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using JetBrains.Annotations;
namespace Content.Server.Atmos.Piping.Unary.EntitySystems
@@ -1,7 +1,5 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Monitor.Systems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
@@ -10,10 +8,10 @@ using Content.Shared.Atmos;
using Content.Shared.Atmos.Piping.Unary.Components;
using JetBrains.Annotations;
using Content.Server.Power.EntitySystems;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping.Unary.Systems;
using Content.Shared.DeviceNetwork;
using Content.Shared.DeviceNetwork.Events;
using Content.Shared.Examine;
using Content.Shared.DeviceNetwork.Components;
namespace Content.Server.Atmos.Piping.Unary.EntitySystems
@@ -1,6 +1,5 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Monitor.Systems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.DeviceLinking.Systems;
using Content.Server.DeviceNetwork.Systems;
@@ -9,6 +8,7 @@ using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.EntitySystems;
using Content.Shared.Administration.Logs;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Piping.Components;
using Content.Shared.Atmos.Piping.Unary;
@@ -1,6 +1,5 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Monitor.Systems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.NodeContainer.EntitySystems;
@@ -8,6 +7,7 @@ using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.EntitySystems;
using Content.Shared.Administration.Logs;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Piping.Components;
using Content.Shared.Atmos.Piping.Unary.Components;
@@ -3,10 +3,7 @@ using Content.Shared.Atmos.Piping.Unary.Components;
using Content.Shared.Atmos.Visuals;
using Content.Shared.Examine;
using Content.Shared.Destructible;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Power.Components;
using Content.Server.NodeContainer;
using Robust.Server.GameObjects;
using Content.Server.NodeContainer.Nodes;
using Content.Server.NodeContainer.NodeGroups;
@@ -14,6 +11,7 @@ using Content.Server.Audio;
using Content.Server.Administration.Logs;
using Content.Server.NodeContainer.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Database;
using Content.Shared.Power;
@@ -1,9 +1,8 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.Popups;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Piping.Portable.Components;
using Content.Shared.Atmos.Piping.Unary.Components;
using Content.Shared.Atmos.Visuals;
@@ -127,11 +127,11 @@ public sealed class RottingSystem : SharedRottingSystem
if (!TryComp<PhysicsComponent>(uid, out var physics))
continue;
// We need a way to get the mass of the mob alone without armor etc in the future
// or just remove the mass mechanics altogether because they aren't good.
var molRate = perishable.MolsPerSecondPerUnitMass * (float)rotting.RotUpdateRate.TotalSeconds;
var tileMix = _atmosphere.GetTileMixture(uid, excite: true);
tileMix?.AdjustMoles(Gas.Ammonia, molRate * physics.FixturesMass);
_atmosphere.AdjustTileMixture(uid, Gas.Ammonia, molRate * physics.FixturesMass, excite: true);
}
}
}
@@ -1,5 +1,6 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Systems;
using Content.Shared.Atmos;
namespace Content.Server.Disposal.Unit;
@@ -6,6 +6,7 @@ using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Shuttles.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Doors.Components;
using Content.Shared.Doors.Systems;
@@ -26,6 +26,7 @@ using Robust.Shared.Containers;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
using System.Linq;
using Content.Shared.Atmos;
namespace Content.Server.Mech.Systems;
+2 -1
View File
@@ -1,13 +1,14 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Unary.EntitySystems;
using Content.Server.Medical.Components;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.NodeGroups;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Damage.Systems;
using Content.Shared.Medical.Cryogenics;
namespace Content.Server.Medical;
public sealed partial class CryoPodSystem : SharedCryoPodSystem
@@ -1,6 +1,6 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Systems;
using Content.Server.Body.Systems;
using Content.Server.Medical.Components;
using Content.Shared.Atmos;
using Content.Shared.Medical.Cryogenics;
namespace Content.Server.Medical
@@ -2,7 +2,6 @@ using System.Diagnostics;
using System.Linq;
using Content.Server.Administration.Managers;
using Content.Server.NodeContainer.NodeGroups;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Administration;
using Content.Shared.NodeContainer;
using Content.Shared.NodeContainer.NodeGroups;
@@ -1,103 +1,92 @@
using System.Linq;
using Content.Server.Atmos;
using Content.Server.Atmos.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Shared.Atmos;
using Content.Shared.NodeContainer;
using Content.Shared.NodeContainer.NodeGroups;
using Robust.Shared.Utility;
namespace Content.Server.NodeContainer.NodeGroups
namespace Content.Server.NodeContainer.NodeGroups;
[NodeGroup(NodeGroupID.Pipe)]
public sealed class PipeNet : BaseNodeGroup, IPipeNet
{
public interface IPipeNet : INodeGroup, IGasMixtureHolder
[ViewVariables] public GasMixture Air { get; set; } = new() {Temperature = Atmospherics.T20C};
[ViewVariables] private AtmosphereSystem? _atmosphereSystem;
public EntityUid? Grid { get; private set; }
public override void Initialize(Node sourceNode, IEntityManager entMan)
{
/// <summary>
/// Causes gas in the PipeNet to react.
/// </summary>
void Update();
base.Initialize(sourceNode, entMan);
Grid = entMan.GetComponent<TransformComponent>(sourceNode.Owner).GridUid;
if (Grid == null)
{
// This is probably due to a canister or something like that being spawned in space.
return;
}
_atmosphereSystem = entMan.EntitySysManager.GetEntitySystem<AtmosphereSystem>();
_atmosphereSystem.AddPipeNet(Grid.Value, this);
}
[NodeGroup(NodeGroupID.Pipe)]
public sealed class PipeNet : BaseNodeGroup, IPipeNet
public void Update()
{
[ViewVariables] public GasMixture Air { get; set; } = new() {Temperature = Atmospherics.T20C};
_atmosphereSystem?.React(Air, this);
}
[ViewVariables] private AtmosphereSystem? _atmosphereSystem;
public override void LoadNodes(List<Node> groupNodes)
{
base.LoadNodes(groupNodes);
public EntityUid? Grid { get; private set; }
public override void Initialize(Node sourceNode, IEntityManager entMan)
foreach (var node in groupNodes)
{
base.Initialize(sourceNode, entMan);
var pipeNode = (PipeNode) node;
Air.Volume += pipeNode.Volume;
}
}
Grid = entMan.GetComponent<TransformComponent>(sourceNode.Owner).GridUid;
public override void RemoveNode(Node node)
{
base.RemoveNode(node);
if (Grid == null)
{
// This is probably due to a cannister or something like that being spawned in space.
return;
}
// if the node is simply being removed into a separate group, we do nothing, as gas redistribution will be
// handled by AfterRemake(). But if it is being deleted, we actually want to remove the gas stored in this node.
if (!node.Deleting || node is not PipeNode pipe)
return;
_atmosphereSystem = entMan.EntitySysManager.GetEntitySystem<AtmosphereSystem>();
_atmosphereSystem.AddPipeNet(Grid.Value, this);
Air.Multiply(1f - pipe.Volume / Air.Volume);
Air.Volume -= pipe.Volume;
}
public override void AfterRemake(IEnumerable<IGrouping<INodeGroup?, Node>> newGroups)
{
RemoveFromGridAtmos();
var newAir = new List<GasMixture>(newGroups.Count());
foreach (var newGroup in newGroups)
{
if (newGroup.Key is IPipeNet newPipeNet)
newAir.Add(newPipeNet.Air);
}
public void Update()
{
_atmosphereSystem?.React(Air, this);
}
_atmosphereSystem?.DivideInto(Air, newAir);
}
public override void LoadNodes(List<Node> groupNodes)
{
base.LoadNodes(groupNodes);
private void RemoveFromGridAtmos()
{
if (Grid == null)
return;
foreach (var node in groupNodes)
{
var pipeNode = (PipeNode) node;
Air.Volume += pipeNode.Volume;
}
}
_atmosphereSystem?.RemovePipeNet(Grid.Value, this);
}
public override void RemoveNode(Node node)
{
base.RemoveNode(node);
// if the node is simply being removed into a separate group, we do nothing, as gas redistribution will be
// handled by AfterRemake(). But if it is being deleted, we actually want to remove the gas stored in this node.
if (!node.Deleting || node is not PipeNode pipe)
return;
Air.Multiply(1f - pipe.Volume / Air.Volume);
Air.Volume -= pipe.Volume;
}
public override void AfterRemake(IEnumerable<IGrouping<INodeGroup?, Node>> newGroups)
{
RemoveFromGridAtmos();
var newAir = new List<GasMixture>(newGroups.Count());
foreach (var newGroup in newGroups)
{
if (newGroup.Key is IPipeNet newPipeNet)
newAir.Add(newPipeNet.Air);
}
_atmosphereSystem?.DivideInto(Air, newAir);
}
private void RemoveFromGridAtmos()
{
if (Grid == null)
return;
_atmosphereSystem?.RemovePipeNet(Grid.Value, this);
}
public override string GetDebugData()
{
return @$"Pressure: { Air.Pressure:G3}
public override string GetDebugData()
{
return @$"Pressure: { Air.Pressure:G3}
Temperature: {Air.Temperature:G3}
Volume: {Air.Volume:G3}";
}
}
}
@@ -3,6 +3,7 @@ using Content.Server.NodeContainer.NodeGroups;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.NodeContainer;
using Content.Shared.NodeContainer.NodeGroups;
using Robust.Shared.Map.Components;
using Robust.Shared.Utility;
@@ -1,13 +1,10 @@
using Content.Server.Atmos;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Audio;
using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.DeviceNetwork;
using Content.Shared.DeviceNetwork.Events;
using Content.Shared.Examine;
@@ -17,7 +14,6 @@ using Content.Shared.Power.EntitySystems;
using Content.Shared.Power.Generation.Teg;
using Content.Shared.Rounding;
using Robust.Server.GameObjects;
using Robust.Shared.Utility;
namespace Content.Server.Power.Generation.Teg;
@@ -1,10 +1,8 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.EntitySystems;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Power;
namespace Content.Server.Power.Generator;
@@ -1,19 +1,16 @@
using System.Collections;
using System.Linq;
using System.Numerics;
using System.Threading;
using System.Threading.Tasks;
using Content.Server.Atmos;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Robust.Shared.CPUJob.JobQueues;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Parallax;
using Content.Server.Procedural;
using Content.Server.Salvage.Expeditions;
using Content.Server.Shuttles.Components;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Construction.EntitySystems;
using Content.Shared.Dataset;
using Content.Shared.Gravity;
using Content.Shared.Parallax.Biomes;
using Content.Shared.Physics;
@@ -24,15 +21,13 @@ using Content.Shared.Salvage;
using Content.Shared.Salvage.Expeditions;
using Content.Shared.Salvage.Expeditions.Modifiers;
using Content.Shared.Shuttles.Components;
using Content.Shared.Storage;
using Robust.Shared.Collections;
using Robust.Shared.Map;
using Robust.Shared.CPUJob.JobQueues;
using Robust.Shared.Map.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Content.Server.Shuttles.Components;
namespace Content.Server.Salvage;
@@ -1,9 +1,8 @@
using Content.Server.Atmos.Monitor.Components;
using Content.Server.Atmos.Monitor.Systems;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.Power.Generation.Teg;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Piping.Binary.Components;
using Content.Shared.Atmos.Piping.Unary.Components;
@@ -2,6 +2,7 @@ using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Systems;
using Content.Server.Construction;
using Content.Server.Construction.Components;
using Content.Shared.Atmos;
using Content.Shared.Storage.Components;
using Content.Shared.Storage.EntitySystems;
using Robust.Server.GameObjects;
@@ -0,0 +1,57 @@
using Robust.Shared.Map;
namespace Content.Shared.Atmos;
/// <summary>
/// Raised on entities that have an AtmosExposedComponent when AtmosphereSystem updates.
/// Exposure events are raised by AtmosphereSystem at some fixed interval.
/// </summary>
/// <param name="coordinates">The coordinates of the entity that is being exposed.</param>
/// <param name="mixture">The gas mixture that the entity is exposed to.</param>
/// <param name="transform">The xform of the entity that is being exposed.</param>
[ByRefEvent]
public readonly struct AtmosExposedUpdateEvent(
EntityCoordinates coordinates,
GasMixture mixture,
TransformComponent transform)
{
public readonly EntityCoordinates Coordinates = coordinates;
public readonly GasMixture GasMixture = mixture;
public readonly TransformComponent Transform = transform;
}
/// <summary>
/// Event that tries to query the mixture a certain entity is exposed to.
/// This is mainly intended for use with entities inside of containers.
/// This event is not raised for entities that are directly parented to the grid.
/// </summary>
[ByRefEvent]
public struct AtmosExposedGetAirEvent
{
/// <summary>
/// The entity we want to query this for.
/// </summary>
public readonly Entity<TransformComponent> Entity;
/// <summary>
/// The mixture that the entity is exposed to. Output parameter.
/// </summary>
public GasMixture? Gas = null;
/// <summary>
/// Whether to excite the mixture, if possible.
/// </summary>
public readonly bool Excite = false;
/// <summary>
/// Whether this event has been handled or not.
/// Check this before changing anything.
/// </summary>
public bool Handled = false;
public AtmosExposedGetAirEvent(Entity<TransformComponent> entity, bool excite = false)
{
Entity = entity;
Excite = excite;
}
}
@@ -1,7 +1,4 @@
using Content.Server.Atmos.Components;
using Content.Shared.Atmos.Components;
namespace Content.Server.Atmos.Piping.Components;
namespace Content.Shared.Atmos.Components;
/// <summary>
/// Component for atmos devices which are updated in line with atmos, as part of a <see cref="GridAtmosphereComponent"/>
@@ -0,0 +1,155 @@
using System.Collections.Concurrent;
using Content.Shared.Atmos.EntitySystems;
using Content.Shared.Atmos.Serialization;
using Content.Shared.NodeContainer.NodeGroups;
namespace Content.Shared.Atmos.Components;
/// <summary>
/// Internal <see cref="SharedAtmosphereSystem"/> class for storing all grid data.
/// If you need to access this data, use the API methods in the <see cref="SharedAtmosphereSystem"/>/server
/// instead of trying to scour this component or others for the data you need.
/// </summary>
[RegisterComponent, Serializable,
Access(typeof(SharedAtmosphereSystem), typeof(SharedGasTileOverlaySystem), typeof(SharedAtmosDebugOverlaySystem))]
public sealed partial class GridAtmosphereComponent : Component
{
/// <summary>
/// Whether the grid is being updated by Atmospherics.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public bool Simulated = true;
/// <summary>
/// Indicator for if Atmospherics has delegated the processing of this
/// grid to another tick due to the time budget running out.
/// </summary>
/// <example>If true, Atmospherics is not finished
/// processing the current stage and has yielded processing
/// to the next tick.</example>
[ViewVariables]
public bool ProcessingPaused;
/// <summary>
/// Timer used to delay processing for every AtmosTick.
/// No, Atmospherics cannot tick every frame.
/// </summary>
/// TODO: Replace with TimeSpan please.
[ViewVariables]
public float Timer;
/// <summary>
/// Integer that is incremented every time the grid is processed by Atmospherics.
/// Used in multiple subsystems to prevent double-copy/processing of data.
/// </summary>
/// <remarks>Do not set to zero by default.
/// You will break roundstart atmos otherwise.</remarks>
[ViewVariables]
public int UpdateCounter = 1;
[ViewVariables]
[IncludeDataField(customTypeSerializer:typeof(TileAtmosCollectionSerializer))]
public Dictionary<Vector2i, TileAtmosphere> Tiles = new(1000);
[ViewVariables]
public HashSet<TileAtmosphere> MapTiles = new(1000);
[ViewVariables]
public readonly HashSet<TileAtmosphere> ActiveTiles = new(1000);
[ViewVariables]
public int ActiveTilesCount => ActiveTiles.Count;
[ViewVariables]
public readonly HashSet<ExcitedGroup> ExcitedGroups = new(1000);
[ViewVariables]
public int ExcitedGroupCount => ExcitedGroups.Count;
[ViewVariables]
public readonly HashSet<TileAtmosphere> HotspotTiles = new(1000);
[ViewVariables]
public int HotspotTilesCount => HotspotTiles.Count;
[ViewVariables]
public readonly HashSet<TileAtmosphere> SuperconductivityTiles = new(1000);
[ViewVariables]
public int SuperconductivityTilesCount => SuperconductivityTiles.Count;
[ViewVariables]
public HashSet<TileAtmosphere> HighPressureDelta = new(1000);
[ViewVariables]
public int HighPressureDeltaCount => HighPressureDelta.Count;
/// <summary>
/// A list of entities that have a <see cref="DeltaPressureComponent"/> and are to
/// be processed by the <see cref="DeltaPressureSystem"/>, if enabled.
///
/// To prevent massive bookkeeping overhead, this list is processed in-place,
/// with add/remove/find operations helped via a dict.
/// </summary>
/// <remarks>If you want to add/remove/find entities in this list,
/// use the API methods in the Atmospherics API.</remarks>
[ViewVariables]
public readonly List<Entity<DeltaPressureComponent>> DeltaPressureEntities =
new(SharedAtmosphereSystem.DeltaPressurePreAllocateLength);
/// <summary>
/// An index lookup for the <see cref="DeltaPressureEntities"/> list.
/// Used for add/remove/find operations to speed up processing.
/// </summary>
public readonly Dictionary<EntityUid, int> DeltaPressureEntityLookup =
new(SharedAtmosphereSystem.DeltaPressurePreAllocateLength);
/// <summary>
/// Integer that indicates the current position in the
/// <see cref="DeltaPressureEntities"/> list that is being processed.
/// </summary>
[ViewVariables(VVAccess.ReadOnly)]
public int DeltaPressureCursor;
/// <summary>
/// Queue of entities that need to have damage applied to them.
/// </summary>
[ViewVariables]
public readonly ConcurrentQueue<DeltaPressureDamageResult> DeltaPressureDamageResults = new();
[ViewVariables]
public readonly HashSet<IPipeNet> PipeNets = new();
[ViewVariables]
public readonly HashSet<Entity<AtmosDeviceComponent>> AtmosDevices = new();
[ViewVariables]
public readonly Queue<TileAtmosphere> CurrentRunTiles = new();
[ViewVariables]
public readonly Queue<ExcitedGroup> CurrentRunExcitedGroups = new();
[ViewVariables]
public readonly Queue<IPipeNet> CurrentRunPipeNet = new();
[ViewVariables]
public readonly Queue<Entity<AtmosDeviceComponent>> CurrentRunAtmosDevices = new();
[ViewVariables]
public readonly HashSet<Vector2i> InvalidatedCoords = new(1000);
[ViewVariables]
public readonly Queue<TileAtmosphere> CurrentRunInvalidatedTiles = new();
[ViewVariables]
public readonly List<TileAtmosphere> PossiblyDisconnectedTiles = new(100);
[ViewVariables]
public int InvalidatedCoordsCount => InvalidatedCoords.Count;
[ViewVariables]
public long EqualizationQueueCycleControl { get; set; }
[ViewVariables]
public AtmosphereProcessingState State { get; set; } = AtmosphereProcessingState.Revalidate;
}
@@ -1,25 +1,23 @@
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
namespace Content.Server.Atmos.Components;
namespace Content.Shared.Atmos.Components;
/// <summary>
/// Component that defines the default GasMixture for a map.
/// Component that defines the default GasMixture for a map.
/// </summary>
[RegisterComponent, Access(typeof(SharedAtmosphereSystem))]
public sealed partial class MapAtmosphereComponent : SharedMapAtmosphereComponent
{
/// <summary>
/// The default GasMixture a map will have. Space mixture by default.
/// The default GasMixture a map will have. Space mixture by default.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
[DataField]
public GasMixture Mixture = GasMixture.SpaceGas;
/// <summary>
/// Whether empty tiles will be considered space or not.
/// Whether empty tiles will be considered space or not.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite)]
[DataField]
public bool Space = true;
public SharedGasTileOverlaySystem.GasOverlayData Overlay;
@@ -0,0 +1,89 @@
using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations;
namespace Content.Shared.Atmos.EntitySystems;
public abstract partial class SharedAtmosphereSystem
{
/// <summary>
/// Merges a given <see cref="GasMixture"/> into this entity's containing <see cref="GasMixture"/>.
/// </summary>
/// <param name="entity">Entity who's containing <see cref="GasMixture"/>
/// we're merging a given <see cref="GasMixture"/> into.</param>
/// <param name="mixture">The gas <see cref="GasMixture"/>
/// we're merging into the containing <see cref="GasMixture"/></param>
/// <param name="ignoreExposed">Whether we should ignore non-tile <see cref="GasMixture"/>s.</param>
/// <param name="excite">Whether we should excite the gas upon merging.</param>
[PublicAPI]
public virtual void MergeContainingMixture(Entity<TransformComponent?> entity, GasMixture mixture, bool ignoreExposed = false, bool excite = false)
{
// Handled by server
}
/// <summary>
/// Merges a given gas <see cref="GasMixture"/> into this entity's tile <see cref="GasMixture"/>.
/// </summary>
/// <param name="entity">Entity who's containing <see cref="GasMixture"/>
/// we're merging a given <see cref="GasMixture"/> into.</param>
/// <param name="mixture">The gas <see cref="GasMixture"/>
/// we're merging into the containing <see cref="GasMixture"/>.</param>
/// <param name="excite">Whether we should excite the gas upon merging.</param>
[PublicAPI]
public virtual void MergeTileMixture(Entity<TransformComponent?> entity, GasMixture mixture, bool excite = false)
{
// Handled by server
}
/// <summary>
/// Adjusts a given gas in this entity's containing <see cref="GasMixture"/>.
/// </summary>
/// <param name="entity">Entity who's containing <see cref="GasMixture"/>
/// we're merging a given <see cref="GasMixture"/> into.</param>
/// <param name="gas">The gas in our given <see cref="GasMixture"/> we're adjusting the mols of.</param>
/// <param name="mols">The amount of mols we're adjusting the gas by.</param>
/// <param name="ignoreExposed">Whether we should ignore non-tile <see cref="GasMixture"/>s.</param>
/// <param name="excite">Whether we should excite the gas upon merging.</param>
[PublicAPI]
public virtual void AdjustContainingMixture(Entity<TransformComponent?> entity, Gas gas, float mols, bool ignoreExposed = false, bool excite = false)
{
// Handled by server
}
/// <summary>
/// Adjusts a given gas in this entity's tile <see cref="GasMixture"/>.
/// </summary>
/// <param name="entity">Entity who's containing <see cref="GasMixture"/>
/// we're merging a given <see cref="GasMixture"/> into.</param>
/// <param name="gas">The gas in our given <see cref="GasMixture"/> we're adjusting the mols of.</param>
/// <param name="mols">The amount of mols we're adjusting the gas by.</param>
/// <param name="excite">Whether we should excite the gas upon merging.</param>
[PublicAPI]
public virtual void AdjustTileMixture(Entity<TransformComponent?> entity, Gas gas, float mols, bool excite = false)
{
// Handled by server
}
/// <summary>
/// Tries to get the <see cref="GasMixture"/> of a containing entity (ex. lockers and cryopods),
/// does not return tile <see cref="GasMixture"/>s.
/// </summary>
/// <param name="entity">Exposed entity that is in some <see cref="GasMixture"/>.</param>
/// <param name="mixture">The found gas <see cref="GasMixture"/>.</param>
/// <returns>Returns true if this entity is in an exposed <see cref="GasMixture"/>, false otherwise.</returns>
[PublicAPI]
public bool TryGetExposedMixture(Entity<TransformComponent?> entity, [NotNullWhen(true)] out GasMixture? mixture)
{
mixture = null;
if (!Resolve(entity, ref entity.Comp) || entity.Comp.Anchored)
return false;
// TODO ATMOS: recursively iterate up through parents
// This really needs recursive InContainer metadata flag for performance
// And ideally some fast way to get the innermost airtight container.
var ev = new AtmosExposedGetAirEvent((entity, entity.Comp));
RaiseLocalEvent(entity, ref ev);
mixture = ev.Gas;
return ev.Handled;
}
}
@@ -1,5 +1,6 @@
using System.Runtime.CompilerServices;
using Content.Shared.Atmos.Prototypes;
using Content.Shared.Atmos.Reactions;
using Content.Shared.CCVar;
using JetBrains.Annotations;
@@ -59,7 +60,7 @@ public abstract partial class SharedAtmosphereSystem
{
var idx = (int)gas;
// Log an error if the corresponding prototype isn't found
if (!_prototypeManager.TryIndex<GasPrototype>(gas.ToString(), out var gasPrototype))
if (!ProtoMan.TryIndex<GasPrototype>(gas.ToString(), out var gasPrototype))
{
Log.Error($"Failed to find corresponding {nameof(GasPrototype)} for gas ID {(int)gas} ({gas}) with expected ID \"{gas.ToString()}\". Is your prototype named correctly?");
continue;
@@ -157,6 +158,67 @@ public abstract partial class SharedAtmosphereSystem
return applyScaling ? scale : scale * HeatScale;
}
/// <summary>
/// Calculates the thermal energy for a <see cref="GasMixture"/>.
/// </summary>
/// <param name="mixture">The <see cref="GasMixture"/> to calculate the thermal
/// energy of.</param>
/// <returns>The <see cref="GasMixture"/>'s thermal energy in joules.</returns>
[PublicAPI]
public float GetThermalEnergy(GasMixture mixture)
{
return mixture.Temperature * GetHeatCapacity(mixture);
}
/// <summary>
/// Calculates the thermal energy for a gas mixture,
/// using a provided cached heat capacity value.
/// </summary>
/// <param name="mixture">The <see cref="GasMixture"/> to calculate the thermal energy of.</param>
/// <param name="cachedHeatCapacity">A cached heat capacity value for the gas mixture,
/// to avoid redundant heat capacity calculations.</param>
/// <returns>The <see cref="GasMixture"/>'s thermal energy in joules.</returns>
[PublicAPI]
public float GetThermalEnergy(GasMixture mixture, float cachedHeatCapacity)
{
return mixture.Temperature * cachedHeatCapacity;
}
/// <summary>
/// Merges one <see cref="GasMixture"/> into another, modifying the receiver.
/// </summary>
/// <param name="receiver">The <see cref="GasMixture"/> to merge into. This will be modified.</param>
/// <param name="giver">The <see cref="GasMixture"/> to merge from. This will not be modified.</param>
[PublicAPI]
public void Merge(GasMixture receiver, GasMixture giver)
{
if (receiver.Immutable)
return;
if (MathF.Abs(receiver.Temperature - giver.Temperature) > Atmospherics.MinimumTemperatureDeltaToConsider)
{
var receiverHeatCapacity = GetHeatCapacity(receiver);
var giverHeatCapacity = GetHeatCapacity(giver);
var combinedHeatCapacity = receiverHeatCapacity + giverHeatCapacity;
if (combinedHeatCapacity > Atmospherics.MinimumHeatCapacity)
{
receiver.Temperature = (GetThermalEnergy(giver, giverHeatCapacity) + GetThermalEnergy(receiver, receiverHeatCapacity)) / combinedHeatCapacity;
}
}
NumericsHelpers.Add(receiver.Moles, giver.Moles);
}
/// <summary>
/// Performs reactions for a given gas mixture on an optional holder.
/// </summary>
/// <param name="mixture">The <see cref="GasMixture"/> to perform reactions on.</param>
/// <param name="holder"><see cref="IGasMixtureHolder"/> that holds the <see cref="GasMixture"/>.
/// used by Atmospherics to determine locality for certain reaction effects.</param>
/// <returns>The <see cref="ReactionResult"/> of the reactions performed.</returns>
[PublicAPI]
public abstract ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder);
/// <summary>
/// Gets the heat capacity for a <see cref="GasMixture"/>.
/// </summary>
@@ -1,34 +1,108 @@
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.Prototypes;
using Content.Shared.Body.Components;
using Content.Shared.Body.Systems;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
namespace Content.Shared.Atmos.EntitySystems
namespace Content.Shared.Atmos.EntitySystems;
public abstract partial class SharedAtmosphereSystem : EntitySystem
{
public abstract partial class SharedAtmosphereSystem : EntitySystem
[Dependency] private readonly IConfigurationManager _cfg = default!;
[Dependency] protected readonly IPrototypeManager ProtoMan = default!;
[Dependency] private readonly SharedInternalsSystem _internals = default!;
[Dependency] protected readonly SharedTransformSystem XformSystem = default!;
private EntityQuery<InternalsComponent> _internalsQuery;
/// <summary>
/// The length to pre-allocate list/dicts of delta pressure entities on a <see cref="GridAtmosphereComponent"/>.
/// </summary>
public const int DeltaPressurePreAllocateLength = 1000;
public override void Initialize()
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly SharedInternalsSystem _internals = default!;
[Dependency] private readonly IConfigurationManager _cfg = default!;
base.Initialize();
private EntityQuery<InternalsComponent> _internalsQuery;
_internalsQuery = GetEntityQuery<InternalsComponent>();
public override void Initialize()
{
base.Initialize();
_internalsQuery = GetEntityQuery<InternalsComponent>();
InitializeBreathTool();
InitializeGases();
InitializeCVars();
}
public GasPrototype GetGas(int gasId) => GasPrototypes[gasId];
public GasPrototype GetGas(Gas gasId) => GasPrototypes[(int) gasId];
public IEnumerable<GasPrototype> Gases => GasPrototypes;
InitializeBreathTool();
InitializeGases();
InitializeCVars();
}
/// <summary>
/// Gets the <see cref="GasPrototype"/> of a given gas ID.
/// </summary>
/// <param name="gasId">The gas ID to get the prototype of.</param>
/// <returns>The <see cref="GasPrototype"/> of the given gas ID.</returns>
public GasPrototype GetGas(int gasId)
{
return GasPrototypes[gasId];
}
/// <summary>
/// Gets the <see cref="GasPrototype"/> of a given gas ID.
/// </summary>
/// <param name="gasId">The gas ID to get the prototype of.</param>
/// <returns>The <see cref="GasPrototype"/> of the given gas ID.</returns>
public GasPrototype GetGas(Gas gasId)
{
return GasPrototypes[(int)gasId];
}
/// <summary>
/// Gets an enumerable of all the <see cref="GasPrototype"/>s.
/// </summary>
public IEnumerable<GasPrototype> Gases => GasPrototypes;
}
/// <summary>
/// Enum that represents the current processing state of a
/// <see cref="GridAtmosphereComponent"/>.
/// </summary>
public enum AtmosphereProcessingState : byte
{
Revalidate,
TileEqualize,
ActiveTiles,
ExcitedGroups,
HighPressureDelta,
DeltaPressure,
Hotspots,
Superconductivity,
PipeNet,
AtmosDevices,
NumStates,
}
/// <summary>
/// Data on the airtightness of a <see cref="TileAtmosphere"/>.
/// Cached on the <see cref="TileAtmosphere"/> and updated during
/// <see cref="AtmosphereProcessingState.Revalidate"/> if it was invalidated.
/// </summary>
/// <param name="BlockedDirections">The current directions blocked on this tile.
/// This is where air cannot flow to.</param>
/// <param name="NoAirWhenBlocked">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.</param>
/// <param name="FixVacuum">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.</param>
public readonly record struct AirtightData(
AtmosDirection BlockedDirections,
bool NoAirWhenBlocked,
bool FixVacuum);
/// <summary>
/// Struct that holds the result of delta pressure damage processing for an entity.
/// This is only created and enqueued when the entity needs to take damage.
/// </summary>
/// <param name="Ent">The entity to deal damage to.</param>
/// <param name="Pressure">The current absolute pressure the entity is experiencing.</param>
/// <param name="DeltaPressure">The current delta pressure the entity is experiencing.</param>
public readonly record struct DeltaPressureDamageResult(
Entity<DeltaPressureComponent> Ent,
float Pressure,
float DeltaPressure);
@@ -1,4 +1,4 @@
namespace Content.Server.Atmos;
namespace Content.Shared.Atmos;
/// <summary>
/// <para>Internal Atmospherics class that stores data about a group of <see cref="TileAtmosphere"/>s
@@ -1,4 +1,4 @@
namespace Content.Server.Atmos;
namespace Content.Shared.Atmos;
/// <summary>
/// Internal Atmospherics struct that stores data about a hotspot in a tile.
@@ -1,6 +1,4 @@
using Content.Shared.Atmos;
namespace Content.Server.Atmos;
namespace Content.Shared.Atmos;
/// <summary>
/// Atmospherics class that stores data on tiles for Monstermos calculations and operations.
@@ -1,5 +1,4 @@
using System.Globalization;
using Content.Shared.Atmos;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.Manager;
using Robust.Shared.Serialization.Markdown;
@@ -10,7 +9,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Generic;
using Robust.Shared.Serialization.TypeSerializers.Interfaces;
using Robust.Shared.Utility;
namespace Content.Server.Atmos.Serialization;
namespace Content.Shared.Atmos.Serialization;
public sealed partial class TileAtmosCollectionSerializer : ITypeSerializer<Dictionary<Vector2i, TileAtmosphere>, MappingDataNode>, ITypeCopier<Dictionary<Vector2i, TileAtmosphere>>
{
@@ -1,15 +1,14 @@
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Components;
using Content.Shared.Atmos.EntitySystems;
namespace Content.Server.Atmos;
namespace Content.Shared.Atmos;
/// <summary>
/// Internal Atmospherics class that stores data on an atmosphere in a single tile.
/// You should not be using these directly outside of <see cref="AtmosphereSystem"/>.
/// Use the public APIs in <see cref="AtmosphereSystem"/> instead.
/// You should not be using these directly outside of <see cref="SharedAtmosphereSystem"/>.
/// Use the public APIs in <see cref="SharedAtmosphereSystem"/> instead.
/// </summary>
[Access(typeof(AtmosphereSystem), typeof(GasTileOverlaySystem), typeof(AtmosDebugOverlaySystem))]
[Access(typeof(SharedAtmosphereSystem), typeof(SharedGasTileOverlaySystem), typeof(SharedAtmosDebugOverlaySystem))]
public sealed class TileAtmosphere : IGasMixtureHolder
{
/// <summary>
@@ -96,7 +95,7 @@ public sealed class TileAtmosphere : IGasMixtureHolder
/// Current <see cref="MonstermosInfo"/> information for this tile.
/// </summary>
[ViewVariables]
[Access(typeof(AtmosphereSystem), Other = AccessPermissions.ReadExecute)]
[Access(typeof(SharedAtmosphereSystem), Other = AccessPermissions.ReadExecute)]
public MonstermosInfo MonstermosInfo;
/// <summary>
@@ -122,7 +121,7 @@ public sealed class TileAtmosphere : IGasMixtureHolder
/// Grid entity this tile belongs to.
/// </summary>
[ViewVariables]
[Access(typeof(AtmosphereSystem))]
[Access(typeof(SharedAtmosphereSystem))]
public EntityUid GridIndex;
/// <summary>
@@ -142,7 +141,7 @@ public sealed class TileAtmosphere : IGasMixtureHolder
/// This can be immutable if the tile is spaced.
/// </summary>
[ViewVariables]
[Access(typeof(AtmosphereSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
[Access(typeof(SharedAtmosphereSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
public GasMixture? Air;
/// <summary>
@@ -202,7 +201,7 @@ public sealed class TileAtmosphere : IGasMixtureHolder
/// Cached information about airtight entities on this tile. This gets updated anytime a tile gets invalidated
/// (i.e., gets added to <see cref="GridAtmosphereComponent.InvalidatedCoords"/>).
/// </summary>
public AtmosphereSystem.AirtightData AirtightData;
public AirtightData AirtightData;
/// <summary>
/// Creates a new TileAtmosphere.
@@ -0,0 +1,11 @@
using Content.Shared.Atmos;
namespace Content.Shared.NodeContainer.NodeGroups;
public interface IPipeNet : INodeGroup, IGasMixtureHolder
{
/// <summary>
/// Causes gas in the PipeNet to react.
/// </summary>
void Update();
}