Refactors the AtmosphereSystem public-facing API to allow for multiple atmos backends. (#8134)
* Refactors the entirety of the AtmosphereSystem public-facing API to allow for multiple atmos backends. * actually compiles * Remove commented out code * funny bracket * Move archived moles, temperature from GasMixture to TileAtmosphere. * WIP customizable map default mixture still VERY buggy * broken mess aaaaaaaaaaaaa * Fix lattice, etc not being considered space * visualization for "IsSpace" * help * Update Content.Client/Atmos/Overlays/AtmosDebugOverlay.cs Co-authored-by: Moony <moonheart08@users.noreply.github.com> * Holy SHIT it compiles AGAIN * Fix AtmosDeviceSystem crash at shutdown * Fix immutable tiles on map blueprints not being fixed by fixgridatmos/revalidate. * Use space instead of gasmixture immutable for heat capacity calculations * Remove all LINDA-specific code from GasMixture, move it to TileAtmosphere/AtmosphereSystem instead. * Fix roundstart tiles not processing * Update Content.Server/Atmos/Commands/SetTemperatureCommand.cs Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> * Update Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs Changed Files tab is so large I can't commit both suggestions at once mfw Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: Moony <moonheart08@users.noreply.github.com> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
43216a000f
commit
aa9281d667
@@ -141,16 +141,27 @@ namespace Content.Client.Atmos.Overlays
|
|||||||
DrawPressureDirection(drawHandle, data.LastPressureDirection, tile, Color.LightGray);
|
DrawPressureDirection(drawHandle, data.LastPressureDirection, tile, Color.LightGray);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Excited Groups --
|
|
||||||
if (data.InExcitedGroup)
|
|
||||||
{
|
|
||||||
var tilePos = new Vector2(tile.X, tile.Y);
|
var tilePos = new Vector2(tile.X, tile.Y);
|
||||||
|
|
||||||
|
// -- Excited Groups --
|
||||||
|
if (data.InExcitedGroup != 0)
|
||||||
|
{
|
||||||
var basisA = tilePos;
|
var basisA = tilePos;
|
||||||
var basisB = tilePos + new Vector2(1.0f, 1.0f);
|
var basisB = tilePos + new Vector2(1.0f, 1.0f);
|
||||||
var basisC = tilePos + new Vector2(0.0f, 1.0f);
|
var basisC = tilePos + new Vector2(0.0f, 1.0f);
|
||||||
var basisD = tilePos + new Vector2(1.0f, 0.0f);
|
var basisD = tilePos + new Vector2(1.0f, 0.0f);
|
||||||
drawHandle.DrawLine(basisA, basisB, Color.Cyan);
|
var color = Color.White // Use first three nibbles for an unique color... Good enough?
|
||||||
drawHandle.DrawLine(basisC, basisD, Color.Cyan);
|
.WithRed( data.InExcitedGroup & 0x000F)
|
||||||
|
.WithGreen((data.InExcitedGroup & 0x00F0) >>4)
|
||||||
|
.WithBlue( (data.InExcitedGroup & 0x0F00) >>8);
|
||||||
|
drawHandle.DrawLine(basisA, basisB, color);
|
||||||
|
drawHandle.DrawLine(basisC, basisD, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Space Tiles --
|
||||||
|
if (data.IsSpace)
|
||||||
|
{
|
||||||
|
drawHandle.DrawCircle(tilePos + Vector2.One/2, 0.125f, Color.Orange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.Atmos.Components;
|
using Content.Server.Atmos.Components;
|
||||||
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
|
|
||||||
@@ -36,7 +37,9 @@ namespace Content.Server.Atmos.Commands
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_entities.HasComponent<IAtmosphereComponent>(euid))
|
var atmos = entMan.EntitySysManager.GetEntitySystem<AtmosphereSystem>();
|
||||||
|
|
||||||
|
if (atmos.HasAtmosphere(euid))
|
||||||
{
|
{
|
||||||
shell.WriteLine("Grid already has an atmosphere.");
|
shell.WriteLine("Grid already has an atmosphere.");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ namespace Content.Server.Atmos.Commands
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
var atmosphereSystem = entMan.EntitySysManager.GetEntitySystem<AtmosphereSystem>();
|
||||||
var indices = new Vector2i(x, y);
|
var indices = new Vector2i(x, y);
|
||||||
var tile = atmosphereSystem.GetTileMixture(euid, indices, true);
|
var tile = atmosphereSystem.GetTileMixture(euid, null, indices, true);
|
||||||
|
|
||||||
if (tile == null)
|
if (tile == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
using Content.Server.Administration;
|
|
||||||
using Content.Server.Atmos.Components;
|
|
||||||
using Content.Shared.Administration;
|
|
||||||
using Robust.Shared.Console;
|
|
||||||
|
|
||||||
namespace Content.Server.Atmos.Commands
|
|
||||||
{
|
|
||||||
[AdminCommand(AdminFlags.Debug)]
|
|
||||||
public sealed class AddUnsimulatedAtmosCommand : IConsoleCommand
|
|
||||||
{
|
|
||||||
public string Command => "addunsimulatedatmos";
|
|
||||||
public string Description => "Adds unimulated atmos support to a grid.";
|
|
||||||
public string Help => $"{Command} <GridId>";
|
|
||||||
|
|
||||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length < 1)
|
|
||||||
{
|
|
||||||
shell.WriteLine(Help);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
|
||||||
|
|
||||||
if (EntityUid.TryParse(args[0], out var euid))
|
|
||||||
{
|
|
||||||
shell.WriteError($"Failed to parse euid '{args[0]}'.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!entMan.HasComponent<IMapGridComponent>(euid))
|
|
||||||
{
|
|
||||||
shell.WriteError($"Euid '{euid}' does not exist or is not a grid.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entMan.HasComponent<IAtmosphereComponent>(euid))
|
|
||||||
{
|
|
||||||
shell.WriteLine("Grid already has an atmosphere.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entMan.AddComponent<UnsimulatedGridAtmosphereComponent>(euid);
|
|
||||||
|
|
||||||
shell.WriteLine($"Added unsimulated atmosphere to grid {euid}.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -134,7 +134,7 @@ namespace Content.Server.Atmos.Commands
|
|||||||
|
|
||||||
if (gas == null)
|
if (gas == null)
|
||||||
{
|
{
|
||||||
foreach (var tile in atmosphereSystem.GetAllTileMixtures(gridId.Value, true))
|
foreach (var tile in atmosphereSystem.GetAllMixtures(gridId.Value, true))
|
||||||
{
|
{
|
||||||
if (tile.Immutable) continue;
|
if (tile.Immutable) continue;
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ namespace Content.Server.Atmos.Commands
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (var tile in atmosphereSystem.GetAllTileMixtures(gridId.Value, true))
|
foreach (var tile in atmosphereSystem.GetAllMixtures(gridId.Value, true))
|
||||||
{
|
{
|
||||||
if (tile.Immutable) continue;
|
if (tile.Immutable) continue;
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Content.Server.Atmos.Commands
|
|||||||
|
|
||||||
var mapMan = IoCManager.Resolve<IMapManager>();
|
var mapMan = IoCManager.Resolve<IMapManager>();
|
||||||
|
|
||||||
if (!gridId.IsValid() || !mapMan.TryGetGrid(gridId, out _))
|
if (!mapMan.TryGetGrid(gridId, out var grid))
|
||||||
{
|
{
|
||||||
shell.WriteLine("Invalid grid ID.");
|
shell.WriteLine("Invalid grid ID.");
|
||||||
return;
|
return;
|
||||||
@@ -31,7 +31,7 @@ namespace Content.Server.Atmos.Commands
|
|||||||
|
|
||||||
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
||||||
|
|
||||||
foreach (var tile in atmosphereSystem.GetAllTileMixtures(gridId, true))
|
foreach (var tile in atmosphereSystem.GetAllMixtures(grid.GridEntityId, true))
|
||||||
{
|
{
|
||||||
tile.AdjustMoles(gasId, moles);
|
tile.AdjustMoles(gasId, moles);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace Content.Server.Atmos.Commands
|
|||||||
|
|
||||||
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
||||||
var indices = new Vector2i(x, y);
|
var indices = new Vector2i(x, y);
|
||||||
var tile = atmosphereSystem.GetTileMixture(id, indices, true);
|
var tile = atmosphereSystem.GetTileMixture(id, null, indices, true);
|
||||||
|
|
||||||
if (tile == null)
|
if (tile == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Content.Server.Atmos.Commands
|
|||||||
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
||||||
|
|
||||||
var tiles = 0;
|
var tiles = 0;
|
||||||
foreach (var tile in atmosphereSystem.GetAllTileMixtures(gridId, true))
|
foreach (var tile in atmosphereSystem.GetAllMixtures(gridComp.GridEntityId, true))
|
||||||
{
|
{
|
||||||
tiles++;
|
tiles++;
|
||||||
tile.Temperature = temperature;
|
tile.Temperature = temperature;
|
||||||
|
|||||||
@@ -2,14 +2,21 @@ using Content.Server.Administration;
|
|||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
using SharpZstd.Interop;
|
||||||
|
|
||||||
namespace Content.Server.Atmos.Commands
|
namespace Content.Server.Atmos.Commands
|
||||||
{
|
{
|
||||||
[AdminCommand(AdminFlags.Debug)]
|
[AdminCommand(AdminFlags.Debug)]
|
||||||
public sealed class SetTemperatureCommand : IConsoleCommand
|
public sealed class SetTemperatureCommand : IConsoleCommand
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IEntityManager _entities = default!;
|
||||||
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
|
|
||||||
public string Command => "settemp";
|
public string Command => "settemp";
|
||||||
public string Description => "Sets a tile's temperature (in kelvin).";
|
public string Description => "Sets a tile's temperature (in kelvin).";
|
||||||
public string Help => "Usage: settemp <X> <Y> <GridId> <Temperature>";
|
public string Help => "Usage: settemp <X> <Y> <GridId> <Temperature>";
|
||||||
@@ -28,9 +35,16 @@ namespace Content.Server.Atmos.Commands
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
if (!_mapManager.TryGetGrid(gridId, out var grid))
|
||||||
|
{
|
||||||
|
shell.WriteError("Invalid grid.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var atmospheres = _entities.EntitySysManager.GetEntitySystem<AtmosphereSystem>();
|
||||||
var indices = new Vector2i(x, y);
|
var indices = new Vector2i(x, y);
|
||||||
var tile = atmosphereSystem.GetTileMixture(gridId, indices, true);
|
|
||||||
|
var tile = atmospheres.GetTileMixture(grid.GridEntityId, null, indices, true);
|
||||||
|
|
||||||
if (tile == null)
|
if (tile == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Content.Server.UserInterface;
|
|||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Atmos.Components;
|
using Content.Shared.Atmos.Components;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
|
using Content.Shared.Maps;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
@@ -120,7 +121,7 @@ namespace Content.Server.Atmos.Components
|
|||||||
{
|
{
|
||||||
// Already get the pressure before Dirty(), because we can't get the EntitySystem in that thread or smth
|
// Already get the pressure before Dirty(), because we can't get the EntitySystem in that thread or smth
|
||||||
var pressure = 0f;
|
var pressure = 0f;
|
||||||
var tile = EntitySystem.Get<AtmosphereSystem>().GetTileMixture(_entities.GetComponent<TransformComponent>(Owner).Coordinates);
|
var tile = EntitySystem.Get<AtmosphereSystem>().GetContainingMixture(Owner, true);
|
||||||
if (tile != null)
|
if (tile != null)
|
||||||
{
|
{
|
||||||
pressure = tile.Pressure;
|
pressure = tile.Pressure;
|
||||||
@@ -178,8 +179,12 @@ namespace Content.Server.Atmos.Components
|
|||||||
pos = _position.Value;
|
pos = _position.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var gridUid = pos.GetGridUid(_entities);
|
||||||
|
var mapUid = pos.GetMapUid(_entities);
|
||||||
|
var position = pos.ToVector2i(_entities, IoCManager.Resolve<IMapManager>());
|
||||||
|
|
||||||
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
||||||
var tile = atmosphereSystem.GetTileMixture(pos);
|
var tile = atmosphereSystem.GetTileMixture(gridUid, mapUid, position);
|
||||||
if (tile == null)
|
if (tile == null)
|
||||||
{
|
{
|
||||||
error = "No Atmosphere!";
|
error = "No Atmosphere!";
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ namespace Content.Server.Atmos.Components
|
|||||||
{
|
{
|
||||||
if (_integrity <= 0)
|
if (_integrity <= 0)
|
||||||
{
|
{
|
||||||
var environment = atmosphereSystem.GetTileMixture(_entMan.GetComponent<TransformComponent>(Owner).Coordinates, true);
|
var environment = atmosphereSystem.GetContainingMixture(Owner, false, true);
|
||||||
if(environment != null)
|
if(environment != null)
|
||||||
atmosphereSystem.Merge(environment, Air);
|
atmosphereSystem.Merge(environment, Air);
|
||||||
|
|
||||||
@@ -279,7 +279,7 @@ namespace Content.Server.Atmos.Components
|
|||||||
{
|
{
|
||||||
if (_integrity <= 0)
|
if (_integrity <= 0)
|
||||||
{
|
{
|
||||||
var environment = atmosphereSystem.GetTileMixture(_entMan.GetComponent<TransformComponent>(Owner).Coordinates, true);
|
var environment = atmosphereSystem.GetContainingMixture(Owner, false, true);
|
||||||
if (environment == null)
|
if (environment == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ namespace Content.Server.Atmos.Components
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Internal Atmos class. Use <see cref="AtmosphereSystem"/> to interact with atmos instead.
|
/// Internal Atmos class. Use <see cref="AtmosphereSystem"/> to interact with atmos instead.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ComponentReference(typeof(IAtmosphereComponent))]
|
[RegisterComponent, Serializable,
|
||||||
[RegisterComponent, Serializable]
|
Access(typeof(AtmosphereSystem), typeof(GasTileOverlaySystem), typeof(AtmosDebugOverlaySystem))]
|
||||||
[Virtual]
|
public sealed class GridAtmosphereComponent : Component, ISerializationHooks
|
||||||
public class GridAtmosphereComponent : Component, IAtmosphereComponent, ISerializationHooks
|
|
||||||
{
|
{
|
||||||
public virtual bool Simulated => true;
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool Simulated { get; set; } = true;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public bool ProcessingPaused { get; set; } = false;
|
public bool ProcessingPaused { get; set; } = false;
|
||||||
@@ -22,7 +22,7 @@ namespace Content.Server.Atmos.Components
|
|||||||
public float Timer { get; set; } = 0f;
|
public float Timer { get; set; } = 0f;
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public int UpdateCounter { get; set; } = 0;
|
public int UpdateCounter { get; set; } = 1; // DO NOT SET TO ZERO BY DEFAULT! It will break roundstart atmos...
|
||||||
|
|
||||||
[DataField("uniqueMixes")]
|
[DataField("uniqueMixes")]
|
||||||
public List<GasMixture>? UniqueMixes;
|
public List<GasMixture>? UniqueMixes;
|
||||||
@@ -94,7 +94,7 @@ namespace Content.Server.Atmos.Components
|
|||||||
public long EqualizationQueueCycleControl { get; set; }
|
public long EqualizationQueueCycleControl { get; set; }
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public AtmosphereProcessingState State { get; set; } = AtmosphereProcessingState.TileEqualize;
|
public AtmosphereProcessingState State { get; set; } = AtmosphereProcessingState.Revalidate;
|
||||||
|
|
||||||
void ISerializationHooks.BeforeSerialization()
|
void ISerializationHooks.BeforeSerialization()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace Content.Server.Atmos.Components
|
|
||||||
{
|
|
||||||
public interface IAtmosphereComponent : IComponent
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Whether this atmosphere is simulated or not.
|
|
||||||
/// </summary>
|
|
||||||
bool Simulated { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
21
Content.Server/Atmos/Components/MapAtmosphereComponent.cs
Normal file
21
Content.Server/Atmos/Components/MapAtmosphereComponent.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
namespace Content.Server.Atmos.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Component that defines the default GasMixture for a map.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Honestly, no need to [Friend] this. It's just two simple data fields... Change them to your heart's content.</remarks>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class MapAtmosphereComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The default GasMixture a map will have. Space mixture by default.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("mixture"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public GasMixture? Mixture = GasMixture.SpaceGas;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether empty tiles will be considered space or not.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("space"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool Space = true;
|
||||||
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
namespace Content.Server.Atmos.Components
|
|
||||||
{
|
|
||||||
[RegisterComponent]
|
|
||||||
[ComponentReference(typeof(IAtmosphereComponent))]
|
|
||||||
public sealed class SpaceAtmosphereComponent : Component, IAtmosphereComponent
|
|
||||||
{
|
|
||||||
public bool Simulated => false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace Content.Server.Atmos.Components
|
|
||||||
{
|
|
||||||
[RegisterComponent]
|
|
||||||
[ComponentReference(typeof(IAtmosphereComponent))]
|
|
||||||
[Serializable]
|
|
||||||
public sealed class UnsimulatedGridAtmosphereComponent : GridAtmosphereComponent
|
|
||||||
{
|
|
||||||
public override bool Simulated => false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -111,17 +111,19 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
|
|
||||||
public void InvalidatePosition(EntityUid gridId, Vector2i pos, bool fixVacuum = false)
|
public void InvalidatePosition(EntityUid gridId, Vector2i pos, bool fixVacuum = false)
|
||||||
{
|
{
|
||||||
if (!gridId.IsValid())
|
if (!_mapManager.TryGetGrid(gridId, out var grid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var gridUid = grid.GridEntityId;
|
||||||
|
|
||||||
var query = EntityManager.GetEntityQuery<AirtightComponent>();
|
var query = EntityManager.GetEntityQuery<AirtightComponent>();
|
||||||
_explosionSystem.UpdateAirtightMap(gridId, pos, query);
|
_explosionSystem.UpdateAirtightMap(gridId, pos, query);
|
||||||
// TODO make atmos system use query
|
// TODO make atmos system use query
|
||||||
_atmosphereSystem.UpdateAdjacent(gridId, pos);
|
_atmosphereSystem.UpdateAdjacent(gridUid, pos);
|
||||||
_atmosphereSystem.InvalidateTile(gridId, pos);
|
_atmosphereSystem.InvalidateTile(gridUid, pos);
|
||||||
|
|
||||||
if(fixVacuum)
|
if(fixVacuum)
|
||||||
_atmosphereSystem.FixVacuum(gridId, pos);
|
_atmosphereSystem.FixTileVacuum(gridUid, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AtmosDirection Rotate(AtmosDirection myDirection, Angle myAngle)
|
private AtmosDirection Rotate(AtmosDirection myDirection, Angle myAngle)
|
||||||
|
|||||||
@@ -92,21 +92,18 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private AtmosDebugOverlayData ConvertTileToData(TileAtmosphere? tile)
|
private AtmosDebugOverlayData ConvertTileToData(TileAtmosphere? tile, bool mapIsSpace)
|
||||||
{
|
{
|
||||||
var gases = new float[Atmospherics.TotalNumberOfGases];
|
var gases = new float[Atmospherics.AdjustedNumberOfGases];
|
||||||
|
|
||||||
if (tile?.Air == null)
|
if (tile?.Air == null)
|
||||||
{
|
{
|
||||||
return new AtmosDebugOverlayData(0, gases, AtmosDirection.Invalid, tile?.LastPressureDirection ?? AtmosDirection.Invalid, false, tile?.BlockedAirflow ?? AtmosDirection.Invalid);
|
return new AtmosDebugOverlayData(Atmospherics.TCMB, gases, AtmosDirection.Invalid, tile?.LastPressureDirection ?? AtmosDirection.Invalid, 0, tile?.BlockedAirflow ?? AtmosDirection.Invalid, tile?.Space ?? mapIsSpace);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
NumericsHelpers.Add(gases, tile.Air.Moles);
|
||||||
{
|
return new AtmosDebugOverlayData(tile.Air.Temperature, gases, tile.PressureDirection, tile.LastPressureDirection, tile.ExcitedGroup?.GetHashCode() ?? 0, tile.BlockedAirflow, tile.Space);
|
||||||
gases[i] = tile.Air.GetMoles(i);
|
|
||||||
}
|
|
||||||
return new AtmosDebugOverlayData(tile.Air.Temperature, gases, tile.PressureDirection, tile.LastPressureDirection, tile.ExcitedGroup != null, tile.BlockedAirflow);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,16 +129,22 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
var transform = EntityManager.GetComponent<TransformComponent>(entity);
|
var transform = EntityManager.GetComponent<TransformComponent>(entity);
|
||||||
|
var mapUid = transform.MapUid;
|
||||||
|
|
||||||
|
var mapIsSpace = _atmosphereSystem.IsTileSpace(null, mapUid, Vector2i.Zero);
|
||||||
|
|
||||||
var worldBounds = Box2.CenteredAround(transform.WorldPosition,
|
var worldBounds = Box2.CenteredAround(transform.WorldPosition,
|
||||||
new Vector2(LocalViewRange, LocalViewRange));
|
new Vector2(LocalViewRange, LocalViewRange));
|
||||||
|
|
||||||
foreach (var grid in _mapManager.FindGridsIntersecting(transform.MapID, worldBounds))
|
foreach (var grid in _mapManager.FindGridsIntersecting(transform.MapID, worldBounds))
|
||||||
{
|
{
|
||||||
if (!EntityManager.EntityExists(grid.GridEntityId))
|
var uid = grid.GridEntityId;
|
||||||
|
|
||||||
|
if (!Exists(uid))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!EntityManager.TryGetComponent<GridAtmosphereComponent?>(grid.GridEntityId, out var gam)) continue;
|
if (!TryComp(uid, out GridAtmosphereComponent? gridAtmos))
|
||||||
|
continue;
|
||||||
|
|
||||||
var entityTile = grid.GetTileRef(transform.Coordinates).GridIndices;
|
var entityTile = grid.GetTileRef(transform.Coordinates).GridIndices;
|
||||||
var baseTile = new Vector2i(entityTile.X - (LocalViewRange / 2), entityTile.Y - (LocalViewRange / 2));
|
var baseTile = new Vector2i(entityTile.X - (LocalViewRange / 2), entityTile.Y - (LocalViewRange / 2));
|
||||||
@@ -153,7 +156,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
for (var x = 0; x < LocalViewRange; x++)
|
for (var x = 0; x < LocalViewRange; x++)
|
||||||
{
|
{
|
||||||
var vector = new Vector2i(baseTile.X + x, baseTile.Y + y);
|
var vector = new Vector2i(baseTile.X + x, baseTile.Y + y);
|
||||||
debugOverlayContent[index++] = ConvertTileToData(_atmosphereSystem.GetTileAtmosphereOrCreateSpace(grid, gam, vector));
|
debugOverlayContent[index++] = ConvertTileToData(gridAtmos.Tiles.TryGetValue(vector, out var tile) ? tile : null, mapIsSpace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,17 +12,47 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
{
|
{
|
||||||
public readonly EntityCoordinates Coordinates;
|
public readonly EntityCoordinates Coordinates;
|
||||||
public readonly GasMixture GasMixture;
|
public readonly GasMixture GasMixture;
|
||||||
|
public readonly TransformComponent Transform;
|
||||||
|
|
||||||
public AtmosExposedUpdateEvent(EntityCoordinates coordinates, GasMixture mixture)
|
public AtmosExposedUpdateEvent(EntityCoordinates coordinates, GasMixture mixture, TransformComponent transform)
|
||||||
{
|
{
|
||||||
Coordinates = coordinates;
|
Coordinates = coordinates;
|
||||||
GasMixture = mixture;
|
GasMixture = mixture;
|
||||||
|
Transform = transform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event that tries to query the mixture a certain entity is exposed to.
|
||||||
|
/// </summary>
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public struct AtmosExposedGetAirEvent
|
public struct AtmosExposedGetAirEvent
|
||||||
{
|
{
|
||||||
public GasMixture? Gas;
|
/// <summary>
|
||||||
|
/// The entity we want to query this for.
|
||||||
|
/// </summary>
|
||||||
|
public readonly EntityUid Entity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The mixture that the entity is exposed to. Output parameter.
|
||||||
|
/// </summary>
|
||||||
|
public GasMixture? Gas = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to invalidate the mixture, if possible.
|
||||||
|
/// </summary>
|
||||||
|
public bool Invalidate = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this event has been handled or not.
|
||||||
|
/// Check this before changing anything.
|
||||||
|
/// </summary>
|
||||||
|
public bool Handled = false;
|
||||||
|
|
||||||
|
public AtmosExposedGetAirEvent(EntityUid entity, bool invalidate = false)
|
||||||
|
{
|
||||||
|
Entity = entity;
|
||||||
|
invalidate = invalidate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
301
Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs
Normal file
301
Content.Server/Atmos/EntitySystems/AtmosphereSystem.API.cs
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Atmos.Piping.Components;
|
||||||
|
using Content.Server.Atmos.Reactions;
|
||||||
|
using Content.Server.NodeContainer.NodeGroups;
|
||||||
|
using Content.Shared.Atmos;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.Atmos.EntitySystems;
|
||||||
|
|
||||||
|
public partial class AtmosphereSystem
|
||||||
|
{
|
||||||
|
public GasMixture? GetContainingMixture(EntityUid uid, bool ignoreExposed = false, bool excite = false, TransformComponent? transform = null)
|
||||||
|
{
|
||||||
|
if (!ignoreExposed)
|
||||||
|
{
|
||||||
|
// Used for things like disposals/cryo to change which air people are exposed to.
|
||||||
|
var ev = new AtmosExposedGetAirEvent(uid, excite);
|
||||||
|
|
||||||
|
// Give the entity itself a chance to handle this.
|
||||||
|
RaiseLocalEvent(uid, ref ev, false);
|
||||||
|
|
||||||
|
if (ev.Handled)
|
||||||
|
return ev.Gas;
|
||||||
|
|
||||||
|
// We need to get the parent now, so we need the transform... If the parent is invalid, we can't do much else.
|
||||||
|
if(!Resolve(uid, ref transform) || !transform.ParentUid.IsValid() || transform.MapUid == null)
|
||||||
|
return GetTileMixture(null, null, Vector2i.Zero, excite);
|
||||||
|
|
||||||
|
// Give the parent entity a chance to handle the event...
|
||||||
|
RaiseLocalEvent(transform.ParentUid, ref ev, false);
|
||||||
|
|
||||||
|
if (ev.Handled)
|
||||||
|
return ev.Gas;
|
||||||
|
}
|
||||||
|
// Oops, we did a little bit of code duplication...
|
||||||
|
else if(!Resolve(uid, ref transform))
|
||||||
|
{
|
||||||
|
return GetTileMixture(null, null, Vector2i.Zero, excite);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var gridUid = transform.GridUid;
|
||||||
|
var mapUid = transform.MapUid;
|
||||||
|
var position = _transformSystem.GetGridOrMapTilePosition(uid, transform);
|
||||||
|
|
||||||
|
return GetTileMixture(gridUid, mapUid, position, excite);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasAtmosphere(EntityUid gridUid)
|
||||||
|
{
|
||||||
|
var ev = new HasAtmosphereMethodEvent(gridUid);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
|
||||||
|
return ev.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SetSimulatedGrid(EntityUid gridUid, bool simulated)
|
||||||
|
{
|
||||||
|
var ev = new SetSimulatedGridMethodEvent(gridUid, simulated);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
|
||||||
|
return ev.Handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSimulatedGrid(EntityUid gridUid)
|
||||||
|
{
|
||||||
|
var ev = new IsSimulatedGridMethodEvent(gridUid);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
|
||||||
|
return ev.Simulated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<GasMixture> GetAllMixtures(EntityUid gridUid, bool excite = false)
|
||||||
|
{
|
||||||
|
var ev = new GetAllMixturesMethodEvent(gridUid, excite);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
|
||||||
|
if(!ev.Handled)
|
||||||
|
return Enumerable.Empty<GasMixture>();
|
||||||
|
|
||||||
|
DebugTools.AssertNotNull(ev.Mixtures);
|
||||||
|
return ev.Mixtures!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InvalidateTile(EntityUid gridUid, Vector2i tile)
|
||||||
|
{
|
||||||
|
var ev = new InvalidateTileMethodEvent(gridUid, tile);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GasMixture? GetTileMixture(EntityUid? gridUid, EntityUid? mapUid, Vector2i tile, bool excite = false)
|
||||||
|
{
|
||||||
|
var ev = new GetTileMixtureMethodEvent(gridUid, mapUid, tile, excite);
|
||||||
|
|
||||||
|
// If we've been passed a grid, try to let it handle it.
|
||||||
|
if(gridUid.HasValue)
|
||||||
|
RaiseLocalEvent(gridUid.Value, ref ev, false);
|
||||||
|
|
||||||
|
if (ev.Handled)
|
||||||
|
return ev.Mixture;
|
||||||
|
|
||||||
|
// We either don't have a grid, or the event wasn't handled.
|
||||||
|
// Let the map handle it instead, and also broadcast the event.
|
||||||
|
if(mapUid.HasValue)
|
||||||
|
RaiseLocalEvent(mapUid.Value, ref ev, true);
|
||||||
|
else
|
||||||
|
RaiseLocalEvent(ref ev);
|
||||||
|
|
||||||
|
// Default to a space mixture... This is a space game, after all!
|
||||||
|
return ev.Mixture ?? GasMixture.SpaceGas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReactionResult ReactTile(EntityUid gridId, Vector2i tile)
|
||||||
|
{
|
||||||
|
var ev = new ReactTileMethodEvent(gridId, tile);
|
||||||
|
RaiseLocalEvent(gridId, ref ev);
|
||||||
|
|
||||||
|
ev.Handled = true;
|
||||||
|
|
||||||
|
return ev.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsTileAirBlocked(EntityUid gridUid, Vector2i tile, AtmosDirection directions = AtmosDirection.All, IMapGridComponent? mapGridComp = null)
|
||||||
|
{
|
||||||
|
var ev = new IsTileAirBlockedMethodEvent(gridUid, tile, directions, mapGridComp);
|
||||||
|
return ev.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsTileSpace(EntityUid? gridUid, EntityUid? mapUid, Vector2i tile, IMapGridComponent? mapGridComp = null)
|
||||||
|
{
|
||||||
|
var ev = new IsTileSpaceMethodEvent(gridUid, mapUid, tile, mapGridComp);
|
||||||
|
|
||||||
|
// Try to let the grid (if any) handle it...
|
||||||
|
if (gridUid.HasValue)
|
||||||
|
RaiseLocalEvent(gridUid.Value, ref ev, false);
|
||||||
|
|
||||||
|
// If we didn't have a grid or the event wasn't handled
|
||||||
|
// we let the map know, and also broadcast the event while at it!
|
||||||
|
if (mapUid.HasValue && !ev.Handled)
|
||||||
|
RaiseLocalEvent(mapUid.Value, ref ev, true);
|
||||||
|
|
||||||
|
// We didn't have a map, and the event isn't handled, therefore broadcast the event.
|
||||||
|
else if (!mapUid.HasValue && !ev.Handled)
|
||||||
|
RaiseLocalEvent(ref ev);
|
||||||
|
|
||||||
|
// If nothing handled the event, it'll default to true.
|
||||||
|
// Oh well, this is a space game after all, deal with it!
|
||||||
|
return ev.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsTileMixtureProbablySafe(EntityUid? gridUid, EntityUid mapUid, Vector2i tile)
|
||||||
|
{
|
||||||
|
return IsMixtureProbablySafe(GetTileMixture(gridUid, mapUid, tile));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetTileHeatCapacity(EntityUid? gridUid, EntityUid mapUid, Vector2i tile)
|
||||||
|
{
|
||||||
|
return GetHeatCapacity(GetTileMixture(gridUid, mapUid, tile) ?? GasMixture.SpaceGas);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Vector2i> GetAdjacentTiles(EntityUid gridUid, Vector2i tile)
|
||||||
|
{
|
||||||
|
var ev = new GetAdjacentTilesMethodEvent(gridUid, tile);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
|
||||||
|
return ev.Result ?? Enumerable.Empty<Vector2i>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<GasMixture> GetAdjacentTileMixtures(EntityUid gridUid, Vector2i tile, bool includeBlocked = false, bool excite = false)
|
||||||
|
{
|
||||||
|
var ev = new GetAdjacentTileMixturesMethodEvent(gridUid, tile, includeBlocked, excite);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
|
||||||
|
return ev.Result ?? Enumerable.Empty<GasMixture>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateAdjacent(EntityUid gridUid, Vector2i tile, IMapGridComponent? mapGridComp = null)
|
||||||
|
{
|
||||||
|
var ev = new UpdateAdjacentMethodEvent(gridUid, tile, mapGridComp);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HotspotExpose(EntityUid gridUid, Vector2i tile, float exposedTemperature, float exposedVolume, bool soh = false)
|
||||||
|
{
|
||||||
|
var ev = new HotspotExposeMethodEvent(gridUid, tile, exposedTemperature, exposedVolume, soh);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HotspotExtinguish(EntityUid gridUid, Vector2i tile)
|
||||||
|
{
|
||||||
|
var ev = new HotspotExtinguishMethodEvent(gridUid, tile);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsHotspotActive(EntityUid gridUid, Vector2i tile)
|
||||||
|
{
|
||||||
|
var ev = new IsHotspotActiveMethodEvent(gridUid, tile);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
|
||||||
|
// If not handled, this will be false. Just like in space!
|
||||||
|
return ev.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FixTileVacuum(EntityUid gridUid, Vector2i tile)
|
||||||
|
{
|
||||||
|
var ev = new FixTileVacuumMethodEvent(gridUid, tile);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddPipeNet(EntityUid gridUid, PipeNet pipeNet)
|
||||||
|
{
|
||||||
|
var ev = new AddPipeNetMethodEvent(gridUid, pipeNet);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemovePipeNet(EntityUid gridUid, PipeNet pipeNet)
|
||||||
|
{
|
||||||
|
var ev = new RemovePipeNetMethodEvent(gridUid, pipeNet);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddAtmosDevice(EntityUid gridUid, AtmosDeviceComponent device)
|
||||||
|
{
|
||||||
|
// TODO: check device is on grid
|
||||||
|
|
||||||
|
var ev = new AddAtmosDeviceMethodEvent(gridUid, device);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
return ev.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool RemoveAtmosDevice(EntityUid gridUid, AtmosDeviceComponent device)
|
||||||
|
{
|
||||||
|
// TODO: check device is on grid
|
||||||
|
|
||||||
|
var ev = new RemoveAtmosDeviceMethodEvent(gridUid, device);
|
||||||
|
RaiseLocalEvent(gridUid, ref ev);
|
||||||
|
return ev.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct HasAtmosphereMethodEvent
|
||||||
|
(EntityUid Grid, bool Result = false, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct SetSimulatedGridMethodEvent
|
||||||
|
(EntityUid Grid, bool Simulated, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct IsSimulatedGridMethodEvent
|
||||||
|
(EntityUid Grid, bool Simulated = false, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct GetAllMixturesMethodEvent
|
||||||
|
(EntityUid Grid, bool Excite = false, IEnumerable<GasMixture>? Mixtures = null, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct InvalidateTileMethodEvent
|
||||||
|
(EntityUid Grid, Vector2i Tile, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct GetTileMixtureMethodEvent
|
||||||
|
(EntityUid? GridUid, EntityUid? MapUid, Vector2i Tile, bool Excite = false, GasMixture? Mixture = null, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct ReactTileMethodEvent
|
||||||
|
(EntityUid GridId, Vector2i Tile, ReactionResult Result = default, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct IsTileAirBlockedMethodEvent
|
||||||
|
(EntityUid Grid, Vector2i Tile, AtmosDirection Direction = AtmosDirection.All, IMapGridComponent? MapGridComponent = null, bool Result = false, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct IsTileSpaceMethodEvent
|
||||||
|
(EntityUid? Grid, EntityUid? Map, Vector2i Tile, IMapGridComponent? MapGridComponent = null, bool Result = true, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct GetAdjacentTilesMethodEvent
|
||||||
|
(EntityUid Grid, Vector2i Tile, IEnumerable<Vector2i>? Result = null, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct GetAdjacentTileMixturesMethodEvent
|
||||||
|
(EntityUid Grid, Vector2i Tile, bool IncludeBlocked, bool Excite,
|
||||||
|
IEnumerable<GasMixture>? Result = null, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct UpdateAdjacentMethodEvent
|
||||||
|
(EntityUid Grid, Vector2i Tile, IMapGridComponent? MapGridComponent = null, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct HotspotExposeMethodEvent
|
||||||
|
(EntityUid Grid, Vector2i Tile, float ExposedTemperature, float ExposedVolume, bool soh, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct HotspotExtinguishMethodEvent
|
||||||
|
(EntityUid Grid, Vector2i Tile, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct IsHotspotActiveMethodEvent
|
||||||
|
(EntityUid Grid, Vector2i Tile, bool Result = false, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct FixTileVacuumMethodEvent
|
||||||
|
(EntityUid Grid, Vector2i Tile, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct AddPipeNetMethodEvent
|
||||||
|
(EntityUid Grid, PipeNet PipeNet, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct RemovePipeNetMethodEvent
|
||||||
|
(EntityUid Grid, PipeNet PipeNet, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct AddAtmosDeviceMethodEvent
|
||||||
|
(EntityUid Grid, AtmosDeviceComponent Device, bool Result = false, bool Handled = false);
|
||||||
|
|
||||||
|
[ByRefEvent] private record struct RemoveAtmosDeviceMethodEvent
|
||||||
|
(EntityUid Grid, AtmosDeviceComponent Device, bool Result = false, bool Handled = false);
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using Content.Server.Administration;
|
|||||||
using Content.Server.Atmos.Components;
|
using Content.Server.Atmos.Components;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
|
using Content.Shared.Maps;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
@@ -83,12 +84,20 @@ public sealed partial class AtmosphereSystem
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var transform = Transform(euid);
|
||||||
|
|
||||||
foreach (var (indices, tileMain) in gridAtmosphere.Tiles)
|
foreach (var (indices, tileMain) in gridAtmosphere.Tiles)
|
||||||
{
|
{
|
||||||
var tile = tileMain.Air;
|
var tile = tileMain.Air;
|
||||||
if (tile == null)
|
if (tile == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (tile.Immutable && !IsTileSpace(euid, transform.MapUid, indices, gridComp))
|
||||||
|
{
|
||||||
|
tile = new GasMixture(tile.Volume) { Temperature = tile.Temperature };
|
||||||
|
tileMain.Air = tile;
|
||||||
|
}
|
||||||
|
|
||||||
tile.Clear();
|
tile.Clear();
|
||||||
var mixtureId = 0;
|
var mixtureId = 0;
|
||||||
foreach (var entUid in gridComp.Grid.GetAnchoredEntities(indices))
|
foreach (var entUid in gridComp.Grid.GetAnchoredEntities(indices))
|
||||||
@@ -102,7 +111,7 @@ public sealed partial class AtmosphereSystem
|
|||||||
Merge(tile, mixture);
|
Merge(tile, mixture);
|
||||||
tile.Temperature = mixture.Temperature;
|
tile.Temperature = mixture.Temperature;
|
||||||
|
|
||||||
InvalidateTile(gridAtmosphere, indices);
|
gridAtmosphere.InvalidatedCoords.Add(indices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
|
|
||||||
Merge(combined, tile.Air);
|
Merge(combined, tile.Air);
|
||||||
|
|
||||||
if (!ExcitedGroupsSpaceIsAllConsuming || !tile.Air.Immutable)
|
if (!ExcitedGroupsSpaceIsAllConsuming || !tile.Space)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
combined.Clear();
|
combined.Clear();
|
||||||
|
|||||||
@@ -48,19 +48,11 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
return GetHeatCapacityCalculation(mixture.Moles, mixture.Immutable);
|
return GetHeatCapacityCalculation(mixture.Moles, mixture.Immutable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calculates the heat capacity for a gas mixture, using the archived values.
|
|
||||||
/// </summary>
|
|
||||||
public float GetHeatCapacityArchived(GasMixture mixture)
|
|
||||||
{
|
|
||||||
return GetHeatCapacityCalculation(mixture.MolesArchived, mixture.Immutable);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private float GetHeatCapacityCalculation(float[] moles, bool immutable)
|
private float GetHeatCapacityCalculation(float[] moles, bool space)
|
||||||
{
|
{
|
||||||
// Little hack to make space gas mixtures have heat capacity, therefore allowing them to cool down rooms.
|
// Little hack to make space gas mixtures have heat capacity, therefore allowing them to cool down rooms.
|
||||||
if (immutable && MathHelper.CloseTo(NumericsHelpers.HorizontalAdd(moles), 0f))
|
if (space && MathHelper.CloseTo(NumericsHelpers.HorizontalAdd(moles), 0f))
|
||||||
{
|
{
|
||||||
return Atmospherics.SpaceHeatCapacity;
|
return Atmospherics.SpaceHeatCapacity;
|
||||||
}
|
}
|
||||||
@@ -154,140 +146,6 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shares gas between two gas mixtures. Part of LINDA.
|
|
||||||
/// </summary>
|
|
||||||
public float Share(GasMixture receiver, GasMixture sharer, int atmosAdjacentTurfs)
|
|
||||||
{
|
|
||||||
var temperatureDelta = receiver.TemperatureArchived - sharer.TemperatureArchived;
|
|
||||||
var absTemperatureDelta = Math.Abs(temperatureDelta);
|
|
||||||
var oldHeatCapacity = 0f;
|
|
||||||
var oldSharerHeatCapacity = 0f;
|
|
||||||
|
|
||||||
if (absTemperatureDelta > Atmospherics.MinimumTemperatureDeltaToConsider)
|
|
||||||
{
|
|
||||||
oldHeatCapacity = GetHeatCapacity(receiver);
|
|
||||||
oldSharerHeatCapacity = GetHeatCapacity(sharer);
|
|
||||||
}
|
|
||||||
|
|
||||||
var heatCapacityToSharer = 0f;
|
|
||||||
var heatCapacitySharerToThis = 0f;
|
|
||||||
var movedMoles = 0f;
|
|
||||||
var absMovedMoles = 0f;
|
|
||||||
|
|
||||||
for(var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
|
||||||
{
|
|
||||||
var thisValue = receiver.Moles[i];
|
|
||||||
var sharerValue = sharer.Moles[i];
|
|
||||||
var delta = (thisValue - sharerValue) / (atmosAdjacentTurfs + 1);
|
|
||||||
if (!(MathF.Abs(delta) >= Atmospherics.GasMinMoles)) continue;
|
|
||||||
if (absTemperatureDelta > Atmospherics.MinimumTemperatureDeltaToConsider)
|
|
||||||
{
|
|
||||||
var gasHeatCapacity = delta * GasSpecificHeats[i];
|
|
||||||
if (delta > 0)
|
|
||||||
{
|
|
||||||
heatCapacityToSharer += gasHeatCapacity;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
heatCapacitySharerToThis -= gasHeatCapacity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!receiver.Immutable) receiver.Moles[i] -= delta;
|
|
||||||
if (!sharer.Immutable) sharer.Moles[i] += delta;
|
|
||||||
movedMoles += delta;
|
|
||||||
absMovedMoles += MathF.Abs(delta);
|
|
||||||
}
|
|
||||||
|
|
||||||
receiver.LastShare = absMovedMoles;
|
|
||||||
|
|
||||||
if (absTemperatureDelta > Atmospherics.MinimumTemperatureDeltaToConsider)
|
|
||||||
{
|
|
||||||
var newHeatCapacity = oldHeatCapacity + heatCapacitySharerToThis - heatCapacityToSharer;
|
|
||||||
var newSharerHeatCapacity = oldSharerHeatCapacity + heatCapacityToSharer - heatCapacitySharerToThis;
|
|
||||||
|
|
||||||
// Transfer of thermal energy (via changed heat capacity) between self and sharer.
|
|
||||||
if (!receiver.Immutable && newHeatCapacity > Atmospherics.MinimumHeatCapacity)
|
|
||||||
{
|
|
||||||
receiver.Temperature = ((oldHeatCapacity * receiver.Temperature) - (heatCapacityToSharer * receiver.TemperatureArchived) + (heatCapacitySharerToThis * sharer.TemperatureArchived)) / newHeatCapacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sharer.Immutable && newSharerHeatCapacity > Atmospherics.MinimumHeatCapacity)
|
|
||||||
{
|
|
||||||
sharer.Temperature = ((oldSharerHeatCapacity * sharer.Temperature) - (heatCapacitySharerToThis * sharer.TemperatureArchived) + (heatCapacityToSharer*receiver.TemperatureArchived)) / newSharerHeatCapacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thermal energy of the system (self and sharer) is unchanged.
|
|
||||||
|
|
||||||
if (MathF.Abs(oldSharerHeatCapacity) > Atmospherics.MinimumHeatCapacity)
|
|
||||||
{
|
|
||||||
if (MathF.Abs(newSharerHeatCapacity / oldSharerHeatCapacity - 1) < 0.1)
|
|
||||||
{
|
|
||||||
TemperatureShare(receiver, sharer, Atmospherics.OpenHeatTransferCoefficient);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(temperatureDelta > Atmospherics.MinimumTemperatureToMove) &&
|
|
||||||
!(MathF.Abs(movedMoles) > Atmospherics.MinimumMolesDeltaToMove)) return 0f;
|
|
||||||
var moles = receiver.TotalMoles;
|
|
||||||
var theirMoles = sharer.TotalMoles;
|
|
||||||
|
|
||||||
return (receiver.TemperatureArchived * (moles + movedMoles)) - (sharer.TemperatureArchived * (theirMoles - movedMoles)) * Atmospherics.R / receiver.Volume;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shares temperature between two mixtures, taking a conduction coefficient into account.
|
|
||||||
/// </summary>
|
|
||||||
public float TemperatureShare(GasMixture receiver, GasMixture sharer, float conductionCoefficient)
|
|
||||||
{
|
|
||||||
var temperatureDelta = receiver.TemperatureArchived - sharer.TemperatureArchived;
|
|
||||||
if (MathF.Abs(temperatureDelta) > Atmospherics.MinimumTemperatureDeltaToConsider)
|
|
||||||
{
|
|
||||||
var heatCapacity = GetHeatCapacityArchived(receiver);
|
|
||||||
var sharerHeatCapacity = GetHeatCapacityArchived(sharer);
|
|
||||||
|
|
||||||
if (sharerHeatCapacity > Atmospherics.MinimumHeatCapacity && heatCapacity > Atmospherics.MinimumHeatCapacity)
|
|
||||||
{
|
|
||||||
var heat = conductionCoefficient * temperatureDelta * (heatCapacity * sharerHeatCapacity / (heatCapacity + sharerHeatCapacity));
|
|
||||||
|
|
||||||
if (!receiver.Immutable)
|
|
||||||
receiver.Temperature = MathF.Abs(MathF.Max(receiver.Temperature - heat / heatCapacity, Atmospherics.TCMB));
|
|
||||||
|
|
||||||
if (!sharer.Immutable)
|
|
||||||
sharer.Temperature = MathF.Abs(MathF.Max(sharer.Temperature + heat / sharerHeatCapacity, Atmospherics.TCMB));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sharer.Temperature;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shares temperature between a gas mixture and an abstract sharer, taking a conduction coefficient into account.
|
|
||||||
/// </summary>
|
|
||||||
public float TemperatureShare(GasMixture receiver, float conductionCoefficient, float sharerTemperature, float sharerHeatCapacity)
|
|
||||||
{
|
|
||||||
var temperatureDelta = receiver.TemperatureArchived - sharerTemperature;
|
|
||||||
if (MathF.Abs(temperatureDelta) > Atmospherics.MinimumTemperatureDeltaToConsider)
|
|
||||||
{
|
|
||||||
var heatCapacity = GetHeatCapacityArchived(receiver);
|
|
||||||
|
|
||||||
if (sharerHeatCapacity > Atmospherics.MinimumHeatCapacity && heatCapacity > Atmospherics.MinimumHeatCapacity)
|
|
||||||
{
|
|
||||||
var heat = conductionCoefficient * temperatureDelta * (heatCapacity * sharerHeatCapacity / (heatCapacity + sharerHeatCapacity));
|
|
||||||
|
|
||||||
if (!receiver.Immutable)
|
|
||||||
receiver.Temperature = MathF.Abs(MathF.Max(receiver.Temperature - heat / heatCapacity, Atmospherics.TCMB));
|
|
||||||
|
|
||||||
sharerTemperature = MathF.Abs(MathF.Max(sharerTemperature + heat / sharerHeatCapacity, Atmospherics.TCMB));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sharerTemperature;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Releases gas from this mixture to the output mixture.
|
/// Releases gas from this mixture to the output mixture.
|
||||||
/// If the output mixture is null, then this is being released into space.
|
/// If the output mixture is null, then this is being released into space.
|
||||||
@@ -362,6 +220,62 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
Merge(destination, buffer);
|
Merge(destination, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks whether a gas mixture is probably safe.
|
||||||
|
/// This only checks temperature and pressure, not gas composition.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="air">Mixture to be checked.</param>
|
||||||
|
/// <returns>Whether the mixture is probably safe.</returns>
|
||||||
|
public bool IsMixtureProbablySafe(GasMixture? air)
|
||||||
|
{
|
||||||
|
// Note that oxygen mix isn't checked, but survival boxes make that not necessary.
|
||||||
|
if (air == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (air.Pressure)
|
||||||
|
{
|
||||||
|
case <= Atmospherics.WarningLowPressure:
|
||||||
|
case >= Atmospherics.WarningHighPressure:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (air.Temperature)
|
||||||
|
{
|
||||||
|
case <= 260:
|
||||||
|
case >= 360:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares two gas mixtures to see if they are within acceptable ranges for group processing to be enabled.
|
||||||
|
/// </summary>
|
||||||
|
public GasCompareResult CompareExchange(GasMixture sample, GasMixture otherSample)
|
||||||
|
{
|
||||||
|
var moles = 0f;
|
||||||
|
|
||||||
|
for(var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||||
|
{
|
||||||
|
var gasMoles = sample.Moles[i];
|
||||||
|
var delta = MathF.Abs(gasMoles - otherSample.Moles[i]);
|
||||||
|
if (delta > Atmospherics.MinimumMolesDeltaToMove && (delta > gasMoles * Atmospherics.MinimumAirRatioToMove))
|
||||||
|
return (GasCompareResult)i; // We can move gases!
|
||||||
|
moles += gasMoles;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moles > Atmospherics.MinimumMolesDeltaToMove)
|
||||||
|
{
|
||||||
|
var tempDelta = MathF.Abs(sample.Temperature - otherSample.Temperature);
|
||||||
|
if (tempDelta > Atmospherics.MinimumTemperatureDeltaToSuspend)
|
||||||
|
return GasCompareResult.TemperatureExchange; // There can be temperature exchange.
|
||||||
|
}
|
||||||
|
|
||||||
|
// No exchange at all!
|
||||||
|
return GasCompareResult.NoExchange;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs reactions for a given gas mixture on an optional holder.
|
/// Performs reactions for a given gas mixture on an optional holder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -401,5 +315,11 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
|
|
||||||
return reaction;
|
return reaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum GasCompareResult
|
||||||
|
{
|
||||||
|
NoExchange = -2,
|
||||||
|
TemperatureExchange = -1,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,549 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Content.Server.Atmos.Components;
|
||||||
|
using Content.Server.Atmos.Reactions;
|
||||||
|
using Content.Shared.Atmos;
|
||||||
|
using Content.Shared.Maps;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.Atmos.EntitySystems;
|
||||||
|
|
||||||
|
public sealed partial class AtmosphereSystem
|
||||||
|
{
|
||||||
|
private void InitializeGridAtmosphere()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, ComponentInit>(OnGridAtmosphereInit);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, GridSplitEvent>(OnGridSplit);
|
||||||
|
|
||||||
|
#region Atmos API Subscriptions
|
||||||
|
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, HasAtmosphereMethodEvent>(GridHasAtmosphere);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, IsSimulatedGridMethodEvent>(GridIsSimulated);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, GetAllMixturesMethodEvent>(GridGetAllMixtures);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, InvalidateTileMethodEvent>(GridInvalidateTile);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, GetTileMixtureMethodEvent>(GridGetTileMixture);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, ReactTileMethodEvent>(GridReactTile);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, IsTileAirBlockedMethodEvent>(GridIsTileAirBlocked);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, IsTileSpaceMethodEvent>(GridIsTileSpace);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, GetAdjacentTilesMethodEvent>(GridGetAdjacentTiles);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, GetAdjacentTileMixturesMethodEvent>(GridGetAdjacentTileMixtures);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, UpdateAdjacentMethodEvent>(GridUpdateAdjacent);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, HotspotExposeMethodEvent>(GridHotspotExpose);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, HotspotExtinguishMethodEvent>(GridHotspotExtinguish);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, IsHotspotActiveMethodEvent>(GridIsHotspotActive);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, FixTileVacuumMethodEvent>(GridFixTileVacuum);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, AddPipeNetMethodEvent>(GridAddPipeNet);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, RemovePipeNetMethodEvent>(GridRemovePipeNet);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, AddAtmosDeviceMethodEvent>(GridAddAtmosDevice);
|
||||||
|
SubscribeLocalEvent<GridAtmosphereComponent, RemoveAtmosDeviceMethodEvent>(GridRemoveAtmosDevice);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGridAtmosphereInit(EntityUid uid, GridAtmosphereComponent gridAtmosphere, ComponentInit args)
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
gridAtmosphere.Tiles.Clear();
|
||||||
|
|
||||||
|
if (!TryComp(uid, out IMapGridComponent? mapGrid))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (gridAtmosphere.TilesUniqueMixes != null)
|
||||||
|
{
|
||||||
|
foreach (var (indices, mix) in gridAtmosphere.TilesUniqueMixes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
gridAtmosphere.Tiles.Add(indices, new TileAtmosphere(mapGrid.Owner, indices,
|
||||||
|
gridAtmosphere.UniqueMixes![mix].Clone()));
|
||||||
|
}
|
||||||
|
catch (ArgumentOutOfRangeException)
|
||||||
|
{
|
||||||
|
Logger.Error(
|
||||||
|
$"Error during atmos serialization! Tile at {indices} points to an unique mix ({mix}) out of range!");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
gridAtmosphere.InvalidatedCoords.Add(indices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GridRepopulateTiles(mapGrid.Grid, gridAtmosphere);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGridSplit(EntityUid uid, GridAtmosphereComponent originalGridAtmos, ref GridSplitEvent args)
|
||||||
|
{
|
||||||
|
foreach (var newGrid in args.NewGrids)
|
||||||
|
{
|
||||||
|
// Make extra sure this is a valid grid.
|
||||||
|
if (!_mapManager.TryGetGrid(newGrid, out var mapGrid))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var entity = mapGrid.GridEntityId;
|
||||||
|
|
||||||
|
// If the new split grid has an atmosphere already somehow, use that. Otherwise, add a new one.
|
||||||
|
if (!TryComp(entity, out GridAtmosphereComponent? newGridAtmos))
|
||||||
|
newGridAtmos = AddComp<GridAtmosphereComponent>(entity);
|
||||||
|
|
||||||
|
// We assume the tiles on the new grid have the same coordinates as they did on the old grid...
|
||||||
|
var enumerator = mapGrid.GetAllTilesEnumerator();
|
||||||
|
|
||||||
|
while (enumerator.MoveNext(out var tile))
|
||||||
|
{
|
||||||
|
var indices = tile.Value.GridIndices;
|
||||||
|
|
||||||
|
// This split event happens *before* the spaced tiles have been invalidated, therefore we can still
|
||||||
|
// access their gas data. On the next atmos update tick, these tiles will be spaced. Poof!
|
||||||
|
if (!originalGridAtmos.Tiles.TryGetValue(indices, out var tileAtmosphere))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// The new grid atmosphere has been initialized, meaning it has all the needed TileAtmospheres...
|
||||||
|
if (!newGridAtmos.Tiles.TryGetValue(indices, out var newTileAtmosphere))
|
||||||
|
// Let's be honest, this is really not gonna happen, but just in case...!
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Copy a bunch of data over... Not great, maybe put this in TileAtmosphere?
|
||||||
|
newTileAtmosphere.Air = tileAtmosphere.Air?.Clone() ?? null;
|
||||||
|
newTileAtmosphere.MolesArchived = newTileAtmosphere.Air == null ? null : new float[Atmospherics.AdjustedNumberOfGases];
|
||||||
|
newTileAtmosphere.Hotspot = tileAtmosphere.Hotspot;
|
||||||
|
newTileAtmosphere.HeatCapacity = tileAtmosphere.HeatCapacity;
|
||||||
|
newTileAtmosphere.Temperature = tileAtmosphere.Temperature;
|
||||||
|
newTileAtmosphere.PressureDifference = tileAtmosphere.PressureDifference;
|
||||||
|
newTileAtmosphere.PressureDirection = tileAtmosphere.PressureDirection;
|
||||||
|
|
||||||
|
// TODO ATMOS: Somehow force GasTileOverlaySystem to perform an update *right now, right here.*
|
||||||
|
// The reason why is that right now, gas will flicker until the next GasTileOverlay update.
|
||||||
|
// That looks bad, of course. We want to avoid that! Anyway that's a bit more complicated so out of scope.
|
||||||
|
|
||||||
|
// Invalidate the tile, it's redundant but redundancy is good! Also HashSet so really, no duplicates.
|
||||||
|
originalGridAtmos.InvalidatedCoords.Add(indices);
|
||||||
|
newGridAtmos.InvalidatedCoords.Add(indices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridHasAtmosphere(EntityUid uid, GridAtmosphereComponent component, ref HasAtmosphereMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Result = true;
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridIsSimulated(EntityUid uid, GridAtmosphereComponent component, ref IsSimulatedGridMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Simulated = component.Simulated;
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridGetAllMixtures(EntityUid uid, GridAtmosphereComponent component,
|
||||||
|
ref GetAllMixturesMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IEnumerable<GasMixture> EnumerateMixtures(EntityUid gridUid, GridAtmosphereComponent grid, bool invalidate)
|
||||||
|
{
|
||||||
|
foreach (var (indices, tile) in grid.Tiles)
|
||||||
|
{
|
||||||
|
if (tile.Air == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (invalidate)
|
||||||
|
{
|
||||||
|
//var ev = new InvalidateTileMethodEvent(gridUid, indices);
|
||||||
|
//GridInvalidateTile(gridUid, grid, ref ev);
|
||||||
|
AddActiveTile(grid, tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return tile.Air;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the enumeration over all the tiles in the atmosphere.
|
||||||
|
args.Mixtures = EnumerateMixtures(uid, component, args.Excite);
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridInvalidateTile(EntityUid uid, GridAtmosphereComponent component, ref InvalidateTileMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
component.InvalidatedCoords.Add(args.Tile);
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridGetTileMixture(EntityUid uid, GridAtmosphereComponent component,
|
||||||
|
ref GetTileMixtureMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!component.Tiles.TryGetValue(args.Tile, out var tile))
|
||||||
|
return; // Do NOT handle the event if we don't have that tile, the map will handle it instead.
|
||||||
|
|
||||||
|
if (args.Excite)
|
||||||
|
component.InvalidatedCoords.Add(args.Tile);
|
||||||
|
|
||||||
|
args.Mixture = tile.Air;
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridReactTile(EntityUid uid, GridAtmosphereComponent component, ref ReactTileMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!component.Tiles.TryGetValue(args.Tile, out var tile))
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Result = tile.Air is { } air ? React(air, tile) : ReactionResult.NoReaction;
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridIsTileAirBlocked(EntityUid uid, GridAtmosphereComponent component,
|
||||||
|
ref IsTileAirBlockedMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var mapGridComp = args.MapGridComponent;
|
||||||
|
|
||||||
|
if (!Resolve(uid, ref mapGridComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var directions = AtmosDirection.Invalid;
|
||||||
|
|
||||||
|
var enumerator = GetObstructingComponentsEnumerator(mapGridComp.Grid, args.Tile);
|
||||||
|
|
||||||
|
while (enumerator.MoveNext(out var obstructingComponent))
|
||||||
|
{
|
||||||
|
if (!obstructingComponent.AirBlocked)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// We set the directions that are air-blocked so far,
|
||||||
|
// as you could have a full obstruction with only 4 directional air blockers.
|
||||||
|
directions |= obstructingComponent.AirBlockedDirection;
|
||||||
|
|
||||||
|
if (directions.IsFlagSet(args.Direction))
|
||||||
|
{
|
||||||
|
args.Result = true;
|
||||||
|
args.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Result = false;
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridIsTileSpace(EntityUid uid, GridAtmosphereComponent component, ref IsTileSpaceMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// We don't have that tile, so let the map handle it.
|
||||||
|
if (!component.Tiles.TryGetValue(args.Tile, out var tile))
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Result = tile.Space;
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridGetAdjacentTiles(EntityUid uid, GridAtmosphereComponent component,
|
||||||
|
ref GetAdjacentTilesMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!component.Tiles.TryGetValue(args.Tile, out var tile))
|
||||||
|
return;
|
||||||
|
|
||||||
|
IEnumerable<Vector2i> EnumerateAdjacent(GridAtmosphereComponent grid, TileAtmosphere t)
|
||||||
|
{
|
||||||
|
foreach (var adj in t.AdjacentTiles)
|
||||||
|
{
|
||||||
|
if (adj == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
yield return adj.GridIndices;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Result = EnumerateAdjacent(component, tile);
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridGetAdjacentTileMixtures(EntityUid uid, GridAtmosphereComponent component,
|
||||||
|
ref GetAdjacentTileMixturesMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!component.Tiles.TryGetValue(args.Tile, out var tile))
|
||||||
|
return;
|
||||||
|
|
||||||
|
IEnumerable<GasMixture> EnumerateAdjacent(GridAtmosphereComponent grid, TileAtmosphere t)
|
||||||
|
{
|
||||||
|
foreach (var adj in t.AdjacentTiles)
|
||||||
|
{
|
||||||
|
if (adj?.Air == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
yield return adj.Air;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Result = EnumerateAdjacent(component, tile);
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridUpdateAdjacent(EntityUid uid, GridAtmosphereComponent component,
|
||||||
|
ref UpdateAdjacentMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var mapGridComp = args.MapGridComponent;
|
||||||
|
|
||||||
|
if (!Resolve(uid, ref mapGridComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var xform = Transform(uid);
|
||||||
|
EntityUid? mapUid = _mapManager.MapExists(xform.MapID) ? _mapManager.GetMapEntityId(xform.MapID) : null;
|
||||||
|
|
||||||
|
if (!component.Tiles.TryGetValue(args.Tile, out var tile))
|
||||||
|
return;
|
||||||
|
|
||||||
|
tile.AdjacentBits = AtmosDirection.Invalid;
|
||||||
|
tile.BlockedAirflow = GetBlockedDirections(mapGridComp.Grid, tile.GridIndices);
|
||||||
|
|
||||||
|
for (var i = 0; i < Atmospherics.Directions; i++)
|
||||||
|
{
|
||||||
|
var direction = (AtmosDirection) (1 << i);
|
||||||
|
|
||||||
|
var otherIndices = tile.GridIndices.Offset(direction);
|
||||||
|
|
||||||
|
if (!component.Tiles.TryGetValue(otherIndices, out var adjacent))
|
||||||
|
{
|
||||||
|
adjacent = new TileAtmosphere(tile.GridIndex, otherIndices,
|
||||||
|
GetTileMixture(uid, mapUid, args.Tile),
|
||||||
|
space:IsTileSpace(uid, mapUid, otherIndices, mapGridComp));
|
||||||
|
}
|
||||||
|
|
||||||
|
var oppositeDirection = direction.GetOpposite();
|
||||||
|
|
||||||
|
adjacent.BlockedAirflow = GetBlockedDirections(mapGridComp.Grid, adjacent.GridIndices);
|
||||||
|
|
||||||
|
// Pass in IMapGridComponent so we don't have to resolve it for every adjacent direction.
|
||||||
|
var tileBlockedEv = new IsTileAirBlockedMethodEvent(uid, tile.GridIndices, direction, mapGridComp);
|
||||||
|
GridIsTileAirBlocked(uid, component, ref tileBlockedEv);
|
||||||
|
|
||||||
|
var adjacentBlockedEv =
|
||||||
|
new IsTileAirBlockedMethodEvent(uid, adjacent.GridIndices, oppositeDirection, mapGridComp);
|
||||||
|
GridIsTileAirBlocked(uid, component, ref adjacentBlockedEv);
|
||||||
|
|
||||||
|
if (!adjacent.BlockedAirflow.IsFlagSet(oppositeDirection) && !tileBlockedEv.Result)
|
||||||
|
{
|
||||||
|
adjacent.AdjacentBits |= oppositeDirection;
|
||||||
|
adjacent.AdjacentTiles[oppositeDirection.ToIndex()] = tile;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
adjacent.AdjacentBits &= ~oppositeDirection;
|
||||||
|
adjacent.AdjacentTiles[oppositeDirection.ToIndex()] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tile.BlockedAirflow.IsFlagSet(direction) && !adjacentBlockedEv.Result)
|
||||||
|
{
|
||||||
|
tile.AdjacentBits |= direction;
|
||||||
|
tile.AdjacentTiles[direction.ToIndex()] = adjacent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tile.AdjacentBits &= ~direction;
|
||||||
|
tile.AdjacentTiles[direction.ToIndex()] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugTools.Assert(!(tile.AdjacentBits.IsFlagSet(direction) ^
|
||||||
|
adjacent.AdjacentBits.IsFlagSet(oppositeDirection)));
|
||||||
|
|
||||||
|
if (!adjacent.AdjacentBits.IsFlagSet(adjacent.MonstermosInfo.CurrentTransferDirection))
|
||||||
|
adjacent.MonstermosInfo.CurrentTransferDirection = AtmosDirection.Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tile.AdjacentBits.IsFlagSet(tile.MonstermosInfo.CurrentTransferDirection))
|
||||||
|
tile.MonstermosInfo.CurrentTransferDirection = AtmosDirection.Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridHotspotExpose(EntityUid uid, GridAtmosphereComponent component, ref HotspotExposeMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!component.Tiles.TryGetValue(args.Tile, out var tile))
|
||||||
|
return;
|
||||||
|
|
||||||
|
HotspotExpose(component, tile, args.ExposedTemperature, args.ExposedVolume, args.soh);
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridHotspotExtinguish(EntityUid uid, GridAtmosphereComponent component,
|
||||||
|
ref HotspotExtinguishMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!component.Tiles.TryGetValue(args.Tile, out var tile))
|
||||||
|
return;
|
||||||
|
|
||||||
|
tile.Hotspot = new Hotspot();
|
||||||
|
args.Handled = true;
|
||||||
|
|
||||||
|
//var ev = new InvalidateTileMethodEvent(uid, args.Tile);
|
||||||
|
//GridInvalidateTile(uid, component, ref ev);
|
||||||
|
AddActiveTile(component, tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridIsHotspotActive(EntityUid uid, GridAtmosphereComponent component,
|
||||||
|
ref IsHotspotActiveMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!component.Tiles.TryGetValue(args.Tile, out var tile))
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Result = tile.Hotspot.Valid;
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridFixTileVacuum(EntityUid uid, GridAtmosphereComponent component, ref FixTileVacuumMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var adjEv = new GetAdjacentTileMixturesMethodEvent(uid, args.Tile, false, true);
|
||||||
|
GridGetAdjacentTileMixtures(uid, component, ref adjEv);
|
||||||
|
|
||||||
|
if (!adjEv.Handled || !component.Tiles.TryGetValue(args.Tile, out var tile))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!TryComp<IMapGridComponent>(uid, out var mapGridComp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var adjacent = adjEv.Result!.ToArray();
|
||||||
|
|
||||||
|
tile.Air = new GasMixture
|
||||||
|
{
|
||||||
|
Volume = GetVolumeForTiles(mapGridComp.Grid, 1),
|
||||||
|
Temperature = Atmospherics.T20C
|
||||||
|
};
|
||||||
|
|
||||||
|
tile.MolesArchived = new float[Atmospherics.AdjustedNumberOfGases];
|
||||||
|
tile.ArchivedCycle = 0;
|
||||||
|
|
||||||
|
// Return early, let's not cause any funny NaNs.
|
||||||
|
if (adjacent.Length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var ratio = 1f / adjacent.Length;
|
||||||
|
var totalTemperature = 0f;
|
||||||
|
|
||||||
|
foreach (var adj in adjacent)
|
||||||
|
{
|
||||||
|
totalTemperature += adj.Temperature;
|
||||||
|
|
||||||
|
// Remove a bit of gas from the adjacent ratio...
|
||||||
|
var mix = adj.RemoveRatio(ratio);
|
||||||
|
|
||||||
|
// And merge it to the new tile air.
|
||||||
|
Merge(tile.Air, mix);
|
||||||
|
|
||||||
|
// Return removed gas to its original mixture.
|
||||||
|
Merge(adj, mix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// New temperature is the arithmetic mean of the sum of the adjacent temperatures...
|
||||||
|
tile.Air.Temperature = totalTemperature / adjacent.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridAddPipeNet(EntityUid uid, GridAtmosphereComponent component, ref AddPipeNetMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Handled = component.PipeNets.Add(args.PipeNet);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridRemovePipeNet(EntityUid uid, GridAtmosphereComponent component, ref RemovePipeNetMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Handled = component.PipeNets.Remove(args.PipeNet);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridAddAtmosDevice(EntityUid uid, GridAtmosphereComponent component,
|
||||||
|
ref AddAtmosDeviceMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!component.AtmosDevices.Add(args.Device))
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Device.JoinedGrid = uid;
|
||||||
|
args.Handled = true;
|
||||||
|
args.Result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GridRemoveAtmosDevice(EntityUid uid, GridAtmosphereComponent component,
|
||||||
|
ref RemoveAtmosDeviceMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!component.AtmosDevices.Remove(args.Device))
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Device.JoinedGrid = null;
|
||||||
|
args.Handled = true;
|
||||||
|
args.Result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Repopulates all tiles on a grid atmosphere.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mapGrid">The grid where to get all valid tiles from.</param>
|
||||||
|
/// <param name="gridAtmosphere">The grid atmosphere where the tiles will be repopulated.</param>
|
||||||
|
private void GridRepopulateTiles(IMapGrid mapGrid, GridAtmosphereComponent gridAtmosphere)
|
||||||
|
{
|
||||||
|
var volume = GetVolumeForTiles(mapGrid, 1);
|
||||||
|
|
||||||
|
foreach (var tile in mapGrid.GetAllTiles())
|
||||||
|
{
|
||||||
|
if (!gridAtmosphere.Tiles.ContainsKey(tile.GridIndices))
|
||||||
|
gridAtmosphere.Tiles[tile.GridIndices] = new TileAtmosphere(tile.GridUid, tile.GridIndices,
|
||||||
|
new GasMixture(volume) {Temperature = Atmospherics.T20C});
|
||||||
|
|
||||||
|
gridAtmosphere.InvalidatedCoords.Add(tile.GridIndices);
|
||||||
|
}
|
||||||
|
|
||||||
|
var uid = gridAtmosphere.Owner;
|
||||||
|
|
||||||
|
// Gotta do this afterwards so we can properly update adjacent tiles.
|
||||||
|
foreach (var (position, _) in gridAtmosphere.Tiles.ToArray())
|
||||||
|
{
|
||||||
|
var ev = new UpdateAdjacentMethodEvent(uid, position);
|
||||||
|
GridUpdateAdjacent(uid, gridAtmosphere, ref ev);
|
||||||
|
InvalidateVisuals(mapGrid.GridEntityId, position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -48,7 +48,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
}
|
}
|
||||||
|
|
||||||
shouldShareAir = true;
|
shouldShareAir = true;
|
||||||
} else if (tile.Air!.Compare(enemyTile.Air!) != GasMixture.GasCompareResult.NoExchange)
|
} else if (CompareExchange(tile.Air, enemyTile.Air) != GasCompareResult.NoExchange)
|
||||||
{
|
{
|
||||||
if (!enemyTile.Excited)
|
if (!enemyTile.Excited)
|
||||||
{
|
{
|
||||||
@@ -78,7 +78,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
|
|
||||||
if (shouldShareAir)
|
if (shouldShareAir)
|
||||||
{
|
{
|
||||||
var difference = Share(tile.Air!, enemyTile.Air!, adjacentTileLength);
|
var difference = Share(tile, enemyTile, adjacentTileLength);
|
||||||
|
|
||||||
// Monstermos already handles this, so let's not handle it ourselves.
|
// Monstermos already handles this, so let's not handle it ourselves.
|
||||||
if (!MonstermosEqualization)
|
if (!MonstermosEqualization)
|
||||||
@@ -114,17 +114,25 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
|
|
||||||
private void Archive(TileAtmosphere tile, int fireCount)
|
private void Archive(TileAtmosphere tile, int fireCount)
|
||||||
{
|
{
|
||||||
tile.Air?.Archive();
|
if (tile.Air != null)
|
||||||
tile.ArchivedCycle = fireCount;
|
{
|
||||||
|
tile.Air.Moles.AsSpan().CopyTo(tile.MolesArchived.AsSpan());
|
||||||
|
tile.TemperatureArchived = tile.Air.Temperature;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
tile.TemperatureArchived = tile.Temperature;
|
tile.TemperatureArchived = tile.Temperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tile.ArchivedCycle = fireCount;
|
||||||
|
}
|
||||||
|
|
||||||
private void LastShareCheck(TileAtmosphere tile)
|
private void LastShareCheck(TileAtmosphere tile)
|
||||||
{
|
{
|
||||||
if (tile.Air == null || tile.ExcitedGroup == null)
|
if (tile.Air == null || tile.ExcitedGroup == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (tile.Air.LastShare)
|
switch (tile.LastShare)
|
||||||
{
|
{
|
||||||
case > Atmospherics.MinimumAirToSuspend:
|
case > Atmospherics.MinimumAirToSuspend:
|
||||||
ExcitedGroupResetCooldowns(tile.ExcitedGroup);
|
ExcitedGroupResetCooldowns(tile.ExcitedGroup);
|
||||||
@@ -134,5 +142,193 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Makes a tile become active and start processing. Does NOT check if the tile belongs to the grid atmos.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="gridAtmosphere">Grid Atmosphere where to get the tile.</param>
|
||||||
|
/// <param name="tile">Tile Atmosphere to be activated.</param>
|
||||||
|
private void AddActiveTile(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile)
|
||||||
|
{
|
||||||
|
if (tile.Air == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tile.Excited = true;
|
||||||
|
gridAtmosphere.ActiveTiles.Add(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Makes a tile become inactive and stop processing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="gridAtmosphere">Grid Atmosphere where to get the tile.</param>
|
||||||
|
/// <param name="tile">Tile Atmosphere to be deactivated.</param>
|
||||||
|
/// <param name="disposeExcitedGroup">Whether to dispose of the tile's <see cref="ExcitedGroup"/></param>
|
||||||
|
private void RemoveActiveTile(GridAtmosphereComponent gridAtmosphere, TileAtmosphere tile, bool disposeExcitedGroup = true)
|
||||||
|
{
|
||||||
|
tile.Excited = false;
|
||||||
|
gridAtmosphere.ActiveTiles.Remove(tile);
|
||||||
|
|
||||||
|
if (tile.ExcitedGroup == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (disposeExcitedGroup)
|
||||||
|
ExcitedGroupDispose(gridAtmosphere, tile.ExcitedGroup);
|
||||||
|
else
|
||||||
|
ExcitedGroupRemoveTile(tile.ExcitedGroup, tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates the heat capacity for a gas mixture, using the archived values.
|
||||||
|
/// </summary>
|
||||||
|
public float GetHeatCapacityArchived(TileAtmosphere tile)
|
||||||
|
{
|
||||||
|
if (tile.Air == null)
|
||||||
|
return tile.HeatCapacity;
|
||||||
|
|
||||||
|
// Moles archived is not null if air is not null.
|
||||||
|
return GetHeatCapacityCalculation(tile.MolesArchived!, tile.Space);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shares gas between two tiles. Part of LINDA.
|
||||||
|
/// </summary>
|
||||||
|
public float Share(TileAtmosphere tileReceiver, TileAtmosphere tileSharer, int atmosAdjacentTurfs)
|
||||||
|
{
|
||||||
|
if (tileReceiver.Air is not {} receiver || tileSharer.Air is not {} sharer)
|
||||||
|
return 0f;
|
||||||
|
|
||||||
|
var temperatureDelta = tileReceiver.TemperatureArchived - tileSharer.TemperatureArchived;
|
||||||
|
var absTemperatureDelta = Math.Abs(temperatureDelta);
|
||||||
|
var oldHeatCapacity = 0f;
|
||||||
|
var oldSharerHeatCapacity = 0f;
|
||||||
|
|
||||||
|
if (absTemperatureDelta > Atmospherics.MinimumTemperatureDeltaToConsider)
|
||||||
|
{
|
||||||
|
oldHeatCapacity = GetHeatCapacity(receiver);
|
||||||
|
oldSharerHeatCapacity = GetHeatCapacity(sharer);
|
||||||
|
}
|
||||||
|
|
||||||
|
var heatCapacityToSharer = 0f;
|
||||||
|
var heatCapacitySharerToThis = 0f;
|
||||||
|
var movedMoles = 0f;
|
||||||
|
var absMovedMoles = 0f;
|
||||||
|
|
||||||
|
for(var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||||
|
{
|
||||||
|
var thisValue = receiver.Moles[i];
|
||||||
|
var sharerValue = sharer.Moles[i];
|
||||||
|
var delta = (thisValue - sharerValue) / (atmosAdjacentTurfs + 1);
|
||||||
|
if (!(MathF.Abs(delta) >= Atmospherics.GasMinMoles)) continue;
|
||||||
|
if (absTemperatureDelta > Atmospherics.MinimumTemperatureDeltaToConsider)
|
||||||
|
{
|
||||||
|
var gasHeatCapacity = delta * GasSpecificHeats[i];
|
||||||
|
if (delta > 0)
|
||||||
|
{
|
||||||
|
heatCapacityToSharer += gasHeatCapacity;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
heatCapacitySharerToThis -= gasHeatCapacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!receiver.Immutable) receiver.Moles[i] -= delta;
|
||||||
|
if (!sharer.Immutable) sharer.Moles[i] += delta;
|
||||||
|
movedMoles += delta;
|
||||||
|
absMovedMoles += MathF.Abs(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
tileReceiver.LastShare = absMovedMoles;
|
||||||
|
|
||||||
|
if (absTemperatureDelta > Atmospherics.MinimumTemperatureDeltaToConsider)
|
||||||
|
{
|
||||||
|
var newHeatCapacity = oldHeatCapacity + heatCapacitySharerToThis - heatCapacityToSharer;
|
||||||
|
var newSharerHeatCapacity = oldSharerHeatCapacity + heatCapacityToSharer - heatCapacitySharerToThis;
|
||||||
|
|
||||||
|
// Transfer of thermal energy (via changed heat capacity) between self and sharer.
|
||||||
|
if (!receiver.Immutable && newHeatCapacity > Atmospherics.MinimumHeatCapacity)
|
||||||
|
{
|
||||||
|
receiver.Temperature = ((oldHeatCapacity * receiver.Temperature) - (heatCapacityToSharer * tileReceiver.TemperatureArchived) + (heatCapacitySharerToThis * tileSharer.TemperatureArchived)) / newHeatCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sharer.Immutable && newSharerHeatCapacity > Atmospherics.MinimumHeatCapacity)
|
||||||
|
{
|
||||||
|
sharer.Temperature = ((oldSharerHeatCapacity * sharer.Temperature) - (heatCapacitySharerToThis * tileSharer.TemperatureArchived) + (heatCapacityToSharer * tileReceiver.TemperatureArchived)) / newSharerHeatCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thermal energy of the system (self and sharer) is unchanged.
|
||||||
|
|
||||||
|
if (MathF.Abs(oldSharerHeatCapacity) > Atmospherics.MinimumHeatCapacity)
|
||||||
|
{
|
||||||
|
if (MathF.Abs(newSharerHeatCapacity / oldSharerHeatCapacity - 1) < 0.1)
|
||||||
|
{
|
||||||
|
TemperatureShare(tileReceiver, tileSharer, Atmospherics.OpenHeatTransferCoefficient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(temperatureDelta > Atmospherics.MinimumTemperatureToMove) &&
|
||||||
|
!(MathF.Abs(movedMoles) > Atmospherics.MinimumMolesDeltaToMove)) return 0f;
|
||||||
|
var moles = receiver.TotalMoles;
|
||||||
|
var theirMoles = sharer.TotalMoles;
|
||||||
|
|
||||||
|
return (tileReceiver.TemperatureArchived * (moles + movedMoles)) - (tileSharer.TemperatureArchived * (theirMoles - movedMoles)) * Atmospherics.R / receiver.Volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shares temperature between two mixtures, taking a conduction coefficient into account.
|
||||||
|
/// </summary>
|
||||||
|
public float TemperatureShare(TileAtmosphere tileReceiver, TileAtmosphere tileSharer, float conductionCoefficient)
|
||||||
|
{
|
||||||
|
if (tileReceiver.Air is not { } receiver || tileSharer.Air is not { } sharer)
|
||||||
|
return 0f;
|
||||||
|
|
||||||
|
var temperatureDelta = tileReceiver.TemperatureArchived - tileSharer.TemperatureArchived;
|
||||||
|
if (MathF.Abs(temperatureDelta) > Atmospherics.MinimumTemperatureDeltaToConsider)
|
||||||
|
{
|
||||||
|
var heatCapacity = GetHeatCapacityArchived(tileReceiver);
|
||||||
|
var sharerHeatCapacity = GetHeatCapacityArchived(tileSharer);
|
||||||
|
|
||||||
|
if (sharerHeatCapacity > Atmospherics.MinimumHeatCapacity && heatCapacity > Atmospherics.MinimumHeatCapacity)
|
||||||
|
{
|
||||||
|
var heat = conductionCoefficient * temperatureDelta * (heatCapacity * sharerHeatCapacity / (heatCapacity + sharerHeatCapacity));
|
||||||
|
|
||||||
|
if (!receiver.Immutable)
|
||||||
|
receiver.Temperature = MathF.Abs(MathF.Max(receiver.Temperature - heat / heatCapacity, Atmospherics.TCMB));
|
||||||
|
|
||||||
|
if (!sharer.Immutable)
|
||||||
|
sharer.Temperature = MathF.Abs(MathF.Max(sharer.Temperature + heat / sharerHeatCapacity, Atmospherics.TCMB));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sharer.Temperature;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shares temperature between a gas mixture and an abstract sharer, taking a conduction coefficient into account.
|
||||||
|
/// </summary>
|
||||||
|
public float TemperatureShare(TileAtmosphere tileReceiver, float conductionCoefficient, float sharerTemperature, float sharerHeatCapacity)
|
||||||
|
{
|
||||||
|
if (tileReceiver.Air is not {} receiver)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
var temperatureDelta = tileReceiver.TemperatureArchived - sharerTemperature;
|
||||||
|
if (MathF.Abs(temperatureDelta) > Atmospherics.MinimumTemperatureDeltaToConsider)
|
||||||
|
{
|
||||||
|
var heatCapacity = GetHeatCapacityArchived(tileReceiver);
|
||||||
|
|
||||||
|
if (sharerHeatCapacity > Atmospherics.MinimumHeatCapacity && heatCapacity > Atmospherics.MinimumHeatCapacity)
|
||||||
|
{
|
||||||
|
var heat = conductionCoefficient * temperatureDelta * (heatCapacity * sharerHeatCapacity / (heatCapacity + sharerHeatCapacity));
|
||||||
|
|
||||||
|
if (!receiver.Immutable)
|
||||||
|
receiver.Temperature = MathF.Abs(MathF.Max(receiver.Temperature - heat / heatCapacity, Atmospherics.TCMB));
|
||||||
|
|
||||||
|
sharerTemperature = MathF.Abs(MathF.Max(sharerTemperature + heat / sharerHeatCapacity, Atmospherics.TCMB));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sharerTemperature;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
Content.Server/Atmos/EntitySystems/AtmosphereSystem.Map.cs
Normal file
31
Content.Server/Atmos/EntitySystems/AtmosphereSystem.Map.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using Content.Server.Atmos.Components;
|
||||||
|
|
||||||
|
namespace Content.Server.Atmos.EntitySystems;
|
||||||
|
|
||||||
|
public partial class AtmosphereSystem
|
||||||
|
{
|
||||||
|
private void InitializeMap()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<MapAtmosphereComponent, IsTileSpaceMethodEvent>(MapIsTileSpace);
|
||||||
|
SubscribeLocalEvent<MapAtmosphereComponent, GetTileMixtureMethodEvent>(MapGetTileMixture);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MapIsTileSpace(EntityUid uid, MapAtmosphereComponent component, ref IsTileSpaceMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Result = component.Space;
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MapGetTileMixture(EntityUid uid, MapAtmosphereComponent component, ref GetTileMixtureMethodEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Clone the mixture, if possible.
|
||||||
|
args.Mixture = component.Mixture?.Clone();
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,8 +10,6 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
{
|
{
|
||||||
public sealed partial class AtmosphereSystem
|
public sealed partial class AtmosphereSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
|
||||||
|
|
||||||
private readonly TileAtmosphereComparer _monstermosComparer = new();
|
private readonly TileAtmosphereComparer _monstermosComparer = new();
|
||||||
|
|
||||||
private readonly TileAtmosphere?[] _equalizeTiles = new TileAtmosphere[Atmospherics.MonstermosHardTileLimit];
|
private readonly TileAtmosphere?[] _equalizeTiles = new TileAtmosphere[Atmospherics.MonstermosHardTileLimit];
|
||||||
@@ -81,7 +79,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
if(tileCount < Atmospherics.MonstermosHardTileLimit)
|
if(tileCount < Atmospherics.MonstermosHardTileLimit)
|
||||||
_equalizeTiles[tileCount++] = adj;
|
_equalizeTiles[tileCount++] = adj;
|
||||||
|
|
||||||
if (adj.Air.Immutable && MonstermosDepressurization)
|
if (adj.Space && MonstermosDepressurization)
|
||||||
{
|
{
|
||||||
// Looks like someone opened an airlock to space!
|
// Looks like someone opened an airlock to space!
|
||||||
|
|
||||||
@@ -146,6 +144,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
var direction = (AtmosDirection) (1 << j);
|
var direction = (AtmosDirection) (1 << j);
|
||||||
if (!otherTile.AdjacentBits.IsFlagSet(direction)) continue;
|
if (!otherTile.AdjacentBits.IsFlagSet(direction)) continue;
|
||||||
var tile2 = otherTile.AdjacentTiles[j]!;
|
var tile2 = otherTile.AdjacentTiles[j]!;
|
||||||
|
DebugTools.Assert(tile2.AdjacentBits.IsFlagSet(direction.GetOpposite()));
|
||||||
|
|
||||||
// skip anything that isn't part of our current processing block.
|
// skip anything that isn't part of our current processing block.
|
||||||
if (tile2.MonstermosInfo.FastDone || tile2.MonstermosInfo.LastQueueCycle != queueCycle)
|
if (tile2.MonstermosInfo.FastDone || tile2.MonstermosInfo.LastQueueCycle != queueCycle)
|
||||||
@@ -213,8 +212,8 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
var otherTile2 = otherTile.AdjacentTiles[k];
|
var otherTile2 = otherTile.AdjacentTiles[k];
|
||||||
if (giver.MonstermosInfo.MoleDelta <= 0) break; // We're done here now. Let's not do more work than needed.
|
if (giver.MonstermosInfo.MoleDelta <= 0) break; // We're done here now. Let's not do more work than needed.
|
||||||
if (otherTile2 == null || otherTile2.MonstermosInfo.LastQueueCycle != queueCycle) continue;
|
if (otherTile2 == null || otherTile2.MonstermosInfo.LastQueueCycle != queueCycle) continue;
|
||||||
|
DebugTools.Assert(otherTile2.AdjacentBits.IsFlagSet(direction.GetOpposite()));
|
||||||
if (otherTile2.MonstermosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
|
if (otherTile2.MonstermosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
|
||||||
|
|
||||||
_equalizeQueue[queueLength++] = otherTile2;
|
_equalizeQueue[queueLength++] = otherTile2;
|
||||||
otherTile2.MonstermosInfo.LastSlowQueueCycle = queueCycleSlow;
|
otherTile2.MonstermosInfo.LastSlowQueueCycle = queueCycleSlow;
|
||||||
otherTile2.MonstermosInfo.CurrentTransferDirection = direction.GetOpposite();
|
otherTile2.MonstermosInfo.CurrentTransferDirection = direction.GetOpposite();
|
||||||
@@ -279,6 +278,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
|
|
||||||
if (taker.MonstermosInfo.MoleDelta >= 0) break; // We're done here now. Let's not do more work than needed.
|
if (taker.MonstermosInfo.MoleDelta >= 0) break; // We're done here now. Let's not do more work than needed.
|
||||||
if (otherTile2 == null || otherTile2.MonstermosInfo.LastQueueCycle != queueCycle) continue;
|
if (otherTile2 == null || otherTile2.MonstermosInfo.LastQueueCycle != queueCycle) continue;
|
||||||
|
DebugTools.Assert(otherTile2.AdjacentBits.IsFlagSet(direction.GetOpposite()));
|
||||||
if (otherTile2.MonstermosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
|
if (otherTile2.MonstermosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
|
||||||
_equalizeQueue[queueLength++] = otherTile2;
|
_equalizeQueue[queueLength++] = otherTile2;
|
||||||
otherTile2.MonstermosInfo.LastSlowQueueCycle = queueCycleSlow;
|
otherTile2.MonstermosInfo.LastSlowQueueCycle = queueCycleSlow;
|
||||||
@@ -335,7 +335,8 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
var direction = (AtmosDirection) (1 << j);
|
var direction = (AtmosDirection) (1 << j);
|
||||||
if (!otherTile.AdjacentBits.IsFlagSet(direction)) continue;
|
if (!otherTile.AdjacentBits.IsFlagSet(direction)) continue;
|
||||||
var otherTile2 = otherTile.AdjacentTiles[j]!;
|
var otherTile2 = otherTile.AdjacentTiles[j]!;
|
||||||
if (otherTile2.Air?.Compare(tile.Air) == GasMixture.GasCompareResult.NoExchange) continue;
|
DebugTools.Assert(otherTile2.AdjacentBits.IsFlagSet(direction.GetOpposite()));
|
||||||
|
if (otherTile2.Air != null && CompareExchange(otherTile2.Air, tile.Air) == GasCompareResult.NoExchange) continue;
|
||||||
AddActiveTile(gridAtmosphere, otherTile2);
|
AddActiveTile(gridAtmosphere, otherTile2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -372,7 +373,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
otherTile.MonstermosInfo.LastCycle = cycleNum;
|
otherTile.MonstermosInfo.LastCycle = cycleNum;
|
||||||
otherTile.MonstermosInfo.CurrentTransferDirection = AtmosDirection.Invalid;
|
otherTile.MonstermosInfo.CurrentTransferDirection = AtmosDirection.Invalid;
|
||||||
// Tiles in the _depressurizeTiles array cannot have null air.
|
// Tiles in the _depressurizeTiles array cannot have null air.
|
||||||
if (!otherTile.Air!.Immutable)
|
if (!otherTile.Space)
|
||||||
{
|
{
|
||||||
for (var j = 0; j < Atmospherics.Directions; j++)
|
for (var j = 0; j < Atmospherics.Directions; j++)
|
||||||
{
|
{
|
||||||
@@ -380,6 +381,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
if (!otherTile.AdjacentBits.IsFlagSet(direction)) continue;
|
if (!otherTile.AdjacentBits.IsFlagSet(direction)) continue;
|
||||||
var otherTile2 = otherTile.AdjacentTiles[j];
|
var otherTile2 = otherTile.AdjacentTiles[j];
|
||||||
if (otherTile2?.Air == null) continue;
|
if (otherTile2?.Air == null) continue;
|
||||||
|
DebugTools.Assert(otherTile2.AdjacentBits.IsFlagSet(direction.GetOpposite()));
|
||||||
if (otherTile2.MonstermosInfo.LastQueueCycle == queueCycle) continue;
|
if (otherTile2.MonstermosInfo.LastQueueCycle == queueCycle) continue;
|
||||||
|
|
||||||
ConsiderFirelocks(gridAtmosphere, otherTile, otherTile2);
|
ConsiderFirelocks(gridAtmosphere, otherTile, otherTile2);
|
||||||
@@ -421,11 +423,12 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
{
|
{
|
||||||
var direction = (AtmosDirection) (1 << j);
|
var direction = (AtmosDirection) (1 << j);
|
||||||
// Tiles in _depressurizeProgressionOrder cannot have null air.
|
// Tiles in _depressurizeProgressionOrder cannot have null air.
|
||||||
if (!otherTile.AdjacentBits.IsFlagSet(direction) && !otherTile.Air!.Immutable) continue;
|
if (!otherTile.AdjacentBits.IsFlagSet(direction) && !otherTile.Space) continue;
|
||||||
var tile2 = otherTile.AdjacentTiles[j];
|
var tile2 = otherTile.AdjacentTiles[j];
|
||||||
if (tile2?.MonstermosInfo.LastQueueCycle != queueCycle) continue;
|
if (tile2?.MonstermosInfo.LastQueueCycle != queueCycle) continue;
|
||||||
|
DebugTools.Assert(tile2.AdjacentBits.IsFlagSet(direction.GetOpposite()));
|
||||||
if (tile2.MonstermosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
|
if (tile2.MonstermosInfo.LastSlowQueueCycle == queueCycleSlow) continue;
|
||||||
if(tile2.Air?.Immutable ?? false) continue;
|
if(tile2.Space) continue;
|
||||||
tile2.MonstermosInfo.CurrentTransferDirection = direction.GetOpposite();
|
tile2.MonstermosInfo.CurrentTransferDirection = direction.GetOpposite();
|
||||||
tile2.MonstermosInfo.CurrentTransferAmount = 0;
|
tile2.MonstermosInfo.CurrentTransferAmount = 0;
|
||||||
tile2.PressureSpecificTarget = otherTile.PressureSpecificTarget;
|
tile2.PressureSpecificTarget = otherTile.PressureSpecificTarget;
|
||||||
@@ -479,7 +482,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(tileCount > 10 && (totalMolesRemoved / tileCount) > 20)
|
if(tileCount > 10 && (totalMolesRemoved / tileCount) > 20)
|
||||||
_adminLogger.Add(LogType.ExplosiveDepressurization, LogImpact.High,
|
_adminLog.Add(LogType.ExplosiveDepressurization, LogImpact.High,
|
||||||
$"Explosive depressurization removed {totalMolesRemoved} moles from {tileCount} tiles starting from position {tile.GridIndices:position} on grid ID {tile.GridIndex:grid}");
|
$"Explosive depressurization removed {totalMolesRemoved} moles from {tileCount} tiles starting from position {tile.GridIndices:position} on grid ID {tile.GridIndex:grid}");
|
||||||
|
|
||||||
Array.Clear(_depressurizeTiles, 0, Atmospherics.MonstermosHardTileLimit);
|
Array.Clear(_depressurizeTiles, 0, Atmospherics.MonstermosHardTileLimit);
|
||||||
@@ -513,8 +516,10 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
if (!reconsiderAdjacent)
|
if (!reconsiderAdjacent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateAdjacent(mapGrid, gridAtmosphere, tile);
|
var tileEv = new UpdateAdjacentMethodEvent(mapGrid.GridEntityId, tile.GridIndices);
|
||||||
UpdateAdjacent(mapGrid, gridAtmosphere, other);
|
var otherEv = new UpdateAdjacentMethodEvent(mapGrid.GridEntityId, other.GridIndices);
|
||||||
|
GridUpdateAdjacent(mapGrid.GridEntityId, gridAtmosphere, ref tileEv);
|
||||||
|
GridUpdateAdjacent(mapGrid.GridEntityId, gridAtmosphere, ref otherEv);
|
||||||
InvalidateVisuals(tile.GridIndex, tile.GridIndices);
|
InvalidateVisuals(tile.GridIndex, tile.GridIndices);
|
||||||
InvalidateVisuals(other.GridIndex, other.GridIndices);
|
InvalidateVisuals(other.GridIndex, other.GridIndices);
|
||||||
}
|
}
|
||||||
@@ -541,6 +546,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
var amount = transferDirections[i];
|
var amount = transferDirections[i];
|
||||||
var otherTile = tile.AdjacentTiles[i];
|
var otherTile = tile.AdjacentTiles[i];
|
||||||
if (otherTile?.Air == null) continue;
|
if (otherTile?.Air == null) continue;
|
||||||
|
DebugTools.Assert(otherTile.AdjacentBits.IsFlagSet(direction.GetOpposite()));
|
||||||
if (amount <= 0) continue;
|
if (amount <= 0) continue;
|
||||||
|
|
||||||
// Everything that calls this method already ensures that Air will not be null.
|
// Everything that calls this method already ensures that Air will not be null.
|
||||||
@@ -569,6 +575,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
|
|
||||||
private void AdjustEqMovement(TileAtmosphere tile, AtmosDirection direction, float amount)
|
private void AdjustEqMovement(TileAtmosphere tile, AtmosDirection direction, float amount)
|
||||||
{
|
{
|
||||||
|
DebugTools.AssertNotNull(tile);
|
||||||
DebugTools.Assert(tile.AdjacentBits.IsFlagSet(direction));
|
DebugTools.Assert(tile.AdjacentBits.IsFlagSet(direction));
|
||||||
DebugTools.Assert(tile.AdjacentTiles[direction.ToIndex()] != null);
|
DebugTools.Assert(tile.AdjacentTiles[direction.ToIndex()] != null);
|
||||||
tile.MonstermosInfo[direction] += amount;
|
tile.MonstermosInfo[direction] += amount;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Content.Server.Atmos.Piping.Components;
|
|||||||
using Content.Server.NodeContainer.NodeGroups;
|
using Content.Server.NodeContainer.NodeGroups;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Server.Atmos.EntitySystems
|
namespace Content.Server.Atmos.EntitySystems
|
||||||
@@ -42,37 +43,45 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
atmosphere.InvalidatedCoords.Clear();
|
atmosphere.InvalidatedCoords.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TryGetMapGrid(atmosphere, out var mapGrid))
|
var uid = atmosphere.Owner;
|
||||||
|
|
||||||
|
if (!TryComp(uid, out IMapGridComponent? mapGridComp))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
var mapGrid = mapGridComp.Grid;
|
||||||
|
var mapUid = _mapManager.GetMapEntityIdOrThrow(mapGridComp.Grid.ParentMapId);
|
||||||
|
|
||||||
var volume = GetVolumeForTiles(mapGrid, 1);
|
var volume = GetVolumeForTiles(mapGrid, 1);
|
||||||
|
|
||||||
var number = 0;
|
var number = 0;
|
||||||
while (atmosphere.CurrentRunInvalidatedCoordinates.TryDequeue(out var indices))
|
while (atmosphere.CurrentRunInvalidatedCoordinates.TryDequeue(out var indices))
|
||||||
{
|
{
|
||||||
var tile = GetTileAtmosphere(atmosphere, indices);
|
if (!atmosphere.Tiles.TryGetValue(indices, out var tile))
|
||||||
|
|
||||||
if (tile == null)
|
|
||||||
{
|
{
|
||||||
tile = new TileAtmosphere(mapGrid.GridEntityId, indices, new GasMixture(volume){Temperature = Atmospherics.T20C});
|
tile = new TileAtmosphere(mapGrid.GridEntityId, indices, new GasMixture(volume){Temperature = Atmospherics.T20C});
|
||||||
atmosphere.Tiles[indices] = tile;
|
atmosphere.Tiles[indices] = tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
var isAirBlocked = IsTileAirBlocked(mapGrid, indices);
|
var airBlockedEv = new IsTileAirBlockedMethodEvent(uid, indices, MapGridComponent:mapGridComp);
|
||||||
|
GridIsTileAirBlocked(uid, atmosphere, ref airBlockedEv);
|
||||||
|
var isAirBlocked = airBlockedEv.Result;
|
||||||
|
|
||||||
UpdateAdjacent(mapGrid, atmosphere, tile);
|
var updateAdjacentEv = new UpdateAdjacentMethodEvent(uid, indices, mapGridComp);
|
||||||
|
GridUpdateAdjacent(uid, atmosphere, ref updateAdjacentEv);
|
||||||
|
|
||||||
if (IsTileSpace(mapGrid, indices) && !isAirBlocked)
|
// Call this instead of the grid method as the map has a say on whether the tile is space or not.
|
||||||
|
if ((!mapGrid.TryGetTileRef(indices, out var t) || t.IsSpace(_tileDefinitionManager)) && !isAirBlocked)
|
||||||
{
|
{
|
||||||
tile.Air = new GasMixture(volume);
|
tile.Air = GetTileMixture(null, mapUid, indices);
|
||||||
tile.Air.MarkImmutable();
|
tile.MolesArchived = tile.Air != null ? new float[Atmospherics.AdjustedNumberOfGases] : null;
|
||||||
atmosphere.Tiles[indices] = tile;
|
tile.Space = IsTileSpace(null, mapUid, indices, mapGridComp);
|
||||||
|
|
||||||
} else if (isAirBlocked)
|
} else if (isAirBlocked)
|
||||||
{
|
{
|
||||||
var nullAir = false;
|
var nullAir = false;
|
||||||
|
|
||||||
foreach (var airtight in GetObstructingComponents(mapGrid, indices))
|
var enumerator = GetObstructingComponentsEnumerator(mapGrid, indices);
|
||||||
|
|
||||||
|
while (enumerator.MoveNext(out var airtight))
|
||||||
{
|
{
|
||||||
if (!airtight.NoAirWhenFullyAirBlocked)
|
if (!airtight.NoAirWhenFullyAirBlocked)
|
||||||
continue;
|
continue;
|
||||||
@@ -84,6 +93,9 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
if (nullAir)
|
if (nullAir)
|
||||||
{
|
{
|
||||||
tile.Air = null;
|
tile.Air = null;
|
||||||
|
tile.MolesArchived = null;
|
||||||
|
tile.ArchivedCycle = 0;
|
||||||
|
tile.LastShare = 0f;
|
||||||
tile.Hotspot = new Hotspot();
|
tile.Hotspot = new Hotspot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,23 +103,31 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
{
|
{
|
||||||
if (tile.Air == null && NeedsVacuumFixing(mapGrid, indices))
|
if (tile.Air == null && NeedsVacuumFixing(mapGrid, indices))
|
||||||
{
|
{
|
||||||
FixVacuum(atmosphere, tile.GridIndices);
|
var vacuumEv = new FixTileVacuumMethodEvent(uid, indices);
|
||||||
|
GridFixTileVacuum(uid, atmosphere, ref vacuumEv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tile used to be space, but isn't anymore.
|
// Tile used to be space, but isn't anymore.
|
||||||
if (tile.Air?.Immutable ?? false)
|
if (tile.Space || (tile.Air?.Immutable ?? false))
|
||||||
{
|
{
|
||||||
tile.Air = null;
|
tile.Air = null;
|
||||||
|
tile.MolesArchived = null;
|
||||||
|
tile.ArchivedCycle = 0;
|
||||||
|
tile.LastShare = 0f;
|
||||||
|
tile.Space = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tile.Air ??= new GasMixture(volume){Temperature = Atmospherics.T20C};
|
tile.Air ??= new GasMixture(volume){Temperature = Atmospherics.T20C};
|
||||||
|
tile.MolesArchived ??= new float[Atmospherics.AdjustedNumberOfGases];
|
||||||
}
|
}
|
||||||
|
|
||||||
// We activate the tile.
|
// We activate the tile.
|
||||||
AddActiveTile(atmosphere, tile);
|
AddActiveTile(atmosphere, tile);
|
||||||
|
|
||||||
// TODO ATMOS: Query all the contents of this tile (like walls) and calculate the correct thermal conductivity and heat capacity
|
// TODO ATMOS: Query all the contents of this tile (like walls) and calculate the correct thermal conductivity and heat capacity
|
||||||
var tileDef = GetTile(tile)?.Tile.GetContentTileDefinition(_tileDefinitionManager);
|
var tileDef = mapGrid.TryGetTileRef(indices, out var tileRef)
|
||||||
|
? tileRef.GetContentTileDefinition(_tileDefinitionManager) : null;
|
||||||
|
|
||||||
tile.ThermalConductivity = tileDef?.ThermalConductivity ?? 0.5f;
|
tile.ThermalConductivity = tileDef?.ThermalConductivity ?? 0.5f;
|
||||||
tile.HeatCapacity = tileDef?.HeatCapacity ?? float.PositiveInfinity;
|
tile.HeatCapacity = tileDef?.HeatCapacity ?? float.PositiveInfinity;
|
||||||
InvalidateVisuals(mapGrid.GridEntityId, indices);
|
InvalidateVisuals(mapGrid.GridEntityId, indices);
|
||||||
@@ -116,8 +136,8 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
{
|
{
|
||||||
var direction = (AtmosDirection) (1 << i);
|
var direction = (AtmosDirection) (1 << i);
|
||||||
var otherIndices = indices.Offset(direction);
|
var otherIndices = indices.Offset(direction);
|
||||||
var otherTile = GetTileAtmosphere(atmosphere, otherIndices);
|
|
||||||
if (otherTile != null)
|
if (atmosphere.Tiles.TryGetValue(otherIndices, out var otherTile))
|
||||||
AddActiveTile(atmosphere, otherTile);
|
AddActiveTile(atmosphere, otherTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,9 +158,13 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
if(!atmosphere.ProcessingPaused)
|
if(!atmosphere.ProcessingPaused)
|
||||||
atmosphere.CurrentRunTiles = new Queue<TileAtmosphere>(atmosphere.ActiveTiles);
|
atmosphere.CurrentRunTiles = new Queue<TileAtmosphere>(atmosphere.ActiveTiles);
|
||||||
|
|
||||||
if (!TryGetMapGrid(atmosphere, out var mapGrid))
|
var uid = atmosphere.Owner;
|
||||||
|
|
||||||
|
if (!TryComp(uid, out IMapGridComponent? mapGridComp))
|
||||||
throw new Exception("Tried to process a grid atmosphere on an entity that isn't a grid!");
|
throw new Exception("Tried to process a grid atmosphere on an entity that isn't a grid!");
|
||||||
|
|
||||||
|
var mapGrid = mapGridComp.Grid;
|
||||||
|
|
||||||
var number = 0;
|
var number = 0;
|
||||||
while (atmosphere.CurrentRunTiles.TryDequeue(out var tile))
|
while (atmosphere.CurrentRunTiles.TryDequeue(out var tile))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
// Conduct with air on my tile if I have it
|
// Conduct with air on my tile if I have it
|
||||||
if (tile.Air != null)
|
if (tile.Air != null)
|
||||||
{
|
{
|
||||||
tile.Temperature = TemperatureShare(tile.Air, tile.ThermalConductivity, tile.Temperature, tile.HeatCapacity);
|
tile.Temperature = TemperatureShare(tile, tile.ThermalConductivity, tile.Temperature, tile.HeatCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
FinishSuperconduction(gridAtmosphere, tile, tile.Air?.Temperature ?? tile.Temperature);
|
FinishSuperconduction(gridAtmosphere, tile, tile.Air?.Temperature ?? tile.Temperature);
|
||||||
@@ -107,7 +107,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
|
|
||||||
if (other.Air != null)
|
if (other.Air != null)
|
||||||
{
|
{
|
||||||
TemperatureShare(other.Air, tile.Air, Atmospherics.WindowHeatTransferCoefficient);
|
TemperatureShare(other, tile, Atmospherics.WindowHeatTransferCoefficient);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -122,7 +122,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
if (tile.Air == null)
|
if (tile.Air == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
other.Temperature = TemperatureShare(tile.Air, other.ThermalConductivity, other.Temperature, other.HeatCapacity);
|
other.Temperature = TemperatureShare(tile, other.ThermalConductivity, other.Temperature, other.HeatCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TemperatureShareMutualSolid(TileAtmosphere tile, TileAtmosphere other, float conductionCoefficient)
|
private void TemperatureShareMutualSolid(TileAtmosphere tile, TileAtmosphere other, float conductionCoefficient)
|
||||||
|
|||||||
84
Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs
Normal file
84
Content.Server/Atmos/EntitySystems/AtmosphereSystem.Utils.cs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using Content.Server.Atmos.Components;
|
||||||
|
using Content.Shared.Atmos;
|
||||||
|
using Content.Shared.Maps;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
|
namespace Content.Server.Atmos.EntitySystems;
|
||||||
|
|
||||||
|
public partial class AtmosphereSystem
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void InvalidateVisuals(EntityUid gridUid, Vector2i tile)
|
||||||
|
{
|
||||||
|
_gasTileOverlaySystem.Invalidate(gridUid, tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool NeedsVacuumFixing(IMapGrid mapGrid, Vector2i indices)
|
||||||
|
{
|
||||||
|
var value = false;
|
||||||
|
|
||||||
|
var enumerator = GetObstructingComponentsEnumerator(mapGrid, indices);
|
||||||
|
|
||||||
|
while (enumerator.MoveNext(out var airtight))
|
||||||
|
{
|
||||||
|
value |= airtight.FixVacuum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the volume in liters for a number of tiles, on a specific grid.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mapGrid">The grid in question.</param>
|
||||||
|
/// <param name="tiles">The amount of tiles.</param>
|
||||||
|
/// <returns>The volume in liters that the tiles occupy.</returns>
|
||||||
|
private float GetVolumeForTiles(IMapGrid mapGrid, int tiles = 1)
|
||||||
|
{
|
||||||
|
return Atmospherics.CellVolume * mapGrid.TileSize * tiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all obstructing <see cref="AirtightComponent"/> instances in a specific tile.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mapGrid">The grid where to get the tile.</param>
|
||||||
|
/// <param name="tile">The indices of the tile.</param>
|
||||||
|
/// <returns>The enumerator for the airtight components.</returns>
|
||||||
|
public AtmosObstructionEnumerator GetObstructingComponentsEnumerator(IMapGrid mapGrid, Vector2i tile)
|
||||||
|
{
|
||||||
|
var ancEnumerator = mapGrid.GetAnchoredEntitiesEnumerator(tile);
|
||||||
|
var airQuery = GetEntityQuery<AirtightComponent>();
|
||||||
|
|
||||||
|
var enumerator = new AtmosObstructionEnumerator(ancEnumerator, airQuery);
|
||||||
|
return enumerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AtmosDirection GetBlockedDirections(IMapGrid mapGrid, Vector2i indices)
|
||||||
|
{
|
||||||
|
var value = AtmosDirection.Invalid;
|
||||||
|
|
||||||
|
var enumerator = GetObstructingComponentsEnumerator(mapGrid, indices);
|
||||||
|
|
||||||
|
while (enumerator.MoveNext(out var airtight))
|
||||||
|
{
|
||||||
|
if(airtight.AirBlocked)
|
||||||
|
value |= airtight.AirBlockedDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pries a tile in a grid.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mapGrid">The grid in question.</param>
|
||||||
|
/// <param name="tile">The indices of the tile.</param>
|
||||||
|
private void PryTile(IMapGrid mapGrid, Vector2i tile)
|
||||||
|
{
|
||||||
|
if (!mapGrid.TryGetTileRef(tile, out var tileRef))
|
||||||
|
return;
|
||||||
|
|
||||||
|
tileRef.PryTile(_mapManager, _tileDefinitionManager, EntityManager, _robustRandom);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,11 +4,13 @@ using Content.Server.NodeContainer.EntitySystems;
|
|||||||
using Content.Shared.Atmos.EntitySystems;
|
using Content.Shared.Atmos.EntitySystems;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Server.Atmos.EntitySystems;
|
||||||
|
|
||||||
namespace Content.Server.Atmos.EntitySystems
|
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is our SSAir equivalent, if you need to interact with or query atmos in any way, go through this.
|
/// This is our SSAir equivalent, if you need to interact with or query atmos in any way, go through this.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -16,9 +18,13 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
public sealed partial class AtmosphereSystem : SharedAtmosphereSystem
|
public sealed partial class AtmosphereSystem : SharedAtmosphereSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||||
|
[Dependency] private readonly IAdminLogManager _adminLog = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _containers = default!;
|
[Dependency] private readonly SharedContainerSystem _containers = default!;
|
||||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||||
|
[Dependency] private readonly GasTileOverlaySystem _gasTileOverlaySystem = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
|
|
||||||
|
|
||||||
private const float ExposedUpdateDelay = 1f;
|
private const float ExposedUpdateDelay = 1f;
|
||||||
@@ -33,7 +39,8 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
InitializeGases();
|
InitializeGases();
|
||||||
InitializeCommands();
|
InitializeCommands();
|
||||||
InitializeCVars();
|
InitializeCVars();
|
||||||
InitializeGrid();
|
InitializeGridAtmosphere();
|
||||||
|
InitializeMap();
|
||||||
|
|
||||||
|
|
||||||
SubscribeLocalEvent<TileChangedEvent>(OnTileChanged);
|
SubscribeLocalEvent<TileChangedEvent>(OnTileChanged);
|
||||||
@@ -49,15 +56,6 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
|
|
||||||
private void OnTileChanged(TileChangedEvent ev)
|
private void OnTileChanged(TileChangedEvent ev)
|
||||||
{
|
{
|
||||||
// When a tile changes, we want to update it only if it's gone from
|
|
||||||
// space -> not space or vice versa. So if the old tile is the
|
|
||||||
// same as the new tile in terms of space-ness, ignore the change
|
|
||||||
|
|
||||||
if (ev.NewTile.IsSpace(_tileDefinitionManager) == ev.OldTile.IsSpace(_tileDefinitionManager))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
InvalidateTile(ev.NewTile.GridUid, ev.NewTile.GridIndices);
|
InvalidateTile(ev.NewTile.GridUid, ev.NewTile.GridIndices);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,19 +73,15 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
|
|
||||||
foreach (var (exposed, transform) in EntityManager.EntityQuery<AtmosExposedComponent, TransformComponent>())
|
foreach (var (exposed, transform) in EntityManager.EntityQuery<AtmosExposedComponent, TransformComponent>())
|
||||||
{
|
{
|
||||||
// Used for things like disposals/cryo to change which air people are exposed to.
|
var air = GetContainingMixture(exposed.Owner, transform:transform);
|
||||||
var airEvent = new AtmosExposedGetAirEvent();
|
|
||||||
RaiseLocalEvent(exposed.Owner, ref airEvent, false);
|
|
||||||
|
|
||||||
airEvent.Gas ??= GetTileMixture(transform.Coordinates);
|
if (air == null)
|
||||||
if (airEvent.Gas == null)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var updateEvent = new AtmosExposedUpdateEvent(transform.Coordinates, airEvent.Gas);
|
var updateEvent = new AtmosExposedUpdateEvent(transform.Coordinates, air, transform);
|
||||||
RaiseLocalEvent(exposed.Owner, ref updateEvent, true);
|
RaiseLocalEvent(exposed.Owner, ref updateEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
_exposedTimer -= ExposedUpdateDelay;
|
_exposedTimer -= ExposedUpdateDelay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace Content.Server.Atmos.EntitySystems;
|
|||||||
public sealed class AutomaticAtmosSystem : EntitySystem
|
public sealed class AutomaticAtmosSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
|
[Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!;
|
||||||
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -27,7 +28,7 @@ public sealed class AutomaticAtmosSystem : EntitySystem
|
|||||||
// TODO: a simple array lookup, as tile IDs are likely contiguous, and there's at most 2^16 possibilities anyway.
|
// TODO: a simple array lookup, as tile IDs are likely contiguous, and there's at most 2^16 possibilities anyway.
|
||||||
if (!((ev.OldTile.IsSpace(_tileDefinitionManager) && !ev.NewTile.IsSpace(_tileDefinitionManager)) ||
|
if (!((ev.OldTile.IsSpace(_tileDefinitionManager) && !ev.NewTile.IsSpace(_tileDefinitionManager)) ||
|
||||||
(!ev.OldTile.IsSpace(_tileDefinitionManager) && ev.NewTile.IsSpace(_tileDefinitionManager))) ||
|
(!ev.OldTile.IsSpace(_tileDefinitionManager) && ev.NewTile.IsSpace(_tileDefinitionManager))) ||
|
||||||
HasComp<IAtmosphereComponent>(ev.Entity))
|
_atmosphereSystem.HasAtmosphere(ev.Entity))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!TryComp<PhysicsComponent>(ev.Entity, out var physics))
|
if (!TryComp<PhysicsComponent>(ev.Entity, out var physics))
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
|
|
||||||
foreach (var (barotrauma, damageable, transform) in EntityManager.EntityQuery<BarotraumaComponent, DamageableComponent, TransformComponent>())
|
foreach (var (barotrauma, damageable, transform) in EntityManager.EntityQuery<BarotraumaComponent, DamageableComponent, TransformComponent>())
|
||||||
{
|
{
|
||||||
|
var uid = barotrauma.Owner;
|
||||||
var totalDamage = FixedPoint2.Zero;
|
var totalDamage = FixedPoint2.Zero;
|
||||||
foreach (var (barotraumaDamageType, _) in barotrauma.Damage.DamageDict)
|
foreach (var (barotraumaDamageType, _) in barotrauma.Damage.DamageDict)
|
||||||
{
|
{
|
||||||
@@ -152,7 +153,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
|
|
||||||
var pressure = 1f;
|
var pressure = 1f;
|
||||||
|
|
||||||
if (_atmosphereSystem.GetTileMixture(transform.Coordinates) is { } mixture)
|
if (_atmosphereSystem.GetContainingMixture(uid) is {} mixture)
|
||||||
{
|
{
|
||||||
pressure = MathF.Max(mixture.Pressure, 1f);
|
pressure = MathF.Max(mixture.Pressure, 1f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Atmos.Components;
|
using Content.Server.Atmos.Components;
|
||||||
using Content.Server.Stunnable;
|
using Content.Server.Stunnable;
|
||||||
@@ -12,6 +14,10 @@ using Content.Shared.Database;
|
|||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Temperature;
|
using Content.Shared.Temperature;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Physics.Dynamics;
|
using Robust.Shared.Physics.Dynamics;
|
||||||
|
|
||||||
@@ -25,6 +31,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
[Dependency] private readonly TemperatureSystem _temperatureSystem = default!;
|
[Dependency] private readonly TemperatureSystem _temperatureSystem = default!;
|
||||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||||
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
|
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
|
|
||||||
private const float MinimumFireStacks = -10f;
|
private const float MinimumFireStacks = -10f;
|
||||||
@@ -272,7 +279,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var air = _atmosphereSystem.GetTileMixture(transform.Coordinates);
|
var air = _atmosphereSystem.GetContainingMixture(uid);
|
||||||
|
|
||||||
// If we're in an oxygenless environment, put the fire out.
|
// If we're in an oxygenless environment, put the fire out.
|
||||||
if (air == null || air.GetMoles(Gas.Oxygen) < 1f)
|
if (air == null || air.GetMoles(Gas.Oxygen) < 1f)
|
||||||
@@ -281,7 +288,13 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_atmosphereSystem.HotspotExpose(transform.Coordinates, 700f, 50f, true);
|
if(transform.GridUid != null)
|
||||||
|
{
|
||||||
|
_atmosphereSystem.HotspotExpose(transform.GridUid.Value,
|
||||||
|
_transformSystem.GetGridOrMapTilePosition(uid, transform),
|
||||||
|
700f, 50f, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var otherUid in flammable.Collided.ToArray())
|
foreach (var otherUid in flammable.Collided.ToArray())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -140,9 +140,7 @@ namespace Content.Server.Atmos.EntitySystems
|
|||||||
/// <returns>true if updated</returns>
|
/// <returns>true if updated</returns>
|
||||||
private bool TryRefreshTile(GridAtmosphereComponent gridAtmosphere, GasOverlayData oldTile, Vector2i indices, out GasOverlayData overlayData)
|
private bool TryRefreshTile(GridAtmosphereComponent gridAtmosphere, GasOverlayData oldTile, Vector2i indices, out GasOverlayData overlayData)
|
||||||
{
|
{
|
||||||
var tile = _atmosphereSystem.GetTileAtmosphere(gridAtmosphere, indices);
|
if (!gridAtmosphere.Tiles.TryGetValue(indices, out var tile))
|
||||||
|
|
||||||
if (tile == null)
|
|
||||||
{
|
{
|
||||||
overlayData = default;
|
overlayData = default;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.Atmos.Reactions;
|
using Content.Server.Atmos.Reactions;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
@@ -19,17 +21,12 @@ namespace Content.Server.Atmos
|
|||||||
[DataField("moles")] [ViewVariables]
|
[DataField("moles")] [ViewVariables]
|
||||||
public float[] Moles = new float[Atmospherics.AdjustedNumberOfGases];
|
public float[] Moles = new float[Atmospherics.AdjustedNumberOfGases];
|
||||||
|
|
||||||
public float[] MolesArchived = new float[Atmospherics.AdjustedNumberOfGases];
|
|
||||||
|
|
||||||
[DataField("temperature")] [ViewVariables]
|
[DataField("temperature")] [ViewVariables]
|
||||||
private float _temperature = Atmospherics.TCMB;
|
private float _temperature = Atmospherics.TCMB;
|
||||||
|
|
||||||
[DataField("immutable")] [ViewVariables]
|
[DataField("immutable")] [ViewVariables]
|
||||||
public bool Immutable { get; private set; }
|
public bool Immutable { get; private set; }
|
||||||
|
|
||||||
[DataField("lastShare")] [ViewVariables]
|
|
||||||
public float LastShare { get; set; }
|
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public readonly Dictionary<GasReaction, float> ReactionResults = new()
|
public readonly Dictionary<GasReaction, float> ReactionResults = new()
|
||||||
{
|
{
|
||||||
@@ -65,8 +62,6 @@ namespace Content.Server.Atmos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float TemperatureArchived { get; private set; }
|
|
||||||
|
|
||||||
[DataField("volume")] [ViewVariables]
|
[DataField("volume")] [ViewVariables]
|
||||||
public float Volume { get; set; }
|
public float Volume { get; set; }
|
||||||
|
|
||||||
@@ -87,13 +82,6 @@ namespace Content.Server.Atmos
|
|||||||
Immutable = true;
|
Immutable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void Archive()
|
|
||||||
{
|
|
||||||
Moles.AsSpan().CopyTo(MolesArchived.AsSpan());
|
|
||||||
TemperatureArchived = Temperature;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public float GetMoles(int gasId)
|
public float GetMoles(int gasId)
|
||||||
{
|
{
|
||||||
@@ -192,40 +180,6 @@ namespace Content.Server.Atmos
|
|||||||
Temperature = sample.Temperature;
|
Temperature = sample.Temperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum GasCompareResult
|
|
||||||
{
|
|
||||||
NoExchange = -2,
|
|
||||||
TemperatureExchange = -1,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compares sample to self to see if within acceptable ranges that group processing may be enabled.
|
|
||||||
/// </summary>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public GasCompareResult Compare(GasMixture sample)
|
|
||||||
{
|
|
||||||
var moles = 0f;
|
|
||||||
|
|
||||||
for(var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
|
||||||
{
|
|
||||||
var gasMoles = Moles[i];
|
|
||||||
var delta = MathF.Abs(gasMoles - sample.Moles[i]);
|
|
||||||
if (delta > Atmospherics.MinimumMolesDeltaToMove && (delta > gasMoles * Atmospherics.MinimumAirRatioToMove))
|
|
||||||
return (GasCompareResult)i; // We can move gases!
|
|
||||||
moles += gasMoles;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (moles > Atmospherics.MinimumMolesDeltaToMove)
|
|
||||||
{
|
|
||||||
var tempDelta = MathF.Abs(Temperature - sample.Temperature);
|
|
||||||
if (tempDelta > Atmospherics.MinimumTemperatureDeltaToSuspend)
|
|
||||||
return GasCompareResult.TemperatureExchange; // There can be temperature exchange.
|
|
||||||
}
|
|
||||||
|
|
||||||
// No exchange at all!
|
|
||||||
return GasCompareResult.NoExchange;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
@@ -244,7 +198,6 @@ namespace Content.Server.Atmos
|
|||||||
{
|
{
|
||||||
// The arrays MUST have a specific length.
|
// The arrays MUST have a specific length.
|
||||||
Array.Resize(ref Moles, Atmospherics.AdjustedNumberOfGases);
|
Array.Resize(ref Moles, Atmospherics.AdjustedNumberOfGases);
|
||||||
Array.Resize(ref MolesArchived, Atmospherics.AdjustedNumberOfGases);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
@@ -259,15 +212,13 @@ namespace Content.Server.Atmos
|
|||||||
if (ReferenceEquals(null, other)) return false;
|
if (ReferenceEquals(null, other)) return false;
|
||||||
if (ReferenceEquals(this, other)) return true;
|
if (ReferenceEquals(this, other)) return true;
|
||||||
return Moles.SequenceEqual(other.Moles)
|
return Moles.SequenceEqual(other.Moles)
|
||||||
&& MolesArchived.SequenceEqual(other.MolesArchived)
|
|
||||||
&& _temperature.Equals(other._temperature)
|
&& _temperature.Equals(other._temperature)
|
||||||
&& ReactionResults.SequenceEqual(other.ReactionResults)
|
&& ReactionResults.SequenceEqual(other.ReactionResults)
|
||||||
&& Immutable == other.Immutable
|
&& Immutable == other.Immutable
|
||||||
&& LastShare.Equals(other.LastShare)
|
|
||||||
&& TemperatureArchived.Equals(other.TemperatureArchived)
|
|
||||||
&& Volume.Equals(other.Volume);
|
&& Volume.Equals(other.Volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")]
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
var hashCode = new HashCode();
|
var hashCode = new HashCode();
|
||||||
@@ -275,15 +226,11 @@ namespace Content.Server.Atmos
|
|||||||
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||||
{
|
{
|
||||||
var moles = Moles[i];
|
var moles = Moles[i];
|
||||||
var molesArchived = MolesArchived[i];
|
|
||||||
hashCode.Add(moles);
|
hashCode.Add(moles);
|
||||||
hashCode.Add(molesArchived);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hashCode.Add(_temperature);
|
hashCode.Add(_temperature);
|
||||||
hashCode.Add(TemperatureArchived);
|
|
||||||
hashCode.Add(Immutable);
|
hashCode.Add(Immutable);
|
||||||
hashCode.Add(LastShare);
|
|
||||||
hashCode.Add(Volume);
|
hashCode.Add(Volume);
|
||||||
|
|
||||||
return hashCode.ToHashCode();
|
return hashCode.ToHashCode();
|
||||||
@@ -294,11 +241,8 @@ namespace Content.Server.Atmos
|
|||||||
var newMixture = new GasMixture()
|
var newMixture = new GasMixture()
|
||||||
{
|
{
|
||||||
Moles = (float[])Moles.Clone(),
|
Moles = (float[])Moles.Clone(),
|
||||||
MolesArchived = (float[])MolesArchived.Clone(),
|
|
||||||
_temperature = _temperature,
|
_temperature = _temperature,
|
||||||
Immutable = Immutable,
|
Immutable = Immutable,
|
||||||
LastShare = LastShare,
|
|
||||||
TemperatureArchived = TemperatureArchived,
|
|
||||||
Volume = Volume,
|
Volume = Volume,
|
||||||
};
|
};
|
||||||
return newMixture;
|
return newMixture;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Content.Server.Atmos.EntitySystems;
|
|||||||
using Content.Server.Temperature.Systems;
|
using Content.Server.Temperature.Systems;
|
||||||
using Content.Server.Body.Components;
|
using Content.Server.Body.Components;
|
||||||
using Content.Shared.Examine;
|
using Content.Shared.Examine;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
using Content.Shared.Tag;
|
using Content.Shared.Tag;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
@@ -13,6 +14,7 @@ namespace Content.Server.Atmos.Miasma
|
|||||||
{
|
{
|
||||||
public sealed class MiasmaSystem : EntitySystem
|
public sealed class MiasmaSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||||
|
|
||||||
@@ -108,9 +110,11 @@ namespace Content.Server.Atmos.Miasma
|
|||||||
|
|
||||||
float molRate = perishable.MolsPerSecondPerUnitMass * _rotUpdateRate;
|
float molRate = perishable.MolsPerSecondPerUnitMass * _rotUpdateRate;
|
||||||
|
|
||||||
var tileMix = _atmosphereSystem.GetTileMixture(Transform(perishable.Owner).Coordinates);
|
var transform = Transform(perishable.Owner);
|
||||||
if (tileMix != null)
|
var indices = _transformSystem.GetGridOrMapTilePosition(perishable.Owner);
|
||||||
tileMix.AdjustMoles(Gas.Miasma, molRate * physics.FixturesMass);
|
|
||||||
|
var tileMix = _atmosphereSystem.GetTileMixture(transform.GridUid, null, indices, true);
|
||||||
|
tileMix?.AdjustMoles(Gas.Miasma, molRate * physics.FixturesMass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,9 +171,10 @@ namespace Content.Server.Atmos.Miasma
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var molsToDump = (component.MolsPerSecondPerUnitMass * physics.FixturesMass) * component.DeathAccumulator;
|
var molsToDump = (component.MolsPerSecondPerUnitMass * physics.FixturesMass) * component.DeathAccumulator;
|
||||||
var tileMix = _atmosphereSystem.GetTileMixture(Transform(uid).Coordinates);
|
var transform = Transform(uid);
|
||||||
if (tileMix != null)
|
var indices = _transformSystem.GetGridOrMapTilePosition(uid, transform);
|
||||||
tileMix.AdjustMoles(Gas.Miasma, molsToDump);
|
var tileMix = _atmosphereSystem.GetTileMixture(transform.GridUid, null, indices, true);
|
||||||
|
tileMix?.AdjustMoles(Gas.Miasma, molsToDump);
|
||||||
|
|
||||||
// Waste of entities to let these through
|
// Waste of entities to let these through
|
||||||
foreach (var part in args.GibbedParts)
|
foreach (var part in args.GibbedParts)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Content.Server.Power.Components;
|
|||||||
using Content.Server.Power.EntitySystems;
|
using Content.Server.Power.EntitySystems;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Atmos.Monitor;
|
using Content.Shared.Atmos.Monitor;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
@@ -24,6 +25,7 @@ namespace Content.Server.Atmos.Monitor.Systems
|
|||||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
[Dependency] private readonly AtmosDeviceSystem _atmosDeviceSystem = default!;
|
[Dependency] private readonly AtmosDeviceSystem _atmosDeviceSystem = default!;
|
||||||
[Dependency] private readonly DeviceNetworkSystem _deviceNetSystem = default!;
|
[Dependency] private readonly DeviceNetworkSystem _deviceNetSystem = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
@@ -118,27 +120,31 @@ namespace Content.Server.Atmos.Monitor.Systems
|
|||||||
if (!Resolve(uid, ref component, ref appearance)) return;
|
if (!Resolve(uid, ref component, ref appearance)) return;
|
||||||
|
|
||||||
var transform = Transform(component.Owner);
|
var transform = Transform(component.Owner);
|
||||||
|
|
||||||
|
if (transform.GridUid == null)
|
||||||
|
return;
|
||||||
|
|
||||||
// atmos alarms will first attempt to get the air
|
// atmos alarms will first attempt to get the air
|
||||||
// directly underneath it - if not, then it will
|
// directly underneath it - if not, then it will
|
||||||
// instead place itself directly in front of the tile
|
// instead place itself directly in front of the tile
|
||||||
// it is facing, and then visually shift itself back
|
// it is facing, and then visually shift itself back
|
||||||
// via sprite offsets (SS13 style but fuck it)
|
// via sprite offsets (SS13 style but fuck it)
|
||||||
var coords = transform.Coordinates;
|
var coords = transform.Coordinates;
|
||||||
|
var pos = _transformSystem.GetGridOrMapTilePosition(uid, transform);
|
||||||
|
|
||||||
if (_atmosphereSystem.IsTileAirBlocked(coords))
|
if (_atmosphereSystem.IsTileAirBlocked(transform.GridUid.Value, pos))
|
||||||
{
|
{
|
||||||
|
|
||||||
var rotPos = transform.LocalRotation.RotateVec(new Vector2(0, -1));
|
var rotPos = transform.LocalRotation.RotateVec(new Vector2(0, -1));
|
||||||
transform.Anchored = false;
|
transform.Anchored = false;
|
||||||
coords = coords.Offset(rotPos);
|
coords = coords.Offset(rotPos);
|
||||||
transform.Coordinates = coords;
|
transform.Coordinates = coords;
|
||||||
|
|
||||||
appearance.SetData("offset", - new Vector2(0, -1));
|
appearance.SetData("offset", - new Vector2i(0, -1));
|
||||||
|
|
||||||
transform.Anchored = true;
|
transform.Anchored = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GasMixture? air = _atmosphereSystem.GetTileMixture(coords);
|
GasMixture? air = _atmosphereSystem.GetContainingMixture(uid, true);
|
||||||
component.TileGas = air;
|
component.TileGas = air;
|
||||||
|
|
||||||
_checkPos.Remove(uid);
|
_checkPos.Remove(uid);
|
||||||
@@ -214,8 +220,7 @@ namespace Content.Server.Atmos.Monitor.Systems
|
|||||||
if (atmosDeviceComponent.JoinedGrid == null)
|
if (atmosDeviceComponent.JoinedGrid == null)
|
||||||
{
|
{
|
||||||
_atmosDeviceSystem.JoinAtmosphere(atmosDeviceComponent);
|
_atmosDeviceSystem.JoinAtmosphere(atmosDeviceComponent);
|
||||||
var coords = Transform(component.Owner).Coordinates;
|
var air = _atmosphereSystem.GetContainingMixture(uid, true);
|
||||||
var air = _atmosphereSystem.GetTileMixture(coords);
|
|
||||||
component.TileGas = air;
|
component.TileGas = air;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,10 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
|
|||||||
public sealed class GasVolumePumpSystem : EntitySystem
|
public sealed class GasVolumePumpSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
|
||||||
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!;
|
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -65,7 +66,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
|
|||||||
|| !nodeContainer.TryGetNode(pump.InletName, out PipeNode? inlet)
|
|| !nodeContainer.TryGetNode(pump.InletName, out PipeNode? inlet)
|
||||||
|| !nodeContainer.TryGetNode(pump.OutletName, out PipeNode? outlet))
|
|| !nodeContainer.TryGetNode(pump.OutletName, out PipeNode? outlet))
|
||||||
{
|
{
|
||||||
_ambientSoundSystem.SetAmbience(pump.Owner, false);
|
_ambientSoundSystem.SetAmbience(uid, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +89,9 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
|
|||||||
// Some of the gas from the mixture leaks when overclocked.
|
// Some of the gas from the mixture leaks when overclocked.
|
||||||
if (pump.Overclocked)
|
if (pump.Overclocked)
|
||||||
{
|
{
|
||||||
var tile = _atmosphereSystem.GetTileMixture(EntityManager.GetComponent<TransformComponent>(pump.Owner).Coordinates, true);
|
var transform = Transform(uid);
|
||||||
|
var indices = _transformSystem.GetGridOrMapTilePosition(uid, transform);
|
||||||
|
var tile = _atmosphereSystem.GetTileMixture(transform.GridUid, null, indices, true);
|
||||||
|
|
||||||
if (tile != null)
|
if (tile != null)
|
||||||
{
|
{
|
||||||
@@ -98,7 +101,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems
|
|||||||
}
|
}
|
||||||
|
|
||||||
_atmosphereSystem.Merge(outlet.Air, removed);
|
_atmosphereSystem.Merge(outlet.Air, removed);
|
||||||
_ambientSoundSystem.SetAmbience(pump.Owner, removed.TotalMoles > 0f);
|
_ambientSoundSystem.SetAmbience(uid, removed.TotalMoles > 0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnVolumePumpLeaveAtmosphere(EntityUid uid, GasVolumePumpComponent pump, AtmosDeviceDisabledEvent args)
|
private void OnVolumePumpLeaveAtmosphere(EntityUid uid, GasVolumePumpComponent pump, AtmosDeviceDisabledEvent args)
|
||||||
|
|||||||
@@ -27,20 +27,25 @@ namespace Content.Server.Atmos.Piping.EntitySystems
|
|||||||
SubscribeLocalEvent<AtmosDeviceComponent, AnchorStateChangedEvent>(OnDeviceAnchorChanged);
|
SubscribeLocalEvent<AtmosDeviceComponent, AnchorStateChangedEvent>(OnDeviceAnchorChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanJoinAtmosphere(AtmosDeviceComponent component)
|
private bool CanJoinAtmosphere(AtmosDeviceComponent component, TransformComponent transform)
|
||||||
{
|
{
|
||||||
return !component.RequireAnchored || EntityManager.GetComponent<TransformComponent>(component.Owner).Anchored;
|
return (!component.RequireAnchored || transform.Anchored) && transform.GridUid != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void JoinAtmosphere(AtmosDeviceComponent component)
|
public void JoinAtmosphere(AtmosDeviceComponent component)
|
||||||
{
|
{
|
||||||
if (!CanJoinAtmosphere(component))
|
var transform = Transform(component.Owner);
|
||||||
|
|
||||||
|
if (!CanJoinAtmosphere(component, transform))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: low-hanging fruit for perf improvements around here
|
||||||
|
|
||||||
|
// GridUid is not null because we can join atmosphere.
|
||||||
// We try to add the device to a valid atmosphere, and if we can't, try to add it to the entity system.
|
// We try to add the device to a valid atmosphere, and if we can't, try to add it to the entity system.
|
||||||
if (!_atmosphereSystem.AddAtmosDevice(component))
|
if (!_atmosphereSystem.AddAtmosDevice(transform.GridUid!.Value, component))
|
||||||
{
|
{
|
||||||
if (component.JoinSystem)
|
if (component.JoinSystem)
|
||||||
{
|
{
|
||||||
@@ -62,7 +67,7 @@ namespace Content.Server.Atmos.Piping.EntitySystems
|
|||||||
public void LeaveAtmosphere(AtmosDeviceComponent component)
|
public void LeaveAtmosphere(AtmosDeviceComponent component)
|
||||||
{
|
{
|
||||||
// Try to remove the component from an atmosphere, and if not
|
// Try to remove the component from an atmosphere, and if not
|
||||||
if (component.JoinedGrid != null && !_atmosphereSystem.RemoveAtmosDevice(component))
|
if (component.JoinedGrid != null && !_atmosphereSystem.RemoveAtmosDevice(component.JoinedGrid.Value, component))
|
||||||
{
|
{
|
||||||
// The grid might have been removed but not us... This usually shouldn't happen.
|
// The grid might have been removed but not us... This usually shouldn't happen.
|
||||||
component.JoinedGrid = null;
|
component.JoinedGrid = null;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Content.Server.Atmos.Piping.EntitySystems
|
|||||||
if (!component.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodes))
|
if (!component.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodes))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_atmosphereSystem.GetTileMixture(EntityManager.GetComponent<TransformComponent>(component.Owner).Coordinates) is not {} environment)
|
if (_atmosphereSystem.GetContainingMixture(uid, true) is not {} environment)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var node in nodes.Nodes.Values)
|
foreach (var node in nodes.Nodes.Values)
|
||||||
@@ -48,7 +48,7 @@ namespace Content.Server.Atmos.Piping.EntitySystems
|
|||||||
if (!component.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodes))
|
if (!component.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodes))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_atmosphereSystem.GetTileMixture(EntityManager.GetComponent<TransformComponent>(component.Owner).Coordinates, true) is not {} environment)
|
if (_atmosphereSystem.GetContainingMixture(uid, true, true) is not {} environment)
|
||||||
environment = GasMixture.SpaceGas;
|
environment = GasMixture.SpaceGas;
|
||||||
|
|
||||||
var lost = 0f;
|
var lost = 0f;
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Content.Server.Atmos.Components;
|
||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.Atmos.Piping.Components;
|
using Content.Server.Atmos.Piping.Components;
|
||||||
using Content.Server.Atmos.Piping.Other.Components;
|
using Content.Server.Atmos.Piping.Other.Components;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
|
||||||
namespace Content.Server.Atmos.Piping.Other.EntitySystems
|
namespace Content.Server.Atmos.Piping.Other.EntitySystems
|
||||||
{
|
{
|
||||||
@@ -11,6 +15,7 @@ namespace Content.Server.Atmos.Piping.Other.EntitySystems
|
|||||||
public sealed class GasMinerSystem : EntitySystem
|
public sealed class GasMinerSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -34,10 +39,14 @@ namespace Content.Server.Atmos.Piping.Other.EntitySystems
|
|||||||
|
|
||||||
private bool CheckMinerOperation(GasMinerComponent miner, [NotNullWhen(true)] out GasMixture? environment)
|
private bool CheckMinerOperation(GasMinerComponent miner, [NotNullWhen(true)] out GasMixture? environment)
|
||||||
{
|
{
|
||||||
environment = _atmosphereSystem.GetTileMixture(EntityManager.GetComponent<TransformComponent>(miner.Owner).Coordinates, true);
|
var uid = miner.Owner;
|
||||||
|
environment = _atmosphereSystem.GetContainingMixture(uid, true, true);
|
||||||
|
|
||||||
|
var transform = Transform(uid);
|
||||||
|
var position = _transformSystem.GetGridOrMapTilePosition(uid, transform);
|
||||||
|
|
||||||
// Space.
|
// Space.
|
||||||
if (_atmosphereSystem.IsTileSpace(EntityManager.GetComponent<TransformComponent>(miner.Owner).Coordinates))
|
if (_atmosphereSystem.IsTileSpace(transform.GridUid, transform.MapUid, position))
|
||||||
{
|
{
|
||||||
miner.Broken = true;
|
miner.Broken = true;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
|||||||
if (!Resolve(uid, ref canister, ref transform))
|
if (!Resolve(uid, ref canister, ref transform))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var environment = _atmosphereSystem.GetTileMixture(transform.Coordinates, true);
|
var environment = _atmosphereSystem.GetContainingMixture(uid, false, true);
|
||||||
|
|
||||||
if (environment is not null)
|
if (environment is not null)
|
||||||
_atmosphereSystem.Merge(environment, canister.Air);
|
_atmosphereSystem.Merge(environment, canister.Air);
|
||||||
@@ -180,7 +180,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var environment = _atmosphereSystem.GetTileMixture(EntityManager.GetComponent<TransformComponent>(canister.Owner).Coordinates, true);
|
var environment = _atmosphereSystem.GetContainingMixture(uid, false, true);
|
||||||
_atmosphereSystem.ReleaseGasTo(canister.Air, environment, canister.ReleasePressure);
|
_atmosphereSystem.ReleaseGasTo(canister.Air, environment, canister.ReleasePressure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
|||||||
if (!nodeContainer.TryGetNode(injector.InletName, out PipeNode? inlet))
|
if (!nodeContainer.TryGetNode(injector.InletName, out PipeNode? inlet))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var environment = _atmosphereSystem.GetTileMixture(EntityManager.GetComponent<TransformComponent>(injector.Owner).Coordinates, true);
|
var environment = _atmosphereSystem.GetContainingMixture(uid, true, true);
|
||||||
|
|
||||||
if (environment == null)
|
if (environment == null)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
|||||||
|
|
||||||
private void OnPassiveVentUpdated(EntityUid uid, GasPassiveVentComponent vent, AtmosDeviceUpdateEvent args)
|
private void OnPassiveVentUpdated(EntityUid uid, GasPassiveVentComponent vent, AtmosDeviceUpdateEvent args)
|
||||||
{
|
{
|
||||||
var environment = _atmosphereSystem.GetTileMixture(EntityManager.GetComponent<TransformComponent>(vent.Owner).Coordinates, true);
|
var environment = _atmosphereSystem.GetContainingMixture(uid, true, true);
|
||||||
|
|
||||||
if (environment == null)
|
if (environment == null)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var environment = _atmosphereSystem.GetTileMixture(EntityManager.GetComponent<TransformComponent>(vent.Owner).Coordinates, true);
|
var environment = _atmosphereSystem.GetContainingMixture(uid, true, true);
|
||||||
|
|
||||||
// We're in an air-blocked tile... Do nothing.
|
// We're in an air-blocked tile... Do nothing.
|
||||||
if (environment == null)
|
if (environment == null)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ using Content.Shared.Atmos.Monitor;
|
|||||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
||||||
@@ -26,6 +27,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
|||||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
[Dependency] private readonly DeviceNetworkSystem _deviceNetSystem = default!;
|
[Dependency] private readonly DeviceNetworkSystem _deviceNetSystem = default!;
|
||||||
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!;
|
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -54,19 +56,24 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
|||||||
if (!scrubber.Enabled
|
if (!scrubber.Enabled
|
||||||
|| !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)
|
|| !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)
|
||||||
|| !nodeContainer.TryGetNode(scrubber.OutletName, out PipeNode? outlet))
|
|| !nodeContainer.TryGetNode(scrubber.OutletName, out PipeNode? outlet))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
var xform = Transform(uid);
|
var xform = Transform(uid);
|
||||||
var environment = _atmosphereSystem.GetTileMixture(xform.Coordinates, true);
|
|
||||||
|
if (xform.GridUid == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var position = _transformSystem.GetGridOrMapTilePosition(uid, xform);
|
||||||
|
|
||||||
|
var environment = _atmosphereSystem.GetTileMixture(xform.GridUid, xform.MapUid, position, true);
|
||||||
|
|
||||||
Scrub(timeDelta, scrubber, environment, outlet);
|
Scrub(timeDelta, scrubber, environment, outlet);
|
||||||
|
|
||||||
if (!scrubber.WideNet) return;
|
if (!scrubber.WideNet)
|
||||||
|
return;
|
||||||
|
|
||||||
// Scrub adjacent tiles too.
|
// Scrub adjacent tiles too.
|
||||||
foreach (var adjacent in _atmosphereSystem.GetAdjacentTileMixtures(xform.Coordinates, false, true))
|
foreach (var adjacent in _atmosphereSystem.GetAdjacentTileMixtures(xform.GridUid.Value, position, false, true))
|
||||||
{
|
{
|
||||||
Scrub(timeDelta, scrubber, adjacent, outlet);
|
Scrub(timeDelta, scrubber, adjacent, outlet);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Content.Server.Atmos
|
|||||||
/// Internal Atmos class that stores data about the atmosphere in a grid.
|
/// Internal Atmos class that stores data about the atmosphere in a grid.
|
||||||
/// You shouldn't use this directly, use <see cref="AtmosphereSystem"/> instead.
|
/// You shouldn't use this directly, use <see cref="AtmosphereSystem"/> instead.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Access(typeof(AtmosphereSystem))]
|
[Access(typeof(AtmosphereSystem), typeof(GasTileOverlaySystem), typeof(AtmosDebugOverlaySystem))]
|
||||||
public sealed class TileAtmosphere : IGasMixtureHolder
|
public sealed class TileAtmosphere : IGasMixtureHolder
|
||||||
{
|
{
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
@@ -39,6 +39,12 @@ namespace Content.Server.Atmos
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public bool Excited { get; set; }
|
public bool Excited { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this tile should be considered space.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public bool Space { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adjacent tiles in the same order as <see cref="AtmosDirection"/>. (NSEW)
|
/// Adjacent tiles in the same order as <see cref="AtmosDirection"/>. (NSEW)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -81,6 +87,13 @@ namespace Content.Server.Atmos
|
|||||||
[Access(typeof(AtmosphereSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
|
[Access(typeof(AtmosphereSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
|
||||||
public GasMixture? Air { get; set; }
|
public GasMixture? Air { get; set; }
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
[DataField("lastShare")]
|
||||||
|
public float LastShare;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public float[]? MolesArchived;
|
||||||
|
|
||||||
GasMixture IGasMixtureHolder.Air
|
GasMixture IGasMixtureHolder.Air
|
||||||
{
|
{
|
||||||
get => Air ?? new GasMixture(Atmospherics.CellVolume){ Temperature = Temperature };
|
get => Air ?? new GasMixture(Atmospherics.CellVolume){ Temperature = Temperature };
|
||||||
@@ -93,11 +106,13 @@ namespace Content.Server.Atmos
|
|||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public AtmosDirection BlockedAirflow { get; set; } = AtmosDirection.Invalid;
|
public AtmosDirection BlockedAirflow { get; set; } = AtmosDirection.Invalid;
|
||||||
|
|
||||||
public TileAtmosphere(EntityUid gridIndex, Vector2i gridIndices, GasMixture? mixture = null, bool immutable = false)
|
public TileAtmosphere(EntityUid gridIndex, Vector2i gridIndices, GasMixture? mixture = null, bool immutable = false, bool space = false)
|
||||||
{
|
{
|
||||||
GridIndex = gridIndex;
|
GridIndex = gridIndex;
|
||||||
GridIndices = gridIndices;
|
GridIndices = gridIndices;
|
||||||
Air = mixture;
|
Air = mixture;
|
||||||
|
Space = space;
|
||||||
|
MolesArchived = Air != null ? new float[Atmospherics.AdjustedNumberOfGases] : null;
|
||||||
|
|
||||||
if(immutable)
|
if(immutable)
|
||||||
Air?.MarkImmutable();
|
Air?.MarkImmutable();
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ namespace Content.Server.Body.Systems
|
|||||||
|
|
||||||
if (ev.Gas == null)
|
if (ev.Gas == null)
|
||||||
{
|
{
|
||||||
ev.Gas = _atmosSys.GetTileMixture(Transform(uid).Coordinates);
|
ev.Gas = _atmosSys.GetContainingMixture(uid, false, true);
|
||||||
if (ev.Gas == null) return;
|
if (ev.Gas == null) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ namespace Content.Server.Body.Systems
|
|||||||
|
|
||||||
if (ev.Gas == null)
|
if (ev.Gas == null)
|
||||||
{
|
{
|
||||||
ev.Gas = _atmosSys.GetTileMixture(Transform(uid).Coordinates);
|
ev.Gas = _atmosSys.GetContainingMixture(uid, false, true);
|
||||||
|
|
||||||
// Walls and grids without atmos comp return null. I guess it makes sense to not be able to exhale in walls,
|
// Walls and grids without atmos comp return null. I guess it makes sense to not be able to exhale in walls,
|
||||||
// but this also means you cannot exhale on some grids.
|
// but this also means you cannot exhale on some grids.
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Content.Shared.Botany;
|
|||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Shared.Chemistry.Reagent;
|
using Content.Shared.Chemistry.Reagent;
|
||||||
using Content.Shared.FixedPoint;
|
using Content.Shared.FixedPoint;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
@@ -225,7 +226,8 @@ namespace Content.Server.Botany.Components
|
|||||||
_updateSpriteAfterUpdate = true;
|
_updateSpriteAfterUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var environment = EntitySystem.Get<AtmosphereSystem>().GetTileMixture(_entMan.GetComponent<TransformComponent>(Owner).Coordinates, true) ??
|
var atmosphereSystem = _entMan.EntitySysManager.GetEntitySystem<AtmosphereSystem>();
|
||||||
|
var environment = atmosphereSystem.GetContainingMixture(Owner, true, true) ??
|
||||||
GasMixture.SpaceGas;
|
GasMixture.SpaceGas;
|
||||||
|
|
||||||
if (Seed.ConsumeGasses.Count > 0)
|
if (Seed.ConsumeGasses.Count > 0)
|
||||||
|
|||||||
@@ -21,10 +21,9 @@ public sealed class CreateGas : ReagentEffect
|
|||||||
|
|
||||||
public override void Effect(ReagentEffectArgs args)
|
public override void Effect(ReagentEffectArgs args)
|
||||||
{
|
{
|
||||||
var atmosSys = EntitySystem.Get<AtmosphereSystem>();
|
var atmosSys = args.EntityManager.EntitySysManager.GetEntitySystem<AtmosphereSystem>();
|
||||||
|
|
||||||
var xform = args.EntityManager.GetComponent<TransformComponent>(args.SolutionEntity);
|
var tileMix = atmosSys.GetContainingMixture(args.SolutionEntity, false, true);
|
||||||
var tileMix = atmosSys.GetTileMixture(xform.Coordinates);
|
|
||||||
|
|
||||||
if (tileMix != null)
|
if (tileMix != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Content.Server.Chemistry.TileReactions
|
|||||||
|
|
||||||
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
||||||
|
|
||||||
var environment = atmosphereSystem.GetTileMixture(tile.GridUid, tile.GridIndices, true);
|
var environment = atmosphereSystem.GetTileMixture(tile.GridUid, null, tile.GridIndices, true);
|
||||||
|
|
||||||
if (environment == null || !atmosphereSystem.IsHotspotActive(tile.GridUid, tile.GridIndices))
|
if (environment == null || !atmosphereSystem.IsHotspotActive(tile.GridUid, tile.GridIndices))
|
||||||
return FixedPoint2.Zero;
|
return FixedPoint2.Zero;
|
||||||
@@ -30,7 +30,7 @@ namespace Content.Server.Chemistry.TileReactions
|
|||||||
MathF.Max(MathF.Min(environment.Temperature - (_coolingTemperature * 1000f),
|
MathF.Max(MathF.Min(environment.Temperature - (_coolingTemperature * 1000f),
|
||||||
environment.Temperature / _coolingTemperature), Atmospherics.TCMB);
|
environment.Temperature / _coolingTemperature), Atmospherics.TCMB);
|
||||||
|
|
||||||
atmosphereSystem.React(tile.GridUid, tile.GridIndices);
|
atmosphereSystem.ReactTile(tile.GridUid, tile.GridIndices);
|
||||||
atmosphereSystem.HotspotExtinguish(tile.GridUid, tile.GridIndices);
|
atmosphereSystem.HotspotExtinguish(tile.GridUid, tile.GridIndices);
|
||||||
|
|
||||||
return FixedPoint2.Zero;
|
return FixedPoint2.Zero;
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ namespace Content.Server.Chemistry.TileReactions
|
|||||||
|
|
||||||
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
||||||
|
|
||||||
var environment = atmosphereSystem.GetTileMixture(tile.GridUid, tile.GridIndices, true);
|
var environment = atmosphereSystem.GetTileMixture(tile.GridUid, null, tile.GridIndices, true);
|
||||||
if (environment == null || !atmosphereSystem.IsHotspotActive(tile.GridUid, tile.GridIndices))
|
if (environment == null || !atmosphereSystem.IsHotspotActive(tile.GridUid, tile.GridIndices))
|
||||||
return FixedPoint2.Zero;
|
return FixedPoint2.Zero;
|
||||||
|
|
||||||
environment.Temperature *= MathF.Max(_temperatureMultiplier * reactVolume.Float(), 1f);
|
environment.Temperature *= MathF.Max(_temperatureMultiplier * reactVolume.Float(), 1f);
|
||||||
atmosphereSystem.React(tile.GridUid, tile.GridIndices);
|
atmosphereSystem.ReactTile(tile.GridUid, tile.GridIndices);
|
||||||
|
|
||||||
return reactVolume;
|
return reactVolume;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
|||||||
_disposalUnitSystem.TryEjectContents(duc);
|
_disposalUnitSystem.TryEjectContents(duc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_atmosphereSystem.GetTileMixture(holderTransform.Coordinates, true) is {} environment)
|
if (_atmosphereSystem.GetContainingMixture(uid, false, true) is {} environment)
|
||||||
{
|
{
|
||||||
_atmosphereSystem.Merge(environment, holder.Air);
|
_atmosphereSystem.Merge(environment, holder.Air);
|
||||||
holder.Air.Clear();
|
holder.Air.Clear();
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
|||||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||||
[Dependency] private readonly DumpableSystem _dumpableSystem = default!;
|
[Dependency] private readonly DumpableSystem _dumpableSystem = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
|
|
||||||
private readonly List<DisposalUnitComponent> _activeDisposals = new();
|
private readonly List<DisposalUnitComponent> _activeDisposals = new();
|
||||||
|
|
||||||
@@ -521,8 +522,9 @@ namespace Content.Server.Disposal.Unit.EntitySystems
|
|||||||
|
|
||||||
var air = component.Air;
|
var air = component.Air;
|
||||||
var entryComponent = EntityManager.GetComponent<DisposalEntryComponent>(entry);
|
var entryComponent = EntityManager.GetComponent<DisposalEntryComponent>(entry);
|
||||||
|
var indices = _transformSystem.GetGridOrMapTilePosition(component.Owner, xform);
|
||||||
|
|
||||||
if (_atmosSystem.GetTileMixture(xform.Coordinates, true) is {Temperature: > 0} environment)
|
if (_atmosSystem.GetTileMixture(xform.GridUid, xform.MapUid, indices, true) is {Temperature: > 0} environment)
|
||||||
{
|
{
|
||||||
var transferMoles = 0.1f * (0.25f * Atmospherics.OneAtmosphere * 1.01f - air.Pressure) * air.Volume / (environment.Temperature * Atmospherics.R);
|
var transferMoles = 0.1f * (0.25f * Atmospherics.OneAtmosphere * 1.01f - air.Pressure) * air.Volume / (environment.Temperature * Atmospherics.R);
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,10 @@ using Content.Server.Atmos.Components;
|
|||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.Doors.Systems;
|
using Content.Server.Doors.Systems;
|
||||||
using Content.Shared.Doors.Components;
|
using Content.Shared.Doors.Components;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
using Robust.Shared.Serialization.Manager.Attributes;
|
||||||
|
|
||||||
namespace Content.Server.Doors.Components
|
namespace Content.Server.Doors.Components
|
||||||
{
|
{
|
||||||
@@ -42,12 +46,20 @@ namespace Content.Server.Doors.Components
|
|||||||
|
|
||||||
public bool IsHoldingPressure(float threshold = 20)
|
public bool IsHoldingPressure(float threshold = 20)
|
||||||
{
|
{
|
||||||
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
var transform = _entMan.GetComponent<TransformComponent>(Owner);
|
||||||
|
|
||||||
|
if (transform.GridUid is not {} gridUid)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var atmosphereSystem = _entMan.EntitySysManager.GetEntitySystem<AtmosphereSystem>();
|
||||||
|
var transformSystem = _entMan.EntitySysManager.GetEntitySystem<TransformSystem>();
|
||||||
|
|
||||||
|
var position = transformSystem.GetGridOrMapTilePosition(Owner, transform);
|
||||||
|
|
||||||
var minMoles = float.MaxValue;
|
var minMoles = float.MaxValue;
|
||||||
var maxMoles = 0f;
|
var maxMoles = 0f;
|
||||||
|
|
||||||
foreach (var adjacent in atmosphereSystem.GetAdjacentTileMixtures(_entMan.GetComponent<TransformComponent>(Owner).Coordinates))
|
foreach (var adjacent in atmosphereSystem.GetAdjacentTileMixtures(gridUid, position))
|
||||||
{
|
{
|
||||||
var moles = adjacent.TotalMoles;
|
var moles = adjacent.TotalMoles;
|
||||||
if (moles < minMoles)
|
if (moles < minMoles)
|
||||||
@@ -61,20 +73,25 @@ namespace Content.Server.Doors.Components
|
|||||||
|
|
||||||
public bool IsHoldingFire()
|
public bool IsHoldingFire()
|
||||||
{
|
{
|
||||||
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
var atmosphereSystem = _entMan.EntitySysManager.GetEntitySystem<AtmosphereSystem>();
|
||||||
|
var transformSystem = _entMan.EntitySysManager.GetEntitySystem<TransformSystem>();
|
||||||
|
|
||||||
if (!atmosphereSystem.TryGetGridAndTile(_entMan.GetComponent<TransformComponent>(Owner).Coordinates, out var tuple))
|
var transform = _entMan.GetComponent<TransformComponent>(Owner);
|
||||||
|
var position = transformSystem.GetGridOrMapTilePosition(Owner, transform);
|
||||||
|
|
||||||
|
// No grid, no fun.
|
||||||
|
if (transform.GridUid is not {} gridUid)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (atmosphereSystem.GetTileMixture(tuple.Value.Grid, tuple.Value.Tile) == null)
|
if (atmosphereSystem.GetTileMixture(gridUid, null, position) == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (atmosphereSystem.IsHotspotActive(tuple.Value.Grid, tuple.Value.Tile))
|
if (atmosphereSystem.IsHotspotActive(gridUid, position))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
foreach (var adjacent in atmosphereSystem.GetAdjacentTiles(_entMan.GetComponent<TransformComponent>(Owner).Coordinates))
|
foreach (var adjacent in atmosphereSystem.GetAdjacentTiles(gridUid, position))
|
||||||
{
|
{
|
||||||
if (atmosphereSystem.IsHotspotActive(tuple.Value.Grid, adjacent))
|
if (atmosphereSystem.IsHotspotActive(gridUid, adjacent))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ using Content.Shared.MobState.Components;
|
|||||||
using Content.Shared.PDA;
|
using Content.Shared.PDA;
|
||||||
using Content.Shared.Roles;
|
using Content.Shared.Roles;
|
||||||
using Content.Shared.Traitor.Uplink;
|
using Content.Shared.Traitor.Uplink;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.Player;
|
using Robust.Server.Player;
|
||||||
using Robust.Shared.Configuration;
|
using Robust.Shared.Configuration;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
@@ -36,6 +37,8 @@ public sealed class TraitorDeathMatchRuleSystem : GameRuleSystem
|
|||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly MaxTimeRestartRuleSystem _restarter = default!;
|
[Dependency] private readonly MaxTimeRestartRuleSystem _restarter = default!;
|
||||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||||
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
|
|
||||||
public override string Prototype => "TraitorDeathMatch";
|
public override string Prototype => "TraitorDeathMatch";
|
||||||
|
|
||||||
@@ -243,10 +246,17 @@ public sealed class TraitorDeathMatchRuleSystem : GameRuleSystem
|
|||||||
_robustRandom.Shuffle(ents);
|
_robustRandom.Shuffle(ents);
|
||||||
var foundATarget = false;
|
var foundATarget = false;
|
||||||
bestTarget = EntityCoordinates.Invalid;
|
bestTarget = EntityCoordinates.Invalid;
|
||||||
var atmosphereSystem = EntitySystem.Get<AtmosphereSystem>();
|
|
||||||
foreach (var entity in ents)
|
foreach (var entity in ents)
|
||||||
{
|
{
|
||||||
if (!atmosphereSystem.IsTileMixtureProbablySafe(Transform(entity).Coordinates))
|
var transform = Transform(entity);
|
||||||
|
|
||||||
|
if (transform.GridUid == null || transform.MapUid == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var position = _transformSystem.GetGridOrMapTilePosition(entity, transform);
|
||||||
|
|
||||||
|
if (!_atmosphereSystem.IsTileMixtureProbablySafe(transform.GridUid.Value, transform.MapUid.Value, position))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var distanceFromNearest = float.PositiveInfinity;
|
var distanceFromNearest = float.PositiveInfinity;
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
public sealed class MatchstickSystem : EntitySystem
|
public sealed class MatchstickSystem : EntitySystem
|
||||||
{
|
{
|
||||||
private HashSet<MatchstickComponent> _litMatches = new();
|
private HashSet<MatchstickComponent> _litMatches = new();
|
||||||
[Dependency]
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -38,7 +38,14 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
if (match.CurrentState != SmokableState.Lit || Paused(match.Owner) || match.Deleted)
|
if (match.CurrentState != SmokableState.Lit || Paused(match.Owner) || match.Deleted)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_atmosphereSystem.HotspotExpose(EntityManager.GetComponent<TransformComponent>(match.Owner).Coordinates, 400, 50, true);
|
var xform = Transform(match.Owner);
|
||||||
|
|
||||||
|
if (xform.GridUid is not {} gridUid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var position = _transformSystem.GetGridOrMapTilePosition(match.Owner, xform);
|
||||||
|
|
||||||
|
_atmosphereSystem.HotspotExpose(gridUid, position, 400, 50, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,10 +33,13 @@ namespace Content.Server.NodeContainer.NodeGroups
|
|||||||
Grid = entMan.GetComponent<TransformComponent>(sourceNode.Owner).GridUid;
|
Grid = entMan.GetComponent<TransformComponent>(sourceNode.Owner).GridUid;
|
||||||
|
|
||||||
if (Grid == null)
|
if (Grid == null)
|
||||||
|
{
|
||||||
Logger.Error($"Created a pipe network without an associated grid. Pipe networks currently need to be tied to a grid for amtos to work. Source entity: {entMan.ToPrettyString(sourceNode.Owner)}");
|
Logger.Error($"Created a pipe network without an associated grid. Pipe networks currently need to be tied to a grid for amtos to work. Source entity: {entMan.ToPrettyString(sourceNode.Owner)}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_atmosphereSystem = entMan.EntitySysManager.GetEntitySystem<AtmosphereSystem>();
|
_atmosphereSystem = entMan.EntitySysManager.GetEntitySystem<AtmosphereSystem>();
|
||||||
_atmosphereSystem.AddPipeNet(this);
|
_atmosphereSystem.AddPipeNet(Grid.Value, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
@@ -85,7 +88,11 @@ namespace Content.Server.NodeContainer.NodeGroups
|
|||||||
private void RemoveFromGridAtmos()
|
private void RemoveFromGridAtmos()
|
||||||
{
|
{
|
||||||
DebugTools.AssertNotNull(_atmosphereSystem);
|
DebugTools.AssertNotNull(_atmosphereSystem);
|
||||||
_atmosphereSystem?.RemovePipeNet(this);
|
|
||||||
|
if (Grid == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_atmosphereSystem?.RemovePipeNet(Grid.Value, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string GetDebugData()
|
public override string GetDebugData()
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using Content.Shared.FixedPoint;
|
|||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
using Content.Shared.Smoking;
|
using Content.Shared.Smoking;
|
||||||
using Content.Shared.Temperature;
|
using Content.Shared.Temperature;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
|
|
||||||
namespace Content.Server.Nutrition.EntitySystems
|
namespace Content.Server.Nutrition.EntitySystems
|
||||||
@@ -21,8 +22,8 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||||
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
||||||
[Dependency] private readonly AtmosphereSystem _atmos = default!;
|
[Dependency] private readonly AtmosphereSystem _atmos = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||||
|
|
||||||
private const float UpdateTimer = 3f;
|
private const float UpdateTimer = 3f;
|
||||||
|
|
||||||
private float _timer = 0f;
|
private float _timer = 0f;
|
||||||
@@ -79,6 +80,7 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
if (_timer < UpdateTimer)
|
if (_timer < UpdateTimer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// TODO Use an "active smoke" component instead, EntityQuery over that.
|
||||||
foreach (var uid in _active.ToArray())
|
foreach (var uid in _active.ToArray())
|
||||||
{
|
{
|
||||||
if (!TryComp(uid, out SmokableComponent? smokable))
|
if (!TryComp(uid, out SmokableComponent? smokable))
|
||||||
@@ -96,7 +98,12 @@ namespace Content.Server.Nutrition.EntitySystems
|
|||||||
if (smokable.ExposeTemperature > 0 && smokable.ExposeVolume > 0)
|
if (smokable.ExposeTemperature > 0 && smokable.ExposeVolume > 0)
|
||||||
{
|
{
|
||||||
var transform = Transform(uid);
|
var transform = Transform(uid);
|
||||||
_atmos.HotspotExpose(transform.Coordinates, smokable.ExposeTemperature, smokable.ExposeVolume, true);
|
|
||||||
|
if (transform.GridUid is {} gridUid)
|
||||||
|
{
|
||||||
|
var position = _transformSystem.GetGridOrMapTilePosition(uid, transform);
|
||||||
|
_atmos.HotspotExpose(gridUid, position, smokable.ExposeTemperature, smokable.ExposeVolume, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var inhaledSolution = _solutionContainerSystem.SplitSolution(uid, solution, smokable.InhaleAmount * _timer);
|
var inhaledSolution = _solutionContainerSystem.SplitSolution(uid, solution, smokable.InhaleAmount * _timer);
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ namespace Content.Server.PneumaticCannon
|
|||||||
{
|
{
|
||||||
// we checked for this earlier in HasGas so a GetComp is okay
|
// we checked for this earlier in HasGas so a GetComp is okay
|
||||||
var gas = EntityManager.GetComponent<GasTankComponent>(contained);
|
var gas = EntityManager.GetComponent<GasTankComponent>(contained);
|
||||||
var environment = _atmos.GetTileMixture(EntityManager.GetComponent<TransformComponent>(comp.Owner).Coordinates, true);
|
var environment = _atmos.GetContainingMixture(comp.Owner, false, true);
|
||||||
var removed = gas.RemoveAir(GetMoleUsageFromPower(comp.Power));
|
var removed = gas.RemoveAir(GetMoleUsageFromPower(comp.Power));
|
||||||
if (environment != null && removed != null)
|
if (environment != null && removed != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Content.Server.Nutrition.Components;
|
|||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
|
|
||||||
namespace Content.Server.RatKing
|
namespace Content.Server.RatKing
|
||||||
@@ -17,6 +18,7 @@ namespace Content.Server.RatKing
|
|||||||
[Dependency] private readonly DiseaseSystem _disease = default!;
|
[Dependency] private readonly DiseaseSystem _disease = default!;
|
||||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||||
[Dependency] private readonly AtmosphereSystem _atmos = default!;
|
[Dependency] private readonly AtmosphereSystem _atmos = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _xform = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -79,9 +81,10 @@ namespace Content.Server.RatKing
|
|||||||
|
|
||||||
_popup.PopupEntity(Loc.GetString("rat-king-domain-popup"), uid, Filter.Pvs(uid));
|
_popup.PopupEntity(Loc.GetString("rat-king-domain-popup"), uid, Filter.Pvs(uid));
|
||||||
|
|
||||||
var tileMix = _atmos.GetTileMixture(Transform(uid).Coordinates);
|
var transform = Transform(uid);
|
||||||
if (tileMix != null)
|
var indices = _xform.GetGridOrMapTilePosition(uid, transform);
|
||||||
tileMix.AdjustMoles(Gas.Miasma, component.MolesMiasmaPerDomain);
|
var tileMix = _atmos.GetTileMixture(transform.GridUid, transform.MapUid, indices, true);
|
||||||
|
tileMix?.AdjustMoles(Gas.Miasma, component.MolesMiasmaPerDomain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ namespace Content.Server.StationEvents.Events
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var environment = atmosphereSystem.GetTileMixture(_targetGrid, _targetTile, true);
|
var environment = atmosphereSystem.GetTileMixture(_targetGrid, null, _targetTile, true);
|
||||||
|
|
||||||
environment?.AdjustMoles(_leakGas, LeakCooldown * _molesPerSecond);
|
environment?.AdjustMoles(_leakGas, LeakCooldown * _molesPerSecond);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,7 +227,8 @@ namespace Content.Server.StationEvents.Events
|
|||||||
|
|
||||||
targetGrid = robustRandom.Pick(possibleTargets);
|
targetGrid = robustRandom.Pick(possibleTargets);
|
||||||
|
|
||||||
if (!entityManager.TryGetComponent<IMapGridComponent>(targetGrid, out var gridComp))
|
if (!entityManager.TryGetComponent<IMapGridComponent>(targetGrid, out var gridComp)
|
||||||
|
|| !entityManager.TryGetComponent<TransformComponent>(targetGrid, out var transform))
|
||||||
return false;
|
return false;
|
||||||
var grid = gridComp.Grid;
|
var grid = gridComp.Grid;
|
||||||
|
|
||||||
@@ -242,7 +243,9 @@ namespace Content.Server.StationEvents.Events
|
|||||||
var randomY = robustRandom.Next((int) gridBounds.Bottom, (int) gridBounds.Top);
|
var randomY = robustRandom.Next((int) gridBounds.Bottom, (int) gridBounds.Top);
|
||||||
|
|
||||||
tile = new Vector2i(randomX - (int) gridPos.X, randomY - (int) gridPos.Y);
|
tile = new Vector2i(randomX - (int) gridPos.X, randomY - (int) gridPos.Y);
|
||||||
if (atmosphereSystem.IsTileSpace(grid, tile) || atmosphereSystem.IsTileAirBlocked(grid, tile)) continue;
|
if (atmosphereSystem.IsTileSpace(grid.GridEntityId, transform.MapUid, tile, mapGridComp:gridComp)
|
||||||
|
|| atmosphereSystem.IsTileAirBlocked(grid.GridEntityId, tile, mapGridComp:gridComp))
|
||||||
|
continue;
|
||||||
found = true;
|
found = true;
|
||||||
targetCoords = grid.GridTileToLocal(tile);
|
targetCoords = grid.GridTileToLocal(tile);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Atmos.Components;
|
using Content.Server.Atmos.Components;
|
||||||
@@ -7,11 +9,15 @@ using Content.Shared.Alert;
|
|||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.Inventory;
|
using Content.Shared.Inventory;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
using Robust.Shared.IoC;
|
||||||
|
|
||||||
namespace Content.Server.Temperature.Systems
|
namespace Content.Server.Temperature.Systems
|
||||||
{
|
{
|
||||||
public sealed class TemperatureSystem : EntitySystem
|
public sealed class TemperatureSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
|
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
|
||||||
@@ -94,8 +100,15 @@ namespace Content.Server.Temperature.Systems
|
|||||||
|
|
||||||
private void OnAtmosExposedUpdate(EntityUid uid, TemperatureComponent temperature, ref AtmosExposedUpdateEvent args)
|
private void OnAtmosExposedUpdate(EntityUid uid, TemperatureComponent temperature, ref AtmosExposedUpdateEvent args)
|
||||||
{
|
{
|
||||||
|
var transform = args.Transform;
|
||||||
|
|
||||||
|
if (transform.MapUid == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var position = _transformSystem.GetGridOrMapTilePosition(uid, transform);
|
||||||
|
|
||||||
var temperatureDelta = args.GasMixture.Temperature - temperature.CurrentTemperature;
|
var temperatureDelta = args.GasMixture.Temperature - temperature.CurrentTemperature;
|
||||||
var tileHeatCapacity = _atmosphereSystem.GetTileHeatCapacity(args.Coordinates);
|
var tileHeatCapacity = _atmosphereSystem.GetTileHeatCapacity(transform.GridUid, transform.MapUid.Value, position);
|
||||||
var heat = temperatureDelta * (tileHeatCapacity * temperature.HeatCapacity / (tileHeatCapacity + temperature.HeatCapacity));
|
var heat = temperatureDelta * (tileHeatCapacity * temperature.HeatCapacity / (tileHeatCapacity + temperature.HeatCapacity));
|
||||||
ChangeHeat(uid, heat * temperature.AtmosTemperatureTransferEfficiency, temperature: temperature );
|
ChangeHeat(uid, heat * temperature.AtmosTemperatureTransferEfficiency, temperature: temperature );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,9 +78,10 @@ namespace Content.Server.Tools
|
|||||||
SolutionContainerManagerComponent? solutionContainer = null,
|
SolutionContainerManagerComponent? solutionContainer = null,
|
||||||
SharedItemComponent? item = null,
|
SharedItemComponent? item = null,
|
||||||
PointLightComponent? light = null,
|
PointLightComponent? light = null,
|
||||||
AppearanceComponent? appearance = null)
|
AppearanceComponent? appearance = null,
|
||||||
|
TransformComponent? transform = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref welder, ref solutionContainer))
|
if (!Resolve(uid, ref welder, ref solutionContainer, ref transform))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Optional components.
|
// Optional components.
|
||||||
@@ -113,8 +114,11 @@ namespace Content.Server.Tools
|
|||||||
|
|
||||||
SoundSystem.Play(welder.WelderOnSounds.GetSound(), Filter.Pvs(uid), uid, AudioHelpers.WithVariation(0.125f).WithVolume(-5f));
|
SoundSystem.Play(welder.WelderOnSounds.GetSound(), Filter.Pvs(uid), uid, AudioHelpers.WithVariation(0.125f).WithVolume(-5f));
|
||||||
|
|
||||||
// TODO: Use TransformComponent directly.
|
if (transform.GridUid is {} gridUid)
|
||||||
_atmosphereSystem.HotspotExpose(EntityManager.GetComponent<TransformComponent>(welder.Owner).Coordinates, 700, 50, true);
|
{
|
||||||
|
var position = _transformSystem.GetGridOrMapTilePosition(uid, transform);
|
||||||
|
_atmosphereSystem.HotspotExpose(gridUid, position, 700, 50, true);
|
||||||
|
}
|
||||||
|
|
||||||
welder.Dirty();
|
welder.Dirty();
|
||||||
|
|
||||||
@@ -300,17 +304,22 @@ namespace Content.Server.Tools
|
|||||||
if (_welderTimer < WelderUpdateTimer)
|
if (_welderTimer < WelderUpdateTimer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// TODO Use an "active welder" component instead, EntityQuery over that.
|
||||||
foreach (var tool in _activeWelders.ToArray())
|
foreach (var tool in _activeWelders.ToArray())
|
||||||
{
|
{
|
||||||
if (!EntityManager.TryGetComponent(tool, out WelderComponent? welder)
|
if (!EntityManager.TryGetComponent(tool, out WelderComponent? welder)
|
||||||
|| !EntityManager.TryGetComponent(tool, out SolutionContainerManagerComponent? solutionContainer))
|
|| !EntityManager.TryGetComponent(tool, out SolutionContainerManagerComponent? solutionContainer)
|
||||||
|
|| !EntityManager.TryGetComponent(tool, out TransformComponent? transform))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!_solutionContainerSystem.TryGetSolution(tool, welder.FuelSolution, out var solution, solutionContainer))
|
if (!_solutionContainerSystem.TryGetSolution(tool, welder.FuelSolution, out var solution, solutionContainer))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// TODO: Use TransformComponent directly.
|
if (transform.GridUid is { } gridUid)
|
||||||
_atmosphereSystem.HotspotExpose(EntityManager.GetComponent<TransformComponent>(welder.Owner).Coordinates, 700, 50, true);
|
{
|
||||||
|
var position = _transformSystem.GetGridOrMapTilePosition(tool, transform);
|
||||||
|
_atmosphereSystem.HotspotExpose(gridUid, position, 700, 50, true);
|
||||||
|
}
|
||||||
|
|
||||||
solution.RemoveReagent(welder.FuelReagent, welder.FuelConsumption * _welderTimer);
|
solution.RemoveReagent(welder.FuelReagent, welder.FuelConsumption * _welderTimer);
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Content.Server.DoAfter;
|
|||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.Tools.Components;
|
using Content.Shared.Tools.Components;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
@@ -23,6 +24,7 @@ namespace Content.Server.Tools
|
|||||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public sealed class GasArtifactSystem : EntitySystem
|
|||||||
|
|
||||||
var transform = Transform(uid);
|
var transform = Transform(uid);
|
||||||
|
|
||||||
var environment = _atmosphereSystem.GetTileMixture(transform.Coordinates, true);
|
var environment = _atmosphereSystem.GetContainingMixture(uid, false, true);
|
||||||
if (environment == null)
|
if (environment == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,14 @@
|
|||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components;
|
||||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
|
||||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
|
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Systems;
|
||||||
|
|
||||||
public sealed class TemperatureArtifactSystem : EntitySystem
|
public sealed class TemperatureArtifactSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -19,14 +21,16 @@ public sealed class TemperatureArtifactSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
var transform = Transform(uid);
|
var transform = Transform(uid);
|
||||||
|
|
||||||
var center = _atmosphereSystem.GetTileMixture(transform.Coordinates, true);
|
var center = _atmosphereSystem.GetContainingMixture(uid, false, true);
|
||||||
if (center == null)
|
if (center == null)
|
||||||
return;
|
return;
|
||||||
UpdateTileTemperature(component, center);
|
UpdateTileTemperature(component, center);
|
||||||
|
|
||||||
if (component.EffectAdjacentTiles)
|
if (component.EffectAdjacentTiles && transform.GridUid != null)
|
||||||
{
|
{
|
||||||
var adjacent = _atmosphereSystem.GetAdjacentTileMixtures(transform.Coordinates, invalidate: true);
|
var adjacent = _atmosphereSystem.GetAdjacentTileMixtures(transform.GridUid.Value,
|
||||||
|
_transformSystem.GetGridOrMapTilePosition(uid, transform), excite: true);
|
||||||
|
|
||||||
foreach (var mixture in adjacent)
|
foreach (var mixture in adjacent)
|
||||||
{
|
{
|
||||||
UpdateTileTemperature(component, mixture);
|
UpdateTileTemperature(component, mixture);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
|
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems;
|
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems;
|
||||||
@@ -10,6 +11,7 @@ public sealed class ArtifactGasTriggerSystem : EntitySystem
|
|||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
[Dependency] private readonly ArtifactSystem _artifactSystem = default!;
|
[Dependency] private readonly ArtifactSystem _artifactSystem = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -32,10 +34,14 @@ public sealed class ArtifactGasTriggerSystem : EntitySystem
|
|||||||
var query = EntityManager.EntityQuery<ArtifactGasTriggerComponent, TransformComponent>();
|
var query = EntityManager.EntityQuery<ArtifactGasTriggerComponent, TransformComponent>();
|
||||||
foreach (var (trigger, transform) in query)
|
foreach (var (trigger, transform) in query)
|
||||||
{
|
{
|
||||||
|
var uid = trigger.Owner;
|
||||||
|
|
||||||
if (trigger.ActivationGas == null)
|
if (trigger.ActivationGas == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var environment = _atmosphereSystem.GetTileMixture(transform.Coordinates);
|
var environment = _atmosphereSystem.GetTileMixture(transform.GridUid, transform.MapUid,
|
||||||
|
_transformSystem.GetGridOrMapTilePosition(uid, transform));
|
||||||
|
|
||||||
if (environment == null)
|
if (environment == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
|
|||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Temperature;
|
using Content.Shared.Temperature;
|
||||||
using Content.Shared.Weapons.Melee;
|
using Content.Shared.Weapons.Melee;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
|
||||||
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems;
|
namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems;
|
||||||
|
|
||||||
@@ -10,6 +11,7 @@ public sealed class ArtifactHeatTriggerSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
[Dependency] private readonly ArtifactSystem _artifactSystem = default!;
|
[Dependency] private readonly ArtifactSystem _artifactSystem = default!;
|
||||||
|
[Dependency] private readonly TransformSystem _transformSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -25,7 +27,9 @@ public sealed class ArtifactHeatTriggerSystem : EntitySystem
|
|||||||
var query = EntityManager.EntityQuery<ArtifactHeatTriggerComponent, TransformComponent, ArtifactComponent>();
|
var query = EntityManager.EntityQuery<ArtifactHeatTriggerComponent, TransformComponent, ArtifactComponent>();
|
||||||
foreach (var (trigger, transform, artifact) in query)
|
foreach (var (trigger, transform, artifact) in query)
|
||||||
{
|
{
|
||||||
var environment = _atmosphereSystem.GetTileMixture(transform.Coordinates);
|
var uid = trigger.Owner;
|
||||||
|
var environment = _atmosphereSystem.GetTileMixture(transform.GridUid, transform.MapUid,
|
||||||
|
_transformSystem.GetGridOrMapTilePosition(uid, transform));
|
||||||
if (environment == null)
|
if (environment == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ namespace Content.Shared.Atmos.EntitySystems
|
|||||||
public readonly float[] Moles;
|
public readonly float[] Moles;
|
||||||
public readonly AtmosDirection PressureDirection;
|
public readonly AtmosDirection PressureDirection;
|
||||||
public readonly AtmosDirection LastPressureDirection;
|
public readonly AtmosDirection LastPressureDirection;
|
||||||
public readonly bool InExcitedGroup;
|
public readonly int InExcitedGroup;
|
||||||
public readonly AtmosDirection BlockDirection;
|
public readonly AtmosDirection BlockDirection;
|
||||||
|
public readonly bool IsSpace;
|
||||||
|
|
||||||
public AtmosDebugOverlayData(float temperature, float[] moles, AtmosDirection pressureDirection, AtmosDirection lastPressureDirection, bool inExcited, AtmosDirection blockDirection)
|
public AtmosDebugOverlayData(float temperature, float[] moles, AtmosDirection pressureDirection, AtmosDirection lastPressureDirection, int inExcited, AtmosDirection blockDirection, bool isSpace)
|
||||||
{
|
{
|
||||||
Temperature = temperature;
|
Temperature = temperature;
|
||||||
Moles = moles;
|
Moles = moles;
|
||||||
@@ -27,6 +28,7 @@ namespace Content.Shared.Atmos.EntitySystems
|
|||||||
LastPressureDirection = lastPressureDirection;
|
LastPressureDirection = lastPressureDirection;
|
||||||
InExcitedGroup = inExcited;
|
InExcitedGroup = inExcited;
|
||||||
BlockDirection = blockDirection;
|
BlockDirection = blockDirection;
|
||||||
|
IsSpace = isSpace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -524,6 +524,7 @@ public sealed class $CLASS$ : Shared$CLASS$ {
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Protolathe/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Protolathe/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pullable/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pullable/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Reparenting/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Reparenting/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=roundstart/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ruinable/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ruinable/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=saltern/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=saltern/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=sandboxing/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=sandboxing/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
Reference in New Issue
Block a user