diff --git a/Content.Server/Atmos/Monitor/Components/AtmosAlarmableComponent.cs b/Content.Server/Atmos/Monitor/Components/AtmosAlarmableComponent.cs
index 23a903ff9c..23f25ad4de 100644
--- a/Content.Server/Atmos/Monitor/Components/AtmosAlarmableComponent.cs
+++ b/Content.Server/Atmos/Monitor/Components/AtmosAlarmableComponent.cs
@@ -1,5 +1,7 @@
using Content.Shared.Atmos.Monitor;
+using Content.Shared.Tag;
using Robust.Shared.Audio;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
namespace Content.Server.Atmos.Monitor.Components
{
@@ -41,12 +43,10 @@ namespace Content.Server.Atmos.Monitor.Components
public float AlarmVolume { get; set; } = -10;
///
- /// List of prototypes that this alarmable can
- /// sync with - this is so that you can sync without
- /// having to worry about cross-contamination.
+ /// List of tags to check for when synchronizing alarms.
///
- [DataField("syncWith")]
- public List SyncWithPrototypes { get; } = new();
+ [DataField("syncWith", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))]
+ public HashSet SyncWithTags { get; } = new();
///
/// If this device should receive only. If it can only
diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs
index 2a0b449cdd..db8db150a8 100644
--- a/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs
+++ b/Content.Server/Atmos/Monitor/Systems/AtmosAlarmableSystem.cs
@@ -17,6 +17,15 @@ namespace Content.Server.Atmos.Monitor.Systems
[Dependency] private readonly AudioSystem _audioSystem = default!;
[Dependency] private readonly DeviceNetworkSystem _deviceNet = default!;
+ ///
+ /// An alarm. Has three valid states: Normal, Warning, Danger.
+ /// Will attempt to fetch the tags from the alarming entity
+ /// to send over.
+ ///
+ public const string AlertCmd = "atmos_alarm";
+
+ public const string AlertSource = "atmos_alarm_source";
+
///
/// Syncs alerts from this alarm receiver to other alarm receivers.
/// Creates a network effect as a result. Note: if the alert receiver
@@ -47,38 +56,57 @@ namespace Content.Server.Atmos.Monitor.Systems
if (!EntityManager.TryGetComponent(uid, out DeviceNetworkComponent? netConn))
return;
- if (args.Data.TryGetValue(DeviceNetworkConstants.Command, out string? cmd))
+ if (!args.Data.TryGetValue(DeviceNetworkConstants.Command, out string? cmd)
+ || !args.Data.TryGetValue(AlertSource, out List? sourceTags))
+ {
+ return;
+ }
+
+ var isValid = false;
+ foreach (var source in sourceTags)
+ {
+ if (component.SyncWithTags.Contains(source))
+ {
+ isValid = true;
+ break;
+ }
+ }
+
+ if (!isValid)
{
return;
}
switch (cmd)
{
- case AtmosMonitorSystem.AtmosMonitorAlarmCmd:
+ case AlertCmd:
// Set the alert state, and then cache it so we can calculate
// the maximum alarm state at all times.
- if (args.Data.TryGetValue(DeviceNetworkConstants.CmdSetState, out AtmosMonitorAlarmType state))
+ if (!args.Data.TryGetValue(DeviceNetworkConstants.CmdSetState, out AtmosMonitorAlarmType state))
{
- if (!component.NetworkAlarmStates.ContainsKey(args.SenderAddress))
- {
- component.NetworkAlarmStates.Add(args.SenderAddress, state);
- }
- else
- {
- component.NetworkAlarmStates[args.SenderAddress] = state;
- }
-
- if (!TryGetHighestAlert(uid, out var netMax, component))
- {
- netMax = AtmosMonitorAlarmType.Normal;
- }
-
- component.LastAlarmState = netMax.Value;
-
- UpdateAppearance(uid, netMax.Value);
- PlayAlertSound(uid, netMax.Value, component);
- RaiseLocalEvent(component.Owner, new AtmosMonitorAlarmEvent(state, netMax.Value), true);
+ return;
}
+
+ if (!component.NetworkAlarmStates.ContainsKey(args.SenderAddress))
+ {
+ component.NetworkAlarmStates.Add(args.SenderAddress, state);
+ }
+ else
+ {
+ component.NetworkAlarmStates[args.SenderAddress] = state;
+ }
+
+ if (!TryGetHighestAlert(uid, out var netMax, component))
+ {
+ netMax = AtmosMonitorAlarmType.Normal;
+ }
+
+ component.LastAlarmState = netMax.Value;
+
+ UpdateAppearance(uid, netMax.Value);
+ PlayAlertSound(uid, netMax.Value, component);
+ RaiseLocalEvent(component.Owner, new AtmosMonitorAlarmEvent(state, netMax.Value), true);
+
break;
case ResetAll:
Reset(uid, component);
@@ -121,12 +149,48 @@ namespace Content.Server.Atmos.Monitor.Systems
var payload = new NetworkPayload
{
[DeviceNetworkConstants.Command] = SyncAlerts,
- [SyncAlerts] = alarmable.NetworkAlarmStates
+ [SyncAlerts] = alarmable.NetworkAlarmStates,
+ [AlertSource] = alarmable.SyncWithTags
};
_deviceNet.QueuePacket(uid, address, payload);
}
+ ///
+ /// Forces this alarmable to have a specific alert. This will not be reset until the alarmable
+ /// is manually reset. This will store the alarmable as a device in its network states, and sync
+ /// it to the rest of the network.
+ ///
+ ///
+ ///
+ ///
+ public void ForceAlert(EntityUid uid, AtmosMonitorAlarmType alarmType,
+ AtmosAlarmableComponent? alarmable = null, DeviceNetworkComponent? devNet = null)
+ {
+ if (!Resolve(uid, ref alarmable, ref devNet))
+ {
+ return;
+ }
+
+ alarmable.LastAlarmState = alarmType;
+
+ if (!alarmable.NetworkAlarmStates.TryAdd(devNet.Address, alarmType))
+ {
+ alarmable.NetworkAlarmStates[devNet.Address] = alarmType;
+ }
+
+ var payload = new NetworkPayload
+ {
+ [DeviceNetworkConstants.Command] = AlertCmd,
+ [DeviceNetworkConstants.CmdSetState] = alarmType,
+ [AlertSource] = alarmable.SyncWithTags
+ };
+
+ _deviceNet.QueuePacket(uid, null, payload);
+
+ RaiseLocalEvent(uid, new AtmosMonitorAlarmEvent(alarmType, alarmType));
+ }
+
///
/// Resets the state of this alarmable to normal.
///
@@ -158,7 +222,8 @@ namespace Content.Server.Atmos.Monitor.Systems
var payload = new NetworkPayload
{
- [DeviceNetworkConstants.Command] = ResetAll
+ [DeviceNetworkConstants.Command] = ResetAll,
+ [AlertSource] = alarmable.SyncWithTags
};
_deviceNet.QueuePacket(uid, null, payload);
@@ -171,7 +236,7 @@ namespace Content.Server.Atmos.Monitor.Systems
///
///
///
- private bool TryGetHighestAlert(EntityUid uid, [NotNullWhen(true)] out AtmosMonitorAlarmType? alarm,
+ public bool TryGetHighestAlert(EntityUid uid, [NotNullWhen(true)] out AtmosMonitorAlarmType? alarm,
AtmosAlarmableComponent? alarmable = null)
{
alarm = null;
diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosDeviceNetwork.cs b/Content.Server/Atmos/Monitor/Systems/AtmosDeviceNetwork.cs
index 0262aee0cd..3190cbd37f 100644
--- a/Content.Server/Atmos/Monitor/Systems/AtmosDeviceNetwork.cs
+++ b/Content.Server/Atmos/Monitor/Systems/AtmosDeviceNetwork.cs
@@ -10,11 +10,6 @@ namespace Content.Server.Atmos.Monitor.Systems;
///
public sealed class AtmosDeviceNetworkSystem : EntitySystem
{
- ///
- /// Any information about atmosphere that a device can scan.
- ///
- public const string AtmosData = "atmos_atmosphere_data";
-
///
/// Register a device's address on this device.
///
@@ -25,11 +20,6 @@ public sealed class AtmosDeviceNetworkSystem : EntitySystem
///
public const string SyncData = "atmos_sync_data";
- ///
- /// Set the state of this device using the contained data.
- ///
- public const string SetState = "atmos_set_state";
-
[Dependency] private readonly DeviceNetworkSystem _deviceNet = default!;
public void Register(EntityUid uid, string? address)
@@ -56,8 +46,8 @@ public sealed class AtmosDeviceNetworkSystem : EntitySystem
{
var payload = new NetworkPayload()
{
- [DeviceNetworkConstants.Command] = SetState,
- [SetState] = data
+ [DeviceNetworkConstants.Command] = DeviceNetworkConstants.CmdSetState,
+ [DeviceNetworkConstants.CmdSetState] = data
};
_deviceNet.QueuePacket(uid, address, payload);
diff --git a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs
index 9949f326db..4e7f94de59 100644
--- a/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs
+++ b/Content.Server/Atmos/Monitor/Systems/AtmosMonitoringSystem.cs
@@ -9,6 +9,7 @@ using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.Atmos;
using Content.Shared.Atmos.Monitor;
+using Content.Shared.Tag;
using Robust.Server.GameObjects;
using Robust.Shared.Audio;
using Robust.Shared.Player;
@@ -332,10 +333,16 @@ namespace Content.Server.Atmos.Monitor.Systems
/// is synced between monitors the moment a monitor sends out an alarm,
/// or if it is explicitly synced (see ResetAll/Sync).
///
- private void BroadcastAlertPacket(AtmosMonitorComponent monitor, IEnumerable? alarms = null)
+ private void BroadcastAlertPacket(AtmosMonitorComponent monitor, IEnumerable? alarms = null, TagComponent? tags = null)
{
if (!monitor.NetEnabled) return;
+ if (!Resolve(monitor.Owner, ref tags))
+ {
+ return;
+ }
+
+
string source = string.Empty;
if (alarms == null) alarms = new List();
var prototype = Prototype(monitor.Owner);
@@ -343,9 +350,9 @@ namespace Content.Server.Atmos.Monitor.Systems
var payload = new NetworkPayload
{
- [DeviceNetworkConstants.Command] = AtmosMonitorAlarmCmd,
+ [DeviceNetworkConstants.Command] = AtmosAlarmableSystem.AlertCmd,
[DeviceNetworkConstants.CmdSetState] = monitor.LastAlarmState,
- [AtmosMonitorAlarmSrc] = source
+ [AtmosAlarmableSystem.AlertSource] = tags.Tags
};
foreach (var addr in monitor.RegisteredDevices)