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