139 lines
4.8 KiB
C#
139 lines
4.8 KiB
C#
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Assets.Scripts;
|
|
using Assets.Scripts.Objects.Electrical;
|
|
using Assets.Scripts.Objects.Motherboards;
|
|
using EmbedIO.WebSockets;
|
|
using RemoteControl.Message;
|
|
using Swan;
|
|
using Swan.Diagnostics;
|
|
using GameDevice = Assets.Scripts.Objects.Pipes.Device;
|
|
|
|
namespace RemoteControl
|
|
{
|
|
internal class SubscriptionModule: WebSocketModule
|
|
{
|
|
private HashSet<IWebSocketContext> _jsonSubscribers = new();
|
|
public void SendUpdate(Message.Update update)
|
|
{
|
|
if (_jsonSubscribers.Count > 0)
|
|
{
|
|
var encoded = System.Text.Encoding.UTF8.GetBytes(update.ToJson());
|
|
foreach (var webSocketContext in _jsonSubscribers)
|
|
{
|
|
_ = SendAsync(webSocketContext, encoded);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public SubscriptionModule(string urlPath, bool enableConnectionWatchdog = true) : base(urlPath, enableConnectionWatchdog)
|
|
{
|
|
}
|
|
|
|
protected override Task OnMessageReceivedAsync(IWebSocketContext context, byte[] buffer, IWebSocketReceiveResult result)
|
|
{
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
protected override Task OnClientConnectedAsync(IWebSocketContext context)
|
|
{
|
|
_jsonSubscribers.Add(context);
|
|
return base.OnClientConnectedAsync(context);
|
|
}
|
|
|
|
protected override Task OnClientDisconnectedAsync(IWebSocketContext context)
|
|
{
|
|
_jsonSubscribers.Remove(context);
|
|
return base.OnClientDisconnectedAsync(context);
|
|
}
|
|
|
|
internal static Update GetUpdate()
|
|
{
|
|
Dictionary<long, Device> cache = new();
|
|
Dictionary<long, Message.Network> networks = new();
|
|
|
|
|
|
// lock (SubscriptionManager.Lock)
|
|
var timer = new HighResolutionTimer();
|
|
timer.Start();
|
|
GameDevice.AllDevices.ForEach(dev =>
|
|
{
|
|
if (dev is CableAnalyser analyser)
|
|
{
|
|
var network = networks.GetOrAdd(analyser.CableNetwork.ReferenceId, (long _) => new Message.Network
|
|
{
|
|
ReferenceId = analyser.CableNetwork.ReferenceId,
|
|
Devices = analyser.CableNetwork.DeviceList
|
|
.Select(subdev => cache.GetOrAdd(subdev.ReferenceId, _ => new Device(subdev)))
|
|
.ToList()
|
|
});
|
|
network.Probes.Add(analyser.DisplayName);
|
|
}
|
|
});
|
|
|
|
Update update = new()
|
|
{
|
|
Networks = networks.Values.ToList(),
|
|
CalculationTime = timer.ElapsedMicroseconds,
|
|
};
|
|
|
|
|
|
return update;
|
|
}
|
|
|
|
internal void SendUpdate()
|
|
{
|
|
SendUpdate(GetUpdate());
|
|
}
|
|
}
|
|
|
|
namespace Message
|
|
{
|
|
public class Update
|
|
{
|
|
public long CalculationTime { get; set; }
|
|
public List<Network> Networks { get; set; } = new();
|
|
}
|
|
|
|
public class Network
|
|
{
|
|
public long ReferenceId { get; set; }
|
|
public List<string> Probes { get; set; } = new();
|
|
|
|
public List<Device> Devices { get; set; } = new();
|
|
}
|
|
|
|
public class Device
|
|
{
|
|
public Device() {}
|
|
|
|
public Device(GameDevice device)
|
|
{
|
|
ReferenceId = device.ReferenceId;
|
|
Name = device.DisplayName;
|
|
NameHash = device.GetNameHash();
|
|
PrefabHash = device.PrefabHash;
|
|
PrefabName = device.PrefabName;
|
|
LogicValues = EnumCollections.LogicTypes.Values.Where(device.CanLogicRead)
|
|
.ToDictionary(ty => ty, device.GetLogicValue);
|
|
Slots = Enumerable.Range(0, device.TotalSlots)
|
|
.Select(slot => EnumCollections.LogicSlotTypes.Values.Where(sty => device.CanLogicRead(sty, slot))
|
|
.ToDictionary(ty => ty, sty => device.GetLogicValue(sty, slot)))
|
|
.ToList();
|
|
IsCircuitHolder = device is ICircuitHolder;
|
|
}
|
|
|
|
public long ReferenceId { get; set; }
|
|
public long NameHash{ get; set; }
|
|
public string Name{ get; set; }
|
|
public long PrefabHash{ get; set; }
|
|
public string PrefabName{ get; set; }
|
|
public Dictionary<LogicType, double> LogicValues { get; set; } = new();
|
|
public List<Dictionary<LogicSlotType, double>> Slots { get; set; }= new();
|
|
public bool IsCircuitHolder { get; set; }
|
|
}
|
|
}
|
|
} |