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 _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 cache = new(); Dictionary 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 Networks { get; set; } = new(); } public class Network { public long ReferenceId { get; set; } public List Probes { get; set; } = new(); public List 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 LogicValues { get; set; } = new(); public List> Slots { get; set; }= new(); public bool IsCircuitHolder { get; set; } } } }