diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs index 106a635c4a..f2422b458b 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs @@ -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; diff --git a/Content.Server/Atmos/Piping/Unary/Components/GasCanisterComponent.cs b/Content.Server/Atmos/Piping/Unary/Components/GasCanisterComponent.cs index d8999b09b2..5f2379b1e4 100644 --- a/Content.Server/Atmos/Piping/Unary/Components/GasCanisterComponent.cs +++ b/Content.Server/Atmos/Piping/Unary/Components/GasCanisterComponent.cs @@ -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(); /// - /// Stores the last pressure the tank had, for appearance-updating purposes. + /// Last recorded pressure, for appearance-updating purposes. /// - [ViewVariables] public float LastPressure { get; set; } = 0f; /// diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs index d12a363475..f3b0d97682 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs @@ -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(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().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(); @@ -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.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(); - if (container.ContainedEntities.Count > 0) { var gasTank = container.ContainedEntities[0].GetComponent(); - 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); } diff --git a/Content.Server/Atmos/Reactions/GasReactionPrototype.cs b/Content.Server/Atmos/Reactions/GasReactionPrototype.cs index 1005f2d49a..deadbdb674 100644 --- a/Content.Server/Atmos/Reactions/GasReactionPrototype.cs +++ b/Content.Server/Atmos/Reactions/GasReactionPrototype.cs @@ -67,7 +67,7 @@ namespace Content.Server.Atmos.Reactions /// [DataField("effects")] private List _effects = new(); - public ReactionResult React(GasMixture mixture, IGasMixtureHolder holder, AtmosphereSystem atmosphereSystem) + public ReactionResult React(GasMixture mixture, IGasMixtureHolder? holder, AtmosphereSystem atmosphereSystem) { var result = ReactionResult.NoReaction; diff --git a/Content.Server/NodeContainer/Nodes/PipeNode.cs b/Content.Server/NodeContainer/Nodes/PipeNode.cs index 68d093188c..d8418efb5a 100644 --- a/Content.Server/NodeContainer/Nodes/PipeNode.cs +++ b/Content.Server/NodeContainer/Nodes/PipeNode.cs @@ -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; - /// /// The directions in which this node is connected to other nodes. /// Used by . @@ -81,20 +77,13 @@ namespace Content.Server.NodeContainer.Nodes [ViewVariables] private IPipeNet? PipeNet => (IPipeNet?) NodeGroup; - /// - /// Whether to ignore the pipenet and return the environment's air. - /// - [ViewVariables(VVAccess.ReadWrite)] - [DataField("environmentalAir")] - public bool EnvironmentalAir { get; set; } = false; - /// /// The gases in this pipe. /// [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().Merge(PipeNet!.Air, giver); + if(PipeNet != null) + EntitySystem.Get().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; - } - } - } } /// @@ -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 /// /// Gets the pipes from entities on the tile adjacent in a direction. /// - private IEnumerable PipesInDirection(PipeDirection pipeDir) + protected IEnumerable PipesInDirection(PipeDirection pipeDir) { if (!Owner.Transform.Anchored) yield break; @@ -233,9 +187,9 @@ namespace Content.Server.NodeContainer.Nodes } /// - /// Gets the pipes from entities on the tile adjacent in a direction. + /// Gets the pipes from entities on the same tile. /// - private IEnumerable PipesInTile() + protected IEnumerable PipesInTile() { if (!Owner.Transform.Anchored) yield break; diff --git a/Content.Server/NodeContainer/Nodes/PortPipeNode.cs b/Content.Server/NodeContainer/Nodes/PortPipeNode.cs new file mode 100644 index 0000000000..18c65173f8 --- /dev/null +++ b/Content.Server/NodeContainer/Nodes/PortPipeNode.cs @@ -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 GetReachableNodes() + { + foreach (var node in PipesInTile()) + { + if (node is PortablePipeNode) + yield return node; + } + + foreach (var node in base.GetReachableNodes()) + { + yield return node; + } + } + } +} diff --git a/Content.Server/NodeContainer/Nodes/PortablePipeNode.cs b/Content.Server/NodeContainer/Nodes/PortablePipeNode.cs new file mode 100644 index 0000000000..7f645cb518 --- /dev/null +++ b/Content.Server/NodeContainer/Nodes/PortablePipeNode.cs @@ -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 GetReachableNodes() + { + foreach (var node in PipesInTile()) + { + if (node is PortPipeNode) + yield return node; + } + + foreach (var node in base.GetReachableNodes()) + { + yield return node; + } + } + } +} diff --git a/Content.Shared/Atmos/PipeDirection.cs b/Content.Shared/Atmos/PipeDirection.cs index d00398f19b..c7f30f064d 100644 --- a/Content.Shared/Atmos/PipeDirection.cs +++ b/Content.Shared/Atmos/PipeDirection.cs @@ -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, diff --git a/Resources/Prototypes/Entities/Constructible/Piping/Atmospherics/binary.yml b/Resources/Prototypes/Entities/Constructible/Piping/Atmospherics/binary.yml index 3260703c01..b3570a9c50 100644 --- a/Resources/Prototypes/Entities/Constructible/Piping/Atmospherics/binary.yml +++ b/Resources/Prototypes/Entities/Constructible/Piping/Atmospherics/binary.yml @@ -122,6 +122,6 @@ - type: NodeContainer nodes: connected: - !type:PipeNode + !type:PortPipeNode nodeGroupID: Pipe - pipeDirection: SPBend + pipeDirection: South diff --git a/Resources/Prototypes/Entities/Constructible/Piping/Atmospherics/gas_canisters.yml b/Resources/Prototypes/Entities/Constructible/Piping/Atmospherics/gas_canisters.yml index c4dcba4396..574f9e9ea8 100644 --- a/Resources/Prototypes/Entities/Constructible/Piping/Atmospherics/gas_canisters.yml +++ b/Resources/Prototypes/Entities/Constructible/Piping/Atmospherics/gas_canisters.yml @@ -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