]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
System for single device net server per station functionality (#23946)
authorJulian Giebel <juliangiebel@live.de>
Mon, 4 Mar 2024 00:45:37 +0000 (01:45 +0100)
committerGitHub <noreply@github.com>
Mon, 4 Mar 2024 00:45:37 +0000 (20:45 -0400)
Content.Server/DeviceNetwork/Components/SingletonDeviceNetServerComponent.cs [new file with mode: 0644]
Content.Server/DeviceNetwork/Systems/SingletonDeviceNetServerSystem.cs [new file with mode: 0644]
Content.Server/Medical/CrewMonitoring/CrewMonitoringServerComponent.cs
Content.Server/Medical/CrewMonitoring/CrewMonitoringServerSystem.cs
Content.Server/Medical/SuitSensors/SuitSensorSystem.cs
Resources/Prototypes/Entities/Structures/Machines/crew_monitor_server.yml

diff --git a/Content.Server/DeviceNetwork/Components/SingletonDeviceNetServerComponent.cs b/Content.Server/DeviceNetwork/Components/SingletonDeviceNetServerComponent.cs
new file mode 100644 (file)
index 0000000..48272ff
--- /dev/null
@@ -0,0 +1,20 @@
+using Content.Server.DeviceNetwork.Systems;
+
+namespace Content.Server.DeviceNetwork.Components;
+
+[RegisterComponent]
+[Access(typeof(SingletonDeviceNetServerSystem))]
+public sealed partial class SingletonDeviceNetServerComponent : Component
+{
+    /// <summary>
+    /// Whether the server can become the currently active server. The server being unavailable usually means that it isn't powered
+    /// </summary>
+    [DataField, ViewVariables(VVAccess.ReadWrite)]
+    public bool Available = true;
+
+    /// <summary>
+    /// Whether the server is the currently active server for the station it's on
+    /// </summary>
+    [DataField, ViewVariables(VVAccess.ReadWrite)]
+    public bool Active = true;
+}
diff --git a/Content.Server/DeviceNetwork/Systems/SingletonDeviceNetServerSystem.cs b/Content.Server/DeviceNetwork/Systems/SingletonDeviceNetServerSystem.cs
new file mode 100644 (file)
index 0000000..fd62514
--- /dev/null
@@ -0,0 +1,137 @@
+using Content.Server.DeviceNetwork.Components;
+using Content.Server.Medical.CrewMonitoring;
+using Content.Server.Power.Components;
+using Content.Server.Station.Systems;
+
+namespace Content.Server.DeviceNetwork.Systems;
+
+/// <summary>
+/// Keeps one active server entity per station. Activates another available one if the currently active server becomes unavailable
+/// Server in this context means an entity that manages the devicenet packets like the <see cref="Content.Server.Medical.CrewMonitoring.CrewMonitoringServerSystem"/>
+/// </summary>
+public sealed class SingletonDeviceNetServerSystem : EntitySystem
+{
+    [Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
+    [Dependency] private readonly StationSystem _stationSystem = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+        SubscribeLocalEvent<SingletonDeviceNetServerComponent, PowerChangedEvent>(OnPowerChanged);
+    }
+
+    /// <summary>
+    /// Returns whether the given entity is an active server or not
+    /// </summary>
+    public bool IsActiveServer(EntityUid serverId, SingletonDeviceNetServerComponent? serverComponent = default)
+    {
+        return Resolve(serverId, ref serverComponent) && serverComponent.Active;
+    }
+
+    /// <summary>
+    /// Returns the address of the currently active server for the given station id if there is one.<br/>
+    /// What kind of server you're trying to get the active instance of is determined by the component type parameter TComp.<br/>
+    /// <br/>
+    /// Setting TComp to <see cref="CrewMonitoringServerComponent"/>, for example, gives you the address of an entity containing the crew monitoring server component.<br/>
+    /// </summary>
+    /// <param name="stationId">The entityUid of the station</param>
+    /// <param name="address">The address of the active server if it exists</param>
+    /// <typeparam name="TComp">The component type that determines what type of server you're getting the address of</typeparam>
+    /// <returns>True if there is an active serve. False otherwise</returns>
+    public bool TryGetActiveServerAddress<TComp>(EntityUid stationId, out string? address) where TComp : IComponent
+    {
+        var servers = EntityQueryEnumerator<
+            SingletonDeviceNetServerComponent,
+            DeviceNetworkComponent,
+            TComp
+        >();
+
+        (EntityUid id, SingletonDeviceNetServerComponent server, DeviceNetworkComponent device)? last = default;
+
+        while (servers.MoveNext(out var uid, out var server, out var device, out _))
+        {
+            if (!_stationSystem.GetOwningStation(uid)?.Equals(stationId) ?? true)
+                continue;
+
+            if (!server.Available)
+            {
+                DisconnectServer(uid,server, device);
+                continue;
+            }
+
+            last = (uid, server, device);
+
+            if (!server.Active)
+                continue;
+
+            address = device.Address;
+            return true;
+        }
+
+        //If there was no active server for the station make the last available inactive one active
+        if (last.HasValue)
+        {
+            ConnectServer(last.Value.id, last.Value.server, last.Value.device);
+            address = last.Value.device.Address;
+            return true;
+        }
+
+        address = null;
+        return address != null;
+    }
+
+    /// <summary>
+    /// Disconnects the server losing power
+    /// </summary>
+    private void OnPowerChanged(EntityUid uid, SingletonDeviceNetServerComponent component, ref PowerChangedEvent args)
+    {
+        component.Available = args.Powered;
+
+        if (!args.Powered && component.Active)
+            DisconnectServer(uid, component);
+    }
+
+    private void ConnectServer(EntityUid uid, SingletonDeviceNetServerComponent? server = null, DeviceNetworkComponent? device = null)
+    {
+        if (!Resolve(uid, ref server, ref device))
+            return;
+
+        server.Active = true;
+
+        var connectedEvent = new DeviceNetServerConnectedEvent();
+        RaiseLocalEvent(uid, ref connectedEvent);
+
+        if (_deviceNetworkSystem.IsDeviceConnected(uid, device))
+            return;
+
+        _deviceNetworkSystem.ConnectDevice(uid, device);
+    }
+
+    /// <summary>
+    /// Disconnects a server from the device network and clears the currently active server
+    /// </summary>
+    private void DisconnectServer(EntityUid uid, SingletonDeviceNetServerComponent? server = null, DeviceNetworkComponent? device = null)
+    {
+        if (!Resolve(uid, ref server, ref device))
+            return;
+
+        server.Active = false;
+
+        var disconnectedEvent = new DeviceNetServerDisconnectedEvent();
+        RaiseLocalEvent(uid, ref disconnectedEvent);
+
+        _deviceNetworkSystem.DisconnectDevice(uid, device, false);
+    }
+}
+
+/// <summary>
+/// Raised when a server gets activated and connected to the device net
+/// </summary>
+[ByRefEvent]
+public record struct DeviceNetServerConnectedEvent;
+
+/// <summary>
+/// Raised when a server gets disconnected
+/// </summary>
+[ByRefEvent]
+public record struct DeviceNetServerDisconnectedEvent;
index 0d95cc48c7e02848114a685d5c977e78d46ace30..7eeafb49c624bff1fb5c908cb929fd458a43f723 100644 (file)
@@ -18,17 +18,4 @@ public sealed partial class CrewMonitoringServerComponent : Component
     /// </summary>
     [DataField("sensorTimeout"), ViewVariables(VVAccess.ReadWrite)]
     public float SensorTimeout = 10f;
-
-    /// <summary>
-    ///     Whether the server can become the currently active server. The server being unavailable usually means that it isn't powered
-    /// </summary>
-    [ViewVariables(VVAccess.ReadWrite)]
-    public bool Available = true;
-
-
-    /// <summary>
-    ///     Whether the server is the currently active server for the station it's on
-    /// </summary>
-    [ViewVariables(VVAccess.ReadWrite)]
-    public bool Active = true;
 }
index bff7f1565a16f57068d61ffe627f2e48492c6595..864ce2c55ec825777dbe07f6d9ca1b1063d57add 100644 (file)
@@ -2,8 +2,6 @@
 using Content.Server.DeviceNetwork.Components;
 using Content.Server.DeviceNetwork.Systems;
 using Content.Server.Medical.SuitSensors;
-using Content.Server.Power.Components;
-using Content.Server.Station.Systems;
 using Content.Shared.DeviceNetwork;
 using Content.Shared.Medical.SuitSensor;
 using Robust.Shared.Timing;
@@ -15,7 +13,7 @@ public sealed class CrewMonitoringServerSystem : EntitySystem
     [Dependency] private readonly SuitSensorSystem _sensors = default!;
     [Dependency] private readonly IGameTiming _gameTiming = default!;
     [Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
-    [Dependency] private readonly StationSystem _stationSystem = default!;
+    [Dependency] private readonly SingletonDeviceNetServerSystem _singletonServerSystem = default!;
 
     private const float UpdateRate = 3f;
     private float _updateDiff;
@@ -25,7 +23,7 @@ public sealed class CrewMonitoringServerSystem : EntitySystem
         base.Initialize();
         SubscribeLocalEvent<CrewMonitoringServerComponent, ComponentRemove>(OnRemove);
         SubscribeLocalEvent<CrewMonitoringServerComponent, DeviceNetworkPacketEvent>(OnPacketReceived);
-        SubscribeLocalEvent<CrewMonitoringServerComponent, PowerChangedEvent>(OnPowerChanged);
+        SubscribeLocalEvent<CrewMonitoringServerComponent, DeviceNetServerDisconnectedEvent>(OnDisconnected);
     }
 
     public override void Update(float frameTime)
@@ -39,70 +37,15 @@ public sealed class CrewMonitoringServerSystem : EntitySystem
         _updateDiff -= UpdateRate;
 
         var servers = EntityQueryEnumerator<CrewMonitoringServerComponent>();
-        List<EntityUid> activeServers = new();
 
         while (servers.MoveNext(out var id, out var server))
         {
-            //Make sure the server is disconnected when it becomes unavailable
-            if (!server.Available)
-            {
-                if (server.Active)
-                    DisconnectServer(id, server);
-
-                continue;
-            }
-
-            if (!server.Active)
-                continue;
-
-            activeServers.Add(id);
-        }
-
-        foreach (var activeServer in activeServers)
-        {
-            UpdateTimeout(activeServer);
-            BroadcastSensorStatus(activeServer);
-        }
-    }
-
-    /// <summary>
-    /// Returns the address of the currently active server for the given station id if there is one
-    /// </summary>
-    public bool TryGetActiveServerAddress(EntityUid stationId, out string? address)
-    {
-        var servers = EntityQueryEnumerator<CrewMonitoringServerComponent, DeviceNetworkComponent>();
-        (EntityUid id, CrewMonitoringServerComponent server, DeviceNetworkComponent device)? last = default;
-
-        while (servers.MoveNext(out var uid, out var server, out var device))
-        {
-            if (!_stationSystem.GetOwningStation(uid)?.Equals(stationId) ?? true)
-                continue;
-
-            if (!server.Available)
-            {
-                DisconnectServer(uid,server, device);
+            if (!_singletonServerSystem.IsActiveServer(id))
                 continue;
-            }
-
-            last = (uid, server, device);
-
-            if (server.Active)
-            {
-                address = device.Address;
-                return true;
-            }
-        }
 
-        //If there was no active server for the station make the last available inactive one active
-        if (last.HasValue)
-        {
-            ConnectServer(last.Value.id, last.Value.server, last.Value.device);
-            address = last.Value.device.Address;
-            return true;
+            UpdateTimeout(id);
+            BroadcastSensorStatus(id, server);
         }
-
-        address = null;
-        return address != null;
     }
 
     /// <summary>
@@ -126,17 +69,6 @@ public sealed class CrewMonitoringServerSystem : EntitySystem
         component.SensorStatus.Clear();
     }
 
-    /// <summary>
-    /// Disconnects the server losing power
-    /// </summary>
-    private void OnPowerChanged(EntityUid uid, CrewMonitoringServerComponent component, ref PowerChangedEvent args)
-    {
-        component.Available = args.Powered;
-
-        if (!args.Powered)
-            DisconnectServer(uid, component);
-    }
-
     /// <summary>
     /// Drop the sensor status if it hasn't been updated for to long
     /// </summary>
@@ -170,30 +102,11 @@ public sealed class CrewMonitoringServerSystem : EntitySystem
         _deviceNetworkSystem.QueuePacket(uid, null, payload, device: device);
     }
 
-    private void ConnectServer(EntityUid uid, CrewMonitoringServerComponent? server = null, DeviceNetworkComponent? device = null)
-    {
-        if (!Resolve(uid, ref server, ref device))
-            return;
-
-        server.Active = true;
-
-        if (_deviceNetworkSystem.IsDeviceConnected(uid, device))
-            return;
-
-        _deviceNetworkSystem.ConnectDevice(uid, device);
-    }
-
     /// <summary>
-    /// Disconnects a server from the device network and clears the currently active server
+    /// Clears sensor data on disconnect
     /// </summary>
-    private void DisconnectServer(EntityUid uid, CrewMonitoringServerComponent? server = null, DeviceNetworkComponent? device = null)
+    private void OnDisconnected(EntityUid uid, CrewMonitoringServerComponent component, ref DeviceNetServerDisconnectedEvent _)
     {
-        if (!Resolve(uid, ref server, ref device))
-         return;
-
-        server.SensorStatus.Clear();
-        server.Active = false;
-
-        _deviceNetworkSystem.DisconnectDevice(uid, device, false);
+        component.SensorStatus.Clear();
     }
 }
index 94ecf5fd0e73de39940750d07c50dd0ce2cafc52..b807b63e21f6687cf2a4ab0f006e1bb3bde9f8ff 100644 (file)
@@ -34,6 +34,7 @@ public sealed class SuitSensorSystem : EntitySystem
     [Dependency] private readonly PopupSystem _popupSystem = default!;
     [Dependency] private readonly SharedTransformSystem _transform = default!;
     [Dependency] private readonly StationSystem _stationSystem = default!;
+    [Dependency] private readonly SingletonDeviceNetServerSystem _singletonServerSystem = default!;
 
     public override void Initialize()
     {
@@ -80,7 +81,7 @@ public sealed class SuitSensorSystem : EntitySystem
             //Retrieve active server address if the sensor isn't connected to a server
             if (sensor.ConnectedServer == null)
             {
-                if (!_monitoringServerSystem.TryGetActiveServerAddress(sensor.StationId!.Value, out var address))
+                if (!_singletonServerSystem.TryGetActiveServerAddress<CrewMonitoringServerComponent>(sensor.StationId!.Value, out var address))
                     continue;
 
                 sensor.ConnectedServer = address;
index 30e42d59ab505505a2ef56ef12b493cffb2ae692..b069d28a33b2c5848c7ed8dbb79cd5a287d7b7dc 100644 (file)
@@ -22,6 +22,8 @@
         machine_board: !type:Container
         machine_parts: !type:Container
     - type: CrewMonitoringServer
+    - type: SingletonDeviceNetServer
+      ServerType: CrewMonitoringServer
     - type: DeviceNetwork
       deviceNetId: Wireless
       transmitFrequencyId: CrewMonitor