From b075606f61c452fde32835af9f7e1f1decf25bbb Mon Sep 17 00:00:00 2001 From: vulppine Date: Wed, 17 Aug 2022 20:32:31 -0700 Subject: [PATCH 01/80] air sensor model (works well enough) --- .../Atmos/Monitor/Systems/AirAlarmSystem.cs | 51 +++++++++++++++++-- .../Monitor/Systems/AtmosMonitoringSystem.cs | 2 + .../Structures/Piping/Atmospherics/unary.yml | 21 +++++++- .../Structures/Wallmounts/air_alarm.yml | 15 +----- 4 files changed, 71 insertions(+), 18 deletions(-) diff --git a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs index a8b8ea5d32..c153e782c6 100644 --- a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs @@ -379,6 +379,50 @@ namespace Content.Server.Atmos.Monitor.Systems SetData(uid, address, devData); } + private void OnAtmosAlarm(EntityUid uid, AirAlarmComponent component, NetworkPayload args) + { + if (component.ActivePlayers.Count != 0) + { + SyncAllDevices(uid); + SendAirData(uid); + } + + string addr = string.Empty; + if (TryComp(uid, out DeviceNetworkComponent? netConn)) + { + addr = netConn.Address; + } + + if (!args.TryGetValue(AtmosMonitorSystem.AtmosMonitorAlarmNetMax, out AtmosMonitorAlarmType? highestNetworkType)) + { + 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); + // set mode to off to mimic the vents/scrubbers being turned off + // update UI + // + // no, the mode isn't processed here - it's literally just + // set to what mimics 'off' + } + else if (highestNetworkType == AtmosMonitorAlarmType.Normal) + { + // if the mode is still set to off, set it to filtering instead + // alternatively, set it to the last saved mode + // + // no, this still doesn't execute the mode + SetMode(uid, addr, AirAlarmMode.Filtering, true); + } + } + private void OnPacketRecv(EntityUid uid, AirAlarmComponent controller, DeviceNetworkPacketEvent args) { if (!args.Data.TryGetValue(DeviceNetworkConstants.Command, out string? cmd)) @@ -388,8 +432,8 @@ namespace Content.Server.Atmos.Monitor.Systems { case AirAlarmSyncData: if (!args.Data.TryGetValue(AirAlarmSyncData, out IAtmosDeviceData? data) - || data == null - || !controller.CanSync) break; + || !controller.CanSync) + break; // Save into component. // Sync data to interface. @@ -402,7 +446,8 @@ namespace Content.Server.Atmos.Monitor.Systems return; case AirAlarmSetDataStatus: - if (!args.Data.TryGetValue(AirAlarmSetDataStatus, out bool dataStatus)) break; + if (!args.Data.TryGetValue(AirAlarmSetDataStatus, out bool dataStatus)) + break; // Sync data to interface. // This should say if the result diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs index c3f3300d11..b7f11ba996 100644 --- a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs @@ -111,8 +111,10 @@ namespace Content.Server.Atmos.Monitor.Systems public override void Update(float frameTime) { + /* NOPE foreach (var uid in _checkPos) OpenAirOrReposition(uid); + */ } private void OpenAirOrReposition(EntityUid uid, AtmosMonitorComponent? component = null, AppearanceComponent? appearance = null) diff --git a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/unary.yml b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/unary.yml index 2963e17f6f..bdddfa018f 100644 --- a/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/unary.yml +++ b/Resources/Prototypes/Entities/Structures/Piping/Atmospherics/unary.yml @@ -31,9 +31,28 @@ receiveFrequencyId: AtmosMonitor transmitFrequencyId: AtmosMonitor prefix: device-address-prefix-vent + sendBroadcastAttemptEvent: true + - type: DeviceList + - type: WiredNetworkConnection - type: AtmosAlarmable alarmedBy: - - AirAlarm + - GasVentPump # TODO: No + - type: AtmosDevice + - type: AtmosMonitor + temperatureThreshold: stationTemperature + pressureThreshold: stationPressure + gasThresholds: + Oxygen: stationOxygen + Nitrogen: ignore + CarbonDioxide: stationCO2 + Plasma: danger # everything below is usually bad + Tritium: danger + WaterVapor: danger + Miasma: danger + NitrousOxide: danger + Frezon: danger + - type: AccessReader + access: [ [ "Atmospherics" ] ] - type: Sprite netsync: false drawdepth: FloorObjects diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/air_alarm.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/air_alarm.yml index 1b82ae3696..0860acdea2 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/air_alarm.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/air_alarm.yml @@ -16,21 +16,8 @@ sendBroadcastAttemptEvent: true - type: WiredNetworkConnection - type: DeviceList - - type: AtmosMonitor - temperatureThreshold: stationTemperature - pressureThreshold: stationPressure - gasThresholds: - Oxygen: stationOxygen - Nitrogen: ignore - CarbonDioxide: stationCO2 - Plasma: danger # everything below is usually bad - Tritium: danger - WaterVapor: danger - Miasma: danger - NitrousOxide: danger - Frezon: danger - type: AtmosAlarmable - alarmedBy: ["AirAlarm"] + alarmedBy: ["GasVentPump"] - type: AtmosDevice - type: AirAlarm - type: Clickable From 32e2686a4b92561c200c4817f0e235f8f3ac26b2 Mon Sep 17 00:00:00 2001 From: vulppine Date: Wed, 17 Aug 2022 20:52:04 -0700 Subject: [PATCH 02/80] threshold cloning --- .../Atmos/Monitor/Systems/AtmosMonitoringSystem.cs | 6 +++--- .../Atmos/Monitor/AtmosAlarmThresholdPrototype.cs | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs index b7f11ba996..d94f97d801 100644 --- a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs @@ -75,17 +75,17 @@ namespace Content.Server.Atmos.Monitor.Systems private void OnAtmosMonitorInit(EntityUid uid, AtmosMonitorComponent component, ComponentInit args) { if (component.TemperatureThresholdId != null) - component.TemperatureThreshold = _prototypeManager.Index(component.TemperatureThresholdId); + component.TemperatureThreshold = new(_prototypeManager.Index(component.TemperatureThresholdId)); if (component.PressureThresholdId != null) - component.PressureThreshold = _prototypeManager.Index(component.PressureThresholdId); + component.PressureThreshold = new(_prototypeManager.Index(component.PressureThresholdId)); if (component.GasThresholdIds != null) { component.GasThresholds = new(); foreach (var (gas, id) in component.GasThresholdIds) if (_prototypeManager.TryIndex(id, out var gasThreshold)) - component.GasThresholds.Add(gas, gasThreshold); + component.GasThresholds.Add(gas, new(gasThreshold)); } } diff --git a/Content.Shared/Atmos/Monitor/AtmosAlarmThresholdPrototype.cs b/Content.Shared/Atmos/Monitor/AtmosAlarmThresholdPrototype.cs index c3270e6b69..68ac59b86d 100644 --- a/Content.Shared/Atmos/Monitor/AtmosAlarmThresholdPrototype.cs +++ b/Content.Shared/Atmos/Monitor/AtmosAlarmThresholdPrototype.cs @@ -52,6 +52,15 @@ namespace Content.Shared.Atmos.Monitor get => CalculateWarningBound(AtmosMonitorThresholdBound.Lower); } + public AtmosAlarmThreshold(AtmosAlarmThreshold other) + { + Ignore = other.Ignore; + UpperBound = other.UpperBound; + LowerBound = other.LowerBound; + UpperWarningPercentage = other.UpperWarningPercentage; + LowerWarningPercentage = other.LowerWarningPercentage; + } + void ISerializationHooks.AfterDeserialization() { if (UpperBound <= LowerBound) From 1c651f051f5f7241f64a77d3670c6f7532aa12d0 Mon Sep 17 00:00:00 2001 From: vulppine Date: Wed, 17 Aug 2022 23:46:15 -0700 Subject: [PATCH 03/80] some backend stuff for air alarms finally, some UI states!!! --- .../Atmos/Monitor/UI/AirAlarmWindow.xaml | 7 +- .../Monitor/Components/AirAlarmComponent.cs | 7 + .../Atmos/Monitor/Systems/AirAlarmSystem.cs | 204 +++++++++--------- .../Monitor/Systems/AtmosAlarmableSystem.cs | 8 + .../Atmos/Monitor/AtmosSensorData.cs | 37 ++++ .../Components/SharedAirAlarmComponent.cs | 37 +++- 6 files changed, 188 insertions(+), 112 deletions(-) create mode 100644 Content.Shared/Atmos/Monitor/AtmosSensorData.cs 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 + } } From 068527b13c529186a8c179806e3d6ab543d488ab Mon Sep 17 00:00:00 2001 From: vulppine Date: Thu, 18 Aug 2022 02:37:12 -0700 Subject: [PATCH 04/80] alert sounds from alarmables, sensor data ctor --- .../Components/AtmosAlarmableComponent.cs | 7 +++ .../Components/AtmosMonitorComponent.cs | 9 ---- .../Atmos/Monitor/Systems/AirAlarmSystem.cs | 1 - .../Monitor/Systems/AtmosAlarmableSystem.cs | 11 +++++ .../Monitor/Systems/AtmosMonitoringSystem.cs | 48 ++++++++++++++----- .../Monitor/AtmosAlarmThresholdPrototype.cs | 3 ++ .../Atmos/Monitor/AtmosSensorData.cs | 23 +++++++-- 7 files changed, 78 insertions(+), 24 deletions(-) diff --git a/Content.Server/Atmos/Monitor/Components/AtmosAlarmableComponent.cs b/Content.Server/Atmos/Monitor/Components/AtmosAlarmableComponent.cs index b762df7b02..c9435bdef6 100644 --- a/Content.Server/Atmos/Monitor/Components/AtmosAlarmableComponent.cs +++ b/Content.Server/Atmos/Monitor/Components/AtmosAlarmableComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.Atmos.Monitor; +using Robust.Shared.Audio; namespace Content.Server.Atmos.Monitor.Components { @@ -30,6 +31,12 @@ namespace Content.Server.Atmos.Monitor.Components [ViewVariables] public AtmosMonitorAlarmType HighestNetworkState = AtmosMonitorAlarmType.Normal; [ViewVariables] public bool IgnoreAlarms { get; set; } = false; + [DataField("alarmSound")] + public SoundSpecifier AlarmSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/alarm.ogg"); + + [DataField("alarmVolume")] + public float AlarmVolume { get; set; } = -10; + /// /// List of prototypes that this alarmable can be /// alarmed by - must be a prototype with AtmosMonitor diff --git a/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs b/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs index a8c56439e6..d741be8ad1 100644 --- a/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs +++ b/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs @@ -46,15 +46,6 @@ namespace Content.Server.Atmos.Monitor.Components [DataField("monitorFire")] public bool MonitorFire = false; - [DataField("displayMaxAlarmInNet")] - public bool DisplayMaxAlarmInNet = false; - - [DataField("alarmSound")] - public SoundSpecifier AlarmSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/alarm.ogg"); - - [DataField("alarmVolume")] - public float AlarmVolume { get; set; } = -10; - // really messy but this is parsed at runtime after // prototypes are initialized, there's no // way without implementing a new diff --git a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs index d70268d513..d0d0246989 100644 --- a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs @@ -516,7 +516,6 @@ namespace Content.Server.Atmos.Monitor.Systems public void ForceCloseAllInterfaces(EntityUid uid) { _uiSystem.TryCloseAll(uid, SharedAirAlarmInterfaceKey.Key); - RemoveActiveInterface(uid); } public void OnAtmosUpdate(EntityUid uid, AirAlarmComponent alarm, AtmosDeviceUpdateEvent args) diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs index ae8664ac54..b38916567e 100644 --- a/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs @@ -4,12 +4,14 @@ using Content.Server.DeviceNetwork.Components; using Content.Server.DeviceNetwork.Systems; using Content.Shared.Atmos.Monitor; using Robust.Server.GameObjects; +using Robust.Shared.Audio; namespace Content.Server.Atmos.Monitor.Systems { public sealed class AtmosAlarmableSystem : EntitySystem { [Dependency] private readonly AppearanceSystem _appearance = default!; + [Dependency] private readonly AudioSystem _audioSystem = default!; public override void Initialize() { SubscribeLocalEvent(OnPacketRecv); @@ -37,11 +39,20 @@ namespace Content.Server.Atmos.Monitor.Systems component.LastAlarmState = state; component.HighestNetworkState = netMax; UpdateAppearance(uid, netMax); + PlayAlertSound(uid, netMax, component); RaiseLocalEvent(component.Owner, new AtmosMonitorAlarmEvent(state, netMax), true); } } } + private void PlayAlertSound(EntityUid uid, AtmosMonitorAlarmType alarm, AtmosAlarmableComponent alarmable) + { + if (alarm == AtmosMonitorAlarmType.Danger) + { + _audioSystem.PlayPvs(alarmable.AlarmSound, uid, AudioParams.Default.WithVolume(alarmable.AlarmVolume)); + } + } + private void UpdateAppearance(EntityUid uid, AtmosMonitorAlarmType alarm) { _appearance.SetData(uid, AtmosMonitorVisuals.AlarmType, alarm); diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs index d94f97d801..1b192c4ca8 100644 --- a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs @@ -44,6 +44,8 @@ namespace Content.Server.Atmos.Monitor.Systems /// public const string AtmosMonitorAlarmResetAllCmd = "atmos_monitor_alarm_reset_all"; + public const string AtmosMonitorSetThresholdData = "atmos_monitor_set_threshold"; + // Packet data /// /// Data response that contains the threshold types in an atmos monitor alarm. @@ -60,6 +62,13 @@ namespace Content.Server.Atmos.Monitor.Systems /// public const string AtmosMonitorAlarmNetMax = "atmos_monitor_alarm_net_max"; + /// + /// Data response that contains the last state recorded by this air monitor. + /// + public const string AtmosMonitorAtmosData = "atmos_monitor_atmos_data"; + + public const string AtmosMonitorThresholdData = "atmos_monitor_threshold_data"; + public override void Initialize() { SubscribeLocalEvent(OnAtmosMonitorInit); @@ -189,16 +198,42 @@ namespace Content.Server.Atmos.Monitor.Systems component.NetworkAlarmStates.Clear(); } break; + case AirAlarmSystem.AirAlarmSyncCmd: + var payload = new NetworkPayload(); + payload.Add(DeviceNetworkConstants.Command, AirAlarmSystem.AirAlarmSyncData); + if (component.TileGas != null) + { + var gases = new Dictionary(); + foreach (var gas in Enum.GetValues()) + { + gases.Add(gas, component.TileGas.GetMoles(gas)); + } + + payload.Add(AtmosMonitorAtmosData, new AtmosSensorData( + component.TileGas.Pressure, + component.TileGas.Temperature, + component.TileGas.TotalMoles, + component.HighestAlarmInNetwork, + gases, + false, + component.PressureThreshold ?? new(), + component.TemperatureThreshold ?? new(), + component.GasThresholds ?? new() + )); + } + + _deviceNetSystem.QueuePacket(uid, args.SenderAddress, payload); + break; } + /* if (component.DisplayMaxAlarmInNet) { if (EntityManager.TryGetComponent(component.Owner, out AppearanceComponent? appearanceComponent)) appearanceComponent.SetData(AtmosMonitorVisuals.AlarmType, component.HighestAlarmInNetwork); - if (component.HighestAlarmInNetwork == AtmosMonitorAlarmType.Danger) PlayAlertSound(uid, component); } - + */ } private void OnPowerChangedEvent(EntityUid uid, AtmosMonitorComponent component, PowerChangedEvent args) @@ -344,21 +379,12 @@ namespace Content.Server.Atmos.Monitor.Systems BroadcastAlertPacket(monitor, alarms); - if (state == AtmosMonitorAlarmType.Danger) PlayAlertSound(uid, monitor); - if (EntityManager.TryGetComponent(monitor.Owner, out AtmosAlarmableComponent? alarmable) && !alarmable.IgnoreAlarms) RaiseLocalEvent(monitor.Owner, new AtmosMonitorAlarmEvent(monitor.LastAlarmState, monitor.HighestAlarmInNetwork), true); // TODO: Central system that grabs *all* alarms from wired network } - private void PlayAlertSound(EntityUid uid, AtmosMonitorComponent? monitor = null) - { - if (!Resolve(uid, ref monitor)) return; - - SoundSystem.Play(monitor.AlarmSound.GetSound(), Filter.Pvs(uid), uid, AudioParams.Default.WithVolume(monitor.AlarmVolume)); - } - /// /// Resets a single monitor's alarm. /// diff --git a/Content.Shared/Atmos/Monitor/AtmosAlarmThresholdPrototype.cs b/Content.Shared/Atmos/Monitor/AtmosAlarmThresholdPrototype.cs index 68ac59b86d..31f077206e 100644 --- a/Content.Shared/Atmos/Monitor/AtmosAlarmThresholdPrototype.cs +++ b/Content.Shared/Atmos/Monitor/AtmosAlarmThresholdPrototype.cs @@ -52,6 +52,9 @@ namespace Content.Shared.Atmos.Monitor get => CalculateWarningBound(AtmosMonitorThresholdBound.Lower); } + public AtmosAlarmThreshold() + {} + public AtmosAlarmThreshold(AtmosAlarmThreshold other) { Ignore = other.Ignore; diff --git a/Content.Shared/Atmos/Monitor/AtmosSensorData.cs b/Content.Shared/Atmos/Monitor/AtmosSensorData.cs index 81adf5d91c..3cb2f09be5 100644 --- a/Content.Shared/Atmos/Monitor/AtmosSensorData.cs +++ b/Content.Shared/Atmos/Monitor/AtmosSensorData.cs @@ -4,6 +4,19 @@ namespace Content.Shared.Atmos.Monitor; public sealed class AtmosSensorData : IAtmosDeviceData { + public AtmosSensorData(float pressure, float temperature, float totalMoles, AtmosMonitorAlarmType alarmState, Dictionary gases, bool onFire, AtmosAlarmThreshold pressureThreshold, AtmosAlarmThreshold temperatureThreshold, Dictionary gasThresholds) + { + Pressure = pressure; + Temperature = temperature; + TotalMoles = totalMoles; + AlarmState = alarmState; + Gases = gases; + OnFire = onFire; + PressureThreshold = pressureThreshold; + TemperatureThreshold = temperatureThreshold; + GasThresholds = gasThresholds; + } + public bool Enabled { get; set; } public bool Dirty { get; set; } public bool IgnoreAlarms { get; set; } @@ -13,15 +26,15 @@ public sealed class AtmosSensorData : IAtmosDeviceData /// /// Current pressure detected by this sensor. /// - public float? Pressure { get; } + public float Pressure { get; } /// /// Current temperature detected by this sensor. /// - public float? Temperature { get; } + public float Temperature { get; } /// /// Current amount of moles detected by this sensor. /// - public float? TotalMoles { get; } + public float TotalMoles { get; } /// /// Current alarm state of this sensor. Does not reflect the highest alarm state on the network. /// @@ -34,4 +47,8 @@ public sealed class AtmosSensorData : IAtmosDeviceData /// If this sensor is currently detecting a fire. /// public bool OnFire { get; } + + public AtmosAlarmThreshold PressureThreshold { get; } + public AtmosAlarmThreshold TemperatureThreshold { get; } + public Dictionary GasThresholds { get; } } From 024e3015162d8d393d3c84dc1c0b3ae134b6c4b0 Mon Sep 17 00:00:00 2001 From: vulppine Date: Thu, 18 Aug 2022 03:15:13 -0700 Subject: [PATCH 05/80] set thresholds from network, reset command, removes OnFire from sensor data --- .../Atmos/Monitor/Systems/AirAlarmSystem.cs | 15 +++++++ .../Monitor/Systems/AtmosMonitoringSystem.cs | 39 ++++++++++++------- .../Atmos/Monitor/AtmosSensorData.cs | 7 +--- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs index d0d0246989..2368b17890 100644 --- a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs @@ -143,6 +143,21 @@ namespace Content.Server.Atmos.Monitor.Systems } } + /// + /// Reset a single sensor's state. + /// + /// + /// + private void ResetSensor(EntityUid uid, string address) + { + var payload = new NetworkPayload + { + [DeviceNetworkConstants.Command] = AtmosMonitorSystem.AtmosMonitorAlarmResetCmd, + }; + + _deviceNet.QueuePacket(uid, address, payload); + } + /// /// Sync this air alarm's mode with the rest of the network. /// diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs index 1b192c4ca8..b99e2f040b 100644 --- a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs @@ -39,12 +39,17 @@ namespace Content.Server.Atmos.Monitor.Systems /// public const string AtmosMonitorAlarmSyncCmd = "atmos_monitor_alarm_sync"; + /// + /// Command to reset a single alarm. + /// + public const string AtmosMonitorAlarmResetCmd = "atmos_monitor_alarm_reset"; + /// /// Command to reset all alarms on a network. /// public const string AtmosMonitorAlarmResetAllCmd = "atmos_monitor_alarm_reset_all"; - public const string AtmosMonitorSetThresholdData = "atmos_monitor_set_threshold"; + public const string AtmosMonitorSetThresholdCmd = "atmos_monitor_set_threshold"; // Packet data /// @@ -69,6 +74,10 @@ namespace Content.Server.Atmos.Monitor.Systems public const string AtmosMonitorThresholdData = "atmos_monitor_threshold_data"; + public const string AtmosMonitorThresholdDataType = "atmos_monitor_threshold_type"; + + public const string AtmosMonitorThresholdGasType = "atmos_monitor_threshold_gas"; + public override void Initialize() { SubscribeLocalEvent(OnAtmosMonitorInit); @@ -190,6 +199,10 @@ namespace Content.Server.Atmos.Monitor.Systems && !component.NetworkAlarmStates.TryAdd(args.SenderAddress, state)) component.NetworkAlarmStates[args.SenderAddress] = state; break; + case AtmosMonitorAlarmResetCmd: + Reset(uid); + // Don't clear alarm states here. + break; case AtmosMonitorAlarmResetAllCmd: if (args.Data.TryGetValue(AtmosMonitorAlarmSrc, out string? resetSrc) && alarmable.AlarmedByPrototypes.Contains(resetSrc)) @@ -197,6 +210,15 @@ namespace Content.Server.Atmos.Monitor.Systems component.LastAlarmState = AtmosMonitorAlarmType.Normal; component.NetworkAlarmStates.Clear(); } + break; + case AtmosMonitorSetThresholdCmd: + if (args.Data.TryGetValue(AtmosMonitorThresholdData, out AtmosAlarmThreshold? thresholdData) + && args.Data.TryGetValue(AtmosMonitorThresholdDataType, out AtmosMonitorThresholdType? thresholdType)) + { + args.Data.TryGetValue(AtmosMonitorThresholdGasType, out Gas? gas); + SetThreshold(uid, thresholdType.Value, thresholdData, gas); + } + break; case AirAlarmSystem.AirAlarmSyncCmd: var payload = new NetworkPayload(); @@ -213,9 +235,8 @@ namespace Content.Server.Atmos.Monitor.Systems component.TileGas.Pressure, component.TileGas.Temperature, component.TileGas.TotalMoles, - component.HighestAlarmInNetwork, + component.LastAlarmState, gases, - false, component.PressureThreshold ?? new(), component.TemperatureThreshold ?? new(), component.GasThresholds ?? new() @@ -225,15 +246,6 @@ namespace Content.Server.Atmos.Monitor.Systems _deviceNetSystem.QueuePacket(uid, args.SenderAddress, payload); break; } - - /* - if (component.DisplayMaxAlarmInNet) - { - if (EntityManager.TryGetComponent(component.Owner, out AppearanceComponent? appearanceComponent)) - appearanceComponent.SetData(AtmosMonitorVisuals.AlarmType, component.HighestAlarmInNetwork); - - } - */ } private void OnPowerChangedEvent(EntityUid uid, AtmosMonitorComponent component, PowerChangedEvent args) @@ -262,9 +274,6 @@ namespace Content.Server.Atmos.Monitor.Systems } } } - - if (EntityManager.TryGetComponent(component.Owner, out AppearanceComponent? appearanceComponent)) - appearanceComponent.SetData(AtmosMonitorVisuals.AlarmType, component.LastAlarmState); } private void OnFireEvent(EntityUid uid, AtmosMonitorComponent component, ref TileFireEvent args) diff --git a/Content.Shared/Atmos/Monitor/AtmosSensorData.cs b/Content.Shared/Atmos/Monitor/AtmosSensorData.cs index 3cb2f09be5..0410d025f0 100644 --- a/Content.Shared/Atmos/Monitor/AtmosSensorData.cs +++ b/Content.Shared/Atmos/Monitor/AtmosSensorData.cs @@ -4,14 +4,13 @@ namespace Content.Shared.Atmos.Monitor; public sealed class AtmosSensorData : IAtmosDeviceData { - public AtmosSensorData(float pressure, float temperature, float totalMoles, AtmosMonitorAlarmType alarmState, Dictionary gases, bool onFire, AtmosAlarmThreshold pressureThreshold, AtmosAlarmThreshold temperatureThreshold, Dictionary gasThresholds) + public AtmosSensorData(float pressure, float temperature, float totalMoles, AtmosMonitorAlarmType alarmState, Dictionary gases, AtmosAlarmThreshold pressureThreshold, AtmosAlarmThreshold temperatureThreshold, Dictionary gasThresholds) { Pressure = pressure; Temperature = temperature; TotalMoles = totalMoles; AlarmState = alarmState; Gases = gases; - OnFire = onFire; PressureThreshold = pressureThreshold; TemperatureThreshold = temperatureThreshold; GasThresholds = gasThresholds; @@ -43,10 +42,6 @@ public sealed class AtmosSensorData : IAtmosDeviceData /// Current number of gases on this sensor. /// public Dictionary Gases { get; } - /// - /// If this sensor is currently detecting a fire. - /// - public bool OnFire { get; } public AtmosAlarmThreshold PressureThreshold { get; } public AtmosAlarmThreshold TemperatureThreshold { get; } From 10e10b4bae2be02d96aff620948c07a68bf9daf6 Mon Sep 17 00:00:00 2001 From: vulppine Date: Thu, 18 Aug 2022 06:44:43 -0700 Subject: [PATCH 06/80] set threshold on server, pressure/temperature average from all sensors sent with air alarm state --- .../Atmos/Monitor/Systems/AirAlarmSystem.cs | 90 ++++++++----------- .../Components/SharedAirAlarmComponent.cs | 58 +++--------- 2 files changed, 48 insertions(+), 100 deletions(-) diff --git a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs index 2368b17890..cb565712e9 100644 --- a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs @@ -1,3 +1,4 @@ +using System.Linq; using Content.Server.Atmos.Monitor.Components; using Content.Server.Atmos.Piping.Components; using Content.Server.DeviceNetwork; @@ -158,6 +159,26 @@ namespace Content.Server.Atmos.Monitor.Systems _deviceNet.QueuePacket(uid, address, payload); } + private void SetThreshold(EntityUid uid, string address, AtmosMonitorThresholdType type, + AtmosAlarmThreshold threshold, Gas? gas = null) + { + var payload = new NetworkPayload + { + [DeviceNetworkConstants.Command] = AtmosMonitorSystem.AtmosMonitorSetThresholdCmd, + [AtmosMonitorSystem.AtmosMonitorThresholdDataType] = type, + [AtmosMonitorSystem.AtmosMonitorThresholdData] = threshold, + }; + + if (gas != null) + { + payload.Add(AtmosMonitorSystem.AtmosMonitorThresholdGasType, gas); + } + + _deviceNet.QueuePacket(uid, address, payload); + + SyncDevice(uid, address); + } + /// /// Sync this air alarm's mode with the rest of the network. /// @@ -273,7 +294,7 @@ namespace Content.Server.Atmos.Monitor.Systems private void OnUpdateThreshold(EntityUid uid, AirAlarmComponent component, AirAlarmUpdateAlarmThresholdMessage args) { if (AccessCheck(uid, args.Session.AttachedEntity, component)) - SetThreshold(uid, args.Threshold, args.Type, args.Gas); + SetThreshold(uid, args.Address, args.Type, args.Threshold, args.Gas); else UpdateUI(uid, component); } @@ -339,20 +360,6 @@ namespace Content.Server.Atmos.Monitor.Systems #region Air Alarm Settings - /// - /// Set a threshold on an air alarm. - /// - /// New threshold data. - public void SetThreshold(EntityUid uid, AtmosAlarmThreshold threshold, AtmosMonitorThresholdType type, Gas? gas = null, AirAlarmComponent? controller = null) - { - if (!Resolve(uid, ref controller)) return; - - _atmosMonitorSystem.SetThreshold(uid, type, threshold, gas); - - // TODO: Use BUI states instead... - _uiSystem.TrySendUiMessage(uid, SharedAirAlarmInterfaceKey.Key, new AirAlarmUpdateAlarmThresholdMessage(type, threshold, gas)); - } - /// /// Set an air alarm's mode. /// @@ -413,45 +420,6 @@ namespace Content.Server.Atmos.Monitor.Systems SetData(uid, address, devData); } - private void OnAtmosAlarm(EntityUid uid, AirAlarmComponent component, NetworkPayload args) - { - if (component.ActivePlayers.Count != 0) - { - SyncAllDevices(uid); - } - - string addr = string.Empty; - if (TryComp(uid, out DeviceNetworkComponent? netConn)) - { - addr = netConn.Address; - } - - if (!args.TryGetValue(AtmosMonitorSystem.AtmosMonitorAlarmNetMax, out AtmosMonitorAlarmType? highestNetworkType)) - { - return; - } - - if (highestNetworkType == AtmosMonitorAlarmType.Danger) - { - SetMode(uid, addr, AirAlarmMode.None, true); - // set mode to off to mimic the vents/scrubbers being turned off - // update UI - // - // no, the mode isn't processed here - it's literally just - // set to what mimics 'off' - } - else if (highestNetworkType == AtmosMonitorAlarmType.Normal) - { - // if the mode is still set to off, set it to filtering instead - // alternatively, set it to the last saved mode - // - // 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) { if (!args.Data.TryGetValue(DeviceNetworkConstants.Command, out string? cmd)) @@ -539,6 +507,16 @@ namespace Content.Server.Atmos.Monitor.Systems alarm.CurrentModeUpdater.Update(uid); } + private float CalculatePressureAverage(AirAlarmComponent alarm) + { + return alarm.SensorData.Values.Select(v => v.Pressure).Average(); + } + + private float CalculateTemperatureAverage(AirAlarmComponent alarm) + { + return alarm.SensorData.Values.Select(v => v.Temperature).Average(); + } + public void UpdateUI(EntityUid uid, AirAlarmComponent? alarm = null, AtmosAlarmableComponent? alarmable = null) { if (!Resolve(uid, ref alarm, ref alarmable)) @@ -546,6 +524,8 @@ namespace Content.Server.Atmos.Monitor.Systems return; } + var pressure = CalculatePressureAverage(uid, alarm); + var temperature = CalculateTemperatureAverage(uid, alarm); var dataToSend = new Dictionary(); if (alarm.CurrentTab != AirAlarmTab.Settings) @@ -579,7 +559,7 @@ namespace Content.Server.Atmos.Monitor.Systems _uiSystem.TrySetUiState( uid, SharedAirAlarmInterfaceKey.Key, - new AirAlarmUIState(dataToSend, alarm.CurrentMode, alarm.CurrentTab, alarmable.HighestNetworkState)); + new AirAlarmUIState(pressure, temperature, dataToSend, alarm.CurrentMode, alarm.CurrentTab, alarmable.HighestNetworkState)); } private const float _delay = 8f; diff --git a/Content.Shared/Atmos/Monitor/Components/SharedAirAlarmComponent.cs b/Content.Shared/Atmos/Monitor/Components/SharedAirAlarmComponent.cs index b7075ee976..3e9e21ffe8 100644 --- a/Content.Shared/Atmos/Monitor/Components/SharedAirAlarmComponent.cs +++ b/Content.Shared/Atmos/Monitor/Components/SharedAirAlarmComponent.cs @@ -27,27 +27,6 @@ namespace Content.Shared.Atmos.Monitor.Components DeviceSync } - [Serializable, NetSerializable] - public readonly struct AirAlarmAirData - { - public readonly float? Pressure { get; } - public readonly float? Temperature { get; } - public readonly float? TotalMoles { get; } - public readonly AtmosMonitorAlarmType AlarmState { get; } - - private readonly Dictionary? _gases; - public readonly IReadOnlyDictionary? Gases { get => _gases; } - - public AirAlarmAirData(float? pressure, float? temperature, float? moles, AtmosMonitorAlarmType state, Dictionary? gases) - { - Pressure = pressure; - Temperature = temperature; - TotalMoles = moles; - AlarmState = state; - _gases = gases; - } - } - public interface IAtmosDeviceData { public bool Enabled { get; set; } @@ -58,14 +37,18 @@ namespace Content.Shared.Atmos.Monitor.Components [Serializable, NetSerializable] public sealed class AirAlarmUIState : BoundUserInterfaceState { - public AirAlarmUIState(Dictionary deviceData, AirAlarmMode mode, AirAlarmTab tab, AtmosMonitorAlarmType alarmType) + public AirAlarmUIState(float pressureAverage, float temperatureAverage, Dictionary deviceData, AirAlarmMode mode, AirAlarmTab tab, AtmosMonitorAlarmType alarmType) { + PressureAverage = pressureAverage; + TemperatureAverage = temperatureAverage; DeviceData = deviceData; Mode = mode; Tab = tab; AlarmType = alarmType; } + public float PressureAverage { get; } + public float TemperatureAverage { get; } /// /// Every single device data that can be seen from this /// air alarm. This includes vents, scrubbers, and sensors. @@ -81,6 +64,11 @@ namespace Content.Shared.Atmos.Monitor.Components [Serializable, NetSerializable] public sealed class AirAlarmTabSetMessage : BoundUserInterfaceMessage { + public AirAlarmTabSetMessage(AirAlarmTab tab) + { + Tab = tab; + } + public AirAlarmTab Tab { get; } } @@ -88,28 +76,6 @@ namespace Content.Shared.Atmos.Monitor.Components public sealed class AirAlarmResyncAllDevicesMessage : BoundUserInterfaceMessage {} - [Serializable, NetSerializable] - public sealed class AirAlarmSetAddressMessage : BoundUserInterfaceMessage - { - public string Address { get; } - - public AirAlarmSetAddressMessage(string address) - { - Address = address; - } - } - - [Serializable, NetSerializable] - public sealed class AirAlarmUpdateAirDataMessage : BoundUserInterfaceMessage - { - public AirAlarmAirData AirData; - - public AirAlarmUpdateAirDataMessage(AirAlarmAirData airData) - { - AirData = airData; - } - } - [Serializable, NetSerializable] public sealed class AirAlarmUpdateAlarmModeMessage : BoundUserInterfaceMessage { @@ -137,12 +103,14 @@ namespace Content.Shared.Atmos.Monitor.Components [Serializable, NetSerializable] public sealed class AirAlarmUpdateAlarmThresholdMessage : BoundUserInterfaceMessage { + public string Address { get; } public AtmosAlarmThreshold Threshold { get; } public AtmosMonitorThresholdType Type { get; } public Gas? Gas { get; } - public AirAlarmUpdateAlarmThresholdMessage(AtmosMonitorThresholdType type, AtmosAlarmThreshold threshold, Gas? gas = null) + public AirAlarmUpdateAlarmThresholdMessage(string address, AtmosMonitorThresholdType type, AtmosAlarmThreshold threshold, Gas? gas = null) { + Address = address; Threshold = threshold; Type = type; Gas = gas; From 531f0cb0e511a41feeb44f65caab1a0b4750c150 Mon Sep 17 00:00:00 2001 From: vulppine Date: Thu, 18 Aug 2022 07:03:37 -0700 Subject: [PATCH 07/80] ui updates (no sensors yet) --- .../Monitor/UI/AirAlarmBoundUserInterface.cs | 29 +++++-------------- .../Atmos/Monitor/UI/AirAlarmWindow.xaml.cs | 21 +++++++++++--- .../Atmos/Monitor/Systems/AirAlarmSystem.cs | 4 +-- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Content.Client/Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs b/Content.Client/Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs index df419b282c..013f70a991 100644 --- a/Content.Client/Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs +++ b/Content.Client/Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs @@ -47,34 +47,21 @@ namespace Content.Client.Atmos.Monitor.UI SendMessage(new AirAlarmUpdateAlarmModeMessage(mode)); } - private void OnThresholdChanged(AtmosMonitorThresholdType type, AtmosAlarmThreshold threshold, Gas? gas = null) + private void OnThresholdChanged(string address, AtmosMonitorThresholdType type, AtmosAlarmThreshold threshold, Gas? gas = null) { - SendMessage(new AirAlarmUpdateAlarmThresholdMessage(type, threshold, gas)); + SendMessage(new AirAlarmUpdateAlarmThresholdMessage(address, type, threshold, gas)); } - protected override void ReceiveMessage(BoundUserInterfaceMessage message) + protected override void UpdateState(BoundUserInterfaceState state) { - if (_window == null) - return; + base.UpdateState(state); - switch (message) + if (state is not AirAlarmUIState cast || _window == null) { - case AirAlarmSetAddressMessage addrMsg: - _window.SetAddress(addrMsg.Address); - break; - case AirAlarmUpdateDeviceDataMessage deviceMsg: - _window.UpdateDeviceData(deviceMsg.Address, deviceMsg.Data); - break; - case AirAlarmUpdateAlarmModeMessage alarmMsg: - _window.UpdateModeSelector(alarmMsg.Mode); - break; - case AirAlarmUpdateAlarmThresholdMessage thresholdMsg: - _window.UpdateThreshold(ref thresholdMsg); - break; - case AirAlarmUpdateAirDataMessage airDataMsg: - _window.UpdateGasData(ref airDataMsg.AirData); - break; + return; } + + _window.UpdateState(cast); } protected override void Dispose(bool disposing) diff --git a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs index 29445cfcff..135f80b3cd 100644 --- a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs +++ b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs @@ -19,7 +19,7 @@ namespace Content.Client.Atmos.Monitor.UI public sealed partial class AirAlarmWindow : DefaultWindow { public event Action? AtmosDeviceDataChanged; - public event Action? AtmosAlarmThresholdChanged; + public event Action? AtmosAlarmThresholdChanged; public event Action? AirAlarmModeChanged; public event Action? ResyncDeviceRequested; public event Action? ResyncAllRequested; @@ -34,9 +34,6 @@ namespace Content.Client.Atmos.Monitor.UI private BoxContainer _gasReadout => CGasContainer; private BoxContainer _ventDevices => CVentContainer; private BoxContainer _scrubberDevices => CScrubberContainer; - private BoxContainer _pressureThreshold => CPressureThreshold; - private BoxContainer _temperatureThreshold => CTemperatureThreshold; - private BoxContainer _gasThreshold => CGasThresholdContainer; private Dictionary _pumps = new(); private Dictionary _scrubbers = new(); @@ -85,11 +82,24 @@ namespace Content.Client.Atmos.Monitor.UI }; } + public void UpdateState(AirAlarmUIState state) + { + _pressure.SetMarkup(Loc.GetString("air-alarm-ui-window-pressure", ("pressure", $"{state.PressureAverage:0.##}"))); + _temperature.SetMarkup(Loc.GetString("air-alarm-ui-window-temperature", ("tempC", $"{TemperatureHelpers.KelvinToCelsius(state.TemperatureAverage):0.#}"), ("temperature", $"{state.TemperatureAverage:0.##}"))); + _alarmState.SetMarkup(Loc.GetString("air-alarm-ui-window-alarm-state", ("state", $"{state.AlarmType}"))); + UpdateModeSelector(state.Mode); + foreach (var (addr, dev) in state.DeviceData) + { + UpdateDeviceData(addr, dev); + } + } + public void SetAddress(string address) { _address.Text = address; } + /* public void UpdateGasData(ref AirAlarmAirData state) { _pressure.SetMarkup(Loc.GetString("air-alarm-ui-window-pressure", ("pressure", $"{state.Pressure:0.##}"))); @@ -100,6 +110,7 @@ namespace Content.Client.Atmos.Monitor.UI foreach (var (gas, amount) in state.Gases) _gasLabels[gas].Text = Loc.GetString("air-alarm-ui-gases", ("gas", $"{gas}"), ("amount", $"{amount:0.####}"), ("percentage", $"{(amount / state.TotalMoles):0.##}")); } + */ public void UpdateModeSelector(AirAlarmMode mode) { @@ -143,6 +154,7 @@ namespace Content.Client.Atmos.Monitor.UI _deviceTotal.Text = $"{_pumps.Count + _scrubbers.Count}"; } + /* public void UpdateThreshold(ref AirAlarmUpdateAlarmThresholdMessage message) { switch (message.Type) @@ -188,5 +200,6 @@ namespace Content.Client.Atmos.Monitor.UI break; } } + */ } } diff --git a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs index cb565712e9..bafaaa641e 100644 --- a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs @@ -524,8 +524,8 @@ namespace Content.Server.Atmos.Monitor.Systems return; } - var pressure = CalculatePressureAverage(uid, alarm); - var temperature = CalculateTemperatureAverage(uid, alarm); + var pressure = CalculatePressureAverage(alarm); + var temperature = CalculateTemperatureAverage(alarm); var dataToSend = new Dictionary(); if (alarm.CurrentTab != AirAlarmTab.Settings) From e0ee36ad629c516e8b9995d378c8d455f84393ed Mon Sep 17 00:00:00 2001 From: vulppine Date: Thu, 18 Aug 2022 07:10:39 -0700 Subject: [PATCH 08/80] average calculation now returns 0 if there are no sensors --- Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs index bafaaa641e..ffd2c9e37c 100644 --- a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs @@ -509,12 +509,16 @@ namespace Content.Server.Atmos.Monitor.Systems private float CalculatePressureAverage(AirAlarmComponent alarm) { - return alarm.SensorData.Values.Select(v => v.Pressure).Average(); + return alarm.SensorData.Count != 0 + ? alarm.SensorData.Values.Select(v => v.Pressure).Average() + : 0f; } private float CalculateTemperatureAverage(AirAlarmComponent alarm) { - return alarm.SensorData.Values.Select(v => v.Temperature).Average(); + return alarm.SensorData.Count != 0 + ? alarm.SensorData.Values.Select(v => v.Temperature).Average() + : 0f; } public void UpdateUI(EntityUid uid, AirAlarmComponent? alarm = null, AtmosAlarmableComponent? alarmable = null) From b444c0bbbebd6232ef96d6e27546cf796dc1dcb3 Mon Sep 17 00:00:00 2001 From: vulppine Date: Thu, 18 Aug 2022 07:26:01 -0700 Subject: [PATCH 09/80] whoops, forgot to actually sync monitor data in --- Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs index b99e2f040b..fffb45f0a5 100644 --- a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs @@ -231,7 +231,7 @@ namespace Content.Server.Atmos.Monitor.Systems gases.Add(gas, component.TileGas.GetMoles(gas)); } - payload.Add(AtmosMonitorAtmosData, new AtmosSensorData( + payload.Add(AirAlarmSystem.AirAlarmSyncData, new AtmosSensorData( component.TileGas.Pressure, component.TileGas.Temperature, component.TileGas.TotalMoles, From 35ba20de17357a5b1ba44920e2befddaf23eedd6 Mon Sep 17 00:00:00 2001 From: vulppine Date: Thu, 18 Aug 2022 07:52:21 -0700 Subject: [PATCH 10/80] air alarm window changes, firelock alarmable --- Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml | 4 ---- .../Atmos/Monitor/UI/AirAlarmWindow.xaml.cs | 13 +++++++++---- .../Structures/Doors/Firelocks/firelock.yml | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml index 734fd74de0..8e8e959e65 100644 --- a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml +++ b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml @@ -28,10 +28,6 @@ - - - - diff --git a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs index 135f80b3cd..56dc363d38 100644 --- a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs +++ b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs @@ -23,6 +23,7 @@ namespace Content.Client.Atmos.Monitor.UI public event Action? AirAlarmModeChanged; public event Action? ResyncDeviceRequested; public event Action? ResyncAllRequested; + public event Action? AirAlarmTabChange; private Label _address => CDeviceAddress; private Label _deviceTotal => CDeviceTotal; @@ -67,10 +68,14 @@ namespace Content.Client.Atmos.Monitor.UI _gasLabels.Add(gas, gasLabel); } - _tabContainer.SetTabTitle(0, Loc.GetString("air-alarm-ui-window-tab-gas")); - _tabContainer.SetTabTitle(1, Loc.GetString("air-alarm-ui-window-tab-vents")); - _tabContainer.SetTabTitle(2, Loc.GetString("air-alarm-ui-window-tab-scrubbers")); - _tabContainer.SetTabTitle(3, Loc.GetString("air-alarm-ui-window-tab-thresholds")); + _tabContainer.SetTabTitle(0, Loc.GetString("air-alarm-ui-window-tab-vents")); + _tabContainer.SetTabTitle(1, Loc.GetString("air-alarm-ui-window-tab-scrubbers")); + _tabContainer.SetTabTitle(2, Loc.GetString("air-alarm-ui-window-tab-sensors")); + + _tabContainer.OnTabChanged += idx => + { + AirAlarmTabChange!((AirAlarmTab) idx); + }; _resyncDevices.OnPressed += _ => { diff --git a/Resources/Prototypes/Entities/Structures/Doors/Firelocks/firelock.yml b/Resources/Prototypes/Entities/Structures/Doors/Firelocks/firelock.yml index 3e63d5e4b2..4312a31f46 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/Firelocks/firelock.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/Firelocks/firelock.yml @@ -7,7 +7,7 @@ - type: AtmosAlarmable alarmedBy: - FireAlarm - - AirAlarm + - GasVentPump # TODO: No - type: ApcPowerReceiver - type: ExtensionCableReceiver - type: DeviceNetwork From 327314b82f5b6a8a251acceb659f0a8d15fa68d2 Mon Sep 17 00:00:00 2001 From: vulppine Date: Thu, 18 Aug 2022 08:14:18 -0700 Subject: [PATCH 11/80] tab changing --- .../Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs | 6 ++++++ Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs | 3 ++- Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Content.Client/Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs b/Content.Client/Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs index 013f70a991..8823ff8b3c 100644 --- a/Content.Client/Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs +++ b/Content.Client/Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs @@ -30,6 +30,7 @@ namespace Content.Client.Atmos.Monitor.UI _window.AtmosAlarmThresholdChanged += OnThresholdChanged; _window.AirAlarmModeChanged += OnAirAlarmModeChanged; _window.ResyncAllRequested += ResyncAllDevices; + _window.AirAlarmTabChange += OnTabChanged; } private void ResyncAllDevices() @@ -52,6 +53,11 @@ namespace Content.Client.Atmos.Monitor.UI SendMessage(new AirAlarmUpdateAlarmThresholdMessage(address, type, threshold, gas)); } + private void OnTabChanged(AirAlarmTab tab) + { + SendMessage(new AirAlarmTabSetMessage(tab)); + } + protected override void UpdateState(BoundUserInterfaceState state) { base.UpdateState(state); diff --git a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs index 56dc363d38..44068c1879 100644 --- a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs +++ b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs @@ -32,7 +32,6 @@ namespace Content.Client.Atmos.Monitor.UI private RichTextLabel _alarmState => CStatusLabel; private TabContainer _tabContainer => CTabContainer; - private BoxContainer _gasReadout => CGasContainer; private BoxContainer _ventDevices => CVentContainer; private BoxContainer _scrubberDevices => CScrubberContainer; @@ -61,12 +60,14 @@ namespace Content.Client.Atmos.Monitor.UI AirAlarmModeChanged!.Invoke((AirAlarmMode) args.Id); }; + /* foreach (var gas in Enum.GetValues()) { var gasLabel = new Label(); _gasReadout.AddChild(gasLabel); _gasLabels.Add(gas, gasLabel); } + */ _tabContainer.SetTabTitle(0, Loc.GetString("air-alarm-ui-window-tab-vents")); _tabContainer.SetTabTitle(1, Loc.GetString("air-alarm-ui-window-tab-scrubbers")); diff --git a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs index ffd2c9e37c..d43c93fcbb 100644 --- a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs @@ -212,11 +212,18 @@ namespace Content.Server.Atmos.Monitor.Systems SubscribeLocalEvent(OnUpdateAlarmMode); SubscribeLocalEvent(OnUpdateThreshold); SubscribeLocalEvent(OnUpdateDeviceData); + SubscribeLocalEvent(OnTabChange); SubscribeLocalEvent(OnClose); SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnInteract); } + private void OnTabChange(EntityUid uid, AirAlarmComponent component, AirAlarmTabSetMessage msg) + { + component.CurrentTab = msg.Tab; + UpdateUI(uid, component); + } + private void OnPowerChanged(EntityUid uid, AirAlarmComponent component, PowerChangedEvent args) { if (!args.Powered) From 787bcf903cf10242ee8e076c02dc8b44afec9ddb Mon Sep 17 00:00:00 2001 From: vulppine Date: Thu, 18 Aug 2022 08:16:30 -0700 Subject: [PATCH 12/80] tab setting on updatestate --- Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs index 44068c1879..2540694d64 100644 --- a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs +++ b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs @@ -98,6 +98,8 @@ namespace Content.Client.Atmos.Monitor.UI { UpdateDeviceData(addr, dev); } + + _tabContainer.CurrentTab = (int) state.Tab; } public void SetAddress(string address) From 9b1c8f63e54d516752d5884468a1f7fbe29f3af9 Mon Sep 17 00:00:00 2001 From: vulppine Date: Thu, 18 Aug 2022 08:30:32 -0700 Subject: [PATCH 13/80] makes sensor data serializable --- Content.Shared/Atmos/Monitor/AtmosSensorData.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Content.Shared/Atmos/Monitor/AtmosSensorData.cs b/Content.Shared/Atmos/Monitor/AtmosSensorData.cs index 0410d025f0..435b538d64 100644 --- a/Content.Shared/Atmos/Monitor/AtmosSensorData.cs +++ b/Content.Shared/Atmos/Monitor/AtmosSensorData.cs @@ -1,7 +1,9 @@ using Content.Shared.Atmos.Monitor.Components; +using Robust.Shared.Serialization; namespace Content.Shared.Atmos.Monitor; +[Serializable, NetSerializable] public sealed class AtmosSensorData : IAtmosDeviceData { public AtmosSensorData(float pressure, float temperature, float totalMoles, AtmosMonitorAlarmType alarmState, Dictionary gases, AtmosAlarmThreshold pressureThreshold, AtmosAlarmThreshold temperatureThreshold, Dictionary gasThresholds) From 376f4c89721bf98c9b8675457be952dd22c760cf Mon Sep 17 00:00:00 2001 From: vulppine Date: Thu, 18 Aug 2022 23:54:39 -0700 Subject: [PATCH 14/80] sensor UI --- .../Atmos/Monitor/UI/AirAlarmWindow.xaml.cs | 18 +++- .../Atmos/Monitor/UI/Widgets/SensorInfo.xaml | 21 ++++ .../Monitor/UI/Widgets/SensorInfo.xaml.cs | 102 ++++++++++++++++++ .../UI/Widgets/ThresholdControl.xaml.cs | 2 + 4 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml create mode 100644 Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml.cs diff --git a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs index 2540694d64..3d77db0914 100644 --- a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs +++ b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs @@ -37,11 +37,9 @@ namespace Content.Client.Atmos.Monitor.UI private Dictionary _pumps = new(); private Dictionary _scrubbers = new(); + private Dictionary _sensors = new(); private Button _resyncDevices => CResyncButton; - private ThresholdControl? _pressureThresholdControl; - private ThresholdControl? _temperatureThresholdControl; - private Dictionary _gasThresholdControls = new(); private Dictionary _gasLabels = new(); @@ -156,6 +154,20 @@ namespace Content.Client.Atmos.Monitor.UI scrubberControl.ChangeData(scrubber); } + break; + case AtmosSensorData sensor: + if (!_sensors.TryGetValue(addr, out var sensorControl)) + { + var control = new SensorInfo(sensor, addr); + control.OnThresholdUpdate += AtmosAlarmThresholdChanged; + _sensors.Add(addr, control); + CSensorContainer.AddChild(control); + } + else + { + sensorControl.ChangeData(sensor); + } + break; } diff --git a/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml b/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml new file mode 100644 index 0000000000..cda3c9a4fe --- /dev/null +++ b/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml.cs b/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml.cs new file mode 100644 index 0000000000..30ae8de850 --- /dev/null +++ b/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml.cs @@ -0,0 +1,102 @@ +using Content.Client.Message; +using Content.Shared.Atmos; +using Content.Shared.Atmos.Monitor; +using Content.Shared.Temperature; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.Atmos.Monitor.UI.Widgets; + +[GenerateTypedNameReferences] +public sealed partial class SensorInfo : BoxContainer +{ + public Action? OnThresholdUpdate; + private string _address; + + private ThresholdControl _pressureThreshold; + private ThresholdControl _temperatureThreshold; + private Dictionary _gasThresholds = new(); + private Dictionary _gasLabels = new(); + + public SensorInfo(AtmosSensorData data, string address) + { + RobustXamlLoader.Load(this); + + _address = address; + + SensorAddress.Title = address; + + PressureLabel.SetMarkup(Loc.GetString("air-alarm-ui-window-pressure", ("pressure", $"{data.Pressure:0.##}"))); + TemperatureLabel.SetMarkup(Loc.GetString("air-alarm-ui-window-temperature", ("tempC", $"{TemperatureHelpers.KelvinToCelsius(data.Temperature):0.#}"), ("temperature", $"{data.Temperature:0.##}"))); + AlarmStateLabel.SetMarkup(Loc.GetString("air-alarm-ui-window-alarm-state", ("state", $"{data.AlarmState}"))); + + foreach (var (gas, amount) in data.Gases) + { + var label = new Label(); + label.Text = Loc.GetString("air-alarm-ui-gases", ("gas", $"{gas}"), + ("amount", $"{(amount / data.TotalMoles):0.##}")); + GasContainer.AddChild(label); + _gasLabels.Add(gas, label); + } + + _pressureThreshold = + new ThresholdControl("Pressure", data.PressureThreshold, AtmosMonitorThresholdType.Pressure); + PressureThresholdContainer.AddChild(_pressureThreshold); + _temperatureThreshold = new ThresholdControl("Temperature", data.TemperatureThreshold, + AtmosMonitorThresholdType.Temperature); + TemperatureThresholdContainer.AddChild(_temperatureThreshold); + + _pressureThreshold.ThresholdDataChanged += (type, threshold, arg3) => + { + OnThresholdUpdate!(_address, type, threshold, arg3); + }; + + _temperatureThreshold.ThresholdDataChanged += (type, threshold, arg3) => + { + OnThresholdUpdate!(_address, type, threshold, arg3); + }; + + foreach (var (gas, threshold) in data.GasThresholds) + { + var gasThresholdControl = new ThresholdControl(gas.ToString(), threshold, AtmosMonitorThresholdType.Gas, gas); + gasThresholdControl.ThresholdDataChanged += (type, threshold, arg3) => + { + OnThresholdUpdate!(_address, type, threshold, arg3); + }; + + _gasThresholds.Add(gas, gasThresholdControl); + GasThresholds.AddChild(gasThresholdControl); + } + } + + public void ChangeData(AtmosSensorData data) + { + PressureLabel.SetMarkup(Loc.GetString("air-alarm-ui-window-pressure", ("pressure", $"{data.Pressure:0.##}"))); + TemperatureLabel.SetMarkup(Loc.GetString("air-alarm-ui-window-temperature", ("tempC", $"{TemperatureHelpers.KelvinToCelsius(data.Temperature):0.#}"), ("temperature", $"{data.Temperature:0.##}"))); + AlarmStateLabel.SetMarkup(Loc.GetString("air-alarm-ui-window-alarm-state", ("state", $"{data.AlarmState}"))); + + foreach (var (gas, amount) in data.Gases) + { + if (!_gasLabels.TryGetValue(gas, out var label)) + { + continue; + } + + label.Text = Loc.GetString("air-alarm-ui-gases", ("gas", $"{gas}"), + ("amount", $"{(amount / data.TotalMoles):0.##}")); + } + + _pressureThreshold.UpdateThresholdData(data.PressureThreshold); + _temperatureThreshold.UpdateThresholdData(data.TemperatureThreshold); + foreach (var (gas, control) in _gasThresholds) + { + if (!data.GasThresholds.TryGetValue(gas, out var threshold)) + { + continue; + } + + control.UpdateThresholdData(threshold); + } + } +} diff --git a/Content.Client/Atmos/Monitor/UI/Widgets/ThresholdControl.xaml.cs b/Content.Client/Atmos/Monitor/UI/Widgets/ThresholdControl.xaml.cs index d05d92f8f2..b3da0b2d6c 100644 --- a/Content.Client/Atmos/Monitor/UI/Widgets/ThresholdControl.xaml.cs +++ b/Content.Client/Atmos/Monitor/UI/Widgets/ThresholdControl.xaml.cs @@ -8,6 +8,8 @@ using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Localization; +// holy FUCK +// this technically works because some of this you can *not* do in XAML but holy FUCK namespace Content.Client.Atmos.Monitor.UI.Widgets { From 7f76d49ea8144054927df360df2facb7a7bcf5ea Mon Sep 17 00:00:00 2001 From: vulppine Date: Fri, 19 Aug 2022 00:20:50 -0700 Subject: [PATCH 15/80] whoops! --- .../Atmos/Monitor/UI/Widgets/SensorInfo.xaml | 30 +++++++++++-------- .../Monitor/UI/Widgets/SensorInfo.xaml.cs | 12 ++++---- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml b/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml index cda3c9a4fe..ee1ef6b7eb 100644 --- a/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml +++ b/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml @@ -3,19 +3,23 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml.cs b/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml.cs index 30ae8de850..de2b2c1a40 100644 --- a/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml.cs +++ b/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml.cs @@ -35,15 +35,16 @@ public sealed partial class SensorInfo : BoxContainer { var label = new Label(); label.Text = Loc.GetString("air-alarm-ui-gases", ("gas", $"{gas}"), - ("amount", $"{(amount / data.TotalMoles):0.##}")); + ("amount", $"{amount:0.####}"), + ("percentage", $"{(amount / data.TotalMoles):0.##}")); GasContainer.AddChild(label); _gasLabels.Add(gas, label); } _pressureThreshold = - new ThresholdControl("Pressure", data.PressureThreshold, AtmosMonitorThresholdType.Pressure); + new ThresholdControl(Loc.GetString("air-alarm-ui-thresholds-pressure-title"), data.PressureThreshold, AtmosMonitorThresholdType.Pressure); PressureThresholdContainer.AddChild(_pressureThreshold); - _temperatureThreshold = new ThresholdControl("Temperature", data.TemperatureThreshold, + _temperatureThreshold = new ThresholdControl(Loc.GetString("air-alarm-ui-thresholds-temperature-title"), data.TemperatureThreshold, AtmosMonitorThresholdType.Temperature); TemperatureThresholdContainer.AddChild(_temperatureThreshold); @@ -59,7 +60,7 @@ public sealed partial class SensorInfo : BoxContainer foreach (var (gas, threshold) in data.GasThresholds) { - var gasThresholdControl = new ThresholdControl(gas.ToString(), threshold, AtmosMonitorThresholdType.Gas, gas); + var gasThresholdControl = new ThresholdControl(Loc.GetString($"air-alarm-ui-thresholds-gas-title", ("gas", $"{gas}")), threshold, AtmosMonitorThresholdType.Gas, gas, 100); gasThresholdControl.ThresholdDataChanged += (type, threshold, arg3) => { OnThresholdUpdate!(_address, type, threshold, arg3); @@ -84,7 +85,8 @@ public sealed partial class SensorInfo : BoxContainer } label.Text = Loc.GetString("air-alarm-ui-gases", ("gas", $"{gas}"), - ("amount", $"{(amount / data.TotalMoles):0.##}")); + ("amount", $"{amount:0.####}"), + ("percentage", $"{(amount / data.TotalMoles):0.##}")); } _pressureThreshold.UpdateThresholdData(data.PressureThreshold); From bf215350a7c9de8257c33e5b36d5577d07638d8e Mon Sep 17 00:00:00 2001 From: vulppine Date: Fri, 19 Aug 2022 00:29:18 -0700 Subject: [PATCH 16/80] double whoops (and also some localization) --- .../Atmos/Monitor/UI/Widgets/SensorInfo.xaml | 18 ++++++++++++------ Resources/Locale/en-US/atmos/air-alarm-ui.ftl | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml b/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml index ee1ef6b7eb..de8cbd6785 100644 --- a/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml +++ b/Content.Client/Atmos/Monitor/UI/Widgets/SensorInfo.xaml @@ -3,12 +3,18 @@ - - - - - - + + + + + + + + + diff --git a/Resources/Locale/en-US/atmos/air-alarm-ui.ftl b/Resources/Locale/en-US/atmos/air-alarm-ui.ftl index 6428a85cda..45eda887ef 100644 --- a/Resources/Locale/en-US/atmos/air-alarm-ui.ftl +++ b/Resources/Locale/en-US/atmos/air-alarm-ui.ftl @@ -21,7 +21,7 @@ air-alarm-ui-window-alarm-state = {$state} air-alarm-ui-window-tab-gas = Gases air-alarm-ui-window-tab-vents = Vents air-alarm-ui-window-tab-scrubbers = Scrubbers -air-alarm-ui-window-tab-thresholds = Thresholds +air-alarm-ui-sensor-thresholds = Thresholds air-alarm-ui-gases = {$gas}: {$amount} mol ({$percentage}%) From a0e9f4d0b84a3be21f3c4ca82655100ec79431a0 Mon Sep 17 00:00:00 2001 From: vulppine Date: Fri, 19 Aug 2022 04:06:09 -0700 Subject: [PATCH 17/80] UI changes --- .../Atmos/Monitor/UI/AirAlarmWindow.xaml | 27 ++----- .../Atmos/Monitor/UI/AirAlarmWindow.xaml.cs | 81 +------------------ .../Atmos/Monitor/UI/Widgets/SensorInfo.xaml | 36 +++++---- .../Monitor/UI/Widgets/SensorInfo.xaml.cs | 2 +- .../Atmos/Monitor/Systems/AirAlarmSystem.cs | 10 ++- .../Components/SharedAirAlarmComponent.cs | 6 +- Resources/Locale/en-US/atmos/air-alarm-ui.ftl | 5 +- 7 files changed, 45 insertions(+), 122 deletions(-) diff --git a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml index 8e8e959e65..6b36b86a23 100644 --- a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml +++ b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml @@ -20,9 +20,14 @@ + + +