diff --git a/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs b/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs index 0b7f2f9e2d..b3fb1751c9 100644 --- a/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs +++ b/Content.IntegrationTests/Tests/Atmos/GasMixtureTest.cs @@ -1,7 +1,9 @@ using System.Threading.Tasks; using Content.Server.Atmos; +using Content.Server.Atmos.EntitySystems; using Content.Shared.Atmos; using NUnit.Framework; +using Robust.Shared.GameObjects; namespace Content.IntegrationTests.Tests.Atmos { @@ -14,6 +16,10 @@ namespace Content.IntegrationTests.Tests.Atmos { var server = StartServerDummyTicker(); + await server.WaitIdleAsync(); + + var atmosphereSystem = server.ResolveDependency().GetEntitySystem(); + server.Assert(() => { var a = new GasMixture(10f); @@ -30,7 +36,7 @@ namespace Content.IntegrationTests.Tests.Atmos Assert.That(b.TotalMoles, Is.EqualTo(50)); Assert.That(b.GetMoles(Gas.Nitrogen), Is.EqualTo(50)); - b.Merge(a); + atmosphereSystem.Merge(b, a); // b now has its contents and the contents of a Assert.That(b.TotalMoles, Is.EqualTo(100)); diff --git a/Content.IntegrationTests/Tests/Body/LungTest.cs b/Content.IntegrationTests/Tests/Body/LungTest.cs index 376a6965aa..580984374b 100644 --- a/Content.IntegrationTests/Tests/Body/LungTest.cs +++ b/Content.IntegrationTests/Tests/Body/LungTest.cs @@ -105,7 +105,7 @@ namespace Content.IntegrationTests.Tests.Body var exhaledOxygen = Math.Abs(lungOxygenBeforeExhale - lungOxygenAfterExhale); // Not completely empty - Assert.Positive(lung.Air.Gases.Sum()); + Assert.Positive(lung.Air.Moles.Sum()); // Retains needed gas Assert.Positive(bloodstream.Air.GetMoles(Gas.Oxygen)); diff --git a/Content.Server/Atmos/Components/AtmosExposedComponent.cs b/Content.Server/Atmos/Components/AtmosExposedComponent.cs index 1ed395cae0..e0ea5ee76a 100644 --- a/Content.Server/Atmos/Components/AtmosExposedComponent.cs +++ b/Content.Server/Atmos/Components/AtmosExposedComponent.cs @@ -1,4 +1,5 @@ #nullable enable +using Content.Server.Atmos.EntitySystems; using Content.Server.Temperature.Components; using Robust.Shared.GameObjects; using Robust.Shared.ViewVariables; @@ -23,14 +24,15 @@ namespace Content.Server.Atmos.Components [ViewVariables] [ComponentDependency] private readonly FlammableComponent? _flammableComponent = null; - public void Update(TileAtmosphere tile, float frameDelta) + public void Update(TileAtmosphere tile, float frameDelta, AtmosphereSystem atmosphereSystem) { if (_temperatureComponent != null) { if (tile.Air != null) { var temperatureDelta = tile.Air.Temperature - _temperatureComponent.CurrentTemperature; - var heat = temperatureDelta * (tile.Air.HeatCapacity * _temperatureComponent.HeatCapacity / (tile.Air.HeatCapacity + _temperatureComponent.HeatCapacity)); + var tileHeatCapacity = atmosphereSystem.GetHeatCapacity(tile.Air); + var heat = temperatureDelta * (tileHeatCapacity * _temperatureComponent.HeatCapacity / (tileHeatCapacity + _temperatureComponent.HeatCapacity)); _temperatureComponent.ReceiveHeat(heat); } _temperatureComponent.Update(); diff --git a/Content.Server/Atmos/Components/GasAnalyzerComponent.cs b/Content.Server/Atmos/Components/GasAnalyzerComponent.cs index e628c61361..23d7b499aa 100644 --- a/Content.Server/Atmos/Components/GasAnalyzerComponent.cs +++ b/Content.Server/Atmos/Components/GasAnalyzerComponent.cs @@ -204,9 +204,9 @@ namespace Content.Server.Atmos.Components { var gas = atmosSystem.GetGas(i); - if (tile.Gases[i] <= Atmospherics.GasMinMoles) continue; + if (tile.Moles[i] <= Atmospherics.GasMinMoles) continue; - gases.Add(new GasEntry(gas.Name, tile.Gases[i], gas.Color)); + gases.Add(new GasEntry(gas.Name, tile.Moles[i], gas.Color)); } UserInterface.SetState( diff --git a/Content.Server/Atmos/Components/GasTankComponent.cs b/Content.Server/Atmos/Components/GasTankComponent.cs index c2e3b9bd40..c57d7518eb 100644 --- a/Content.Server/Atmos/Components/GasTankComponent.cs +++ b/Content.Server/Atmos/Components/GasTankComponent.cs @@ -1,6 +1,7 @@ #nullable enable #nullable disable warnings using System; +using Content.Server.Atmos.EntitySystems; using Content.Server.Body.Respiratory; using Content.Server.Explosion; using Content.Server.GameObjects.Components.NodeContainer.Nodes; @@ -155,13 +156,6 @@ namespace Content.Server.Atmos.Components DisconnectFromInternals(); } - public void Update() - { - Air?.React(this); - CheckStatus(); - UpdateUserInterface(); - } - public GasMixture? RemoveAir(float amount) { var gas = Air?.Remove(amount); @@ -223,7 +217,7 @@ namespace Content.Server.Atmos.Components UpdateUserInterface(); } - private void UpdateUserInterface(bool initialUpdate = false) + public void UpdateUserInterface(bool initialUpdate = false) { var internals = GetInternalsComponent(); _userInterface?.SetState( @@ -279,15 +273,17 @@ namespace Content.Server.Atmos.Components public void AssumeAir(GasMixture giver) { - Air?.Merge(giver); + EntitySystem.Get().Merge(Air, giver); CheckStatus(); } - private void CheckStatus() + public void CheckStatus() { if (Air == null) return; + var atmosphereSystem = EntitySystem.Get(); + var pressure = Air.Pressure; if (pressure > TankFragmentPressure) @@ -295,7 +291,7 @@ namespace Content.Server.Atmos.Components // Give the gas a chance to build up more pressure. for (var i = 0; i < 3; i++) { - Air.React(this); + atmosphereSystem.React(Air, this); } pressure = Air.Pressure; diff --git a/Content.Server/Atmos/Components/GridAtmosphereComponent.cs b/Content.Server/Atmos/Components/GridAtmosphereComponent.cs index 9d606fe731..6b7b902285 100644 --- a/Content.Server/Atmos/Components/GridAtmosphereComponent.cs +++ b/Content.Server/Atmos/Components/GridAtmosphereComponent.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Runtime.CompilerServices; using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.Piping.Components; +using Content.Server.CPUJob.JobQueues.Queues; using Content.Server.NodeContainer.NodeGroups; using Content.Shared.Atmos; using Content.Shared.Maps; @@ -204,7 +205,7 @@ namespace Content.Server.Atmos.Components foreach (var tile in mapGrid.Grid.GetAllTiles()) { if(!Tiles.ContainsKey(tile.GridIndices)) - Tiles.Add(tile.GridIndices, new TileAtmosphere(this, tile.GridIndex, tile.GridIndices, new GasMixture(GetVolumeForCells(1), AtmosphereSystem){Temperature = Atmospherics.T20C})); + Tiles.Add(tile.GridIndices, new TileAtmosphere(this, tile.GridIndex, tile.GridIndices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C})); Invalidate(tile.GridIndices); } @@ -230,7 +231,7 @@ namespace Content.Server.Atmos.Components if (tile == null) { - tile = new TileAtmosphere(this, _gridId, indices, new GasMixture(GetVolumeForCells(1), AtmosphereSystem){Temperature = Atmospherics.T20C}); + tile = new TileAtmosphere(this, _gridId, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}); Tiles[indices] = tile; } @@ -238,7 +239,7 @@ namespace Content.Server.Atmos.Components if (IsSpace(indices) && !isAirBlocked) { - tile.Air = new GasMixture(GetVolumeForCells(1), AtmosphereSystem); + tile.Air = new GasMixture(GetVolumeForCells(1)); tile.Air.MarkImmutable(); Tiles[indices] = tile; @@ -271,7 +272,7 @@ namespace Content.Server.Atmos.Components tile.Air = null; } - tile.Air ??= new GasMixture(GetVolumeForCells(1), AtmosphereSystem){Temperature = Atmospherics.T20C}; + tile.Air ??= new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}; } // By removing the active tile, we effectively remove its excited group, if any. @@ -312,7 +313,7 @@ namespace Content.Server.Atmos.Components if (tile?.GridIndex != _gridId) return; // includeAirBlocked is false, therefore all tiles in this have Air != null. var adjacent = GetAdjacentTiles(indices); - tile.Air = new GasMixture(GetVolumeForCells(1), AtmosphereSystem){Temperature = Atmospherics.T20C}; + tile.Air = new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}; Tiles[indices] = tile; var ratio = 1f / adjacent.Count; @@ -320,8 +321,8 @@ namespace Content.Server.Atmos.Components foreach (var (_, adj) in adjacent) { var mix = adj.Air!.RemoveRatio(ratio); - tile.Air.Merge(mix); - adj.Air.Merge(mix); + AtmosphereSystem.Merge(tile.Air, mix); + AtmosphereSystem.Merge(adj.Air, mix); } } @@ -435,7 +436,7 @@ namespace Content.Server.Atmos.Components // We don't have that tile! if (IsSpace(indices) && createSpace) { - return new TileAtmosphere(this, _gridId, indices, new GasMixture(GetVolumeForCells(1), AtmosphereSystem){Temperature = Atmospherics.TCMB}, true); + return new TileAtmosphere(this, _gridId, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.TCMB}, true); } return null; diff --git a/Content.Server/Atmos/Components/SpaceGridAtmosphereComponent.cs b/Content.Server/Atmos/Components/SpaceGridAtmosphereComponent.cs index fd1df0e654..ff63d979ea 100644 --- a/Content.Server/Atmos/Components/SpaceGridAtmosphereComponent.cs +++ b/Content.Server/Atmos/Components/SpaceGridAtmosphereComponent.cs @@ -1,6 +1,7 @@ #nullable enable using System.Collections.Generic; using System.Linq; +using Content.Shared.Atmos; using Robust.Shared.GameObjects; using Robust.Shared.Map; using Robust.Shared.Maths; @@ -22,7 +23,7 @@ namespace Content.Server.Atmos.Components public override TileAtmosphere GetTile(Vector2i indices, bool createSpace = true) { - return new(this, GridId.Invalid, indices, new GasMixture(2500, AtmosphereSystem), true); + return new(this, GridId.Invalid, indices, new GasMixture(Atmospherics.CellVolume), true); } protected override IEnumerable GetObstructingComponents(Vector2i indices) diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs index 282d3f97be..106a635c4a 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Content.Server.Atmos.Reactions; +using Content.Server.Interfaces; using Content.Shared.Atmos; using Robust.Shared.Maths; @@ -30,5 +31,273 @@ namespace Content.Server.Atmos.EntitySystems _gasSpecificHeats[i] = GasPrototypes[i].SpecificHeat; } } + + public float GetHeatCapacity(GasMixture mixture) + { + Span tmp = stackalloc float[mixture.Moles.Length]; + NumericsHelpers.Multiply(mixture.Moles, GasSpecificHeats, tmp); + return MathF.Max(NumericsHelpers.HorizontalAdd(tmp), Atmospherics.MinimumHeatCapacity); + } + + public float GetHeatCapacityArchived(GasMixture mixture) + { + Span tmp = stackalloc float[mixture.Moles.Length]; + NumericsHelpers.Multiply(mixture.MolesArchived, GasSpecificHeats, tmp); + return MathF.Max(NumericsHelpers.HorizontalAdd(tmp), Atmospherics.MinimumHeatCapacity); + } + + public float GetThermalEnergy(GasMixture mixture) + { + return mixture.Temperature * GetHeatCapacity(mixture); + } + + public void Merge(GasMixture receiver, GasMixture giver) + { + if (receiver.Immutable) return; + + if (MathF.Abs(receiver.Temperature - giver.Temperature) > Atmospherics.MinimumTemperatureDeltaToConsider) + { + var combinedHeatCapacity = GetHeatCapacity(receiver) + GetHeatCapacity(giver); + if (combinedHeatCapacity > 0f) + { + receiver.Temperature = (GetThermalEnergy(giver) + GetThermalEnergy(receiver)) / combinedHeatCapacity; + } + } + + NumericsHelpers.Add(receiver.Moles, giver.Moles); + } + + public float Share(GasMixture receiver, GasMixture sharer, int atmosAdjacentTurfs) + { + var temperatureDelta = receiver.TemperatureArchived - sharer.TemperatureArchived; + var absTemperatureDelta = Math.Abs(temperatureDelta); + var oldHeatCapacity = 0f; + var oldSharerHeatCapacity = 0f; + + if (absTemperatureDelta > Atmospherics.MinimumTemperatureDeltaToConsider) + { + oldHeatCapacity = GetHeatCapacity(receiver); + oldSharerHeatCapacity = GetHeatCapacity(sharer); + } + + var heatCapacityToSharer = 0f; + var heatCapacitySharerToThis = 0f; + var movedMoles = 0f; + var absMovedMoles = 0f; + + for(var i = 0; i < Atmospherics.TotalNumberOfGases; i++) + { + var thisValue = receiver.Moles[i]; + var sharerValue = sharer.Moles[i]; + var delta = (thisValue - sharerValue) / (atmosAdjacentTurfs + 1); + if (!(MathF.Abs(delta) >= Atmospherics.GasMinMoles)) continue; + if (absTemperatureDelta > Atmospherics.MinimumTemperatureDeltaToConsider) + { + var gasHeatCapacity = delta * GasSpecificHeats[i]; + if (delta > 0) + { + heatCapacityToSharer += gasHeatCapacity; + } + else + { + heatCapacitySharerToThis -= gasHeatCapacity; + } + } + + if (!receiver.Immutable) receiver.Moles[i] -= delta; + if (!sharer.Immutable) sharer.Moles[i] += delta; + movedMoles += delta; + absMovedMoles += MathF.Abs(delta); + } + + receiver.LastShare = absMovedMoles; + + if (absTemperatureDelta > Atmospherics.MinimumTemperatureDeltaToConsider) + { + var newHeatCapacity = oldHeatCapacity + heatCapacitySharerToThis - heatCapacityToSharer; + var newSharerHeatCapacity = oldSharerHeatCapacity + heatCapacityToSharer - heatCapacitySharerToThis; + + // Transfer of thermal energy (via changed heat capacity) between self and sharer. + if (!receiver.Immutable && newHeatCapacity > Atmospherics.MinimumHeatCapacity) + { + receiver.Temperature = ((oldHeatCapacity * receiver.Temperature) - (heatCapacityToSharer * receiver.TemperatureArchived) + (heatCapacitySharerToThis * sharer.TemperatureArchived)) / newHeatCapacity; + } + + if (!sharer.Immutable && newSharerHeatCapacity > Atmospherics.MinimumHeatCapacity) + { + sharer.Temperature = ((oldSharerHeatCapacity * sharer.Temperature) - (heatCapacitySharerToThis * sharer.TemperatureArchived) + (heatCapacityToSharer*receiver.TemperatureArchived)) / newSharerHeatCapacity; + } + + // Thermal energy of the system (self and sharer) is unchanged. + + if (MathF.Abs(oldSharerHeatCapacity) > Atmospherics.MinimumHeatCapacity) + { + if (MathF.Abs(newSharerHeatCapacity / oldSharerHeatCapacity - 1) < 0.1) + { + TemperatureShare(receiver, sharer, Atmospherics.OpenHeatTransferCoefficient); + } + } + } + + if (!(temperatureDelta > Atmospherics.MinimumTemperatureToMove) && + !(MathF.Abs(movedMoles) > Atmospherics.MinimumMolesDeltaToMove)) return 0f; + var moles = receiver.TotalMoles; + var theirMoles = sharer.TotalMoles; + + return (receiver.TemperatureArchived * (moles + movedMoles)) - (sharer.TemperatureArchived * (theirMoles - movedMoles)) * Atmospherics.R / receiver.Volume; + + } + + public float TemperatureShare(GasMixture receiver, GasMixture sharer, float conductionCoefficient) + { + var temperatureDelta = receiver.TemperatureArchived - sharer.TemperatureArchived; + if (MathF.Abs(temperatureDelta) > Atmospherics.MinimumTemperatureDeltaToConsider) + { + var heatCapacity = GetHeatCapacityArchived(receiver); + var sharerHeatCapacity = GetHeatCapacityArchived(sharer); + + if (sharerHeatCapacity > Atmospherics.MinimumHeatCapacity && heatCapacity > Atmospherics.MinimumHeatCapacity) + { + var heat = conductionCoefficient * temperatureDelta * (heatCapacity * sharerHeatCapacity / (heatCapacity + sharerHeatCapacity)); + + if (!receiver.Immutable) + receiver.Temperature = MathF.Abs(MathF.Max(receiver.Temperature - heat / heatCapacity, Atmospherics.TCMB)); + + if (!sharer.Immutable) + sharer.Temperature = MathF.Abs(MathF.Max(sharer.Temperature + heat / sharerHeatCapacity, Atmospherics.TCMB)); + } + } + + return sharer.Temperature; + } + + public float TemperatureShare(GasMixture receiver, float conductionCoefficient, float sharerTemperature, float sharerHeatCapacity) + { + var temperatureDelta = receiver.TemperatureArchived - sharerTemperature; + if (MathF.Abs(temperatureDelta) > Atmospherics.MinimumTemperatureDeltaToConsider) + { + var heatCapacity = GetHeatCapacityArchived(receiver); + + if (sharerHeatCapacity > Atmospherics.MinimumHeatCapacity && heatCapacity > Atmospherics.MinimumHeatCapacity) + { + var heat = conductionCoefficient * temperatureDelta * (heatCapacity * sharerHeatCapacity / (heatCapacity + sharerHeatCapacity)); + + if (!receiver.Immutable) + receiver.Temperature = MathF.Abs(MathF.Max(receiver.Temperature - heat / heatCapacity, Atmospherics.TCMB)); + + sharerTemperature = MathF.Abs(MathF.Max(sharerTemperature + heat / sharerHeatCapacity, Atmospherics.TCMB)); + } + } + + return sharerTemperature; + } + + /// + /// Releases gas from this mixture to the output mixture. + /// If the output mixture is null, then this is being released into space. + /// It can't transfer air to a mixture with higher pressure. + /// + public bool ReleaseGasTo(GasMixture mixture, GasMixture? output, float targetPressure) + { + var outputStartingPressure = output?.Pressure ?? 0; + var inputStartingPressure = mixture.Pressure; + + if (outputStartingPressure >= MathF.Min(targetPressure, inputStartingPressure - 10)) + // No need to pump gas if the target is already reached or input pressure is too low. + // Need at least 10 kPa difference to overcome friction in the mechanism. + return false; + + if (!(mixture.TotalMoles > 0) || !(mixture.Temperature > 0)) return false; + + // We calculate the necessary moles to transfer with the ideal gas law. + var pressureDelta = MathF.Min(targetPressure - outputStartingPressure, (inputStartingPressure - outputStartingPressure) / 2f); + var transferMoles = pressureDelta * (output?.Volume ?? Atmospherics.CellVolume) / (mixture.Temperature * Atmospherics.R); + + // And now we transfer the gas. + var removed = mixture.Remove(transferMoles); + + if(output != null) + Merge(output, removed); + + return true; + } + + /// + /// Pump gas from this mixture to the output mixture. + /// Amount depends on target pressure. + /// + /// The mixture to pump the gas from + /// The mixture to pump the gas to + /// The target pressure to reach + /// Whether we could pump air to the output or not + public bool PumpGasTo(GasMixture mixture, GasMixture output, float targetPressure) + { + var outputStartingPressure = output.Pressure; + var pressureDelta = targetPressure - outputStartingPressure; + + if (pressureDelta < 0.01) + // No need to pump gas, we've reached the target. + return false; + + if (!(mixture.TotalMoles > 0) || !(mixture.Temperature > 0)) return false; + + // We calculate the necessary moles to transfer with the ideal gas law. + var transferMoles = pressureDelta * output.Volume / (mixture.Temperature * Atmospherics.R); + + // And now we transfer the gas. + var removed = mixture.Remove(transferMoles); + Merge(output, removed); + return true; + } + + public void ScrubInto(GasMixture mixture, GasMixture destination, IReadOnlyCollection filterGases) + { + var buffer = new GasMixture(mixture.Volume){Temperature = mixture.Temperature}; + + foreach (var gas in filterGases) + { + buffer.AdjustMoles(gas, mixture.GetMoles(gas)); + mixture.SetMoles(gas, 0f); + } + + Merge(destination, buffer); + } + + public ReactionResult React(GasMixture mixture, IGasMixtureHolder holder) + { + var reaction = ReactionResult.NoReaction; + var temperature = mixture.Temperature; + var energy = GetThermalEnergy(mixture); + + foreach (var prototype in GasReactions) + { + if (energy < prototype.MinimumEnergyRequirement || + temperature < prototype.MinimumTemperatureRequirement || + temperature > prototype.MaximumTemperatureRequirement) + continue; + + var doReaction = true; + for (var i = 0; i < prototype.MinimumRequirements.Length; i++) + { + if(i > Atmospherics.TotalNumberOfGases) + throw new IndexOutOfRangeException("Reaction Gas Minimum Requirements Array Prototype exceeds total number of gases!"); + + var req = prototype.MinimumRequirements[i]; + + if (!(mixture.GetMoles(i) < req)) continue; + doReaction = false; + break; + } + + if (!doReaction) + continue; + + reaction = prototype.React(mixture, holder, this); + if(reaction.HasFlag(ReactionResult.StopReactions)) + break; + } + + return reaction; + } } } diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs index b9ece658f6..f2627ca8fb 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Processing.cs @@ -33,7 +33,7 @@ namespace Content.Server.Atmos.EntitySystems var number = 0; while (atmosphere.CurrentRunTiles.TryDequeue(out var tile)) { - tile.EqualizePressureInZone(atmosphere.UpdateCounter); + tile.EqualizePressureInZone(this, atmosphere.UpdateCounter); if (number++ < LagCheckIterations) continue; number = 0; @@ -55,7 +55,7 @@ namespace Content.Server.Atmos.EntitySystems var number = 0; while (atmosphere.CurrentRunTiles.TryDequeue(out var tile)) { - tile.ProcessCell(atmosphere.UpdateCounter, SpaceWind); + tile.ProcessCell(this, atmosphere.UpdateCounter, SpaceWind); if (number++ < LagCheckIterations) continue; number = 0; @@ -81,7 +81,7 @@ namespace Content.Server.Atmos.EntitySystems excitedGroup.DismantleCooldown++; if(excitedGroup.BreakdownCooldown > Atmospherics.ExcitedGroupBreakdownCycles) - excitedGroup.SelfBreakdown(ExcitedGroupsSpaceIsAllConsuming); + excitedGroup.SelfBreakdown(this, ExcitedGroupsSpaceIsAllConsuming); else if(excitedGroup.DismantleCooldown > Atmospherics.ExcitedGroupsDismantleCycles) excitedGroup.Dismantle(); @@ -153,7 +153,7 @@ namespace Content.Server.Atmos.EntitySystems var number = 0; while (atmosphere.CurrentRunTiles.TryDequeue(out var superconductivity)) { - superconductivity.Superconduct(); + superconductivity.Superconduct(this); if (number++ < LagCheckIterations) continue; number = 0; diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs index 6268319e0d..f7bdf1839b 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.cs @@ -159,7 +159,7 @@ namespace Content.Server.Atmos.EntitySystems { var tile = exposed.Owner.Transform.Coordinates.GetTileAtmosphere(); if (tile == null) continue; - exposed.Update(tile, _exposedTimer); + exposed.Update(tile, _exposedTimer, this); } _exposedTimer -= ExposedUpdateDelay; diff --git a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs b/Content.Server/Atmos/EntitySystems/GasTankSystem.cs deleted file mode 100644 index c9a6fd9d62..0000000000 --- a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Content.Server.Atmos.Components; -using JetBrains.Annotations; -using Robust.Shared.GameObjects; - -namespace Content.Server.Atmos.EntitySystems -{ - [UsedImplicitly] - public class GasTankSystem : EntitySystem - { - private float _timer = 0f; - private const float Interval = 0.5f; - - public override void Update(float frameTime) - { - base.Update(frameTime); - - _timer += frameTime; - - if (_timer < Interval) return; - _timer = 0f; - - foreach (var gasTank in EntityManager.ComponentManager.EntityQuery(true)) - { - gasTank.Update(); - } - } - } -} diff --git a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs index 29355268de..fd0101e5c4 100644 --- a/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs +++ b/Content.Server/Atmos/EntitySystems/GasTileOverlaySystem.cs @@ -167,7 +167,7 @@ namespace Content.Server.Atmos.EntitySystems var overlay = _atmosphereSystem.GetOverlay(i); if (overlay == null) continue; - var moles = tile.Air.Gases[i]; + var moles = tile.Air.Moles[i]; if (moles < gas.GasMolesVisible) continue; diff --git a/Content.Server/Atmos/ExcitedGroup.cs b/Content.Server/Atmos/ExcitedGroup.cs index c32202db52..76831b4d69 100644 --- a/Content.Server/Atmos/ExcitedGroup.cs +++ b/Content.Server/Atmos/ExcitedGroup.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Content.Server.Atmos.Components; +using Content.Server.Atmos.EntitySystems; using Content.Shared.Atmos; using Robust.Shared.ViewVariables; @@ -82,7 +83,7 @@ namespace Content.Server.Atmos DismantleCooldown = 0; } - public void SelfBreakdown(bool spaceIsAllConsuming = false) + public void SelfBreakdown(AtmosphereSystem atmosphereSystem, bool spaceIsAllConsuming = false) { var combined = new GasMixture(Atmospherics.CellVolume); @@ -99,7 +100,7 @@ namespace Content.Server.Atmos foreach (var tile in _tiles) { if (tile?.Air == null) continue; - combined.Merge(tile.Air); + atmosphereSystem.Merge(combined, tile.Air); if (!spaceIsAllConsuming || !tile.Air.Immutable) continue; combined.Clear(); break; diff --git a/Content.Server/Atmos/GasMixture.cs b/Content.Server/Atmos/GasMixture.cs index e8216f176d..31d609b579 100644 --- a/Content.Server/Atmos/GasMixture.cs +++ b/Content.Server/Atmos/GasMixture.cs @@ -22,26 +22,23 @@ namespace Content.Server.Atmos [DataDefinition] public class GasMixture : IEquatable, ICloneable, ISerializationHooks { - private AtmosphereSystem? _atmosphereSystem; - - public static GasMixture SpaceGas => new() {Volume = 2500f, Immutable = true, Temperature = Atmospherics.TCMB}; + public static GasMixture SpaceGas => new() {Volume = Atmospherics.CellVolume, Temperature = Atmospherics.TCMB, Immutable = true}; // This must always have a length that is a multiple of 4 for SIMD acceleration. - [DataField("moles")] [ViewVariables] private float[] _moles = new float[Atmospherics.AdjustedNumberOfGases]; + [DataField("moles")] [ViewVariables] + public float[] Moles = new float[Atmospherics.AdjustedNumberOfGases]; [DataField("molesArchived")] [ViewVariables] - private float[] _molesArchived = new float[Atmospherics.AdjustedNumberOfGases]; + public float[] MolesArchived = new float[Atmospherics.AdjustedNumberOfGases]; [DataField("temperature")] [ViewVariables] private float _temperature = Atmospherics.TCMB; - public IReadOnlyList Gases => _moles; - [DataField("immutable")] [ViewVariables] public bool Immutable { get; private set; } [DataField("lastShare")] [ViewVariables] - public float LastShare { get; private set; } + public float LastShare { get; set; } [ViewVariables] public readonly Dictionary ReactionResults = new() @@ -50,39 +47,11 @@ namespace Content.Server.Atmos { GasReaction.Fire, 0f } }; - [ViewVariables] - public float HeatCapacity - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - _atmosphereSystem ??= EntitySystem.Get(); - Span tmp = stackalloc float[_moles.Length]; - NumericsHelpers.Multiply(_moles, _atmosphereSystem.GasSpecificHeats, tmp); - - return MathF.Max(NumericsHelpers.HorizontalAdd(tmp), Atmospherics.MinimumHeatCapacity); - } - } - - [ViewVariables] - public float HeatCapacityArchived - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - _atmosphereSystem ??= EntitySystem.Get(); - Span tmp = stackalloc float[_moles.Length]; - NumericsHelpers.Multiply(_molesArchived, _atmosphereSystem.GasSpecificHeats, tmp); - - return MathF.Max(NumericsHelpers.HorizontalAdd(tmp), Atmospherics.MinimumHeatCapacity); - } - } - [ViewVariables] public float TotalMoles { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => NumericsHelpers.HorizontalAdd(_moles); + get => NumericsHelpers.HorizontalAdd(Moles); } [ViewVariables] @@ -106,25 +75,17 @@ namespace Content.Server.Atmos } } - [ViewVariables] - public float ThermalEnergy => Temperature * HeatCapacity; - [DataField("temperatureArchived")] [ViewVariables] public float TemperatureArchived { get; private set; } [DataField("volume")] [ViewVariables] public float Volume { get; set; } - public GasMixture() : this(null) + public GasMixture() { } - public GasMixture(AtmosphereSystem? atmosphereSystem) - { - _atmosphereSystem = atmosphereSystem; - } - - public GasMixture(float volume, AtmosphereSystem? atmosphereSystem = null): this(atmosphereSystem) + public GasMixture(float volume = 0f) { if (volume < 0) volume = 0; @@ -140,31 +101,14 @@ namespace Content.Server.Atmos [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Archive() { - _moles.AsSpan().CopyTo(_molesArchived.AsSpan()); + Moles.AsSpan().CopyTo(MolesArchived.AsSpan()); TemperatureArchived = Temperature; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Merge(GasMixture giver) - { - if (Immutable) return; - - if (MathF.Abs(Temperature - giver.Temperature) > Atmospherics.MinimumTemperatureDeltaToConsider) - { - var combinedHeatCapacity = HeatCapacity + giver.HeatCapacity; - if (combinedHeatCapacity > 0f) - { - Temperature = (giver.Temperature * giver.HeatCapacity + Temperature * HeatCapacity) / combinedHeatCapacity; - } - } - - NumericsHelpers.Add(_moles, giver._moles); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetMoles(int gasId) { - return _moles[gasId]; + return Moles[gasId]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -180,7 +124,7 @@ namespace Content.Server.Atmos throw new ArgumentException($"Invalid quantity \"{quantity}\" specified!", nameof(quantity)); if (!Immutable) - _moles[gasId] = quantity; + Moles[gasId] = quantity; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -197,9 +141,9 @@ namespace Content.Server.Atmos if (float.IsInfinity(quantity) || float.IsNaN(quantity)) throw new ArgumentException($"Invalid quantity \"{quantity}\" specified!", nameof(quantity)); - _moles[gasId] += quantity; + Moles[gasId] += quantity; - var moles = _moles[gasId]; + var moles = Moles[gasId]; if (float.IsInfinity(moles) || float.IsNaN(moles) || float.IsNegative(moles)) throw new Exception($"Invalid mole quantity \"{moles}\" in gas Id {gasId} after adjusting moles with \"{quantity}\"!"); @@ -224,28 +168,28 @@ namespace Content.Server.Atmos switch (ratio) { case <= 0: - return new GasMixture(Volume, _atmosphereSystem){Temperature = Temperature}; + return new GasMixture(Volume){Temperature = Temperature}; case > 1: ratio = 1; break; } - var removed = new GasMixture(_atmosphereSystem) {Volume = Volume, Temperature = Temperature}; + var removed = new GasMixture(Volume) { Temperature = Temperature }; - _moles.CopyTo(removed._moles.AsSpan()); - NumericsHelpers.Multiply(removed._moles, ratio); + Moles.CopyTo(removed.Moles.AsSpan()); + NumericsHelpers.Multiply(removed.Moles, ratio); if (!Immutable) - NumericsHelpers.Sub(_moles, removed._moles); + NumericsHelpers.Sub(Moles, removed.Moles); - for (var i = 0; i < _moles.Length; i++) + for (var i = 0; i < Moles.Length; i++) { - var moles = _moles[i]; - var otherMoles = removed._moles[i]; + var moles = Moles[i]; + var otherMoles = removed.Moles[i]; if (moles < Atmospherics.GasMinMoles || float.IsNaN(moles)) - _moles[i] = 0; + Moles[i] = 0; if (otherMoles < Atmospherics.GasMinMoles || float.IsNaN(otherMoles)) - removed._moles[i] = 0; + removed.Moles[i] = 0; } return removed; @@ -255,139 +199,10 @@ namespace Content.Server.Atmos public void CopyFromMutable(GasMixture sample) { if (Immutable) return; - sample._moles.CopyTo(_moles, 0); + sample.Moles.CopyTo(Moles, 0); Temperature = sample.Temperature; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float Share(GasMixture sharer, int atmosAdjacentTurfs) - { - _atmosphereSystem ??= EntitySystem.Get(); - var temperatureDelta = TemperatureArchived - sharer.TemperatureArchived; - var absTemperatureDelta = Math.Abs(temperatureDelta); - var oldHeatCapacity = 0f; - var oldSharerHeatCapacity = 0f; - - if (absTemperatureDelta > Atmospherics.MinimumTemperatureDeltaToConsider) - { - oldHeatCapacity = HeatCapacity; - oldSharerHeatCapacity = sharer.HeatCapacity; - } - - var heatCapacityToSharer = 0f; - var heatCapacitySharerToThis = 0f; - var movedMoles = 0f; - var absMovedMoles = 0f; - - for(var i = 0; i < Atmospherics.TotalNumberOfGases; i++) - { - var thisValue = _moles[i]; - var sharerValue = sharer._moles[i]; - var delta = (thisValue - sharerValue) / (atmosAdjacentTurfs + 1); - if (!(MathF.Abs(delta) >= Atmospherics.GasMinMoles)) continue; - if (absTemperatureDelta > Atmospherics.MinimumTemperatureDeltaToConsider) - { - var gasHeatCapacity = delta * _atmosphereSystem.GasSpecificHeats[i]; - if (delta > 0) - { - heatCapacityToSharer += gasHeatCapacity; - } - else - { - heatCapacitySharerToThis -= gasHeatCapacity; - } - } - - if (!Immutable) _moles[i] -= delta; - if (!sharer.Immutable) sharer._moles[i] += delta; - movedMoles += delta; - absMovedMoles += MathF.Abs(delta); - } - - LastShare = absMovedMoles; - - if (absTemperatureDelta > Atmospherics.MinimumTemperatureDeltaToConsider) - { - var newHeatCapacity = oldHeatCapacity + heatCapacitySharerToThis - heatCapacityToSharer; - var newSharerHeatCapacity = oldSharerHeatCapacity + heatCapacityToSharer - heatCapacitySharerToThis; - - // Transfer of thermal energy (via changed heat capacity) between self and sharer. - if (!Immutable && newHeatCapacity > Atmospherics.MinimumHeatCapacity) - { - Temperature = ((oldHeatCapacity * Temperature) - (heatCapacityToSharer * TemperatureArchived) + (heatCapacitySharerToThis * sharer.TemperatureArchived)) / newHeatCapacity; - } - - if (!sharer.Immutable && newSharerHeatCapacity > Atmospherics.MinimumHeatCapacity) - { - sharer.Temperature = ((oldSharerHeatCapacity * sharer.Temperature) - (heatCapacitySharerToThis * sharer.TemperatureArchived) + (heatCapacityToSharer*TemperatureArchived)) / newSharerHeatCapacity; - } - - // Thermal energy of the system (self and sharer) is unchanged. - - if (MathF.Abs(oldSharerHeatCapacity) > Atmospherics.MinimumHeatCapacity) - { - if (MathF.Abs(newSharerHeatCapacity / oldSharerHeatCapacity - 1) < 0.1) - { - TemperatureShare(sharer, Atmospherics.OpenHeatTransferCoefficient); - } - } - } - - if (!(temperatureDelta > Atmospherics.MinimumTemperatureToMove) && - !(MathF.Abs(movedMoles) > Atmospherics.MinimumMolesDeltaToMove)) return 0f; - var moles = TotalMoles; - var theirMoles = sharer.TotalMoles; - - return (TemperatureArchived * (moles + movedMoles)) - (sharer.TemperatureArchived * (theirMoles - movedMoles)) * Atmospherics.R / Volume; - - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float TemperatureShare(GasMixture sharer, float conductionCoefficient) - { - var temperatureDelta = TemperatureArchived - sharer.TemperatureArchived; - if (MathF.Abs(temperatureDelta) > Atmospherics.MinimumTemperatureDeltaToConsider) - { - var heatCapacity = HeatCapacityArchived; - var sharerHeatCapacity = sharer.HeatCapacityArchived; - - if (sharerHeatCapacity > Atmospherics.MinimumHeatCapacity && heatCapacity > Atmospherics.MinimumHeatCapacity) - { - var heat = conductionCoefficient * temperatureDelta * (heatCapacity * sharerHeatCapacity / (heatCapacity + sharerHeatCapacity)); - - if (!Immutable) - Temperature = MathF.Abs(MathF.Max(Temperature - heat / heatCapacity, Atmospherics.TCMB)); - - if (!sharer.Immutable) - sharer.Temperature = MathF.Abs(MathF.Max(sharer.Temperature + heat / sharerHeatCapacity, Atmospherics.TCMB)); - } - } - - return sharer.Temperature; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public float TemperatureShare(float conductionCoefficient, float sharerTemperature, float sharerHeatCapacity) - { - var temperatureDelta = TemperatureArchived - sharerTemperature; - if (MathF.Abs(temperatureDelta) > Atmospherics.MinimumTemperatureDeltaToConsider) - { - var heatCapacity = HeatCapacityArchived; - - if (sharerHeatCapacity > Atmospherics.MinimumHeatCapacity && heatCapacity > Atmospherics.MinimumHeatCapacity) - { - var heat = conductionCoefficient * temperatureDelta * (heatCapacity * sharerHeatCapacity / (heatCapacity + sharerHeatCapacity)); - - if (!Immutable) - Temperature = MathF.Abs(MathF.Max(Temperature - heat / heatCapacity, Atmospherics.TCMB)); - - sharerTemperature = MathF.Abs(MathF.Max(sharerTemperature + heat / sharerHeatCapacity, Atmospherics.TCMB)); - } - } - - return sharerTemperature; - } - public enum GasCompareResult { NoExchange = -2, @@ -404,8 +219,8 @@ namespace Content.Server.Atmos for(var i = 0; i < Atmospherics.TotalNumberOfGases; i++) { - var gasMoles = _moles[i]; - var delta = MathF.Abs(gasMoles - sample._moles[i]); + var gasMoles = Moles[i]; + var delta = MathF.Abs(gasMoles - sample.Moles[i]); if (delta > Atmospherics.MinimumMolesDeltaToMove && (delta > gasMoles * Atmospherics.MinimumAirRatioToMove)) return (GasCompareResult)i; // We can move gases! moles += gasMoles; @@ -422,125 +237,25 @@ namespace Content.Server.Atmos return GasCompareResult.NoExchange; } - /// - /// Pump gas from this mixture to the output mixture. - /// Amount depends on target pressure. - /// - /// The mixture to pump the gas to - /// The target pressure to reach - /// Whether we could pump air to the output or not - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool PumpGasTo(GasMixture outputAir, float targetPressure) - { - var outputStartingPressure = outputAir.Pressure; - var pressureDelta = targetPressure - outputStartingPressure; - - if (pressureDelta < 0.01) - // No need to pump gas, we've reached the target. - return false; - - if (!(TotalMoles > 0) || !(Temperature > 0)) return false; - - // We calculate the necessary moles to transfer with the ideal gas law. - var transferMoles = pressureDelta * outputAir.Volume / (Temperature * Atmospherics.R); - - // And now we transfer the gas. - var removed = Remove(transferMoles); - outputAir.Merge(removed); - return true; - } - - /// - /// Releases gas from this mixture to the output mixture. - /// If the output mixture is null, then this is being released into space. - /// It can't transfer air to a mixture with higher pressure. - /// - /// - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool ReleaseGasTo(GasMixture? outputAir, float targetPressure) - { - var outputStartingPressure = outputAir?.Pressure ?? 0; - var inputStartingPressure = Pressure; - - if (outputStartingPressure >= MathF.Min(targetPressure, inputStartingPressure - 10)) - // No need to pump gas if the target is already reached or input pressure is too low. - // Need at least 10 kPa difference to overcome friction in the mechanism. - return false; - - if (!(TotalMoles > 0) || !(Temperature > 0)) return false; - - // We calculate the necessary moles to transfer with the ideal gas law. - var pressureDelta = MathF.Min(targetPressure - outputStartingPressure, (inputStartingPressure - outputStartingPressure) / 2f); - var transferMoles = pressureDelta * (outputAir?.Volume ?? Atmospherics.CellVolume) / (Temperature * Atmospherics.R); - - // And now we transfer the gas. - var removed = Remove(transferMoles); - outputAir?.Merge(removed); - - return true; - - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReactionResult React(IGasMixtureHolder holder) - { - _atmosphereSystem ??= EntitySystem.Get(); - var reaction = ReactionResult.NoReaction; - var temperature = Temperature; - var energy = ThermalEnergy; - - foreach (var prototype in _atmosphereSystem.GasReactions) - { - if (energy < prototype.MinimumEnergyRequirement || - temperature < prototype.MinimumTemperatureRequirement || - temperature > prototype.MaximumTemperatureRequirement) - continue; - - var doReaction = true; - for (var i = 0; i < prototype.MinimumRequirements.Length; i++) - { - if(i > Atmospherics.TotalNumberOfGases) - throw new IndexOutOfRangeException("Reaction Gas Minimum Requirements Array Prototype exceeds total number of gases!"); - - var req = prototype.MinimumRequirements[i]; - - if (!(GetMoles(i) < req)) continue; - doReaction = false; - break; - } - - if (!doReaction) - continue; - - reaction = prototype.React(this, holder, _atmosphereSystem.GridTileLookupSystem); - if(reaction.HasFlag(ReactionResult.StopReactions)) - break; - } - - return reaction; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Clear() { if (Immutable) return; - Array.Clear(_moles, 0, Atmospherics.TotalNumberOfGases); + Array.Clear(Moles, 0, Atmospherics.TotalNumberOfGases); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Multiply(float multiplier) { if (Immutable) return; - NumericsHelpers.Multiply(_moles, multiplier); + NumericsHelpers.Multiply(Moles, multiplier); } void ISerializationHooks.AfterDeserialization() { // The arrays MUST have a specific length. - Array.Resize(ref _moles, Atmospherics.AdjustedNumberOfGases); - Array.Resize(ref _molesArchived, Atmospherics.AdjustedNumberOfGases); + Array.Resize(ref Moles, Atmospherics.AdjustedNumberOfGases); + Array.Resize(ref MolesArchived, Atmospherics.AdjustedNumberOfGases); } public override bool Equals(object? obj) @@ -554,8 +269,8 @@ namespace Content.Server.Atmos { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; - return _moles.SequenceEqual(other._moles) - && _molesArchived.SequenceEqual(other._molesArchived) + return Moles.SequenceEqual(other.Moles) + && MolesArchived.SequenceEqual(other.MolesArchived) && _temperature.Equals(other._temperature) && ReactionResults.SequenceEqual(other.ReactionResults) && Immutable == other.Immutable @@ -570,8 +285,8 @@ namespace Content.Server.Atmos for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++) { - var moles = _moles[i]; - var molesArchived = _molesArchived[i]; + var moles = Moles[i]; + var molesArchived = MolesArchived[i]; hashCode.Add(moles); hashCode.Add(molesArchived); } @@ -587,10 +302,10 @@ namespace Content.Server.Atmos public object Clone() { - var newMixture = new GasMixture(_atmosphereSystem) + var newMixture = new GasMixture() { - _moles = (float[])_moles.Clone(), - _molesArchived = (float[])_molesArchived.Clone(), + Moles = (float[])Moles.Clone(), + MolesArchived = (float[])MolesArchived.Clone(), _temperature = _temperature, Immutable = Immutable, LastShare = LastShare, @@ -599,18 +314,5 @@ namespace Content.Server.Atmos }; return newMixture; } - - public void ScrubInto(GasMixture destination, IReadOnlyCollection filterGases) - { - var buffer = new GasMixture(Volume){Temperature = Temperature}; - - foreach (var gas in filterGases) - { - buffer.AdjustMoles(gas, GetMoles(gas)); - SetMoles(gas, 0f); - } - - destination.Merge(buffer); - } } } diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasCanisterSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasCanisterSystem.cs index f29b4895b3..d084826a2c 100644 --- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasCanisterSystem.cs +++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasCanisterSystem.cs @@ -1,5 +1,6 @@ using System; using Content.Server.Atmos.Components; +using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.Piping.Binary.Components; using Content.Server.Atmos.Piping.Components; using Content.Server.GameObjects.Components.NodeContainer.Nodes; @@ -49,7 +50,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems // Create a pipenet if we don't have one already. portNode.TryAssignGroupIfNeeded(); - portNode.Air.Merge(canister.InitialMixture); + Get().Merge(portNode.Air, canister.InitialMixture); portNode.Air.Temperature = canister.InitialMixture.Temperature; portNode.Volume = canister.InitialMixture.Volume; } diff --git a/Content.Server/Atmos/Piping/EntitySystems/AtmosUnsafeUnanchorSystem.cs b/Content.Server/Atmos/Piping/EntitySystems/AtmosUnsafeUnanchorSystem.cs index a06fe44367..b94441e5b4 100644 --- a/Content.Server/Atmos/Piping/EntitySystems/AtmosUnsafeUnanchorSystem.cs +++ b/Content.Server/Atmos/Piping/EntitySystems/AtmosUnsafeUnanchorSystem.cs @@ -1,3 +1,4 @@ +using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.Piping.Components; using Content.Server.Construction.Components; using Content.Server.GameObjects.Components.NodeContainer.Nodes; @@ -67,11 +68,13 @@ namespace Content.Server.Atmos.Piping.EntitySystems var sharedLoss = lost / timesLost; var buffer = new GasMixture(); + var atmosphereSystem = Get(); + foreach (var node in nodes.Nodes.Values) { if (node is not PipeNode pipe) continue; - buffer.Merge(pipe.Air.Remove(sharedLoss)); + atmosphereSystem.Merge(buffer, pipe.Air.Remove(sharedLoss)); } environment?.AssumeAir(buffer); diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasTankSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasTankSystem.cs index ac329dc9bf..6cea9c7f89 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasTankSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasTankSystem.cs @@ -1,4 +1,5 @@ using Content.Server.Atmos.Components; +using Content.Server.Atmos.EntitySystems; using Content.Server.GameObjects.Components.NodeContainer.Nodes; using Content.Server.NodeContainer; using JetBrains.Annotations; @@ -9,6 +10,9 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems [UsedImplicitly] public class GasTankSystem : EntitySystem { + private const float TimerDelay = 0.5f; + private float _timer = 0f; + public override void Initialize() { base.Initialize(); @@ -31,5 +35,24 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems tankNode.Air.Volume = tank.InitialMixture.Volume; tankNode.Air.Temperature = tank.InitialMixture.Temperature; } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + _timer += frameTime; + + if (_timer < TimerDelay) return; + _timer -= TimerDelay; + + var atmosphereSystem = Get(); + + foreach (var gasTank in EntityManager.ComponentManager.EntityQuery(true)) + { + atmosphereSystem.React(gasTank.Air, gasTank); + gasTank.CheckStatus(); + gasTank.UpdateUserInterface(); + } + } } } diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs index 3d18755e5e..43f001d186 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasThermoMachineSystem.cs @@ -1,3 +1,4 @@ +using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.Piping.Components; using Content.Server.Atmos.Piping.Unary.Components; using Content.Server.GameObjects.Components.NodeContainer.Nodes; @@ -34,7 +35,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems if (!nodeContainer.TryGetNode(thermoMachine.InletName, out PipeNode? inlet)) return; - var airHeatCapacity = inlet.Air.HeatCapacity; + var airHeatCapacity = Get().GetHeatCapacity(inlet.Air); var combinedHeatCapacity = airHeatCapacity + thermoMachine.HeatCapacity; var oldTemperature = inlet.Air.Temperature; diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs index 45a068e799..17559dbb4b 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs @@ -1,4 +1,5 @@ using System; +using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.Piping.Components; using Content.Server.Atmos.Piping.Unary.Components; using Content.Server.GameObjects.Components.NodeContainer.Nodes; @@ -88,7 +89,8 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems if (MathHelper.CloseTo(removed.TotalMoles, 0f)) return; - removed.ScrubInto(outlet.Air, scrubber.FilterGases); + // TODO: Entity system dependency + Get().ScrubInto(removed, outlet.Air, scrubber.FilterGases); // Remix the gases. tile.AssumeAir(removed); diff --git a/Content.Server/Atmos/Reactions/GasReactionPrototype.cs b/Content.Server/Atmos/Reactions/GasReactionPrototype.cs index 776d1fe059..1005f2d49a 100644 --- a/Content.Server/Atmos/Reactions/GasReactionPrototype.cs +++ b/Content.Server/Atmos/Reactions/GasReactionPrototype.cs @@ -1,6 +1,7 @@ #nullable enable using System; using System.Collections.Generic; +using Content.Server.Atmos.EntitySystems; using Content.Server.Interfaces; using Content.Shared.Atmos; using Robust.Server.GameObjects; @@ -66,13 +67,13 @@ namespace Content.Server.Atmos.Reactions /// [DataField("effects")] private List _effects = new(); - public ReactionResult React(GasMixture mixture, IGasMixtureHolder holder, GridTileLookupSystem gridLookup) + public ReactionResult React(GasMixture mixture, IGasMixtureHolder holder, AtmosphereSystem atmosphereSystem) { var result = ReactionResult.NoReaction; foreach (var effect in _effects) { - result |= effect.React(mixture, holder, gridLookup); + result |= effect.React(mixture, holder, atmosphereSystem); } return result; diff --git a/Content.Server/Atmos/Reactions/PlasmaFireReaction.cs b/Content.Server/Atmos/Reactions/PlasmaFireReaction.cs index 5ca5bc6298..4d34cd33cd 100644 --- a/Content.Server/Atmos/Reactions/PlasmaFireReaction.cs +++ b/Content.Server/Atmos/Reactions/PlasmaFireReaction.cs @@ -1,5 +1,6 @@ #nullable enable using System; +using Content.Server.Atmos.EntitySystems; using Content.Server.Coordinates.Helpers; using Content.Server.Interfaces; using Content.Shared.Atmos; @@ -13,10 +14,10 @@ namespace Content.Server.Atmos.Reactions [DataDefinition] public class PlasmaFireReaction : IGasReactionEffect { - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, GridTileLookupSystem gridTileLookup) + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem) { var energyReleased = 0f; - var oldHeatCapacity = mixture.HeatCapacity; + var oldHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture); var temperature = mixture.Temperature; var location = holder as TileAtmosphere; mixture.ReactionResults[GasReaction.Fire] = 0; @@ -63,7 +64,7 @@ namespace Content.Server.Atmos.Reactions if (energyReleased > 0) { - var newHeatCapacity = mixture.HeatCapacity; + var newHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture); if (newHeatCapacity > Atmospherics.MinimumHeatCapacity) mixture.Temperature = ((temperature * oldHeatCapacity + energyReleased) / newHeatCapacity); } @@ -75,7 +76,7 @@ namespace Content.Server.Atmos.Reactions { location.HotspotExpose(temperature, mixture.Volume); - foreach (var entity in location.GridIndices.GetEntitiesInTileFast(location.GridIndex, gridTileLookup)) + foreach (var entity in location.GridIndices.GetEntitiesInTileFast(location.GridIndex)) { foreach (var temperatureExpose in entity.GetAllComponents()) { diff --git a/Content.Server/Atmos/Reactions/TritiumFireReaction.cs b/Content.Server/Atmos/Reactions/TritiumFireReaction.cs index c6c596c121..3c71b26c15 100644 --- a/Content.Server/Atmos/Reactions/TritiumFireReaction.cs +++ b/Content.Server/Atmos/Reactions/TritiumFireReaction.cs @@ -1,4 +1,5 @@ #nullable enable +using Content.Server.Atmos.EntitySystems; using Content.Server.Coordinates.Helpers; using Content.Server.Interfaces; using Content.Shared.Atmos; @@ -12,10 +13,10 @@ namespace Content.Server.Atmos.Reactions [DataDefinition] public class TritiumFireReaction : IGasReactionEffect { - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, GridTileLookupSystem gridTileLookup) + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem) { var energyReleased = 0f; - var oldHeatCapacity = mixture.HeatCapacity; + var oldHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture); var temperature = mixture.Temperature; var location = holder as TileAtmosphere; mixture.ReactionResults[GasReaction.Fire] = 0f; @@ -42,7 +43,7 @@ namespace Content.Server.Atmos.Reactions if (burnedFuel > 0) { energyReleased += (Atmospherics.FireHydrogenEnergyReleased * burnedFuel); - + // TODO ATMOS Radiation pulse here! // Conservation of mass is important. @@ -53,7 +54,7 @@ namespace Content.Server.Atmos.Reactions if (energyReleased > 0) { - var newHeatCapacity = mixture.HeatCapacity; + var newHeatCapacity = atmosphereSystem.GetHeatCapacity(mixture); if (newHeatCapacity > Atmospherics.MinimumHeatCapacity) mixture.Temperature = ((temperature * oldHeatCapacity + energyReleased) / newHeatCapacity); } @@ -65,7 +66,7 @@ namespace Content.Server.Atmos.Reactions { location.HotspotExpose(temperature, mixture.Volume); - foreach (var entity in location.GridIndices.GetEntitiesInTileFast(location.GridIndex, gridTileLookup)) + foreach (var entity in location.GridIndices.GetEntitiesInTileFast(location.GridIndex)) { foreach (var temperatureExpose in entity.GetAllComponents()) { diff --git a/Content.Server/Atmos/Reactions/WaterVaporReaction.cs b/Content.Server/Atmos/Reactions/WaterVaporReaction.cs index d49b39a9b1..6f2c98d16c 100644 --- a/Content.Server/Atmos/Reactions/WaterVaporReaction.cs +++ b/Content.Server/Atmos/Reactions/WaterVaporReaction.cs @@ -1,4 +1,5 @@ #nullable enable +using Content.Server.Atmos.EntitySystems; using Content.Server.Fluids.Components; using Content.Server.Interfaces; using Content.Shared.Chemistry.Reagent; @@ -22,7 +23,7 @@ namespace Content.Server.Atmos.Reactions [DataField("puddlePrototype")] public string? PuddlePrototype { get; } = "PuddleSmear"; - public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, GridTileLookupSystem gridTileLookup) + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem) { // If any of the prototypes is invalid, we do nothing. if (string.IsNullOrEmpty(Reagent) || string.IsNullOrEmpty(PuddlePrototype)) return ReactionResult.NoReaction; diff --git a/Content.Server/Atmos/TileAtmosphere.cs b/Content.Server/Atmos/TileAtmosphere.cs index c297cf1a63..d3328ce7fb 100644 --- a/Content.Server/Atmos/TileAtmosphere.cs +++ b/Content.Server/Atmos/TileAtmosphere.cs @@ -5,6 +5,7 @@ using System.Buffers; using System.Collections.Generic; using System.Runtime.CompilerServices; using Content.Server.Atmos.Components; +using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.Reactions; using Content.Server.Coordinates.Helpers; using Content.Server.Interfaces; @@ -12,6 +13,7 @@ using Content.Shared.Atmos; using Content.Shared.Audio; using Content.Shared.Maps; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Metadata.Builders; using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Containers; @@ -197,7 +199,7 @@ namespace Content.Server.Atmos } } - public void EqualizePressureInZone(int cycleNum) + public void EqualizePressureInZone(AtmosphereSystem atmosphereSystem, int cycleNum) { if (Air == null || (_tileAtmosInfo.LastCycle >= cycleNum)) return; // Already done. @@ -504,7 +506,7 @@ namespace Content.Server.Atmos for (var i = 0; i < tileCount; i++) { var tile = tiles[i]; - tile.FinalizeEq(); + tile.FinalizeEq(atmosphereSystem); } for (var i = 0; i < tileCount; i++) @@ -526,7 +528,7 @@ namespace Content.Server.Atmos ArrayPool.Shared.Return(takerTiles); } - private void FinalizeEq() + private void FinalizeEq(AtmosphereSystem atmosphereSystem) { Span transferDirections = stackalloc float[Atmospherics.Directions]; var hasTransferDirs = false; @@ -551,10 +553,10 @@ namespace Content.Server.Atmos if (amount > 0) { if (Air.TotalMoles < amount) - FinalizeEqNeighbors(transferDirections); + FinalizeEqNeighbors(atmosphereSystem, transferDirections); tile._tileAtmosInfo[direction.GetOpposite()] = 0; - tile.Air.Merge(Air.Remove(amount)); + atmosphereSystem.Merge(tile.Air, Air.Remove(amount)); UpdateVisuals(); tile.UpdateVisuals(); ConsiderPressureDifference(tile, amount); @@ -563,14 +565,14 @@ namespace Content.Server.Atmos } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void FinalizeEqNeighbors(ReadOnlySpan transferDirs) + private void FinalizeEqNeighbors(AtmosphereSystem atmosphereSystem, ReadOnlySpan transferDirs) { for (var i = 0; i < Atmospherics.Directions; i++) { var direction = (AtmosDirection) (1 << i); var amount = transferDirs[i]; if(amount < 0 && _adjacentBits.IsFlagSet(direction)) - _adjacentTiles[i].FinalizeEq(); // A bit of recursion if needed. + _adjacentTiles[i].FinalizeEq(atmosphereSystem); // A bit of recursion if needed. } } @@ -592,7 +594,7 @@ namespace Content.Server.Atmos _adjacentTiles[direction.ToIndex()]._tileAtmosInfo[direction.GetOpposite()] -= amount; } - public void ProcessCell(int fireCount, bool spaceWind = true) + public void ProcessCell(AtmosphereSystem atmosphereSystem, int fireCount, bool spaceWind = true) { // Can't process a tile without air if (Air == null) @@ -662,7 +664,7 @@ namespace Content.Server.Atmos if (shouldShareAir) { - var difference = Air.Share(enemyTile.Air, adjacentTileLength); + var difference = atmosphereSystem.Share(Air, enemyTile.Air, adjacentTileLength); if (spaceWind) { @@ -680,7 +682,8 @@ namespace Content.Server.Atmos } } - React(); + if(Air != null) + _gridAtmosphereComponent.AtmosphereSystem.React(Air, this); UpdateVisuals(); var remove = true; @@ -715,7 +718,7 @@ namespace Content.Server.Atmos ExcitedGroup?.ResetCooldowns(); if ((Hotspot.Temperature < Atmospherics.FireMinimumTemperatureToExist) || (Hotspot.Volume <= 1f) - || Air == null || Air.Gases[(int)Gas.Oxygen] < 0.5f || (Air.Gases[(int)Gas.Plasma] < 0.5f && Air.GetMoles(Gas.Tritium) < 0.5f)) + || Air == null || Air.GetMoles(Gas.Oxygen) < 0.5f || (Air.GetMoles(Gas.Plasma) < 0.5f && Air.GetMoles(Gas.Tritium) < 0.5f)) { Hotspot = new Hotspot(); UpdateVisuals(); @@ -767,7 +770,7 @@ namespace Content.Server.Atmos { var affected = Air.RemoveRatio(Hotspot.Volume / Air.Volume); affected.Temperature = Hotspot.Temperature; - affected.React(this); + _gridAtmosphereComponent.AtmosphereSystem.React(affected, this); Hotspot.Temperature = affected.Temperature; Hotspot.Volume = affected.ReactionResults[GasReaction.Fire] * Atmospherics.FireGrowthRate; AssumeAir(affected); @@ -846,10 +849,10 @@ namespace Content.Server.Atmos : Atmospherics.MinimumTemperatureForSuperconduction)) return false; - return !(Air.HeatCapacity < Atmospherics.MCellWithRatio) && ConsiderSuperconductivity(); + return !(_gridAtmosphereComponent.AtmosphereSystem.GetHeatCapacity(Air) < Atmospherics.MCellWithRatio) && ConsiderSuperconductivity(); } - public void Superconduct() + public void Superconduct(AtmosphereSystem atmosphereSystem) { var directions = ConductivityDirections(); @@ -867,22 +870,22 @@ namespace Content.Server.Atmos if(adjacent._archivedCycle < _gridAtmosphereComponent.UpdateCounter) adjacent.Archive(_gridAtmosphereComponent.UpdateCounter); - adjacent.NeighborConductWithSource(this); + adjacent.NeighborConductWithSource(atmosphereSystem, this); adjacent.ConsiderSuperconductivity(); } RadiateToSpace(); - FinishSuperconduction(); + FinishSuperconduction(atmosphereSystem); } - private void FinishSuperconduction() + private void FinishSuperconduction(AtmosphereSystem atmosphereSystem) { // Conduct with air on my tile if I have it if (!BlocksAllAir) { - Temperature = Air.TemperatureShare(ThermalConductivity, Temperature, HeatCapacity); + Temperature = atmosphereSystem.TemperatureShare(Air, ThermalConductivity, Temperature, HeatCapacity); } FinishSuperconduction(BlocksAllAir ? Temperature : Air.Temperature); @@ -897,13 +900,13 @@ namespace Content.Server.Atmos } } - private void NeighborConductWithSource(TileAtmosphere other) + private void NeighborConductWithSource(AtmosphereSystem atmosphereSystem, TileAtmosphere other) { if (BlocksAllAir) { if (!other.BlocksAllAir) { - other.TemperatureShareOpenToSolid(this); + other.TemperatureShareOpenToSolid(atmosphereSystem, this); } else { @@ -916,20 +919,19 @@ namespace Content.Server.Atmos if (!other.BlocksAllAir) { - other.Air.TemperatureShare(Air, Atmospherics.WindowHeatTransferCoefficient); + atmosphereSystem.TemperatureShare(other.Air, Air, Atmospherics.WindowHeatTransferCoefficient); } else { - TemperatureShareOpenToSolid(other); + TemperatureShareOpenToSolid(atmosphereSystem, other); } _gridAtmosphereComponent.AddActiveTile(this); } - private void TemperatureShareOpenToSolid(TileAtmosphere other) + private void TemperatureShareOpenToSolid(AtmosphereSystem atmosphereSystem, TileAtmosphere other) { - other.Temperature = - Air.TemperatureShare(other.ThermalConductivity, other.Temperature, other.HeatCapacity); + other.Temperature = atmosphereSystem.TemperatureShare(Air, other.ThermalConductivity, other.Temperature, other.HeatCapacity); } private void TemperatureShareMutualSolid(TileAtmosphere other, float conductionCoefficient) @@ -1120,17 +1122,11 @@ namespace Content.Server.Atmos } } - private void React() - { - // TODO ATMOS I think this is enough? gotta make sure... - Air?.React(this); - } - public bool AssumeAir(GasMixture giver) { if (Air == null) return false; - Air.Merge(giver); + EntitySystem.Get().Merge(Air, giver); UpdateVisuals(); diff --git a/Content.Server/Body/Behavior/LungBehavior.cs b/Content.Server/Body/Behavior/LungBehavior.cs index 6154fd92d0..51130d9790 100644 --- a/Content.Server/Body/Behavior/LungBehavior.cs +++ b/Content.Server/Body/Behavior/LungBehavior.cs @@ -2,12 +2,14 @@ using System; using Content.Server.Atmos; using Content.Server.Atmos.Components; +using Content.Server.Atmos.EntitySystems; using Content.Server.Body.Circulatory; using Content.Server.Body.Respiratory; using Content.Server.Notification; using Content.Shared.Atmos; using Content.Shared.Body.Components; using Content.Shared.MobState; +using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Serialization.Manager.Attributes; @@ -67,7 +69,7 @@ namespace Content.Server.Body.Behavior public void Transfer(GasMixture from, GasMixture to, float ratio) { - to.Merge(from.RemoveRatio(ratio)); + EntitySystem.Get().Merge(to, from.RemoveRatio(ratio)); } public void ToBloodstream(GasMixture mixture) @@ -84,7 +86,7 @@ namespace Content.Server.Body.Behavior var to = bloodstream.Air; - to.Merge(mixture); + EntitySystem.Get().Merge(to, mixture); mixture.Clear(); } @@ -189,7 +191,7 @@ namespace Content.Server.Body.Behavior bloodstream.PumpToxins(Air); var lungRemoved = Air.RemoveRatio(0.5f); - to.Merge(lungRemoved); + EntitySystem.Get().Merge(to, lungRemoved); } } diff --git a/Content.Server/Body/Circulatory/BloodstreamComponent.cs b/Content.Server/Body/Circulatory/BloodstreamComponent.cs index 77778a4af9..2b50d039a5 100644 --- a/Content.Server/Body/Circulatory/BloodstreamComponent.cs +++ b/Content.Server/Body/Circulatory/BloodstreamComponent.cs @@ -1,5 +1,7 @@ +using System; using System.Linq; using Content.Server.Atmos; +using Content.Server.Atmos.EntitySystems; using Content.Server.Chemistry.Components; using Content.Server.Interfaces; using Content.Server.Metabolism; @@ -69,17 +71,20 @@ namespace Content.Server.Body.Circulatory public void PumpToxins(GasMixture to) { + var atmosphereSystem = EntitySystem.Get(); + if (!Owner.TryGetComponent(out MetabolismComponent? metabolism)) { - to.Merge(Air); + atmosphereSystem.Merge(to, Air); Air.Clear(); return; } var toxins = metabolism.Clean(this); - var toOld = to.Gases.ToArray(); + var toOld = new float[to.Moles.Length]; + Array.Copy(to.Moles, toOld, toOld.Length); - to.Merge(toxins); + atmosphereSystem.Merge(to, toxins); for (var i = 0; i < toOld.Length; i++) { @@ -90,7 +95,7 @@ namespace Content.Server.Body.Circulatory toxins.AdjustMoles(i, -delta); } - Air.Merge(toxins); + atmosphereSystem.Merge(Air, toxins); } } } diff --git a/Content.Server/Chemistry/TileReactions/ExtinguishTileReaction.cs b/Content.Server/Chemistry/TileReactions/ExtinguishTileReaction.cs index 61705c27e9..699ce8dfaf 100644 --- a/Content.Server/Chemistry/TileReactions/ExtinguishTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/ExtinguishTileReaction.cs @@ -1,11 +1,13 @@ using System; using Content.Server.Atmos; +using Content.Server.Atmos.EntitySystems; using Content.Shared.Atmos; using Content.Shared.Chemistry; using Content.Shared.Chemistry.Reaction; using Content.Shared.Chemistry.Reagent; using Content.Shared.Maps; using JetBrains.Annotations; +using Robust.Shared.GameObjects; using Robust.Shared.Map; using Robust.Shared.Serialization.Manager.Attributes; @@ -26,7 +28,7 @@ namespace Content.Server.Chemistry.TileReactions MathF.Max(MathF.Min(tileAtmos.Air.Temperature - (_coolingTemperature * 1000f), tileAtmos.Air.Temperature / _coolingTemperature), Atmospherics.TCMB); - tileAtmos.Air.React(tileAtmos); + EntitySystem.Get().React(tileAtmos.Air, tileAtmos); tileAtmos.Hotspot = new Hotspot(); tileAtmos.UpdateVisuals(); return ReagentUnit.Zero; diff --git a/Content.Server/Chemistry/TileReactions/FlammableTileReaction.cs b/Content.Server/Chemistry/TileReactions/FlammableTileReaction.cs index d8a4cfb0b8..da0b9f54be 100644 --- a/Content.Server/Chemistry/TileReactions/FlammableTileReaction.cs +++ b/Content.Server/Chemistry/TileReactions/FlammableTileReaction.cs @@ -1,10 +1,12 @@ using System; using Content.Server.Atmos; +using Content.Server.Atmos.EntitySystems; using Content.Shared.Chemistry; using Content.Shared.Chemistry.Reaction; using Content.Shared.Chemistry.Reagent; using Content.Shared.Maps; using JetBrains.Annotations; +using Robust.Shared.GameObjects; using Robust.Shared.Map; using Robust.Shared.Serialization.Manager.Attributes; @@ -22,7 +24,7 @@ namespace Content.Server.Chemistry.TileReactions var tileAtmos = tile.GridPosition().GetTileAtmosphere(); if (tileAtmos?.Air == null || !tileAtmos.Hotspot.Valid) return ReagentUnit.Zero; tileAtmos.Air.Temperature *= MathF.Max(_temperatureMultiplier * reactVolume.Float(), 1f); - tileAtmos.Air.React(tileAtmos); + EntitySystem.Get().React(tileAtmos.Air, tileAtmos); return reactVolume; } } diff --git a/Content.Server/Disposal/Tube/Components/DisposalEntryComponent.cs b/Content.Server/Disposal/Tube/Components/DisposalEntryComponent.cs index 910176f23c..2e4d444cac 100644 --- a/Content.Server/Disposal/Tube/Components/DisposalEntryComponent.cs +++ b/Content.Server/Disposal/Tube/Components/DisposalEntryComponent.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using Content.Server.Atmos.EntitySystems; using Content.Server.Disposal.Unit.Components; using Robust.Shared.GameObjects; using Robust.Shared.IoC; @@ -28,7 +29,7 @@ namespace Content.Server.Disposal.Tube.Components holderComponent.TryInsert(entity); } - holderComponent.Air.Merge(from.Air); + EntitySystem.Get().Merge(holderComponent.Air, from.Air); from.Air.Clear(); return TryInsert(holderComponent); diff --git a/Content.Server/Interfaces/IGasMixtureHolder.cs b/Content.Server/Interfaces/IGasMixtureHolder.cs index 171bb3c64d..bd34555949 100644 --- a/Content.Server/Interfaces/IGasMixtureHolder.cs +++ b/Content.Server/Interfaces/IGasMixtureHolder.cs @@ -1,4 +1,6 @@ using Content.Server.Atmos; +using Content.Server.Atmos.EntitySystems; +using Robust.Shared.GameObjects; namespace Content.Server.Interfaces { @@ -8,7 +10,7 @@ namespace Content.Server.Interfaces public virtual void AssumeAir(GasMixture giver) { - Air.Merge(giver); + EntitySystem.Get().Merge(Air, giver); } public GasMixture RemoveAir(float amount) diff --git a/Content.Server/Interfaces/IGasReactionEffect.cs b/Content.Server/Interfaces/IGasReactionEffect.cs index 7ca58d4342..7268b8654e 100644 --- a/Content.Server/Interfaces/IGasReactionEffect.cs +++ b/Content.Server/Interfaces/IGasReactionEffect.cs @@ -1,5 +1,6 @@ #nullable enable using Content.Server.Atmos; +using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.Reactions; using Robust.Server.GameObjects; @@ -7,6 +8,6 @@ namespace Content.Server.Interfaces { public interface IGasReactionEffect { - ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, GridTileLookupSystem gridTileLookup); + ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem); } } diff --git a/Content.Server/NodeContainer/NodeGroups/IPipeNet.cs b/Content.Server/NodeContainer/NodeGroups/IPipeNet.cs index 7809433318..37280d3b9f 100644 --- a/Content.Server/NodeContainer/NodeGroups/IPipeNet.cs +++ b/Content.Server/NodeContainer/NodeGroups/IPipeNet.cs @@ -46,7 +46,7 @@ namespace Content.Server.NodeContainer.NodeGroups public void Update() { - Air.React(this); + EntitySystem.Get().React(Air, this); } protected override void OnAddNode(Node node) @@ -74,7 +74,7 @@ namespace Content.Server.NodeContainer.NodeGroups if (newGroup is not IPipeNet newPipeNet) return; - newPipeNet.Air.Merge(Air); + EntitySystem.Get().Merge(newPipeNet.Air, Air); } protected override void AfterRemake(IEnumerable newGroups) @@ -82,6 +82,7 @@ namespace Content.Server.NodeContainer.NodeGroups RemoveFromGridAtmos(); var buffer = new GasMixture(Air.Volume) {Temperature = Air.Temperature}; + var atmosphereSystem = EntitySystem.Get(); foreach (var newGroup in newGroups) { @@ -91,9 +92,9 @@ namespace Content.Server.NodeContainer.NodeGroups var newAir = newPipeNet.Air; buffer.Clear(); - buffer.Merge(Air); + atmosphereSystem.Merge(buffer, Air); buffer.Multiply(MathF.Min(newAir.Volume / Air.Volume, 1f)); - newAir.Merge(buffer); + atmosphereSystem.Merge(newAir, buffer); } } diff --git a/Content.Server/NodeContainer/Nodes/PipeNode.cs b/Content.Server/NodeContainer/Nodes/PipeNode.cs index 8bee157688..54f0c0fb54 100644 --- a/Content.Server/NodeContainer/Nodes/PipeNode.cs +++ b/Content.Server/NodeContainer/Nodes/PipeNode.cs @@ -1,6 +1,7 @@ #nullable enable using System.Collections.Generic; using Content.Server.Atmos; +using Content.Server.Atmos.EntitySystems; using Content.Server.Interfaces; using Content.Server.NodeContainer; using Content.Server.NodeContainer.NodeGroups; @@ -104,7 +105,7 @@ namespace Content.Server.GameObjects.Components.NodeContainer.Nodes return; } - _pipeNet.Air.Merge(giver); + EntitySystem.Get().Merge(_pipeNet.Air, giver); } [ViewVariables] diff --git a/Content.Shared/Atmos/EntitySystems/SharedAtmosphereSystem.cs b/Content.Shared/Atmos/EntitySystems/SharedAtmosphereSystem.cs index a28035e3b2..9e52787813 100644 --- a/Content.Shared/Atmos/EntitySystems/SharedAtmosphereSystem.cs +++ b/Content.Shared/Atmos/EntitySystems/SharedAtmosphereSystem.cs @@ -14,7 +14,7 @@ namespace Content.Shared.Atmos.EntitySystems protected readonly GasPrototype[] GasPrototypes = new GasPrototype[Atmospherics.TotalNumberOfGases]; - private readonly SpriteSpecifier[] _gasOverlays = new SpriteSpecifier[Atmospherics.TotalNumberOfGases]; + private readonly SpriteSpecifier?[] _gasOverlays = new SpriteSpecifier[Atmospherics.TotalNumberOfGases]; public override void Initialize() { @@ -39,6 +39,6 @@ namespace Content.Shared.Atmos.EntitySystems public IEnumerable Gases => GasPrototypes; - public SpriteSpecifier GetOverlay(int overlayId) => _gasOverlays[overlayId]; + public SpriteSpecifier? GetOverlay(int overlayId) => _gasOverlays[overlayId]; } }