Atmos optimizations (#1944)
* Adds IFireAct, ITemperatureExpose * Use AtmosDirection instead of Direction for Atmos * Refactor atmos to heavily rely on arrays and bitflags. Adds F A S T M O S and reduces atmos tech debt heavily. * Optimize and fix more stuff * Kinda improve superconduction * Pipenet is a word * T U R B O M O S * Address reviews * Small optimization * Superconduct is also a word * Remove check * Cleanup tile atmosphere * Correct a comment
This commit is contained in:
committed by
GitHub
parent
3758eb1b60
commit
fb0ac3d70e
16
Content.Server/Atmos/FireEvent.cs
Normal file
16
Content.Server/Atmos/FireEvent.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Server.Atmos
|
||||||
|
{
|
||||||
|
public class FireActEvent : EntitySystemMessage
|
||||||
|
{
|
||||||
|
public float Temperature { get; }
|
||||||
|
public float Volume { get; }
|
||||||
|
|
||||||
|
public FireActEvent(float temperature, float volume)
|
||||||
|
{
|
||||||
|
Temperature = temperature;
|
||||||
|
Volume = volume;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -129,17 +129,21 @@ namespace Content.Server.Atmos
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public float Volume { get; set; }
|
public float Volume { get; set; }
|
||||||
|
|
||||||
public GasMixture()
|
public GasMixture() : this(null)
|
||||||
{
|
{
|
||||||
_atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GasMixture(float volume)
|
public GasMixture(AtmosphereSystem? atmosphereSystem)
|
||||||
|
{
|
||||||
|
_atmosphereSystem = atmosphereSystem ?? EntitySystem.Get<AtmosphereSystem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GasMixture(float volume, AtmosphereSystem? atmosphereSystem = null)
|
||||||
{
|
{
|
||||||
if (volume < 0)
|
if (volume < 0)
|
||||||
volume = 0;
|
volume = 0;
|
||||||
Volume = volume;
|
Volume = volume;
|
||||||
_atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
_atmosphereSystem = atmosphereSystem ?? EntitySystem.Get<AtmosphereSystem>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -224,12 +228,12 @@ namespace Content.Server.Atmos
|
|||||||
public GasMixture RemoveRatio(float ratio)
|
public GasMixture RemoveRatio(float ratio)
|
||||||
{
|
{
|
||||||
if(ratio <= 0)
|
if(ratio <= 0)
|
||||||
return new GasMixture(Volume);
|
return new GasMixture(Volume, _atmosphereSystem);
|
||||||
|
|
||||||
if (ratio > 1)
|
if (ratio > 1)
|
||||||
ratio = 1;
|
ratio = 1;
|
||||||
|
|
||||||
var removed = new GasMixture {Volume = Volume, Temperature = Temperature};
|
var removed = new GasMixture(_atmosphereSystem) {Volume = Volume, Temperature = Temperature};
|
||||||
|
|
||||||
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||||
{
|
{
|
||||||
@@ -252,7 +256,7 @@ namespace Content.Server.Atmos
|
|||||||
public void CopyFromMutable(GasMixture sample)
|
public void CopyFromMutable(GasMixture sample)
|
||||||
{
|
{
|
||||||
if (Immutable) return;
|
if (Immutable) return;
|
||||||
sample._moles.AsSpan().CopyTo(_moles.AsSpan());
|
sample._moles.CopyTo(_moles, 0);
|
||||||
Temperature = sample.Temperature;
|
Temperature = sample.Temperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,8 +489,7 @@ namespace Content.Server.Atmos
|
|||||||
var temperature = Temperature;
|
var temperature = Temperature;
|
||||||
var energy = ThermalEnergy;
|
var energy = ThermalEnergy;
|
||||||
|
|
||||||
// TODO ATMOS Take reaction priority into account!
|
foreach (var prototype in _atmosphereSystem.GasReactions)
|
||||||
foreach (var prototype in IoCManager.Resolve<IPrototypeManager>().EnumeratePrototypes<GasReactionPrototype>())
|
|
||||||
{
|
{
|
||||||
if (energy < prototype.MinimumEnergyRequirement ||
|
if (energy < prototype.MinimumEnergyRequirement ||
|
||||||
temperature < prototype.MinimumTemperatureRequirement)
|
temperature < prototype.MinimumTemperatureRequirement)
|
||||||
@@ -508,7 +511,7 @@ namespace Content.Server.Atmos
|
|||||||
if (!doReaction)
|
if (!doReaction)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
reaction = prototype.React(this, holder);
|
reaction = prototype.React(this, holder, _atmosphereSystem.EventBus);
|
||||||
if(reaction.HasFlag(ReactionResult.StopReactions))
|
if(reaction.HasFlag(ReactionResult.StopReactions))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -588,7 +591,7 @@ namespace Content.Server.Atmos
|
|||||||
|
|
||||||
public object Clone()
|
public object Clone()
|
||||||
{
|
{
|
||||||
var newMixture = new GasMixture()
|
var newMixture = new GasMixture(_atmosphereSystem)
|
||||||
{
|
{
|
||||||
_moles = (float[])_moles.Clone(),
|
_moles = (float[])_moles.Clone(),
|
||||||
_molesArchived = (float[])_molesArchived.Clone(),
|
_molesArchived = (float[])_molesArchived.Clone(),
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using Content.Server.GameObjects.Components.Atmos;
|
using Content.Server.GameObjects.Components.Atmos;
|
||||||
|
using Content.Shared.Atmos;
|
||||||
using Robust.Shared.GameObjects.Components;
|
using Robust.Shared.GameObjects.Components;
|
||||||
using Robust.Shared.Interfaces.Physics;
|
using Robust.Shared.Interfaces.Physics;
|
||||||
using Robust.Shared.Interfaces.Random;
|
using Robust.Shared.Interfaces.Random;
|
||||||
@@ -24,7 +25,7 @@ namespace Content.Server.Atmos
|
|||||||
private const float ProbabilityBasePercent = 10f;
|
private const float ProbabilityBasePercent = 10f;
|
||||||
private const float ThrowForce = 100f;
|
private const float ThrowForce = 100f;
|
||||||
|
|
||||||
public void ExperiencePressureDifference(int cycle, float pressureDifference, Direction direction,
|
public void ExperiencePressureDifference(int cycle, float pressureDifference, AtmosDirection direction,
|
||||||
float pressureResistanceProbDelta, GridCoordinates throwTarget)
|
float pressureResistanceProbDelta, GridCoordinates throwTarget)
|
||||||
{
|
{
|
||||||
if (ControlledComponent == null)
|
if (ControlledComponent == null)
|
||||||
@@ -54,14 +55,14 @@ namespace Content.Server.Atmos
|
|||||||
if (throwTarget != GridCoordinates.InvalidGrid)
|
if (throwTarget != GridCoordinates.InvalidGrid)
|
||||||
{
|
{
|
||||||
var moveForce = maxForce * MathHelper.Clamp(moveProb, 0, 100) / 150f;
|
var moveForce = maxForce * MathHelper.Clamp(moveProb, 0, 100) / 150f;
|
||||||
var pos = ((throwTarget.Position - transform.GridPosition.Position).Normalized + direction.ToVec()).Normalized;
|
var pos = ((throwTarget.Position - transform.GridPosition.Position).Normalized + direction.ToDirection().ToVec()).Normalized;
|
||||||
LinearVelocity = pos * moveForce;
|
LinearVelocity = pos * moveForce;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var moveForce = MathF.Min(maxForce * MathHelper.Clamp(moveProb, 0, 100) / 2500f, 20f);
|
var moveForce = MathF.Min(maxForce * MathHelper.Clamp(moveProb, 0, 100) / 2500f, 20f);
|
||||||
LinearVelocity = direction.ToVec() * moveForce;
|
LinearVelocity = direction.ToDirection().ToVec() * moveForce;
|
||||||
}
|
}
|
||||||
|
|
||||||
pressureComponent.LastHighPressureMovementAirCycle = cycle;
|
pressureComponent.LastHighPressureMovementAirCycle = cycle;
|
||||||
|
|||||||
@@ -13,11 +13,6 @@ namespace Content.Server.Atmos
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
int UpdateCounter { get; }
|
int UpdateCounter { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// How many tiles have high pressure delta.
|
|
||||||
/// </summary>
|
|
||||||
int HighPressureDeltaCount { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Control variable for equalization.
|
/// Control variable for equalization.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -115,14 +110,14 @@ namespace Content.Server.Atmos
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="indices"></param>
|
/// <param name="indices"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
TileAtmosphere GetTile(MapIndices indices);
|
TileAtmosphere GetTile(MapIndices indices, bool createSpace = true);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a tile.
|
/// Returns a tile.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="coordinates"></param>
|
/// <param name="coordinates"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
TileAtmosphere GetTile(GridCoordinates coordinates);
|
TileAtmosphere GetTile(GridCoordinates coordinates, bool createSpace = true);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns if the tile in question is air-blocked.
|
/// Returns if the tile in question is air-blocked.
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
using YamlDotNet.RepresentationModel;
|
using YamlDotNet.RepresentationModel;
|
||||||
@@ -64,13 +65,13 @@ namespace Content.Server.Atmos.Reactions
|
|||||||
serializer.DataField(ref _effects, "effects", new List<IGasReactionEffect>());
|
serializer.DataField(ref _effects, "effects", new List<IGasReactionEffect>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactionResult React(GasMixture mixture, IGasMixtureHolder holder)
|
public ReactionResult React(GasMixture mixture, IGasMixtureHolder holder, IEventBus eventBus)
|
||||||
{
|
{
|
||||||
var result = ReactionResult.NoReaction;
|
var result = ReactionResult.NoReaction;
|
||||||
|
|
||||||
foreach (var effect in _effects)
|
foreach (var effect in _effects)
|
||||||
{
|
{
|
||||||
result |= effect.React(mixture, holder);
|
result |= effect.React(mixture, holder, eventBus);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
|
using Content.Server.Interfaces.GameObjects.Components.Interaction;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
|
using Content.Shared.Maps;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Server.Atmos.Reactions
|
namespace Content.Server.Atmos.Reactions
|
||||||
@@ -10,7 +14,7 @@ namespace Content.Server.Atmos.Reactions
|
|||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public class PhoronFireReaction : IGasReactionEffect
|
public class PhoronFireReaction : IGasReactionEffect
|
||||||
{
|
{
|
||||||
public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder)
|
public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, IEventBus eventBus)
|
||||||
{
|
{
|
||||||
var energyReleased = 0f;
|
var energyReleased = 0f;
|
||||||
var oldHeatCapacity = mixture.HeatCapacity;
|
var oldHeatCapacity = mixture.HeatCapacity;
|
||||||
@@ -71,9 +75,7 @@ namespace Content.Server.Atmos.Reactions
|
|||||||
{
|
{
|
||||||
location.HotspotExpose(temperature, mixture.Volume);
|
location.HotspotExpose(temperature, mixture.Volume);
|
||||||
|
|
||||||
// TODO ATMOS Expose temperature all items on cell
|
eventBus.QueueEvent(EventSource.Local, new TemperatureExposeEvent(location.GridIndices, location.GridIndex, mixture, temperature, mixture.Volume));
|
||||||
|
|
||||||
location.TemperatureExpose(mixture, temperature, mixture.Volume);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
|
using Content.Server.Interfaces.GameObjects.Components.Interaction;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
|
using Content.Shared.Maps;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Server.Atmos.Reactions
|
namespace Content.Server.Atmos.Reactions
|
||||||
@@ -13,7 +16,7 @@ namespace Content.Server.Atmos.Reactions
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder)
|
public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, IEventBus eventBus)
|
||||||
{
|
{
|
||||||
var energyReleased = 0f;
|
var energyReleased = 0f;
|
||||||
var oldHeatCapacity = mixture.HeatCapacity;
|
var oldHeatCapacity = mixture.HeatCapacity;
|
||||||
@@ -66,9 +69,7 @@ namespace Content.Server.Atmos.Reactions
|
|||||||
{
|
{
|
||||||
location.HotspotExpose(temperature, mixture.Volume);
|
location.HotspotExpose(temperature, mixture.Volume);
|
||||||
|
|
||||||
// TODO ATMOS Expose temperature all items on cell
|
eventBus.QueueEvent(EventSource.Local, new TemperatureExposeEvent(location.GridIndices, location.GridIndex, mixture, temperature, mixture.Volume));
|
||||||
|
|
||||||
location.TemperatureExpose(mixture, temperature, mixture.Volume);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
23
Content.Server/Atmos/TemperatureExposeEvent.cs
Normal file
23
Content.Server/Atmos/TemperatureExposeEvent.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
|
namespace Content.Server.Atmos
|
||||||
|
{
|
||||||
|
public class TemperatureExposeEvent : EntitySystemMessage
|
||||||
|
{
|
||||||
|
public MapIndices Indices { get; }
|
||||||
|
public GridId Grid { get; }
|
||||||
|
public GasMixture Air { get; }
|
||||||
|
public float Temperature { get; }
|
||||||
|
public float Volume { get; }
|
||||||
|
|
||||||
|
public TemperatureExposeEvent(MapIndices indices, GridId gridId, GasMixture air, float temperature, float volume)
|
||||||
|
{
|
||||||
|
Indices = indices;
|
||||||
|
Grid = gridId;
|
||||||
|
Air = air;
|
||||||
|
Temperature = temperature;
|
||||||
|
Volume = volume;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Content.Shared.Atmos;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
|
||||||
@@ -30,15 +31,15 @@ namespace Content.Server.Atmos
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public float TransferDirectionSouth;
|
public float TransferDirectionSouth;
|
||||||
|
|
||||||
public float this[Direction direction]
|
public float this[AtmosDirection direction]
|
||||||
{
|
{
|
||||||
get =>
|
get =>
|
||||||
direction switch
|
direction switch
|
||||||
{
|
{
|
||||||
Direction.East => TransferDirectionEast,
|
AtmosDirection.East => TransferDirectionEast,
|
||||||
Direction.West => TransferDirectionWest,
|
AtmosDirection.West => TransferDirectionWest,
|
||||||
Direction.North => TransferDirectionNorth,
|
AtmosDirection.North => TransferDirectionNorth,
|
||||||
Direction.South => TransferDirectionSouth,
|
AtmosDirection.South => TransferDirectionSouth,
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(direction))
|
_ => throw new ArgumentOutOfRangeException(nameof(direction))
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -46,16 +47,16 @@ namespace Content.Server.Atmos
|
|||||||
{
|
{
|
||||||
switch (direction)
|
switch (direction)
|
||||||
{
|
{
|
||||||
case Direction.East:
|
case AtmosDirection.East:
|
||||||
TransferDirectionEast = value;
|
TransferDirectionEast = value;
|
||||||
break;
|
break;
|
||||||
case Direction.West:
|
case AtmosDirection.West:
|
||||||
TransferDirectionWest = value;
|
TransferDirectionWest = value;
|
||||||
break;
|
break;
|
||||||
case Direction.North:
|
case AtmosDirection.North:
|
||||||
TransferDirectionNorth = value;
|
TransferDirectionNorth = value;
|
||||||
break;
|
break;
|
||||||
case Direction.South:
|
case AtmosDirection.South:
|
||||||
TransferDirectionSouth = value;
|
TransferDirectionSouth = value;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -64,10 +65,16 @@ namespace Content.Server.Atmos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float this[int index]
|
||||||
|
{
|
||||||
|
get => this[(AtmosDirection) (1 << index)];
|
||||||
|
set => this[(AtmosDirection) (1 << index)] = value;
|
||||||
|
}
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public float CurrentTransferAmount;
|
public float CurrentTransferAmount;
|
||||||
|
|
||||||
public Direction CurrentTransferDirection;
|
public AtmosDirection CurrentTransferDirection;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public bool FastDone;
|
public bool FastDone;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using System.Collections.Generic;
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Content.Server.Atmos.Reactions;
|
using Content.Server.Atmos.Reactions;
|
||||||
using Content.Server.GameObjects.Components.Atmos;
|
using Content.Server.GameObjects.Components.Atmos;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
|
||||||
using Content.Server.GameObjects.EntitySystems.Atmos;
|
using Content.Server.GameObjects.EntitySystems.Atmos;
|
||||||
using Content.Server.Interfaces;
|
using Content.Server.Interfaces;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
@@ -12,13 +11,13 @@ using Content.Shared.Audio;
|
|||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
using Robust.Server.GameObjects.EntitySystems;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Components;
|
using Robust.Shared.GameObjects.Components;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
using Robust.Shared.Interfaces.GameObjects;
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Map;
|
using Robust.Shared.Interfaces.Map;
|
||||||
using Robust.Shared.Interfaces.Random;
|
using Robust.Shared.Interfaces.Random;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Log;
|
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
@@ -28,18 +27,15 @@ namespace Content.Server.Atmos
|
|||||||
{
|
{
|
||||||
public class TileAtmosphere : IGasMixtureHolder
|
public class TileAtmosphere : IGasMixtureHolder
|
||||||
{
|
{
|
||||||
[Robust.Shared.IoC.Dependency] private IRobustRandom _robustRandom = default!;
|
[Robust.Shared.IoC.Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||||
[Robust.Shared.IoC.Dependency] private IEntityManager _entityManager = default!;
|
[Robust.Shared.IoC.Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
[Robust.Shared.IoC.Dependency] private IMapManager _mapManager = default!;
|
[Robust.Shared.IoC.Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
|
|
||||||
|
|
||||||
private static readonly TileAtmosphereComparer _comparer = new TileAtmosphereComparer();
|
private static readonly TileAtmosphereComparer Comparer = new TileAtmosphereComparer();
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables] private int _archivedCycle;
|
||||||
private int _archivedCycle = 0;
|
[ViewVariables] private int _currentCycle;
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
private int _currentCycle = 0;
|
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private static GasTileOverlaySystem _gasTileOverlaySystem;
|
private static GasTileOverlaySystem _gasTileOverlaySystem;
|
||||||
@@ -51,13 +47,13 @@ namespace Content.Server.Atmos
|
|||||||
private float _temperatureArchived = Atmospherics.T20C;
|
private float _temperatureArchived = Atmospherics.T20C;
|
||||||
|
|
||||||
// I know this being static is evil, but I seriously can't come up with a better solution to sound spam.
|
// I know this being static is evil, but I seriously can't come up with a better solution to sound spam.
|
||||||
private static int _soundCooldown = 0;
|
private static int _soundCooldown;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public TileAtmosphere PressureSpecificTarget { get; set; } = null;
|
public TileAtmosphere PressureSpecificTarget { get; set; }
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public float PressureDifference { get; set; } = 0;
|
public float PressureDifference { get; set; }
|
||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
public float HeatCapacity { get; set; } = 1f;
|
public float HeatCapacity { get; set; } = 1f;
|
||||||
@@ -66,13 +62,19 @@ namespace Content.Server.Atmos
|
|||||||
public float ThermalConductivity => Tile?.Tile.GetContentTileDefinition().ThermalConductivity ?? 0.05f;
|
public float ThermalConductivity => Tile?.Tile.GetContentTileDefinition().ThermalConductivity ?? 0.05f;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public bool Excited { get; set; } = false;
|
public bool Excited { get; set; }
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private GridAtmosphereComponent _gridAtmosphereComponent;
|
private readonly GridAtmosphereComponent _gridAtmosphereComponent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adjacent tiles in the same order as <see cref="AtmosDirection"/>. (NSEW)
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
private readonly TileAtmosphere[] _adjacentTiles = new TileAtmosphere[Atmospherics.Directions];
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private readonly Dictionary<Direction, TileAtmosphere> _adjacentTiles = new Dictionary<Direction, TileAtmosphere>();
|
private AtmosDirection _adjacentBits = AtmosDirection.Invalid;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private TileAtmosInfo _tileAtmosInfo;
|
private TileAtmosInfo _tileAtmosInfo;
|
||||||
@@ -80,7 +82,7 @@ namespace Content.Server.Atmos
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public Hotspot Hotspot;
|
public Hotspot Hotspot;
|
||||||
|
|
||||||
private Direction _pressureDirection;
|
private AtmosDirection _pressureDirection;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public GridId GridIndex { get; }
|
public GridId GridIndex { get; }
|
||||||
@@ -100,14 +102,16 @@ namespace Content.Server.Atmos
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public bool BlocksAir => _gridAtmosphereComponent.IsAirBlocked(GridIndices);
|
public bool BlocksAir => _gridAtmosphereComponent.IsAirBlocked(GridIndices);
|
||||||
|
|
||||||
public TileAtmosphere(GridAtmosphereComponent atmosphereComponent, GridId gridIndex, MapIndices gridIndices, GasMixture mixture = null)
|
public TileAtmosphere(GridAtmosphereComponent atmosphereComponent, GridId gridIndex, MapIndices gridIndices, GasMixture mixture = null, bool immutable = false)
|
||||||
{
|
{
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
_gridAtmosphereComponent = atmosphereComponent;
|
_gridAtmosphereComponent = atmosphereComponent;
|
||||||
GridIndex = gridIndex;
|
GridIndex = gridIndex;
|
||||||
GridIndices = gridIndices;
|
GridIndices = gridIndices;
|
||||||
Air = mixture;
|
Air = mixture;
|
||||||
ResetTileAtmosInfo();
|
|
||||||
|
if(immutable)
|
||||||
|
Air?.MarkImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -163,7 +167,7 @@ namespace Content.Server.Atmos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void HighPressureMovements()
|
public void HighPressureMovements()
|
||||||
{
|
{
|
||||||
// TODO ATMOS finish this
|
// TODO ATMOS finish this
|
||||||
@@ -175,7 +179,6 @@ namespace Content.Server.Atmos
|
|||||||
GridIndices.ToGridCoordinates(_mapManager, GridIndex), AudioHelpers.WithVariation(0.125f).WithVolume(MathHelper.Clamp(PressureDifference / 10, 10, 100)));
|
GridIndices.ToGridCoordinates(_mapManager, GridIndex), AudioHelpers.WithVariation(0.125f).WithVolume(MathHelper.Clamp(PressureDifference / 10, 10, 100)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
foreach (var entity in _entityManager.GetEntitiesIntersecting(_mapManager.GetGrid(GridIndex).ParentMapId, Box2.UnitCentered.Translated(GridIndices)))
|
foreach (var entity in _entityManager.GetEntitiesIntersecting(_mapManager.GetGrid(GridIndex).ParentMapId, Box2.UnitCentered.Translated(GridIndices)))
|
||||||
{
|
{
|
||||||
if (!entity.TryGetComponent(out ICollidableComponent physics)
|
if (!entity.TryGetComponent(out ICollidableComponent physics)
|
||||||
@@ -195,7 +198,7 @@ namespace Content.Server.Atmos
|
|||||||
|
|
||||||
if (PressureDifference > 100)
|
if (PressureDifference > 100)
|
||||||
{
|
{
|
||||||
// Do space wind graphics here!
|
// TODO ATMOS Do space wind graphics here!
|
||||||
}
|
}
|
||||||
|
|
||||||
_soundCooldown++;
|
_soundCooldown++;
|
||||||
@@ -220,20 +223,22 @@ namespace Content.Server.Atmos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void EqualizePressureInZone(int cycleNum)
|
public void EqualizePressureInZone(int cycleNum)
|
||||||
{
|
{
|
||||||
if (Air == null || (_tileAtmosInfo.LastCycle >= cycleNum)) return; // Already done.
|
if (Air == null || (_tileAtmosInfo.LastCycle >= cycleNum)) return; // Already done.
|
||||||
|
|
||||||
ResetTileAtmosInfo();
|
_tileAtmosInfo = new TileAtmosInfo();
|
||||||
|
|
||||||
|
|
||||||
var startingMoles = Air.TotalMoles;
|
var startingMoles = Air.TotalMoles;
|
||||||
var runAtmos = false;
|
var runAtmos = false;
|
||||||
|
|
||||||
// We need to figure if this is necessary
|
// We need to figure if this is necessary
|
||||||
foreach (var (direction, other) in _adjacentTiles)
|
for (var i = 0; i < Atmospherics.Directions; i++)
|
||||||
{
|
{
|
||||||
|
var direction = (AtmosDirection) (1 << i);
|
||||||
|
if (!_adjacentBits.HasFlag(direction)) continue;
|
||||||
|
var other = _adjacentTiles[i];
|
||||||
if (other?.Air == null) continue;
|
if (other?.Air == null) continue;
|
||||||
var comparisonMoles = other.Air.TotalMoles;
|
var comparisonMoles = other.Air.TotalMoles;
|
||||||
if (!(MathF.Abs(comparisonMoles - startingMoles) > Atmospherics.MinimumMolesDeltaToMove)) continue;
|
if (!(MathF.Abs(comparisonMoles - startingMoles) > Atmospherics.MinimumMolesDeltaToMove)) continue;
|
||||||
@@ -265,13 +270,15 @@ namespace Content.Server.Atmos
|
|||||||
totalMoles += tileMoles;
|
totalMoles += tileMoles;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (_, adj) in exploring._adjacentTiles)
|
for (var j = 0; j < Atmospherics.Directions; j++)
|
||||||
{
|
{
|
||||||
|
var direction = (AtmosDirection) (1 << j);
|
||||||
|
if (!exploring._adjacentBits.HasFlag(direction)) continue;
|
||||||
|
var adj = exploring._adjacentTiles[j];
|
||||||
if (adj?.Air == null) continue;
|
if (adj?.Air == null) continue;
|
||||||
if(adj._tileAtmosInfo.LastQueueCycle == queueCycle) continue;
|
if(adj._tileAtmosInfo.LastQueueCycle == queueCycle) continue;
|
||||||
adj.ResetTileAtmosInfo();
|
adj._tileAtmosInfo = new TileAtmosInfo {LastQueueCycle = queueCycle};
|
||||||
|
|
||||||
adj._tileAtmosInfo.LastQueueCycle = queueCycle;
|
|
||||||
if(tileCount < Atmospherics.ZumosHardTileLimit)
|
if(tileCount < Atmospherics.ZumosHardTileLimit)
|
||||||
tiles[tileCount++] = adj;
|
tiles[tileCount++] = adj;
|
||||||
if (adj.Air.Immutable)
|
if (adj.Air.Immutable)
|
||||||
@@ -326,47 +333,42 @@ namespace Content.Server.Atmos
|
|||||||
if (giverTilesLength > logN && takerTilesLength > logN)
|
if (giverTilesLength > logN && takerTilesLength > logN)
|
||||||
{
|
{
|
||||||
// Even if it fails, it will speed up the next part.
|
// Even if it fails, it will speed up the next part.
|
||||||
Array.Sort(tiles, 0, tileCount, _comparer);
|
Array.Sort(tiles, 0, tileCount, Comparer);
|
||||||
|
|
||||||
for (var i = 0; i < tileCount; i++)
|
for (var i = 0; i < tileCount; i++)
|
||||||
{
|
{
|
||||||
var tile = tiles[i];
|
var tile = tiles[i];
|
||||||
tile._tileAtmosInfo.FastDone = true;
|
tile._tileAtmosInfo.FastDone = true;
|
||||||
if (!(tile._tileAtmosInfo.MoleDelta > 0)) continue;
|
if (!(tile._tileAtmosInfo.MoleDelta > 0)) continue;
|
||||||
var eligibleDirections = ArrayPool<Direction>.Shared.Rent(4);
|
var eligibleDirections = AtmosDirection.Invalid;
|
||||||
var eligibleDirectionCount = 0;
|
var eligibleDirectionCount = 0;
|
||||||
foreach (var direction in Cardinal)
|
for (var j = 0; j < Atmospherics.Directions; j++)
|
||||||
{
|
{
|
||||||
if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
|
var direction = (AtmosDirection) (1 << j);
|
||||||
|
if (!tile._adjacentBits.HasFlag(direction)) continue;
|
||||||
|
var tile2 = tile._adjacentTiles[j];
|
||||||
|
|
||||||
// skip anything that isn't part of our current processing block.
|
// skip anything that isn't part of our current processing block.
|
||||||
if (tile2._tileAtmosInfo.FastDone || tile2._tileAtmosInfo.LastQueueCycle != queueCycle)
|
if (tile2._tileAtmosInfo.FastDone || tile2._tileAtmosInfo.LastQueueCycle != queueCycle)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
eligibleDirections[eligibleDirectionCount++] = direction;
|
eligibleDirections |= direction;
|
||||||
|
eligibleDirectionCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eligibleDirectionCount <= 0)
|
if (eligibleDirectionCount <= 0)
|
||||||
continue; // Oof we've painted ourselves into a corner. Bad luck. Next part will handle this.
|
continue; // Oof we've painted ourselves into a corner. Bad luck. Next part will handle this.
|
||||||
|
|
||||||
var molesToMove = tile._tileAtmosInfo.MoleDelta / eligibleDirectionCount;
|
var molesToMove = tile._tileAtmosInfo.MoleDelta / eligibleDirectionCount;
|
||||||
foreach (var direction in Cardinal)
|
for (var j = 0; j < Atmospherics.Directions; j++)
|
||||||
{
|
{
|
||||||
var hasDirection = false;
|
var direction = (AtmosDirection) (1 << j);
|
||||||
for (var j = 0; j < eligibleDirectionCount; j++)
|
if (!eligibleDirections.HasFlag(direction)) continue;
|
||||||
{
|
|
||||||
if (eligibleDirections[j] != direction) continue;
|
|
||||||
hasDirection = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasDirection || !tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
|
|
||||||
tile.AdjustEqMovement(direction, molesToMove);
|
tile.AdjustEqMovement(direction, molesToMove);
|
||||||
tile._tileAtmosInfo.MoleDelta -= molesToMove;
|
tile._tileAtmosInfo.MoleDelta -= molesToMove;
|
||||||
tile2._tileAtmosInfo.MoleDelta += molesToMove;
|
tile._adjacentTiles[j]._tileAtmosInfo.MoleDelta += molesToMove;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayPool<Direction>.Shared.Return(eligibleDirections);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
giverTilesLength = 0;
|
giverTilesLength = 0;
|
||||||
@@ -393,7 +395,7 @@ namespace Content.Server.Atmos
|
|||||||
for (var j = 0; j < giverTilesLength; j++)
|
for (var j = 0; j < giverTilesLength; j++)
|
||||||
{
|
{
|
||||||
var giver = giverTiles[j];
|
var giver = giverTiles[j];
|
||||||
giver._tileAtmosInfo.CurrentTransferDirection = (Direction) (-1);
|
giver._tileAtmosInfo.CurrentTransferDirection = AtmosDirection.Invalid;
|
||||||
giver._tileAtmosInfo.CurrentTransferAmount = 0;
|
giver._tileAtmosInfo.CurrentTransferAmount = 0;
|
||||||
var queueCycleSlow = ++_gridAtmosphereComponent.EqualizationQueueCycleControl;
|
var queueCycleSlow = ++_gridAtmosphereComponent.EqualizationQueueCycleControl;
|
||||||
var queueLength = 0;
|
var queueLength = 0;
|
||||||
@@ -405,9 +407,11 @@ namespace Content.Server.Atmos
|
|||||||
break; // We're done here now. Let's not do more work than needed.
|
break; // We're done here now. Let's not do more work than needed.
|
||||||
|
|
||||||
var tile = queue[i];
|
var tile = queue[i];
|
||||||
foreach (var direction in Cardinal)
|
for (var k = 0; k < Atmospherics.Directions; k++)
|
||||||
{
|
{
|
||||||
if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
|
var direction = (AtmosDirection) (1 << k);
|
||||||
|
if (!tile._adjacentBits.HasFlag(direction)) continue;
|
||||||
|
var tile2 = tile._adjacentTiles[k];
|
||||||
if (giver._tileAtmosInfo.MoleDelta <= 0) break; // We're done here now. Let's not do more work than needed.
|
if (giver._tileAtmosInfo.MoleDelta <= 0) break; // We're done here now. Let's not do more work than needed.
|
||||||
if (tile2._tileAtmosInfo.LastQueueCycle != queueCycle) continue;
|
if (tile2._tileAtmosInfo.LastQueueCycle != queueCycle) continue;
|
||||||
if (tile2._tileAtmosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
|
if (tile2._tileAtmosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
|
||||||
@@ -441,15 +445,11 @@ namespace Content.Server.Atmos
|
|||||||
for (var i = queueLength - 1; i >= 0; i--)
|
for (var i = queueLength - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var tile = queue[i];
|
var tile = queue[i];
|
||||||
if (tile._tileAtmosInfo.CurrentTransferAmount != 0 &&
|
if (tile._tileAtmosInfo.CurrentTransferAmount != 0 && tile._tileAtmosInfo.CurrentTransferDirection != AtmosDirection.Invalid)
|
||||||
tile._tileAtmosInfo.CurrentTransferDirection != (Direction) (-1))
|
|
||||||
{
|
{
|
||||||
tile.AdjustEqMovement(tile._tileAtmosInfo.CurrentTransferDirection,
|
tile.AdjustEqMovement(tile._tileAtmosInfo.CurrentTransferDirection, tile._tileAtmosInfo.CurrentTransferAmount);
|
||||||
tile._tileAtmosInfo.CurrentTransferAmount);
|
tile._adjacentTiles[tile._tileAtmosInfo.CurrentTransferDirection.ToIndex()]
|
||||||
if (tile._adjacentTiles.TryGetValue(tile._tileAtmosInfo.CurrentTransferDirection,
|
._tileAtmosInfo.CurrentTransferAmount += tile._tileAtmosInfo.CurrentTransferAmount;
|
||||||
out var adjacent))
|
|
||||||
adjacent._tileAtmosInfo.CurrentTransferAmount +=
|
|
||||||
tile._tileAtmosInfo.CurrentTransferAmount;
|
|
||||||
tile._tileAtmosInfo.CurrentTransferAmount = 0;
|
tile._tileAtmosInfo.CurrentTransferAmount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -463,7 +463,7 @@ namespace Content.Server.Atmos
|
|||||||
for (var j = 0; j < takerTilesLength; j++)
|
for (var j = 0; j < takerTilesLength; j++)
|
||||||
{
|
{
|
||||||
var taker = takerTiles[j];
|
var taker = takerTiles[j];
|
||||||
taker._tileAtmosInfo.CurrentTransferDirection = Direction.Invalid;
|
taker._tileAtmosInfo.CurrentTransferDirection = AtmosDirection.Invalid;
|
||||||
taker._tileAtmosInfo.CurrentTransferAmount = 0;
|
taker._tileAtmosInfo.CurrentTransferAmount = 0;
|
||||||
var queueCycleSlow = ++_gridAtmosphereComponent.EqualizationQueueCycleControl;
|
var queueCycleSlow = ++_gridAtmosphereComponent.EqualizationQueueCycleControl;
|
||||||
var queueLength = 0;
|
var queueLength = 0;
|
||||||
@@ -475,10 +475,11 @@ namespace Content.Server.Atmos
|
|||||||
break; // We're done here now. Let's not do more work than needed.
|
break; // We're done here now. Let's not do more work than needed.
|
||||||
|
|
||||||
var tile = queue[i];
|
var tile = queue[i];
|
||||||
foreach (var direction in Cardinal)
|
for (var k = 0; k < Atmospherics.Directions; k++)
|
||||||
{
|
{
|
||||||
if (!tile._adjacentTiles.ContainsKey(direction)) continue;
|
var direction = (AtmosDirection) (1 << k);
|
||||||
var tile2 = tile._adjacentTiles[direction];
|
if (!tile._adjacentBits.HasFlag(direction)) continue;
|
||||||
|
var tile2 = tile._adjacentTiles[k];
|
||||||
|
|
||||||
if (taker._tileAtmosInfo.MoleDelta >= 0) break; // We're done here now. Let's not do more work than needed.
|
if (taker._tileAtmosInfo.MoleDelta >= 0) break; // We're done here now. Let's not do more work than needed.
|
||||||
if (tile2._tileAtmosInfo.LastQueueCycle != queueCycle) continue;
|
if (tile2._tileAtmosInfo.LastQueueCycle != queueCycle) continue;
|
||||||
@@ -512,18 +513,16 @@ namespace Content.Server.Atmos
|
|||||||
for (var i = queueLength - 1; i >= 0; i--)
|
for (var i = queueLength - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var tile = queue[i];
|
var tile = queue[i];
|
||||||
if (tile._tileAtmosInfo.CurrentTransferAmount == 0 || tile._tileAtmosInfo.CurrentTransferDirection == Direction.Invalid)
|
if (tile._tileAtmosInfo.CurrentTransferAmount == 0 || tile._tileAtmosInfo.CurrentTransferDirection == AtmosDirection.Invalid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tile.AdjustEqMovement(tile._tileAtmosInfo.CurrentTransferDirection, tile._tileAtmosInfo.CurrentTransferAmount);
|
tile.AdjustEqMovement(tile._tileAtmosInfo.CurrentTransferDirection, tile._tileAtmosInfo.CurrentTransferAmount);
|
||||||
|
|
||||||
if (tile._adjacentTiles.TryGetValue(tile._tileAtmosInfo.CurrentTransferDirection, out var adjacent))
|
tile._adjacentTiles[tile._tileAtmosInfo.CurrentTransferDirection.ToIndex()]
|
||||||
{
|
._tileAtmosInfo.CurrentTransferAmount += tile._tileAtmosInfo.CurrentTransferAmount;
|
||||||
adjacent._tileAtmosInfo.CurrentTransferAmount += tile._tileAtmosInfo.CurrentTransferAmount;
|
|
||||||
tile._tileAtmosInfo.CurrentTransferAmount = 0;
|
tile._tileAtmosInfo.CurrentTransferAmount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ArrayPool<TileAtmosphere>.Shared.Return(queue);
|
ArrayPool<TileAtmosphere>.Shared.Return(queue);
|
||||||
}
|
}
|
||||||
@@ -537,9 +536,11 @@ namespace Content.Server.Atmos
|
|||||||
for (var i = 0; i < tileCount; i++)
|
for (var i = 0; i < tileCount; i++)
|
||||||
{
|
{
|
||||||
var tile = tiles[i];
|
var tile = tiles[i];
|
||||||
foreach (var direction in Cardinal)
|
for (var j = 0; j < Atmospherics.Directions; j++)
|
||||||
{
|
{
|
||||||
if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
|
var direction = (AtmosDirection) (1 << j);
|
||||||
|
if (!tile._adjacentBits.HasFlag(direction)) continue;
|
||||||
|
var tile2 = tile._adjacentTiles[j];
|
||||||
if (tile2?.Air?.Compare(Air) == GasMixture.GasCompareResult.NoExchange) continue;
|
if (tile2?.Air?.Compare(Air) == GasMixture.GasCompareResult.NoExchange) continue;
|
||||||
_gridAtmosphereComponent.AddActiveTile(tile2);
|
_gridAtmosphereComponent.AddActiveTile(tile2);
|
||||||
break;
|
break;
|
||||||
@@ -555,69 +556,68 @@ namespace Content.Server.Atmos
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void FinalizeEq()
|
private void FinalizeEq()
|
||||||
{
|
{
|
||||||
var transferDirections = new Dictionary<Direction, float>();
|
var transferDirections = new float[Atmospherics.Directions];
|
||||||
var hasTransferDirs = false;
|
var hasTransferDirs = false;
|
||||||
foreach (var direction in Cardinal)
|
for (var i = 0; i < Atmospherics.Directions; i++)
|
||||||
{
|
{
|
||||||
var amount = _tileAtmosInfo[direction];
|
var amount = _tileAtmosInfo[i];
|
||||||
if (amount == 0) continue;
|
if (amount == 0) continue;
|
||||||
transferDirections[direction] = amount;
|
transferDirections[i] = amount;
|
||||||
_tileAtmosInfo[direction] = 0;
|
_tileAtmosInfo[i] = 0; // Set them to 0 to prevent infinite recursion.
|
||||||
hasTransferDirs = true;
|
hasTransferDirs = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasTransferDirs) return;
|
if (!hasTransferDirs) return;
|
||||||
|
|
||||||
foreach (var (direction, amount) in transferDirections)
|
for(var i = 0; i < Atmospherics.Directions; i++)
|
||||||
{
|
{
|
||||||
if (!_adjacentTiles.TryGetValue(direction, out var tile) || tile.Air == null) continue;
|
var direction = (AtmosDirection) (1 << i);
|
||||||
|
if (!_adjacentBits.HasFlag(direction)) continue;
|
||||||
|
var amount = transferDirections[i];
|
||||||
|
var tile = _adjacentTiles[i];
|
||||||
|
if (tile?.Air == null) continue;
|
||||||
if (amount > 0)
|
if (amount > 0)
|
||||||
{
|
{
|
||||||
if (Air.TotalMoles < amount)
|
if (Air.TotalMoles < amount)
|
||||||
FinalizeEqNeighbors(transferDirections.Keys);
|
FinalizeEqNeighbors(transferDirections);
|
||||||
|
|
||||||
|
tile._tileAtmosInfo[direction.GetOpposite()] = 0;
|
||||||
tile.Air.Merge(Air.Remove(amount));
|
tile.Air.Merge(Air.Remove(amount));
|
||||||
UpdateVisuals();
|
UpdateVisuals();
|
||||||
tile.UpdateVisuals();
|
tile.UpdateVisuals();
|
||||||
ConsiderPressureDifference(direction, amount);
|
ConsiderPressureDifference(tile, amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void FinalizeEqNeighbors(IEnumerable<Direction> directions)
|
private void FinalizeEqNeighbors(in float[] transferDirs)
|
||||||
{
|
{
|
||||||
foreach (var direction in directions)
|
for (var i = 0; i < Atmospherics.Directions; i++)
|
||||||
{
|
{
|
||||||
var amount = _tileAtmosInfo[direction];
|
var direction = (AtmosDirection) (1 << i);
|
||||||
if(amount < 0 && _adjacentTiles.TryGetValue(direction, out var adjacent))
|
var amount = transferDirs[i];
|
||||||
adjacent.FinalizeEq();
|
if(amount < 0 && _adjacentBits.HasFlag(direction))
|
||||||
|
_adjacentTiles[i].FinalizeEq(); // A bit of recursion if needed.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void ConsiderPressureDifference(Direction direction, float difference)
|
private void ConsiderPressureDifference(TileAtmosphere other, float difference)
|
||||||
{
|
{
|
||||||
_gridAtmosphereComponent.AddHighPressureDelta(this);
|
_gridAtmosphereComponent.AddHighPressureDelta(this);
|
||||||
if (difference > PressureDifference)
|
if (difference > PressureDifference)
|
||||||
{
|
{
|
||||||
PressureDifference = difference;
|
PressureDifference = difference;
|
||||||
_pressureDirection = difference < 0 ? direction.GetOpposite() : direction;
|
_pressureDirection = ((Vector2i)(GridIndices - other.GridIndices)).GetDir().ToAtmosDirection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void AdjustEqMovement(Direction direction, float molesToMove)
|
private void AdjustEqMovement(AtmosDirection direction, float amount)
|
||||||
{
|
{
|
||||||
_tileAtmosInfo[direction] += molesToMove;
|
_tileAtmosInfo[direction] += amount;
|
||||||
if(direction != Direction.Invalid && _adjacentTiles.TryGetValue(direction, out var adj))
|
_adjacentTiles[direction.ToIndex()]._tileAtmosInfo[direction.GetOpposite()] -= amount;
|
||||||
adj._tileAtmosInfo[direction.GetOpposite()] -= molesToMove;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private void ResetTileAtmosInfo()
|
|
||||||
{
|
|
||||||
_tileAtmosInfo = new TileAtmosInfo {CurrentTransferDirection = Direction.Invalid};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -635,9 +635,13 @@ namespace Content.Server.Atmos
|
|||||||
|
|
||||||
_currentCycle = fireCount;
|
_currentCycle = fireCount;
|
||||||
var adjacentTileLength = 0;
|
var adjacentTileLength = 0;
|
||||||
foreach (var (direction, enemyTile) in _adjacentTiles)
|
for(var i = 0; i < Atmospherics.Directions; i++)
|
||||||
{
|
{
|
||||||
// If the tile is null or has no air, we don't do anything
|
var direction = (AtmosDirection) (1 << i);
|
||||||
|
if (!_adjacentBits.HasFlag(direction)) continue;
|
||||||
|
var enemyTile = _adjacentTiles[i];
|
||||||
|
|
||||||
|
// If the tile is null or has no air, we don't do anything for it.
|
||||||
if(enemyTile?.Air == null) continue;
|
if(enemyTile?.Air == null) continue;
|
||||||
adjacentTileLength++;
|
adjacentTileLength++;
|
||||||
if (fireCount <= enemyTile._currentCycle) continue;
|
if (fireCount <= enemyTile._currentCycle) continue;
|
||||||
@@ -685,11 +689,11 @@ namespace Content.Server.Atmos
|
|||||||
// Space wind!
|
// Space wind!
|
||||||
if (difference > 0)
|
if (difference > 0)
|
||||||
{
|
{
|
||||||
ConsiderPressureDifference(direction, difference);
|
ConsiderPressureDifference(enemyTile, difference);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
enemyTile.ConsiderPressureDifference(direction.GetOpposite(), -difference);
|
enemyTile.ConsiderPressureDifference(this, -difference);
|
||||||
}
|
}
|
||||||
|
|
||||||
LastShareCheck();
|
LastShareCheck();
|
||||||
@@ -737,7 +741,7 @@ namespace Content.Server.Atmos
|
|||||||
if (Air.Temperature > Atmospherics.FireMinimumTemperatureToSpread)
|
if (Air.Temperature > Atmospherics.FireMinimumTemperatureToSpread)
|
||||||
{
|
{
|
||||||
var radiatedTemperature = Air.Temperature * Atmospherics.FireSpreadRadiosityScale;
|
var radiatedTemperature = Air.Temperature * Atmospherics.FireSpreadRadiosityScale;
|
||||||
foreach (var (_, tile) in _adjacentTiles)
|
foreach (var tile in _adjacentTiles)
|
||||||
{
|
{
|
||||||
if(!tile.Hotspot.Valid)
|
if(!tile.Hotspot.Valid)
|
||||||
tile.HotspotExpose(radiatedTemperature, Atmospherics.CellVolume/4);
|
tile.HotspotExpose(radiatedTemperature, Atmospherics.CellVolume/4);
|
||||||
@@ -771,17 +775,19 @@ namespace Content.Server.Atmos
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var affected = Air.RemoveRatio(Hotspot.Volume / Air.Volume);
|
var affected = Air.RemoveRatio(Hotspot.Volume / Air.Volume);
|
||||||
if (affected != null)
|
|
||||||
{
|
|
||||||
affected.Temperature = Hotspot.Temperature;
|
affected.Temperature = Hotspot.Temperature;
|
||||||
affected.React(this);
|
affected.React(this);
|
||||||
Hotspot.Temperature = affected.Temperature;
|
Hotspot.Temperature = affected.Temperature;
|
||||||
Hotspot.Volume = affected.ReactionResults[GasReaction.Fire] * Atmospherics.FireGrowthRate;
|
Hotspot.Volume = affected.ReactionResults[GasReaction.Fire] * Atmospherics.FireGrowthRate;
|
||||||
AssumeAir(affected);
|
AssumeAir(affected);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// TODO ATMOS Let all entities in this tile know about the fire?
|
var tileRef = GridIndices.GetTileRef(GridIndex);
|
||||||
|
|
||||||
|
if (tileRef == null) return;
|
||||||
|
|
||||||
|
_gridAtmosphereComponent.Owner.EntityManager.
|
||||||
|
EventBus.QueueEvent(EventSource.Local, new FireActEvent(Hotspot.Temperature, Hotspot.Volume));
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ConsiderSuperconductivity()
|
private bool ConsiderSuperconductivity()
|
||||||
@@ -806,15 +812,16 @@ namespace Content.Server.Atmos
|
|||||||
public void Superconduct()
|
public void Superconduct()
|
||||||
{
|
{
|
||||||
var directions = ConductivityDirections();
|
var directions = ConductivityDirections();
|
||||||
var adjacentTiles = _gridAtmosphereComponent.GetAdjacentTiles(GridIndices, true);
|
|
||||||
|
|
||||||
if (directions.Length > 0)
|
for(var i = 0; i < Atmospherics.Directions; i++)
|
||||||
{
|
{
|
||||||
foreach (var direction in directions)
|
var direction = (AtmosDirection) (1 << i);
|
||||||
{
|
if (!directions.HasFlag(direction)) continue;
|
||||||
if (!adjacentTiles.TryGetValue(direction, out var adjacent)) continue;
|
|
||||||
|
|
||||||
if (adjacent.ThermalConductivity == 0f)
|
var adjacent = _adjacentTiles[direction.ToIndex()];
|
||||||
|
|
||||||
|
// TODO ATMOS handle adjacent being null.
|
||||||
|
if (adjacent == null || adjacent.ThermalConductivity == 0f)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(adjacent._archivedCycle < _gridAtmosphereComponent.UpdateCounter)
|
if(adjacent._archivedCycle < _gridAtmosphereComponent.UpdateCounter)
|
||||||
@@ -824,7 +831,6 @@ namespace Content.Server.Atmos
|
|||||||
|
|
||||||
adjacent.ConsiderSuperconductivity();
|
adjacent.ConsiderSuperconductivity();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
RadiateToSpace();
|
RadiateToSpace();
|
||||||
|
|
||||||
@@ -917,20 +923,20 @@ namespace Content.Server.Atmos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Direction[] ConductivityDirections()
|
public AtmosDirection ConductivityDirections()
|
||||||
{
|
{
|
||||||
if(BlocksAir)
|
if(BlocksAir)
|
||||||
{
|
{
|
||||||
if(_archivedCycle < _gridAtmosphereComponent.UpdateCounter)
|
if(_archivedCycle < _gridAtmosphereComponent.UpdateCounter)
|
||||||
Archive(_gridAtmosphereComponent.UpdateCounter);
|
Archive(_gridAtmosphereComponent.UpdateCounter);
|
||||||
return Cardinal;
|
return AtmosDirection.All;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO ATMOS check if this is correct
|
// TODO ATMOS check if this is correct
|
||||||
return Cardinal;
|
return AtmosDirection.All;
|
||||||
}
|
}
|
||||||
|
|
||||||
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void ExplosivelyDepressurize(int cycleNum)
|
public void ExplosivelyDepressurize(int cycleNum)
|
||||||
{
|
{
|
||||||
if (Air == null) return;
|
if (Air == null) return;
|
||||||
@@ -947,14 +953,13 @@ namespace Content.Server.Atmos
|
|||||||
|
|
||||||
tiles[tileCount++] = this;
|
tiles[tileCount++] = this;
|
||||||
|
|
||||||
ResetTileAtmosInfo();
|
_tileAtmosInfo = new TileAtmosInfo {LastQueueCycle = queueCycle};
|
||||||
_tileAtmosInfo.LastQueueCycle = queueCycle;
|
|
||||||
|
|
||||||
for (var i = 0; i < tileCount; i++)
|
for (var i = 0; i < tileCount; i++)
|
||||||
{
|
{
|
||||||
var tile = tiles[i];
|
var tile = tiles[i];
|
||||||
tile._tileAtmosInfo.LastCycle = cycleNum;
|
tile._tileAtmosInfo.LastCycle = cycleNum;
|
||||||
tile._tileAtmosInfo.CurrentTransferDirection = Direction.Invalid;
|
tile._tileAtmosInfo.CurrentTransferDirection = AtmosDirection.Invalid;
|
||||||
if (tile.Air.Immutable)
|
if (tile.Air.Immutable)
|
||||||
{
|
{
|
||||||
spaceTiles[spaceTileCount++] = tile;
|
spaceTiles[spaceTileCount++] = tile;
|
||||||
@@ -962,18 +967,19 @@ namespace Content.Server.Atmos
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (var direction in Cardinal)
|
for (var j = 0; j < Atmospherics.Directions; j++)
|
||||||
{
|
{
|
||||||
if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
|
var direction = (AtmosDirection) (1 << j);
|
||||||
|
if (!tile._adjacentBits.HasFlag(direction)) continue;
|
||||||
|
var tile2 = tile._adjacentTiles[j];
|
||||||
if (tile2.Air == null) continue;
|
if (tile2.Air == null) continue;
|
||||||
if (tile2._tileAtmosInfo.LastQueueCycle == queueCycle) continue;
|
if (tile2._tileAtmosInfo.LastQueueCycle == queueCycle) continue;
|
||||||
|
|
||||||
tile.ConsiderFirelocks(tile2);
|
tile.ConsiderFirelocks(tile2);
|
||||||
|
|
||||||
// The firelocks might have closed on us.
|
// The firelocks might have closed on us.
|
||||||
if (tile._adjacentTiles[direction]?.Air == null) continue;
|
if (!tile._adjacentBits.HasFlag(direction)) continue;
|
||||||
tile2.ResetTileAtmosInfo();
|
tile2._tileAtmosInfo = new TileAtmosInfo {LastQueueCycle = queueCycle};
|
||||||
tile2._tileAtmosInfo.LastQueueCycle = queueCycle;
|
|
||||||
tiles[tileCount++] = tile2;
|
tiles[tileCount++] = tile2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -991,18 +997,21 @@ namespace Content.Server.Atmos
|
|||||||
var tile = spaceTiles[i];
|
var tile = spaceTiles[i];
|
||||||
progressionOrder[progressionCount++] = tile;
|
progressionOrder[progressionCount++] = tile;
|
||||||
tile._tileAtmosInfo.LastSlowQueueCycle = queueCycleSlow;
|
tile._tileAtmosInfo.LastSlowQueueCycle = queueCycleSlow;
|
||||||
tile._tileAtmosInfo.CurrentTransferDirection = Direction.Invalid;
|
tile._tileAtmosInfo.CurrentTransferDirection = AtmosDirection.Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < progressionCount; i++)
|
for (var i = 0; i < progressionCount; i++)
|
||||||
{
|
{
|
||||||
var tile = progressionOrder[i];
|
var tile = progressionOrder[i];
|
||||||
foreach (var direction in Cardinal)
|
for (var j = 0; j < Atmospherics.Directions; j++)
|
||||||
{
|
{
|
||||||
if (!tile._adjacentTiles.TryGetValue(direction, out var tile2)) continue;
|
var direction = (AtmosDirection) (1 << j);
|
||||||
|
// TODO ATMOS This is a terrible hack that accounts for the mess that are space TileAtmospheres.
|
||||||
|
if (!tile._adjacentBits.HasFlag(direction) && !tile.Air.Immutable) continue;
|
||||||
|
var tile2 = tile._adjacentTiles[j];
|
||||||
if (tile2?._tileAtmosInfo.LastQueueCycle != queueCycle) continue;
|
if (tile2?._tileAtmosInfo.LastQueueCycle != queueCycle) continue;
|
||||||
if (tile2._tileAtmosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
|
if (tile2._tileAtmosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
|
||||||
if(tile2.Air.Immutable) continue;
|
if(tile2.Air?.Immutable ?? false) continue;
|
||||||
tile2._tileAtmosInfo.CurrentTransferDirection = direction.GetOpposite();
|
tile2._tileAtmosInfo.CurrentTransferDirection = direction.GetOpposite();
|
||||||
tile2._tileAtmosInfo.CurrentTransferAmount = 0;
|
tile2._tileAtmosInfo.CurrentTransferAmount = 0;
|
||||||
tile2.PressureSpecificTarget = tile.PressureSpecificTarget;
|
tile2.PressureSpecificTarget = tile.PressureSpecificTarget;
|
||||||
@@ -1014,10 +1023,11 @@ namespace Content.Server.Atmos
|
|||||||
for (var i = progressionCount - 1; i >= 0; i--)
|
for (var i = progressionCount - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var tile = progressionOrder[i];
|
var tile = progressionOrder[i];
|
||||||
if (tile._tileAtmosInfo.CurrentTransferDirection == Direction.Invalid) continue;
|
if (tile._tileAtmosInfo.CurrentTransferDirection == AtmosDirection.Invalid) continue;
|
||||||
_gridAtmosphereComponent.AddHighPressureDelta(tile);
|
_gridAtmosphereComponent.AddHighPressureDelta(tile);
|
||||||
_gridAtmosphereComponent.AddActiveTile(tile);
|
_gridAtmosphereComponent.AddActiveTile(tile);
|
||||||
if (!tile._adjacentTiles.TryGetValue(tile._tileAtmosInfo.CurrentTransferDirection, out var tile2) || tile2.Air == null) continue;
|
var tile2 = tile._adjacentTiles[tile._tileAtmosInfo.CurrentTransferDirection.ToIndex()];
|
||||||
|
if (tile2?.Air == null) continue;
|
||||||
var sum = tile2.Air.TotalMoles;
|
var sum = tile2.Air.TotalMoles;
|
||||||
totalGasesRemoved += sum;
|
totalGasesRemoved += sum;
|
||||||
tile._tileAtmosInfo.CurrentTransferAmount += sum;
|
tile._tileAtmosInfo.CurrentTransferAmount += sum;
|
||||||
@@ -1025,7 +1035,7 @@ namespace Content.Server.Atmos
|
|||||||
tile.PressureDifference = tile._tileAtmosInfo.CurrentTransferAmount;
|
tile.PressureDifference = tile._tileAtmosInfo.CurrentTransferAmount;
|
||||||
tile._pressureDirection = tile._tileAtmosInfo.CurrentTransferDirection;
|
tile._pressureDirection = tile._tileAtmosInfo.CurrentTransferDirection;
|
||||||
|
|
||||||
if (tile2._tileAtmosInfo.CurrentTransferDirection == Direction.Invalid)
|
if (tile2._tileAtmosInfo.CurrentTransferDirection == AtmosDirection.Invalid)
|
||||||
{
|
{
|
||||||
tile2.PressureDifference = tile2._tileAtmosInfo.CurrentTransferAmount;
|
tile2.PressureDifference = tile2._tileAtmosInfo.CurrentTransferAmount;
|
||||||
tile2._pressureDirection = tile._tileAtmosInfo.CurrentTransferDirection;
|
tile2._pressureDirection = tile._tileAtmosInfo.CurrentTransferDirection;
|
||||||
@@ -1082,21 +1092,30 @@ namespace Content.Server.Atmos
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void UpdateAdjacent()
|
public void UpdateAdjacent()
|
||||||
{
|
{
|
||||||
foreach (var direction in Cardinal)
|
for (var i = 0; i < Atmospherics.Directions; i++)
|
||||||
{
|
{
|
||||||
if (!_gridAtmosphereComponent.IsAirBlocked(GridIndices.Offset(direction)))
|
var direction = (AtmosDirection) (1 << i);
|
||||||
|
|
||||||
|
var otherIndices = GridIndices.Offset(direction.ToDirection());
|
||||||
|
|
||||||
|
var isSpace = _gridAtmosphereComponent.IsSpace(GridIndices);
|
||||||
|
var adjacent = _gridAtmosphereComponent.GetTile(otherIndices, !isSpace);
|
||||||
|
_adjacentTiles[direction.ToIndex()] = adjacent;
|
||||||
|
adjacent?.UpdateAdjacent(direction.GetOpposite());
|
||||||
|
|
||||||
|
if (adjacent != null && !_gridAtmosphereComponent.IsAirBlocked(adjacent.GridIndices))
|
||||||
{
|
{
|
||||||
var adjacent = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction));
|
_adjacentBits |= direction;
|
||||||
_adjacentTiles[direction] = adjacent;
|
|
||||||
adjacent.UpdateAdjacent(direction.GetOpposite());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateAdjacent(Direction direction)
|
public void UpdateAdjacent(AtmosDirection direction)
|
||||||
{
|
{
|
||||||
if (!_gridAtmosphereComponent.IsAirBlocked(GridIndices.Offset(direction)))
|
if (!_gridAtmosphereComponent.IsAirBlocked(GridIndices.Offset(direction.ToDirection())))
|
||||||
_adjacentTiles[direction] = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction));
|
{
|
||||||
|
_adjacentTiles[direction.ToIndex()] = _gridAtmosphereComponent.GetTile(GridIndices.Offset(direction.ToDirection()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LastShareCheck()
|
private void LastShareCheck()
|
||||||
@@ -1111,13 +1130,7 @@ namespace Content.Server.Atmos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Direction[] Cardinal =
|
public void TemperatureExpose(GasMixture air, float temperature, float volume)
|
||||||
new Direction[]
|
|
||||||
{
|
|
||||||
Direction.North, Direction.East, Direction.South, Direction.West
|
|
||||||
};
|
|
||||||
|
|
||||||
public void TemperatureExpose(GasMixture mixture, float temperature, float cellVolume)
|
|
||||||
{
|
{
|
||||||
// TODO ATMOS do this
|
// TODO ATMOS do this
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check current execution time every n instances processed.
|
/// Check current execution time every n instances processed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const int LagCheckIterations = 15;
|
private const int LagCheckIterations = 30;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Max milliseconds allowed for atmos updates.
|
/// Max milliseconds allowed for atmos updates.
|
||||||
@@ -50,46 +50,93 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
|
|
||||||
public override string Name => "GridAtmosphere";
|
public override string Name => "GridAtmosphere";
|
||||||
|
|
||||||
|
private bool _paused = false;
|
||||||
private float _timer = 0f;
|
private float _timer = 0f;
|
||||||
private Stopwatch _stopwatch = new Stopwatch();
|
private Stopwatch _stopwatch = new Stopwatch();
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
public int UpdateCounter { get; private set; } = 0;
|
public int UpdateCounter { get; private set; } = 0;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private double _tileEqualizeLastProcess;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private readonly HashSet<ExcitedGroup> _excitedGroups = new HashSet<ExcitedGroup>(1000);
|
private readonly HashSet<ExcitedGroup> _excitedGroups = new HashSet<ExcitedGroup>(1000);
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private int ExcitedGroupCount => _excitedGroups.Count;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private double _excitedGroupLastProcess;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private readonly Dictionary<MapIndices, TileAtmosphere> _tiles = new Dictionary<MapIndices, TileAtmosphere>(1000);
|
private readonly Dictionary<MapIndices, TileAtmosphere> _tiles = new Dictionary<MapIndices, TileAtmosphere>(1000);
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private readonly HashSet<TileAtmosphere> _activeTiles = new HashSet<TileAtmosphere>(1000);
|
private readonly HashSet<TileAtmosphere> _activeTiles = new HashSet<TileAtmosphere>(1000);
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private int ActiveTilesCount => _activeTiles.Count;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private double _activeTilesLastProcess;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private readonly HashSet<TileAtmosphere> _hotspotTiles = new HashSet<TileAtmosphere>(1000);
|
private readonly HashSet<TileAtmosphere> _hotspotTiles = new HashSet<TileAtmosphere>(1000);
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private int HotspotTilesCount => _hotspotTiles.Count;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private double _hotspotsLastProcess;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private readonly HashSet<TileAtmosphere> _superconductivityTiles = new HashSet<TileAtmosphere>(1000);
|
private readonly HashSet<TileAtmosphere> _superconductivityTiles = new HashSet<TileAtmosphere>(1000);
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private int SuperconductivityTilesCount => _superconductivityTiles.Count;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private double _superconductivityLastProcess;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private readonly HashSet<MapIndices> _invalidatedCoords = new HashSet<MapIndices>(1000);
|
private readonly HashSet<MapIndices> _invalidatedCoords = new HashSet<MapIndices>(1000);
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private int InvalidatedCoordsCount => _invalidatedCoords.Count;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private HashSet<TileAtmosphere> _highPressureDelta = new HashSet<TileAtmosphere>(1000);
|
private HashSet<TileAtmosphere> _highPressureDelta = new HashSet<TileAtmosphere>(1000);
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private readonly List<IPipeNet> _pipeNets = new List<IPipeNet>();
|
private int HighPressureDeltaCount => _highPressureDelta.Count;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Index of most recently updated <see cref="IPipeNet"/>.
|
|
||||||
/// </summary>
|
|
||||||
private int _pipeNetIndex = 0;
|
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private readonly List<PipeNetDeviceComponent> _pipeNetDevices = new List<PipeNetDeviceComponent>();
|
private double _highPressureDeltaLastProcess;
|
||||||
|
|
||||||
/// <summary>
|
[ViewVariables]
|
||||||
/// Index of most recently updated <see cref="PipeNetDeviceComponent"/>.
|
private readonly HashSet<IPipeNet> _pipeNets = new HashSet<IPipeNet>();
|
||||||
/// </summary>
|
|
||||||
private int _deviceIndex = 0;
|
[ViewVariables]
|
||||||
|
private double _pipeNetLastProcess;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private readonly HashSet<PipeNetDeviceComponent> _pipeNetDevices = new HashSet<PipeNetDeviceComponent>();
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private double _pipeNetDevicesLastProcess;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private Queue<TileAtmosphere> _currentRunTiles = new Queue<TileAtmosphere>();
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private Queue<ExcitedGroup> _currentRunExcitedGroups = new Queue<ExcitedGroup>();
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private Queue<IPipeNet> _currentRunPipeNet = new Queue<IPipeNet>();
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
private Queue<PipeNetDeviceComponent> _currentRunPipeNetDevice = new Queue<PipeNetDeviceComponent>();
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private ProcessState _state = ProcessState.TileEqualize;
|
private ProcessState _state = ProcessState.TileEqualize;
|
||||||
@@ -204,9 +251,10 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
tile.UpdateAdjacent();
|
tile.UpdateAdjacent();
|
||||||
tile.UpdateVisuals();
|
tile.UpdateVisuals();
|
||||||
|
|
||||||
foreach (var direction in Cardinal)
|
for (var i = 0; i < Atmospherics.Directions; i++)
|
||||||
{
|
{
|
||||||
var otherIndices = indices.Offset(direction);
|
var direction = (AtmosDirection) (1 << i);
|
||||||
|
var otherIndices = indices.Offset(direction.ToDirection());
|
||||||
var otherTile = GetTile(otherIndices);
|
var otherTile = GetTile(otherIndices);
|
||||||
AddActiveTile(otherTile);
|
AddActiveTile(otherTile);
|
||||||
otherTile?.UpdateAdjacent(direction.GetOpposite());
|
otherTile?.UpdateAdjacent(direction.GetOpposite());
|
||||||
@@ -324,7 +372,6 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
public void RemovePipeNet(IPipeNet pipeNet)
|
public void RemovePipeNet(IPipeNet pipeNet)
|
||||||
{
|
{
|
||||||
_pipeNets.Remove(pipeNet);
|
_pipeNets.Remove(pipeNet);
|
||||||
_deviceIndex = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddPipeNetDevice(PipeNetDeviceComponent pipeNetDevice)
|
public void AddPipeNetDevice(PipeNetDeviceComponent pipeNetDevice)
|
||||||
@@ -335,28 +382,25 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
public void RemovePipeNetDevice(PipeNetDeviceComponent pipeNetDevice)
|
public void RemovePipeNetDevice(PipeNetDeviceComponent pipeNetDevice)
|
||||||
{
|
{
|
||||||
_pipeNetDevices.Remove(pipeNetDevice);
|
_pipeNetDevices.Remove(pipeNetDevice);
|
||||||
_deviceIndex = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public TileAtmosphere? GetTile(GridCoordinates coordinates)
|
public TileAtmosphere? GetTile(GridCoordinates coordinates, bool createSpace = true)
|
||||||
{
|
{
|
||||||
return GetTile(coordinates.ToMapIndices(_mapManager));
|
return GetTile(coordinates.ToMapIndices(_mapManager), createSpace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public TileAtmosphere? GetTile(MapIndices indices)
|
public TileAtmosphere? GetTile(MapIndices indices, bool createSpace = true)
|
||||||
{
|
{
|
||||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return null;
|
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return null;
|
||||||
|
|
||||||
if (_tiles.TryGetValue(indices, out var tile)) return tile;
|
if (_tiles.TryGetValue(indices, out var tile)) return tile;
|
||||||
|
|
||||||
// We don't have that tile!
|
// We don't have that tile!
|
||||||
if (IsSpace(indices))
|
if (IsSpace(indices) && createSpace)
|
||||||
{
|
{
|
||||||
var space = new TileAtmosphere(this, mapGrid.Grid.Index, indices, new GasMixture(int.MaxValue){Temperature = Atmospherics.TCMB});
|
return new TileAtmosphere(this, mapGrid.Grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.TCMB}, true);
|
||||||
space.Air.MarkImmutable();
|
|
||||||
return space;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -378,23 +422,21 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
return mapGrid.Grid.GetTileRef(indices).Tile.IsEmpty;
|
return mapGrid.Grid.GetTileRef(indices).Tile.IsEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<Direction, TileAtmosphere> GetAdjacentTiles(MapIndices indices, bool includeAirBlocked = false)
|
public Dictionary<AtmosDirection, TileAtmosphere> GetAdjacentTiles(MapIndices indices, bool includeAirBlocked = false)
|
||||||
{
|
{
|
||||||
var sides = new Dictionary<Direction, TileAtmosphere>();
|
var sides = new Dictionary<AtmosDirection, TileAtmosphere>();
|
||||||
foreach (var dir in Cardinal)
|
for (var i = 0; i < Atmospherics.Directions; i++)
|
||||||
{
|
{
|
||||||
var side = indices.Offset(dir);
|
var direction = (AtmosDirection) (1 << i);
|
||||||
|
var side = indices.Offset(direction.ToDirection());
|
||||||
var tile = GetTile(side);
|
var tile = GetTile(side);
|
||||||
if (tile != null && (tile.Air != null || includeAirBlocked))
|
if (tile != null && (tile.Air != null || includeAirBlocked))
|
||||||
sides[dir] = tile;
|
sides[direction] = tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sides;
|
return sides;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public int HighPressureDeltaCount => _highPressureDelta.Count;
|
|
||||||
|
|
||||||
public long EqualizationQueueCycleControl { get; set; }
|
public long EqualizationQueueCycleControl { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -422,35 +464,83 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
switch (_state)
|
switch (_state)
|
||||||
{
|
{
|
||||||
case ProcessState.TileEqualize:
|
case ProcessState.TileEqualize:
|
||||||
ProcessTileEqualize();
|
if (!ProcessTileEqualize(_paused))
|
||||||
|
{
|
||||||
|
_paused = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_paused = false;
|
||||||
_state = ProcessState.ActiveTiles;
|
_state = ProcessState.ActiveTiles;
|
||||||
return;
|
return;
|
||||||
case ProcessState.ActiveTiles:
|
case ProcessState.ActiveTiles:
|
||||||
ProcessActiveTiles();
|
if (!ProcessActiveTiles(_paused))
|
||||||
|
{
|
||||||
|
_paused = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_paused = false;
|
||||||
_state = ProcessState.ExcitedGroups;
|
_state = ProcessState.ExcitedGroups;
|
||||||
return;
|
return;
|
||||||
case ProcessState.ExcitedGroups:
|
case ProcessState.ExcitedGroups:
|
||||||
ProcessExcitedGroups();
|
if (!ProcessExcitedGroups(_paused))
|
||||||
|
{
|
||||||
|
_paused = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_paused = false;
|
||||||
_state = ProcessState.HighPressureDelta;
|
_state = ProcessState.HighPressureDelta;
|
||||||
return;
|
return;
|
||||||
case ProcessState.HighPressureDelta:
|
case ProcessState.HighPressureDelta:
|
||||||
ProcessHighPressureDelta();
|
if (!ProcessHighPressureDelta(_paused))
|
||||||
|
{
|
||||||
|
_paused = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_paused = false;
|
||||||
_state = ProcessState.Hotspots;
|
_state = ProcessState.Hotspots;
|
||||||
break;
|
break;
|
||||||
case ProcessState.Hotspots:
|
case ProcessState.Hotspots:
|
||||||
ProcessHotspots();
|
if (!ProcessHotspots(_paused))
|
||||||
|
{
|
||||||
|
_paused = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_paused = false;
|
||||||
_state = ProcessState.Superconductivity;
|
_state = ProcessState.Superconductivity;
|
||||||
break;
|
break;
|
||||||
case ProcessState.Superconductivity:
|
case ProcessState.Superconductivity:
|
||||||
ProcessSuperconductivity();
|
if (!ProcessSuperconductivity(_paused))
|
||||||
|
{
|
||||||
|
_paused = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_paused = false;
|
||||||
_state = ProcessState.PipeNet;
|
_state = ProcessState.PipeNet;
|
||||||
break;
|
break;
|
||||||
case ProcessState.PipeNet:
|
case ProcessState.PipeNet:
|
||||||
ProcessPipeNets();
|
if (!ProcessPipeNets(_paused))
|
||||||
|
{
|
||||||
|
_paused = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_paused = false;
|
||||||
_state = ProcessState.PipeNetDevices;
|
_state = ProcessState.PipeNetDevices;
|
||||||
break;
|
break;
|
||||||
case ProcessState.PipeNetDevices:
|
case ProcessState.PipeNetDevices:
|
||||||
ProcessPipeNetDevices();
|
if (!ProcessPipeNetDevices(_paused))
|
||||||
|
{
|
||||||
|
_paused = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_paused = false;
|
||||||
_state = ProcessState.TileEqualize;
|
_state = ProcessState.TileEqualize;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -458,47 +548,71 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
UpdateCounter++;
|
UpdateCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProcessTileEqualize()
|
public bool ProcessTileEqualize(bool resumed = false)
|
||||||
{
|
{
|
||||||
_stopwatch.Restart();
|
_stopwatch.Restart();
|
||||||
|
|
||||||
|
if(!resumed)
|
||||||
|
_currentRunTiles = new Queue<TileAtmosphere>(_activeTiles);
|
||||||
|
|
||||||
var number = 0;
|
var number = 0;
|
||||||
foreach (var tile in _activeTiles.ToArray())
|
while (_currentRunTiles.Count > 0)
|
||||||
{
|
{
|
||||||
|
var tile = _currentRunTiles.Dequeue();
|
||||||
tile.EqualizePressureInZone(UpdateCounter);
|
tile.EqualizePressureInZone(UpdateCounter);
|
||||||
|
|
||||||
if (number++ < LagCheckIterations) continue;
|
if (number++ < LagCheckIterations) continue;
|
||||||
number = 0;
|
number = 0;
|
||||||
// Process the rest next time.
|
// Process the rest next time.
|
||||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||||
return;
|
{
|
||||||
|
_tileEqualizeLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProcessActiveTiles()
|
_tileEqualizeLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ProcessActiveTiles(bool resumed = false)
|
||||||
{
|
{
|
||||||
_stopwatch.Restart();
|
_stopwatch.Restart();
|
||||||
|
|
||||||
|
if(!resumed)
|
||||||
|
_currentRunTiles = new Queue<TileAtmosphere>(_activeTiles);
|
||||||
|
|
||||||
var number = 0;
|
var number = 0;
|
||||||
foreach (var tile in _activeTiles.ToArray())
|
while (_currentRunTiles.Count > 0)
|
||||||
{
|
{
|
||||||
|
var tile = _currentRunTiles.Dequeue();
|
||||||
tile.ProcessCell(UpdateCounter);
|
tile.ProcessCell(UpdateCounter);
|
||||||
|
|
||||||
if (number++ < LagCheckIterations) continue;
|
if (number++ < LagCheckIterations) continue;
|
||||||
number = 0;
|
number = 0;
|
||||||
// Process the rest next time.
|
// Process the rest next time.
|
||||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||||
return;
|
{
|
||||||
|
_activeTilesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProcessExcitedGroups()
|
_activeTilesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ProcessExcitedGroups(bool resumed = false)
|
||||||
{
|
{
|
||||||
_stopwatch.Restart();
|
_stopwatch.Restart();
|
||||||
|
|
||||||
|
if(!resumed)
|
||||||
|
_currentRunExcitedGroups = new Queue<ExcitedGroup>(_excitedGroups);
|
||||||
|
|
||||||
var number = 0;
|
var number = 0;
|
||||||
foreach (var excitedGroup in _excitedGroups.ToArray())
|
while (_currentRunExcitedGroups.Count > 0)
|
||||||
{
|
{
|
||||||
|
var excitedGroup = _currentRunExcitedGroups.Dequeue();
|
||||||
excitedGroup.BreakdownCooldown++;
|
excitedGroup.BreakdownCooldown++;
|
||||||
excitedGroup.DismantleCooldown++;
|
excitedGroup.DismantleCooldown++;
|
||||||
|
|
||||||
@@ -512,17 +626,27 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
number = 0;
|
number = 0;
|
||||||
// Process the rest next time.
|
// Process the rest next time.
|
||||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||||
return;
|
{
|
||||||
|
_excitedGroupLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProcessHighPressureDelta()
|
_excitedGroupLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ProcessHighPressureDelta(bool resumed = false)
|
||||||
{
|
{
|
||||||
_stopwatch.Restart();
|
_stopwatch.Restart();
|
||||||
|
|
||||||
|
if(!resumed)
|
||||||
|
_currentRunTiles = new Queue<TileAtmosphere>(_highPressureDelta);
|
||||||
|
|
||||||
var number = 0;
|
var number = 0;
|
||||||
foreach (var tile in _highPressureDelta.ToArray())
|
while (_currentRunTiles.Count > 0)
|
||||||
{
|
{
|
||||||
|
var tile = _currentRunTiles.Dequeue();
|
||||||
tile.HighPressureMovements();
|
tile.HighPressureMovements();
|
||||||
tile.PressureDifference = 0f;
|
tile.PressureDifference = 0f;
|
||||||
tile.PressureSpecificTarget = null;
|
tile.PressureSpecificTarget = null;
|
||||||
@@ -532,83 +656,124 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
number = 0;
|
number = 0;
|
||||||
// Process the rest next time.
|
// Process the rest next time.
|
||||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||||
return;
|
{
|
||||||
|
_highPressureDeltaLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessHotspots()
|
_highPressureDeltaLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ProcessHotspots(bool resumed = false)
|
||||||
{
|
{
|
||||||
_stopwatch.Restart();
|
_stopwatch.Restart();
|
||||||
|
|
||||||
|
if(!resumed)
|
||||||
|
_currentRunTiles = new Queue<TileAtmosphere>(_hotspotTiles);
|
||||||
|
|
||||||
var number = 0;
|
var number = 0;
|
||||||
foreach (var hotspot in _hotspotTiles.ToArray())
|
while (_currentRunTiles.Count > 0)
|
||||||
{
|
{
|
||||||
|
var hotspot = _currentRunTiles.Dequeue();
|
||||||
hotspot.ProcessHotspot();
|
hotspot.ProcessHotspot();
|
||||||
|
|
||||||
if (number++ < LagCheckIterations) continue;
|
if (number++ < LagCheckIterations) continue;
|
||||||
number = 0;
|
number = 0;
|
||||||
// Process the rest next time.
|
// Process the rest next time.
|
||||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||||
return;
|
{
|
||||||
|
_hotspotsLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessSuperconductivity()
|
_hotspotsLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ProcessSuperconductivity(bool resumed = false)
|
||||||
{
|
{
|
||||||
_stopwatch.Restart();
|
_stopwatch.Restart();
|
||||||
|
|
||||||
|
if(!resumed)
|
||||||
|
_currentRunTiles = new Queue<TileAtmosphere>(_superconductivityTiles);
|
||||||
|
|
||||||
var number = 0;
|
var number = 0;
|
||||||
foreach (var superconductivity in _superconductivityTiles.ToArray())
|
while (_currentRunTiles.Count > 0)
|
||||||
{
|
{
|
||||||
|
var superconductivity = _currentRunTiles.Dequeue();
|
||||||
superconductivity.Superconduct();
|
superconductivity.Superconduct();
|
||||||
|
|
||||||
if (number++ < LagCheckIterations) continue;
|
if (number++ < LagCheckIterations) continue;
|
||||||
number = 0;
|
number = 0;
|
||||||
// Process the rest next time.
|
// Process the rest next time.
|
||||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||||
return;
|
{
|
||||||
|
_superconductivityLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessPipeNets()
|
_superconductivityLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ProcessPipeNets(bool resumed = false)
|
||||||
{
|
{
|
||||||
_stopwatch.Restart();
|
_stopwatch.Restart();
|
||||||
|
|
||||||
|
if(!resumed)
|
||||||
|
_currentRunPipeNet = new Queue<IPipeNet>(_pipeNets);
|
||||||
|
|
||||||
var number = 0;
|
var number = 0;
|
||||||
var pipeNets = _pipeNets.ToArray();
|
while (_currentRunPipeNet.Count > 0)
|
||||||
var netCount = pipeNets.Count();
|
|
||||||
for ( ; _pipeNetIndex < netCount; _pipeNetIndex++)
|
|
||||||
{
|
{
|
||||||
pipeNets[_pipeNetIndex].Update();
|
var pipenet = _currentRunPipeNet.Dequeue();
|
||||||
|
pipenet.Update();
|
||||||
|
|
||||||
if (number++ < LagCheckIterations) continue;
|
if (number++ < LagCheckIterations) continue;
|
||||||
number = 0;
|
number = 0;
|
||||||
// Process the rest next time.
|
// Process the rest next time.
|
||||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||||
return;
|
{
|
||||||
|
_pipeNetLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
_pipeNetIndex = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessPipeNetDevices()
|
_pipeNetLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ProcessPipeNetDevices(bool resumed = false)
|
||||||
{
|
{
|
||||||
_stopwatch.Restart();
|
_stopwatch.Restart();
|
||||||
|
|
||||||
|
if(!resumed)
|
||||||
|
_currentRunPipeNetDevice = new Queue<PipeNetDeviceComponent>(_pipeNetDevices);
|
||||||
|
|
||||||
var number = 0;
|
var number = 0;
|
||||||
var pipeNetDevices = _pipeNetDevices.ToArray();
|
while (_currentRunPipeNet.Count > 0)
|
||||||
var deviceCount = pipeNetDevices.Count();
|
|
||||||
for ( ; _deviceIndex < deviceCount; _deviceIndex++)
|
|
||||||
{
|
{
|
||||||
pipeNetDevices[_deviceIndex].Update();
|
var device = _currentRunPipeNetDevice.Dequeue();
|
||||||
|
device.Update();
|
||||||
|
|
||||||
if (number++ < LagCheckIterations) continue;
|
if (number++ < LagCheckIterations) continue;
|
||||||
number = 0;
|
number = 0;
|
||||||
// Process the rest next time.
|
// Process the rest next time.
|
||||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||||
return;
|
{
|
||||||
|
_pipeNetDevicesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
_deviceIndex = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_pipeNetDevicesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private AirtightComponent? GetObstructingComponent(MapIndices indices)
|
private AirtightComponent? GetObstructingComponent(MapIndices indices)
|
||||||
{
|
{
|
||||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return default;
|
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return default;
|
||||||
@@ -622,12 +787,6 @@ namespace Content.Server.GameObjects.Components.Atmos
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Direction[] Cardinal =
|
|
||||||
new []
|
|
||||||
{
|
|
||||||
Direction.North, Direction.East, Direction.South, Direction.West
|
|
||||||
};
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,50 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Content.Server.Atmos;
|
using Content.Server.Atmos;
|
||||||
|
using Content.Server.Atmos.Reactions;
|
||||||
|
using Content.Server.Interfaces;
|
||||||
using Content.Shared.GameObjects.EntitySystems.Atmos;
|
using Content.Shared.GameObjects.EntitySystems.Atmos;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.Interfaces.Timing;
|
using Robust.Server.Interfaces.Timing;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.GameObjects.Components.Map;
|
using Robust.Shared.GameObjects.Components.Map;
|
||||||
|
using Robust.Shared.Interfaces.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Map;
|
using Robust.Shared.Interfaces.Map;
|
||||||
using Robust.Shared.IoC;
|
using Robust.Shared.IoC;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
namespace Content.Server.GameObjects.EntitySystems
|
namespace Content.Server.GameObjects.EntitySystems
|
||||||
{
|
{
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public class AtmosphereSystem : SharedAtmosphereSystem
|
public class AtmosphereSystem : SharedAtmosphereSystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
[Dependency] private readonly IPauseManager _pauseManager = default!;
|
[Dependency] private readonly IPauseManager _pauseManager = default!;
|
||||||
|
[Dependency] private IEntityManager _entityManager = default!;
|
||||||
|
|
||||||
|
private GasReactionPrototype[] _gasReactions = Array.Empty<GasReactionPrototype>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of gas reactions ordered by priority.
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<GasReactionPrototype> GasReactions => _gasReactions!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// EventBus reference for gas reactions.
|
||||||
|
/// </summary>
|
||||||
|
public IEventBus EventBus => _entityManager.EventBus;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
|
_gasReactions = _protoMan.EnumeratePrototypes<GasReactionPrototype>().ToArray();
|
||||||
|
Array.Sort(_gasReactions, (a, b) => b.Priority.CompareTo(a.Priority));
|
||||||
|
|
||||||
_mapManager.TileChanged += OnTileChanged;
|
_mapManager.TileChanged += OnTileChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using Content.Server.Atmos;
|
using Content.Server.Atmos;
|
||||||
using Content.Server.Atmos.Reactions;
|
using Content.Server.Atmos.Reactions;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Interfaces.Serialization;
|
using Robust.Shared.Interfaces.Serialization;
|
||||||
|
|
||||||
namespace Content.Server.Interfaces
|
namespace Content.Server.Interfaces
|
||||||
{
|
{
|
||||||
public interface IGasReactionEffect : IExposeData
|
public interface IGasReactionEffect : IExposeData
|
||||||
{
|
{
|
||||||
ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder);
|
ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, IEventBus eventBus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
89
Content.Shared/Atmos/AtmosDirection.cs
Normal file
89
Content.Shared/Atmos/AtmosDirection.cs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
using System;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
|
||||||
|
namespace Content.Shared.Atmos
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The reason we use this over <see cref="Direction"/> is that we are going to do some heavy bitflag usage.
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum AtmosDirection : byte
|
||||||
|
{
|
||||||
|
Invalid = 0,
|
||||||
|
North = 1 << 0,
|
||||||
|
South = 1 << 1,
|
||||||
|
East = 1 << 2,
|
||||||
|
West = 1 << 3,
|
||||||
|
|
||||||
|
NorthEast = North | East,
|
||||||
|
NorthWest = North | West,
|
||||||
|
SouthEast = South | East,
|
||||||
|
SouthWest = South | West,
|
||||||
|
|
||||||
|
All = North | South | East | West,
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AtmosDirectionHelpers
|
||||||
|
{
|
||||||
|
public static AtmosDirection GetOpposite(this AtmosDirection direction)
|
||||||
|
{
|
||||||
|
return direction switch
|
||||||
|
{
|
||||||
|
AtmosDirection.North => AtmosDirection.South,
|
||||||
|
AtmosDirection.South => AtmosDirection.North,
|
||||||
|
AtmosDirection.East => AtmosDirection.West,
|
||||||
|
AtmosDirection.West => AtmosDirection.East,
|
||||||
|
AtmosDirection.NorthEast => AtmosDirection.SouthWest,
|
||||||
|
AtmosDirection.NorthWest => AtmosDirection.SouthEast,
|
||||||
|
AtmosDirection.SouthEast => AtmosDirection.NorthWest,
|
||||||
|
AtmosDirection.SouthWest => AtmosDirection.NorthEast,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(direction))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Direction ToDirection(this AtmosDirection direction)
|
||||||
|
{
|
||||||
|
return direction switch
|
||||||
|
{
|
||||||
|
AtmosDirection.North => Direction.North,
|
||||||
|
AtmosDirection.South => Direction.South,
|
||||||
|
AtmosDirection.East => Direction.East,
|
||||||
|
AtmosDirection.West => Direction.West,
|
||||||
|
AtmosDirection.NorthEast => Direction.NorthEast,
|
||||||
|
AtmosDirection.NorthWest => Direction.NorthWest,
|
||||||
|
AtmosDirection.SouthEast => Direction.SouthEast,
|
||||||
|
AtmosDirection.SouthWest => Direction.SouthWest,
|
||||||
|
AtmosDirection.Invalid => Direction.Invalid,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(direction))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AtmosDirection ToAtmosDirection(this Direction direction)
|
||||||
|
{
|
||||||
|
return direction switch
|
||||||
|
{
|
||||||
|
Direction.North => AtmosDirection.North,
|
||||||
|
Direction.South => AtmosDirection.South,
|
||||||
|
Direction.East => AtmosDirection.East,
|
||||||
|
Direction.West => AtmosDirection.West,
|
||||||
|
Direction.NorthEast => AtmosDirection.NorthEast,
|
||||||
|
Direction.NorthWest => AtmosDirection.NorthWest,
|
||||||
|
Direction.SouthEast => AtmosDirection.SouthEast,
|
||||||
|
Direction.SouthWest => AtmosDirection.SouthWest,
|
||||||
|
Direction.Invalid => AtmosDirection.Invalid,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(direction))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ToIndex(this AtmosDirection direction)
|
||||||
|
{
|
||||||
|
// This will throw if you pass an invalid direction. Not this method's fault, but yours!
|
||||||
|
return (int) Math.Log2((int) direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AtmosDirection WithFlag(this AtmosDirection direction, AtmosDirection other)
|
||||||
|
{
|
||||||
|
return direction | other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -211,6 +211,12 @@
|
|||||||
public const int LowPressureDamage = 4;
|
public const int LowPressureDamage = 4;
|
||||||
|
|
||||||
public const float WindowHeatTransferCoefficient = 0.1f;
|
public const float WindowHeatTransferCoefficient = 0.1f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Directions that atmos currently supports. Modify in case of multi-z.
|
||||||
|
/// See <see cref="AtmosDirection"/> on the server.
|
||||||
|
/// </summary>
|
||||||
|
public const int Directions = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -84,6 +84,7 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Occluders/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Occluders/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Patreon/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Patreon/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Phoron/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Phoron/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=pipenet/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=placeable/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=placeable/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=preemptively/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=preemptively/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=prefs/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=prefs/@EntryIndexedValue">True</s:Boolean>
|
||||||
@@ -96,6 +97,7 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Spawner/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Spawner/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Strippable/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Strippable/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=stunnable/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=stunnable/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Superconduct/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=superconduction/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=superconduction/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=swsl/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=swsl/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=underplating/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=underplating/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
Reference in New Issue
Block a user