Misc Atmos Improvements (#5613)

* Revert "Remove atmos archiving."

This reverts commit 7fa10bd17b.

* Explosive Depressurization now brings tiles down to TCMB.

* Tiles now specify heat capacity.

* Do not serialize archived gas mixture values.

* Remove bad idea

* dumb typo

* Space gas mixtures now have a harcoded heat capacity.
This is a bit of a hack, but rooms exposed to space now cool down properly when monstermos is disabled.
Huge thanks to @LemonInTheDark for helping me with this!

* Clean up heat capacity methods

* Better logging based on the original monstermos' logging

* Comment explosive depressurization hack better
This commit is contained in:
Vera Aguilera Puerto
2021-11-30 11:42:48 +01:00
committed by GitHub
parent 9db2fbefe1
commit 94fa6efefb
11 changed files with 157 additions and 31 deletions

View File

@@ -1,11 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Content.Server.Atmos.Reactions;
using Content.Shared.Atmos;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
using DependencyAttribute = Robust.Shared.IoC.DependencyAttribute;
namespace Content.Server.Atmos.EntitySystems
{
@@ -37,8 +38,25 @@ namespace Content.Server.Atmos.EntitySystems
public float GetHeatCapacity(GasMixture mixture)
{
Span<float> tmp = stackalloc float[mixture.Moles.Length];
NumericsHelpers.Multiply(mixture.Moles, GasSpecificHeats, tmp);
return GetHeatCapacityCalculation(mixture.Moles, mixture.Immutable);
}
public float GetHeatCapacityArchived(GasMixture mixture)
{
return GetHeatCapacityCalculation(mixture.MolesArchived, mixture.Immutable);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private float GetHeatCapacityCalculation(float[] moles, bool immutable)
{
// Little hack to make space gas mixtures have heat capacity, therefore allowing them to cool down rooms.
if (immutable && MathHelper.CloseTo(NumericsHelpers.HorizontalAdd(moles), 0f))
{
return Atmospherics.SpaceHeatCapacity;
}
Span<float> tmp = stackalloc float[moles.Length];
NumericsHelpers.Multiply(moles, GasSpecificHeats, tmp);
return MathF.Max(NumericsHelpers.HorizontalAdd(tmp), Atmospherics.MinimumHeatCapacity);
}
@@ -72,7 +90,7 @@ namespace Content.Server.Atmos.EntitySystems
public float Share(GasMixture receiver, GasMixture sharer, int atmosAdjacentTurfs)
{
var temperatureDelta = receiver.Temperature - sharer.Temperature;
var temperatureDelta = receiver.TemperatureArchived - sharer.TemperatureArchived;
var absTemperatureDelta = Math.Abs(temperatureDelta);
var oldHeatCapacity = 0f;
var oldSharerHeatCapacity = 0f;
@@ -123,12 +141,12 @@ namespace Content.Server.Atmos.EntitySystems
// 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.Temperature) + (heatCapacitySharerToThis * sharer.Temperature)) / newHeatCapacity;
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.Temperature) + (heatCapacityToSharer*receiver.Temperature)) / newSharerHeatCapacity;
sharer.Temperature = ((oldSharerHeatCapacity * sharer.Temperature) - (heatCapacitySharerToThis * sharer.TemperatureArchived) + (heatCapacityToSharer*receiver.TemperatureArchived)) / newSharerHeatCapacity;
}
// Thermal energy of the system (self and sharer) is unchanged.
@@ -147,17 +165,17 @@ namespace Content.Server.Atmos.EntitySystems
var moles = receiver.TotalMoles;
var theirMoles = sharer.TotalMoles;
return (receiver.Temperature * (moles + movedMoles)) - (sharer.Temperature * (theirMoles - movedMoles)) * Atmospherics.R / receiver.Volume;
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.Temperature - sharer.Temperature;
var temperatureDelta = receiver.TemperatureArchived - sharer.TemperatureArchived;
if (MathF.Abs(temperatureDelta) > Atmospherics.MinimumTemperatureDeltaToConsider)
{
var heatCapacity = GetHeatCapacity(receiver);
var sharerHeatCapacity = GetHeatCapacity(sharer);
var heatCapacity = GetHeatCapacityArchived(receiver);
var sharerHeatCapacity = GetHeatCapacityArchived(sharer);
if (sharerHeatCapacity > Atmospherics.MinimumHeatCapacity && heatCapacity > Atmospherics.MinimumHeatCapacity)
{
@@ -176,10 +194,10 @@ namespace Content.Server.Atmos.EntitySystems
public float TemperatureShare(GasMixture receiver, float conductionCoefficient, float sharerTemperature, float sharerHeatCapacity)
{
var temperatureDelta = receiver.Temperature - sharerTemperature;
var temperatureDelta = receiver.TemperatureArchived - sharerTemperature;
if (MathF.Abs(temperatureDelta) > Atmospherics.MinimumTemperatureDeltaToConsider)
{
var heatCapacity = GetHeatCapacity(receiver);
var heatCapacity = GetHeatCapacityArchived(receiver);
if (sharerHeatCapacity > Atmospherics.MinimumHeatCapacity && heatCapacity > Atmospherics.MinimumHeatCapacity)
{

View File

@@ -14,6 +14,9 @@ namespace Content.Server.Atmos.EntitySystems
return;
}
if (tile.ArchivedCycle < fireCount)
Archive(tile, fireCount);
tile.CurrentCycle = fireCount;
var adjacentTileLength = 0;
@@ -33,6 +36,7 @@ namespace Content.Server.Atmos.EntitySystems
// If the tile is null or has no air, we don't do anything for it.
if(enemyTile?.Air == null) continue;
if (fireCount <= enemyTile.CurrentCycle) continue;
Archive(enemyTile, fireCount);
var shouldShareAir = false;
@@ -107,6 +111,13 @@ namespace Content.Server.Atmos.EntitySystems
RemoveActiveTile(gridAtmosphere, tile);
}
private void Archive(TileAtmosphere tile, int fireCount)
{
tile.Air?.Archive();
tile.ArchivedCycle = fireCount;
tile.TemperatureArchived = tile.Temperature;
}
private void LastShareCheck(TileAtmosphere tile)
{
if (tile.Air == null || tile.ExcitedGroup == null)

View File

@@ -18,11 +18,6 @@ namespace Content.Server.Atmos.EntitySystems
{
[Dependency] private readonly IRobustRandom _robustRandom = default!;
/// <summary>
/// Threshold for logging explosive depressurization.
/// </summary>
private const float DepressurizationLogThreshold = Atmospherics.MolesCellStandard * 10;
private readonly TileAtmosphereComparer _monstermosComparer = new();
private readonly TileAtmosphere?[] _equalizeTiles = new TileAtmosphere[Atmospherics.MonstermosHardTileLimit];
@@ -92,7 +87,7 @@ namespace Content.Server.Atmos.EntitySystems
if(tileCount < Atmospherics.MonstermosHardTileLimit)
_equalizeTiles[tileCount++] = adj;
if (adj.Air.Immutable)
if (adj.Air.Immutable && MonstermosDepressurization)
{
// Looks like someone opened an airlock to space!
@@ -466,7 +461,14 @@ namespace Content.Server.Atmos.EntitySystems
otherTile2.PressureDirection = otherTile.MonstermosInfo.CurrentTransferDirection;
}
otherTile.Air?.Clear();
// This gas mixture cannot be null, no tile in _depressurizeProgressionOrder can have a null gas mixture
otherTile.Air!.Clear();
// This is a little hacky, but hear me out. It makes sense. We have just vacuumed all of the tile's air
// therefore there is no more gas in the tile, therefore the tile should be as cold as space!
otherTile.Air.Temperature = Atmospherics.TCMB;
InvalidateVisuals(otherTile.GridIndex, otherTile.GridIndices);
HandleDecompressionFloorRip(mapGrid, otherTile, sum);
}
@@ -482,7 +484,7 @@ namespace Content.Server.Atmos.EntitySystems
gridPhysics.ApplyAngularImpulse(Vector2.Cross(tile.GridIndices - gridPhysics.LocalCenter, direction) * totalMolesRemoved);
}
if(totalMolesRemoved > DepressurizationLogThreshold)
if(tileCount > 10 && (totalMolesRemoved / tileCount) > 20)
_adminLog.Add(LogType.ExplosiveDepressurization, LogImpact.High,
$"Explosive depressurization removed {totalMolesRemoved} moles from {tileCount} tiles starting from position {tile.GridIndices:position} on grid ID {tile.GridIndex:grid}");

View File

@@ -108,14 +108,13 @@ namespace Content.Server.Atmos.EntitySystems
tile.Air ??= new GasMixture(volume){Temperature = Atmospherics.T20C};
}
// By removing the active tile, we effectively remove its excited group, if any.
RemoveActiveTile(atmosphere, tile);
// Then we activate the tile again.
// We activate the tile.
AddActiveTile(atmosphere, tile);
// TODO ATMOS: Query all the contents of this tile (like walls) and calculate the correct thermal conductivity
tile.ThermalConductivity = tile.Tile?.Tile.GetContentTileDefinition().ThermalConductivity ?? 0.5f;
// TODO ATMOS: Query all the contents of this tile (like walls) and calculate the correct thermal conductivity and heat capacity
var tileDef = tile.Tile?.Tile.GetContentTileDefinition();
tile.ThermalConductivity = tileDef?.ThermalConductivity ?? 0.5f;
tile.HeatCapacity = tileDef?.HeatCapacity ?? float.PositiveInfinity;
InvalidateVisuals(mapGrid.Index, indices);
for (var i = 0; i < Atmospherics.Directions; i++)

View File

@@ -21,6 +21,9 @@ namespace Content.Server.Atmos.EntitySystems
if (adjacent == null || adjacent.ThermalConductivity == 0f)
continue;
if(adjacent.ArchivedCycle < gridAtmosphere.UpdateCounter)
Archive(adjacent, gridAtmosphere.UpdateCounter);
NeighborConductWithSource(gridAtmosphere, adjacent, tile);
ConsiderSuperconductivity(gridAtmosphere, adjacent);
@@ -34,6 +37,8 @@ namespace Content.Server.Atmos.EntitySystems
{
if(tile.Air == null)
{
if(tile.ArchivedCycle < gridAtmosphere.UpdateCounter)
Archive(tile, gridAtmosphere.UpdateCounter);
return AtmosDirection.All;
}
@@ -56,8 +61,8 @@ namespace Content.Server.Atmos.EntitySystems
return false;
if (tile.Air == null || tile.Air.Temperature < (starting
? Atmospherics.MinimumTemperatureStartSuperConduction
: Atmospherics.MinimumTemperatureForSuperconduction))
? Atmospherics.MinimumTemperatureStartSuperConduction
: Atmospherics.MinimumTemperatureForSuperconduction))
return false;
return !(GetHeatCapacity(tile.Air) < Atmospherics.MCellWithRatio)
@@ -123,7 +128,7 @@ namespace Content.Server.Atmos.EntitySystems
private void TemperatureShareMutualSolid(TileAtmosphere tile, TileAtmosphere other, float conductionCoefficient)
{
var deltaTemperature = (tile.Temperature - other.Temperature);
var deltaTemperature = (tile.TemperatureArchived - other.TemperatureArchived);
if (MathF.Abs(deltaTemperature) > Atmospherics.MinimumTemperatureDeltaToConsider
&& tile.HeatCapacity != 0f && other.HeatCapacity != 0f)
{
@@ -141,7 +146,7 @@ namespace Content.Server.Atmos.EntitySystems
if (tile.Temperature > Atmospherics.T0C)
{
// Hardcoded space temperature.
var deltaTemperature = (tile.Temperature - Atmospherics.TCMB);
var deltaTemperature = (tile.TemperatureArchived - Atmospherics.TCMB);
if ((tile.HeatCapacity > 0) && (MathF.Abs(deltaTemperature) > Atmospherics.MinimumTemperatureDeltaToConsider))
{
var heat = tile.ThermalConductivity * deltaTemperature * (tile.HeatCapacity *