Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

atmos circulation #33380

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions Content.Client/Atmos/Monitor/UI/Widgets/ScrubberControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,14 @@
<FloatSpinBox Name="CVolumeRate" HorizontalExpand="True" />
</BoxContainer>
</BoxContainer>
<BoxContainer>
<CheckBox Name="CWideNet" Text="{Loc 'air-alarm-ui-scrubber-wide-net-label'}" />
<BoxContainer Orientation="Horizontal" Margin="0 0 0 2" HorizontalExpand="True">
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<CheckBox Name="CWideNet" Text="{Loc 'air-alarm-ui-scrubber-wide-net-label'}" />
</BoxContainer>
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<Label Text="{Loc 'air-alarm-ui-scrubber-target-pressure-label'}" Margin="0 0 0 1" />
<FloatSpinBox Name="CTargetPressure" HorizontalExpand="True" />
</BoxContainer>
</BoxContainer>
<BoxContainer Orientation="Horizontal" Margin ="0 0 0 2">
<Button Name="CCopySettings" Text="{Loc 'air-alarm-ui-widget-copy'}" ToolTip="{Loc 'air-alarm-ui-widget-copy-tooltip'}" />
Expand Down
70 changes: 62 additions & 8 deletions Content.Client/Atmos/Monitor/UI/Widgets/ScrubberControl.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Content.Client.Stylesheets;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Monitor.Components;
Expand All @@ -26,6 +27,7 @@ public sealed partial class ScrubberControl : BoxContainer
private CollapsibleHeading _addressLabel => CAddress;
private OptionButton _pumpDirection => CPumpDirection;
private FloatSpinBox _volumeRate => CVolumeRate;
private FloatSpinBox _targetPressure => CTargetPressure;
private CheckBox _wideNet => CWideNet;
private Button _copySettings => CCopySettings;

Expand Down Expand Up @@ -65,6 +67,13 @@ public ScrubberControl(GasVentScrubberData data, string address)
};
_volumeRate.IsValid += value => value >= 0;

_targetPressure.Value = _data.TargetPressure;
_targetPressure.OnValueChanged += _ =>
{
_data.TargetPressure = _targetPressure.Value;
ScrubberDataChanged?.Invoke(address, _data);
};

foreach (var value in Enum.GetValues<ScrubberPumpDirection>())
{
_pumpDirection.AddItem(Loc.GetString($"{value}"), (int) value);
Expand All @@ -90,15 +99,47 @@ public ScrubberControl(GasVentScrubberData data, string address)
Name = value.ToString(),
Text = Loc.GetString($"{value}"),
ToggleMode = true,
HorizontalExpand = true,
Pressed = _data.FilterGases.Contains(value)
HorizontalExpand = true
};
gasButton.OnToggled += args =>
if (_data.FilterGases.Contains(value))
{
gasButton.StyleClasses.Add("ButtonColorGreen");
}
else if (!_data.OverflowGases.Contains(value))
{
if (args.Pressed)
_data.FilterGases.Add(value);
else
_data.FilterGases.Remove(value);
gasButton.StyleClasses.Add(StyleBase.ButtonCaution);
}
gasButton.OnPressed += args =>
{
var beforeState = 0; // Disabled
if (_data.OverflowGases.Contains(value))
{
beforeState = 1; // Overflow
}
else if (_data.FilterGases.Contains(value))
{
beforeState = 2; // Filter
}

_data.FilterGases.Remove(value);
_data.OverflowGases.Remove(value);
gasButton.StyleClasses.Remove("ButtonColorGreen");
gasButton.StyleClasses.Remove(StyleBase.ButtonCaution);
gasButton.Pressed = false;

switch (beforeState)
{
case 0: // Disabled -> Overflow
_data.OverflowGases.Add(value);
break;
case 1: // Overflow -> Filter
_data.FilterGases.Add(value);
gasButton.StyleClasses.Add("ButtonColorGreen");
break;
case 2: // Filter -> Disabled
gasButton.StyleClasses.Add(StyleBase.ButtonCaution);
break;
}

ScrubberDataChanged?.Invoke(_address, _data);
};
Expand All @@ -119,13 +160,26 @@ public void ChangeData(GasVentScrubberData data)
_data.VolumeRate = data.VolumeRate;
_volumeRate.Value = _data.VolumeRate;

_data.TargetPressure = data.TargetPressure;
_targetPressure.Value = _data.TargetPressure;

_data.WideNet = data.WideNet;
_wideNet.Pressed = _data.WideNet;
_data.FilterGases = data.FilterGases;
_data.OverflowGases = data.OverflowGases;

foreach (var value in Enum.GetValues<Gas>())
{
_gasControls[value].Pressed = data.FilterGases.Contains(value);
_gasControls[value].StyleClasses.Remove("ButtonColorGreen");
_gasControls[value].StyleClasses.Remove(StyleBase.ButtonCaution);
if (data.FilterGases.Contains(value))
{
_gasControls[value].StyleClasses.Add("ButtonColorGreen");
}
else if (!data.OverflowGases.Contains(value))
{
_gasControls[value].StyleClasses.Add(StyleBase.ButtonCaution);
}
}
}
}
17 changes: 17 additions & 0 deletions Content.Server/Atmos/EntitySystems/AtmosphereSystem.Gases.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,23 @@ public void ScrubInto(GasMixture mixture, GasMixture destination, IReadOnlyColle
Merge(destination, buffer);
}

/// <summary>
/// Scrubs a fraction of specified gases from a gas mixture into a <see cref="destination"/> gas mixture.
/// </summary>
public void ScrubInto(GasMixture mixture, GasMixture destination, IReadOnlyCollection<Gas> filterGases, float fraction)
{
var buffer = new GasMixture(mixture.Volume) { Temperature = mixture.Temperature };

foreach (var gas in filterGases)
{
var moles = mixture.GetMoles(gas) * fraction;
buffer.AdjustMoles(gas, moles);
mixture.AdjustMoles(gas, -moles);
}

Merge(destination, buffer);
}

/// <summary>
/// Checks whether a gas mixture is probably safe.
/// This only checks temperature and pressure, not gas composition.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public float ExternalPressureBound
}
}

private float _externalPressureBound = Atmospherics.OneAtmosphere;
private float _externalPressureBound = Atmospherics.OneAtmosphereTarget;

[DataField]
public float InternalPressureBound
Expand Down Expand Up @@ -138,7 +138,7 @@ public float InternalPressureBound
public string DepressurizePort = "Depressurize";

[DataField]
public float PressurizePressure = Atmospherics.OneAtmosphere;
public float PressurizePressure = Atmospherics.OneAtmosphereTarget;

[DataField]
public float DepressurizePressure = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public sealed partial class GasVentScrubberComponent : Component

[DataField]
public HashSet<Gas> FilterGases = new(GasVentScrubberData.DefaultFilterGases);
[DataField]
public HashSet<Gas> OverflowGases = new(GasVentScrubberData.DefaultOverflowGases);

[DataField]
public ScrubberPumpDirection PumpDirection { get; set; } = ScrubberPumpDirection.Scrubbing;
Expand All @@ -36,6 +38,17 @@ public float TransferRate

private float _transferRate = Atmospherics.MaxTransferRate;

/// <summary>
/// Target pressure. If the pressure is below this value only priority gases are getting scrubbed.
/// </summary>
[DataField]
public float TargetPressure
{
get => _targetPressure;
set => _targetPressure = Math.Max(value, 0f);
}
private float _targetPressure = Atmospherics.OneAtmosphere;

[DataField]
public float MaxTransferRate = Atmospherics.MaxTransferRate;

Expand All @@ -56,8 +69,10 @@ public GasVentScrubberData ToAirAlarmData()
Enabled = Enabled,
Dirty = IsDirty,
FilterGases = FilterGases,
OverflowGases = OverflowGases,
PumpDirection = PumpDirection,
VolumeRate = TransferRate,
TargetPressure = TargetPressure,
WideNet = WideNet
};
}
Expand All @@ -68,6 +83,7 @@ public void FromAirAlarmData(GasVentScrubberData data)
IsDirty = data.Dirty;
PumpDirection = data.PumpDirection;
TransferRate = data.VolumeRate;
TargetPressure = data.TargetPressure;
WideNet = data.WideNet;

if (!data.FilterGases.SequenceEqual(FilterGases))
Expand All @@ -76,6 +92,12 @@ public void FromAirAlarmData(GasVentScrubberData data)
foreach (var gas in data.FilterGases)
FilterGases.Add(gas);
}
if (!data.OverflowGases.SequenceEqual(OverflowGases))
{
OverflowGases.Clear();
foreach (var gas in data.OverflowGases)
OverflowGases.Add(gas);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,13 @@ private void OnVentScrubberEnterAtmosphere(EntityUid uid, GasVentScrubberCompone

private void Scrub(float timeDelta, GasVentScrubberComponent scrubber, GasMixture? tile, PipeNode outlet)
{
Scrub(timeDelta, scrubber.TransferRate*_atmosphereSystem.PumpSpeedup(), scrubber.PumpDirection, scrubber.FilterGases, tile, outlet.Air);
Scrub(timeDelta, scrubber.TransferRate*_atmosphereSystem.PumpSpeedup(), scrubber.TargetPressure, scrubber.PumpDirection, scrubber.FilterGases, scrubber.OverflowGases, tile, outlet.Air);
}

/// <summary>
/// True if we were able to scrub, false if we were not.
/// </summary>
public bool Scrub(float timeDelta, float transferRate, ScrubberPumpDirection mode, HashSet<Gas> filterGases, GasMixture? tile, GasMixture destination)
public bool Scrub(float timeDelta, float transferRate, float targetPressure, ScrubberPumpDirection mode, HashSet<Gas> filterGases, HashSet<Gas> overflowGases, GasMixture? tile, GasMixture destination)
{
// Cannot scrub if tile is null or air-blocked.
if (tile == null
Expand All @@ -100,6 +100,7 @@ public bool Scrub(float timeDelta, float transferRate, ScrubberPumpDirection mod
}

// Take a gas sample.
var aboveTarget = tile.Pressure > targetPressure;
var ratio = MathF.Min(1f, timeDelta * transferRate / tile.Volume);
var removed = tile.RemoveRatio(ratio);

Expand All @@ -109,6 +110,10 @@ public bool Scrub(float timeDelta, float transferRate, ScrubberPumpDirection mod

if (mode == ScrubberPumpDirection.Scrubbing)
{
if (aboveTarget)
{
_atmosphereSystem.ScrubInto(removed, destination, overflowGases, 0.5f);
}
_atmosphereSystem.ScrubInto(removed, destination, filterGases);

// Remix the gases.
Expand Down
2 changes: 1 addition & 1 deletion Content.Server/Atmos/Portable/PortableScrubberSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ private void OnDestroyed(EntityUid uid, PortableScrubberComponent component, Des

private bool Scrub(float timeDelta, PortableScrubberComponent scrubber, GasMixture? tile)
{
return _scrubberSystem.Scrub(timeDelta, scrubber.TransferRate * _atmosphereSystem.PumpSpeedup(), ScrubberPumpDirection.Scrubbing, scrubber.FilterGases, tile, scrubber.Air);
return _scrubberSystem.Scrub(timeDelta, scrubber.TransferRate * _atmosphereSystem.PumpSpeedup(), Atmospherics.OneAtmosphere, ScrubberPumpDirection.Scrubbing, scrubber.FilterGases, [], tile, scrubber.Air);
}

private void UpdateAppearance(EntityUid uid, bool isFull, bool isRunning)
Expand Down
6 changes: 6 additions & 0 deletions Content.Shared/Atmos/Atmospherics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ public static class Atmospherics
/// </summary>
public const float OneAtmosphere = 101.325f;

/// <summary>
/// Default target for vents in kPA.
/// It is set slightly higher than 1 ATM, as to cause air to circulate.
/// </summary>
public const float OneAtmosphereTarget = OneAtmosphere * 1.05f;

/// <summary>
/// Maximum external pressure (in kPA) a gas miner will, by default, output to.
/// This is used to initialize roundstart atmos rooms.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public sealed class GasVentPumpData : IAtmosDeviceData
public bool IgnoreAlarms { get; set; } = false;
public VentPumpDirection PumpDirection { get; set; } = VentPumpDirection.Releasing;
public VentPressureBound PressureChecks { get; set; } = VentPressureBound.ExternalBound;
public float ExternalPressureBound { get; set; } = Atmospherics.OneAtmosphere;
public float ExternalPressureBound { get; set; } = Atmospherics.OneAtmosphereTarget;
public float InternalPressureBound { get; set; } = 0f;
public bool PressureLockoutOverride { get; set; } = false;

Expand All @@ -22,7 +22,7 @@ public sealed class GasVentPumpData : IAtmosDeviceData
Enabled = true,
PumpDirection = VentPumpDirection.Releasing,
PressureChecks = VentPressureBound.ExternalBound,
ExternalPressureBound = Atmospherics.OneAtmosphere,
ExternalPressureBound = Atmospherics.OneAtmosphereTarget,
InternalPressureBound = 0f,
PressureLockoutOverride = false
};
Expand All @@ -44,19 +44,7 @@ public sealed class GasVentPumpData : IAtmosDeviceData
Dirty = true,
PumpDirection = VentPumpDirection.Releasing,
PressureChecks = VentPressureBound.ExternalBound,
ExternalPressureBound = Atmospherics.OneAtmosphere,
InternalPressureBound = 0f,
PressureLockoutOverride = false
};

public static GasVentPumpData ReplaceModePreset = new GasVentPumpData
{
Enabled = false,
IgnoreAlarms = true,
Dirty = true,
PumpDirection = VentPumpDirection.Releasing,
PressureChecks = VentPressureBound.ExternalBound,
ExternalPressureBound = Atmospherics.OneAtmosphere,
ExternalPressureBound = Atmospherics.OneAtmosphereTarget,
InternalPressureBound = 0f,
PressureLockoutOverride = false
};
Expand Down
Loading
Loading