diff --git a/Content.Client/Atmos/Visualizers/PressurePumpVisualizer.cs b/Content.Client/Atmos/Visualizers/PressurePumpVisualizer.cs index 7eff2bdc6e..bf6d4a34ca 100644 --- a/Content.Client/Atmos/Visualizers/PressurePumpVisualizer.cs +++ b/Content.Client/Atmos/Visualizers/PressurePumpVisualizer.cs @@ -8,7 +8,7 @@ namespace Content.Client.Atmos.Visualizers public sealed class PressurePumpVisualizer : EnabledAtmosDeviceVisualizer { protected override object LayerMap => Layers.Enabled; - protected override Enum DataKey => PressurePumpVisuals.Enabled; + protected override Enum DataKey => PumpVisuals.Enabled; enum Layers : byte { diff --git a/Content.Server/Atmos/Piping/Binary/Components/GasPassiveGateComponent.cs b/Content.Server/Atmos/Piping/Binary/Components/GasPassiveGateComponent.cs index bee12dc001..b219ae46f8 100644 --- a/Content.Server/Atmos/Piping/Binary/Components/GasPassiveGateComponent.cs +++ b/Content.Server/Atmos/Piping/Binary/Components/GasPassiveGateComponent.cs @@ -1,7 +1,4 @@ using Content.Shared.Atmos; -using Robust.Shared.GameObjects; -using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.ViewVariables; namespace Content.Server.Atmos.Piping.Binary.Components { @@ -28,6 +25,7 @@ namespace Content.Server.Atmos.Piping.Binary.Components public string OutletName { get; set; } = "outlet"; [ViewVariables(VVAccess.ReadWrite)] + [DataField("targetPressure")] public float TargetPressure { get; set; } = Atmospherics.OneAtmosphere; } } diff --git a/Content.Server/Atmos/Piping/Binary/Components/GasPressurePumpComponent.cs b/Content.Server/Atmos/Piping/Binary/Components/GasPressurePumpComponent.cs index 26ed73422b..4fa562ff5c 100644 --- a/Content.Server/Atmos/Piping/Binary/Components/GasPressurePumpComponent.cs +++ b/Content.Server/Atmos/Piping/Binary/Components/GasPressurePumpComponent.cs @@ -1,7 +1,4 @@ using Content.Shared.Atmos; -using Robust.Shared.GameObjects; -using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.ViewVariables; namespace Content.Server.Atmos.Piping.Binary.Components { @@ -20,6 +17,14 @@ namespace Content.Server.Atmos.Piping.Binary.Components public string OutletName { get; set; } = "outlet"; [ViewVariables(VVAccess.ReadWrite)] + [DataField("targetPressure")] public float TargetPressure { get; set; } = Atmospherics.OneAtmosphere; + + /// + /// Max pressure of the target gas (NOT relative to source). + /// + [ViewVariables(VVAccess.ReadWrite)] + [DataField("maxTargetPressure")] + public float MaxTargetPressure = Atmospherics.MaxOutputPressure; } } diff --git a/Content.Server/Atmos/Piping/Binary/Components/GasVolumePumpComponent.cs b/Content.Server/Atmos/Piping/Binary/Components/GasVolumePumpComponent.cs index 4bee30c9a6..e28416e013 100644 --- a/Content.Server/Atmos/Piping/Binary/Components/GasVolumePumpComponent.cs +++ b/Content.Server/Atmos/Piping/Binary/Components/GasVolumePumpComponent.cs @@ -1,7 +1,4 @@ using Content.Shared.Atmos; -using Robust.Shared.GameObjects; -using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.ViewVariables; namespace Content.Server.Atmos.Piping.Binary.Components { @@ -23,8 +20,13 @@ namespace Content.Server.Atmos.Piping.Binary.Components public string OutletName { get; set; } = "outlet"; [ViewVariables(VVAccess.ReadWrite)] + [DataField("transferRate")] public float TransferRate { get; set; } = Atmospherics.MaxTransferRate; + [ViewVariables(VVAccess.ReadWrite)] + [DataField("maxTransferRate")] + public float MaxTransferRate { get; set; } = Atmospherics.MaxTransferRate; + [DataField("leakRatio")] public float LeakRatio { get; set; } = 0.1f; @@ -32,9 +34,9 @@ namespace Content.Server.Atmos.Piping.Binary.Components public float LowerThreshold { get; set; } = 0.01f; [DataField("higherThreshold")] - public float HigherThreshold { get; set; } = 9000f; + public float HigherThreshold { get; set; } = 2 * Atmospherics.MaxOutputPressure; [DataField("overclockThreshold")] - public float OverclockThreshold { get; set; } = 1000f; + public float OverclockThreshold { get; set; } = 1000; } } diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs index 04ed617adf..c8cb4aa451 100644 --- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs +++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasPressurePumpSystem.cs @@ -14,10 +14,6 @@ using Content.Shared.Interaction; using Content.Shared.Popups; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Localization; -using Robust.Shared.Maths; namespace Content.Server.Atmos.Piping.Binary.EntitySystems { @@ -62,7 +58,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems || !nodeContainer.TryGetNode(pump.InletName, out PipeNode? inlet) || !nodeContainer.TryGetNode(pump.OutletName, out PipeNode? outlet)) { - appearance?.SetData(PressurePumpVisuals.Enabled, false); + appearance?.SetData(PumpVisuals.Enabled, false); return; } @@ -70,13 +66,13 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems if (MathHelper.CloseToPercent(pump.TargetPressure, outputStartingPressure)) { - appearance?.SetData(PressurePumpVisuals.Enabled, false); + appearance?.SetData(PumpVisuals.Enabled, false); return; // No need to pump gas if target has been reached. } if (inlet.Air.TotalMoles > 0 && inlet.Air.Temperature > 0) { - appearance?.SetData(PressurePumpVisuals.Enabled, true); + appearance?.SetData(PumpVisuals.Enabled, true); // We calculate the necessary moles to transfer using our good ol' friend PV=nRT. var pressureDelta = pump.TargetPressure - outputStartingPressure; @@ -91,7 +87,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems { if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance)) { - appearance.SetData(PressurePumpVisuals.Enabled, false); + appearance.SetData(PumpVisuals.Enabled, false); } } diff --git a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs index d74c2ba253..9df988fdd6 100644 --- a/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs +++ b/Content.Server/Atmos/Piping/Binary/EntitySystems/GasVolumePumpSystem.cs @@ -1,11 +1,10 @@ -using System; using Content.Server.Administration.Logs; using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.Piping.Binary.Components; using Content.Server.Atmos.Piping.Components; using Content.Server.NodeContainer; using Content.Server.NodeContainer.Nodes; -using Content.Shared.Atmos; +using Content.Shared.Atmos.Piping; using Content.Shared.Atmos.Piping.Binary.Components; using Content.Shared.Database; using Content.Shared.Examine; @@ -13,9 +12,6 @@ using Content.Shared.Interaction; using Content.Shared.Popups; using JetBrains.Annotations; using Robust.Server.GameObjects; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Localization; using Robust.Shared.Timing; namespace Content.Server.Atmos.Piping.Binary.EntitySystems @@ -54,18 +50,17 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems private void OnVolumePumpUpdated(EntityUid uid, GasVolumePumpComponent pump, AtmosDeviceUpdateEvent args) { - if (!pump.Enabled) - return; + TryComp(uid, out AppearanceComponent? appearance); - if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) - return; - - if (!EntityManager.TryGetComponent(uid, out AtmosDeviceComponent? device)) - return; - - if (!nodeContainer.TryGetNode(pump.InletName, out PipeNode? inlet) + if (!pump.Enabled + || !TryComp(uid, out NodeContainerComponent? nodeContainer) + || !TryComp(uid, out AtmosDeviceComponent? device) + || !nodeContainer.TryGetNode(pump.InletName, out PipeNode? inlet) || !nodeContainer.TryGetNode(pump.OutletName, out PipeNode? outlet)) + { + appearance?.SetData(PumpVisuals.Enabled, false); return; + } var inputStartingPressure = inlet.Air.Pressure; var outputStartingPressure = outlet.Air.Pressure; @@ -78,6 +73,8 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems if ((outputStartingPressure - inputStartingPressure > pump.OverclockThreshold) && pump.Overclocked) return; + appearance?.SetData(PumpVisuals.Enabled, true); + // We multiply the transfer rate in L/s by the seconds passed since the last process to get the liters. var transferRatio = (float)(pump.TransferRate * (_gameTiming.CurTime - device.LastProcess).TotalSeconds) / inlet.Air.Volume; @@ -126,7 +123,7 @@ namespace Content.Server.Atmos.Piping.Binary.EntitySystems private void OnTransferRateChangeMessage(EntityUid uid, GasVolumePumpComponent pump, GasVolumePumpChangeTransferRateMessage args) { - pump.TransferRate = Math.Clamp(args.TransferRate, 0f, Atmospherics.MaxTransferRate); + pump.TransferRate = Math.Clamp(args.TransferRate, 0f, pump.MaxTransferRate); _adminLogSystem.Add(LogType.AtmosVolumeChanged, LogImpact.Medium, $"{ToPrettyString(args.Session.AttachedEntity!.Value):player} set the transfer rate on {ToPrettyString(uid):device} to {args.TransferRate}"); DirtyUI(uid, pump); diff --git a/Content.Server/Atmos/Piping/Trinary/Components/GasFilterComponent.cs b/Content.Server/Atmos/Piping/Trinary/Components/GasFilterComponent.cs index 63915bb805..ccdb612d43 100644 --- a/Content.Server/Atmos/Piping/Trinary/Components/GasFilterComponent.cs +++ b/Content.Server/Atmos/Piping/Trinary/Components/GasFilterComponent.cs @@ -1,9 +1,4 @@ -using System; -using Content.Server.Atmos.Piping.Trinary.EntitySystems; using Content.Shared.Atmos; -using Robust.Shared.GameObjects; -using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.ViewVariables; namespace Content.Server.Atmos.Piping.Trinary.Components { @@ -26,8 +21,13 @@ namespace Content.Server.Atmos.Piping.Trinary.Components public string OutletName { get; set; } = "outlet"; [ViewVariables(VVAccess.ReadWrite)] + + [DataField("transferRate")] public float TransferRate { get; set; } = Atmospherics.MaxTransferRate; + [DataField("maxTransferRate")] + public float MaxTransferRate { get; set; } = Atmospherics.MaxTransferRate; + [ViewVariables(VVAccess.ReadWrite)] public Gas? FilteredGas { get; set; } } diff --git a/Content.Server/Atmos/Piping/Trinary/Components/GasMixerComponent.cs b/Content.Server/Atmos/Piping/Trinary/Components/GasMixerComponent.cs index 02add9b8c6..8858663faf 100644 --- a/Content.Server/Atmos/Piping/Trinary/Components/GasMixerComponent.cs +++ b/Content.Server/Atmos/Piping/Trinary/Components/GasMixerComponent.cs @@ -23,8 +23,13 @@ namespace Content.Server.Atmos.Piping.Trinary.Components public string OutletName = "outlet"; [ViewVariables(VVAccess.ReadWrite)] + [DataField("targetPressure")] public float TargetPressure = Atmospherics.OneAtmosphere; + [ViewVariables(VVAccess.ReadWrite)] + [DataField("maxTargetPressure")] + public float MaxTargetPressure = Atmospherics.MaxOutputPressure; + [ViewVariables(VVAccess.ReadWrite)] [DataField("inletOneConcentration")] public float InletOneConcentration = 0.5f; diff --git a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs index 7980daf5bc..8568b94ff3 100644 --- a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs +++ b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs @@ -138,7 +138,7 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems private void OnTransferRateChangeMessage(EntityUid uid, GasFilterComponent filter, GasFilterChangeRateMessage args) { - filter.TransferRate = Math.Clamp(args.Rate, 0f, Atmospherics.MaxTransferRate); + filter.TransferRate = Math.Clamp(args.Rate, 0f, filter.MaxTransferRate); _adminLogSystem.Add(LogType.AtmosVolumeChanged, LogImpact.Medium, $"{ToPrettyString(args.Session.AttachedEntity!.Value):player} set the transfer rate on {ToPrettyString(uid):device} to {args.Rate}"); DirtyUI(uid, filter); diff --git a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs index 0c6da97641..30a33e2246 100644 --- a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs +++ b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs @@ -173,7 +173,7 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems private void OnOutputPressureChangeMessage(EntityUid uid, GasMixerComponent mixer, GasMixerChangeOutputPressureMessage args) { - mixer.TargetPressure = Math.Clamp(args.Pressure, 0f, Atmospherics.MaxOutputPressure); + mixer.TargetPressure = Math.Clamp(args.Pressure, 0f, mixer.MaxTargetPressure); _adminLogSystem.Add(LogType.AtmosPressureChanged, LogImpact.Medium, $"{ToPrettyString(args.Session.AttachedEntity!.Value):player} set the pressure on {ToPrettyString(uid):device} to {args.Pressure}kPa"); DirtyUI(uid, mixer); diff --git a/Content.Server/Atmos/Piping/Unary/Components/GasOutletInjectorComponent.cs b/Content.Server/Atmos/Piping/Unary/Components/GasOutletInjectorComponent.cs index 19fb93461f..74f19758a9 100644 --- a/Content.Server/Atmos/Piping/Unary/Components/GasOutletInjectorComponent.cs +++ b/Content.Server/Atmos/Piping/Unary/Components/GasOutletInjectorComponent.cs @@ -1,10 +1,10 @@ -using Robust.Shared.GameObjects; -using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.ViewVariables; +using Content.Server.Atmos.Piping.Unary.EntitySystems; +using Content.Shared.Atmos; namespace Content.Server.Atmos.Piping.Unary.Components { [RegisterComponent] + [Friend(typeof(GasOutletInjectorSystem))] public sealed class GasOutletInjectorComponent : Component { @@ -14,12 +14,26 @@ namespace Content.Server.Atmos.Piping.Unary.Components [ViewVariables(VVAccess.ReadWrite)] public bool Injecting { get; set; } = false; + /// + /// Target volume to transfer. If is enabled, actual transfer rate will be much higher. + /// [ViewVariables(VVAccess.ReadWrite)] - public float VolumeRate { get; set; } = 50f; + public float TransferRate + { + get => _transferRate; + set => _transferRate = Math.Clamp(value, 0f, MaxTransferRate); + } + + private float _transferRate = 50; + + [ViewVariables(VVAccess.ReadWrite)] + [DataField("maxTransferRate")] + public float MaxTransferRate = Atmospherics.MaxTransferRate; + + [DataField("maxPressure")] + public float MaxPressure { get; set; } = 2 * Atmospherics.MaxOutputPressure; [DataField("inlet")] public string InletName { get; set; } = "pipe"; - - // TODO ATMOS: Inject method. } } diff --git a/Content.Server/Atmos/Piping/Unary/Components/GasVentPumpComponent.cs b/Content.Server/Atmos/Piping/Unary/Components/GasVentPumpComponent.cs index 546010709e..b1dcefd7b6 100644 --- a/Content.Server/Atmos/Piping/Unary/Components/GasVentPumpComponent.cs +++ b/Content.Server/Atmos/Piping/Unary/Components/GasVentPumpComponent.cs @@ -1,9 +1,5 @@ -using System; using Content.Shared.Atmos; using Content.Shared.Atmos.Piping.Unary.Components; -using Robust.Shared.GameObjects; -using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.ViewVariables; namespace Content.Server.Atmos.Piping.Unary.Components { @@ -24,17 +20,57 @@ namespace Content.Server.Atmos.Piping.Unary.Components public string InletName { get; set; } = "pipe"; [ViewVariables(VVAccess.ReadWrite)] + [DataField("pumpDirection")] public VentPumpDirection PumpDirection { get; set; } = VentPumpDirection.Releasing; [ViewVariables(VVAccess.ReadWrite)] + [DataField("pressureChecks")] public VentPressureBound PressureChecks { get; set; } = VentPressureBound.ExternalBound; [ViewVariables(VVAccess.ReadWrite)] [DataField("externalPressureBound")] - public float ExternalPressureBound { get; set; } = Atmospherics.OneAtmosphere; + public float ExternalPressureBound + { + get => _externalPressureBound; + set + { + _externalPressureBound = Math.Clamp(value, 0, MaxPressure); + } + } + private float _externalPressureBound = Atmospherics.OneAtmosphere; + [ViewVariables(VVAccess.ReadWrite)] - public float InternalPressureBound { get; set; } = 0f; + [DataField("internalPressureBound")] + public float InternalPressureBound + { + get => _internalPressureBound; + set + { + _internalPressureBound = Math.Clamp(value, 0, MaxPressure); + } + } + + private float _internalPressureBound = 0; + + /// + /// Max pressure of the target gas (NOT relative to source). + /// + [ViewVariables(VVAccess.ReadWrite)] + [DataField("maxPressure")] + public float MaxPressure = Atmospherics.MaxOutputPressure; + + /// + /// Pressure pump speed in kPa/s. Determines how much gas is moved. + /// + /// + /// The pump will attempt to modify the destination's final pressure by this quantity every second. If this + /// is too high, and the vent is connected to a large pipe-net, then someone can nearly instantly flood a + /// room with gas. + /// + [ViewVariables(VVAccess.ReadWrite)] + [DataField("targetPressureChange")] + public float TargetPressureChange = Atmospherics.OneAtmosphere; public GasVentPumpData ToAirAlarmData() { diff --git a/Content.Server/Atmos/Piping/Unary/Components/GasVentScrubberComponent.cs b/Content.Server/Atmos/Piping/Unary/Components/GasVentScrubberComponent.cs index fc8060dd6d..21c00db8db 100644 --- a/Content.Server/Atmos/Piping/Unary/Components/GasVentScrubberComponent.cs +++ b/Content.Server/Atmos/Piping/Unary/Components/GasVentScrubberComponent.cs @@ -1,14 +1,12 @@ -using System.Collections.Generic; using System.Linq; +using Content.Server.Atmos.Piping.Unary.EntitySystems; using Content.Shared.Atmos; using Content.Shared.Atmos.Piping.Unary.Components; -using Robust.Shared.GameObjects; -using Robust.Shared.Serialization.Manager.Attributes; -using Robust.Shared.ViewVariables; namespace Content.Server.Atmos.Piping.Unary.Components { [RegisterComponent] + [Friend(typeof(GasVentScrubberSystem))] public sealed class GasVentScrubberComponent : Component { [ViewVariables(VVAccess.ReadWrite)] @@ -30,8 +28,28 @@ namespace Content.Server.Atmos.Piping.Unary.Components [ViewVariables(VVAccess.ReadWrite)] public ScrubberPumpDirection PumpDirection { get; set; } = ScrubberPumpDirection.Scrubbing; + /// + /// Target volume to transfer. If is enabled, actual transfer rate will be much higher. + /// [ViewVariables(VVAccess.ReadWrite)] - public float VolumeRate { get; set; } = 200f; + public float TransferRate + { + get => _transferRate; + set => _transferRate = Math.Clamp(value, 0f, MaxTransferRate); + } + + private float _transferRate = Atmospherics.MaxTransferRate; + + [ViewVariables(VVAccess.ReadWrite)] + [DataField("maxTransferRate")] + public float MaxTransferRate = Atmospherics.MaxTransferRate; + + /// + /// As pressure difference approaches this number, the effective volume rate may be smaller than + /// + [DataField("maxPressure")] + public float MaxPressure = Atmospherics.MaxOutputPressure; [ViewVariables(VVAccess.ReadWrite)] public bool WideNet { get; set; } = false; @@ -46,7 +64,7 @@ namespace Content.Server.Atmos.Piping.Unary.Components Dirty = IsDirty, FilterGases = FilterGases, PumpDirection = PumpDirection, - VolumeRate = VolumeRate, + VolumeRate = TransferRate, WideNet = WideNet }; } @@ -56,7 +74,7 @@ namespace Content.Server.Atmos.Piping.Unary.Components Enabled = data.Enabled; IsDirty = data.Dirty; PumpDirection = (ScrubberPumpDirection) data.PumpDirection!; - VolumeRate = (float) data.VolumeRate!; + TransferRate = (float) data.VolumeRate!; WideNet = data.WideNet; if (!data.FilterGases!.SequenceEqual(FilterGases)) diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasOutletInjectorSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasOutletInjectorSystem.cs index fdc0858a24..a02378f5a1 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasOutletInjectorSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasOutletInjectorSystem.cs @@ -3,10 +3,8 @@ using Content.Server.Atmos.Piping.Components; using Content.Server.Atmos.Piping.Unary.Components; using Content.Server.NodeContainer; using Content.Server.NodeContainer.Nodes; -using Content.Shared.Atmos; using JetBrains.Annotations; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; +using Robust.Shared.Timing; namespace Content.Server.Atmos.Piping.Unary.EntitySystems { @@ -14,6 +12,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems public sealed class GasOutletInjectorSystem : EntitySystem { [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; public override void Initialize() { @@ -32,6 +31,9 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)) return; + if (!TryComp(uid, out AtmosDeviceComponent? device)) + return; + if (!nodeContainer.TryGetNode(injector.InletName, out PipeNode? inlet)) return; @@ -40,14 +42,14 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems if (environment == null) return; - if (inlet.Air.Temperature > 0) - { - var transferMoles = inlet.Air.Pressure * injector.VolumeRate / (inlet.Air.Temperature * Atmospherics.R); + if (inlet.Air.Temperature < 0) + return; - var removed = inlet.Air.Remove(transferMoles); + var timeDelta = (float) (_gameTiming.CurTime - device.LastProcess).TotalSeconds; + var ratio = MathF.Min(1f, timeDelta * injector.TransferRate / inlet.Air.Volume); + var removed = inlet.Air.RemoveRatio(ratio); - _atmosphereSystem.Merge(environment, removed); - } + _atmosphereSystem.Merge(environment, removed); } } } diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs index 3ef20c7b4f..0e61af26c1 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs @@ -1,4 +1,3 @@ -using System; using Content.Server.Atmos.EntitySystems; using Content.Server.Atmos.Monitor.Components; using Content.Server.Atmos.Monitor.Systems; @@ -12,12 +11,10 @@ using Content.Server.NodeContainer.Nodes; using Content.Server.Power.Components; using Content.Shared.Atmos; using Content.Shared.Atmos.Monitor; -using Content.Shared.Atmos.Monitor.Components; using Content.Shared.Atmos.Piping.Unary.Components; using Content.Shared.Atmos.Visuals; using JetBrains.Annotations; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; +using Robust.Shared.Timing; namespace Content.Server.Atmos.Piping.Unary.EntitySystems { @@ -26,6 +23,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems { [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Dependency] private readonly DeviceNetworkSystem _deviceNetSystem = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; public override void Initialize() { @@ -49,7 +47,8 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems } if (!vent.Enabled - || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) + || !TryComp(uid, out AtmosDeviceComponent? device) + || !TryComp(uid, out NodeContainerComponent? nodeContainer) || !nodeContainer.TryGetNode(vent.InletName, out PipeNode? pipe)) { appearance?.SetData(VentPumpVisuals.State, VentPumpState.Off); @@ -65,43 +64,71 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems return; } - if (vent.PumpDirection == VentPumpDirection.Releasing) + var timeDelta = (_gameTiming.CurTime - device.LastProcess).TotalSeconds; + var pressureDelta = (float) timeDelta * vent.TargetPressureChange; + + if (vent.PumpDirection == VentPumpDirection.Releasing && pipe.Air.Pressure > 0) { appearance?.SetData(VentPumpVisuals.State, VentPumpState.Out); - var pressureDelta = 10000f; + + if (environment.Pressure > vent.MaxPressure) + return; if ((vent.PressureChecks & VentPressureBound.ExternalBound) != 0) pressureDelta = MathF.Min(pressureDelta, vent.ExternalPressureBound - environment.Pressure); + if (pressureDelta <= 0) + return; + + // how many moles to transfer to change external pressure by pressureDelta + // (ignoring temperature differences because I am lazy) + var transferMoles = pressureDelta * environment.Volume / (pipe.Air.Temperature * Atmospherics.R); + + // limit transferMoles so the source doesn't go below its bound. if ((vent.PressureChecks & VentPressureBound.InternalBound) != 0) - pressureDelta = MathF.Min(pressureDelta, pipe.Air.Pressure - vent.InternalPressureBound); - - if (pressureDelta > 0 && pipe.Air.Temperature > 0) { - var transferMoles = pressureDelta * environment.Volume / (pipe.Air.Temperature * Atmospherics.R); + var internalDelta = pipe.Air.Pressure - vent.InternalPressureBound; - _atmosphereSystem.Merge(environment, pipe.Air.Remove(transferMoles)); + if (internalDelta <= 0) + return; + + var maxTransfer = internalDelta * pipe.Air.Volume / (pipe.Air.Temperature * Atmospherics.R); + transferMoles = MathF.Min(transferMoles, maxTransfer); } + + _atmosphereSystem.Merge(environment, pipe.Air.Remove(transferMoles)); } else if (vent.PumpDirection == VentPumpDirection.Siphoning && environment.Pressure > 0) { appearance?.SetData(VentPumpVisuals.State, VentPumpState.In); - var ourMultiplier = pipe.Air.Volume / (environment.Temperature * Atmospherics.R); - var molesDelta = 10000f * ourMultiplier; - if ((vent.PressureChecks & VentPressureBound.ExternalBound) != 0) - molesDelta = MathF.Min(molesDelta, - (environment.Pressure - vent.ExternalPressureBound) * environment.Volume / - (environment.Temperature * Atmospherics.R)); + if (pipe.Air.Pressure > vent.MaxPressure) + return; if ((vent.PressureChecks & VentPressureBound.InternalBound) != 0) - molesDelta = MathF.Min(molesDelta, (vent.InternalPressureBound - pipe.Air.Pressure) * ourMultiplier); + pressureDelta = MathF.Min(pressureDelta, vent.InternalPressureBound - pipe.Air.Pressure); - if (molesDelta > 0) + if (pressureDelta <= 0) + return; + + // how many moles to transfer to change internal pressure by pressureDelta + // (ignoring temperature differences because I am lazy) + var transferMoles = pressureDelta * pipe.Air.Volume / (environment.Temperature * Atmospherics.R); + + // limit transferMoles so the source doesn't go below its bound. + if ((vent.PressureChecks & VentPressureBound.ExternalBound) != 0) { - var removed = environment.Remove(molesDelta); - _atmosphereSystem.Merge(pipe.Air, removed); + var externalDelta = environment.Pressure - vent.ExternalPressureBound; + + if (externalDelta <= 0) + return; + + var maxTransfer = externalDelta * environment.Volume / (environment.Temperature * Atmospherics.R); + + transferMoles = MathF.Min(transferMoles, maxTransfer); } + + _atmosphereSystem.Merge(pipe.Air, environment.Remove(transferMoles)); } } diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs index 93664fb74d..98d032aefd 100644 --- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs +++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentScrubberSystem.cs @@ -15,15 +15,14 @@ using Content.Shared.Atmos.Piping.Unary.Visuals; using Content.Shared.Atmos.Monitor; using Content.Shared.Atmos.Piping.Unary.Components; using JetBrains.Annotations; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Maths; +using Robust.Shared.Timing; namespace Content.Server.Atmos.Piping.Unary.EntitySystems { [UsedImplicitly] public sealed class GasVentScrubberSystem : EntitySystem { + [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Dependency] private readonly DeviceNetworkSystem _deviceNetSystem = default!; @@ -36,7 +35,6 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems SubscribeLocalEvent(OnAtmosAlarm); SubscribeLocalEvent(OnPowerChanged); SubscribeLocalEvent(OnPacketRecv); - } private void OnVentScrubberUpdated(EntityUid uid, GasVentScrubberComponent scrubber, AtmosDeviceUpdateEvent args) @@ -49,6 +47,11 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems return; } + if (!TryComp(uid, out AtmosDeviceComponent? device)) + return; + + var timeDelta = (float) (_gameTiming.CurTime - device.LastProcess).TotalSeconds; + if (!scrubber.Enabled || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !nodeContainer.TryGetNode(scrubber.OutletName, out PipeNode? outlet)) @@ -59,14 +62,14 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems var environment = _atmosphereSystem.GetTileMixture(EntityManager.GetComponent(scrubber.Owner).Coordinates, true); - Scrub(_atmosphereSystem, scrubber, appearance, environment, outlet); + Scrub(timeDelta, scrubber, appearance, environment, outlet); if (!scrubber.WideNet) return; // Scrub adjacent tiles too. foreach (var adjacent in _atmosphereSystem.GetAdjacentTileMixtures(EntityManager.GetComponent(scrubber.Owner).Coordinates, false, true)) { - Scrub(_atmosphereSystem, scrubber, null, adjacent, outlet); + Scrub(timeDelta, scrubber, null, adjacent, outlet); } } @@ -78,7 +81,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems } } - private void Scrub(AtmosphereSystem atmosphereSystem, GasVentScrubberComponent scrubber, AppearanceComponent? appearance, GasMixture? tile, PipeNode outlet) + private void Scrub(float timeDelta, GasVentScrubberComponent scrubber, AppearanceComponent? appearance, GasMixture? tile, PipeNode outlet) { // Cannot scrub if tile is null or air-blocked. if (tile == null @@ -88,29 +91,26 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems return; } + // Take a gas sample. + var ratio = MathF.Min(1f, timeDelta * scrubber.TransferRate / tile.Volume); + var removed = tile.RemoveRatio(ratio); + + // Nothing left to remove from the tile. + if (MathHelper.CloseToPercent(removed.TotalMoles, 0f)) + return; + if (scrubber.PumpDirection == ScrubberPumpDirection.Scrubbing) { appearance?.SetData(ScrubberVisuals.State, scrubber.WideNet ? ScrubberState.WideScrub : ScrubberState.Scrub); - var transferMoles = MathF.Min(1f, scrubber.VolumeRate / tile.Volume) * tile.TotalMoles; - // Take a gas sample. - var removed = tile.Remove(transferMoles); - - // Nothing left to remove from the tile. - if (MathHelper.CloseToPercent(removed.TotalMoles, 0f)) - return; - - atmosphereSystem.ScrubInto(removed, outlet.Air, scrubber.FilterGases); + _atmosphereSystem.ScrubInto(removed, outlet.Air, scrubber.FilterGases); // Remix the gases. - atmosphereSystem.Merge(tile, removed); + _atmosphereSystem.Merge(tile, removed); } else if (scrubber.PumpDirection == ScrubberPumpDirection.Siphoning) { appearance?.SetData(ScrubberVisuals.State, ScrubberState.Siphon); - var transferMoles = tile.TotalMoles * (scrubber.VolumeRate / tile.Volume); - - var removed = tile.Remove(transferMoles); _atmosphereSystem.Merge(outlet.Air, removed); } diff --git a/Content.Shared/Atmos/Atmospherics.cs b/Content.Shared/Atmos/Atmospherics.cs index bd9b2cc050..b1fc05ed3e 100644 --- a/Content.Shared/Atmos/Atmospherics.cs +++ b/Content.Shared/Atmos/Atmospherics.cs @@ -263,12 +263,12 @@ namespace Content.Shared.Atmos #region Pipes /// - /// The pressure pumps and powered equipment max out at, in kPa. + /// The default pressure at which pumps and powered equipment max out at, in kPa. /// public const float MaxOutputPressure = 4500; /// - /// The maximum speed powered equipment can work at, in L/s. + /// The default maximum speed powered equipment can work at, in L/s. /// public const float MaxTransferRate = 200; diff --git a/Content.Shared/Atmos/Piping/EnabledAtmosDeviceVisuals.cs b/Content.Shared/Atmos/Piping/EnabledAtmosDeviceVisuals.cs index 5f3883a25c..d5cc51895a 100644 --- a/Content.Shared/Atmos/Piping/EnabledAtmosDeviceVisuals.cs +++ b/Content.Shared/Atmos/Piping/EnabledAtmosDeviceVisuals.cs @@ -28,7 +28,7 @@ namespace Content.Shared.Atmos.Piping } [Serializable, NetSerializable] - public enum PressurePumpVisuals : byte + public enum PumpVisuals : byte { Enabled, } diff --git a/Content.Shared/Atmos/Piping/Unary/Components/SharedVentPumpComponent.cs b/Content.Shared/Atmos/Piping/Unary/Components/SharedVentPumpComponent.cs index e9718fcadc..37c88c4531 100644 --- a/Content.Shared/Atmos/Piping/Unary/Components/SharedVentPumpComponent.cs +++ b/Content.Shared/Atmos/Piping/Unary/Components/SharedVentPumpComponent.cs @@ -73,5 +73,6 @@ namespace Content.Shared.Atmos.Piping.Unary.Components NoBound = 0, InternalBound = 1, ExternalBound = 2, + Both = 3, } } diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/binary.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/binary.yml index ae94ae512f..d62ea2bf0c 100644 --- a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/binary.yml +++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/binary.yml @@ -67,10 +67,13 @@ state: pipeStraight map: [ "enum.PipeColorVisualizer+Layers.Pipe" ] - state: pumpVolume - map: [ "enum.SubfloorLayers.FirstLayer" ] + map: [ "enum.SubfloorLayers.FirstLayer", "enum.PressurePumpVisualizer+Layers.Enabled" ] - type: Appearance visuals: - type: PipeColorVisualizer + - type: PressurePumpVisualizer + disabledState: pumpVolume + enabledState: pumpVolumeOn - type: GasVolumePump - type: UserInterface interfaces: