The comparison for doing gas exchange used current and not archived moles. This could lead to update order-dependent gas spreading effects. To fix this, convert TileAtmosphere's MolesArchived and TemperatureArchived to a AirArchived, and use that in the comparison method. --------- Co-authored-by: PraxisMapper <praxismapper@gmail.com> Co-authored-by: Kevin Zheng <kevinz5000@gmail.com>
170 lines
6.5 KiB
C#
170 lines
6.5 KiB
C#
using Content.Server.Atmos.Components;
|
|
using Content.Shared.Atmos;
|
|
using Robust.Shared.Map.Components;
|
|
|
|
namespace Content.Server.Atmos.EntitySystems
|
|
{
|
|
public sealed partial class AtmosphereSystem
|
|
{
|
|
private void Superconduct(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile)
|
|
{
|
|
var directions = ConductivityDirections(gridAtmosphere, tile);
|
|
|
|
for(var i = 0; i < Atmospherics.Directions; i++)
|
|
{
|
|
var direction = (AtmosDirection) (1 << i);
|
|
if (!directions.IsFlagSet(direction))
|
|
continue;
|
|
|
|
var adjacent = tile.AdjacentTiles[i];
|
|
|
|
// TODO ATMOS handle adjacent being null.
|
|
if (adjacent == null || adjacent.ThermalConductivity == 0f)
|
|
continue;
|
|
|
|
if(adjacent.ArchivedCycle < gridAtmosphere.UpdateCounter)
|
|
Archive(adjacent, gridAtmosphere.UpdateCounter);
|
|
|
|
NeighborConductWithSource(gridAtmosphere, adjacent, tile);
|
|
|
|
ConsiderSuperconductivity(gridAtmosphere, adjacent);
|
|
}
|
|
|
|
RadiateToSpace(tile);
|
|
FinishSuperconduction(gridAtmosphere, tile);
|
|
}
|
|
|
|
private AtmosDirection ConductivityDirections(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile)
|
|
{
|
|
if(tile.Air == null)
|
|
{
|
|
if(tile.ArchivedCycle < gridAtmosphere.UpdateCounter)
|
|
Archive(tile, gridAtmosphere.UpdateCounter);
|
|
return AtmosDirection.All;
|
|
}
|
|
|
|
// TODO ATMOS check if this is correct
|
|
return AtmosDirection.All;
|
|
}
|
|
|
|
public bool ConsiderSuperconductivity(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile)
|
|
{
|
|
if (tile.ThermalConductivity == 0f || !Superconduction)
|
|
return false;
|
|
|
|
gridAtmosphere.SuperconductivityTiles.Add(tile);
|
|
return true;
|
|
}
|
|
|
|
public bool ConsiderSuperconductivity(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, bool starting)
|
|
{
|
|
if (!Superconduction)
|
|
return false;
|
|
|
|
if (tile.Air == null || tile.Air.Temperature < (starting
|
|
? Atmospherics.MinimumTemperatureStartSuperConduction
|
|
: Atmospherics.MinimumTemperatureForSuperconduction))
|
|
return false;
|
|
|
|
return !(GetHeatCapacity(tile.Air) < Atmospherics.MCellWithRatio)
|
|
&& ConsiderSuperconductivity(gridAtmosphere, tile);
|
|
}
|
|
|
|
public void FinishSuperconduction(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile)
|
|
{
|
|
// Conduct with air on my tile if I have it
|
|
if (tile.Air != null)
|
|
{
|
|
tile.Temperature = TemperatureShare(tile, tile.ThermalConductivity, tile.Temperature, tile.HeatCapacity);
|
|
}
|
|
|
|
FinishSuperconduction(gridAtmosphere, tile, tile.Air?.Temperature ?? tile.Temperature);
|
|
}
|
|
|
|
public void FinishSuperconduction(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, float temperature)
|
|
{
|
|
// Make sure it's still hot enough to continue conducting.
|
|
if (temperature < Atmospherics.MinimumTemperatureForSuperconduction)
|
|
{
|
|
gridAtmosphere.SuperconductivityTiles.Remove(tile);
|
|
}
|
|
}
|
|
|
|
public void NeighborConductWithSource(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, TileAtmosphere other)
|
|
{
|
|
if (tile.Air == null)
|
|
{
|
|
// TODO ATMOS: why does this need to check if a tile exists if it doesn't use the tile?
|
|
if (TryComp<MapGridComponent>(other.GridIndex, out var grid)
|
|
&& _mapSystem.TryGetTileRef(other.GridIndex, grid, other.GridIndices, out var _))
|
|
{
|
|
TemperatureShareOpenToSolid(other, tile);
|
|
}
|
|
else
|
|
{
|
|
TemperatureShareMutualSolid(other, tile, tile.ThermalConductivity);
|
|
}
|
|
|
|
// TODO ATMOS: tile.TemperatureExpose(null, tile.Temperature, gridAtmosphere.GetVolumeForCells(1));
|
|
return;
|
|
}
|
|
|
|
if (other.Air != null)
|
|
{
|
|
TemperatureShare(other, tile, Atmospherics.WindowHeatTransferCoefficient);
|
|
}
|
|
else
|
|
{
|
|
TemperatureShareOpenToSolid(tile, other);
|
|
}
|
|
|
|
AddActiveTile(gridAtmosphere, tile);
|
|
}
|
|
|
|
private void TemperatureShareOpenToSolid(TileAtmosphere tile, TileAtmosphere other)
|
|
{
|
|
if (tile.Air == null)
|
|
return;
|
|
|
|
other.Temperature = TemperatureShare(tile, other.ThermalConductivity, other.Temperature, other.HeatCapacity);
|
|
}
|
|
|
|
private void TemperatureShareMutualSolid(TileAtmosphere tile, TileAtmosphere other, float conductionCoefficient)
|
|
{
|
|
if (tile.AirArchived == null || other.AirArchived == null)
|
|
return;
|
|
|
|
var deltaTemperature = (tile.AirArchived.Temperature - other.AirArchived.Temperature);
|
|
if (MathF.Abs(deltaTemperature) > Atmospherics.MinimumTemperatureDeltaToConsider
|
|
&& tile.HeatCapacity != 0f && other.HeatCapacity != 0f)
|
|
{
|
|
var heat = conductionCoefficient * deltaTemperature *
|
|
(tile.HeatCapacity * other.HeatCapacity / (tile.HeatCapacity + other.HeatCapacity));
|
|
|
|
tile.Temperature -= heat / tile.HeatCapacity;
|
|
other.Temperature += heat / other.HeatCapacity;
|
|
}
|
|
}
|
|
|
|
public void RadiateToSpace(TileAtmosphere tile)
|
|
{
|
|
if (tile.AirArchived == null)
|
|
return;
|
|
|
|
// Considering 0ºC as the break even point for radiation in and out.
|
|
if (tile.Temperature > Atmospherics.T0C)
|
|
{
|
|
// Hardcoded space temperature.
|
|
var deltaTemperature = (tile.AirArchived.Temperature - Atmospherics.TCMB);
|
|
if ((tile.HeatCapacity > 0) && (MathF.Abs(deltaTemperature) > Atmospherics.MinimumTemperatureDeltaToConsider))
|
|
{
|
|
var heat = tile.ThermalConductivity * deltaTemperature * (tile.HeatCapacity *
|
|
Atmospherics.HeatCapacityVacuum / (tile.HeatCapacity + Atmospherics.HeatCapacityVacuum));
|
|
|
|
tile.Temperature -= heat;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|