diff --git a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml
index 76a1a41cdb..734fd74de0 100644
--- a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml
+++ b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml
@@ -40,9 +40,10 @@
-
+
-
+
+
diff --git a/Content.Server/Atmos/Monitor/Components/AirAlarmComponent.cs b/Content.Server/Atmos/Monitor/Components/AirAlarmComponent.cs
index d56d25d7c7..6d53721801 100644
--- a/Content.Server/Atmos/Monitor/Components/AirAlarmComponent.cs
+++ b/Content.Server/Atmos/Monitor/Components/AirAlarmComponent.cs
@@ -1,4 +1,6 @@
+using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Monitor.Components;
+using Content.Shared.Atmos.Piping.Unary.Components;
using Robust.Shared.Network;
namespace Content.Server.Atmos.Monitor.Components
@@ -11,7 +13,12 @@ namespace Content.Server.Atmos.Monitor.Components
// Remember to null this afterwards.
[ViewVariables] public IAirAlarmModeUpdate? CurrentModeUpdater { get; set; }
+ [ViewVariables] public AirAlarmTab CurrentTab { get; set; }
+
public Dictionary DeviceData = new();
+ public Dictionary VentData = new();
+ public Dictionary ScrubberData = new();
+ public Dictionary SensorData = new();
public HashSet ActivePlayers = new();
diff --git a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs
index c153e782c6..d70268d513 100644
--- a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs
+++ b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs
@@ -12,6 +12,7 @@ using Content.Shared.Access.Systems;
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.Interaction;
using Robust.Server.GameObjects;
using Robust.Shared.Player;
@@ -124,6 +125,24 @@ namespace Content.Server.Atmos.Monitor.Systems
_deviceNet.QueuePacket(uid, address, payload);
}
+ ///
+ /// Synchronize all sensors on an air alarm, but only if its current tab is set to Sensors.
+ ///
+ ///
+ ///
+ private void SyncAllSensors(EntityUid uid, AirAlarmComponent? monitor = null)
+ {
+ if (!Resolve(uid, ref monitor) || monitor.CurrentTab != AirAlarmTab.Sensors)
+ {
+ return;
+ }
+
+ foreach (var addr in monitor.SensorData.Keys)
+ {
+ SyncDevice(uid, addr);
+ }
+ }
+
///
/// Sync this air alarm's mode with the rest of the network.
///
@@ -168,7 +187,9 @@ namespace Content.Server.Atmos.Monitor.Systems
{
ForceCloseAllInterfaces(uid);
component.CurrentModeUpdater = null;
- component.DeviceData.Clear();
+ component.ScrubberData.Clear();
+ component.SensorData.Clear();
+ component.VentData.Clear();
}
else
{
@@ -208,18 +229,18 @@ namespace Content.Server.Atmos.Monitor.Systems
_uiSystem.GetUiOrNull(component.Owner, SharedAirAlarmInterfaceKey.Key)?.Open(actor.PlayerSession);
component.ActivePlayers.Add(actor.PlayerSession.UserId);
AddActiveInterface(uid);
- SendAddress(uid);
- SendAlarmMode(uid);
- SendThresholds(uid);
SyncAllDevices(uid);
- SendAirData(uid);
+ UpdateUI(uid, component);
}
private void OnResyncAll(EntityUid uid, AirAlarmComponent component, AirAlarmResyncAllDevicesMessage args)
{
if (AccessCheck(uid, args.Session.AttachedEntity, component))
{
- component.DeviceData.Clear();
+ component.VentData.Clear();
+ component.ScrubberData.Clear();
+ component.SensorData.Clear();
+
SyncAllDevices(uid);
}
}
@@ -231,7 +252,7 @@ namespace Content.Server.Atmos.Monitor.Systems
if (AccessCheck(uid, args.Session.AttachedEntity, component))
SetMode(uid, addr, args.Mode, true, false);
else
- SendAlarmMode(uid);
+ UpdateUI(uid, component);
}
private void OnUpdateThreshold(EntityUid uid, AirAlarmComponent component, AirAlarmUpdateAlarmThresholdMessage args)
@@ -239,7 +260,7 @@ namespace Content.Server.Atmos.Monitor.Systems
if (AccessCheck(uid, args.Session.AttachedEntity, component))
SetThreshold(uid, args.Threshold, args.Type, args.Gas);
else
- SendThresholds(uid);
+ UpdateUI(uid, component);
}
private void OnUpdateDeviceData(EntityUid uid, AirAlarmComponent component, AirAlarmUpdateDeviceDataMessage args)
@@ -247,7 +268,7 @@ namespace Content.Server.Atmos.Monitor.Systems
if (AccessCheck(uid, args.Session.AttachedEntity, component))
SetDeviceData(uid, args.Address, args.Data);
else
- SyncDevice(uid, args.Address);
+ UpdateUI(uid, component);
}
private bool AccessCheck(EntityUid uid, EntityUid? user, AirAlarmComponent? component = null)
@@ -272,7 +293,6 @@ namespace Content.Server.Atmos.Monitor.Systems
if (component.ActivePlayers.Count != 0)
{
SyncAllDevices(uid);
- SendAirData(uid);
}
string addr = string.Empty;
@@ -296,6 +316,8 @@ namespace Content.Server.Atmos.Monitor.Systems
// no, this still doesn't execute the mode
SetMode(uid, addr, AirAlarmMode.Filtering, true);
}
+
+ UpdateUI(uid, component);
}
#endregion
@@ -355,10 +377,7 @@ namespace Content.Server.Atmos.Monitor.Systems
&& controller.CurrentModeUpdater.NetOwner != origin)
controller.CurrentModeUpdater = null;
- // controller.SendMessage(new AirAlarmUpdateAlarmModeMessage(mode));
- // TODO: Use BUI states instead...
- _uiSystem.TrySendUiMessage(uid, SharedAirAlarmInterfaceKey.Key, new AirAlarmUpdateAlarmModeMessage(mode));
-
+ UpdateUI(uid, controller);
// setting sync deals with the issue of air alarms
// in the same network needing to have the same mode
@@ -384,7 +403,6 @@ namespace Content.Server.Atmos.Monitor.Systems
if (component.ActivePlayers.Count != 0)
{
SyncAllDevices(uid);
- SendAirData(uid);
}
string addr = string.Empty;
@@ -398,12 +416,6 @@ namespace Content.Server.Atmos.Monitor.Systems
return;
}
- // set this air alarm's visuals to match the highest network alarm
- if (TryComp(uid, out AppearanceComponent? appearanceComponent))
- {
- appearanceComponent.SetData(AtmosMonitorVisuals.AlarmType, highestNetworkType);
- }
-
if (highestNetworkType == AtmosMonitorAlarmType.Danger)
{
SetMode(uid, addr, AirAlarmMode.None, true);
@@ -421,6 +433,8 @@ namespace Content.Server.Atmos.Monitor.Systems
// no, this still doesn't execute the mode
SetMode(uid, addr, AirAlarmMode.Filtering, true);
}
+
+ UpdateUI(uid, component);
}
private void OnPacketRecv(EntityUid uid, AirAlarmComponent controller, DeviceNetworkPacketEvent args)
@@ -439,10 +453,23 @@ namespace Content.Server.Atmos.Monitor.Systems
// Sync data to interface.
// _airAlarmDataSystem.UpdateDeviceData(uid, args.SenderAddress, data);
//
- _uiSystem.TrySendUiMessage(uid, SharedAirAlarmInterfaceKey.Key, new AirAlarmUpdateDeviceDataMessage(args.SenderAddress, data));
- // if (HasComp(uid)) controller.UpdateWires();
- if (!controller.DeviceData.TryAdd(args.SenderAddress, data))
- controller.DeviceData[args.SenderAddress] = data;
+ switch (data)
+ {
+ case GasVentPumpData ventData:
+ if (!controller.VentData.TryAdd(args.SenderAddress, ventData))
+ controller.VentData[args.SenderAddress] = ventData;
+ break;
+ case GasVentScrubberData scrubberData:
+ if (!controller.ScrubberData.TryAdd(args.SenderAddress, scrubberData))
+ controller.ScrubberData[args.SenderAddress] = scrubberData;
+ break;
+ case AtmosSensorData sensorData:
+ if (!controller.SensorData.TryAdd(args.SenderAddress, sensorData))
+ controller.SensorData[args.SenderAddress] = sensorData;
+ break;
+ }
+
+ UpdateUI(uid, controller);
return;
case AirAlarmSetDataStatus:
@@ -486,84 +513,10 @@ namespace Content.Server.Atmos.Monitor.Systems
///
/// Force closes all interfaces currently open related to this air alarm.
///
- public void ForceCloseAllInterfaces(EntityUid uid) =>
+ public void ForceCloseAllInterfaces(EntityUid uid)
+ {
_uiSystem.TryCloseAll(uid, SharedAirAlarmInterfaceKey.Key);
-
- private void SendAddress(EntityUid uid, DeviceNetworkComponent? netConn = null)
- {
- if (!Resolve(uid, ref netConn)) return;
-
- // TODO: Use BUI states instead...
- _uiSystem.TrySendUiMessage(uid, SharedAirAlarmInterfaceKey.Key, new AirAlarmSetAddressMessage(netConn.Address));
- }
-
- ///
- /// Update an interface's air data. This is all the 'hot' data
- /// that an air alarm contains server-side. Updated with a whopping 8
- /// delay automatically once a UI is in the loop.
- ///
- public void SendAirData(EntityUid uid, AirAlarmComponent? alarm = null, AtmosMonitorComponent? monitor = null, ApcPowerReceiverComponent? power = null)
- {
- if (!Resolve(uid, ref alarm, ref monitor, ref power)) return;
-
- if (!power.Powered) return;
-
-
- if (monitor.TileGas != null)
- {
- var gases = new Dictionary();
-
- foreach (var gas in Enum.GetValues())
- gases.Add(gas, monitor.TileGas.GetMoles(gas));
-
- var airData = new AirAlarmAirData(monitor.TileGas.Pressure, monitor.TileGas.Temperature, monitor.TileGas.TotalMoles, monitor.LastAlarmState, gases);
-
- // TODO: Use BUI states instead...
- _uiSystem.TrySendUiMessage(uid, SharedAirAlarmInterfaceKey.Key, new AirAlarmUpdateAirDataMessage(airData));
- }
- }
-
- ///
- /// Send an air alarm mode to any open interface related to an air alarm.
- ///
- public void SendAlarmMode(EntityUid uid, AtmosMonitorComponent? monitor = null, ApcPowerReceiverComponent? power = null, AirAlarmComponent? controller = null)
- {
- if (!Resolve(uid, ref monitor, ref power, ref controller)
- || !power.Powered) return;
-
- // TODO: Use BUI states instead...
- _uiSystem.TrySendUiMessage(uid, SharedAirAlarmInterfaceKey.Key, new AirAlarmUpdateAlarmModeMessage(controller.CurrentMode));
- }
-
- ///
- /// Send all thresholds to any open interface related to a given air alarm.
- ///
- public void SendThresholds(EntityUid uid, AtmosMonitorComponent? monitor = null, ApcPowerReceiverComponent? power = null, AirAlarmComponent? controller = null)
- {
- if (!Resolve(uid, ref monitor, ref power, ref controller)
- || !power.Powered) return;
-
- if (monitor.PressureThreshold == null
- && monitor.TemperatureThreshold == null
- && monitor.GasThresholds == null)
- return;
-
- // TODO: Use BUI states instead...
- if (monitor.PressureThreshold != null)
- {
- _uiSystem.TrySendUiMessage(uid, SharedAirAlarmInterfaceKey.Key, new AirAlarmUpdateAlarmThresholdMessage(AtmosMonitorThresholdType.Pressure, monitor.PressureThreshold));
- }
-
- if (monitor.TemperatureThreshold != null)
- {
- _uiSystem.TrySendUiMessage(uid, SharedAirAlarmInterfaceKey.Key, new AirAlarmUpdateAlarmThresholdMessage(AtmosMonitorThresholdType.Temperature, monitor.TemperatureThreshold));
- }
-
- if (monitor.GasThresholds != null)
- {
- foreach (var (gas, threshold) in monitor.GasThresholds)
- _uiSystem.TrySendUiMessage(uid, SharedAirAlarmInterfaceKey.Key, new AirAlarmUpdateAlarmThresholdMessage(AtmosMonitorThresholdType.Gas, threshold, gas));
- }
+ RemoveActiveInterface(uid);
}
public void OnAtmosUpdate(EntityUid uid, AirAlarmComponent alarm, AtmosDeviceUpdateEvent args)
@@ -572,6 +525,49 @@ namespace Content.Server.Atmos.Monitor.Systems
alarm.CurrentModeUpdater.Update(uid);
}
+ public void UpdateUI(EntityUid uid, AirAlarmComponent? alarm = null, AtmosAlarmableComponent? alarmable = null)
+ {
+ if (!Resolve(uid, ref alarm, ref alarmable))
+ {
+ return;
+ }
+
+ var dataToSend = new Dictionary();
+
+ if (alarm.CurrentTab != AirAlarmTab.Settings)
+ {
+ switch (alarm.CurrentTab)
+ {
+ case AirAlarmTab.Vent:
+ foreach (var (addr, data) in alarm.VentData)
+ {
+ dataToSend.Add(addr, data);
+ }
+
+ break;
+ case AirAlarmTab.Scrubber:
+ foreach (var (addr, data) in alarm.ScrubberData)
+ {
+ dataToSend.Add(addr, data);
+ }
+
+ break;
+ case AirAlarmTab.Sensors:
+ foreach (var (addr, data) in alarm.SensorData)
+ {
+ dataToSend.Add(addr, data);
+ }
+
+ break;
+ }
+ }
+
+ _uiSystem.TrySetUiState(
+ uid,
+ SharedAirAlarmInterfaceKey.Key,
+ new AirAlarmUIState(dataToSend, alarm.CurrentMode, alarm.CurrentTab, alarmable.HighestNetworkState));
+ }
+
private const float _delay = 8f;
private float _timer = 0f;
@@ -583,9 +579,7 @@ namespace Content.Server.Atmos.Monitor.Systems
_timer = 0f;
foreach (var uid in _activeUserInterfaces)
{
- // TODO: Awful idea, use BUI states instead...
- SendAirData(uid);
- _uiSystem.TrySetUiState(uid, SharedAirAlarmInterfaceKey.Key, new AirAlarmUIState());
+ SyncAllSensors(uid);
}
}
}
diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs
index 221b1dba7e..ae8664ac54 100644
--- a/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs
+++ b/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs
@@ -3,11 +3,13 @@ using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Components;
using Content.Server.DeviceNetwork.Systems;
using Content.Shared.Atmos.Monitor;
+using Robust.Server.GameObjects;
namespace Content.Server.Atmos.Monitor.Systems
{
public sealed class AtmosAlarmableSystem : EntitySystem
{
+ [Dependency] private readonly AppearanceSystem _appearance = default!;
public override void Initialize()
{
SubscribeLocalEvent(OnPacketRecv);
@@ -34,9 +36,15 @@ namespace Content.Server.Atmos.Monitor.Systems
{
component.LastAlarmState = state;
component.HighestNetworkState = netMax;
+ UpdateAppearance(uid, netMax);
RaiseLocalEvent(component.Owner, new AtmosMonitorAlarmEvent(state, netMax), true);
}
}
}
+
+ private void UpdateAppearance(EntityUid uid, AtmosMonitorAlarmType alarm)
+ {
+ _appearance.SetData(uid, AtmosMonitorVisuals.AlarmType, alarm);
+ }
}
}
diff --git a/Content.Shared/Atmos/Monitor/AtmosSensorData.cs b/Content.Shared/Atmos/Monitor/AtmosSensorData.cs
new file mode 100644
index 0000000000..81adf5d91c
--- /dev/null
+++ b/Content.Shared/Atmos/Monitor/AtmosSensorData.cs
@@ -0,0 +1,37 @@
+using Content.Shared.Atmos.Monitor.Components;
+
+namespace Content.Shared.Atmos.Monitor;
+
+public sealed class AtmosSensorData : IAtmosDeviceData
+{
+ public bool Enabled { get; set; }
+ public bool Dirty { get; set; }
+ public bool IgnoreAlarms { get; set; }
+
+ /// Most fields are readonly, because it's data that's meant to be transmitted.
+
+ ///
+ /// Current pressure detected by this sensor.
+ ///
+ public float? Pressure { get; }
+ ///
+ /// Current temperature detected by this sensor.
+ ///
+ public float? Temperature { get; }
+ ///
+ /// Current amount of moles detected by this sensor.
+ ///
+ public float? TotalMoles { get; }
+ ///
+ /// Current alarm state of this sensor. Does not reflect the highest alarm state on the network.
+ ///
+ public AtmosMonitorAlarmType AlarmState { get; }
+ ///
+ /// Current number of gases on this sensor.
+ ///
+ public Dictionary Gases { get; }
+ ///
+ /// If this sensor is currently detecting a fire.
+ ///
+ public bool OnFire { get; }
+}
diff --git a/Content.Shared/Atmos/Monitor/Components/SharedAirAlarmComponent.cs b/Content.Shared/Atmos/Monitor/Components/SharedAirAlarmComponent.cs
index 5424c75920..b7075ee976 100644
--- a/Content.Shared/Atmos/Monitor/Components/SharedAirAlarmComponent.cs
+++ b/Content.Shared/Atmos/Monitor/Components/SharedAirAlarmComponent.cs
@@ -55,11 +55,34 @@ namespace Content.Shared.Atmos.Monitor.Components
public bool IgnoreAlarms { get; set; }
}
- // would be nice to include the entire state here
- // but it's already handled by messages
[Serializable, NetSerializable]
public sealed class AirAlarmUIState : BoundUserInterfaceState
- {}
+ {
+ public AirAlarmUIState(Dictionary deviceData, AirAlarmMode mode, AirAlarmTab tab, AtmosMonitorAlarmType alarmType)
+ {
+ DeviceData = deviceData;
+ Mode = mode;
+ Tab = tab;
+ AlarmType = alarmType;
+ }
+
+ ///
+ /// Every single device data that can be seen from this
+ /// air alarm. This includes vents, scrubbers, and sensors.
+ /// The device data you get, however, depends on the current
+ /// selected tab.
+ ///
+ public Dictionary DeviceData { get; }
+ public AirAlarmMode Mode { get; }
+ public AirAlarmTab Tab { get; }
+ public AtmosMonitorAlarmType AlarmType { get; }
+ }
+
+ [Serializable, NetSerializable]
+ public sealed class AirAlarmTabSetMessage : BoundUserInterfaceMessage
+ {
+ public AirAlarmTab Tab { get; }
+ }
[Serializable, NetSerializable]
public sealed class AirAlarmResyncAllDevicesMessage : BoundUserInterfaceMessage
@@ -126,5 +149,11 @@ namespace Content.Shared.Atmos.Monitor.Components
}
}
-
+ public enum AirAlarmTab
+ {
+ Vent,
+ Scrubber,
+ Sensors,
+ Settings
+ }
}