Files
tbd-station-14/Content.Server/DeviceNetwork/DeviceNetwork.cs
metalgearsloth 864fa0a57c Minor device network changes (#2499)
* Device network changes

* Update too

* Update Content.Server/GameObjects/EntitySystems/DeviceNetworkSystem.cs

Co-authored-by: Metal Gear Sloth <metalgearsloth@gmail.com>
Co-authored-by: Víctor Aguilera Puerto <6766154+Zumorica@users.noreply.github.com>
2020-11-05 18:04:21 +01:00

198 lines
6.4 KiB
C#

using System;
using Content.Server.Interfaces;
using Robust.Shared.Interfaces.Random;
using Robust.Shared.IoC;
using System.Collections.Generic;
namespace Content.Server.GameObjects.EntitySystems.DeviceNetwork
{
public delegate void OnReceiveNetMessage(int frequency, string sender, IReadOnlyDictionary<string, string> payload, Metadata metadata, bool broadcast);
public class DeviceNetwork : IDeviceNetwork
{
private const int PACKAGES_PER_TICK = 30;
[Dependency] private readonly IRobustRandom _random = default!;
private readonly Dictionary<int, List<NetworkDevice>> _devices = new Dictionary<int, List<NetworkDevice>>();
private readonly Queue<NetworkPackage> _packages = new Queue<NetworkPackage>();
/// <inheritdoc/>
public DeviceNetworkConnection Register(int netId, int frequency, OnReceiveNetMessage messageHandler, bool receiveAll = false)
{
var address = GenerateValidAddress(netId, frequency);
var device = new NetworkDevice
{
Address = address,
Frequency = frequency,
ReceiveAll = receiveAll,
ReceiveNetMessage = messageHandler
};
AddDevice(netId, device);
return new DeviceNetworkConnection(this, netId, address, frequency);
}
public DeviceNetworkConnection Register(int netId, OnReceiveNetMessage messageHandler, bool receiveAll = false)
{
return Register(netId, 0, messageHandler, receiveAll);
}
public void Update()
{
var count = Math.Min(PACKAGES_PER_TICK, _packages.Count);
for (var i = 0; i < count; i++)
{
var package = _packages.Dequeue();
if (package.Broadcast)
{
BroadcastPackage(package);
continue;
}
SendPackage(package);
}
}
public bool EnqueuePackage(int netId, int frequency, string address, IReadOnlyDictionary<string, string> data, string sender, Metadata metadata, bool broadcast = false)
{
if (!_devices.ContainsKey(netId))
return false;
var package = new NetworkPackage()
{
NetId = netId,
Frequency = frequency,
Address = address,
Broadcast = broadcast,
Data = data,
Sender = sender,
Metadata = metadata
};
_packages.Enqueue(package);
return true;
}
public void RemoveDevice(int netId, int frequency, string address)
{
var device = DeviceWithAddress(netId, frequency, address);
_devices[netId].Remove(device);
}
public void SetDeviceReceiveAll(int netId, int frequency, string address, bool receiveAll)
{
var device = DeviceWithAddress(netId, frequency, address);
device.ReceiveAll = receiveAll;
}
public bool GetDeviceReceiveAll(int netId, int frequency, string address)
{
var device = DeviceWithAddress(netId, frequency, address);
return device.ReceiveAll;
}
private string GenerateValidAddress(int netId, int frequency)
{
var unique = false;
var devices = DevicesForFrequency(netId, frequency);
var address = "";
while (!unique)
{
address = _random.Next().ToString("x");
unique = !devices.Exists(device => device.Address == address);
}
return address;
}
private void AddDevice(int netId, NetworkDevice networkDevice)
{
if(!_devices.ContainsKey(netId))
_devices[netId] = new List<NetworkDevice>();
_devices[netId].Add(networkDevice);
}
private List<NetworkDevice> DevicesForFrequency(int netId, int frequency)
{
if (!_devices.ContainsKey(netId))
return new List<NetworkDevice>();
var result = _devices[netId].FindAll(device => device.Frequency == frequency);
return result;
}
private NetworkDevice DeviceWithAddress(int netId, int frequency, string address)
{
var devices = DevicesForFrequency(netId, frequency);
var device = devices.Find(dvc => dvc.Address == address);
return device;
}
private List<NetworkDevice> DevicesWithReceiveAll(int netId, int frequency)
{
if (!_devices.ContainsKey(netId))
return new List<NetworkDevice>();
var result = _devices[netId].FindAll(device => device.Frequency == frequency && device.ReceiveAll);
return result;
}
private void BroadcastPackage(NetworkPackage package)
{
var devices = DevicesForFrequency(package.NetId, package.Frequency);
SendToDevices(devices, package, true);
}
private void SendPackage(NetworkPackage package)
{
var devices = DevicesWithReceiveAll(package.NetId, package.Frequency);
var device = DeviceWithAddress(package.NetId, package.Frequency, package.Address);
devices.Add(device);
SendToDevices(devices, package, false);
}
private void SendToDevices(List<NetworkDevice> devices, NetworkPackage package, bool broadcast)
{
for (var index = 0; index < devices.Count; index++)
{
var device = devices[index];
if (device.Address == package.Sender)
continue;
device.ReceiveNetMessage(package.Frequency, package.Sender, package.Data, package.Metadata, broadcast);
}
}
internal class NetworkDevice
{
public int Frequency;
public string Address;
public OnReceiveNetMessage ReceiveNetMessage;
public bool ReceiveAll;
}
internal class NetworkPackage
{
public int NetId;
public int Frequency;
public string Address;
public bool Broadcast;
public IReadOnlyDictionary<string, string> Data { get; set; }
public Metadata Metadata;
public string Sender;
}
}
}