force alert on alarmable, enforces synchronization with alarmables to be bounded by the tags that it can sync with
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
using Content.Shared.Atmos.Monitor;
|
using Content.Shared.Atmos.Monitor;
|
||||||
|
using Content.Shared.Tag;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
|
||||||
|
|
||||||
namespace Content.Server.Atmos.Monitor.Components
|
namespace Content.Server.Atmos.Monitor.Components
|
||||||
{
|
{
|
||||||
@@ -41,12 +43,10 @@ namespace Content.Server.Atmos.Monitor.Components
|
|||||||
public float AlarmVolume { get; set; } = -10;
|
public float AlarmVolume { get; set; } = -10;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of prototypes that this alarmable can
|
/// List of tags to check for when synchronizing alarms.
|
||||||
/// sync with - this is so that you can sync without
|
|
||||||
/// having to worry about cross-contamination.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("syncWith")]
|
[DataField("syncWith", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<TagPrototype>))]
|
||||||
public List<string> SyncWithPrototypes { get; } = new();
|
public HashSet<string> SyncWithTags { get; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If this device should receive only. If it can only
|
/// If this device should receive only. If it can only
|
||||||
|
|||||||
@@ -17,6 +17,15 @@ namespace Content.Server.Atmos.Monitor.Systems
|
|||||||
[Dependency] private readonly AudioSystem _audioSystem = default!;
|
[Dependency] private readonly AudioSystem _audioSystem = default!;
|
||||||
[Dependency] private readonly DeviceNetworkSystem _deviceNet = default!;
|
[Dependency] private readonly DeviceNetworkSystem _deviceNet = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An alarm. Has three valid states: Normal, Warning, Danger.
|
||||||
|
/// Will attempt to fetch the tags from the alarming entity
|
||||||
|
/// to send over.
|
||||||
|
/// </summary>
|
||||||
|
public const string AlertCmd = "atmos_alarm";
|
||||||
|
|
||||||
|
public const string AlertSource = "atmos_alarm_source";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Syncs alerts from this alarm receiver to other alarm receivers.
|
/// Syncs alerts from this alarm receiver to other alarm receivers.
|
||||||
/// Creates a network effect as a result. Note: if the alert receiver
|
/// Creates a network effect as a result. Note: if the alert receiver
|
||||||
@@ -47,18 +56,37 @@ namespace Content.Server.Atmos.Monitor.Systems
|
|||||||
if (!EntityManager.TryGetComponent(uid, out DeviceNetworkComponent? netConn))
|
if (!EntityManager.TryGetComponent(uid, out DeviceNetworkComponent? netConn))
|
||||||
return;
|
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<string>? sourceTags))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isValid = false;
|
||||||
|
foreach (var source in sourceTags)
|
||||||
|
{
|
||||||
|
if (component.SyncWithTags.Contains(source))
|
||||||
|
{
|
||||||
|
isValid = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValid)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case AtmosMonitorSystem.AtmosMonitorAlarmCmd:
|
case AlertCmd:
|
||||||
// Set the alert state, and then cache it so we can calculate
|
// Set the alert state, and then cache it so we can calculate
|
||||||
// the maximum alarm state at all times.
|
// 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))
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!component.NetworkAlarmStates.ContainsKey(args.SenderAddress))
|
if (!component.NetworkAlarmStates.ContainsKey(args.SenderAddress))
|
||||||
{
|
{
|
||||||
component.NetworkAlarmStates.Add(args.SenderAddress, state);
|
component.NetworkAlarmStates.Add(args.SenderAddress, state);
|
||||||
@@ -78,7 +106,7 @@ namespace Content.Server.Atmos.Monitor.Systems
|
|||||||
UpdateAppearance(uid, netMax.Value);
|
UpdateAppearance(uid, netMax.Value);
|
||||||
PlayAlertSound(uid, netMax.Value, component);
|
PlayAlertSound(uid, netMax.Value, component);
|
||||||
RaiseLocalEvent(component.Owner, new AtmosMonitorAlarmEvent(state, netMax.Value), true);
|
RaiseLocalEvent(component.Owner, new AtmosMonitorAlarmEvent(state, netMax.Value), true);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ResetAll:
|
case ResetAll:
|
||||||
Reset(uid, component);
|
Reset(uid, component);
|
||||||
@@ -121,12 +149,48 @@ namespace Content.Server.Atmos.Monitor.Systems
|
|||||||
var payload = new NetworkPayload
|
var payload = new NetworkPayload
|
||||||
{
|
{
|
||||||
[DeviceNetworkConstants.Command] = SyncAlerts,
|
[DeviceNetworkConstants.Command] = SyncAlerts,
|
||||||
[SyncAlerts] = alarmable.NetworkAlarmStates
|
[SyncAlerts] = alarmable.NetworkAlarmStates,
|
||||||
|
[AlertSource] = alarmable.SyncWithTags
|
||||||
};
|
};
|
||||||
|
|
||||||
_deviceNet.QueuePacket(uid, address, payload);
|
_deviceNet.QueuePacket(uid, address, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid"></param>
|
||||||
|
/// <param name="alarmType"></param>
|
||||||
|
/// <param name="alarmable"></param>
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resets the state of this alarmable to normal.
|
/// Resets the state of this alarmable to normal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -158,7 +222,8 @@ namespace Content.Server.Atmos.Monitor.Systems
|
|||||||
|
|
||||||
var payload = new NetworkPayload
|
var payload = new NetworkPayload
|
||||||
{
|
{
|
||||||
[DeviceNetworkConstants.Command] = ResetAll
|
[DeviceNetworkConstants.Command] = ResetAll,
|
||||||
|
[AlertSource] = alarmable.SyncWithTags
|
||||||
};
|
};
|
||||||
|
|
||||||
_deviceNet.QueuePacket(uid, null, payload);
|
_deviceNet.QueuePacket(uid, null, payload);
|
||||||
@@ -171,7 +236,7 @@ namespace Content.Server.Atmos.Monitor.Systems
|
|||||||
/// <param name="alarm"></param>
|
/// <param name="alarm"></param>
|
||||||
/// <param name="alarmable"></param>
|
/// <param name="alarmable"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private bool TryGetHighestAlert(EntityUid uid, [NotNullWhen(true)] out AtmosMonitorAlarmType? alarm,
|
public bool TryGetHighestAlert(EntityUid uid, [NotNullWhen(true)] out AtmosMonitorAlarmType? alarm,
|
||||||
AtmosAlarmableComponent? alarmable = null)
|
AtmosAlarmableComponent? alarmable = null)
|
||||||
{
|
{
|
||||||
alarm = null;
|
alarm = null;
|
||||||
|
|||||||
@@ -10,11 +10,6 @@ namespace Content.Server.Atmos.Monitor.Systems;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class AtmosDeviceNetworkSystem : EntitySystem
|
public sealed class AtmosDeviceNetworkSystem : EntitySystem
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Any information about atmosphere that a device can scan.
|
|
||||||
/// </summary>
|
|
||||||
public const string AtmosData = "atmos_atmosphere_data";
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register a device's address on this device.
|
/// Register a device's address on this device.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -25,11 +20,6 @@ public sealed class AtmosDeviceNetworkSystem : EntitySystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const string SyncData = "atmos_sync_data";
|
public const string SyncData = "atmos_sync_data";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set the state of this device using the contained data.
|
|
||||||
/// </summary>
|
|
||||||
public const string SetState = "atmos_set_state";
|
|
||||||
|
|
||||||
[Dependency] private readonly DeviceNetworkSystem _deviceNet = default!;
|
[Dependency] private readonly DeviceNetworkSystem _deviceNet = default!;
|
||||||
|
|
||||||
public void Register(EntityUid uid, string? address)
|
public void Register(EntityUid uid, string? address)
|
||||||
@@ -56,8 +46,8 @@ public sealed class AtmosDeviceNetworkSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
var payload = new NetworkPayload()
|
var payload = new NetworkPayload()
|
||||||
{
|
{
|
||||||
[DeviceNetworkConstants.Command] = SetState,
|
[DeviceNetworkConstants.Command] = DeviceNetworkConstants.CmdSetState,
|
||||||
[SetState] = data
|
[DeviceNetworkConstants.CmdSetState] = data
|
||||||
};
|
};
|
||||||
|
|
||||||
_deviceNet.QueuePacket(uid, address, payload);
|
_deviceNet.QueuePacket(uid, address, payload);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Content.Server.Power.Components;
|
|||||||
using Content.Server.Power.EntitySystems;
|
using Content.Server.Power.EntitySystems;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Atmos.Monitor;
|
using Content.Shared.Atmos.Monitor;
|
||||||
|
using Content.Shared.Tag;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Player;
|
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,
|
/// is synced between monitors the moment a monitor sends out an alarm,
|
||||||
/// or if it is explicitly synced (see ResetAll/Sync).
|
/// or if it is explicitly synced (see ResetAll/Sync).
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
private void BroadcastAlertPacket(AtmosMonitorComponent monitor, IEnumerable<AtmosMonitorThresholdType>? alarms = null)
|
private void BroadcastAlertPacket(AtmosMonitorComponent monitor, IEnumerable<AtmosMonitorThresholdType>? alarms = null, TagComponent? tags = null)
|
||||||
{
|
{
|
||||||
if (!monitor.NetEnabled) return;
|
if (!monitor.NetEnabled) return;
|
||||||
|
|
||||||
|
if (!Resolve(monitor.Owner, ref tags))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
string source = string.Empty;
|
string source = string.Empty;
|
||||||
if (alarms == null) alarms = new List<AtmosMonitorThresholdType>();
|
if (alarms == null) alarms = new List<AtmosMonitorThresholdType>();
|
||||||
var prototype = Prototype(monitor.Owner);
|
var prototype = Prototype(monitor.Owner);
|
||||||
@@ -343,9 +350,9 @@ namespace Content.Server.Atmos.Monitor.Systems
|
|||||||
|
|
||||||
var payload = new NetworkPayload
|
var payload = new NetworkPayload
|
||||||
{
|
{
|
||||||
[DeviceNetworkConstants.Command] = AtmosMonitorAlarmCmd,
|
[DeviceNetworkConstants.Command] = AtmosAlarmableSystem.AlertCmd,
|
||||||
[DeviceNetworkConstants.CmdSetState] = monitor.LastAlarmState,
|
[DeviceNetworkConstants.CmdSetState] = monitor.LastAlarmState,
|
||||||
[AtmosMonitorAlarmSrc] = source
|
[AtmosAlarmableSystem.AlertSource] = tags.Tags
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var addr in monitor.RegisteredDevices)
|
foreach (var addr in monitor.RegisteredDevices)
|
||||||
|
|||||||
Reference in New Issue
Block a user