Merge branch 'master' into 2020-08-19-firelocks
# Conflicts: # Content.Server/GameObjects/Components/Atmos/AirtightComponent.cs # Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs # SpaceStation14.sln.DotSettings
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components.Transform;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
@@ -13,7 +16,8 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
[RegisterComponent]
|
||||
public class AirtightComponent : Component, IMapInit
|
||||
{
|
||||
private SnapGridComponent _snapGrid;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
|
||||
private (GridId, MapIndices) _lastPosition;
|
||||
|
||||
public override string Name => "Airtight";
|
||||
@@ -28,7 +32,11 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
set
|
||||
{
|
||||
_airBlocked = value;
|
||||
EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(Owner.Transform.GridID)?.Revalidate(_snapGrid.Position);
|
||||
|
||||
if (Owner.TryGetComponent(out SnapGridComponent? snapGrid))
|
||||
{
|
||||
EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(Owner.Transform.GridID)?.Invalidate(snapGrid.Position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,19 +56,23 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
base.Initialize();
|
||||
|
||||
// Using the SnapGrid is critical for the performance of the room builder, and thus if
|
||||
// it is absent the component will not be airtight. An exception is much easier to track
|
||||
// down than the object magically not being airtight, so throw one if the SnapGrid component
|
||||
// it is absent the component will not be airtight. A warning is much easier to track
|
||||
// down than the object magically not being airtight, so log one if the SnapGrid component
|
||||
// is missing.
|
||||
if (!Owner.TryGetComponent(out _snapGrid))
|
||||
throw new Exception("Airtight entities must have a SnapGrid component");
|
||||
if (!Owner.EnsureComponent(out SnapGridComponent _))
|
||||
Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition.ToString()} didn't have a {nameof(SnapGridComponent)}");
|
||||
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
public void MapInit()
|
||||
{
|
||||
_snapGrid.OnPositionChanged += OnTransformMove;
|
||||
_lastPosition = (Owner.Transform.GridID, _snapGrid.Position);
|
||||
if (Owner.TryGetComponent(out SnapGridComponent? snapGrid))
|
||||
{
|
||||
snapGrid.OnPositionChanged += OnTransformMove;
|
||||
_lastPosition = (Owner.Transform.GridID, snapGrid.Position);
|
||||
}
|
||||
|
||||
UpdatePosition();
|
||||
}
|
||||
|
||||
@@ -70,11 +82,16 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
_airBlocked = false;
|
||||
|
||||
_snapGrid.OnPositionChanged -= OnTransformMove;
|
||||
if (Owner.TryGetComponent(out SnapGridComponent? snapGrid))
|
||||
{
|
||||
snapGrid.OnPositionChanged -= OnTransformMove;
|
||||
}
|
||||
|
||||
if(_fixVacuum)
|
||||
EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(Owner.Transform.GridID)?
|
||||
.FixVacuum(_snapGrid.Position);
|
||||
if (_fixVacuum)
|
||||
{
|
||||
var mapIndices = Owner.Transform.GridPosition.ToMapIndices(_mapManager);
|
||||
EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(Owner.Transform.GridID)?.FixVacuum(mapIndices);
|
||||
}
|
||||
|
||||
UpdatePosition();
|
||||
}
|
||||
@@ -83,15 +100,22 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
{
|
||||
UpdatePosition(_lastPosition.Item1, _lastPosition.Item2);
|
||||
UpdatePosition();
|
||||
_lastPosition = (Owner.Transform.GridID, _snapGrid.Position);
|
||||
|
||||
if (Owner.TryGetComponent(out SnapGridComponent? snapGrid))
|
||||
{
|
||||
_lastPosition = (Owner.Transform.GridID, snapGrid.Position);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePosition() => UpdatePosition(Owner.Transform.GridID, _snapGrid.Position);
|
||||
private void UpdatePosition()
|
||||
{
|
||||
var mapIndices = Owner.Transform.GridPosition.ToMapIndices(_mapManager);
|
||||
UpdatePosition(Owner.Transform.GridID, mapIndices);
|
||||
}
|
||||
|
||||
private void UpdatePosition(GridId gridId, MapIndices pos)
|
||||
{
|
||||
EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(gridId)?.Invalidate(pos);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Server.Interfaces;
|
||||
using Content.Server.Interfaces.GameObjects.Components.Items;
|
||||
using Content.Server.Utility;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.GameObjects.Components;
|
||||
using Content.Shared.GameObjects.EntitySystems;
|
||||
@@ -16,30 +17,32 @@ using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Atmos
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class GasAnalyzerComponent : SharedGasAnalyzerComponent, IAfterInteract, IDropped, IUse
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private IMapManager _mapManager = default!;
|
||||
#pragma warning restore 649
|
||||
[Dependency] private readonly IServerNotifyManager _notifyManager = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
|
||||
private BoundUserInterface _userInterface = default!;
|
||||
private GasAnalyzerDanger _pressureDanger;
|
||||
private float _timeSinceSync;
|
||||
private const float TimeBetweenSyncs = 2f;
|
||||
private bool _checkPlayer = false; // Check at the player pos or at some other tile?
|
||||
private GridCoordinates? _position; // The tile that we scanned
|
||||
|
||||
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(GasAnalyzerUiKey.Key);
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_userInterface = Owner.GetComponent<ServerUserInterfaceComponent>()
|
||||
.GetBoundUserInterface(GasAnalyzerUiKey.Key);
|
||||
_userInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
|
||||
if (UserInterface != null)
|
||||
{
|
||||
UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
|
||||
}
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
@@ -56,7 +59,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
{
|
||||
_checkPlayer = true;
|
||||
_position = null;
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
UpdateUserInterface();
|
||||
Resync();
|
||||
}
|
||||
@@ -71,7 +74,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
{
|
||||
_checkPlayer = false;
|
||||
_position = pos;
|
||||
_userInterface.Open(session);
|
||||
UserInterface?.Open(session);
|
||||
UpdateUserInterface();
|
||||
Resync();
|
||||
}
|
||||
@@ -79,7 +82,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
public void CloseInterface(IPlayerSession session)
|
||||
{
|
||||
_position = null;
|
||||
_userInterface.Close(session);
|
||||
UserInterface?.Close(session);
|
||||
Resync();
|
||||
}
|
||||
|
||||
@@ -123,10 +126,15 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
private void UpdateUserInterface()
|
||||
{
|
||||
if (UserInterface == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string? error = null;
|
||||
|
||||
// Check if the player is still holding the gas analyzer => if not, don't update
|
||||
foreach (var session in _userInterface.SubscribedSessions)
|
||||
foreach (var session in UserInterface.SubscribedSessions)
|
||||
{
|
||||
if (session.AttachedEntity == null)
|
||||
return;
|
||||
@@ -151,12 +159,13 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
pos = _position.Value;
|
||||
}
|
||||
|
||||
var gam = EntitySystem.Get<AtmosphereSystem>().GetGridAtmosphere(pos.GridID);
|
||||
var atmosSystem = EntitySystem.Get<AtmosphereSystem>();
|
||||
var gam = atmosSystem.GetGridAtmosphere(pos.GridID);
|
||||
var tile = gam?.GetTile(pos).Air;
|
||||
if (tile == null)
|
||||
{
|
||||
error = "No Atmosphere!";
|
||||
_userInterface.SetState(
|
||||
UserInterface.SetState(
|
||||
new GasAnalyzerBoundUserInterfaceState(
|
||||
0,
|
||||
0,
|
||||
@@ -166,16 +175,17 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
}
|
||||
|
||||
var gases = new List<GasEntry>();
|
||||
for (int i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||
|
||||
for (var i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||
{
|
||||
var gas = Atmospherics.GetGas(i);
|
||||
var gas = atmosSystem.GetGas(i);
|
||||
|
||||
if (tile.Gases[i] <= Atmospherics.GasMinMoles) continue;
|
||||
|
||||
gases.Add(new GasEntry(gas.Name, tile.Gases[i], gas.Color));
|
||||
}
|
||||
|
||||
_userInterface.SetState(
|
||||
UserInterface.SetState(
|
||||
new GasAnalyzerBoundUserInterfaceState(
|
||||
tile.Pressure,
|
||||
tile.Temperature,
|
||||
|
||||
@@ -6,16 +6,23 @@ using Robust.Shared.ViewVariables;
|
||||
namespace Content.Server.GameObjects.Components.Atmos
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class GasMixtureComponent : Component
|
||||
public class GasMixtureHolderComponent : Component
|
||||
{
|
||||
public override string Name => "GasMixture";
|
||||
public override string Name => "GasMixtureHolder";
|
||||
|
||||
[ViewVariables] public GasMixture GasMixture { get; set; } = new GasMixture();
|
||||
[ViewVariables] public GasMixture GasMixture { get; set; }
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
serializer.DataField(this, x => GasMixture.Volume, "volume", 0f);
|
||||
|
||||
GasMixture = new GasMixture();
|
||||
|
||||
serializer.DataReadWriteFunction(
|
||||
"volume",
|
||||
0f,
|
||||
vol => GasMixture.Volume = vol,
|
||||
() => GasMixture.Volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Content.Server.Atmos;
|
||||
using Content.Server.GameObjects.Components.Atmos.Piping;
|
||||
using Content.Server.GameObjects.Components.NodeContainer.NodeGroups;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Maps;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
@@ -33,7 +36,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
/// <summary>
|
||||
/// Check current execution time every n instances processed.
|
||||
/// </summary>
|
||||
private const int LagCheckIterations = 15;
|
||||
private const int LagCheckIterations = 30;
|
||||
|
||||
/// <summary>
|
||||
/// Max milliseconds allowed for atmos updates.
|
||||
@@ -47,32 +50,94 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
public override string Name => "GridAtmosphere";
|
||||
|
||||
private bool _paused = false;
|
||||
private float _timer = 0f;
|
||||
private Stopwatch _stopwatch = new Stopwatch();
|
||||
|
||||
[ViewVariables]
|
||||
public int UpdateCounter { get; private set; } = 0;
|
||||
private IMapGrid _grid;
|
||||
|
||||
[ViewVariables]
|
||||
private double _tileEqualizeLastProcess;
|
||||
|
||||
[ViewVariables]
|
||||
private readonly HashSet<ExcitedGroup> _excitedGroups = new HashSet<ExcitedGroup>(1000);
|
||||
|
||||
[ViewVariables]
|
||||
private int ExcitedGroupCount => _excitedGroups.Count;
|
||||
|
||||
[ViewVariables]
|
||||
private double _excitedGroupLastProcess;
|
||||
|
||||
[ViewVariables]
|
||||
private readonly Dictionary<MapIndices, TileAtmosphere> _tiles = new Dictionary<MapIndices, TileAtmosphere>(1000);
|
||||
|
||||
[ViewVariables]
|
||||
private readonly HashSet<TileAtmosphere> _activeTiles = new HashSet<TileAtmosphere>(1000);
|
||||
|
||||
[ViewVariables]
|
||||
private int ActiveTilesCount => _activeTiles.Count;
|
||||
|
||||
[ViewVariables]
|
||||
private double _activeTilesLastProcess;
|
||||
|
||||
[ViewVariables]
|
||||
private readonly HashSet<TileAtmosphere> _hotspotTiles = new HashSet<TileAtmosphere>(1000);
|
||||
|
||||
[ViewVariables]
|
||||
private int HotspotTilesCount => _hotspotTiles.Count;
|
||||
|
||||
[ViewVariables]
|
||||
private double _hotspotsLastProcess;
|
||||
|
||||
[ViewVariables]
|
||||
private readonly HashSet<TileAtmosphere> _superconductivityTiles = new HashSet<TileAtmosphere>(1000);
|
||||
|
||||
[ViewVariables]
|
||||
private int SuperconductivityTilesCount => _superconductivityTiles.Count;
|
||||
|
||||
[ViewVariables]
|
||||
private double _superconductivityLastProcess;
|
||||
|
||||
[ViewVariables]
|
||||
private readonly HashSet<MapIndices> _invalidatedCoords = new HashSet<MapIndices>(1000);
|
||||
|
||||
[ViewVariables]
|
||||
private int InvalidatedCoordsCount => _invalidatedCoords.Count;
|
||||
|
||||
[ViewVariables]
|
||||
private HashSet<TileAtmosphere> _highPressureDelta = new HashSet<TileAtmosphere>(1000);
|
||||
|
||||
[ViewVariables]
|
||||
private int HighPressureDeltaCount => _highPressureDelta.Count;
|
||||
|
||||
[ViewVariables]
|
||||
private double _highPressureDeltaLastProcess;
|
||||
|
||||
[ViewVariables]
|
||||
private readonly HashSet<IPipeNet> _pipeNets = new HashSet<IPipeNet>();
|
||||
|
||||
[ViewVariables]
|
||||
private double _pipeNetLastProcess;
|
||||
|
||||
[ViewVariables]
|
||||
private readonly HashSet<PipeNetDeviceComponent> _pipeNetDevices = new HashSet<PipeNetDeviceComponent>();
|
||||
|
||||
[ViewVariables]
|
||||
private double _pipeNetDevicesLastProcess;
|
||||
|
||||
[ViewVariables]
|
||||
private Queue<TileAtmosphere> _currentRunTiles = new Queue<TileAtmosphere>();
|
||||
|
||||
[ViewVariables]
|
||||
private Queue<ExcitedGroup> _currentRunExcitedGroups = new Queue<ExcitedGroup>();
|
||||
|
||||
[ViewVariables]
|
||||
private Queue<IPipeNet> _currentRunPipeNet = new Queue<IPipeNet>();
|
||||
|
||||
[ViewVariables]
|
||||
private Queue<PipeNetDeviceComponent> _currentRunPipeNetDevice = new Queue<PipeNetDeviceComponent>();
|
||||
|
||||
[ViewVariables]
|
||||
private ProcessState _state = ProcessState.TileEqualize;
|
||||
|
||||
@@ -84,47 +149,47 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
HighPressureDelta,
|
||||
Hotspots,
|
||||
Superconductivity,
|
||||
PipeNet,
|
||||
PipeNetDevices,
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void PryTile(MapIndices indices)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGridComponent)) return;
|
||||
if (IsSpace(indices) || IsAirBlocked(indices)) return;
|
||||
|
||||
var tile = _grid.GetTileRef(indices).Tile;
|
||||
var mapGrid = mapGridComponent.Grid;
|
||||
var tile = mapGrid.GetTileRef(indices).Tile;
|
||||
|
||||
var tileDefinitionManager = IoCManager.Resolve<ITileDefinitionManager>();
|
||||
var tileDef = (ContentTileDefinition)tileDefinitionManager[tile.TypeId];
|
||||
|
||||
var underplating = tileDefinitionManager["underplating"];
|
||||
_grid.SetTile(indices, new Tile(underplating.TileId));
|
||||
mapGrid.SetTile(indices, new Tile(underplating.TileId));
|
||||
|
||||
//Actually spawn the relevant tile item at the right position and give it some offset to the corner.
|
||||
var tileItem = IoCManager.Resolve<IServerEntityManager>().SpawnEntity(tileDef.ItemDropPrototypeName, new GridCoordinates(indices.X, indices.Y, _grid));
|
||||
var tileItem = IoCManager.Resolve<IServerEntityManager>().SpawnEntity(tileDef.ItemDropPrototypeName, new GridCoordinates(indices.X, indices.Y, mapGrid));
|
||||
tileItem.Transform.WorldPosition += (0.2f, 0.2f);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_grid = Owner.GetComponent<IMapGridComponent>().Grid;
|
||||
|
||||
RepopulateTiles();
|
||||
}
|
||||
|
||||
public override void OnAdd()
|
||||
{
|
||||
base.OnAdd();
|
||||
|
||||
_grid = Owner.GetComponent<IMapGridComponent>().Grid;
|
||||
|
||||
RepopulateTiles();
|
||||
}
|
||||
|
||||
public void RepopulateTiles()
|
||||
{
|
||||
foreach (var tile in _grid.GetAllTiles())
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
|
||||
foreach (var tile in mapGrid.Grid.GetAllTiles())
|
||||
{
|
||||
if(!_tiles.ContainsKey(tile.GridIndices))
|
||||
_tiles.Add(tile.GridIndices, new TileAtmosphere(this, tile.GridIndex, tile.GridIndices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C}));
|
||||
@@ -145,69 +210,66 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
private void Revalidate()
|
||||
{
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
|
||||
foreach (var indices in _invalidatedCoords.ToArray())
|
||||
{
|
||||
Revalidate(indices);
|
||||
var tile = GetTile(indices);
|
||||
AddActiveTile(tile);
|
||||
|
||||
if (tile == null)
|
||||
{
|
||||
tile = new TileAtmosphere(this, mapGrid.Grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C});
|
||||
_tiles[indices] = tile;
|
||||
}
|
||||
|
||||
if (IsSpace(indices))
|
||||
{
|
||||
tile.Air = new GasMixture(GetVolumeForCells(1));
|
||||
tile.Air.MarkImmutable();
|
||||
_tiles[indices] = tile;
|
||||
|
||||
} else if (IsAirBlocked(indices))
|
||||
{
|
||||
tile.Air = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var obs = GetObstructingComponent(indices);
|
||||
|
||||
if (obs != null)
|
||||
{
|
||||
if (tile.Air == null && obs.FixVacuum)
|
||||
{
|
||||
FixVacuum(tile.GridIndices);
|
||||
}
|
||||
}
|
||||
|
||||
tile.Air ??= new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C};
|
||||
}
|
||||
|
||||
tile.UpdateAdjacent();
|
||||
tile.UpdateVisuals();
|
||||
|
||||
for (var i = 0; i < Atmospherics.Directions; i++)
|
||||
{
|
||||
var direction = (AtmosDirection) (1 << i);
|
||||
var otherIndices = indices.Offset(direction.ToDirection());
|
||||
var otherTile = GetTile(otherIndices);
|
||||
AddActiveTile(otherTile);
|
||||
otherTile?.UpdateAdjacent(direction.GetOpposite());
|
||||
}
|
||||
}
|
||||
|
||||
_invalidatedCoords.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Revalidate(MapIndices indices)
|
||||
{
|
||||
var tile = GetTile(indices);
|
||||
AddActiveTile(tile);
|
||||
|
||||
if (tile == null)
|
||||
{
|
||||
tile = new TileAtmosphere(this, _grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C});
|
||||
_tiles[indices] = tile;
|
||||
}
|
||||
|
||||
if (IsSpace(indices))
|
||||
{
|
||||
tile.Air = new GasMixture(GetVolumeForCells(1));
|
||||
tile.Air.MarkImmutable();
|
||||
_tiles[indices] = tile;
|
||||
|
||||
} else if (IsAirBlocked(indices))
|
||||
{
|
||||
tile.Air = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var obs = GetObstructingComponent(indices);
|
||||
|
||||
if (obs != null)
|
||||
{
|
||||
if (tile.Air == null && obs.FixVacuum)
|
||||
{
|
||||
FixVacuum(tile.GridIndices);
|
||||
}
|
||||
}
|
||||
|
||||
tile.Air ??= new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C};
|
||||
}
|
||||
|
||||
tile.UpdateAdjacent();
|
||||
tile.UpdateVisuals();
|
||||
|
||||
foreach (var direction in Cardinal)
|
||||
{
|
||||
var otherIndices = indices.Offset(direction);
|
||||
var otherTile = GetTile(otherIndices);
|
||||
AddActiveTile(otherTile);
|
||||
otherTile?.UpdateAdjacent(direction.GetOpposite());
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void FixVacuum(MapIndices indices)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
var tile = GetTile(indices);
|
||||
if (tile?.GridIndex != _grid.Index) return;
|
||||
if (tile?.GridIndex != mapGrid.Grid.Index) return;
|
||||
var adjacent = GetAdjacentTiles(indices);
|
||||
tile.Air = new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.T20C};
|
||||
_tiles[indices] = tile;
|
||||
@@ -224,16 +286,17 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void AddActiveTile(TileAtmosphere tile)
|
||||
public void AddActiveTile(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile?.GridIndex != _grid.Index || tile?.Air == null) return;
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
if (tile?.GridIndex != mapGrid.Grid.Index || tile?.Air == null) return;
|
||||
tile.Excited = true;
|
||||
_activeTiles.Add(tile);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void RemoveActiveTile(TileAtmosphere tile)
|
||||
public void RemoveActiveTile(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile == null) return;
|
||||
_activeTiles.Remove(tile);
|
||||
@@ -243,27 +306,29 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void AddHotspotTile(TileAtmosphere tile)
|
||||
public void AddHotspotTile(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile?.GridIndex != _grid.Index || tile?.Air == null) return;
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
if (tile?.GridIndex != mapGrid.Grid.Index || tile?.Air == null) return;
|
||||
_hotspotTiles.Add(tile);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void RemoveHotspotTile(TileAtmosphere tile)
|
||||
public void RemoveHotspotTile(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile == null) return;
|
||||
_hotspotTiles.Remove(tile);
|
||||
}
|
||||
|
||||
public void AddSuperconductivityTile(TileAtmosphere tile)
|
||||
public void AddSuperconductivityTile(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile?.GridIndex != _grid.Index) return;
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
if (tile?.GridIndex != mapGrid.Grid.Index) return;
|
||||
_superconductivityTiles.Add(tile);
|
||||
}
|
||||
|
||||
public void RemoveSuperconductivityTile(TileAtmosphere tile)
|
||||
public void RemoveSuperconductivityTile(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile == null) return;
|
||||
_superconductivityTiles.Remove(tile);
|
||||
@@ -271,9 +336,10 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
/// <inheritdoc />
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void AddHighPressureDelta(TileAtmosphere tile)
|
||||
public void AddHighPressureDelta(TileAtmosphere? tile)
|
||||
{
|
||||
if (tile?.GridIndex != _grid.Index) return;
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return;
|
||||
if (tile?.GridIndex != mapGrid.Grid.Index) return;
|
||||
_highPressureDelta.Add(tile);
|
||||
}
|
||||
|
||||
@@ -298,23 +364,43 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
_excitedGroups.Remove(excitedGroup);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public TileAtmosphere GetTile(GridCoordinates coordinates)
|
||||
public void AddPipeNet(IPipeNet pipeNet)
|
||||
{
|
||||
return GetTile(coordinates.ToMapIndices(_mapManager));
|
||||
_pipeNets.Add(pipeNet);
|
||||
}
|
||||
|
||||
public void RemovePipeNet(IPipeNet pipeNet)
|
||||
{
|
||||
_pipeNets.Remove(pipeNet);
|
||||
}
|
||||
|
||||
public void AddPipeNetDevice(PipeNetDeviceComponent pipeNetDevice)
|
||||
{
|
||||
_pipeNetDevices.Add(pipeNetDevice);
|
||||
}
|
||||
|
||||
public void RemovePipeNetDevice(PipeNetDeviceComponent pipeNetDevice)
|
||||
{
|
||||
_pipeNetDevices.Remove(pipeNetDevice);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public TileAtmosphere GetTile(MapIndices indices)
|
||||
public TileAtmosphere? GetTile(GridCoordinates coordinates, bool createSpace = true)
|
||||
{
|
||||
return GetTile(coordinates.ToMapIndices(_mapManager), createSpace);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public TileAtmosphere? GetTile(MapIndices indices, bool createSpace = true)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return null;
|
||||
|
||||
if (_tiles.TryGetValue(indices, out var tile)) return tile;
|
||||
|
||||
// We don't have that tile!
|
||||
if (IsSpace(indices))
|
||||
if (IsSpace(indices) && createSpace)
|
||||
{
|
||||
var space = new TileAtmosphere(this, _grid.Index, indices, new GasMixture(int.MaxValue){Temperature = Atmospherics.TCMB});
|
||||
space.Air.MarkImmutable();
|
||||
return space;
|
||||
return new TileAtmosphere(this, mapGrid.Grid.Index, indices, new GasMixture(GetVolumeForCells(1)){Temperature = Atmospherics.TCMB}, true);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -331,32 +417,34 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
public bool IsSpace(MapIndices indices)
|
||||
{
|
||||
// TODO ATMOS use ContentTileDefinition to define in YAML whether or not a tile is considered space
|
||||
return _grid.GetTileRef(indices).Tile.IsEmpty;
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return default;
|
||||
|
||||
return mapGrid.Grid.GetTileRef(indices).Tile.IsEmpty;
|
||||
}
|
||||
|
||||
public Dictionary<Direction, TileAtmosphere> GetAdjacentTiles(MapIndices indices, bool includeAirBlocked = false)
|
||||
public Dictionary<AtmosDirection, TileAtmosphere> GetAdjacentTiles(MapIndices indices, bool includeAirBlocked = false)
|
||||
{
|
||||
var sides = new Dictionary<Direction, TileAtmosphere>();
|
||||
foreach (var dir in Cardinal)
|
||||
var sides = new Dictionary<AtmosDirection, TileAtmosphere>();
|
||||
for (var i = 0; i < Atmospherics.Directions; i++)
|
||||
{
|
||||
var side = indices.Offset(dir);
|
||||
var direction = (AtmosDirection) (1 << i);
|
||||
var side = indices.Offset(direction.ToDirection());
|
||||
var tile = GetTile(side);
|
||||
if(tile?.Air != null || includeAirBlocked)
|
||||
sides[dir] = tile;
|
||||
if (tile != null && (tile.Air != null || includeAirBlocked))
|
||||
sides[direction] = tile;
|
||||
}
|
||||
|
||||
return sides;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int HighPressureDeltaCount => _highPressureDelta.Count;
|
||||
|
||||
public long EqualizationQueueCycleControl { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public float GetVolumeForCells(int cellCount)
|
||||
{
|
||||
return _grid.TileSize * cellCount * Atmospherics.CellVolume;
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return default;
|
||||
|
||||
return mapGrid.Grid.TileSize * cellCount * Atmospherics.CellVolume;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -376,27 +464,83 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
switch (_state)
|
||||
{
|
||||
case ProcessState.TileEqualize:
|
||||
ProcessTileEqualize();
|
||||
if (!ProcessTileEqualize(_paused))
|
||||
{
|
||||
_paused = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_paused = false;
|
||||
_state = ProcessState.ActiveTiles;
|
||||
return;
|
||||
case ProcessState.ActiveTiles:
|
||||
ProcessActiveTiles();
|
||||
if (!ProcessActiveTiles(_paused))
|
||||
{
|
||||
_paused = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_paused = false;
|
||||
_state = ProcessState.ExcitedGroups;
|
||||
return;
|
||||
case ProcessState.ExcitedGroups:
|
||||
ProcessExcitedGroups();
|
||||
if (!ProcessExcitedGroups(_paused))
|
||||
{
|
||||
_paused = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_paused = false;
|
||||
_state = ProcessState.HighPressureDelta;
|
||||
return;
|
||||
case ProcessState.HighPressureDelta:
|
||||
ProcessHighPressureDelta();
|
||||
if (!ProcessHighPressureDelta(_paused))
|
||||
{
|
||||
_paused = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_paused = false;
|
||||
_state = ProcessState.Hotspots;
|
||||
break;
|
||||
case ProcessState.Hotspots:
|
||||
ProcessHotspots();
|
||||
if (!ProcessHotspots(_paused))
|
||||
{
|
||||
_paused = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_paused = false;
|
||||
_state = ProcessState.Superconductivity;
|
||||
break;
|
||||
case ProcessState.Superconductivity:
|
||||
ProcessSuperconductivity();
|
||||
if (!ProcessSuperconductivity(_paused))
|
||||
{
|
||||
_paused = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_paused = false;
|
||||
_state = ProcessState.PipeNet;
|
||||
break;
|
||||
case ProcessState.PipeNet:
|
||||
if (!ProcessPipeNets(_paused))
|
||||
{
|
||||
_paused = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_paused = false;
|
||||
_state = ProcessState.PipeNetDevices;
|
||||
break;
|
||||
case ProcessState.PipeNetDevices:
|
||||
if (!ProcessPipeNetDevices(_paused))
|
||||
{
|
||||
_paused = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_paused = false;
|
||||
_state = ProcessState.TileEqualize;
|
||||
break;
|
||||
}
|
||||
@@ -404,47 +548,71 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
UpdateCounter++;
|
||||
}
|
||||
|
||||
public void ProcessTileEqualize()
|
||||
public bool ProcessTileEqualize(bool resumed = false)
|
||||
{
|
||||
_stopwatch.Restart();
|
||||
|
||||
if(!resumed)
|
||||
_currentRunTiles = new Queue<TileAtmosphere>(_activeTiles);
|
||||
|
||||
var number = 0;
|
||||
foreach (var tile in _activeTiles.ToArray())
|
||||
while (_currentRunTiles.Count > 0)
|
||||
{
|
||||
var tile = _currentRunTiles.Dequeue();
|
||||
tile.EqualizePressureInZone(UpdateCounter);
|
||||
|
||||
if (number++ < LagCheckIterations) continue;
|
||||
number = 0;
|
||||
// Process the rest next time.
|
||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||
return;
|
||||
{
|
||||
_tileEqualizeLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_tileEqualizeLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ProcessActiveTiles()
|
||||
public bool ProcessActiveTiles(bool resumed = false)
|
||||
{
|
||||
_stopwatch.Restart();
|
||||
|
||||
if(!resumed)
|
||||
_currentRunTiles = new Queue<TileAtmosphere>(_activeTiles);
|
||||
|
||||
var number = 0;
|
||||
foreach (var tile in _activeTiles.ToArray())
|
||||
while (_currentRunTiles.Count > 0)
|
||||
{
|
||||
var tile = _currentRunTiles.Dequeue();
|
||||
tile.ProcessCell(UpdateCounter);
|
||||
|
||||
if (number++ < LagCheckIterations) continue;
|
||||
number = 0;
|
||||
// Process the rest next time.
|
||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||
return;
|
||||
{
|
||||
_activeTilesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_activeTilesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ProcessExcitedGroups()
|
||||
public bool ProcessExcitedGroups(bool resumed = false)
|
||||
{
|
||||
_stopwatch.Restart();
|
||||
|
||||
if(!resumed)
|
||||
_currentRunExcitedGroups = new Queue<ExcitedGroup>(_excitedGroups);
|
||||
|
||||
var number = 0;
|
||||
foreach (var excitedGroup in _excitedGroups.ToArray())
|
||||
while (_currentRunExcitedGroups.Count > 0)
|
||||
{
|
||||
var excitedGroup = _currentRunExcitedGroups.Dequeue();
|
||||
excitedGroup.BreakdownCooldown++;
|
||||
excitedGroup.DismantleCooldown++;
|
||||
|
||||
@@ -458,17 +626,27 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
number = 0;
|
||||
// Process the rest next time.
|
||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||
return;
|
||||
{
|
||||
_excitedGroupLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_excitedGroupLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ProcessHighPressureDelta()
|
||||
public bool ProcessHighPressureDelta(bool resumed = false)
|
||||
{
|
||||
_stopwatch.Restart();
|
||||
|
||||
if(!resumed)
|
||||
_currentRunTiles = new Queue<TileAtmosphere>(_highPressureDelta);
|
||||
|
||||
var number = 0;
|
||||
foreach (var tile in _highPressureDelta.ToArray())
|
||||
while (_currentRunTiles.Count > 0)
|
||||
{
|
||||
var tile = _currentRunTiles.Dequeue();
|
||||
tile.HighPressureMovements();
|
||||
tile.PressureDifference = 0f;
|
||||
tile.PressureSpecificTarget = null;
|
||||
@@ -478,47 +656,129 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
number = 0;
|
||||
// Process the rest next time.
|
||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||
return;
|
||||
{
|
||||
_highPressureDeltaLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_highPressureDeltaLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ProcessHotspots()
|
||||
private bool ProcessHotspots(bool resumed = false)
|
||||
{
|
||||
_stopwatch.Restart();
|
||||
|
||||
if(!resumed)
|
||||
_currentRunTiles = new Queue<TileAtmosphere>(_hotspotTiles);
|
||||
|
||||
var number = 0;
|
||||
foreach (var hotspot in _hotspotTiles.ToArray())
|
||||
while (_currentRunTiles.Count > 0)
|
||||
{
|
||||
var hotspot = _currentRunTiles.Dequeue();
|
||||
hotspot.ProcessHotspot();
|
||||
|
||||
if (number++ < LagCheckIterations) continue;
|
||||
number = 0;
|
||||
// Process the rest next time.
|
||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||
return;
|
||||
{
|
||||
_hotspotsLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_hotspotsLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ProcessSuperconductivity()
|
||||
private bool ProcessSuperconductivity(bool resumed = false)
|
||||
{
|
||||
_stopwatch.Restart();
|
||||
|
||||
if(!resumed)
|
||||
_currentRunTiles = new Queue<TileAtmosphere>(_superconductivityTiles);
|
||||
|
||||
var number = 0;
|
||||
foreach (var superconductivity in _superconductivityTiles.ToArray())
|
||||
while (_currentRunTiles.Count > 0)
|
||||
{
|
||||
var superconductivity = _currentRunTiles.Dequeue();
|
||||
superconductivity.Superconduct();
|
||||
|
||||
if (number++ < LagCheckIterations) continue;
|
||||
number = 0;
|
||||
// Process the rest next time.
|
||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||
return;
|
||||
{
|
||||
_superconductivityLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_superconductivityLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return true;
|
||||
}
|
||||
|
||||
private AirtightComponent GetObstructingComponent(MapIndices indices)
|
||||
private bool ProcessPipeNets(bool resumed = false)
|
||||
{
|
||||
foreach (var v in _grid.GetSnapGridCell(indices, SnapGridOffset.Center))
|
||||
_stopwatch.Restart();
|
||||
|
||||
if(!resumed)
|
||||
_currentRunPipeNet = new Queue<IPipeNet>(_pipeNets);
|
||||
|
||||
var number = 0;
|
||||
while (_currentRunPipeNet.Count > 0)
|
||||
{
|
||||
var pipenet = _currentRunPipeNet.Dequeue();
|
||||
pipenet.Update();
|
||||
|
||||
if (number++ < LagCheckIterations) continue;
|
||||
number = 0;
|
||||
// Process the rest next time.
|
||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||
{
|
||||
_pipeNetLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_pipeNetLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ProcessPipeNetDevices(bool resumed = false)
|
||||
{
|
||||
_stopwatch.Restart();
|
||||
|
||||
if(!resumed)
|
||||
_currentRunPipeNetDevice = new Queue<PipeNetDeviceComponent>(_pipeNetDevices);
|
||||
|
||||
var number = 0;
|
||||
while (_currentRunPipeNet.Count > 0)
|
||||
{
|
||||
var device = _currentRunPipeNetDevice.Dequeue();
|
||||
device.Update();
|
||||
|
||||
if (number++ < LagCheckIterations) continue;
|
||||
number = 0;
|
||||
// Process the rest next time.
|
||||
if (_stopwatch.Elapsed.TotalMilliseconds >= LagCheckMaxMilliseconds)
|
||||
{
|
||||
_pipeNetDevicesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_pipeNetDevicesLastProcess = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
return true;
|
||||
}
|
||||
|
||||
private AirtightComponent? GetObstructingComponent(MapIndices indices)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return default;
|
||||
|
||||
foreach (var v in mapGrid.Grid.GetSnapGridCell(indices, SnapGridOffset.Center))
|
||||
{
|
||||
if (v.Owner.TryGetComponent<AirtightComponent>(out var ac))
|
||||
return ac;
|
||||
@@ -527,12 +787,6 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
return null;
|
||||
}
|
||||
|
||||
private static readonly Direction[] Cardinal =
|
||||
new []
|
||||
{
|
||||
Direction.North, Direction.East, Direction.South, Direction.West
|
||||
};
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
@@ -541,22 +795,24 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
if (serializer.Reading)
|
||||
if (serializer.Reading &&
|
||||
Owner.TryGetComponent(out IMapGridComponent? mapGrid))
|
||||
{
|
||||
var gridId = Owner.GetComponent<IMapGridComponent>().Grid.Index;
|
||||
var gridId = mapGrid.Grid.Index;
|
||||
|
||||
if (!serializer.TryReadDataField("uniqueMixes", out List<GasMixture> uniqueMixes) ||
|
||||
!serializer.TryReadDataField("tiles", out Dictionary<MapIndices, int> tiles))
|
||||
if (!serializer.TryReadDataField("uniqueMixes", out List<GasMixture>? uniqueMixes) ||
|
||||
!serializer.TryReadDataField("tiles", out Dictionary<MapIndices, int>? tiles))
|
||||
return;
|
||||
|
||||
_tiles.Clear();
|
||||
|
||||
foreach (var (indices, mix) in tiles)
|
||||
foreach (var (indices, mix) in tiles!)
|
||||
{
|
||||
_tiles.Add(indices, new TileAtmosphere(this, gridId, indices, (GasMixture)uniqueMixes[mix].Clone()));
|
||||
_tiles.Add(indices, new TileAtmosphere(this, gridId, indices, (GasMixture)uniqueMixes![mix].Clone()));
|
||||
Invalidate(indices);
|
||||
}
|
||||
} else if (serializer.Writing)
|
||||
}
|
||||
else if (serializer.Writing)
|
||||
{
|
||||
var uniqueMixes = new List<GasMixture>();
|
||||
var uniqueMixHash = new Dictionary<GasMixture, int>();
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using Content.Server.Atmos;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Log;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Atmos.Piping
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds itself to a <see cref="IGridAtmosphereComponent"/> to be updated by.
|
||||
/// TODO: Make compatible with unanchoring/anchoring. Currently assumes that the Owner does not move.
|
||||
/// </summary>
|
||||
public abstract class PipeNetDeviceComponent : Component
|
||||
{
|
||||
public abstract void Update();
|
||||
|
||||
protected IGridAtmosphereComponent JoinedGridAtmos { get; private set; }
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
JoinGridAtmos();
|
||||
}
|
||||
|
||||
public override void OnRemove()
|
||||
{
|
||||
base.OnRemove();
|
||||
LeaveGridAtmos();
|
||||
}
|
||||
|
||||
private void JoinGridAtmos()
|
||||
{
|
||||
var gridAtmos = EntitySystem.Get<AtmosphereSystem>()
|
||||
.GetGridAtmosphere(Owner.Transform.GridID);
|
||||
if (gridAtmos == null)
|
||||
{
|
||||
Logger.Error($"{nameof(PipeNetDeviceComponent)} on entity {Owner.Uid} could not find an {nameof(IGridAtmosphereComponent)}.");
|
||||
return;
|
||||
}
|
||||
JoinedGridAtmos = gridAtmos;
|
||||
JoinedGridAtmos.AddPipeNetDevice(this);
|
||||
}
|
||||
|
||||
private void LeaveGridAtmos()
|
||||
{
|
||||
JoinedGridAtmos?.RemovePipeNetDevice(this);
|
||||
JoinedGridAtmos = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using Content.Server.Atmos;
|
||||
using Content.Server.GameObjects.Components.NodeContainer;
|
||||
using Content.Server.GameObjects.Components.NodeContainer.Nodes;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Atmos.Piping
|
||||
{
|
||||
/// <summary>
|
||||
/// Transfer gas from one <see cref="PipeNode"/> to another.
|
||||
/// </summary>
|
||||
public abstract class BasePumpComponent : PipeNetDeviceComponent
|
||||
{
|
||||
/// <summary>
|
||||
/// Needs to be same <see cref="PipeDirection"/> as that of a <see cref="Pipe"/> on this entity.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
private PipeDirection _inletDirection;
|
||||
|
||||
/// <summary>
|
||||
/// Needs to be same <see cref="PipeDirection"/> as that of a <see cref="Pipe"/> on this entity.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
private PipeDirection _outletDirection;
|
||||
|
||||
[ViewVariables]
|
||||
private PipeNode _inletPipe;
|
||||
|
||||
[ViewVariables]
|
||||
private PipeNode _outletPipe;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
serializer.DataField(ref _inletDirection, "inletDirection", PipeDirection.None);
|
||||
serializer.DataField(ref _outletDirection, "outletDirection", PipeDirection.None);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
if (!Owner.TryGetComponent<NodeContainerComponent>(out var container))
|
||||
{
|
||||
JoinedGridAtmos?.RemovePipeNetDevice(this);
|
||||
Logger.Error($"{typeof(BasePumpComponent)} on entity {Owner.Uid} did not have a {nameof(NodeContainerComponent)}.");
|
||||
return;
|
||||
}
|
||||
var pipeNodes = container.Nodes.OfType<PipeNode>();
|
||||
_inletPipe = pipeNodes.Where(pipe => pipe.PipeDirection == _inletDirection).FirstOrDefault();
|
||||
_outletPipe = pipeNodes.Where(pipe => pipe.PipeDirection == _outletDirection).FirstOrDefault();
|
||||
if (_inletPipe == null | _outletPipe == null)
|
||||
{
|
||||
JoinedGridAtmos?.RemovePipeNetDevice(this);
|
||||
Logger.Error($"{typeof(BasePumpComponent)} on entity {Owner.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
PumpGas(_inletPipe.Air, _outletPipe.Air);
|
||||
}
|
||||
|
||||
protected abstract void PumpGas(GasMixture inletGas, GasMixture outletGas);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Content.Server.Atmos;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Atmos.Piping
|
||||
{
|
||||
/// <summary>
|
||||
/// Placeholder example of pump functionality.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(BasePumpComponent))]
|
||||
public class DebugPumpComponent : BasePumpComponent
|
||||
{
|
||||
public override string Name => "DebugPump";
|
||||
|
||||
protected override void PumpGas(GasMixture inletGas, GasMixture outletGas)
|
||||
{
|
||||
outletGas.Merge(inletGas);
|
||||
inletGas.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using Content.Server.Atmos;
|
||||
using Content.Server.GameObjects.Components.NodeContainer;
|
||||
using Content.Server.GameObjects.Components.NodeContainer.Nodes;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Atmos.Piping
|
||||
{
|
||||
/// <summary>
|
||||
/// Transfers gas from the tile it is on to a <see cref="PipeNode"/>.
|
||||
/// </summary>
|
||||
public abstract class BaseSiphonComponent : PipeNetDeviceComponent
|
||||
{
|
||||
[ViewVariables]
|
||||
private PipeNode _scrubberOutlet;
|
||||
|
||||
private AtmosphereSystem _atmosSystem;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_atmosSystem = EntitySystem.Get<AtmosphereSystem>();
|
||||
if (!Owner.TryGetComponent<NodeContainerComponent>(out var container))
|
||||
{
|
||||
JoinedGridAtmos?.RemovePipeNetDevice(this);
|
||||
Logger.Error($"{typeof(BaseSiphonComponent)} on entity {Owner.Uid} did not have a {nameof(NodeContainerComponent)}.");
|
||||
return;
|
||||
}
|
||||
_scrubberOutlet = container.Nodes.OfType<PipeNode>().FirstOrDefault();
|
||||
if (_scrubberOutlet == null)
|
||||
{
|
||||
JoinedGridAtmos?.RemovePipeNetDevice(this);
|
||||
Logger.Error($"{typeof(BaseSiphonComponent)} on entity {Owner.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
var tileAtmos = AtmosHelpers.GetTileAtmosphere(Owner.Transform.GridPosition);
|
||||
if (tileAtmos == null)
|
||||
return;
|
||||
ScrubGas(tileAtmos.Air, _scrubberOutlet.Air);
|
||||
_atmosSystem.GetGridAtmosphere(Owner.Transform.GridID).Invalidate(tileAtmos.GridIndices);
|
||||
}
|
||||
|
||||
protected abstract void ScrubGas(GasMixture inletGas, GasMixture outletGas);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Content.Server.Atmos;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Atmos.Piping
|
||||
{
|
||||
/// <summary>
|
||||
/// Placeholder example of scrubber functionality.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(BaseSiphonComponent))]
|
||||
public class DebugSiphonComponent : BaseSiphonComponent
|
||||
{
|
||||
public override string Name => "DebugSiphon";
|
||||
|
||||
protected override void ScrubGas(GasMixture inletGas, GasMixture outletGas)
|
||||
{
|
||||
outletGas.Merge(inletGas);
|
||||
inletGas.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Content.Server.Atmos;
|
||||
using Content.Server.GameObjects.Components.NodeContainer;
|
||||
using Content.Server.GameObjects.Components.NodeContainer.Nodes;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Atmos.Piping
|
||||
{
|
||||
/// <summary>
|
||||
/// Transfers gas from a <see cref="PipeNode"/> to the tile it is on.
|
||||
/// </summary>
|
||||
public abstract class BaseVentComponent : PipeNetDeviceComponent
|
||||
{
|
||||
[ViewVariables]
|
||||
private PipeNode _ventInlet;
|
||||
|
||||
private AtmosphereSystem _atmosSystem;
|
||||
|
||||
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_atmosSystem = EntitySystem.Get<AtmosphereSystem>();
|
||||
if (!Owner.TryGetComponent<NodeContainerComponent>(out var container))
|
||||
{
|
||||
JoinedGridAtmos?.RemovePipeNetDevice(this);
|
||||
Logger.Error($"{typeof(BaseVentComponent)} on entity {Owner.Uid} did not have a {nameof(NodeContainerComponent)}.");
|
||||
return;
|
||||
}
|
||||
_ventInlet = container.Nodes.OfType<PipeNode>().FirstOrDefault();
|
||||
if (_ventInlet == null)
|
||||
{
|
||||
JoinedGridAtmos?.RemovePipeNetDevice(this);
|
||||
Logger.Error($"{typeof(BaseVentComponent)} on entity {Owner.Uid} could not find compatible {nameof(PipeNode)}s on its {nameof(NodeContainerComponent)}.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
var tileAtmos = AtmosHelpers.GetTileAtmosphere(Owner.Transform.GridPosition);
|
||||
if (tileAtmos == null)
|
||||
return;
|
||||
VentGas(_ventInlet.Air, tileAtmos.Air);
|
||||
_atmosSystem.GetGridAtmosphere(Owner.Transform.GridID).Invalidate(tileAtmos.GridIndices);
|
||||
}
|
||||
|
||||
protected abstract void VentGas(GasMixture inletGas, GasMixture outletGas);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Content.Server.Atmos;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Atmos.Piping
|
||||
{
|
||||
/// <summary>
|
||||
/// Placeholder example of vent functionality.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(BaseVentComponent))]
|
||||
public class DebugVentComponent : BaseVentComponent
|
||||
{
|
||||
public override string Name => "DebugVent";
|
||||
|
||||
protected override void VentGas(GasMixture inletGas, GasMixture outletGas)
|
||||
{
|
||||
outletGas.Merge(inletGas);
|
||||
inletGas.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user