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 *

View File

@@ -26,6 +26,8 @@ namespace Content.Server.Atmos
[DataField("moles")] [ViewVariables]
public float[] Moles = new float[Atmospherics.AdjustedNumberOfGases];
public float[] MolesArchived = new float[Atmospherics.AdjustedNumberOfGases];
[DataField("temperature")] [ViewVariables]
private float _temperature = Atmospherics.TCMB;
@@ -70,6 +72,8 @@ namespace Content.Server.Atmos
}
}
public float TemperatureArchived { get; private set; }
[DataField("volume")] [ViewVariables]
public float Volume { get; set; }
@@ -90,6 +94,13 @@ namespace Content.Server.Atmos
Immutable = true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Archive()
{
Moles.AsSpan().CopyTo(MolesArchived.AsSpan());
TemperatureArchived = Temperature;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float GetMoles(int gasId)
{
@@ -240,6 +251,7 @@ namespace Content.Server.Atmos
{
// The arrays MUST have a specific length.
Array.Resize(ref Moles, Atmospherics.AdjustedNumberOfGases);
Array.Resize(ref MolesArchived, Atmospherics.AdjustedNumberOfGases);
}
public override bool Equals(object? obj)
@@ -254,10 +266,12 @@ 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)
&& _temperature.Equals(other._temperature)
&& ReactionResults.SequenceEqual(other.ReactionResults)
&& Immutable == other.Immutable
&& LastShare.Equals(other.LastShare)
&& TemperatureArchived.Equals(other.TemperatureArchived)
&& Volume.Equals(other.Volume);
}
@@ -268,10 +282,13 @@ namespace Content.Server.Atmos
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
{
var moles = Moles[i];
var molesArchived = MolesArchived[i];
hashCode.Add(moles);
hashCode.Add(molesArchived);
}
hashCode.Add(_temperature);
hashCode.Add(TemperatureArchived);
hashCode.Add(Immutable);
hashCode.Add(LastShare);
hashCode.Add(Volume);
@@ -284,9 +301,11 @@ namespace Content.Server.Atmos
var newMixture = new GasMixture()
{
Moles = (float[])Moles.Clone(),
MolesArchived = (float[])MolesArchived.Clone(),
_temperature = _temperature,
Immutable = Immutable,
LastShare = LastShare,
TemperatureArchived = TemperatureArchived,
Volume = Volume,
};
return newMixture;

View File

@@ -13,12 +13,18 @@ namespace Content.Server.Atmos
/// </summary>
public class TileAtmosphere : IGasMixtureHolder
{
[ViewVariables]
public int ArchivedCycle;
[ViewVariables]
public int CurrentCycle;
[ViewVariables]
public float Temperature { get; set; } = Atmospherics.T20C;
[ViewVariables]
public float TemperatureArchived { get; set; } = Atmospherics.T20C;
[ViewVariables]
public TileAtmosphere? PressureSpecificTarget { get; set; }
@@ -26,7 +32,7 @@ namespace Content.Server.Atmos
public float PressureDifference { get; set; }
[ViewVariables(VVAccess.ReadWrite)]
public float HeatCapacity { get; set; } = 1f;
public float HeatCapacity { get; set; } = Atmospherics.MinimumHeatCapacity;
[ViewVariables]
public float ThermalConductivity { get; set; } = 0.05f;

View File

@@ -138,6 +138,11 @@ namespace Content.Shared.Atmos
/// </summary>
public const float MinimumHeatCapacity = 0.0003f;
/// <summary>
/// For the purposes of making space "colder"
/// </summary>
public const float SpaceHeatCapacity = 7000f;
#region Excited Groups
/// <summary>

View File

@@ -6,6 +6,7 @@ using Robust.Shared.Serialization.Manager.Attributes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.ViewVariables;
using System.Collections.Generic;
using Content.Shared.Atmos;
namespace Content.Shared.Maps
{
@@ -38,6 +39,9 @@ namespace Content.Shared.Maps
[DataField("thermalConductivity")] public float ThermalConductivity { get; set; } = 0.05f;
// Heat capacity is opt-in, not opt-out.
[DataField("heatCapacity")] public float HeatCapacity = Atmospherics.MinimumHeatCapacity;
[DataField("item_drop", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
public string ItemDropPrototypeName { get; } = "FloorTileItemSteel";

View File

@@ -10,6 +10,9 @@
collection: footstep_floor
friction: 0.30
item_drop: FloorTileItemDark
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_elevator_shaft
@@ -22,6 +25,8 @@
footstep_sounds:
collection: footstep_floor
friction: 0.30
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_freezer
@@ -35,6 +40,8 @@
collection: footstep_floor
friction: 0.30
item_drop: FloorTileItemFreezer
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_hydro
@@ -47,6 +54,8 @@
footstep_sounds:
collection: footstep_floor
friction: 0.30
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_green_circuit
@@ -60,6 +69,8 @@
collection: footstep_floor
friction: 0.30
item_drop: FloorTileItemGCircuit
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_blue_circuit
@@ -72,6 +83,8 @@
footstep_sounds:
collection: footstep_floor
friction: 0.30
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_lino
@@ -85,6 +98,8 @@
collection: footstep_floor
friction: 0.30
item_drop: FloorTileItemLino
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_mono
@@ -98,6 +113,8 @@
collection: footstep_floor
friction: 0.30
item_drop: FloorTileItemMono
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_reinforced
@@ -111,6 +128,8 @@
collection: footstep_floor
friction: 0.30
item_drop: FloorTileItemReinforced
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_rock_vault
@@ -123,6 +142,8 @@
footstep_sounds:
collection: footstep_floor
friction: 0.30
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_showroom
@@ -136,6 +157,8 @@
collection: footstep_floor
friction: 0.30
item_drop: FloorTileItemShowroom
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_steel
@@ -149,6 +172,8 @@
collection: footstep_floor
friction: 0.30
item_drop: FloorTileItemSteel
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_steel_dirty
@@ -162,6 +187,8 @@
collection: footstep_floor
friction: 0.30
item_drop: FloorTileItemDirty
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_techmaint
@@ -175,6 +202,8 @@
collection: footstep_floor
friction: 0.30
item_drop: FloorTileItemTechmaint
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_white
@@ -188,6 +217,8 @@
collection: footstep_floor
friction: 0.25
item_drop: FloorTileItemWhite
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_asteroid_sand
@@ -200,6 +231,8 @@
footstep_sounds:
collection: footstep_asteroid
friction: 0.30
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_asteroid_tile
@@ -212,6 +245,8 @@
footstep_sounds:
collection: footstep_asteroid
friction: 0.30
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_asteroid_coarse_sand0
@@ -224,6 +259,8 @@
footstep_sounds:
collection: footstep_asteroid
friction: 0.30
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_asteroid_coarse_sand1
@@ -236,6 +273,8 @@
footstep_sounds:
collection: footstep_asteroid
friction: 0.30
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_asteroid_coarse_sand2
@@ -248,6 +287,8 @@
footstep_sounds:
collection: footstep_asteroid
friction: 0.30
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_asteroid_coarse_sand_dug
@@ -260,6 +301,8 @@
footstep_sounds:
collection: footstep_asteroid
friction: 0.30
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_snow
@@ -272,6 +315,8 @@
footstep_sounds:
collection: footstep_snow
friction: 0.30
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_gold
@@ -285,6 +330,8 @@
collection: footstep_floor
friction: 0.30
item_drop: FloorTileItemGold
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_silver
@@ -297,6 +344,8 @@
footstep_sounds:
collection: footstep_floor
friction: 0.30
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_glass
@@ -310,6 +359,8 @@
collection: footstep_floor
friction: 0.30
item_drop: SheetGlass1
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_rglass
@@ -323,6 +374,8 @@
collection: footstep_floor
friction: 0.30
item_drop: SheetRGlass1
thermalConductivity: 0.04
heatCapacity: 10000
- type: tile
name: floor_blue
@@ -335,3 +388,5 @@
footstep_sounds:
collection: footstep_floor
friction: 0.30
thermalConductivity: 0.04
heatCapacity: 10000

View File

@@ -6,3 +6,5 @@
is_subfloor: true
is_space: true
sturdy: false
thermalConductivity: 0.4
heatCapacity: 700000