Make atmos Turing-complete (#10520)
* Add pneumatic valves Pneumatic valves permit bidirectional flow between the inlet and outlet if the pressure at the control port is high enough. * Add construction recipe
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Atmos.Piping.Components;
|
||||
using Content.Server.Atmos.Piping.Trinary.Components;
|
||||
using Content.Server.NodeContainer;
|
||||
using Content.Server.NodeContainer.Nodes;
|
||||
using Content.Shared.Atmos.Piping;
|
||||
using Content.Shared.Audio;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class PressureControlledValveSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<PressureControlledValveComponent, ComponentInit>(OnInit);
|
||||
SubscribeLocalEvent<PressureControlledValveComponent, AtmosDeviceUpdateEvent>(OnUpdate);
|
||||
SubscribeLocalEvent<PressureControlledValveComponent, AtmosDeviceDisabledEvent>(OnFilterLeaveAtmosphere);
|
||||
}
|
||||
|
||||
private void OnInit(EntityUid uid, PressureControlledValveComponent comp, ComponentInit args)
|
||||
{
|
||||
UpdateAppearance(uid, comp);
|
||||
}
|
||||
|
||||
private void OnUpdate(EntityUid uid, PressureControlledValveComponent comp, AtmosDeviceUpdateEvent args)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)
|
||||
|| !EntityManager.TryGetComponent(uid, out AtmosDeviceComponent? device)
|
||||
|| !nodeContainer.TryGetNode(comp.InletName, out PipeNode? inletNode)
|
||||
|| !nodeContainer.TryGetNode(comp.ControlName, out PipeNode? controlNode)
|
||||
|| !nodeContainer.TryGetNode(comp.OutletName, out PipeNode? outletNode))
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(comp.Owner, false);
|
||||
comp.Enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// If output is higher than input, flip input/output to enable bidirectional flow.
|
||||
if (outletNode.Air.Pressure > inletNode.Air.Pressure)
|
||||
{
|
||||
PipeNode temp = outletNode;
|
||||
outletNode = inletNode;
|
||||
inletNode = temp;
|
||||
}
|
||||
|
||||
float control = (controlNode.Air.Pressure - outletNode.Air.Pressure) - comp.Threshold;
|
||||
float transferRate;
|
||||
if (control < 0)
|
||||
{
|
||||
comp.Enabled = false;
|
||||
transferRate = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
comp.Enabled = true;
|
||||
transferRate = Math.Min(control * comp.Gain, comp.MaxTransferRate);
|
||||
}
|
||||
UpdateAppearance(uid, comp);
|
||||
|
||||
// We multiply the transfer rate in L/s by the seconds passed since the last process to get the liters.
|
||||
var transferRatio = (float)(transferRate * (_gameTiming.CurTime - device.LastProcess).TotalSeconds) / inletNode.Air.Volume;
|
||||
if (transferRatio <= 0)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(comp.Owner, false);
|
||||
return;
|
||||
}
|
||||
|
||||
_ambientSoundSystem.SetAmbience(comp.Owner, true);
|
||||
var removed = inletNode.Air.RemoveRatio(transferRatio);
|
||||
_atmosphereSystem.Merge(outletNode.Air, removed);
|
||||
}
|
||||
|
||||
private void OnFilterLeaveAtmosphere(EntityUid uid, PressureControlledValveComponent comp, AtmosDeviceDisabledEvent args)
|
||||
{
|
||||
comp.Enabled = false;
|
||||
UpdateAppearance(uid, comp);
|
||||
_ambientSoundSystem.SetAmbience(comp.Owner, false);
|
||||
}
|
||||
|
||||
private void UpdateAppearance(EntityUid uid, PressureControlledValveComponent? comp = null, AppearanceComponent? appearance = null)
|
||||
{
|
||||
if (!Resolve(uid, ref comp, ref appearance, false))
|
||||
return;
|
||||
|
||||
appearance.SetData(FilterVisuals.Enabled, comp.Enabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user