diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs
index c268521d8e..aa71837fdc 100644
--- a/Content.Server/Atmos/TileAtmosphere.cs
+++ b/Content.Server/Atmos/TileAtmosphere.cs
@@ -636,7 +636,7 @@ namespace Content.Server.Atmos
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ProcessCell(int fireCount)
+ public void ProcessCell(int fireCount, bool spaceWind = true)
{
// Can't process a tile without air
if (Air == null)
@@ -708,14 +708,16 @@ namespace Content.Server.Atmos
{
var difference = Air.Share(enemyTile.Air, adjacentTileLength);
- // Space wind!
- if (difference > 0)
+ if (spaceWind)
{
- ConsiderPressureDifference(enemyTile, difference);
- }
- else
- {
- enemyTile.ConsiderPressureDifference(this, -difference);
+ if (difference > 0)
+ {
+ ConsiderPressureDifference(enemyTile, difference);
+ }
+ else
+ {
+ enemyTile.ConsiderPressureDifference(this, -difference);
+ }
}
LastShareCheck();
diff --git a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs
index b18fb84f90..0b2202cef8 100644
--- a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs
+++ b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs
@@ -9,6 +9,7 @@ using Content.Server.GameObjects.Components.Atmos.Piping;
using Content.Server.GameObjects.Components.NodeContainer.NodeGroups;
using Content.Server.GameObjects.EntitySystems;
using Content.Server.GameObjects.EntitySystems.Atmos;
+using Content.Shared;
using Content.Shared.Atmos;
using Content.Shared.Maps;
using Robust.Server.GameObjects.EntitySystems.TileLookup;
@@ -16,10 +17,9 @@ using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.ComponentDependencies;
using Robust.Shared.GameObjects.Components.Map;
-using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.GameObjects.Systems;
+using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.Interfaces.Map;
-using Robust.Shared.IoC;
using Robust.Shared.Log;
using Robust.Shared.Map;
using Robust.Shared.Maths;
@@ -49,16 +49,6 @@ namespace Content.Server.GameObjects.Components.Atmos
///
private const int LagCheckIterations = 30;
- ///
- /// Max milliseconds allowed for atmos updates.
- ///
- private const float LagCheckMaxMilliseconds = 5f;
-
- ///
- /// How much time before atmos updates are ran.
- ///
- private const float AtmosTime = 1/26f;
-
public override string Name => "GridAtmosphere";
private bool _paused = false;
@@ -256,7 +246,12 @@ namespace Content.Server.GameObjects.Components.Atmos
tile.Air ??= new GasMixture(GetVolumeForCells(1), AtmosphereSystem){Temperature = Atmospherics.T20C};
}
+ // By removing the active tile, we effectively remove its excited group, if any.
+ RemoveActiveTile(tile);
+
+ // Then we activate the tile again.
AddActiveTile(tile);
+
tile.BlockedAirflow = GetBlockedDirections(indices);
// TODO ATMOS: Query all the contents of this tile (like walls) and calculate the correct thermal conductivity
@@ -478,20 +473,23 @@ namespace Content.Server.GameObjects.Components.Atmos
public virtual void Update(float frameTime)
{
_timer += frameTime;
+ var atmosTime = 1f/AtmosphereSystem.AtmosTickRate;
if (_invalidatedCoords.Count != 0)
Revalidate();
- if (_timer < AtmosTime)
+ if (_timer < atmosTime)
return;
// We subtract it so it takes lost time into account.
- _timer -= AtmosTime;
+ _timer -= atmosTime;
+
+ var maxProcessTime = AtmosphereSystem.AtmosMaxProcessTime;
switch (_state)
{
case ProcessState.TileEqualize:
- if (!ProcessTileEqualize(_paused))
+ if (!ProcessTileEqualize(_paused, maxProcessTime))
{
_paused = true;
return;
@@ -501,7 +499,7 @@ namespace Content.Server.GameObjects.Components.Atmos
_state = ProcessState.ActiveTiles;
return;
case ProcessState.ActiveTiles:
- if (!ProcessActiveTiles(_paused))
+ if (!ProcessActiveTiles(_paused, maxProcessTime))
{
_paused = true;
return;
@@ -511,7 +509,7 @@ namespace Content.Server.GameObjects.Components.Atmos
_state = ProcessState.ExcitedGroups;
return;
case ProcessState.ExcitedGroups:
- if (!ProcessExcitedGroups(_paused))
+ if (!ProcessExcitedGroups(_paused, maxProcessTime))
{
_paused = true;
return;
@@ -521,7 +519,7 @@ namespace Content.Server.GameObjects.Components.Atmos
_state = ProcessState.HighPressureDelta;
return;
case ProcessState.HighPressureDelta:
- if (!ProcessHighPressureDelta(_paused))
+ if (!ProcessHighPressureDelta(_paused, maxProcessTime))
{
_paused = true;
return;
@@ -531,7 +529,7 @@ namespace Content.Server.GameObjects.Components.Atmos
_state = ProcessState.Hotspots;
break;
case ProcessState.Hotspots:
- if (!ProcessHotspots(_paused))
+ if (!ProcessHotspots(_paused, maxProcessTime))
{
_paused = true;
return;
@@ -541,7 +539,7 @@ namespace Content.Server.GameObjects.Components.Atmos
_state = ProcessState.Superconductivity;
break;
case ProcessState.Superconductivity:
- if (!ProcessSuperconductivity(_paused))
+ if (!ProcessSuperconductivity(_paused, maxProcessTime))
{
_paused = true;
return;
@@ -551,7 +549,7 @@ namespace Content.Server.GameObjects.Components.Atmos
_state = ProcessState.PipeNet;
break;
case ProcessState.PipeNet:
- if (!ProcessPipeNets(_paused))
+ if (!ProcessPipeNets(_paused, maxProcessTime))
{
_paused = true;
return;
@@ -561,21 +559,24 @@ namespace Content.Server.GameObjects.Components.Atmos
_state = ProcessState.PipeNetDevices;
break;
case ProcessState.PipeNetDevices:
- if (!ProcessPipeNetDevices(_paused))
+ if (!ProcessPipeNetDevices(_paused, maxProcessTime))
{
_paused = true;
return;
}
_paused = false;
- _state = ProcessState.TileEqualize;
+ // 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)
+ public virtual bool ProcessTileEqualize(bool resumed = false, float lagCheck = 5f)
{
_stopwatch.Restart();
@@ -591,7 +592,7 @@ namespace Content.Server.GameObjects.Components.Atmos
if (number++ < LagCheckIterations) continue;
number = 0;
// Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
+ if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
{
_tileEqualizeLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
return false;
@@ -602,10 +603,12 @@ namespace Content.Server.GameObjects.Components.Atmos
return true;
}
- public virtual bool ProcessActiveTiles(bool resumed = false)
+ public virtual bool ProcessActiveTiles(bool resumed = false, float lagCheck = 5f)
{
_stopwatch.Restart();
+ var spaceWind = AtmosphereSystem.SpaceWind;
+
if(!resumed)
_currentRunTiles = new Queue(_activeTiles);
@@ -613,12 +616,12 @@ namespace Content.Server.GameObjects.Components.Atmos
while (_currentRunTiles.Count > 0)
{
var tile = _currentRunTiles.Dequeue();
- tile.ProcessCell(UpdateCounter);
+ tile.ProcessCell(UpdateCounter, spaceWind);
if (number++ < LagCheckIterations) continue;
number = 0;
// Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
+ if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
{
_activeTilesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
return false;
@@ -629,10 +632,12 @@ namespace Content.Server.GameObjects.Components.Atmos
return true;
}
- public virtual bool ProcessExcitedGroups(bool resumed = false)
+ public virtual bool ProcessExcitedGroups(bool resumed = false, float lagCheck = 5f)
{
_stopwatch.Restart();
+ var spaceIsAllConsuming = AtmosphereSystem.ExcitedGroupsSpaceIsAllConsuming;
+
if(!resumed)
_currentRunExcitedGroups = new Queue(_excitedGroups);
@@ -644,7 +649,7 @@ namespace Content.Server.GameObjects.Components.Atmos
excitedGroup.DismantleCooldown++;
if(excitedGroup.BreakdownCooldown > Atmospherics.ExcitedGroupBreakdownCycles)
- excitedGroup.SelfBreakdown();
+ excitedGroup.SelfBreakdown(spaceIsAllConsuming);
else if(excitedGroup.DismantleCooldown > Atmospherics.ExcitedGroupsDismantleCycles)
excitedGroup.Dismantle();
@@ -652,7 +657,7 @@ namespace Content.Server.GameObjects.Components.Atmos
if (number++ < LagCheckIterations) continue;
number = 0;
// Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
+ if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
{
_excitedGroupLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
return false;
@@ -663,7 +668,7 @@ namespace Content.Server.GameObjects.Components.Atmos
return true;
}
- public virtual bool ProcessHighPressureDelta(bool resumed = false)
+ public virtual bool ProcessHighPressureDelta(bool resumed = false, float lagCheck = 5f)
{
_stopwatch.Restart();
@@ -682,7 +687,7 @@ namespace Content.Server.GameObjects.Components.Atmos
if (number++ < LagCheckIterations) continue;
number = 0;
// Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
+ if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
{
_highPressureDeltaLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
return false;
@@ -693,7 +698,7 @@ namespace Content.Server.GameObjects.Components.Atmos
return true;
}
- protected virtual bool ProcessHotspots(bool resumed = false)
+ protected virtual bool ProcessHotspots(bool resumed = false, float lagCheck = 5f)
{
_stopwatch.Restart();
@@ -709,7 +714,7 @@ namespace Content.Server.GameObjects.Components.Atmos
if (number++ < LagCheckIterations) continue;
number = 0;
// Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
+ if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
{
_hotspotsLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
return false;
@@ -720,7 +725,7 @@ namespace Content.Server.GameObjects.Components.Atmos
return true;
}
- protected virtual bool ProcessSuperconductivity(bool resumed = false)
+ protected virtual bool ProcessSuperconductivity(bool resumed = false, float lagCheck = 5f)
{
_stopwatch.Restart();
@@ -736,7 +741,7 @@ namespace Content.Server.GameObjects.Components.Atmos
if (number++ < LagCheckIterations) continue;
number = 0;
// Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
+ if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
{
_superconductivityLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
return false;
@@ -747,7 +752,7 @@ namespace Content.Server.GameObjects.Components.Atmos
return true;
}
- protected virtual bool ProcessPipeNets(bool resumed = false)
+ protected virtual bool ProcessPipeNets(bool resumed = false, float lagCheck = 5f)
{
_stopwatch.Restart();
@@ -763,7 +768,7 @@ namespace Content.Server.GameObjects.Components.Atmos
if (number++ < LagCheckIterations) continue;
number = 0;
// Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
+ if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
{
_pipeNetLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
return false;
@@ -774,7 +779,7 @@ namespace Content.Server.GameObjects.Components.Atmos
return true;
}
- protected virtual bool ProcessPipeNetDevices(bool resumed = false)
+ protected virtual bool ProcessPipeNetDevices(bool resumed = false, float lagCheck = 5f)
{
_stopwatch.Restart();
@@ -790,7 +795,7 @@ namespace Content.Server.GameObjects.Components.Atmos
if (number++ < LagCheckIterations) continue;
number = 0;
// Process the rest next time.
- if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
+ if (_stopwatch.Elapsed.TotalMilliseconds >= lagCheck)
{
_pipeNetDevicesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
return false;
diff --git a/Content.Server/GameObjects/Components/Atmos/UnsimulatedGridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/UnsimulatedGridAtmosphereComponent.cs
index d2e31e0838..a2a9829673 100644
--- a/Content.Server/GameObjects/Components/Atmos/UnsimulatedGridAtmosphereComponent.cs
+++ b/Content.Server/GameObjects/Components/Atmos/UnsimulatedGridAtmosphereComponent.cs
@@ -71,42 +71,42 @@ namespace Content.Server.GameObjects.Components.Atmos
public override void Update(float frameTime) { }
- public override bool ProcessTileEqualize(bool resumed = false)
+ public override bool ProcessTileEqualize(bool resumed = false, float lagCheck = 5f)
{
return false;
}
- public override bool ProcessActiveTiles(bool resumed = false)
+ public override bool ProcessActiveTiles(bool resumed = false, float lagCheck = 5f)
{
return false;
}
- public override bool ProcessExcitedGroups(bool resumed = false)
+ public override bool ProcessExcitedGroups(bool resumed = false, float lagCheck = 5f)
{
return false;
}
- public override bool ProcessHighPressureDelta(bool resumed = false)
+ public override bool ProcessHighPressureDelta(bool resumed = false, float lagCheck = 5f)
{
return false;
}
- protected override bool ProcessHotspots(bool resumed = false)
+ protected override bool ProcessHotspots(bool resumed = false, float lagCheck = 5f)
{
return false;
}
- protected override bool ProcessSuperconductivity(bool resumed = false)
+ protected override bool ProcessSuperconductivity(bool resumed = false, float lagCheck = 5f)
{
return false;
}
- protected override bool ProcessPipeNets(bool resumed = false)
+ protected override bool ProcessPipeNets(bool resumed = false, float lagCheck = 5f)
{
return false;
}
- protected override bool ProcessPipeNetDevices(bool resumed = false)
+ protected override bool ProcessPipeNetDevices(bool resumed = false, float lagCheck = 5f)
{
return false;
}
diff --git a/Content.Server/GameObjects/EntitySystems/AtmosphereSystem.cs b/Content.Server/GameObjects/EntitySystems/AtmosphereSystem.cs
index cd1919ba4c..ef7359e8e5 100644
--- a/Content.Server/GameObjects/EntitySystems/AtmosphereSystem.cs
+++ b/Content.Server/GameObjects/EntitySystems/AtmosphereSystem.cs
@@ -5,6 +5,7 @@ using System.Linq;
using Content.Server.Atmos;
using Content.Server.Atmos.Reactions;
using Content.Server.GameObjects.Components.Atmos;
+using Content.Shared;
using Content.Shared.Atmos;
using Content.Shared.GameObjects.EntitySystems.Atmos;
using Content.Shared.Maps;
@@ -15,6 +16,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.GameObjects.Components.Map;
using Robust.Shared.GameObjects.Components.Transform;
using Robust.Shared.GameObjects.Systems;
+using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.IoC;
@@ -30,6 +32,7 @@ namespace Content.Server.GameObjects.EntitySystems
[Dependency] private readonly IPrototypeManager _protoMan = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPauseManager _pauseManager = default!;
+ [Dependency] private readonly IConfigurationManager _cfg = default!;
private GasReactionPrototype[] _gasReactions = Array.Empty();
@@ -68,6 +71,43 @@ namespace Content.Server.GameObjects.EntitySystems
// Required for airtight components.
EntityManager.EventBus.SubscribeEvent(EventSource.Local, this, RotateEvent);
+
+ _cfg.OnValueChanged(CCVars.SpaceWind, OnSpaceWindChanged, true);
+ _cfg.OnValueChanged(CCVars.MonstermosEqualization, OnMonstermosEqualizationChanged, true);
+ _cfg.OnValueChanged(CCVars.AtmosMaxProcessTime, OnAtmosMaxProcessTimeChanged, true);
+ _cfg.OnValueChanged(CCVars.AtmosTickRate, OnAtmosTickRateChanged, true);
+ _cfg.OnValueChanged(CCVars.ExcitedGroupsSpaceIsAllConsuming, OnExcitedGroupsSpaceIsAllConsumingChanged, true);
+ }
+
+ public bool SpaceWind { get; private set; }
+ public bool MonstermosEqualization { get; private set; }
+ public bool ExcitedGroupsSpaceIsAllConsuming { get; private set; }
+ public float AtmosMaxProcessTime { get; private set; }
+ public float AtmosTickRate { get; private set; }
+
+ private void OnExcitedGroupsSpaceIsAllConsumingChanged(bool obj)
+ {
+ ExcitedGroupsSpaceIsAllConsuming = obj;
+ }
+
+ private void OnAtmosTickRateChanged(float obj)
+ {
+ AtmosTickRate = obj;
+ }
+
+ private void OnAtmosMaxProcessTimeChanged(float obj)
+ {
+ AtmosMaxProcessTime = obj;
+ }
+
+ private void OnMonstermosEqualizationChanged(bool obj)
+ {
+ MonstermosEqualization = obj;
+ }
+
+ private void OnSpaceWindChanged(bool obj)
+ {
+ SpaceWind = obj;
}
public override void Shutdown()
diff --git a/Content.Shared/CCVars.cs b/Content.Shared/CCVars.cs
index 65a5ab08b9..78d6442e19 100644
--- a/Content.Shared/CCVars.cs
+++ b/Content.Shared/CCVars.cs
@@ -151,6 +151,36 @@ namespace Content.Shared
public static readonly CVarDef AdminAnnounceLogout =
CVarDef.Create("admin.announce_logout", true, CVar.SERVERONLY);
+ /*
+ * Atmos
+ */
+
+ ///
+ /// Whether gas differences will move entities.
+ ///
+ public static readonly CVarDef SpaceWind =
+ CVarDef.Create("atmos.space_wind", true, CVar.SERVERONLY);
+
+ ///
+ /// Whether monstermos tile equalization is enabled.
+ ///
+ public static readonly CVarDef MonstermosEqualization =
+ CVarDef.Create("atmos.monstermos_equalization", true, CVar.SERVERONLY);
+
+ ///
+ /// Maximum time in milliseconds that atmos can take processing.
+ ///
+ public static readonly CVarDef AtmosMaxProcessTime =
+ CVarDef.Create("atmos.max_process_time", 5f, CVar.SERVERONLY);
+
+ ///
+ /// Atmos tickrate in TPS. Atmos processing will happen every 1/TPS seconds.
+ ///
+ public static readonly CVarDef AtmosTickRate =
+ CVarDef.Create("atmos.tickrate", 26f, CVar.SERVERONLY);
+
+ public static readonly CVarDef ExcitedGroupsSpaceIsAllConsuming =
+ CVarDef.Create("atmos.excited_groups_space_is_all_consuming", false, CVar.SERVERONLY);
/*
* Branding stuff
diff --git a/SpaceStation14.sln.DotSettings b/SpaceStation14.sln.DotSettings
index c3b5453582..6d662c0697 100644
--- a/SpaceStation14.sln.DotSettings
+++ b/SpaceStation14.sln.DotSettings
@@ -118,6 +118,7 @@
True
True
True
+ True
True
True
True
@@ -151,6 +152,7 @@
True
True
True
+ True
True
True
True