Refactors the AtmosphereSystem public-facing API to allow for multiple atmos backends. (#8134)

* Refactors the entirety of the AtmosphereSystem public-facing API to allow for multiple atmos backends.

* actually compiles

* Remove commented out code

* funny bracket

* Move archived moles, temperature from GasMixture to TileAtmosphere.

* WIP customizable map default mixture
still VERY buggy

* broken mess
aaaaaaaaaaaaa

* Fix lattice, etc not being considered space

* visualization for "IsSpace"

* help

* Update Content.Client/Atmos/Overlays/AtmosDebugOverlay.cs

Co-authored-by: Moony <moonheart08@users.noreply.github.com>

* Holy SHIT it compiles AGAIN

* Fix AtmosDeviceSystem crash at shutdown

* Fix immutable tiles on map blueprints not being fixed by fixgridatmos/revalidate.

* Use space instead of gasmixture immutable for heat capacity calculations

* Remove all LINDA-specific code from GasMixture, move it to TileAtmosphere/AtmosphereSystem instead.

* Fix roundstart tiles not processing

* Update Content.Server/Atmos/Commands/SetTemperatureCommand.cs

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>

* Update Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs

Changed Files tab is so large I can't commit both suggestions at once mfw

Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>

Co-authored-by: Moony <moonheart08@users.noreply.github.com>
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
Vera Aguilera Puerto
2022-07-04 16:51:34 +02:00
committed by GitHub
parent 43216a000f
commit aa9281d667
74 changed files with 1764 additions and 2141 deletions

View File

@@ -48,19 +48,11 @@ namespace Content.Server.Atmos.EntitySystems
return GetHeatCapacityCalculation(mixture.Moles, mixture.Immutable);
}
/// <summary>
/// Calculates the heat capacity for a gas mixture, using the archived values.
/// </summary>
public float GetHeatCapacityArchived(GasMixture mixture)
{
return GetHeatCapacityCalculation(mixture.MolesArchived, mixture.Immutable);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private float GetHeatCapacityCalculation(float[] moles, bool immutable)
private float GetHeatCapacityCalculation(float[] moles, bool space)
{
// 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))
if (space && MathHelper.CloseTo(NumericsHelpers.HorizontalAdd(moles), 0f))
{
return Atmospherics.SpaceHeatCapacity;
}
@@ -136,7 +128,7 @@ namespace Content.Server.Atmos.EntitySystems
if (MathF.Abs(receiver.Temperature - source.Temperature) > Atmospherics.MinimumTemperatureDeltaToConsider)
{
// Often this divides a pipe net into new and completely empty pipe nets
if (receiver.TotalMoles == 0)
if (receiver.TotalMoles == 0)
receiver.Temperature = source.Temperature;
else
{
@@ -154,140 +146,6 @@ namespace Content.Server.Atmos.EntitySystems
}
}
/// <summary>
/// Shares gas between two gas mixtures. Part of LINDA.
/// </summary>
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;
}
/// <summary>
/// Shares temperature between two mixtures, taking a conduction coefficient into account.
/// </summary>
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;
}
/// <summary>
/// Shares temperature between a gas mixture and an abstract sharer, taking a conduction coefficient into account.
/// </summary>
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;
}
/// <summary>
/// Releases gas from this mixture to the output mixture.
/// If the output mixture is null, then this is being released into space.
@@ -362,6 +220,62 @@ namespace Content.Server.Atmos.EntitySystems
Merge(destination, buffer);
}
/// <summary>
/// Checks whether a gas mixture is probably safe.
/// This only checks temperature and pressure, not gas composition.
/// </summary>
/// <param name="air">Mixture to be checked.</param>
/// <returns>Whether the mixture is probably safe.</returns>
public bool IsMixtureProbablySafe(GasMixture? air)
{
// Note that oxygen mix isn't checked, but survival boxes make that not necessary.
if (air == null)
return false;
switch (air.Pressure)
{
case <= Atmospherics.WarningLowPressure:
case >= Atmospherics.WarningHighPressure:
return false;
}
switch (air.Temperature)
{
case <= 260:
case >= 360:
return false;
}
return true;
}
/// <summary>
/// Compares two gas mixtures to see if they are within acceptable ranges for group processing to be enabled.
/// </summary>
public GasCompareResult CompareExchange(GasMixture sample, GasMixture otherSample)
{
var moles = 0f;
for(var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
{
var gasMoles = sample.Moles[i];
var delta = MathF.Abs(gasMoles - otherSample.Moles[i]);
if (delta > Atmospherics.MinimumMolesDeltaToMove && (delta > gasMoles * Atmospherics.MinimumAirRatioToMove))
return (GasCompareResult)i; // We can move gases!
moles += gasMoles;
}
if (moles > Atmospherics.MinimumMolesDeltaToMove)
{
var tempDelta = MathF.Abs(sample.Temperature - otherSample.Temperature);
if (tempDelta > Atmospherics.MinimumTemperatureDeltaToSuspend)
return GasCompareResult.TemperatureExchange; // There can be temperature exchange.
}
// No exchange at all!
return GasCompareResult.NoExchange;
}
/// <summary>
/// Performs reactions for a given gas mixture on an optional holder.
/// </summary>
@@ -401,5 +315,11 @@ namespace Content.Server.Atmos.EntitySystems
return reaction;
}
public enum GasCompareResult
{
NoExchange = -2,
TemperatureExchange = -1,
}
}
}