Cleaning device net system (#8153)
This commit is contained in:
@@ -3,6 +3,8 @@ using Content.Shared.DeviceNetwork;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
using System.Buffers;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using static Content.Server.DeviceNetwork.Components.DeviceNetworkComponent;
|
using static Content.Server.DeviceNetwork.Components.DeviceNetworkComponent;
|
||||||
|
|
||||||
@@ -19,7 +21,7 @@ namespace Content.Server.DeviceNetwork.Systems
|
|||||||
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
||||||
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
||||||
|
|
||||||
private readonly Dictionary<ConnectionType, DeviceNet> _networks = new();
|
private readonly DeviceNet[] _networks = new DeviceNet[4]; // Number of ConnectionType enum values
|
||||||
private readonly Queue<DeviceNetworkPacketEvent> _packets = new();
|
private readonly Queue<DeviceNetworkPacketEvent> _packets = new();
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -28,16 +30,17 @@ namespace Content.Server.DeviceNetwork.Systems
|
|||||||
|
|
||||||
SubscribeLocalEvent<DeviceNetworkComponent, MapInitEvent>(OnMapInit);
|
SubscribeLocalEvent<DeviceNetworkComponent, MapInitEvent>(OnMapInit);
|
||||||
SubscribeLocalEvent<DeviceNetworkComponent, ComponentShutdown>(OnNetworkShutdown);
|
SubscribeLocalEvent<DeviceNetworkComponent, ComponentShutdown>(OnNetworkShutdown);
|
||||||
|
|
||||||
|
InitNetwork(ConnectionType.Private);
|
||||||
|
InitNetwork(ConnectionType.Wired);
|
||||||
|
InitNetwork(ConnectionType.Wireless);
|
||||||
|
InitNetwork(ConnectionType.Apc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
base.Update(frameTime);
|
while (_packets.TryDequeue(out var packet))
|
||||||
|
|
||||||
while (_packets.Count > 0)
|
|
||||||
{
|
{
|
||||||
var packet = _packets.Dequeue();
|
|
||||||
|
|
||||||
SendPacket(packet);
|
SendPacket(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,6 +67,9 @@ namespace Content.Server.DeviceNetwork.Systems
|
|||||||
_packets.Enqueue(new DeviceNetworkPacketEvent(device.DeviceNetId, address, frequency.Value, device.Address, uid, data));
|
_packets.Enqueue(new DeviceNetworkPacketEvent(device.DeviceNetId, address, frequency.Value, device.Address, uid, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitNetwork(ConnectionType connectionType) =>
|
||||||
|
_networks[(int) connectionType] = new(connectionType, _random);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Automatically attempt to connect some devices when a map starts.
|
/// Automatically attempt to connect some devices when a map starts.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -87,12 +93,15 @@ namespace Content.Server.DeviceNetwork.Systems
|
|||||||
ConnectDevice(uid, device);
|
ConnectDevice(uid, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DeviceNet GetNetwork(ConnectionType connectionType) =>
|
||||||
|
_networks[(int) connectionType];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Automatically disconnect when an entity with a DeviceNetworkComponent shuts down.
|
/// Automatically disconnect when an entity with a DeviceNetworkComponent shuts down.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnNetworkShutdown(EntityUid uid, DeviceNetworkComponent component, ComponentShutdown args)
|
private void OnNetworkShutdown(EntityUid uid, DeviceNetworkComponent component, ComponentShutdown args)
|
||||||
{
|
{
|
||||||
DisconnectDevice(uid, component, false);
|
GetNetwork(component.DeviceNetId).Remove(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -104,13 +113,7 @@ namespace Content.Server.DeviceNetwork.Systems
|
|||||||
if (!Resolve(uid, ref device, false))
|
if (!Resolve(uid, ref device, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!_networks.TryGetValue(device.DeviceNetId, out var network))
|
return GetNetwork(device.DeviceNetId).Add(device);
|
||||||
{
|
|
||||||
network = new(device.DeviceNetId, _random);
|
|
||||||
_networks[device.DeviceNetId] = network;
|
|
||||||
}
|
|
||||||
|
|
||||||
return network.Add(device);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -125,82 +128,115 @@ namespace Content.Server.DeviceNetwork.Systems
|
|||||||
if (preventAutoConnect)
|
if (preventAutoConnect)
|
||||||
device.AutoConnect = false;
|
device.AutoConnect = false;
|
||||||
|
|
||||||
if (!_networks.TryGetValue(device.DeviceNetId, out var network))
|
return GetNetwork(device.DeviceNetId).Remove(device);
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!network.Remove(device))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (network.Devices.Count == 0)
|
|
||||||
_networks.Remove(device.DeviceNetId);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Get Device
|
public void SetReceiveFrequency(EntityUid uid, uint? frequency, DeviceNetworkComponent? device = null)
|
||||||
/// <summary>
|
|
||||||
/// Get a list of devices listening on a given frequency on some network.
|
|
||||||
/// </summary>
|
|
||||||
private HashSet<DeviceNetworkComponent> GetListeningDevices(ConnectionType netId, uint frequency)
|
|
||||||
{
|
{
|
||||||
if (_networks.TryGetValue(netId, out var network) && network.ListeningDevices.TryGetValue(frequency, out var devices))
|
if (!Resolve(uid, ref device, false))
|
||||||
return devices;
|
return;
|
||||||
|
|
||||||
return new();
|
if (device.ReceiveFrequency == frequency) return;
|
||||||
|
|
||||||
|
var deviceNet = GetNetwork(device.DeviceNetId);
|
||||||
|
deviceNet.Remove(device);
|
||||||
|
device.ReceiveFrequency = frequency;
|
||||||
|
deviceNet.Add(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void SetTransmitFrequency(EntityUid uid, uint? frequency, DeviceNetworkComponent? device = null)
|
||||||
/// Get a list of devices listening for ANY transmission on a given frequency, rather than just broadcast & addressed events.
|
|
||||||
/// </summary>
|
|
||||||
private HashSet<DeviceNetworkComponent> GetRecieveAllDevices(ConnectionType netId, uint frequency)
|
|
||||||
{
|
{
|
||||||
if (_networks.TryGetValue(netId, out var network) && network.ReceiveAllDevices.TryGetValue(frequency, out var devices))
|
if (Resolve(uid, ref device, false))
|
||||||
return devices;
|
device.TransmitFrequency = frequency;
|
||||||
|
}
|
||||||
|
|
||||||
return new();
|
public void SetReceiveAll(EntityUid uid, bool receiveAll, DeviceNetworkComponent? device = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref device, false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (device.ReceiveAll == receiveAll) return;
|
||||||
|
|
||||||
|
var deviceNet = GetNetwork(device.DeviceNetId);
|
||||||
|
deviceNet.Remove(device);
|
||||||
|
device.ReceiveAll = receiveAll;
|
||||||
|
deviceNet.Add(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAddress(EntityUid uid, string address, DeviceNetworkComponent? device = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref device, false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (device.Address == address && device.CustomAddress == true) return;
|
||||||
|
|
||||||
|
var deviceNet = GetNetwork(device.DeviceNetId);
|
||||||
|
deviceNet.Remove(device);
|
||||||
|
device.CustomAddress = true;
|
||||||
|
device.Address = address;
|
||||||
|
deviceNet.Add(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RandomizeAddress(EntityUid uid, DeviceNetworkComponent? device = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref device, false))
|
||||||
|
return;
|
||||||
|
var deviceNet = GetNetwork(device.DeviceNetId);
|
||||||
|
deviceNet.Remove(device);
|
||||||
|
device.CustomAddress = false;
|
||||||
|
device.Address = "";
|
||||||
|
deviceNet.Add(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Try to find a device on a network using its address.
|
/// Try to find a device on a network using its address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool TryGetDevice(ConnectionType netId, string address, [NotNullWhen(true)] out DeviceNetworkComponent? device)
|
private bool TryGetDevice(ConnectionType netId, string address, [NotNullWhen(true)] out DeviceNetworkComponent? device) =>
|
||||||
{
|
GetNetwork(netId).Devices.TryGetValue(address, out device);
|
||||||
if (!_networks.TryGetValue(netId, out var network))
|
|
||||||
{
|
|
||||||
device = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return network.Devices.TryGetValue(address, out device);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Packet Sending
|
|
||||||
private void SendPacket(DeviceNetworkPacketEvent packet)
|
private void SendPacket(DeviceNetworkPacketEvent packet)
|
||||||
{
|
{
|
||||||
HashSet<DeviceNetworkComponent> recipients;
|
var network = GetNetwork(packet.NetId);
|
||||||
|
|
||||||
if (packet.Address == null)
|
if (packet.Address == null)
|
||||||
{
|
{
|
||||||
// Broadcast to all listening devices
|
if (network.ListeningDevices.TryGetValue(packet.Frequency, out var devices))
|
||||||
recipients = GetListeningDevices(packet.NetId, packet.Frequency);
|
{
|
||||||
|
var deviceCopy = ArrayPool<DeviceNetworkComponent>.Shared.Rent(devices.Count);
|
||||||
|
devices.CopyTo(deviceCopy);
|
||||||
|
SendToConnections(deviceCopy.AsSpan(0, devices.Count), packet);
|
||||||
|
ArrayPool<DeviceNetworkComponent>.Shared.Return(deviceCopy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Add devices listening to all messages
|
var totalDevices = 0;
|
||||||
recipients = new(GetRecieveAllDevices(packet.NetId, packet.Frequency));
|
var hasTargetedDevice = false;
|
||||||
|
if (network.ReceiveAllDevices.TryGetValue(packet.Frequency, out var devices))
|
||||||
// add the intended recipient (if they are even listening).
|
{
|
||||||
if (TryGetDevice(packet.NetId, packet.Address, out var device) && device.ReceiveFrequency == packet.Frequency)
|
totalDevices += devices.Count;
|
||||||
recipients.Add(device);
|
}
|
||||||
|
if (TryGetDevice(packet.NetId, packet.Address, out var device) &&
|
||||||
|
!device.ReceiveAll &&
|
||||||
|
device.ReceiveFrequency == packet.Frequency)
|
||||||
|
{
|
||||||
|
totalDevices += 1;
|
||||||
|
hasTargetedDevice = true;
|
||||||
|
}
|
||||||
|
var deviceCopy = ArrayPool<DeviceNetworkComponent>.Shared.Rent(totalDevices);
|
||||||
|
if (devices != null)
|
||||||
|
{
|
||||||
|
devices.CopyTo(deviceCopy);
|
||||||
|
}
|
||||||
|
if (hasTargetedDevice)
|
||||||
|
{
|
||||||
|
deviceCopy[totalDevices - 1] = device!;
|
||||||
|
}
|
||||||
|
SendToConnections(deviceCopy.AsSpan(0, totalDevices), packet);
|
||||||
|
ArrayPool<DeviceNetworkComponent>.Shared.Return(deviceCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendToConnections(recipients, packet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendToConnections(HashSet<DeviceNetworkComponent> connections, DeviceNetworkPacketEvent packet)
|
private void SendToConnections(ReadOnlySpan<DeviceNetworkComponent> connections, DeviceNetworkPacketEvent packet)
|
||||||
{
|
{
|
||||||
var xform = Transform(packet.Sender);
|
var xform = Transform(packet.Sender);
|
||||||
|
|
||||||
@@ -219,70 +255,6 @@ namespace Content.Server.DeviceNetwork.Systems
|
|||||||
beforeEv.Uncancel();
|
beforeEv.Uncancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Component Setter Functions
|
|
||||||
public void SetReceiveFrequency(EntityUid uid, uint? frequency, DeviceNetworkComponent? device = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref device, false))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (device.ReceiveFrequency == frequency)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!_networks.TryGetValue(device.DeviceNetId, out var deviceNet) || !deviceNet.UpdateReceiveFrequency(device.Address, frequency))
|
|
||||||
device.ReceiveFrequency = frequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetTransmitFrequency(EntityUid uid, uint? frequency, DeviceNetworkComponent? device = null)
|
|
||||||
{
|
|
||||||
if (Resolve(uid, ref device, false))
|
|
||||||
device.TransmitFrequency = frequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetReceiveAll(EntityUid uid, bool receiveAll, DeviceNetworkComponent? device = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref device, false))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (device.ReceiveAll == receiveAll)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!_networks.TryGetValue(device.DeviceNetId, out var deviceNet) || !deviceNet.UpdateReceiveAll(device.Address, receiveAll))
|
|
||||||
device.ReceiveAll = receiveAll;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetAddress(EntityUid uid, string address, DeviceNetworkComponent? device = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref device, false))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (device.Address == address)
|
|
||||||
{
|
|
||||||
device.CustomAddress = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_networks.TryGetValue(device.DeviceNetId, out var deviceNet) || !deviceNet.UpdateAddress(device.Address, address))
|
|
||||||
{
|
|
||||||
device.Address = address;
|
|
||||||
device.CustomAddress = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RandomizeAddress(EntityUid uid, string address, DeviceNetworkComponent? device = null)
|
|
||||||
{
|
|
||||||
if (!Resolve(uid, ref device, false))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!_networks.TryGetValue(device.DeviceNetId, out var deviceNet) || !deviceNet.RandomizeAddress(device.Address, address))
|
|
||||||
{
|
|
||||||
var prefix = string.IsNullOrWhiteSpace(device.Prefix) ? null : Loc.GetString(device.Prefix);
|
|
||||||
device.Address = $"{prefix}{_random.Next():x}";
|
|
||||||
device.CustomAddress = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user