Send cluster tree to the client

master
D4VID 6 months ago
parent 578138fa6c
commit 295993f4e8

@ -1,7 +1,7 @@
ID: CriticalPathAnalyzer
Name: CriticalPathAnalyzer
Author: D4VID
Version: 0.1.0
Version: 0.2.0
Priority: 0
Dependencies:
- HarmonyForLogicWorld

@ -130,11 +130,11 @@ namespace CriticalPathAnalyzer.Client.Tool {
PathHighlighter.RemoveHighlighting();
if (_response.LoopingClusters.Count > 0) {
PathHighlighter.HighlightWires(_response.LoopingClusters);
if (_response.LoopingNodes.Count > 0) {
PathHighlighter.HighlightClusterNodes(_response.LoopingNodes);
} else {
_logger.Info($"Critical path length is: {_response.CriticalPathLength}");
PathHighlighter.HighlightWires(_response.Clusters);
PathHighlighter.HighlightClusterNodes(_response.Nodes);
}
}
}

@ -9,26 +9,26 @@ using LogicWorld.Outlines;
namespace CriticalPathAnalyzer.Client.Tool {
public class PathHighlighter {
private static List<ClusterDetails> _clusters = new List<ClusterDetails>();
private static List<Node> _nodes = new List<Node>();
private static List<WireAddress> _highlightedWires = new List<WireAddress>();
public static void HighlightWires(List<ClusterDetails> clusters) {
_clusters = clusters;
public static void HighlightClusterNodes(List<Node> nodes) {
_nodes = nodes;
foreach (ClusterDetails clusterDetails in _clusters) {
HighlightCluster(clusterDetails);
foreach (Node node in _nodes) {
HighlightNode(node);
}
}
/// <summary>
/// Highlight all pegs and wires of the given cluster.
/// </summary>
private static void HighlightCluster(ClusterDetails cluster) {
private static void HighlightNode(Node node) {
IWorldData world = Instances.MainWorld.Data;
var outline = new OutlineData(new Color24(HsvToRgb(cluster.Time * 20, 1.0f, 1.0f)));
var outline = new OutlineData(new Color24(HsvToRgb(node.Time * 20, 1.0f, 1.0f)));
foreach (ComponentAddress address in cluster.ConnectingComponents) {
foreach (ComponentAddress address in node.ConnectingComponents) {
if (!world.Contains(address)) {
continue;
}
@ -36,7 +36,7 @@ namespace CriticalPathAnalyzer.Client.Tool {
Outliner.Outline(address, outline);
}
foreach (PegAddress pegAddress in cluster.Pegs) {
foreach (PegAddress pegAddress in node.Pegs) {
if (!world.Contains(pegAddress.ComponentAddress)) {
continue;
}
@ -64,28 +64,28 @@ namespace CriticalPathAnalyzer.Client.Tool {
}
public static void RemoveHighlighting() {
if (_clusters == null) {
if (_nodes == null) {
return;
}
foreach (ClusterDetails cluster in _clusters) {
UnhighlightCluster(cluster);
foreach (Node cluster in _nodes) {
UnhighlightNode(cluster);
}
foreach (WireAddress wireAddress in _highlightedWires) {
Outliner.RemoveOutline(wireAddress);
}
_clusters = null;
_nodes = null;
_highlightedWires.Clear();
}
private static void UnhighlightCluster(ClusterDetails cluster) {
foreach (PegAddress address in cluster.Pegs) {
private static void UnhighlightNode(Node node) {
foreach (PegAddress address in node.Pegs) {
Outliner.RemoveOutline(address);
}
foreach (ComponentAddress address in cluster.ConnectingComponents) {
foreach (ComponentAddress address in node.ConnectingComponents) {
Outliner.RemoveOutline(address);
}
}

@ -3,10 +3,29 @@ using LogicWorld.Server.Circuitry;
namespace CriticalPathAnalyzer.Server.Tool {
public class ClusterNode {
public int Index; // "identifier"
public HashSet<Cluster> Clusters; // bidirectionally connected clusters without delay
public int Time; // what point in time has been this cluster last updated
public Dictionary<int, int> NextNodes; // next node index / delay between them
public HashSet<int> PrevNodeIndexes; // node indexes that update this one
/// <summary>
/// Identifier
/// </summary>
public int Index;
/// <summary>
/// All bidirectionally connected clusters without delay that form this node
/// </summary>
public HashSet<Cluster> Clusters;
/// <summary>
/// Next node index / delay between them
/// </summary>
public Dictionary<int, int> NextNodes;
/// <summary>
/// Node indexes that update this one
/// </summary>
public HashSet<int> PrevNodeIndexes;
/// <summary>
/// After how many ticks has been this cluster last updated
/// </summary>
public int Time;
}
}

@ -109,14 +109,16 @@ namespace CriticalPathAnalyzer.Server.Tool {
}
}
foreach (ClusterNode node in clusterNodes) {
FillNodeInformation(node);
}
// Collect information about each cluster:
response = new AnalyzePathResponse() {
RequestGuid = requestGuid,
Clusters = clusterNodes.SelectMany(node =>
node.Clusters.Select(cluster => CollectClusterInformation(cluster, node.Time))).ToList(),
Nodes = clusterNodes.Select(FillNodeInformation).ToList(),
CriticalPathLength = criticalPathLength,
LoopingClusters = loopingNodes.SelectMany(loopingNode => loopingNode.Clusters
.Select(cluster => CollectClusterInformation(cluster, 0))).ToList(),
LoopingNodes = loopingNodes.Select(FillNodeInformation).ToList(),
};
logger.Info("Trace end");
@ -400,31 +402,36 @@ namespace CriticalPathAnalyzer.Server.Tool {
/// <summary>
/// Obtain additional information about the cluster:
/// Collect all it's pegs and sockets.
/// Obtain additional information about the clusters:
/// Collect all their pegs and sockets.
/// </summary>
private static ClusterDetails CollectClusterInformation(Cluster cluster, int time) {
var details = new ClusterDetails {
private static Node FillNodeInformation(ClusterNode node) {
var clientNode = new Node() {
Index = node.Index,
NextNodes = node.NextNodes,
PrevNodeIndexes = node.PrevNodeIndexes,
Time = node.Time,
Pegs = new List<PegAddress>(),
ConnectingComponents = new List<ComponentAddress>(),
Time = time,
};
// Two lists are never null, according to how it is created and used:
IReadOnlyList<InputPeg> inputPegs = cluster.ConnectedInputs;
IReadOnlyList<OutputPeg> outputPegs = cluster.ConnectedOutputs;
foreach (Cluster cluster in node.Clusters) {
// Two lists are never null, according to how it is created and used:
IReadOnlyList<InputPeg> inputPegs = cluster.ConnectedInputs;
IReadOnlyList<OutputPeg> outputPegs = cluster.ConnectedOutputs;
foreach (InputPeg peg in inputPegs) {
details.Pegs.Add(peg.Address);
if (peg.SecretLinks != null && peg.SecretLinks.Any()) {
// Socket
details.ConnectingComponents.Add(peg.Address.ComponentAddress);
foreach (InputPeg peg in inputPegs) {
clientNode.Pegs.Add(peg.Address);
if (peg.SecretLinks != null && peg.SecretLinks.Any()) {
// Socket
clientNode.ConnectingComponents.Add(peg.Address.ComponentAddress);
}
}
}
details.Pegs.AddRange(outputPegs.Select(peg => peg.Address));
clientNode.Pegs.AddRange(outputPegs.Select(peg => peg.Address));
}
return details;
return clientNode;
}
}
}

@ -8,28 +8,42 @@ namespace CriticalPathAnalyzer.Shared.Packets.S2C {
[MessagePackObject]
public class AnalyzePathResponse : Packet {
[Key(0)] public Guid RequestGuid;
[Key(1)] public List<ClusterDetails> Clusters;
[Key(1)] public List<Node> Nodes;
[Key(2)] public int CriticalPathLength;
[Key(3)] public List<ClusterDetails> LoopingClusters;
[Key(3)] public List<Node> LoopingNodes;
}
[MessagePackObject]
public sealed class ClusterDetails {
public sealed class Node {
/// <summary>
/// List of all pegs inside the cluster
/// Identifier
/// </summary>
[Key(0)] public List<PegAddress> Pegs;
[Key(0)] public int Index;
/// <summary>
/// Sockets
/// Next node index / delay between them
/// </summary>
[Key(1)] public List<ComponentAddress> ConnectingComponents;
[Key(1)] public Dictionary<int, int> NextNodes;
/// <summary>
/// Delay in ticks after which this cluster gets last updated
/// Node indexes that update this one
/// </summary>
[Key(2)] public HashSet<int> PrevNodeIndexes;
/// <summary>
/// After how many ticks has been this cluster last updated
/// </summary>
[Key(3)] public int Time;
/// <summary>
/// List of all pegs inside the cluster
/// </summary>
[Key(4)] public List<PegAddress> Pegs;
/// <summary>
/// Sockets
/// </summary>
[Key(2)] public int Time;
[Key(5)] public List<ComponentAddress> ConnectingComponents;
}
}
Loading…
Cancel
Save