Cleaning device net system (#8153)
This commit is contained in:
@@ -3,6 +3,8 @@ using Content.Shared.DeviceNetwork;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Buffers;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
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 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();
|
||||
|
||||
public override void Initialize()
|
||||
@@ -28,16 +30,17 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
|
||||
SubscribeLocalEvent<DeviceNetworkComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<DeviceNetworkComponent, ComponentShutdown>(OnNetworkShutdown);
|
||||
|
||||
InitNetwork(ConnectionType.Private);
|
||||
InitNetwork(ConnectionType.Wired);
|
||||
InitNetwork(ConnectionType.Wireless);
|
||||
InitNetwork(ConnectionType.Apc);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
while (_packets.Count > 0)
|
||||
while (_packets.TryDequeue(out var packet))
|
||||
{
|
||||
var packet = _packets.Dequeue();
|
||||
|
||||
SendPacket(packet);
|
||||
}
|
||||
}
|
||||
@@ -64,6 +67,9 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
_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>
|
||||
/// Automatically attempt to connect some devices when a map starts.
|
||||
/// </summary>
|
||||
@@ -87,12 +93,15 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
ConnectDevice(uid, device);
|
||||
}
|
||||
|
||||
private DeviceNet GetNetwork(ConnectionType connectionType) =>
|
||||
_networks[(int) connectionType];
|
||||
|
||||
/// <summary>
|
||||
/// Automatically disconnect when an entity with a DeviceNetworkComponent shuts down.
|
||||
/// </summary>
|
||||
private void OnNetworkShutdown(EntityUid uid, DeviceNetworkComponent component, ComponentShutdown args)
|
||||
{
|
||||
DisconnectDevice(uid, component, false);
|
||||
GetNetwork(component.DeviceNetId).Remove(component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -104,13 +113,7 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
if (!Resolve(uid, ref device, false))
|
||||
return false;
|
||||
|
||||
if (!_networks.TryGetValue(device.DeviceNetId, out var network))
|
||||
{
|
||||
network = new(device.DeviceNetId, _random);
|
||||
_networks[device.DeviceNetId] = network;
|
||||
}
|
||||
|
||||
return network.Add(device);
|
||||
return GetNetwork(device.DeviceNetId).Add(device);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -125,82 +128,115 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
if (preventAutoConnect)
|
||||
device.AutoConnect = false;
|
||||
|
||||
if (!_networks.TryGetValue(device.DeviceNetId, out var network))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!network.Remove(device))
|
||||
return false;
|
||||
|
||||
if (network.Devices.Count == 0)
|
||||
_networks.Remove(device.DeviceNetId);
|
||||
|
||||
return true;
|
||||
return GetNetwork(device.DeviceNetId).Remove(device);
|
||||
}
|
||||
|
||||
#region Get Device
|
||||
/// <summary>
|
||||
/// Get a list of devices listening on a given frequency on some network.
|
||||
/// </summary>
|
||||
private HashSet<DeviceNetworkComponent> GetListeningDevices(ConnectionType netId, uint frequency)
|
||||
public void SetReceiveFrequency(EntityUid uid, uint? frequency, DeviceNetworkComponent? device = null)
|
||||
{
|
||||
if (_networks.TryGetValue(netId, out var network) && network.ListeningDevices.TryGetValue(frequency, out var devices))
|
||||
return devices;
|
||||
if (!Resolve(uid, ref device, false))
|
||||
return;
|
||||
|
||||
return new();
|
||||
if (device.ReceiveFrequency == frequency) return;
|
||||
|
||||
var deviceNet = GetNetwork(device.DeviceNetId);
|
||||
deviceNet.Remove(device);
|
||||
device.ReceiveFrequency = frequency;
|
||||
deviceNet.Add(device);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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)
|
||||
public void SetTransmitFrequency(EntityUid uid, uint? frequency, DeviceNetworkComponent? device = null)
|
||||
{
|
||||
if (_networks.TryGetValue(netId, out var network) && network.ReceiveAllDevices.TryGetValue(frequency, out var devices))
|
||||
return devices;
|
||||
if (Resolve(uid, ref device, false))
|
||||
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>
|
||||
/// Try to find a device on a network using its address.
|
||||
/// </summary>
|
||||
private bool TryGetDevice(ConnectionType netId, string address, [NotNullWhen(true)] out DeviceNetworkComponent? device)
|
||||
{
|
||||
if (!_networks.TryGetValue(netId, out var network))
|
||||
{
|
||||
device = null;
|
||||
return false;
|
||||
}
|
||||
private bool TryGetDevice(ConnectionType netId, string address, [NotNullWhen(true)] out DeviceNetworkComponent? device) =>
|
||||
GetNetwork(netId).Devices.TryGetValue(address, out device);
|
||||
|
||||
return network.Devices.TryGetValue(address, out device);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Packet Sending
|
||||
private void SendPacket(DeviceNetworkPacketEvent packet)
|
||||
{
|
||||
HashSet<DeviceNetworkComponent> recipients;
|
||||
|
||||
var network = GetNetwork(packet.NetId);
|
||||
if (packet.Address == null)
|
||||
{
|
||||
// Broadcast to all listening devices
|
||||
recipients = GetListeningDevices(packet.NetId, packet.Frequency);
|
||||
if (network.ListeningDevices.TryGetValue(packet.Frequency, out var devices))
|
||||
{
|
||||
var deviceCopy = ArrayPool<DeviceNetworkComponent>.Shared.Rent(devices.Count);
|
||||
devices.CopyTo(deviceCopy);
|
||||
SendToConnections(deviceCopy.AsSpan(0, devices.Count), packet);
|
||||
ArrayPool<DeviceNetworkComponent>.Shared.Return(deviceCopy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add devices listening to all messages
|
||||
recipients = new(GetRecieveAllDevices(packet.NetId, packet.Frequency));
|
||||
|
||||
// add the intended recipient (if they are even listening).
|
||||
if (TryGetDevice(packet.NetId, packet.Address, out var device) && device.ReceiveFrequency == packet.Frequency)
|
||||
recipients.Add(device);
|
||||
var totalDevices = 0;
|
||||
var hasTargetedDevice = false;
|
||||
if (network.ReceiveAllDevices.TryGetValue(packet.Frequency, out var devices))
|
||||
{
|
||||
totalDevices += devices.Count;
|
||||
}
|
||||
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);
|
||||
|
||||
@@ -219,70 +255,6 @@ namespace Content.Server.DeviceNetwork.Systems
|
||||
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>
|
||||
|
||||
Reference in New Issue
Block a user