some backend stuff for air alarms

finally, some UI states!!!
This commit is contained in:
vulppine
2022-08-17 23:46:15 -07:00
parent 32e2686a4b
commit 1c651f051f
6 changed files with 188 additions and 112 deletions

View File

@@ -40,9 +40,10 @@
<ScrollContainer VerticalExpand="True"> <ScrollContainer VerticalExpand="True">
<BoxContainer Name="CScrubberContainer" Orientation="Vertical"/> <BoxContainer Name="CScrubberContainer" Orientation="Vertical"/>
</ScrollContainer> </ScrollContainer>
<!-- Alarm thresholds --> <!-- Sensors -->
<ScrollContainer VerticalExpand="True"> <ScrollContainer VerticalExpand="True">
<BoxContainer Orientation="Vertical" VerticalExpand="True"> <BoxContainer Name="CSensorContainer" Orientation="Vertical"/>
<!-- <BoxContainer Orientation="Vertical" VerticalExpand="True">
<BoxContainer Name="CPressureThreshold" Orientation="Vertical" Margin="2 0 2 0" /> <BoxContainer Name="CPressureThreshold" Orientation="Vertical" Margin="2 0 2 0" />
<BoxContainer Name="CTemperatureThreshold" Orientation="Vertical" Margin="2 0 2 0" /> <BoxContainer Name="CTemperatureThreshold" Orientation="Vertical" Margin="2 0 2 0" />
<Collapsible Orientation="Vertical"> <Collapsible Orientation="Vertical">
@@ -51,7 +52,7 @@
<BoxContainer Name="CGasThresholdContainer" Orientation="Vertical" Margin="2 0 2 0" /> <BoxContainer Name="CGasThresholdContainer" Orientation="Vertical" Margin="2 0 2 0" />
</CollapsibleBody> </CollapsibleBody>
</Collapsible> </Collapsible>
</BoxContainer> </BoxContainer> -->
</ScrollContainer> </ScrollContainer>
</TabContainer> </TabContainer>

View File

@@ -1,4 +1,6 @@
using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Monitor.Components; using Content.Shared.Atmos.Monitor.Components;
using Content.Shared.Atmos.Piping.Unary.Components;
using Robust.Shared.Network; using Robust.Shared.Network;
namespace Content.Server.Atmos.Monitor.Components namespace Content.Server.Atmos.Monitor.Components
@@ -11,7 +13,12 @@ namespace Content.Server.Atmos.Monitor.Components
// Remember to null this afterwards. // Remember to null this afterwards.
[ViewVariables] public IAirAlarmModeUpdate? CurrentModeUpdater { get; set; } [ViewVariables] public IAirAlarmModeUpdate? CurrentModeUpdater { get; set; }
[ViewVariables] public AirAlarmTab CurrentTab { get; set; }
public Dictionary<string, IAtmosDeviceData> DeviceData = new(); public Dictionary<string, IAtmosDeviceData> DeviceData = new();
public Dictionary<string, GasVentPumpData> VentData = new();
public Dictionary<string, GasVentScrubberData> ScrubberData = new();
public Dictionary<string, AtmosSensorData> SensorData = new();
public HashSet<NetUserId> ActivePlayers = new(); public HashSet<NetUserId> ActivePlayers = new();

View File

@@ -12,6 +12,7 @@ using Content.Shared.Access.Systems;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor; using Content.Shared.Atmos.Monitor;
using Content.Shared.Atmos.Monitor.Components; using Content.Shared.Atmos.Monitor.Components;
using Content.Shared.Atmos.Piping.Unary.Components;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
using Robust.Shared.Player; using Robust.Shared.Player;
@@ -124,6 +125,24 @@ namespace Content.Server.Atmos.Monitor.Systems
_deviceNet.QueuePacket(uid, address, payload); _deviceNet.QueuePacket(uid, address, payload);
} }
/// <summary>
/// Synchronize all sensors on an air alarm, but only if its current tab is set to Sensors.
/// </summary>
/// <param name="uid"></param>
/// <param name="monitor"></param>
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);
}
}
/// <summary> /// <summary>
/// Sync this air alarm's mode with the rest of the network. /// Sync this air alarm's mode with the rest of the network.
/// </summary> /// </summary>
@@ -168,7 +187,9 @@ namespace Content.Server.Atmos.Monitor.Systems
{ {
ForceCloseAllInterfaces(uid); ForceCloseAllInterfaces(uid);
component.CurrentModeUpdater = null; component.CurrentModeUpdater = null;
component.DeviceData.Clear(); component.ScrubberData.Clear();
component.SensorData.Clear();
component.VentData.Clear();
} }
else else
{ {
@@ -208,18 +229,18 @@ namespace Content.Server.Atmos.Monitor.Systems
_uiSystem.GetUiOrNull(component.Owner, SharedAirAlarmInterfaceKey.Key)?.Open(actor.PlayerSession); _uiSystem.GetUiOrNull(component.Owner, SharedAirAlarmInterfaceKey.Key)?.Open(actor.PlayerSession);
component.ActivePlayers.Add(actor.PlayerSession.UserId); component.ActivePlayers.Add(actor.PlayerSession.UserId);
AddActiveInterface(uid); AddActiveInterface(uid);
SendAddress(uid);
SendAlarmMode(uid);
SendThresholds(uid);
SyncAllDevices(uid); SyncAllDevices(uid);
SendAirData(uid); UpdateUI(uid, component);
} }
private void OnResyncAll(EntityUid uid, AirAlarmComponent component, AirAlarmResyncAllDevicesMessage args) private void OnResyncAll(EntityUid uid, AirAlarmComponent component, AirAlarmResyncAllDevicesMessage args)
{ {
if (AccessCheck(uid, args.Session.AttachedEntity, component)) if (AccessCheck(uid, args.Session.AttachedEntity, component))
{ {
component.DeviceData.Clear(); component.VentData.Clear();
component.ScrubberData.Clear();
component.SensorData.Clear();
SyncAllDevices(uid); SyncAllDevices(uid);
} }
} }
@@ -231,7 +252,7 @@ namespace Content.Server.Atmos.Monitor.Systems
if (AccessCheck(uid, args.Session.AttachedEntity, component)) if (AccessCheck(uid, args.Session.AttachedEntity, component))
SetMode(uid, addr, args.Mode, true, false); SetMode(uid, addr, args.Mode, true, false);
else else
SendAlarmMode(uid); UpdateUI(uid, component);
} }
private void OnUpdateThreshold(EntityUid uid, AirAlarmComponent component, AirAlarmUpdateAlarmThresholdMessage args) 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)) if (AccessCheck(uid, args.Session.AttachedEntity, component))
SetThreshold(uid, args.Threshold, args.Type, args.Gas); SetThreshold(uid, args.Threshold, args.Type, args.Gas);
else else
SendThresholds(uid); UpdateUI(uid, component);
} }
private void OnUpdateDeviceData(EntityUid uid, AirAlarmComponent component, AirAlarmUpdateDeviceDataMessage args) 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)) if (AccessCheck(uid, args.Session.AttachedEntity, component))
SetDeviceData(uid, args.Address, args.Data); SetDeviceData(uid, args.Address, args.Data);
else else
SyncDevice(uid, args.Address); UpdateUI(uid, component);
} }
private bool AccessCheck(EntityUid uid, EntityUid? user, AirAlarmComponent? component = null) 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) if (component.ActivePlayers.Count != 0)
{ {
SyncAllDevices(uid); SyncAllDevices(uid);
SendAirData(uid);
} }
string addr = string.Empty; string addr = string.Empty;
@@ -296,6 +316,8 @@ namespace Content.Server.Atmos.Monitor.Systems
// no, this still doesn't execute the mode // no, this still doesn't execute the mode
SetMode(uid, addr, AirAlarmMode.Filtering, true); SetMode(uid, addr, AirAlarmMode.Filtering, true);
} }
UpdateUI(uid, component);
} }
#endregion #endregion
@@ -355,10 +377,7 @@ namespace Content.Server.Atmos.Monitor.Systems
&& controller.CurrentModeUpdater.NetOwner != origin) && controller.CurrentModeUpdater.NetOwner != origin)
controller.CurrentModeUpdater = null; controller.CurrentModeUpdater = null;
// controller.SendMessage(new AirAlarmUpdateAlarmModeMessage(mode)); UpdateUI(uid, controller);
// TODO: Use BUI states instead...
_uiSystem.TrySendUiMessage(uid, SharedAirAlarmInterfaceKey.Key, new AirAlarmUpdateAlarmModeMessage(mode));
// setting sync deals with the issue of air alarms // setting sync deals with the issue of air alarms
// in the same network needing to have the same mode // 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) if (component.ActivePlayers.Count != 0)
{ {
SyncAllDevices(uid); SyncAllDevices(uid);
SendAirData(uid);
} }
string addr = string.Empty; string addr = string.Empty;
@@ -398,12 +416,6 @@ namespace Content.Server.Atmos.Monitor.Systems
return; 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) if (highestNetworkType == AtmosMonitorAlarmType.Danger)
{ {
SetMode(uid, addr, AirAlarmMode.None, true); SetMode(uid, addr, AirAlarmMode.None, true);
@@ -421,6 +433,8 @@ namespace Content.Server.Atmos.Monitor.Systems
// no, this still doesn't execute the mode // no, this still doesn't execute the mode
SetMode(uid, addr, AirAlarmMode.Filtering, true); SetMode(uid, addr, AirAlarmMode.Filtering, true);
} }
UpdateUI(uid, component);
} }
private void OnPacketRecv(EntityUid uid, AirAlarmComponent controller, DeviceNetworkPacketEvent args) private void OnPacketRecv(EntityUid uid, AirAlarmComponent controller, DeviceNetworkPacketEvent args)
@@ -439,10 +453,23 @@ namespace Content.Server.Atmos.Monitor.Systems
// Sync data to interface. // Sync data to interface.
// _airAlarmDataSystem.UpdateDeviceData(uid, args.SenderAddress, data); // _airAlarmDataSystem.UpdateDeviceData(uid, args.SenderAddress, data);
// //
_uiSystem.TrySendUiMessage(uid, SharedAirAlarmInterfaceKey.Key, new AirAlarmUpdateDeviceDataMessage(args.SenderAddress, data)); switch (data)
// if (HasComp<WiresComponent>(uid)) controller.UpdateWires(); {
if (!controller.DeviceData.TryAdd(args.SenderAddress, data)) case GasVentPumpData ventData:
controller.DeviceData[args.SenderAddress] = data; 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; return;
case AirAlarmSetDataStatus: case AirAlarmSetDataStatus:
@@ -486,84 +513,10 @@ namespace Content.Server.Atmos.Monitor.Systems
/// <summary> /// <summary>
/// Force closes all interfaces currently open related to this air alarm. /// Force closes all interfaces currently open related to this air alarm.
/// </summary> /// </summary>
public void ForceCloseAllInterfaces(EntityUid uid) => public void ForceCloseAllInterfaces(EntityUid uid)
{
_uiSystem.TryCloseAll(uid, SharedAirAlarmInterfaceKey.Key); _uiSystem.TryCloseAll(uid, SharedAirAlarmInterfaceKey.Key);
RemoveActiveInterface(uid);
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));
}
/// <summary>
/// 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.
/// </summary>
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<Gas, float>();
foreach (var gas in Enum.GetValues<Gas>())
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));
}
}
/// <summary>
/// Send an air alarm mode to any open interface related to an air alarm.
/// </summary>
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));
}
/// <summary>
/// Send all thresholds to any open interface related to a given air alarm.
/// </summary>
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));
}
} }
public void OnAtmosUpdate(EntityUid uid, AirAlarmComponent alarm, AtmosDeviceUpdateEvent args) public void OnAtmosUpdate(EntityUid uid, AirAlarmComponent alarm, AtmosDeviceUpdateEvent args)
@@ -572,6 +525,49 @@ namespace Content.Server.Atmos.Monitor.Systems
alarm.CurrentModeUpdater.Update(uid); 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<string, IAtmosDeviceData>();
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 const float _delay = 8f;
private float _timer = 0f; private float _timer = 0f;
@@ -583,9 +579,7 @@ namespace Content.Server.Atmos.Monitor.Systems
_timer = 0f; _timer = 0f;
foreach (var uid in _activeUserInterfaces) foreach (var uid in _activeUserInterfaces)
{ {
// TODO: Awful idea, use BUI states instead... SyncAllSensors(uid);
SendAirData(uid);
_uiSystem.TrySetUiState(uid, SharedAirAlarmInterfaceKey.Key, new AirAlarmUIState());
} }
} }
} }

View File

@@ -3,11 +3,13 @@ using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Components; using Content.Server.DeviceNetwork.Components;
using Content.Server.DeviceNetwork.Systems; using Content.Server.DeviceNetwork.Systems;
using Content.Shared.Atmos.Monitor; using Content.Shared.Atmos.Monitor;
using Robust.Server.GameObjects;
namespace Content.Server.Atmos.Monitor.Systems namespace Content.Server.Atmos.Monitor.Systems
{ {
public sealed class AtmosAlarmableSystem : EntitySystem public sealed class AtmosAlarmableSystem : EntitySystem
{ {
[Dependency] private readonly AppearanceSystem _appearance = default!;
public override void Initialize() public override void Initialize()
{ {
SubscribeLocalEvent<AtmosAlarmableComponent, DeviceNetworkPacketEvent>(OnPacketRecv); SubscribeLocalEvent<AtmosAlarmableComponent, DeviceNetworkPacketEvent>(OnPacketRecv);
@@ -34,9 +36,15 @@ namespace Content.Server.Atmos.Monitor.Systems
{ {
component.LastAlarmState = state; component.LastAlarmState = state;
component.HighestNetworkState = netMax; component.HighestNetworkState = netMax;
UpdateAppearance(uid, netMax);
RaiseLocalEvent(component.Owner, new AtmosMonitorAlarmEvent(state, netMax), true); RaiseLocalEvent(component.Owner, new AtmosMonitorAlarmEvent(state, netMax), true);
} }
} }
} }
private void UpdateAppearance(EntityUid uid, AtmosMonitorAlarmType alarm)
{
_appearance.SetData(uid, AtmosMonitorVisuals.AlarmType, alarm);
}
} }
} }

View File

@@ -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.
/// <summary>
/// Current pressure detected by this sensor.
/// </summary>
public float? Pressure { get; }
/// <summary>
/// Current temperature detected by this sensor.
/// </summary>
public float? Temperature { get; }
/// <summary>
/// Current amount of moles detected by this sensor.
/// </summary>
public float? TotalMoles { get; }
/// <summary>
/// Current alarm state of this sensor. Does not reflect the highest alarm state on the network.
/// </summary>
public AtmosMonitorAlarmType AlarmState { get; }
/// <summary>
/// Current number of gases on this sensor.
/// </summary>
public Dictionary<Gas, float> Gases { get; }
/// <summary>
/// If this sensor is currently detecting a fire.
/// </summary>
public bool OnFire { get; }
}

View File

@@ -55,11 +55,34 @@ namespace Content.Shared.Atmos.Monitor.Components
public bool IgnoreAlarms { get; set; } public bool IgnoreAlarms { get; set; }
} }
// would be nice to include the entire state here
// but it's already handled by messages
[Serializable, NetSerializable] [Serializable, NetSerializable]
public sealed class AirAlarmUIState : BoundUserInterfaceState public sealed class AirAlarmUIState : BoundUserInterfaceState
{} {
public AirAlarmUIState(Dictionary<string, IAtmosDeviceData> deviceData, AirAlarmMode mode, AirAlarmTab tab, AtmosMonitorAlarmType alarmType)
{
DeviceData = deviceData;
Mode = mode;
Tab = tab;
AlarmType = alarmType;
}
/// <summary>
/// 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.
/// </summary>
public Dictionary<string, IAtmosDeviceData> 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] [Serializable, NetSerializable]
public sealed class AirAlarmResyncAllDevicesMessage : BoundUserInterfaceMessage public sealed class AirAlarmResyncAllDevicesMessage : BoundUserInterfaceMessage
@@ -126,5 +149,11 @@ namespace Content.Shared.Atmos.Monitor.Components
} }
} }
public enum AirAlarmTab
{
Vent,
Scrubber,
Sensors,
Settings
}
} }