diff --git a/Patches/Tick.cs b/Patches/Tick.cs
index 09b827b..f3c8cba 100644
--- a/Patches/Tick.cs
+++ b/Patches/Tick.cs
@@ -17,60 +17,21 @@ namespace RemoteControl.Patches
// ReSharper disable once InconsistentNaming
public class LogicStack_LogicStackTick
{
- private struct State
- {
- internal object LockObj;
- internal bool Taken;
- }
+
[UsedImplicitly]
- private static void Prefix(out State __state)
+ private static void Prefix()
{
- __state = new State
- {
- LockObj = SubscriptionManager.Lock,
- Taken = false
- };
- // System.Threading.Monitor.Enter(__state.LockObj, ref __state.Taken);
try
{
- RemoteControl.Log("logic stack tick: start prefix");
RemoteControl.Subscribers.SendUpdate();
- RemoteControl.Log("logic stack tick: end prefix");
}
catch (Exception e)
{
RemoteControl.Log($"prefix: Exception {e}:\n {e.StackTrace}");
}
}
-
- [UsedImplicitly]
- private static void Postfix(State __state)
- {
- try
- {
- if (!GameManager.RunSimulation) return;
- RemoteControl.Log("logic stack tick: start prefix");
- SubscriptionManager.RescanNetworks();
- RemoteControl.Log("logic stack tick: start postfix");
-
- }
- catch (Exception e)
- {
- RemoteControl.Log("logic stack tick: start postfix");
- RemoteControl.Log($"postfix: Exception {e}: \n{e.StackTrace}");
- RemoteControl.Log("logic stack tick: end postfix");
- }
- finally
- {
- // if (__state.Taken)
- // {
- // System.Threading.Monitor.Exit(__state.LockObj);
- // }
- }
-
- }
}
diff --git a/RemoteControl.csproj b/RemoteControl.csproj
index 3f58104..7e81263 100644
--- a/RemoteControl.csproj
+++ b/RemoteControl.csproj
@@ -72,7 +72,7 @@
-
+
diff --git a/Scripts/LogTimer.cs b/Scripts/LogTimer.cs
new file mode 100644
index 0000000..926824f
--- /dev/null
+++ b/Scripts/LogTimer.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Assets.Scripts;
+using Assets.Scripts.Networks;
+using Assets.Scripts.Objects.Electrical;
+using Assets.Scripts.Objects.Motherboards;
+using Assets.Scripts.Util;
+using JetBrains.Annotations;
+using RemoteControl.Message;
+using Swan;
+using UnityEngine;
+using GameDevice = Assets.Scripts.Objects.Pipes.Device;
+// ReSharper disable ClassNeverInstantiated.Global
+// ReSharper disable MemberCanBePrivate.Global
+namespace RemoteControl
+{
+
+ public class LogTimer : IDisposable
+ {
+ private readonly DateTime _startTime = DateTime.Now;
+ private string _action;
+
+ public LogTimer(string action)
+ {
+ RemoteControl.Log($"Beginning {action}");
+ _action = action;
+ }
+
+ public void Dispose()
+ {
+ var endTime = DateTime.Now;
+ var elapsed = endTime - _startTime;
+ Debug.Log($"Time taken for {_action}: " + elapsed);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Scripts/Remotecontrol.cs b/Scripts/Remotecontrol.cs
index 2383d6b..154e10a 100644
--- a/Scripts/Remotecontrol.cs
+++ b/Scripts/Remotecontrol.cs
@@ -204,7 +204,18 @@ namespace RemoteControl
}
[Route(HttpVerbs.Get, "/networks")]
- public Task> ListNetworks() => Task.FromResult(SubscriptionManager.GetProbes());
+ public Task> ListNetworks()
+ {
+ IList probeNames = new List();
+ GameDevice.AllDevices.ForEach(dev =>
+ {
+ if (dev is CableAnalyser analyser)
+ {
+ probeNames.Add(analyser.DisplayName);
+ }
+ });
+ return Task.FromResult(probeNames);
+ }
[Route(HttpVerbs.Get, "/networks/{networkId}")]
public Task> ListDevices(string networkId)
diff --git a/Scripts/SubscriptionManager.cs b/Scripts/SubscriptionManager.cs
deleted file mode 100644
index 47489c4..0000000
--- a/Scripts/SubscriptionManager.cs
+++ /dev/null
@@ -1,390 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Assets.Scripts;
-using Assets.Scripts.Networks;
-using Assets.Scripts.Objects.Electrical;
-using Assets.Scripts.Objects.Motherboards;
-using Assets.Scripts.Util;
-using JetBrains.Annotations;
-using RemoteControl.Message;
-using Swan;
-using UnityEngine;
-using GameDevice = Assets.Scripts.Objects.Pipes.Device;
-// ReSharper disable ClassNeverInstantiated.Global
-// ReSharper disable MemberCanBePrivate.Global
-namespace RemoteControl
-{
- public class DataNetwork
- {
- public long ReferenceId { get; private set; }
- internal readonly List Probes = new ();
- internal CableNetwork Network { get; private set; }
-
- private readonly HashSet _knownIds = new();
-
-
- internal readonly Dictionary DeviceCache = new();
-
- public DataNetwork(CableNetwork network)
- {
-
- ReferenceId = network.ReferenceId;
- Network = network;
- }
-
- internal void RescanNetworkComposition()
- {
- _knownIds.Clear();
- _knownIds.UnionWith(Network.DataDeviceList.Select(device => device.ReferenceId));
- DeviceCache.Keys.Except(_knownIds).ToList().ForEach(device => DeviceCache.Remove(device));
-
- _knownIds.Except(DeviceCache.Keys).ToList().ForEach(device =>
- {
- var newDev = new Device();
- var dev = Referencable.Find(device);
- if (dev == null) return;
- newDev.ReferenceId = device;
- newDev.PrefabHash = dev.PrefabHash;
- newDev.PrefabName = dev.PrefabName;
- DeviceCache.Add(device, newDev);
- });
- UpdateAllDevices();
- }
-
- private void UpdateAllDevices()
- {
- foreach (var kvp in DeviceCache)
- {
- var device = kvp.Value;
- var gameObj = Referencable.Find(kvp.Key);
- if (gameObj == null) continue;
- device.LogicValues.Clear();
- foreach (var type in EnumCollections.LogicTypes.Values)
- {
- if (gameObj.CanLogicRead(type))
- {
- device.LogicValues[type] = gameObj.GetLogicValue(type);
- }
- }
-
- var slotCount = gameObj.TotalSlots;
- while (device.Slots.Count > slotCount)
- {
- device.Slots.RemoveAt(device.Slots.Count - 1);
- }
- for (int slotIndex = 0; slotIndex < slotCount; slotIndex++)
- {
- if (device.Slots.Count <= slotIndex)
- {
- device.Slots.Add(new Dictionary());
- }
-
- foreach (var type in EnumCollections.LogicSlotTypes.Values)
- {
- if (gameObj.CanLogicRead(type, slotIndex))
- {
- device.Slots[slotIndex][type] = gameObj.GetLogicValue(type, slotIndex);
- }
- }
- }
- }
- }
-
-
- public DataNetwork Reset(CableNetwork cnet)
- {
- ReferenceId = cnet.ReferenceId;
- Network = cnet;
- Probes.Clear();
- DeviceCache.Clear();
- _knownIds.Clear();
- return this;
- }
- }
-
- public readonly struct LogicUpdate : IEquatable
- {
- public readonly long TargetReferenceId;
- public readonly LogicType LogicType;
-
- public LogicUpdate(long targetReferenceId, LogicType logicType)
- {
- TargetReferenceId = targetReferenceId;
- LogicType = logicType;
- }
-
- public bool Equals(LogicUpdate other)
- {
- return TargetReferenceId == other.TargetReferenceId && LogicType == other.LogicType;
- }
-
- public override bool Equals(object obj)
- {
- return obj is LogicUpdate other && Equals(other);
- }
-
- public override int GetHashCode()
- {
- return CompositeHashCode.Using(TargetReferenceId, LogicType);
- }
- }
-
- public readonly struct SlotUpdate : IEquatable
- {
- public readonly long ReferenceId;
- public readonly int Slot;
- public readonly LogicSlotType Type;
-
- public SlotUpdate(long referenceID, int slot, LogicSlotType type)
- {
- ReferenceId = referenceID;
- Slot = slot;
- Type = type;
- }
-
- public bool Equals(SlotUpdate other)
- {
- return ReferenceId == other.ReferenceId && Slot == other.Slot && Type == other.Type;
- }
-
- public override bool Equals(object obj)
- {
- return obj is SlotUpdate other && Equals(other);
- }
-
- public override int GetHashCode()
- {
- return CompositeHashCode.Using(ReferenceId, Slot, Type);
- }
- }
-
- public static class SubscriptionManager
- {
- public static readonly object Lock = new();
-
- private static readonly Dictionary DataNetworks = new();
- // private Dictionary> _probesByName = new();
- // private Dictionary _probesById = new();
- private static readonly Dictionary PendingUpdates = new();
- private static readonly Dictionary PendingSlotUpdates = new();
-
- [CanBeNull]
- public static Device FindCachedDevice(string probeName, long referenceID)
- {
- foreach (var analyzer in GetDataNetwork(probeName))
- {
- if (analyzer.DeviceCache.TryGetValue(referenceID, out var device))
- {
- return device;
- }
- }
-
- return null;
- }
-
- // Can be called from any thread
- public static bool SetLogic(string probeName, long referenceID, LogicType type, double value)
- {
- // lock (Lock)
- {
- var dev = FindCachedDevice(probeName, referenceID);
- if (dev == null)
- {
- return false;
- }
-
- dev.LogicValues[type] = value;
- PendingUpdates[new LogicUpdate(referenceID, type)] = value;
- }
-
- return true;
- }
-
- // Can be called from any thread
- public static bool SetSlot(string probeName, long referenceID, int slot, LogicSlotType type, double value)
- {
- // lock (Lock)
- {
-
- var dev = FindCachedDevice(probeName, referenceID);
- if (dev != null && dev.Slots.Count > slot && dev.Slots[slot].ContainsKey(type))
- {
- dev.Slots[slot][type] = value;
- PendingSlotUpdates[new SlotUpdate(referenceID, slot, type)] = value;
- return true;
- }
- else
- {
- return false;
- }
- }
-
- }
-
- public static DataNetwork GetDataNetwork(CableNetwork network)
- {
- if (DataNetworks.TryGetValue(network.ReferenceId, out var dataNetwork))
- {
- return dataNetwork;
- }
- else
- {
- var ret = new DataNetwork(network);
- DataNetworks.Add(network.ReferenceId, ret);
- return ret;
- }
- }
-
- public static IEnumerable GetDataNetwork(string probeName)
- {
- // lock (Lock)
- {
- List networks = new();
- GameDevice.AllDevices.ForEach(dev =>
- {
- if (dev is CableAnalyser analyzer)
- {
- networks.Add(GetDataNetwork(analyzer.CableNetwork));
- }
- });
- return networks;
- }
- }
-
-
- public static GameDevice GetDevice(long referenceID)
- {
- var device = Referencable.Find(referenceID);
- if (!DataNetworks.Values.Any((item) => item.Network.DataDeviceList.Contains(device)))
- return null;
- return device;
-
- }
-
- public static GameDevice GetDevice(string probeName, long referenceID)
- {
- var device = Referencable.Find(referenceID);
- if (GetDataNetwork(probeName).Any(network => network.DeviceCache.ContainsKey(referenceID)))
- {
- return device;
- }
- return null;
- }
-
- ///
- /// Called from Unity thread pool before the logic tick
- ///
- ///
- public static void ApplyUpdates()
- {
- lock (Lock)
- {
- foreach (var update in PendingUpdates)
- {
- var device = GetDevice(update.Key.TargetReferenceId);
-
- if (!device.CanLogicWrite(update.Key.LogicType))
- {
- device.SetLogicValue(update.Key.LogicType, update.Value);
- }
- }
-
- foreach (var update in PendingSlotUpdates)
- {
- var device = Referencable.Find(update.Key.ReferenceId);
- if (!DataNetworks.Values.Any((item) => item.Network.DataDeviceList.Contains(device)))
- continue;
-
- if (!device.CanLogicWrite(update.Key.Type, update.Key.Slot))
- {
- device.SetLogicValue(update.Key.Type, update.Key.Slot, update.Value);
- }
- }
-
- PendingUpdates.Clear();
- PendingSlotUpdates.Clear();
- }
- }
-
- public static void RescanNetworks()
- {
- using (new LogTimer("RescanNetworks"))
- {
- HashSet scannedAnalyzers = new();
- HashSet scannedNetworks = new();
-
- scannedNetworks.Clear();
- GameDevice.AllDevices.ForEach(dev =>
- {
- if (dev is CableAnalyser analyser)
- {
- scannedAnalyzers.Add(analyser);
- scannedNetworks.Add(analyser.CableNetwork);
- }
- });
-
- var removed =
- new List(DataNetworks.Values.Where(dataNetwork =>
- !scannedNetworks.Contains(dataNetwork.Network)));
- foreach (var dataNet in removed)
- {
- DataNetworks.Remove(dataNet.ReferenceId);
- }
-
- foreach (var dataNet in DataNetworks.Values)
- {
- dataNet.Probes.Clear();
- }
-
- foreach (var analyzer in scannedAnalyzers)
- {
- if (DataNetworks.ContainsKey(analyzer.ReferenceId)) continue;
-
- var dataNet = removed.Pop()?.Reset(analyzer.CableNetwork) ?? new DataNetwork(analyzer.CableNetwork);
- dataNet.Probes.Add(analyzer);
- }
-
-
- // TODO: when we have our own device for tagging a network, make this triggered by on the DataNetworkChange method
- foreach (var dataNet in DataNetworks.Values)
- {
- dataNet.RescanNetworkComposition();
- }
- }
- }
-
- public static IList GetProbes()
- {
- List probes = new();
- GameDevice.AllDevices.ForEach(dev =>
- {
- if (dev is CableAnalyser)
- {
- probes.Add(dev.DisplayName);
- }
- });
- return probes;
- }
-
- }
-
- public class LogTimer : IDisposable
- {
- private readonly DateTime _startTime = DateTime.Now;
- private string _action;
-
- public LogTimer(string action)
- {
- RemoteControl.Log($"Beginning {action}");
- _action = action;
- }
-
- public void Dispose()
- {
- var endTime = DateTime.Now;
- var elapsed = endTime - _startTime;
- Debug.Log($"Time taken for {_action}: " + elapsed);
- }
- }
-}
\ No newline at end of file