diff --git a/Content.Client/Atmos/UI/GasAnalyzerWindow.xaml.cs b/Content.Client/Atmos/UI/GasAnalyzerWindow.xaml.cs
index b105e629cf..b54af3a587 100644
--- a/Content.Client/Atmos/UI/GasAnalyzerWindow.xaml.cs
+++ b/Content.Client/Atmos/UI/GasAnalyzerWindow.xaml.cs
@@ -163,6 +163,26 @@ namespace Content.Client.Atmos.UI
parent.AddChild(panel);
panel.AddChild(dataContainer);
+ // Volume label
+ var volBox = new BoxContainer { Orientation = BoxContainer.LayoutOrientation.Horizontal };
+
+ volBox.AddChild(new Label
+ {
+ Text = Loc.GetString("gas-analyzer-window-volume-text")
+ });
+ volBox.AddChild(new Control
+ {
+ MinSize = new Vector2(10, 0),
+ HorizontalExpand = true
+ });
+ volBox.AddChild(new Label
+ {
+ Text = Loc.GetString("gas-analyzer-window-volume-val-text", ("volume", $"{gasMix.Volume:0.##}")),
+ Align = Label.AlignMode.Right,
+ HorizontalExpand = true
+ });
+ dataContainer.AddChild(volBox);
+
// Pressure label
var presBox = new BoxContainer { Orientation = BoxContainer.LayoutOrientation.Horizontal };
diff --git a/Content.Server/Atmos/EntitySystems/GasAnalyzerSystem.cs b/Content.Server/Atmos/EntitySystems/GasAnalyzerSystem.cs
index 2eedb1c6a7..1f5ca80935 100644
--- a/Content.Server/Atmos/EntitySystems/GasAnalyzerSystem.cs
+++ b/Content.Server/Atmos/EntitySystems/GasAnalyzerSystem.cs
@@ -132,7 +132,7 @@ namespace Content.Server.Atmos.EntitySystems
///
private void OnDisabledMessage(EntityUid uid, GasAnalyzerComponent component, GasAnalyzerDisableMessage message)
{
- if (message.Session.AttachedEntity is not {Valid: true})
+ if (message.Session.AttachedEntity is not { Valid: true })
return;
DisableAnalyzer(uid, component);
}
@@ -169,7 +169,7 @@ namespace Content.Server.Atmos.EntitySystems
// Check if position is out of range => don't update and disable
if (!component.LastPosition.Value.InRange(EntityManager, _transform, userPos, SharedInteractionSystem.InteractionRange))
{
- if(component.User is { } userId && component.Enabled)
+ if (component.User is { } userId && component.Enabled)
_popup.PopupEntity(Loc.GetString("gas-analyzer-shutoff"), userId, userId);
DisableAnalyzer(uid, component, component.User);
return false;
@@ -182,13 +182,13 @@ namespace Content.Server.Atmos.EntitySystems
var tileMixture = _atmo.GetContainingMixture(uid, true);
if (tileMixture != null)
{
- gasMixList.Add(new GasMixEntry(Loc.GetString("gas-analyzer-window-environment-tab-label"), tileMixture.Pressure, tileMixture.Temperature,
+ gasMixList.Add(new GasMixEntry(Loc.GetString("gas-analyzer-window-environment-tab-label"), tileMixture.Volume, tileMixture.Pressure, tileMixture.Temperature,
GenerateGasEntryArray(tileMixture)));
}
else
{
// No gases were found
- gasMixList.Add(new GasMixEntry(Loc.GetString("gas-analyzer-window-environment-tab-label"), 0f, 0f));
+ gasMixList.Add(new GasMixEntry(Loc.GetString("gas-analyzer-window-environment-tab-label"), 0f, 0f, 0f));
}
var deviceFlipped = false;
@@ -209,8 +209,8 @@ namespace Content.Server.Atmos.EntitySystems
{
foreach (var mixes in ev.GasMixtures)
{
- if(mixes.Value != null)
- gasMixList.Add(new GasMixEntry(mixes.Key, mixes.Value.Pressure, mixes.Value.Temperature, GenerateGasEntryArray(mixes.Value)));
+ if (mixes.Item2 != null)
+ gasMixList.Add(new GasMixEntry(mixes.Item1, mixes.Item2.Volume, mixes.Item2.Pressure, mixes.Item2.Temperature, GenerateGasEntryArray(mixes.Item2)));
}
deviceFlipped = ev.DeviceFlipped;
@@ -223,7 +223,16 @@ namespace Content.Server.Atmos.EntitySystems
foreach (var pair in node.Nodes)
{
if (pair.Value is PipeNode pipeNode)
- gasMixList.Add(new GasMixEntry(pair.Key, pipeNode.Air.Pressure, pipeNode.Air.Temperature, GenerateGasEntryArray(pipeNode.Air)));
+ {
+ // check if the volume is zero for some reason so we don't divide by zero
+ if (pipeNode.Air.Volume == 0f)
+ continue;
+ // only display the gas in the analyzed pipe element, not the whole system
+ var pipeAir = pipeNode.Air.Clone();
+ pipeAir.Multiply(pipeNode.Volume / pipeNode.Air.Volume);
+ pipeAir.Volume = pipeNode.Volume;
+ gasMixList.Add(new GasMixEntry(pair.Key, pipeAir.Volume, pipeAir.Pressure, pipeAir.Temperature, GenerateGasEntryArray(pipeAir)));
+ }
}
}
}
@@ -286,9 +295,9 @@ namespace Content.Server.Atmos.EntitySystems
public sealed class GasAnalyzerScanEvent : EntityEventArgs
{
///
- /// Key is the mix name (ex "pipe", "inlet", "filter"), value is the pipe direction and GasMixture. Add all mixes that should be reported when scanned.
+ /// The string is for the name (ex "pipe", "inlet", "filter"), GasMixture for the corresponding gas mix. Add all mixes that should be reported when scanned.
///
- public Dictionary? GasMixtures;
+ public List<(string, GasMixture?)>? GasMixtures;
///
/// If the device is flipped. Flipped is defined as when the inline input is 90 degrees CW to the side input
diff --git a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs b/Content.Server/Atmos/EntitySystems/GasTankSystem.cs
index 80842416e8..dd84756e45 100644
--- a/Content.Server/Atmos/EntitySystems/GasTankSystem.cs
+++ b/Content.Server/Atmos/EntitySystems/GasTankSystem.cs
@@ -359,7 +359,8 @@ namespace Content.Server.Atmos.EntitySystems
///
private void OnAnalyzed(EntityUid uid, GasTankComponent component, GasAnalyzerScanEvent args)
{
- args.GasMixtures = new Dictionary { {Name(uid), component.Air} };
+ args.GasMixtures ??= new List<(string, GasMixture?)>();
+ args.GasMixtures.Add((Name(uid), component.Air));
}
private void OnGasTankPrice(EntityUid uid, GasTankComponent component, ref PriceCalculationEvent args)
diff --git a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs
index fbd4260469..c0c2b930f6 100644
--- a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs
+++ b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasFilterSystem.cs
@@ -73,7 +73,7 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
if (filter.FilteredGas.HasValue)
{
- var filteredOut = new GasMixture() {Temperature = removed.Temperature};
+ var filteredOut = new GasMixture() { Temperature = removed.Temperature };
filteredOut.SetMoles(filter.FilteredGas.Value, removed.GetMoles(filter.FilteredGas.Value));
removed.SetMoles(filter.FilteredGas.Value, 0f);
@@ -180,17 +180,30 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
///
private void OnFilterAnalyzed(EntityUid uid, GasFilterComponent component, GasAnalyzerScanEvent args)
{
- if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer))
- return;
+ args.GasMixtures ??= new List<(string, GasMixture?)>();
- args.GasMixtures ??= new Dictionary();
-
- if(_nodeContainer.TryGetNode(nodeContainer, component.InletName, out PipeNode? inlet))
- args.GasMixtures.Add(Loc.GetString("gas-analyzer-window-text-inlet"), inlet.Air);
- if(_nodeContainer.TryGetNode(nodeContainer, component.FilterName, out PipeNode? filterNode))
- args.GasMixtures.Add(Loc.GetString("gas-analyzer-window-text-filter"), filterNode.Air);
- if(_nodeContainer.TryGetNode(nodeContainer, component.OutletName, out PipeNode? outlet))
- args.GasMixtures.Add(Loc.GetString("gas-analyzer-window-text-outlet"), outlet.Air);
+ // multiply by volume fraction to make sure to send only the gas inside the analyzed pipe element, not the whole pipe system
+ if (_nodeContainer.TryGetNode(uid, component.InletName, out PipeNode? inlet) && inlet.Air.Volume != 0f)
+ {
+ var inletAirLocal = inlet.Air.Clone();
+ inletAirLocal.Multiply(inlet.Volume / inlet.Air.Volume);
+ inletAirLocal.Volume = inlet.Volume;
+ args.GasMixtures.Add((Loc.GetString("gas-analyzer-window-text-inlet"), inletAirLocal));
+ }
+ if (_nodeContainer.TryGetNode(uid, component.FilterName, out PipeNode? filterNode) && filterNode.Air.Volume != 0f)
+ {
+ var filterNodeAirLocal = filterNode.Air.Clone();
+ filterNodeAirLocal.Multiply(filterNode.Volume / filterNode.Air.Volume);
+ filterNodeAirLocal.Volume = filterNode.Volume;
+ args.GasMixtures.Add((Loc.GetString("gas-analyzer-window-text-filter"), filterNodeAirLocal));
+ }
+ if (_nodeContainer.TryGetNode(uid, component.OutletName, out PipeNode? outlet) && outlet.Air.Volume != 0f)
+ {
+ var outletAirLocal = outlet.Air.Clone();
+ outletAirLocal.Multiply(outlet.Volume / outlet.Air.Volume);
+ outletAirLocal.Volume = outlet.Volume;
+ args.GasMixtures.Add((Loc.GetString("gas-analyzer-window-text-outlet"), outletAirLocal));
+ }
args.DeviceFlipped = inlet != null && filterNode != null && inlet.CurrentPipeDirection.ToDirection() == filterNode.CurrentPipeDirection.ToDirection().GetClockwise90Degrees();
}
diff --git a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs
index ba8ebf3c9a..4d7fc134c7 100644
--- a/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs
+++ b/Content.Server/Atmos/Piping/Trinary/EntitySystems/GasMixerSystem.cs
@@ -205,19 +205,31 @@ namespace Content.Server.Atmos.Piping.Trinary.EntitySystems
///
private void OnMixerAnalyzed(EntityUid uid, GasMixerComponent component, GasAnalyzerScanEvent args)
{
- if (!EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer))
- return;
+ args.GasMixtures ??= new List<(string, GasMixture?)>();
- var gasMixDict = new Dictionary();
+ // multiply by volume fraction to make sure to send only the gas inside the analyzed pipe element, not the whole pipe system
+ if (_nodeContainer.TryGetNode(uid, component.InletOneName, out PipeNode? inletOne) && inletOne.Air.Volume != 0f)
+ {
+ var inletOneAirLocal = inletOne.Air.Clone();
+ inletOneAirLocal.Multiply(inletOne.Volume / inletOne.Air.Volume);
+ inletOneAirLocal.Volume = inletOne.Volume;
+ args.GasMixtures.Add(($"{inletOne.CurrentPipeDirection} {Loc.GetString("gas-analyzer-window-text-inlet")}", inletOneAirLocal));
+ }
+ if (_nodeContainer.TryGetNode(uid, component.InletTwoName, out PipeNode? inletTwo) && inletTwo.Air.Volume != 0f)
+ {
+ var inletTwoAirLocal = inletTwo.Air.Clone();
+ inletTwoAirLocal.Multiply(inletTwo.Volume / inletTwo.Air.Volume);
+ inletTwoAirLocal.Volume = inletTwo.Volume;
+ args.GasMixtures.Add(($"{inletTwo.CurrentPipeDirection} {Loc.GetString("gas-analyzer-window-text-inlet")}", inletTwoAirLocal));
+ }
+ if (_nodeContainer.TryGetNode(uid, component.OutletName, out PipeNode? outlet) && outlet.Air.Volume != 0f)
+ {
+ var outletAirLocal = outlet.Air.Clone();
+ outletAirLocal.Multiply(outlet.Volume / outlet.Air.Volume);
+ outletAirLocal.Volume = outlet.Volume;
+ args.GasMixtures.Add((Loc.GetString("gas-analyzer-window-text-outlet"), outletAirLocal));
+ }
- if(_nodeContainer.TryGetNode(nodeContainer, component.InletOneName, out PipeNode? inletOne))
- gasMixDict.Add($"{inletOne.CurrentPipeDirection} {Loc.GetString("gas-analyzer-window-text-inlet")}", inletOne.Air);
- if(_nodeContainer.TryGetNode(nodeContainer, component.InletTwoName, out PipeNode? inletTwo))
- gasMixDict.Add($"{inletTwo.CurrentPipeDirection} {Loc.GetString("gas-analyzer-window-text-inlet")}", inletTwo.Air);
- if(_nodeContainer.TryGetNode(nodeContainer, component.OutletName, out PipeNode? outlet))
- gasMixDict.Add(Loc.GetString("gas-analyzer-window-text-outlet"), outlet.Air);
-
- args.GasMixtures = gasMixDict;
args.DeviceFlipped = inletOne != null && inletTwo != null && inletOne.CurrentPipeDirection.ToDirection() == inletTwo.CurrentPipeDirection.ToDirection().GetClockwise90Degrees();
}
}
diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs
index 3e4340bf1d..bdc9e76538 100644
--- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs
+++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasCanisterSystem.cs
@@ -294,9 +294,17 @@ public sealed class GasCanisterSystem : EntitySystem
///
/// Returns the gas mixture for the gas analyzer
///
- private void OnAnalyzed(EntityUid uid, GasCanisterComponent component, GasAnalyzerScanEvent args)
+ private void OnAnalyzed(EntityUid uid, GasCanisterComponent canisterComponent, GasAnalyzerScanEvent args)
{
- args.GasMixtures = new Dictionary { {Name(uid), component.Air} };
+ args.GasMixtures ??= new List<(string, GasMixture?)>();
+ args.GasMixtures.Add((Name(uid), canisterComponent.Air));
+ // if a tank is inserted show it on the analyzer as well
+ if (canisterComponent.GasTankSlot.Item != null)
+ {
+ var tank = canisterComponent.GasTankSlot.Item.Value;
+ var tankComponent = Comp(tank);
+ args.GasMixtures.Add((Name(tank), tankComponent.Air));
+ }
}
///
diff --git a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs
index a986385f5e..7c12cf3f77 100644
--- a/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs
+++ b/Content.Server/Atmos/Piping/Unary/EntitySystems/GasVentPumpSystem.cs
@@ -80,7 +80,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
return;
}
- var timeDelta = args.dt;
+ var timeDelta = args.dt;
var pressureDelta = timeDelta * vent.TargetPressureChange;
if (vent.PumpDirection == VentPumpDirection.Releasing && pipe.Air.Pressure > 0)
@@ -292,7 +292,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
///
private void OnAnalyzed(EntityUid uid, GasVentPumpComponent component, GasAnalyzerScanEvent args)
{
- var gasMixDict = new Dictionary();
+ args.GasMixtures ??= new List<(string, GasMixture?)>();
// these are both called pipe, above it switches using this so I duplicated that...?
var nodeName = component.PumpDirection switch
@@ -301,10 +301,14 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
VentPumpDirection.Siphoning => component.Outlet,
_ => throw new ArgumentOutOfRangeException()
};
- if (_nodeContainer.TryGetNode(uid, nodeName, out PipeNode? pipe))
- gasMixDict.Add(nodeName, pipe.Air);
-
- args.GasMixtures = gasMixDict;
+ // multiply by volume fraction to make sure to send only the gas inside the analyzed pipe element, not the whole pipe system
+ if (_nodeContainer.TryGetNode(uid, nodeName, out PipeNode? pipe) && pipe.Air.Volume != 0f)
+ {
+ var pipeAirLocal = pipe.Air.Clone();
+ pipeAirLocal.Multiply(pipe.Volume / pipe.Air.Volume);
+ pipeAirLocal.Volume = pipe.Volume;
+ args.GasMixtures.Add((nodeName, pipeAirLocal));
+ }
}
private void OnWeldChanged(EntityUid uid, GasVentPumpComponent component, ref WeldableChangedEvent args)
diff --git a/Content.Server/Atmos/Portable/PortableScrubberSystem.cs b/Content.Server/Atmos/Portable/PortableScrubberSystem.cs
index f9043c091a..91ee588057 100644
--- a/Content.Server/Atmos/Portable/PortableScrubberSystem.cs
+++ b/Content.Server/Atmos/Portable/PortableScrubberSystem.cs
@@ -151,10 +151,8 @@ namespace Content.Server.Atmos.Portable
///
private void OnScrubberAnalyzed(EntityUid uid, PortableScrubberComponent component, GasAnalyzerScanEvent args)
{
- args.GasMixtures ??= new Dictionary { { Name(uid), component.Air } };
- // If it's connected to a port, include the port side
- if (_nodeContainer.TryGetNode(uid, component.PortName, out PipeNode? port))
- args.GasMixtures.Add(component.PortName, port.Air);
+ args.GasMixtures ??= new List<(string, GasMixture?)>();
+ args.GasMixtures.Add((Name(uid), component.Air));
}
}
}
diff --git a/Content.Server/Medical/CryoPodSystem.cs b/Content.Server/Medical/CryoPodSystem.cs
index a949d980be..02e8cebbe0 100644
--- a/Content.Server/Medical/CryoPodSystem.cs
+++ b/Content.Server/Medical/CryoPodSystem.cs
@@ -276,10 +276,17 @@ public sealed partial class CryoPodSystem : SharedCryoPodSystem
if (!TryComp(entity, out CryoPodAirComponent? cryoPodAir))
return;
- args.GasMixtures ??= new Dictionary { { Name(entity.Owner), cryoPodAir.Air } };
+ args.GasMixtures ??= new List<(string, GasMixture?)>();
+ args.GasMixtures.Add((Name(entity.Owner), cryoPodAir.Air));
// If it's connected to a port, include the port side
- if (_nodeContainer.TryGetNode(entity.Owner, entity.Comp.PortName, out PipeNode? port))
- args.GasMixtures.Add(entity.Comp.PortName, port.Air);
+ // multiply by volume fraction to make sure to send only the gas inside the analyzed pipe element, not the whole pipe system
+ if (_nodeContainer.TryGetNode(entity.Owner, entity.Comp.PortName, out PipeNode? port) && port.Air.Volume != 0f)
+ {
+ var portAirLocal = port.Air.Clone();
+ portAirLocal.Multiply(port.Volume / port.Air.Volume);
+ portAirLocal.Volume = port.Volume;
+ args.GasMixtures.Add((entity.Comp.PortName, portAirLocal));
+ }
}
private void OnEjected(Entity cryoPod, ref EntRemovedFromContainerMessage args)
diff --git a/Content.Server/Singularity/EntitySystems/RadiationCollectorSystem.cs b/Content.Server/Singularity/EntitySystems/RadiationCollectorSystem.cs
index b26ab301c6..9107ff2e32 100644
--- a/Content.Server/Singularity/EntitySystems/RadiationCollectorSystem.cs
+++ b/Content.Server/Singularity/EntitySystems/RadiationCollectorSystem.cs
@@ -151,7 +151,8 @@ public sealed class RadiationCollectorSystem : EntitySystem
if (!TryGetLoadedGasTank(uid, out var gasTankComponent))
return;
- args.GasMixtures = new Dictionary { { Name(uid), gasTankComponent.Air } };
+ args.GasMixtures ??= new List<(string, GasMixture?)>();
+ args.GasMixtures.Add((Name(uid), gasTankComponent.Air));
}
public void ToggleCollector(EntityUid uid, EntityUid? user = null, RadiationCollectorComponent? component = null)
diff --git a/Content.Shared/Atmos/Components/GasAnalyzerComponent.cs b/Content.Shared/Atmos/Components/GasAnalyzerComponent.cs
index 51ae8cc740..dec9516c01 100644
--- a/Content.Shared/Atmos/Components/GasAnalyzerComponent.cs
+++ b/Content.Shared/Atmos/Components/GasAnalyzerComponent.cs
@@ -56,13 +56,15 @@ public sealed partial class GasAnalyzerComponent : Component
/// Name of the tab in the UI
///
public readonly string Name;
+ public readonly float Volume;
public readonly float Pressure;
public readonly float Temperature;
public readonly GasEntry[]? Gases;
- public GasMixEntry(string name, float pressure, float temperature, GasEntry[]? gases = null)
+ public GasMixEntry(string name, float volume, float pressure, float temperature, GasEntry[]? gases = null)
{
Name = name;
+ Volume = volume;
Pressure = pressure;
Temperature = temperature;
Gases = gases;
diff --git a/Resources/Locale/en-US/atmos/gas-analyzer-component.ftl b/Resources/Locale/en-US/atmos/gas-analyzer-component.ftl
index 03a920cb64..652bb19cb5 100644
--- a/Resources/Locale/en-US/atmos/gas-analyzer-component.ftl
+++ b/Resources/Locale/en-US/atmos/gas-analyzer-component.ftl
@@ -12,6 +12,8 @@ gas-analyzer-window-refresh-button = Refresh
gas-analyzer-window-no-data = No Data
gas-analyzer-window-no-gas-text = No Gases
gas-analyzer-window-error-text = Error: {$errorText}
+gas-analyzer-window-volume-text = Volume:
+gas-analyzer-window-volume-val-text = {$volume} L
gas-analyzer-window-pressure-text = Pressure:
gas-analyzer-window-pressure-val-text = {$pressure} kPa
gas-analyzer-window-temperature-text = Temperature: