Canister fixes and rework (#4266)

* Kills PipeNode ConnectToContainedEntities and EnvironmentalAir with fire.

* Reaction IGasMixtureHolder is nullable.

* Reworks canisters

* Adds PortablePipeNode and PortPipeNode, which connect to each other.
This commit is contained in:
Vera Aguilera Puerto
2021-07-12 10:00:50 +02:00
committed by GitHub
parent 077f158dda
commit d8e353742c
10 changed files with 96 additions and 107 deletions

View File

@@ -263,7 +263,7 @@ namespace Content.Server.Atmos.EntitySystems
Merge(destination, buffer);
}
public ReactionResult React(GasMixture mixture, IGasMixtureHolder holder)
public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder)
{
var reaction = ReactionResult.NoReaction;
var temperature = mixture.Temperature;

View File

@@ -23,12 +23,11 @@ namespace Content.Server.Atmos.Piping.Unary.Components
[ViewVariables(VVAccess.ReadWrite)]
[DataField("gasMixture")]
public GasMixture InitialMixture { get; } = new();
public GasMixture Air { get; } = new();
/// <summary>
/// Stores the last pressure the tank had, for appearance-updating purposes.
/// Last recorded pressure, for appearance-updating purposes.
/// </summary>
[ViewVariables]
public float LastPressure { get; set; } = 0f;
/// <summary>

View File

@@ -1,4 +1,5 @@
using System;
using System.CodeDom;
using Content.Server.Atmos.Components;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Atmos.Piping.Binary.Components;
@@ -6,6 +7,7 @@ using Content.Server.Atmos.Piping.Components;
using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.Hands.Components;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.NodeGroups;
using Content.Server.NodeContainer.Nodes;
using Content.Server.UserInterface;
using Content.Shared.ActionBlocker;
@@ -54,18 +56,6 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
{
containerManager.MakeContainer<ContainerSlot>(canister.ContainerName);
}
if (!ComponentManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer))
return;
if (!nodeContainer.TryGetNode(canister.PortName, out PipeNode? portNode))
return;
// Create a pipenet if we don't have one already.
portNode.CreateSingleNetImmediate();
Get<AtmosphereSystem>().Merge(portNode.Air, canister.InitialMixture);
portNode.Air.Temperature = canister.InitialMixture.Temperature;
portNode.Volume = canister.InitialMixture.Volume;
}
private void DirtyUI(EntityUid uid)
@@ -81,7 +71,9 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
string? tankLabel = null;
var tankPressure = 0f;
if (ComponentManager.TryGetComponent(uid, out ContainerManagerComponent? containerManager) && containerManager.TryGetContainer(canister.ContainerName, out var tankContainer) && tankContainer.ContainedEntities.Count > 0)
if (ComponentManager.TryGetComponent(uid, out ContainerManagerComponent? containerManager)
&& containerManager.TryGetContainer(canister.ContainerName, out var tankContainer)
&& tankContainer.ContainedEntities.Count > 0)
{
var tank = tankContainer.ContainedEntities[0];
var tankComponent = tank.GetComponent<GasTankComponent>();
@@ -89,8 +81,8 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
tankPressure = tankComponent.Air.Pressure;
}
ui.SetState(new GasCanisterBoundUserInterfaceState(metadata.EntityName, portNode.Air.Pressure,
portNode.NodeGroup!.Nodes.Count > 1, tankLabel, tankPressure,
ui.SetState(new GasCanisterBoundUserInterfaceState(metadata.EntityName, canister.Air.Pressure,
portNode.NodeGroup?.Nodes.Count > 1, tankLabel, tankPressure,
canister.ReleasePressure, canister.ReleaseValve,
canister.MinReleasePressure, canister.MaxReleasePressure));
}
@@ -136,9 +128,29 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|| !ComponentManager.TryGetComponent(uid, out AppearanceComponent? appearance))
return;
if (!nodeContainer.TryGetNode(canister.PortName, out PipeNode? portNode))
if (!nodeContainer.TryGetNode(canister.PortName, out PortablePipeNode? portNode))
return;
var atmosphereSystem = Get<AtmosphereSystem>();
atmosphereSystem.React(canister.Air, portNode);
if (portNode.NodeGroup is PipeNet {NodeCount: > 1} net)
{
var buffer = new GasMixture(net.Air.Volume + canister.Air.Volume);
atmosphereSystem.Merge(buffer, net.Air);
atmosphereSystem.Merge(buffer, canister.Air);
net.Air.Clear();
atmosphereSystem.Merge(net.Air, buffer);
net.Air.Multiply(net.Air.Volume / buffer.Volume);
canister.Air.Clear();
atmosphereSystem.Merge(canister.Air, buffer);
canister.Air.Multiply(canister.Air.Volume / buffer.Volume);
}
// Release valve is open, release gas.
if (canister.ReleaseValve)
{
@@ -146,38 +158,36 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|| !containerManager.TryGetContainer(canister.ContainerName, out var container))
return;
var atmosphereSystem = Get<AtmosphereSystem>();
if (container.ContainedEntities.Count > 0)
{
var gasTank = container.ContainedEntities[0].GetComponent<GasTankComponent>();
atmosphereSystem.ReleaseGasTo(portNode.Air, gasTank.Air, canister.ReleasePressure);
atmosphereSystem.ReleaseGasTo(canister.Air, gasTank.Air, canister.ReleasePressure);
}
else
{
var tileAtmosphere = canister.Owner.Transform.Coordinates.GetTileAtmosphere();
atmosphereSystem.ReleaseGasTo(portNode.Air, tileAtmosphere?.Air, canister.ReleasePressure);
atmosphereSystem.ReleaseGasTo(canister.Air, tileAtmosphere?.Air, canister.ReleasePressure);
tileAtmosphere?.Invalidate();
}
}
DirtyUI(uid);
// Nothing to do here.
if (MathHelper.CloseTo(portNode.Air.Pressure, canister.LastPressure))
// If last pressure is very close to the current pressure, do nothing.
if (MathHelper.CloseTo(canister.Air.Pressure, canister.LastPressure))
return;
canister.LastPressure = portNode.Air.Pressure;
canister.LastPressure = canister.Air.Pressure;
if (portNode.Air.Pressure < 10)
if (canister.Air.Pressure < 10)
{
appearance.SetData(GasCanisterVisuals.PressureState, 0);
}
else if (portNode.Air.Pressure < Atmospherics.OneAtmosphere)
else if (canister.Air.Pressure < Atmospherics.OneAtmosphere)
{
appearance.SetData(GasCanisterVisuals.PressureState, 1);
}
else if (portNode.Air.Pressure < (15 * Atmospherics.OneAtmosphere))
else if (canister.Air.Pressure < (15 * Atmospherics.OneAtmosphere))
{
appearance.SetData(GasCanisterVisuals.PressureState, 2);
}

View File

@@ -67,7 +67,7 @@ namespace Content.Server.Atmos.Reactions
/// </summary>
[DataField("effects")] private List<IGasReactionEffect> _effects = new();
public ReactionResult React(GasMixture mixture, IGasMixtureHolder holder, AtmosphereSystem atmosphereSystem)
public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem)
{
var result = ReactionResult.NoReaction;

View File

@@ -34,10 +34,6 @@ namespace Content.Server.NodeContainer.Nodes
[DataField("pipeDirection")]
public PipeDirection PipeDirection { get; private set; }
[ViewVariables(VVAccess.ReadWrite)]
[DataField("connectToContainedEntities")]
public bool ConnectToContainedEntities { get; set; } = false;
/// <summary>
/// The directions in which this node is connected to other nodes.
/// Used by <see cref="PipeVisualState"/>.
@@ -81,20 +77,13 @@ namespace Content.Server.NodeContainer.Nodes
[ViewVariables]
private IPipeNet? PipeNet => (IPipeNet?) NodeGroup;
/// <summary>
/// Whether to ignore the pipenet and return the environment's air.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
[DataField("environmentalAir")]
public bool EnvironmentalAir { get; set; } = false;
/// <summary>
/// The gases in this pipe.
/// </summary>
[ViewVariables]
public GasMixture Air
{
get => (!EnvironmentalAir ? PipeNet?.Air : Owner.Transform.Coordinates.GetTileAir()) ?? GasMixture.SpaceGas;
get => PipeNet?.Air ?? GasMixture.SpaceGas;
set
{
DebugTools.Assert(PipeNet != null);
@@ -104,14 +93,8 @@ namespace Content.Server.NodeContainer.Nodes
public void AssumeAir(GasMixture giver)
{
if (EnvironmentalAir)
{
var tileAtmosphere = Owner.Transform.Coordinates.GetTileAtmosphere();
tileAtmosphere?.AssumeAir(giver);
return;
}
EntitySystem.Get<AtmosphereSystem>().Merge(PipeNet!.Air, giver);
if(PipeNet != null)
EntitySystem.Get<AtmosphereSystem>().Merge(PipeNet.Air, giver);
}
[ViewVariables]
@@ -163,24 +146,6 @@ namespace Content.Server.NodeContainer.Nodes
yield return pipe;
}
}
if (!ConnectionsEnabled || !ConnectToContainedEntities || !Owner.TryGetComponent(out ContainerManagerComponent? containerManager))
yield break;
// TODO ATMOS Kill it with fire.
foreach (var container in containerManager.GetAllContainers())
{
foreach (var entity in container.ContainedEntities)
{
if (!entity.TryGetComponent(out NodeContainerComponent? nodeContainer))
continue;
foreach (var node in nodeContainer.Nodes.Values)
{
yield return node;
}
}
}
}
/// <summary>
@@ -191,17 +156,6 @@ namespace Content.Server.NodeContainer.Nodes
if (!Anchored)
yield break;
if (pipeDir is PipeDirection.Port or PipeDirection.Connector)
{
foreach (var pipe in PipesInTile())
{
if (pipe.Anchored && pipe.ConnectionsEnabled && pipe.PipeDirection.HasDirection(pipeDir.GetOpposite()))
yield return pipe;
}
yield break;
}
foreach (var pipe in PipesInDirection(pipeDir))
{
if (pipe.ConnectionsEnabled && pipe.PipeDirection.HasDirection(pipeDir.GetOpposite()))
@@ -212,7 +166,7 @@ namespace Content.Server.NodeContainer.Nodes
/// <summary>
/// Gets the pipes from entities on the tile adjacent in a direction.
/// </summary>
private IEnumerable<PipeNode> PipesInDirection(PipeDirection pipeDir)
protected IEnumerable<PipeNode> PipesInDirection(PipeDirection pipeDir)
{
if (!Owner.Transform.Anchored)
yield break;
@@ -233,9 +187,9 @@ namespace Content.Server.NodeContainer.Nodes
}
/// <summary>
/// Gets the pipes from entities on the tile adjacent in a direction.
/// Gets the pipes from entities on the same tile.
/// </summary>
private IEnumerable<PipeNode> PipesInTile()
protected IEnumerable<PipeNode> PipesInTile()
{
if (!Owner.Transform.Anchored)
yield break;

View File

@@ -0,0 +1,23 @@
using System.Collections.Generic;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Server.NodeContainer.Nodes
{
[DataDefinition]
public class PortPipeNode : PipeNode
{
public override IEnumerable<Node> GetReachableNodes()
{
foreach (var node in PipesInTile())
{
if (node is PortablePipeNode)
yield return node;
}
foreach (var node in base.GetReachableNodes())
{
yield return node;
}
}
}
}

View File

@@ -0,0 +1,23 @@
using System.Collections.Generic;
using Robust.Shared.Serialization.Manager.Attributes;
namespace Content.Server.NodeContainer.Nodes
{
[DataDefinition]
public class PortablePipeNode : PipeNode
{
public override IEnumerable<Node> GetReachableNodes()
{
foreach (var node in PipesInTile())
{
if (node is PortPipeNode)
yield return node;
}
foreach (var node in base.GetReachableNodes())
{
yield return node;
}
}
}
}

View File

@@ -36,8 +36,6 @@ namespace Content.Shared.Atmos
South = 1 << 1,
West = 1 << 2,
East = 1 << 3,
Port = 1 << 4,
Connector = 1 << 5,
//Straight pipes
Longitudinal = North | South,
@@ -49,12 +47,6 @@ namespace Content.Shared.Atmos
SWBend = South | West,
SEBend = South | East,
//Vertical Bends (Port only)
NPBend = North | Port,
SPBend = South | Port,
WPBend = West | Port,
EPBend = East | Port,
//T-Junctions
TNorth = North | Lateral,
TSouth = South | Lateral,
@@ -72,7 +64,6 @@ namespace Content.Shared.Atmos
Half,
Straight,
Bend,
VerticalBend,
TJunction,
Fourway
}
@@ -89,7 +80,6 @@ namespace Content.Shared.Atmos
PipeShape.Half => PipeDirection.South,
PipeShape.Straight => PipeDirection.Longitudinal,
PipeShape.Bend => PipeDirection.SWBend,
PipeShape.VerticalBend => PipeDirection.SPBend,
PipeShape.TJunction => PipeDirection.TSouth,
PipeShape.Fourway => PipeDirection.Fourway,
_ => throw new ArgumentOutOfRangeException(nameof(shape), $"{shape} does not have an associated {nameof(PipeDirection)}."),
@@ -148,8 +138,6 @@ namespace Content.Shared.Atmos
PipeDirection.South => PipeDirection.North,
PipeDirection.East => PipeDirection.West,
PipeDirection.West => PipeDirection.East,
PipeDirection.Port => PipeDirection.Connector,
PipeDirection.Connector => PipeDirection.Port,
_ => throw new ArgumentOutOfRangeException(nameof(pipeDirection)),
};
}
@@ -171,11 +159,6 @@ namespace Content.Shared.Atmos
PipeDirection.SEBend => PipeShape.Bend,
PipeDirection.SWBend => PipeShape.Bend,
PipeDirection.NPBend => PipeShape.VerticalBend,
PipeDirection.SPBend => PipeShape.VerticalBend,
PipeDirection.WPBend => PipeShape.VerticalBend,
PipeDirection.EPBend => PipeShape.VerticalBend,
PipeDirection.TNorth => PipeShape.TJunction,
PipeDirection.TSouth => PipeShape.TJunction,
PipeDirection.TEast => PipeShape.TJunction,

View File

@@ -122,6 +122,6 @@
- type: NodeContainer
nodes:
connected:
!type:PipeNode
!type:PortPipeNode
nodeGroupID: Pipe
pipeDirection: SPBend
pipeDirection: South

View File

@@ -64,13 +64,10 @@
- type: NodeContainer
nodes:
port:
!type:PipeNode
!type:PortablePipeNode
nodeGroupID: Pipe
pipeDirection: Connector
connectionsEnabled: false
needAnchored: false
rotationsEnabled: false
volume: 1000
volume: 1
- type: GasPortable
- type: GasCanister