sync alarms, reset all, etc

This commit is contained in:
vulppine
2022-08-22 04:21:20 -07:00
parent 14669f1521
commit 550ea771a7
4 changed files with 56 additions and 74 deletions

View File

@@ -28,13 +28,10 @@ namespace Content.Server.Atmos.Monitor.Components
public sealed class AtmosAlarmableComponent : Component public sealed class AtmosAlarmableComponent : Component
{ {
[ViewVariables] [ViewVariables]
public List<EntityUid> LinkedMonitors { get; set; } = new(); public readonly Dictionary<string, AtmosMonitorAlarmType> NetworkAlarmStates = new();
[ViewVariables]
public Dictionary<string, AtmosMonitorAlarmType> NetworkAlarmStates = new();
[ViewVariables] public AtmosMonitorAlarmType LastAlarmState = AtmosMonitorAlarmType.Normal; [ViewVariables] public AtmosMonitorAlarmType LastAlarmState = AtmosMonitorAlarmType.Normal;
[ViewVariables] public AtmosMonitorAlarmType HighestNetworkState = AtmosMonitorAlarmType.Normal;
[ViewVariables] public bool IgnoreAlarms { get; set; } = false; [ViewVariables] public bool IgnoreAlarms { get; set; } = false;
[DataField("alarmSound")] [DataField("alarmSound")]
@@ -44,11 +41,19 @@ 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 be /// List of prototypes that this alarmable can
/// alarmed by - must be a prototype with AtmosMonitor /// sync with - this is so that you can sync without
/// attached to it /// having to worry about cross-contamination.
/// </summary> /// </summary>
[DataField("alarmedBy")] [DataField("syncWith")]
public List<string> AlarmedByPrototypes { get; } = new(); public List<string> SyncWithPrototypes { get; } = new();
/// <summary>
/// If this device should receive only. If it can only
/// receive, that means that attempting to sync outwards
/// will result in nothing happening.
/// </summary>
[DataField("receiveOnly")]
public bool ReceiveOnly { get; }
} }
} }

View File

@@ -22,11 +22,6 @@ namespace Content.Server.Atmos.Monitor.Components
[ViewVariables] [ViewVariables]
public bool NetEnabled = true; public bool NetEnabled = true;
// Entities that the monitor will alarm. Stores only EntityUids, is populated
// when this component starts up.
[ViewVariables]
public List<EntityUid> LinkedEntities = new();
[DataField("temperatureThreshold", customTypeSerializer: (typeof(PrototypeIdSerializer<AtmosAlarmThreshold>)))] [DataField("temperatureThreshold", customTypeSerializer: (typeof(PrototypeIdSerializer<AtmosAlarmThreshold>)))]
public readonly string? TemperatureThresholdId; public readonly string? TemperatureThresholdId;
@@ -64,34 +59,10 @@ namespace Content.Server.Atmos.Monitor.Components
[ViewVariables] [ViewVariables]
public AtmosMonitorAlarmType LastAlarmState = AtmosMonitorAlarmType.Normal; 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<string, AtmosMonitorAlarmType> NetworkAlarmStates = new();
/// <summary> /// <summary>
/// Registered devices in this atmos monitor. Alerts will be sent directly /// Registered devices in this atmos monitor. Alerts will be sent directly
/// to these devices. /// to these devices.
/// </summary> /// </summary>
[ViewVariables] public HashSet<string> RegisteredDevices = new(); [ViewVariables] public HashSet<string> 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;
}
}
} }
} }

View File

@@ -15,6 +15,7 @@ namespace Content.Server.Atmos.Monitor.Systems
{ {
[Dependency] private readonly AppearanceSystem _appearance = default!; [Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly AudioSystem _audioSystem = default!; [Dependency] private readonly AudioSystem _audioSystem = default!;
[Dependency] private readonly DeviceNetworkSystem _deviceNet = default!;
/// <summary> /// <summary>
/// Syncs alerts from this alarm receiver to other alarm receivers. /// Syncs alerts from this alarm receiver to other alarm receivers.
@@ -23,6 +24,8 @@ namespace Content.Server.Atmos.Monitor.Systems
/// </summary> /// </summary>
public const string SyncAlerts = "atmos_alarmable_sync_alerts"; public const string SyncAlerts = "atmos_alarmable_sync_alerts";
public const string ResetAll = "atmos_alarmable_reset_all";
public override void Initialize() public override void Initialize()
{ {
SubscribeLocalEvent<AtmosAlarmableComponent, DeviceNetworkPacketEvent>(OnPacketRecv); SubscribeLocalEvent<AtmosAlarmableComponent, DeviceNetworkPacketEvent>(OnPacketRecv);
@@ -77,6 +80,9 @@ namespace Content.Server.Atmos.Monitor.Systems
RaiseLocalEvent(component.Owner, new AtmosMonitorAlarmEvent(state, netMax.Value), true); RaiseLocalEvent(component.Owner, new AtmosMonitorAlarmEvent(state, netMax.Value), true);
} }
break; break;
case ResetAll:
Reset(uid, component);
break;
case SyncAlerts: case SyncAlerts:
// Synchronize alerts, but only if they're already known by this monitor. // Synchronize alerts, but only if they're already known by this monitor.
// This should help eliminate the chain effect, especially with // 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);
}
/// <summary> /// <summary>
/// Resets the state of this alarmable to normal. /// Resets the state of this alarmable to normal.
/// </summary> /// </summary>
@@ -120,9 +142,28 @@ namespace Content.Server.Atmos.Monitor.Systems
alarmable.LastAlarmState = AtmosMonitorAlarmType.Normal; alarmable.LastAlarmState = AtmosMonitorAlarmType.Normal;
alarmable.NetworkAlarmStates.Clear(); alarmable.NetworkAlarmStates.Clear();
SyncAlertsToNetwork(uid);
RaiseLocalEvent(uid, new AtmosMonitorAlarmEvent(AtmosMonitorAlarmType.Normal, AtmosMonitorAlarmType.Normal)); 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);
}
/// <summary> /// <summary>
/// Tries to get the highest possible alert stored in this alarm. /// Tries to get the highest possible alert stored in this alarm.
/// </summary> /// </summary>

View File

@@ -300,9 +300,6 @@ namespace Content.Server.Atmos.Monitor.Systems
BroadcastAlertPacket(monitor, alarms); 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 // TODO: Central system that grabs *all* alarms from wired network
} }
@@ -320,38 +317,6 @@ namespace Content.Server.Atmos.Monitor.Systems
/// </remarks> /// </remarks>
public void ResetAll(EntityUid uid, AtmosMonitorComponent? monitor = null) 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?)
/// <summary>
/// Syncs the current state of this monitor to the network (to avoid alerting other monitors).
/// </summary>
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);
} }
/// <summary> /// <summary>