diff --git a/Content.Server/Atmos/Monitor/Components/AtmosAlarmableComponent.cs b/Content.Server/Atmos/Monitor/Components/AtmosAlarmableComponent.cs index c7fb878001..23a903ff9c 100644 --- a/Content.Server/Atmos/Monitor/Components/AtmosAlarmableComponent.cs +++ b/Content.Server/Atmos/Monitor/Components/AtmosAlarmableComponent.cs @@ -28,13 +28,10 @@ namespace Content.Server.Atmos.Monitor.Components public sealed class AtmosAlarmableComponent : Component { [ViewVariables] - public List LinkedMonitors { get; set; } = new(); - - [ViewVariables] - public Dictionary NetworkAlarmStates = new(); + public readonly Dictionary NetworkAlarmStates = new(); [ViewVariables] public AtmosMonitorAlarmType LastAlarmState = AtmosMonitorAlarmType.Normal; - [ViewVariables] public AtmosMonitorAlarmType HighestNetworkState = AtmosMonitorAlarmType.Normal; + [ViewVariables] public bool IgnoreAlarms { get; set; } = false; [DataField("alarmSound")] @@ -44,11 +41,19 @@ namespace Content.Server.Atmos.Monitor.Components public float AlarmVolume { get; set; } = -10; /// - /// List of prototypes that this alarmable can be - /// alarmed by - must be a prototype with AtmosMonitor - /// attached to it + /// List of prototypes that this alarmable can + /// sync with - this is so that you can sync without + /// having to worry about cross-contamination. /// - [DataField("alarmedBy")] - public List AlarmedByPrototypes { get; } = new(); + [DataField("syncWith")] + public List SyncWithPrototypes { get; } = new(); + + /// + /// If this device should receive only. If it can only + /// receive, that means that attempting to sync outwards + /// will result in nothing happening. + /// + [DataField("receiveOnly")] + public bool ReceiveOnly { get; } } } diff --git a/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs b/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs index c91412e1ee..5d8cd915e4 100644 --- a/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs +++ b/Content.Server/Atmos/Monitor/Components/AtmosMonitorComponent.cs @@ -22,11 +22,6 @@ namespace Content.Server.Atmos.Monitor.Components [ViewVariables] public bool NetEnabled = true; - // Entities that the monitor will alarm. Stores only EntityUids, is populated - // when this component starts up. - [ViewVariables] - public List LinkedEntities = new(); - [DataField("temperatureThreshold", customTypeSerializer: (typeof(PrototypeIdSerializer)))] public readonly string? TemperatureThresholdId; @@ -64,34 +59,10 @@ namespace Content.Server.Atmos.Monitor.Components [ViewVariables] public AtmosMonitorAlarmType LastAlarmState = AtmosMonitorAlarmType.Normal; - // feeling real dirty about this one - // Caches the alarm states it recieves from the rest of the network. - // This is so that the highest alarm in the network can be calculated - // from any monitor without having to reping every alarm. - [ViewVariables] - public Dictionary NetworkAlarmStates = new(); - /// /// Registered devices in this atmos monitor. Alerts will be sent directly /// to these devices. /// [ViewVariables] public HashSet RegisteredDevices = new(); - - // Calculates the highest alarm in the network, including itself. - [ViewVariables] - public AtmosMonitorAlarmType HighestAlarmInNetwork - { - get - { - var state = AtmosMonitorAlarmType.Normal; - foreach (var (_, netState) in NetworkAlarmStates) - if (state < netState) - state = netState; - - if (LastAlarmState > state) state = LastAlarmState; - - return state; - } - } } } diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs index 56ca5f134f..2a0b449cdd 100644 --- a/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs @@ -15,6 +15,7 @@ namespace Content.Server.Atmos.Monitor.Systems { [Dependency] private readonly AppearanceSystem _appearance = default!; [Dependency] private readonly AudioSystem _audioSystem = default!; + [Dependency] private readonly DeviceNetworkSystem _deviceNet = default!; /// /// Syncs alerts from this alarm receiver to other alarm receivers. @@ -23,6 +24,8 @@ namespace Content.Server.Atmos.Monitor.Systems /// public const string SyncAlerts = "atmos_alarmable_sync_alerts"; + public const string ResetAll = "atmos_alarmable_reset_all"; + public override void Initialize() { SubscribeLocalEvent(OnPacketRecv); @@ -77,6 +80,9 @@ namespace Content.Server.Atmos.Monitor.Systems RaiseLocalEvent(component.Owner, new AtmosMonitorAlarmEvent(state, netMax.Value), true); } break; + case ResetAll: + Reset(uid, component); + break; case SyncAlerts: // Synchronize alerts, but only if they're already known by this monitor. // This should help eliminate the chain effect, especially with @@ -105,6 +111,22 @@ namespace Content.Server.Atmos.Monitor.Systems } } + public void SyncAlertsToNetwork(EntityUid uid, string? address = null, AtmosAlarmableComponent? alarmable = null) + { + if (!Resolve(uid, ref alarmable) || alarmable.ReceiveOnly) + { + return; + } + + var payload = new NetworkPayload + { + [DeviceNetworkConstants.Command] = SyncAlerts, + [SyncAlerts] = alarmable.NetworkAlarmStates + }; + + _deviceNet.QueuePacket(uid, address, payload); + } + /// /// Resets the state of this alarmable to normal. /// @@ -120,9 +142,28 @@ namespace Content.Server.Atmos.Monitor.Systems alarmable.LastAlarmState = AtmosMonitorAlarmType.Normal; alarmable.NetworkAlarmStates.Clear(); + SyncAlertsToNetwork(uid); RaiseLocalEvent(uid, new AtmosMonitorAlarmEvent(AtmosMonitorAlarmType.Normal, AtmosMonitorAlarmType.Normal)); } + public void ResetAllOnNetwork(EntityUid uid, AtmosAlarmableComponent? alarmable = null) + { + if (!Resolve(uid, ref alarmable)) + { + return; + } + + alarmable.LastAlarmState = AtmosMonitorAlarmType.Normal; + alarmable.NetworkAlarmStates.Clear(); + + var payload = new NetworkPayload + { + [DeviceNetworkConstants.Command] = ResetAll + }; + + _deviceNet.QueuePacket(uid, null, payload); + } + /// /// Tries to get the highest possible alert stored in this alarm. /// diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs index 2205547663..9949f326db 100644 --- a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs @@ -300,9 +300,6 @@ namespace Content.Server.Atmos.Monitor.Systems BroadcastAlertPacket(monitor, alarms); - 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 } @@ -320,38 +317,6 @@ namespace Content.Server.Atmos.Monitor.Systems /// public void ResetAll(EntityUid uid, AtmosMonitorComponent? monitor = null) { - if (!Resolve(uid, ref monitor)) return; - - var prototype = Prototype(monitor.Owner); - var payload = new NetworkPayload - { - [DeviceNetworkConstants.Command] = AtmosMonitorAlarmResetAllCmd, - [AtmosMonitorAlarmSrc] = prototype != null ? prototype.ID : string.Empty - }; - - _deviceNetSystem.QueuePacket(monitor.Owner, null, payload); - monitor.NetworkAlarmStates.Clear(); - - Alert(uid, AtmosMonitorAlarmType.Normal, null, monitor); - } - - // (TODO: maybe just cache monitors in other monitors?) - /// - /// Syncs the current state of this monitor to the network (to avoid alerting other monitors). - /// - private void Sync(AtmosMonitorComponent monitor) - { - if (!monitor.NetEnabled) return; - - var prototype = Prototype(monitor.Owner); - var payload = new NetworkPayload - { - [DeviceNetworkConstants.Command] = AtmosMonitorAlarmSyncCmd, - [DeviceNetworkConstants.CmdSetState] = monitor.LastAlarmState, - [AtmosMonitorAlarmSrc] = prototype != null ? prototype.ID : string.Empty - }; - - _deviceNetSystem.QueuePacket(monitor.Owner, null, payload); } ///