Fix dual port vents 2: Electric Boogaloo (#8396)

This commit is contained in:
Leon Friedrich
2022-06-06 20:38:20 +12:00
committed by GitHub
parent 9964e20abd
commit cbae005d08
7 changed files with 100 additions and 153 deletions

View File

@@ -1,46 +0,0 @@
using Content.Shared.Atmos;
using Content.Shared.Atmos.Piping.Unary.Components;
namespace Content.Server.Atmos.Piping.Binary.Components
{
[RegisterComponent]
public sealed class GasDualPortVentPumpComponent : Component
{
[ViewVariables(VVAccess.ReadWrite)]
public bool Enabled { get; set; } = true;
[ViewVariables(VVAccess.ReadWrite)]
public bool Welded { get; set; } = false;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("inlet")]
public string InletName { get; set; } = "inlet";
[ViewVariables(VVAccess.ReadWrite)]
[DataField("outlet")]
public string OutletName { get; set; } = "outlet";
[ViewVariables(VVAccess.ReadWrite)]
public VentPumpDirection PumpDirection { get; set; } = VentPumpDirection.Releasing;
[ViewVariables(VVAccess.ReadWrite)]
public DualPortVentPressureBound PressureChecks { get; set; } = DualPortVentPressureBound.ExternalBound;
[ViewVariables(VVAccess.ReadWrite)]
public float ExternalPressureBound { get; set; } = Atmospherics.OneAtmosphere;
[ViewVariables(VVAccess.ReadWrite)]
public float InputPressureMin { get; set; } = 0f;
[ViewVariables(VVAccess.ReadWrite)]
public float OutputPressureMax { get; set; } = 0f;
}
[Flags]
public enum DualPortVentPressureBound : sbyte
{
NoBound = 0,
ExternalBound = 1,
InputMinimum = 2,
}
}

View File

@@ -1,103 +0,0 @@
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.Unary.Components;
using Content.Shared.Atmos.Visuals;
using JetBrains.Annotations;
namespace Content.Server.Atmos.Piping.Binary.EntitySystems
{
[UsedImplicitly]
public sealed class GasDualPortVentPumpSystem : EntitySystem
{
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GasDualPortVentPumpComponent, AtmosDeviceUpdateEvent>(OnGasDualPortVentPumpUpdated);
SubscribeLocalEvent<GasDualPortVentPumpComponent, AtmosDeviceDisabledEvent>(OnGasDualPortVentPumpDisabled);
}
private void OnGasDualPortVentPumpUpdated(EntityUid uid, GasDualPortVentPumpComponent vent, AtmosDeviceUpdateEvent args)
{
var appearance = EntityManager.GetComponentOrNull<AppearanceComponent>(vent.Owner);
if (vent.Welded)
{
appearance?.SetData(VentPumpVisuals.State, VentPumpState.Welded);
return;
}
if (!vent.Enabled
|| !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)
|| !nodeContainer.TryGetNode(vent.InletName, out PipeNode? inlet)
|| !nodeContainer.TryGetNode(vent.OutletName, out PipeNode? outlet))
{
appearance?.SetData(VentPumpVisuals.State, VentPumpState.Off);
return;
}
var environment = _atmosphereSystem.GetTileMixture(EntityManager.GetComponent<TransformComponent>(vent.Owner).Coordinates, true);
// We're in an air-blocked tile... Do nothing.
if (environment == null)
{
appearance?.SetData(VentPumpVisuals.State, VentPumpState.Off);
return;
}
if (vent.PumpDirection == VentPumpDirection.Releasing)
{
appearance?.SetData(VentPumpVisuals.State, VentPumpState.Out);
var pressureDelta = 10000f;
if ((vent.PressureChecks & DualPortVentPressureBound.ExternalBound) != 0)
pressureDelta = MathF.Min(pressureDelta, (vent.ExternalPressureBound - environment.Pressure));
if ((vent.PressureChecks & DualPortVentPressureBound.InputMinimum) != 0)
pressureDelta = MathF.Min(pressureDelta, (inlet.Air.Pressure - vent.InputPressureMin));
if (pressureDelta > 0 && inlet.Air.Temperature > 0)
{
var transferMoles = pressureDelta * environment.Volume / inlet.Air.Temperature * Atmospherics.R;
var removed = inlet.Air.Remove(transferMoles);
_atmosphereSystem.Merge(environment, removed);
}
}
else if (vent.PumpDirection == VentPumpDirection.Siphoning && environment.Pressure > 0f)
{
appearance?.SetData(VentPumpVisuals.State, VentPumpState.In);
var ourMultiplier = outlet.Air.Volume / environment.Temperature * Atmospherics.R;
var molesDelta = 10000 * ourMultiplier;
if ((vent.PressureChecks & DualPortVentPressureBound.ExternalBound) != 0)
molesDelta =
MathF.Min(molesDelta,
(environment.Pressure - vent.OutputPressureMax) * environment.Volume / (environment.Temperature * Atmospherics.R));
if ((vent.PressureChecks &DualPortVentPressureBound.InputMinimum) != 0)
molesDelta = MathF.Min(molesDelta, (vent.InputPressureMin - outlet.Air.Pressure) * ourMultiplier);
if (molesDelta > 0)
{
var removed = environment.Remove(molesDelta);
_atmosphereSystem.Merge(outlet.Air, removed);
}
}
}
private void OnGasDualPortVentPumpDisabled(EntityUid uid, GasDualPortVentPumpComponent vent, AtmosDeviceDisabledEvent args)
{
if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance))
{
appearance.SetData(VentPumpVisuals.State, VentPumpState.Off);
}
}
}
}

View File

@@ -1,5 +1,7 @@
using Content.Shared.Atmos;
using Content.Shared.Atmos.Piping.Unary.Components;
using Content.Shared.MachineLinking;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Atmos.Piping.Unary.Components
{
@@ -17,7 +19,11 @@ namespace Content.Server.Atmos.Piping.Unary.Components
[ViewVariables(VVAccess.ReadWrite)]
[DataField("inlet")]
public string InletName { get; set; } = "pipe";
public string Inlet { get; set; } = "pipe";
[ViewVariables(VVAccess.ReadWrite)]
[DataField("outlet")]
public string Outlet { get; set; } = "pipe";
[ViewVariables(VVAccess.ReadWrite)]
[DataField("pumpDirection")]
@@ -72,6 +78,28 @@ namespace Content.Server.Atmos.Piping.Unary.Components
[DataField("targetPressureChange")]
public float TargetPressureChange = Atmospherics.OneAtmosphere;
#region Machine Linking
/// <summary>
/// Whether or not machine linking is enabled for this component.
/// </summary>
[DataField("canLink")]
public readonly bool CanLink = false;
[DataField("pressurizePort", customTypeSerializer: typeof(PrototypeIdSerializer<ReceiverPortPrototype>))]
public string PressurizePort = "Pressurize";
[DataField("depressurizePort", customTypeSerializer: typeof(PrototypeIdSerializer<ReceiverPortPrototype>))]
public string DepressurizePort = "Depressurize";
[ViewVariables(VVAccess.ReadWrite)]
[DataField("pressurizePressure")]
public float PressurizePressure = Atmospherics.OneAtmosphere;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("depressurizePressure")]
public float DepressurizePressure = 0;
#endregion
public GasVentPumpData ToAirAlarmData()
{
return new GasVentPumpData

View File

@@ -6,6 +6,8 @@ using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Components;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.MachineLinking.Events;
using Content.Server.MachineLinking.System;
using Content.Server.NodeContainer;
using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.Components;
@@ -24,6 +26,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
{
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly DeviceNetworkSystem _deviceNetSystem = default!;
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!;
@@ -37,6 +40,8 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
SubscribeLocalEvent<GasVentPumpComponent, AtmosMonitorAlarmEvent>(OnAtmosAlarm);
SubscribeLocalEvent<GasVentPumpComponent, PowerChangedEvent>(OnPowerChanged);
SubscribeLocalEvent<GasVentPumpComponent, DeviceNetworkPacketEvent>(OnPacketRecv);
SubscribeLocalEvent<GasVentPumpComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<GasVentPumpComponent, SignalReceivedEvent>(OnSignalReceived);
}
private void OnGasVentPumpUpdated(EntityUid uid, GasVentPumpComponent vent, AtmosDeviceUpdateEvent args)
@@ -47,10 +52,17 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
return;
}
var nodeName = vent.PumpDirection switch
{
VentPumpDirection.Releasing => vent.Inlet,
VentPumpDirection.Siphoning => vent.Outlet,
_ => throw new ArgumentOutOfRangeException()
};
if (!vent.Enabled
|| !TryComp(uid, out AtmosDeviceComponent? device)
|| !TryComp(uid, out NodeContainerComponent? nodeContainer)
|| !nodeContainer.TryGetNode(vent.InletName, out PipeNode? pipe))
|| !nodeContainer.TryGetNode(nodeName, out PipeNode? pipe))
{
return;
}
@@ -191,6 +203,33 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
}
}
private void OnInit(EntityUid uid, GasVentPumpComponent component, ComponentInit args)
{
if (component.CanLink)
_signalSystem.EnsureReceiverPorts(uid, component.PressurizePort, component.DepressurizePort);
}
private void OnSignalReceived(EntityUid uid, GasVentPumpComponent component, SignalReceivedEvent args)
{
if (!component.CanLink)
return;
if (args.Port == component.PressurizePort)
{
component.PumpDirection = VentPumpDirection.Releasing;
component.ExternalPressureBound = component.PressurizePressure;
component.PressureChecks = VentPressureBound.ExternalBound;
UpdateState(uid, component);
}
else if (args.Port == component.DepressurizePort)
{
component.PumpDirection = VentPumpDirection.Siphoning;
component.ExternalPressureBound = component.DepressurizePressure;
component.PressureChecks = VentPressureBound.ExternalBound;
UpdateState(uid, component);
}
}
private void UpdateState(EntityUid uid, GasVentPumpComponent vent, AppearanceComponent? appearance = null)
{
if (!Resolve(uid, ref appearance, false))

View File

@@ -27,3 +27,9 @@ signal-port-description-order-sender = Cargo console order sender
signal-port-name-order-receiver = Order receiver
signal-port-description-order-receiver = Cargo console order receiver
signal-port-name-pressurize = Pressurize
signal-port-description-pressurize = Causes the device to starts releasing air until some target pressure is reached.
signal-port-name-depressurize = Depressurize
signal-port-description-depressurize = Causes the device to starts siphoning air until some target pressure is reached.

View File

@@ -206,10 +206,10 @@
node: port
- type: entity
parent: GasUnaryBase
parent: GasVentPump
id: GasDualPortVentPump
name: dual-port air vent
description: Has a valve and a pump attached to it. There are two ports.
description: Has a valve and a pump attached to it. There are two ports, one is an input for releasing air, the other is an output when siphoning.
placement:
mode: SnapgridCenter
components:
@@ -228,6 +228,19 @@
- type: PipeColorVisualizer
- type: VentPumpVisualizer
- type: GasVentPump
inlet: inlet
outlet: outlet
canLink: true
- type: Construction
graph: GasBinary
node: dualportventpump
- type: NodeContainer
nodes:
inlet:
!type:PipeNode
nodeGroupID: Pipe
pipeDirection: North
outlet:
!type:PipeNode
nodeGroupID: Pipe
pipeDirection: South

View File

@@ -42,3 +42,13 @@
id: OrderReceiver
name: signal-port-name-order-receiver
description: signal-port-description-order-receiver
- type: receiverPort
id: Pressurize
name: signal-port-name-pressurize
description: signal-port-description-pressurize
- type: receiverPort
id: Depressurize
name: signal-port-name-depressurize
description: signal-port-description-depressurize