Add a crew monitoring server (#7542)
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server.DeviceNetwork.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class StationLimitedNetworkComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The station id the device is limited to.
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public EntityUid? StationId;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the entity is allowed to receive packets from entities that are not tied to any station
|
||||
/// </summary>
|
||||
[DataField("allowNonStationPackets")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public bool AllowNonStationPackets = false;
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,7 @@ public sealed class DeviceNet
|
||||
/// </summary>
|
||||
public bool Remove(DeviceNetworkComponent device)
|
||||
{
|
||||
if (device.Address == null || Devices.Remove(device.Address))
|
||||
if (device.Address == null || !Devices.Remove(device.Address))
|
||||
return false;
|
||||
|
||||
if (device.ReceiveFrequency is not uint freq)
|
||||
|
||||
@@ -48,18 +48,22 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
/// <param name="address">The address of the entity that the packet gets sent to. If null, the message is broadcast to all devices on that frequency (except the sender)</param>
|
||||
/// <param name="frequency">The frequency to send on</param>
|
||||
/// <param name="data">The data to be sent</param>
|
||||
public void QueuePacket(EntityUid uid, string? address, NetworkPayload data, uint? frequency = null, DeviceNetworkComponent? device = null)
|
||||
/// <returns>Returns true when the packet was successfully enqueued.</returns>
|
||||
public bool QueuePacket(EntityUid uid, string? address, NetworkPayload data, uint? frequency = null, DeviceNetworkComponent? device = null)
|
||||
{
|
||||
if (!Resolve(uid, ref device, false))
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (device.Address == string.Empty)
|
||||
return;
|
||||
return false;
|
||||
|
||||
frequency ??= device.TransmitFrequency;
|
||||
|
||||
if (frequency != null)
|
||||
_packets.Enqueue(new DeviceNetworkPacketEvent(device.DeviceNetId, address, frequency.Value, device.Address, uid, data));
|
||||
if (frequency == null)
|
||||
return false;
|
||||
|
||||
_packets.Enqueue(new DeviceNetworkPacketEvent(device.DeviceNetId, address, frequency.Value, device.Address, uid, data));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnExamine(EntityUid uid, DeviceNetworkComponent device, ExaminedEvent args)
|
||||
@@ -137,6 +141,32 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
return GetNetwork(device.DeviceNetId).Remove(device);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a device is already connected to its network
|
||||
/// </summary>
|
||||
/// <returns>True if the device was found in the network with its corresponding network id</returns>
|
||||
public bool IsDeviceConnected(EntityUid uid, DeviceNetworkComponent? device)
|
||||
{
|
||||
if (!Resolve(uid, ref device, false))
|
||||
return false;
|
||||
|
||||
if (!_networks.TryGetValue(device.DeviceNetId, out var deviceNet))
|
||||
return false;
|
||||
|
||||
return deviceNet.Devices.ContainsValue(device);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if an address exists in the network with the given netId
|
||||
/// </summary>
|
||||
public bool IsAddressPresent(int netId, string? address)
|
||||
{
|
||||
if (address == null || !_networks.TryGetValue(netId, out var network))
|
||||
return false;
|
||||
|
||||
return network.Devices.ContainsKey(address);
|
||||
}
|
||||
|
||||
public void SetReceiveFrequency(EntityUid uid, uint? frequency, DeviceNetworkComponent? device = null)
|
||||
{
|
||||
if (!Resolve(uid, ref device, false))
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
using Content.Server.DeviceNetwork.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server.DeviceNetwork.Systems
|
||||
{
|
||||
/// <summary>
|
||||
/// This system requires the StationLimitedNetworkComponent to be on the the sending entity as well as the receiving entity
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public sealed class StationLimitedNetworkSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly StationSystem _stationSystem = default!;
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<StationLimitedNetworkComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<StationLimitedNetworkComponent, BeforePacketSentEvent>(OnBeforePacketSent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the station id the device is limited to.
|
||||
/// </summary>
|
||||
public void SetStation(EntityUid uid, EntityUid? stationId, StationLimitedNetworkComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
component.StationId = stationId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the station id to the one the entity is on when the station limited component is added
|
||||
/// </summary>
|
||||
private void OnMapInit(EntityUid uid, StationLimitedNetworkComponent networkComponent, MapInitEvent args)
|
||||
{
|
||||
networkComponent.StationId = _stationSystem.GetOwningStation(uid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if both devices are limited to the same station
|
||||
/// </summary>
|
||||
private void OnBeforePacketSent(EntityUid uid, StationLimitedNetworkComponent component, BeforePacketSentEvent args)
|
||||
{
|
||||
if (!CheckStationId(args.Sender, component.AllowNonStationPackets, component.StationId))
|
||||
{
|
||||
args.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares the station IDs of the sending and receiving network components.
|
||||
/// Returns false if either of them doesn't have a station ID or if their station ID isn't equal.
|
||||
/// Returns true even when the sending entity isn't tied to a station if `allowNonStationPackets` is set to true.
|
||||
/// </summary>
|
||||
private bool CheckStationId(EntityUid senderUid, bool allowNonStationPackets, EntityUid? receiverStationId, StationLimitedNetworkComponent? sender = null)
|
||||
{
|
||||
if (!receiverStationId.HasValue)
|
||||
return false;
|
||||
|
||||
if (!Resolve(senderUid, ref sender, false))
|
||||
return allowNonStationPackets;
|
||||
|
||||
return sender.StationId == receiverStationId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
using System.Linq;
|
||||
using Content.Server.DeviceNetwork;
|
||||
using Content.Server.DeviceNetwork.Systems;
|
||||
using Content.Server.Medical.SuitSensors;
|
||||
using Content.Server.UserInterface;
|
||||
using Content.Shared.Medical.CrewMonitoring;
|
||||
using Robust.Shared.Map;
|
||||
using Content.Shared.Medical.SuitSensor;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Medical.CrewMonitoring
|
||||
@@ -13,33 +15,14 @@ namespace Content.Server.Medical.CrewMonitoring
|
||||
[Dependency] private readonly SuitSensorSystem _sensors = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _xform = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
|
||||
private const float UpdateRate = 3f;
|
||||
private float _updateDif;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<CrewMonitoringConsoleComponent, ComponentRemove>(OnRemove);
|
||||
SubscribeLocalEvent<CrewMonitoringConsoleComponent, DeviceNetworkPacketEvent>(OnPacketReceived);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
// check update rate
|
||||
_updateDif += frameTime;
|
||||
if (_updateDif < UpdateRate)
|
||||
return;
|
||||
_updateDif = 0f;
|
||||
|
||||
var consoles = EntityManager.EntityQuery<CrewMonitoringConsoleComponent>();
|
||||
foreach (var console in consoles)
|
||||
{
|
||||
UpdateTimeouts(console.Owner, console);
|
||||
UpdateUserInterface(console.Owner, console);
|
||||
}
|
||||
SubscribeLocalEvent<CrewMonitoringConsoleComponent, BoundUIOpenedEvent>(OnUIOpened);
|
||||
}
|
||||
|
||||
private void OnRemove(EntityUid uid, CrewMonitoringConsoleComponent component, ComponentRemove args)
|
||||
@@ -49,12 +32,22 @@ namespace Content.Server.Medical.CrewMonitoring
|
||||
|
||||
private void OnPacketReceived(EntityUid uid, CrewMonitoringConsoleComponent component, DeviceNetworkPacketEvent args)
|
||||
{
|
||||
var suitSensor = _sensors.PacketToSuitSensor(args.Data);
|
||||
if (suitSensor == null)
|
||||
var payload = args.Data;
|
||||
// check command
|
||||
if (!payload.TryGetValue(DeviceNetworkConstants.Command, out string? command))
|
||||
return;
|
||||
if (command != DeviceNetworkConstants.CmdUpdatedState)
|
||||
return;
|
||||
if (!payload.TryGetValue(SuitSensorConstants.NET_STATUS_COLLECTION, out Dictionary<string, SuitSensorStatus>? sensorStatus))
|
||||
return;
|
||||
|
||||
suitSensor.Timestamp = _gameTiming.CurTime;
|
||||
component.ConnectedSensors[args.SenderAddress] = suitSensor;
|
||||
component.ConnectedSensors = sensorStatus;
|
||||
UpdateUserInterface(uid, component);
|
||||
}
|
||||
|
||||
private void OnUIOpened(EntityUid uid, CrewMonitoringConsoleComponent component, BoundUIOpenedEvent args)
|
||||
{
|
||||
UpdateUserInterface(uid, component);
|
||||
}
|
||||
|
||||
private void UpdateUserInterface(EntityUid uid, CrewMonitoringConsoleComponent? component = null)
|
||||
@@ -72,19 +65,5 @@ namespace Content.Server.Medical.CrewMonitoring
|
||||
var uiState = new CrewMonitoringState(allSensors, xform.WorldPosition, component.Snap, component.Precision);
|
||||
ui.SetState(uiState);
|
||||
}
|
||||
|
||||
private void UpdateTimeouts(EntityUid uid, CrewMonitoringConsoleComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
foreach (var (address, sensor) in component.ConnectedSensors)
|
||||
{
|
||||
// if too many time passed - sensor just dropped connection
|
||||
var dif = _gameTiming.CurTime - sensor.Timestamp;
|
||||
if (dif.Seconds > component.SensorTimeout)
|
||||
component.ConnectedSensors.Remove(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using Content.Shared.Medical.SuitSensor;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server.Medical.CrewMonitoring;
|
||||
|
||||
[RegisterComponent]
|
||||
[Access(typeof(CrewMonitoringServerSystem))]
|
||||
public sealed class CrewMonitoringServerComponent : Component
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// List of all currently connected sensors to this server.
|
||||
/// </summary>
|
||||
public readonly Dictionary<string, SuitSensorStatus> SensorStatus = new();
|
||||
|
||||
/// <summary>
|
||||
/// After what time sensor consider to be lost.
|
||||
/// </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;
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
using Content.Server.DeviceNetwork;
|
||||
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.Medical.SuitSensor;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Medical.CrewMonitoring;
|
||||
|
||||
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!;
|
||||
|
||||
private const float UpdateRate = 3f;
|
||||
private float _updateDiff;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<CrewMonitoringServerComponent, ComponentRemove>(OnRemove);
|
||||
SubscribeLocalEvent<CrewMonitoringServerComponent, DeviceNetworkPacketEvent>(OnPacketReceived);
|
||||
SubscribeLocalEvent<CrewMonitoringServerComponent, PowerChangedEvent>(OnPowerChanged);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
// check update rate
|
||||
_updateDiff += frameTime;
|
||||
if (_updateDiff < UpdateRate)
|
||||
return;
|
||||
_updateDiff -= UpdateRate;
|
||||
|
||||
var servers = EntityManager.EntityQuery<CrewMonitoringServerComponent>();
|
||||
List<EntityUid> activeServers = new();
|
||||
|
||||
foreach (var server in servers)
|
||||
{
|
||||
//Make sure the server is disconnected when it becomes unavailable
|
||||
if (!server.Available)
|
||||
{
|
||||
if (server.Active)
|
||||
DisconnectServer(server.Owner, server);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!server.Active)
|
||||
continue;
|
||||
|
||||
activeServers.Add(server.Owner);
|
||||
}
|
||||
|
||||
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 = EntityManager.EntityQuery<CrewMonitoringServerComponent, DeviceNetworkComponent>();
|
||||
(CrewMonitoringServerComponent, DeviceNetworkComponent)? last = default;
|
||||
|
||||
foreach (var (server, device) in servers)
|
||||
{
|
||||
if (!_stationSystem.GetOwningStation(server.Owner)?.Equals(stationId) ?? false)
|
||||
continue;
|
||||
|
||||
if (!server.Available)
|
||||
{
|
||||
DisconnectServer(server.Owner,server, device);
|
||||
continue;
|
||||
}
|
||||
|
||||
last = (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.Item1.Owner, last.Value.Item1, last.Value.Item2);
|
||||
address = last.Value.Item2.Address;
|
||||
return true;
|
||||
}
|
||||
|
||||
address = null;
|
||||
return address != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds or updates a sensor status entry if the received package is a sensor status update
|
||||
/// </summary>
|
||||
private void OnPacketReceived(EntityUid uid, CrewMonitoringServerComponent component, DeviceNetworkPacketEvent args)
|
||||
{
|
||||
var sensorStatus = _sensors.PacketToSuitSensor(args.Data);
|
||||
if (sensorStatus == null)
|
||||
return;
|
||||
|
||||
sensorStatus.Timestamp = _gameTiming.CurTime;
|
||||
component.SensorStatus[args.SenderAddress] = sensorStatus;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the servers sensor status list
|
||||
/// </summary>
|
||||
private void OnRemove(EntityUid uid, CrewMonitoringServerComponent component, ComponentRemove args)
|
||||
{
|
||||
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>
|
||||
private void UpdateTimeout(EntityUid uid, CrewMonitoringServerComponent? component = null)
|
||||
{
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
foreach (var (address, sensor) in component.SensorStatus)
|
||||
{
|
||||
var dif = _gameTiming.CurTime - sensor.Timestamp;
|
||||
if (dif.Seconds > component.SensorTimeout)
|
||||
component.SensorStatus.Remove(address);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Broadcasts the status of all connected sensors
|
||||
/// </summary>
|
||||
private void BroadcastSensorStatus(EntityUid uid, CrewMonitoringServerComponent? serverComponent = null, DeviceNetworkComponent? device = null)
|
||||
{
|
||||
if (!Resolve(uid, ref serverComponent, ref device))
|
||||
return;
|
||||
|
||||
var payload = new NetworkPayload()
|
||||
{
|
||||
[DeviceNetworkConstants.Command] = DeviceNetworkConstants.CmdUpdatedState,
|
||||
[SuitSensorConstants.NET_STATUS_COLLECTION] = serverComponent.SensorStatus
|
||||
};
|
||||
|
||||
_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
|
||||
/// </summary>
|
||||
private void DisconnectServer(EntityUid uid, CrewMonitoringServerComponent? server = null, DeviceNetworkComponent? device = null)
|
||||
{
|
||||
if (!Resolve(uid, ref server, ref device))
|
||||
return;
|
||||
|
||||
server.SensorStatus.Clear();
|
||||
server.Active = false;
|
||||
|
||||
_deviceNetworkSystem.DisconnectDevice(uid, device, false);
|
||||
}
|
||||
}
|
||||
@@ -56,5 +56,19 @@ namespace Content.Server.Medical.SuitSensors
|
||||
/// Last time when sensor updated owners status
|
||||
/// </summary>
|
||||
public TimeSpan LastUpdate = TimeSpan.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// The station this suit sensor belongs to. If it's null the suit didn't spawn on a station and the sensor doesn't work.
|
||||
/// </summary>
|
||||
[DataField("station")]
|
||||
public EntityUid? StationId = null;
|
||||
|
||||
/// <summary>
|
||||
/// The server the suit sensor sends it state to.
|
||||
/// The suit sensor will try connecting to a new server when no server is connected.
|
||||
/// It does this by calling the servers entity system for performance reasons.
|
||||
/// </summary>
|
||||
[DataField("server")]
|
||||
public string? ConnectedServer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ using Content.Server.Access.Systems;
|
||||
using Content.Server.DeviceNetwork;
|
||||
using Content.Server.DeviceNetwork.Components;
|
||||
using Content.Server.DeviceNetwork.Systems;
|
||||
using Content.Server.Medical.CrewMonitoring;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Inventory.Events;
|
||||
@@ -25,6 +27,8 @@ namespace Content.Server.Medical.SuitSensors
|
||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
||||
[Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly CrewMonitoringServerSystem _monitoringServerSystem = default!;
|
||||
[Dependency] private readonly StationSystem _stationSystem = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _xform = default!;
|
||||
|
||||
private const float UpdateRate = 1f;
|
||||
@@ -57,27 +61,48 @@ namespace Content.Server.Medical.SuitSensors
|
||||
var sensors = EntityManager.EntityQuery<SuitSensorComponent, DeviceNetworkComponent>();
|
||||
foreach (var (sensor, device) in sensors)
|
||||
{
|
||||
if (device.TransmitFrequency is not uint frequency)
|
||||
if (!device.TransmitFrequency.HasValue || !sensor.StationId.HasValue)
|
||||
continue;
|
||||
|
||||
// check if sensor is ready to update
|
||||
if (curTime - sensor.LastUpdate < sensor.UpdateRate)
|
||||
continue;
|
||||
sensor.LastUpdate = curTime;
|
||||
|
||||
// Add a random offset to the next update time that isn't longer than the sensors update rate
|
||||
sensor.LastUpdate = curTime.Add(TimeSpan.FromSeconds(_random.Next(0, sensor.UpdateRate.Seconds)));
|
||||
|
||||
// get sensor status
|
||||
var status = GetSensorState(sensor.Owner, sensor);
|
||||
if (status == null)
|
||||
continue;
|
||||
|
||||
// broadcast it to device network
|
||||
//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))
|
||||
continue;
|
||||
|
||||
sensor.ConnectedServer = address;
|
||||
}
|
||||
|
||||
// Send it to the connected server
|
||||
var payload = SuitSensorToPacket(status);
|
||||
_deviceNetworkSystem.QueuePacket(sensor.Owner, null, payload, device: device);
|
||||
|
||||
// Clear the connected server if its address isn't on the network
|
||||
if (!_deviceNetworkSystem.IsAddressPresent(device.DeviceNetId, sensor.ConnectedServer))
|
||||
{
|
||||
sensor.ConnectedServer = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
_deviceNetworkSystem.QueuePacket(sensor.Owner, sensor.ConnectedServer, payload, device: device);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMapInit(EntityUid uid, SuitSensorComponent component, MapInitEvent args)
|
||||
{
|
||||
component.StationId = _stationSystem.GetOwningStation(uid);
|
||||
|
||||
// generate random mode
|
||||
if (component.RandomMode)
|
||||
{
|
||||
@@ -277,7 +302,7 @@ namespace Content.Server.Medical.SuitSensors
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serialize suit sensor status into device network package.
|
||||
/// Serialize create a device network package from the suit sensors status.
|
||||
/// </summary>
|
||||
public NetworkPayload SuitSensorToPacket(SuitSensorStatus status)
|
||||
{
|
||||
@@ -299,7 +324,7 @@ namespace Content.Server.Medical.SuitSensors
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to deserialize device network message into suit sensor status
|
||||
/// Try to create the suit sensors status from the device network message
|
||||
/// </summary>
|
||||
public SuitSensorStatus? PacketToSuitSensor(NetworkPayload payload)
|
||||
{
|
||||
|
||||
@@ -51,5 +51,8 @@ namespace Content.Shared.Medical.SuitSensor
|
||||
public const string NET_IS_ALIVE = "alive";
|
||||
public const string NET_TOTAL_DAMAGE = "vitals";
|
||||
public const string NET_CORDINATES = "cords";
|
||||
|
||||
///Used by the CrewMonitoringServerSystem to send the status of all connected suit sensors to each crew monitor
|
||||
public const string NET_STATUS_COLLECTION = "suit-status-collection";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# named frequencies
|
||||
device-frequency-prototype-name-atmos = Atmospheric Devices
|
||||
device-frequency-prototype-name-suit-sensors = Suit Sensors
|
||||
device-frequency-prototype-name-crew-monitor = Crew Monitor
|
||||
device-frequency-prototype-name-lights = Smart Lights
|
||||
device-frequency-prototype-name-mailing-units = Mailing Units
|
||||
device-frequency-prototype-name-pdas = PDAs
|
||||
|
||||
@@ -53,12 +53,19 @@
|
||||
name: device-frequency-prototype-name-atmos
|
||||
frequency: 1621
|
||||
|
||||
# Only listen to this frequency if you are a health or GPS monitor. Otherwise you will just slow down the server by constantly receiving periodic broadcasts from every player-entity.
|
||||
# Only listen to this frequency if you are a crew monitor server. Otherwise you will just slow down the server by constantly receiving periodic broadcasts from every player-entity.
|
||||
- type: deviceFrequency
|
||||
id: SuitSensor
|
||||
name: device-frequency-prototype-name-suit-sensors
|
||||
frequency: 1262
|
||||
|
||||
# Crew monitors listen to this for a list of suit sensor statuses
|
||||
- type: deviceFrequency
|
||||
id: CrewMonitor
|
||||
name: device-frequency-prototype-name-crew-monitor
|
||||
frequency: 1261
|
||||
|
||||
|
||||
# This frequency will likely have a LARGE number of listening entities. Please don't broadcast on this frequency.
|
||||
- type: deviceFrequency
|
||||
id: SmartLight #used by powered lights.
|
||||
|
||||
@@ -35,7 +35,8 @@
|
||||
deviceNetId: Wireless
|
||||
transmitFrequencyId: SuitSensor
|
||||
- type: WirelessNetworkConnection
|
||||
range: 500
|
||||
range: 1200
|
||||
- type: StationLimitedNetwork
|
||||
|
||||
- type: entity
|
||||
abstract: true
|
||||
|
||||
@@ -98,9 +98,10 @@
|
||||
precision: 3
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: SuitSensor
|
||||
receiveFrequencyId: CrewMonitor
|
||||
- type: WirelessNetworkConnection
|
||||
range: 500
|
||||
- type: StationLimitedNetwork
|
||||
- type: Thieving
|
||||
stripTimeReduction: 9999
|
||||
stealthy: true
|
||||
|
||||
@@ -302,6 +302,21 @@
|
||||
Glass: 5
|
||||
Cable: 1
|
||||
|
||||
- type: entity
|
||||
id: CrewMonitoringServerMachineCircuitboard
|
||||
parent: BaseMachineCircuitboard
|
||||
name: crew monitoring server machine board
|
||||
description: A machine printed circuit board for a crew monitoring server
|
||||
components:
|
||||
- type: MachineBoard
|
||||
prototype: CrewMonitoringServer
|
||||
requirements:
|
||||
Capacitor: 1
|
||||
ScanningModule: 2
|
||||
materialRequirements:
|
||||
Steel: 1
|
||||
Cable: 2
|
||||
|
||||
- type: entity
|
||||
id: CryoPodMachineCircuitboard
|
||||
parent: BaseMachineCircuitboard
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
- type: CrewMonitoringConsole
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: SuitSensor
|
||||
receiveFrequencyId: CrewMonitor
|
||||
- type: WirelessNetworkConnection
|
||||
range: 500
|
||||
- type: StationLimitedNetwork
|
||||
- type: StaticPrice
|
||||
price: 500
|
||||
|
||||
@@ -311,9 +311,9 @@
|
||||
- type: CrewMonitoringConsole
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: SuitSensor
|
||||
receiveFrequencyId: CrewMonitor
|
||||
- type: WirelessNetworkConnection
|
||||
range: 500
|
||||
range: 1200
|
||||
|
||||
- type: entity
|
||||
parent: BaseComputer
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
- type: entity
|
||||
id: CrewMonitoringServer
|
||||
parent: BaseMachinePowered
|
||||
name: crew monitoring server
|
||||
description: Receives and relays the status of all active suit sensors on the station.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Structures/Machines/server.rsi
|
||||
layers:
|
||||
- state: server
|
||||
- state: variant-crew
|
||||
- type: Construction
|
||||
graph: Machine
|
||||
node: machine
|
||||
containers:
|
||||
- machine_board
|
||||
- machine_parts
|
||||
- type: Machine
|
||||
board: CrewMonitoringServerMachineCircuitboard
|
||||
- type: ContainerContainer
|
||||
containers:
|
||||
machine_board: !type:Container
|
||||
machine_parts: !type:Container
|
||||
- type: CrewMonitoringServer
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
transmitFrequencyId: CrewMonitor
|
||||
receiveFrequencyId: SuitSensor
|
||||
autoConnect: false
|
||||
- type: WirelessNetworkConnection
|
||||
range: 500
|
||||
- type: StationLimitedNetwork
|
||||
- type: ApcPowerReceiver
|
||||
powerLoad: 200
|
||||
priority: Low
|
||||
- type: ExtensionCableReceiver
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
!type:DamageTrigger
|
||||
damage: 300
|
||||
behaviors:
|
||||
- !type:DoActsBehavior
|
||||
acts: ["Destruction"]
|
||||
- !type:PlaySoundBehavior
|
||||
sound:
|
||||
path: /Audio/Effects/metalbreak.ogg
|
||||
- !type:SpawnEntitiesBehavior
|
||||
spawn:
|
||||
SheetSteel1:
|
||||
min: 1
|
||||
max: 2
|
||||
- type: AmbientSound
|
||||
volume: -9
|
||||
range: 5
|
||||
sound:
|
||||
path: /Audio/Ambience/Objects/server_fans.ogg
|
||||
@@ -26,6 +26,10 @@
|
||||
{
|
||||
"name": "server_o"
|
||||
|
||||
},
|
||||
{
|
||||
"name": "variant-crew"
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 167 B |
Reference in New Issue
Block a user