diff --git a/Content.Server/Atmos/Components/GridAtmosphereComponent.cs b/Content.Server/Atmos/Components/GridAtmosphereComponent.cs
index c03c52f252..9d606fe731 100644
--- a/Content.Server/Atmos/Components/GridAtmosphereComponent.cs
+++ b/Content.Server/Atmos/Components/GridAtmosphereComponent.cs
@@ -40,16 +40,10 @@ namespace Content.Server.Atmos.Components
internal GasTileOverlaySystem GasTileOverlaySystem { get; private set; } = default!;
public AtmosphereSystem AtmosphereSystem { get; private set; } = default!;
- ///
- /// Check current execution time every n instances processed.
- ///
- private const int LagCheckIterations = 30;
-
public override string Name => "GridAtmosphere";
- private bool _paused;
- private float _timer;
- private Stopwatch _stopwatch = new();
+ public bool ProcessingPaused { get; set; } = false;
+ public float Timer { get; set; }
private GridId _gridId;
[ComponentDependency] private IMapGridComponent? _mapGridComponent;
@@ -57,113 +51,74 @@ namespace Content.Server.Atmos.Components
public virtual bool Simulated => true;
[ViewVariables]
- public int UpdateCounter { get; private set; } = 0;
+ public int UpdateCounter { get; set; } = 0;
[ViewVariables]
- private double _tileEqualizeLastProcess;
+ public readonly HashSet ExcitedGroups = new(1000);
[ViewVariables]
- private readonly HashSet _excitedGroups = new(1000);
-
- [ViewVariables]
- private int ExcitedGroupCount => _excitedGroups.Count;
-
- [ViewVariables]
- private double _excitedGroupLastProcess;
+ public int ExcitedGroupCount => ExcitedGroups.Count;
[DataField("uniqueMixes")]
- private List? _uniqueMixes;
+ public List? UniqueMixes;
[DataField("tiles")]
- private Dictionary? _tiles;
+ public Dictionary? TilesUniqueMixes;
[ViewVariables]
- protected readonly Dictionary Tiles = new(1000);
+ public readonly Dictionary Tiles = new(1000);
[ViewVariables]
- private readonly HashSet _activeTiles = new(1000);
+ public readonly HashSet ActiveTiles = new(1000);
[ViewVariables]
- private int ActiveTilesCount => _activeTiles.Count;
+ public int ActiveTilesCount => ActiveTiles.Count;
[ViewVariables]
- private double _activeTilesLastProcess;
+ public readonly HashSet HotspotTiles = new(1000);
[ViewVariables]
- private readonly HashSet _hotspotTiles = new(1000);
+ public int HotspotTilesCount => HotspotTiles.Count;
[ViewVariables]
- private int HotspotTilesCount => _hotspotTiles.Count;
+ public readonly HashSet SuperconductivityTiles = new(1000);
[ViewVariables]
- private double _hotspotsLastProcess;
+ public int SuperconductivityTilesCount => SuperconductivityTiles.Count;
[ViewVariables]
- private readonly HashSet _superconductivityTiles = new(1000);
+ public readonly HashSet InvalidatedCoords = new(1000);
[ViewVariables]
- private int SuperconductivityTilesCount => _superconductivityTiles.Count;
+ public HashSet HighPressureDelta = new(1000);
[ViewVariables]
- private double _superconductivityLastProcess;
+ public int HighPressureDeltaCount => HighPressureDelta.Count;
[ViewVariables]
- private readonly HashSet _invalidatedCoords = new(1000);
+ public readonly HashSet PipeNets = new();
[ViewVariables]
- private int InvalidatedCoordsCount => _invalidatedCoords.Count;
+ public readonly HashSet AtmosDevices = new();
[ViewVariables]
- private HashSet _highPressureDelta = new(1000);
+ public Queue CurrentRunTiles = new();
[ViewVariables]
- private int HighPressureDeltaCount => _highPressureDelta.Count;
+ public Queue CurrentRunExcitedGroups = new();
[ViewVariables]
- private double _highPressureDeltaLastProcess;
+ public Queue CurrentRunPipeNet = new();
[ViewVariables]
- private readonly HashSet _pipeNets = new();
+ public Queue CurrentRunAtmosDevices = new();
[ViewVariables]
- private double _pipeNetLastProcess;
-
- [ViewVariables]
- private readonly HashSet _atmosDevices = new();
-
- [ViewVariables]
- private double _atmosDevicesLastProcess;
-
- [ViewVariables]
- private Queue _currentRunTiles = new();
-
- [ViewVariables]
- private Queue _currentRunExcitedGroups = new();
-
- [ViewVariables]
- private Queue _currentRunPipeNet = new();
-
- [ViewVariables]
- private Queue _currentRunAtmosDevices = new();
-
- [ViewVariables]
- private ProcessState _state = ProcessState.TileEqualize;
+ public AtmosphereProcessingState State { get; set; } = AtmosphereProcessingState.TileEqualize;
public GridAtmosphereComponent()
{
- _paused = false;
- }
-
- private enum ProcessState
- {
- TileEqualize,
- ActiveTiles,
- ExcitedGroups,
- HighPressureDelta,
- Hotspots,
- Superconductivity,
- PipeNet,
- AtmosDevices,
+ ProcessingPaused = false;
}
///
@@ -199,8 +154,8 @@ namespace Content.Server.Atmos.Components
if (uniqueMixes.Count == 0) uniqueMixes = null;
if (tiles.Count == 0) tiles = null;
- _uniqueMixes = uniqueMixes;
- _tiles = tiles;
+ UniqueMixes = uniqueMixes;
+ TilesUniqueMixes = tiles;
}
protected override void Initialize()
@@ -209,13 +164,13 @@ namespace Content.Server.Atmos.Components
Tiles.Clear();
- if (_tiles != null && Owner.TryGetComponent(out IMapGridComponent? mapGrid))
+ if (TilesUniqueMixes != null && Owner.TryGetComponent(out IMapGridComponent? mapGrid))
{
- foreach (var (indices, mix) in _tiles)
+ foreach (var (indices, mix) in TilesUniqueMixes)
{
try
{
- Tiles.Add(indices, new TileAtmosphere(this, mapGrid.GridIndex, indices, (GasMixture) _uniqueMixes![mix].Clone()));
+ Tiles.Add(indices, new TileAtmosphere(this, mapGrid.GridIndex, indices, (GasMixture) UniqueMixes![mix].Clone()));
}
catch (ArgumentOutOfRangeException)
{
@@ -264,12 +219,12 @@ namespace Content.Server.Atmos.Components
///
public virtual void Invalidate(Vector2i indices)
{
- _invalidatedCoords.Add(indices);
+ InvalidatedCoords.Add(indices);
}
- protected virtual void Revalidate()
+ public virtual void Revalidate()
{
- foreach (var indices in _invalidatedCoords)
+ foreach (var indices in InvalidatedCoords)
{
var tile = GetTile(indices);
@@ -341,7 +296,7 @@ namespace Content.Server.Atmos.Components
}
}
- _invalidatedCoords.Clear();
+ InvalidatedCoords.Clear();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -376,14 +331,14 @@ namespace Content.Server.Atmos.Components
{
if (tile?.GridIndex != _gridId || tile.Air == null) return;
tile.Excited = true;
- _activeTiles.Add(tile);
+ ActiveTiles.Add(tile);
}
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public virtual void RemoveActiveTile(TileAtmosphere tile, bool disposeGroup = true)
{
- _activeTiles.Remove(tile);
+ ActiveTiles.Remove(tile);
tile.Excited = false;
if(disposeGroup)
tile.ExcitedGroup?.Dispose();
@@ -396,25 +351,25 @@ namespace Content.Server.Atmos.Components
public virtual void AddHotspotTile(TileAtmosphere tile)
{
if (tile?.GridIndex != _gridId || tile?.Air == null) return;
- _hotspotTiles.Add(tile);
+ HotspotTiles.Add(tile);
}
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public virtual void RemoveHotspotTile(TileAtmosphere tile)
{
- _hotspotTiles.Remove(tile);
+ HotspotTiles.Remove(tile);
}
public virtual void AddSuperconductivityTile(TileAtmosphere tile)
{
if (tile?.GridIndex != _gridId || !AtmosphereSystem.Superconduction) return;
- _superconductivityTiles.Add(tile);
+ SuperconductivityTiles.Add(tile);
}
public virtual void RemoveSuperconductivityTile(TileAtmosphere tile)
{
- _superconductivityTiles.Remove(tile);
+ SuperconductivityTiles.Remove(tile);
}
///
@@ -422,48 +377,48 @@ namespace Content.Server.Atmos.Components
public virtual void AddHighPressureDelta(TileAtmosphere tile)
{
if (tile.GridIndex != _gridId) return;
- _highPressureDelta.Add(tile);
+ HighPressureDelta.Add(tile);
}
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public virtual bool HasHighPressureDelta(TileAtmosphere tile)
{
- return _highPressureDelta.Contains(tile);
+ return HighPressureDelta.Contains(tile);
}
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public virtual void AddExcitedGroup(ExcitedGroup excitedGroup)
{
- _excitedGroups.Add(excitedGroup);
+ ExcitedGroups.Add(excitedGroup);
}
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public virtual void RemoveExcitedGroup(ExcitedGroup excitedGroup)
{
- _excitedGroups.Remove(excitedGroup);
+ ExcitedGroups.Remove(excitedGroup);
}
public virtual void AddPipeNet(IPipeNet pipeNet)
{
- _pipeNets.Add(pipeNet);
+ PipeNets.Add(pipeNet);
}
public virtual void RemovePipeNet(IPipeNet pipeNet)
{
- _pipeNets.Remove(pipeNet);
+ PipeNets.Remove(pipeNet);
}
public virtual void AddAtmosDevice(AtmosDeviceComponent atmosDevice)
{
- _atmosDevices.Add(atmosDevice);
+ AtmosDevices.Add(atmosDevice);
}
public virtual void RemoveAtmosDevice(AtmosDeviceComponent atmosDevice)
{
- _atmosDevices.Remove(atmosDevice);
+ AtmosDevices.Remove(atmosDevice);
}
///
@@ -545,349 +500,6 @@ namespace Content.Server.Atmos.Components
return _mapGridComponent.Grid.TileSize * cellCount * Atmospherics.CellVolume;
}
- ///
- public virtual void Update(float frameTime)
- {
- _timer += frameTime;
- var atmosTime = 1f/AtmosphereSystem.AtmosTickRate;
-
- if (_invalidatedCoords.Count != 0)
- Revalidate();
-
- if (_timer < atmosTime)
- return;
-
- // We subtract it so it takes lost time into account.
- _timer -= atmosTime;
-
- var maxProcessTime = AtmosphereSystem.AtmosMaxProcessTime;
-
- switch (_state)
- {
- case ProcessState.TileEqualize:
- if (!ProcessTileEqualize(_paused, maxProcessTime))
- {
- _paused = true;
- return;
- }
-
- _paused = false;
- _state = ProcessState.ActiveTiles;
- return;
- case ProcessState.ActiveTiles:
- if (!ProcessActiveTiles(_paused, maxProcessTime))
- {
- _paused = true;
- return;
- }
-
- _paused = false;
- _state = ProcessState.ExcitedGroups;
- return;
- case ProcessState.ExcitedGroups:
- if (!ProcessExcitedGroups(_paused, maxProcessTime))
- {
- _paused = true;
- return;
- }
-
- _paused = false;
- _state = ProcessState.HighPressureDelta;
- return;
- case ProcessState.HighPressureDelta:
- if (!ProcessHighPressureDelta(_paused, maxProcessTime))
- {
- _paused = true;
- return;
- }
-
- _paused = false;
- _state = ProcessState.Hotspots;
- break;
- case ProcessState.Hotspots:
- if (!ProcessHotspots(_paused, maxProcessTime))
- {
- _paused = true;
- return;
- }
-
- _paused = false;
- // Next state depends on whether superconduction is enabled or not.
- // Note: We do this here instead of on the tile equalization step to prevent ending it early.
- // Therefore, a change to this CVar might only be applied after that step is over.
- _state = AtmosphereSystem.Superconduction ? ProcessState.Superconductivity : ProcessState.PipeNet;
- break;
- case ProcessState.Superconductivity:
- if (!ProcessSuperconductivity(_paused, maxProcessTime))
- {
- _paused = true;
- return;
- }
-
- _paused = false;
- _state = ProcessState.PipeNet;
- break;
- case ProcessState.PipeNet:
- if (!ProcessPipeNets(_paused, maxProcessTime))
- {
- _paused = true;
- return;
- }
-
- _paused = false;
- _state = ProcessState.AtmosDevices;
- break;
- case ProcessState.AtmosDevices:
- if (!ProcessAtmosDevices(_paused, maxProcessTime))
- {
- _paused = true;
- return;
- }
-
- _paused = false;
- // Next state depends on whether monstermos equalization is enabled or not.
- // Note: We do this here instead of on the tile equalization step to prevent ending it early.
- // Therefore, a change to this CVar might only be applied after that step is over.
- _state = AtmosphereSystem.MonstermosEqualization ? ProcessState.TileEqualize : ProcessState.ActiveTiles;
- break;
- }
-
- UpdateCounter++;
- }
-
- public virtual bool ProcessTileEqualize(bool resumed = false, float lagCheck = 5f)
- {
- _stopwatch.Restart();
-
- if(!resumed)
- _currentRunTiles = new Queue(_activeTiles);
-
- var number = 0;
- while (_currentRunTiles.Count > 0)
- {
- var tile = _currentRunTiles.Dequeue();
- tile.EqualizePressureInZone(UpdateCounter);
-
- if (number++ < LagCheckIterations) continue;
- number = 0;
- // Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
- {
- _tileEqualizeLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return false;
- }
- }
-
- _tileEqualizeLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return true;
- }
-
- public virtual bool ProcessActiveTiles(bool resumed = false, float lagCheck = 5f)
- {
- _stopwatch.Restart();
-
- var spaceWind = AtmosphereSystem.SpaceWind;
-
- if(!resumed)
- _currentRunTiles = new Queue(_activeTiles);
-
- var number = 0;
- while (_currentRunTiles.Count > 0)
- {
- var tile = _currentRunTiles.Dequeue();
- tile.ProcessCell(UpdateCounter, spaceWind);
-
- if (number++ < LagCheckIterations) continue;
- number = 0;
- // Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
- {
- _activeTilesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return false;
- }
- }
-
- _activeTilesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return true;
- }
-
- public virtual bool ProcessExcitedGroups(bool resumed = false, float lagCheck = 5f)
- {
- _stopwatch.Restart();
-
- var spaceIsAllConsuming = AtmosphereSystem.ExcitedGroupsSpaceIsAllConsuming;
-
- if(!resumed)
- _currentRunExcitedGroups = new Queue(_excitedGroups);
-
- var number = 0;
- while (_currentRunExcitedGroups.Count > 0)
- {
- var excitedGroup = _currentRunExcitedGroups.Dequeue();
- excitedGroup.BreakdownCooldown++;
- excitedGroup.DismantleCooldown++;
-
- if(excitedGroup.BreakdownCooldown > Atmospherics.ExcitedGroupBreakdownCycles)
- excitedGroup.SelfBreakdown(spaceIsAllConsuming);
-
- else if(excitedGroup.DismantleCooldown > Atmospherics.ExcitedGroupsDismantleCycles)
- excitedGroup.Dismantle();
-
- if (number++ < LagCheckIterations) continue;
- number = 0;
- // Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
- {
- _excitedGroupLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return false;
- }
- }
-
- _excitedGroupLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return true;
- }
-
- public virtual bool ProcessHighPressureDelta(bool resumed = false, float lagCheck = 5f)
- {
- _stopwatch.Restart();
-
- if(!resumed)
- _currentRunTiles = new Queue(_highPressureDelta);
-
- var number = 0;
- while (_currentRunTiles.Count > 0)
- {
- var tile = _currentRunTiles.Dequeue();
- tile.HighPressureMovements();
- tile.PressureDifference = 0f;
- tile.PressureSpecificTarget = null;
- _highPressureDelta.Remove(tile);
-
- if (number++ < LagCheckIterations) continue;
- number = 0;
- // Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
- {
- _highPressureDeltaLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return false;
- }
- }
-
- _highPressureDeltaLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return true;
- }
-
- protected virtual bool ProcessHotspots(bool resumed = false, float lagCheck = 5f)
- {
- _stopwatch.Restart();
-
- if(!resumed)
- _currentRunTiles = new Queue(_hotspotTiles);
-
- var number = 0;
- while (_currentRunTiles.Count > 0)
- {
- var hotspot = _currentRunTiles.Dequeue();
- hotspot.ProcessHotspot();
-
- if (number++ < LagCheckIterations) continue;
- number = 0;
- // Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
- {
- _hotspotsLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return false;
- }
- }
-
- _hotspotsLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return true;
- }
-
- protected virtual bool ProcessSuperconductivity(bool resumed = false, float lagCheck = 5f)
- {
- _stopwatch.Restart();
-
- if(!resumed)
- _currentRunTiles = new Queue(_superconductivityTiles);
-
- var number = 0;
- while (_currentRunTiles.Count > 0)
- {
- var superconductivity = _currentRunTiles.Dequeue();
- superconductivity.Superconduct();
-
- if (number++ < LagCheckIterations) continue;
- number = 0;
- // Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
- {
- _superconductivityLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return false;
- }
- }
-
- _superconductivityLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return true;
- }
-
- protected virtual bool ProcessPipeNets(bool resumed = false, float lagCheck = 5f)
- {
- _stopwatch.Restart();
-
- if(!resumed)
- _currentRunPipeNet = new Queue(_pipeNets);
-
- var number = 0;
- while (_currentRunPipeNet.Count > 0)
- {
- var pipenet = _currentRunPipeNet.Dequeue();
- pipenet.Update();
-
- if (number++ < LagCheckIterations) continue;
- number = 0;
- // Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
- {
- _pipeNetLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return false;
- }
- }
-
- _pipeNetLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return true;
- }
-
- protected virtual bool ProcessAtmosDevices(bool resumed = false, float lagCheck = 5f)
- {
- _stopwatch.Restart();
-
- if(!resumed)
- _currentRunAtmosDevices = new Queue(_atmosDevices);
-
- var time = _gameTiming.CurTime;
- var updateEvent = new AtmosDeviceUpdateEvent(this);
- var number = 0;
- while (_currentRunAtmosDevices.Count > 0)
- {
- var device = _currentRunAtmosDevices.Dequeue();
- Owner.EntityManager.EventBus.RaiseLocalEvent(device.Owner.Uid, updateEvent, false);
- device.LastProcess = time;
-
- if (number++ < LagCheckIterations) continue;
- number = 0;
- // Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
- {
- _atmosDevicesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return false;
- }
- }
-
- _atmosDevicesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
- return true;
- }
-
protected virtual IEnumerable GetObstructingComponents(Vector2i indices)
{
var gridLookup = EntitySystem.Get();
diff --git a/Content.Server/Atmos/Components/IGridAtmosphereComponent.cs b/Content.Server/Atmos/Components/IGridAtmosphereComponent.cs
index 6e6735475e..e82e0a75b1 100644
--- a/Content.Server/Atmos/Components/IGridAtmosphereComponent.cs
+++ b/Content.Server/Atmos/Components/IGridAtmosphereComponent.cs
@@ -171,8 +171,6 @@ namespace Content.Server.Atmos.Components
///
Dictionary GetAdjacentTiles(Vector2i indices, bool includeAirBlocked = false);
- void Update(float frameTime);
-
void AddPipeNet(IPipeNet pipeNet);
void RemovePipeNet(IPipeNet pipeNet);
diff --git a/Content.Server/Atmos/Components/UnsimulatedGridAtmosphereComponent.cs b/Content.Server/Atmos/Components/UnsimulatedGridAtmosphereComponent.cs
index c59ffa486c..090f506902 100644
--- a/Content.Server/Atmos/Components/UnsimulatedGridAtmosphereComponent.cs
+++ b/Content.Server/Atmos/Components/UnsimulatedGridAtmosphereComponent.cs
@@ -33,7 +33,7 @@ namespace Content.Server.Atmos.Components
public override void Invalidate(Vector2i indices) { }
- protected override void Revalidate() { }
+ public override void Revalidate() { }
public override void FixVacuum(Vector2i indices) { }
@@ -67,47 +67,5 @@ namespace Content.Server.Atmos.Components
public override void AddAtmosDevice(AtmosDeviceComponent atmosDevice) { }
public override void RemoveAtmosDevice(AtmosDeviceComponent atmosDevice) { }
-
- public override void Update(float frameTime) { }
-
- public override bool ProcessTileEqualize(bool resumed = false, float lagCheck = 5f)
- {
- return false;
- }
-
- public override bool ProcessActiveTiles(bool resumed = false, float lagCheck = 5f)
- {
- return false;
- }
-
- public override bool ProcessExcitedGroups(bool resumed = false, float lagCheck = 5f)
- {
- return false;
- }
-
- public override bool ProcessHighPressureDelta(bool resumed = false, float lagCheck = 5f)
- {
- return false;
- }
-
- protected override bool ProcessHotspots(bool resumed = false, float lagCheck = 5f)
- {
- return false;
- }
-
- protected override bool ProcessSuperconductivity(bool resumed = false, float lagCheck = 5f)
- {
- return false;
- }
-
- protected override bool ProcessPipeNets(bool resumed = false, float lagCheck = 5f)
- {
- return false;
- }
-
- protected override bool ProcessAtmosDevices(bool resumed = false, float lagCheck = 5f)
- {
- return false;
- }
}
}
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.CVars.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.CVars.cs
index 2c8e0de6ac..f2baf06066 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.CVars.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.CVars.cs
@@ -10,6 +10,7 @@ namespace Content.Server.Atmos.EntitySystems
public bool ExcitedGroupsSpaceIsAllConsuming { get; private set; }
public float AtmosMaxProcessTime { get; private set; }
public float AtmosTickRate { get; private set; }
+ public float AtmosTime => 1f / AtmosTickRate;
private void InitializeCVars()
{
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs
new file mode 100644
index 0000000000..b9ece658f6
--- /dev/null
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs
@@ -0,0 +1,365 @@
+using System.Collections.Generic;
+using Content.Server.Atmos.Components;
+using Content.Server.Atmos.Piping.Components;
+using Content.Server.NodeContainer.NodeGroups;
+using Content.Shared.Atmos;
+using Robust.Shared.GameObjects;
+using Robust.Shared.IoC;
+using Robust.Shared.Timing;
+
+namespace Content.Server.Atmos.EntitySystems
+{
+ public partial class AtmosphereSystem
+ {
+ [Dependency] private readonly IGameTiming _gameTiming = default!;
+
+ private readonly Stopwatch _simulationStopwatch = new();
+
+ ///
+ /// Check current execution time every n instances processed.
+ ///
+ private const int LagCheckIterations = 30;
+
+ private int _currentRunAtmosphereIndex = 0;
+ private bool _simulationPaused = false;
+
+ private readonly List _currentRunAtmosphere = new();
+
+ private bool ProcessTileEqualize(GridAtmosphereComponent atmosphere)
+ {
+ if(!atmosphere.ProcessingPaused)
+ atmosphere.CurrentRunTiles = new Queue(atmosphere.ActiveTiles);
+
+ var number = 0;
+ while (atmosphere.CurrentRunTiles.TryDequeue(out var tile))
+ {
+ tile.EqualizePressureInZone(atmosphere.UpdateCounter);
+
+ if (number++ < LagCheckIterations) continue;
+ number = 0;
+ // Process the rest next time.
+ if (_simulationStopwatch.Elapsed.TotalMilliseconds >= AtmosMaxProcessTime)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private bool ProcessActiveTiles(GridAtmosphereComponent atmosphere)
+ {
+ if(!atmosphere.ProcessingPaused)
+ atmosphere.CurrentRunTiles = new Queue(atmosphere.ActiveTiles);
+
+ var number = 0;
+ while (atmosphere.CurrentRunTiles.TryDequeue(out var tile))
+ {
+ tile.ProcessCell(atmosphere.UpdateCounter, SpaceWind);
+
+ if (number++ < LagCheckIterations) continue;
+ number = 0;
+ // Process the rest next time.
+ if (_simulationStopwatch.Elapsed.TotalMilliseconds >= AtmosMaxProcessTime)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private bool ProcessExcitedGroups(GridAtmosphereComponent atmosphere)
+ {
+ if(!atmosphere.ProcessingPaused)
+ atmosphere.CurrentRunExcitedGroups = new Queue(atmosphere.ExcitedGroups);
+
+ var number = 0;
+ while (atmosphere.CurrentRunExcitedGroups.TryDequeue(out var excitedGroup))
+ {
+ excitedGroup.BreakdownCooldown++;
+ excitedGroup.DismantleCooldown++;
+
+ if(excitedGroup.BreakdownCooldown > Atmospherics.ExcitedGroupBreakdownCycles)
+ excitedGroup.SelfBreakdown(ExcitedGroupsSpaceIsAllConsuming);
+
+ else if(excitedGroup.DismantleCooldown > Atmospherics.ExcitedGroupsDismantleCycles)
+ excitedGroup.Dismantle();
+
+ if (number++ < LagCheckIterations) continue;
+ number = 0;
+ // Process the rest next time.
+ if (_simulationStopwatch.Elapsed.TotalMilliseconds >= AtmosMaxProcessTime)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private bool ProcessHighPressureDelta(GridAtmosphereComponent atmosphere)
+ {
+ if(!atmosphere.ProcessingPaused)
+ atmosphere.CurrentRunTiles = new Queue(atmosphere.HighPressureDelta);
+
+ var number = 0;
+ while (atmosphere.CurrentRunTiles.TryDequeue(out var tile))
+ {
+ tile.HighPressureMovements();
+ tile.PressureDifference = 0f;
+ tile.PressureSpecificTarget = null;
+ atmosphere.HighPressureDelta.Remove(tile);
+
+ if (number++ < LagCheckIterations) continue;
+ number = 0;
+ // Process the rest next time.
+ if (_simulationStopwatch.Elapsed.TotalMilliseconds >= AtmosMaxProcessTime)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private bool ProcessHotspots(GridAtmosphereComponent atmosphere)
+ {
+ if(!atmosphere.ProcessingPaused)
+ atmosphere.CurrentRunTiles = new Queue(atmosphere.HotspotTiles);
+
+ var number = 0;
+ while (atmosphere.CurrentRunTiles.TryDequeue(out var hotspot))
+ {
+ hotspot.ProcessHotspot();
+
+ if (number++ < LagCheckIterations) continue;
+ number = 0;
+ // Process the rest next time.
+ if (_simulationStopwatch.Elapsed.TotalMilliseconds >= AtmosMaxProcessTime)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private bool ProcessSuperconductivity(GridAtmosphereComponent atmosphere)
+ {
+ if(!atmosphere.ProcessingPaused)
+ atmosphere.CurrentRunTiles = new Queue(atmosphere.SuperconductivityTiles);
+
+ var number = 0;
+ while (atmosphere.CurrentRunTiles.TryDequeue(out var superconductivity))
+ {
+ superconductivity.Superconduct();
+
+ if (number++ < LagCheckIterations) continue;
+ number = 0;
+ // Process the rest next time.
+ if (_simulationStopwatch.Elapsed.TotalMilliseconds >= AtmosMaxProcessTime)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private bool ProcessPipeNets(GridAtmosphereComponent atmosphere)
+ {
+ if(!atmosphere.ProcessingPaused)
+ atmosphere.CurrentRunPipeNet = new Queue(atmosphere.PipeNets);
+
+ var number = 0;
+ while (atmosphere.CurrentRunPipeNet.TryDequeue(out var pipenet))
+ {
+ pipenet.Update();
+
+ if (number++ < LagCheckIterations) continue;
+ number = 0;
+ // Process the rest next time.
+ if (_simulationStopwatch.Elapsed.TotalMilliseconds >= AtmosMaxProcessTime)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private bool ProcessAtmosDevices(GridAtmosphereComponent atmosphere)
+ {
+ if(!atmosphere.ProcessingPaused)
+ atmosphere.CurrentRunAtmosDevices = new Queue(atmosphere.AtmosDevices);
+
+ var time = _gameTiming.CurTime;
+ var updateEvent = new AtmosDeviceUpdateEvent(atmosphere);
+ var number = 0;
+ while (atmosphere.CurrentRunAtmosDevices.TryDequeue(out var device))
+ {
+ EntityManager.EventBus.RaiseLocalEvent(device.Owner.Uid, updateEvent, false);
+ device.LastProcess = time;
+
+ if (number++ < LagCheckIterations) continue;
+ number = 0;
+ // Process the rest next time.
+ if (_simulationStopwatch.Elapsed.TotalMilliseconds >= AtmosMaxProcessTime)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void UpdateProcessing(float frameTime)
+ {
+ _simulationStopwatch.Restart();
+
+ if (!_simulationPaused)
+ {
+ _currentRunAtmosphereIndex = 0;
+ _currentRunAtmosphere.Clear();
+ _currentRunAtmosphere.AddRange(ComponentManager.EntityQuery());
+ }
+
+ // We set this to true just in case we have to stop processing due to time constraints.
+ _simulationPaused = true;
+
+ for (; _currentRunAtmosphereIndex < _currentRunAtmosphere.Count; _currentRunAtmosphereIndex++)
+ {
+ var atmosphere = _currentRunAtmosphere[_currentRunAtmosphereIndex];
+
+ if (atmosphere.Paused || atmosphere.LifeStage >= ComponentLifeStage.Stopping)
+ continue;
+
+ atmosphere.Timer += frameTime;
+
+ if (atmosphere.InvalidatedCoords.Count != 0)
+ atmosphere.Revalidate();
+
+ if (atmosphere.Timer < AtmosTime)
+ continue;
+
+ // We subtract it so it takes lost time into account.
+ atmosphere.Timer -= AtmosTime;
+
+ switch (atmosphere.State)
+ {
+ case AtmosphereProcessingState.TileEqualize:
+ if (!ProcessTileEqualize(atmosphere))
+ {
+ atmosphere.ProcessingPaused = true;
+ return;
+ }
+
+ atmosphere.ProcessingPaused = false;
+ atmosphere.State = AtmosphereProcessingState.ActiveTiles;
+ continue;
+ case AtmosphereProcessingState.ActiveTiles:
+ if (!ProcessActiveTiles(atmosphere))
+ {
+ atmosphere.ProcessingPaused = true;
+ return;
+ }
+
+ atmosphere.ProcessingPaused = false;
+ atmosphere.State = AtmosphereProcessingState.ExcitedGroups;
+ continue;
+ case AtmosphereProcessingState.ExcitedGroups:
+ if (!ProcessExcitedGroups(atmosphere))
+ {
+ atmosphere.ProcessingPaused = true;
+ return;
+ }
+
+ atmosphere.ProcessingPaused = false;
+ atmosphere.State = AtmosphereProcessingState.HighPressureDelta;
+ continue;
+ case AtmosphereProcessingState.HighPressureDelta:
+ if (!ProcessHighPressureDelta(atmosphere))
+ {
+ atmosphere.ProcessingPaused = true;
+ return;
+ }
+
+ atmosphere.ProcessingPaused = false;
+ atmosphere.State = AtmosphereProcessingState.Hotspots;
+ continue;
+ case AtmosphereProcessingState.Hotspots:
+ if (!ProcessHotspots(atmosphere))
+ {
+ atmosphere.ProcessingPaused = true;
+ return;
+ }
+
+ atmosphere.ProcessingPaused = false;
+ // Next state depends on whether superconduction is enabled or not.
+ // Note: We do this here instead of on the tile equalization step to prevent ending it early.
+ // Therefore, a change to this CVar might only be applied after that step is over.
+ atmosphere.State = Superconduction
+ ? AtmosphereProcessingState.Superconductivity
+ : AtmosphereProcessingState.PipeNet;
+ continue;
+ case AtmosphereProcessingState.Superconductivity:
+ if (!ProcessSuperconductivity(atmosphere))
+ {
+ atmosphere.ProcessingPaused = true;
+ return;
+ }
+
+ atmosphere.ProcessingPaused = false;
+ atmosphere.State = AtmosphereProcessingState.PipeNet;
+ continue;
+ case AtmosphereProcessingState.PipeNet:
+ if (!ProcessPipeNets(atmosphere))
+ {
+ atmosphere.ProcessingPaused = true;
+ return;
+ }
+
+ atmosphere.ProcessingPaused = false;
+ atmosphere.State = AtmosphereProcessingState.AtmosDevices;
+ continue;
+ case AtmosphereProcessingState.AtmosDevices:
+ if (!ProcessAtmosDevices(atmosphere))
+ {
+ atmosphere.ProcessingPaused = true;
+ return;
+ }
+
+ atmosphere.ProcessingPaused = false;
+ // Next state depends on whether monstermos equalization is enabled or not.
+ // Note: We do this here instead of on the tile equalization step to prevent ending it early.
+ // Therefore, a change to this CVar might only be applied after that step is over.
+ atmosphere.State = MonstermosEqualization
+ ? AtmosphereProcessingState.TileEqualize
+ : AtmosphereProcessingState.ActiveTiles;
+
+ // We reached the end of this atmosphere's update tick. Break out of the switch.
+ break;
+ }
+
+ // And increase the update counter.
+ atmosphere.UpdateCounter++;
+ }
+
+ // We finished processing all atmospheres successfully, therefore we won't be paused next tick.
+ _simulationPaused = false;
+ }
+ }
+
+ public enum AtmosphereProcessingState : byte
+ {
+ TileEqualize,
+ ActiveTiles,
+ ExcitedGroups,
+ HighPressureDelta,
+ Hotspots,
+ Superconductivity,
+ PipeNet,
+ AtmosDevices,
+ }
+}
diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs
index cb0f5d3234..6268319e0d 100644
--- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs
+++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs
@@ -149,15 +149,10 @@ namespace Content.Server.Atmos.EntitySystems
{
base.Update(frameTime);
+ UpdateProcessing(frameTime);
+
_exposedTimer += frameTime;
- foreach (var (mapGridComponent, gridAtmosphereComponent) in EntityManager.ComponentManager.EntityQuery(true))
- {
- if (_pauseManager.IsGridPaused(mapGridComponent.GridIndex)) continue;
-
- gridAtmosphereComponent.Update(frameTime);
- }
-
if (_exposedTimer >= ExposedUpdateDelay)
{
foreach (var exposed in EntityManager.ComponentManager.EntityQuery(true))
@@ -167,7 +162,7 @@ namespace Content.Server.Atmos.EntitySystems
exposed.Update(tile, _exposedTimer);
}
- _exposedTimer = 0;
+ _exposedTimer -= ExposedUpdateDelay;
}
}
}