diff --git a/CriticalPathAnalyzer.sln.DotSettings b/CriticalPathAnalyzer.sln.DotSettings
new file mode 100644
index 0000000..fb4dc8c
--- /dev/null
+++ b/CriticalPathAnalyzer.sln.DotSettings
@@ -0,0 +1,2 @@
+
+ True
\ No newline at end of file
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/manifest.jecs b/CriticalPathAnalyzer/CriticalPathAnalyzer/manifest.jecs
index 84f0047..659fc76 100644
--- a/CriticalPathAnalyzer/CriticalPathAnalyzer/manifest.jecs
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/manifest.jecs
@@ -1,7 +1,7 @@
ID: CriticalPathAnalyzer
Name: CriticalPathAnalyzer
Author: D4VID
-Version: 0.0.3
+Version: 0.0.4
Priority: 0
Dependencies:
- HarmonyForLogicWorld
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/PathHighlighter.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/PathHighlighter.cs
index 965ef4c..baa46e1 100644
--- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/PathHighlighter.cs
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/PathHighlighter.cs
@@ -9,7 +9,6 @@ using LogicWorld.Outlines;
namespace CriticalPathAnalyzer.Client.Tool {
public class PathHighlighter {
private static List _clusters = new List();
- private static List _highlightedComponents = new List();
private static List _highlightedWires = new List();
public static void HighlightWires(List clusters) {
@@ -18,22 +17,6 @@ namespace CriticalPathAnalyzer.Client.Tool {
foreach (ClusterDetails clusterDetails in _clusters) {
HighlightCluster(clusterDetails);
}
-
- // IWorldData world = Instances.MainWorld.Data;
-
- // foreach (ComponentAddress componentAddress in response.PerimeterComponents) {
- // if (!world.Contains(componentAddress)) {
- // continue;
- // }
- //
- // Outliner.Outline(componentAddress, PerimeterColor);
- // _highlightedComponents.Add(componentAddress);
- // }
-
- // _clusters.AddRange(response.NextClusters); // add to the collection to unhighlight
- // foreach (ClusterDetails clusterDetails in response.NextClusters) {
- // HighlightCluster(clusterDetails, NextColor);
- // }
}
///
@@ -52,14 +35,6 @@ namespace CriticalPathAnalyzer.Client.Tool {
Outliner.Outline(address, outline);
}
- foreach (ComponentAddress address in cluster.LinkingComponents) {
- if (!world.Contains(address)) {
- continue;
- }
-
- Outliner.Outline(address, outline);
- }
-
foreach (PegAddress pegAddress in cluster.Pegs) {
if (!world.Contains(pegAddress.ComponentAddress)) {
continue;
@@ -99,14 +74,9 @@ namespace CriticalPathAnalyzer.Client.Tool {
foreach (WireAddress wireAddress in _highlightedWires) {
Outliner.RemoveOutline(wireAddress);
}
-
- foreach (ComponentAddress componentAddress in _highlightedComponents) {
- Outliner.RemoveOutline(componentAddress);
- }
_clusters = null;
_highlightedWires.Clear();
- _highlightedComponents.Clear();
}
private static void UnhighlightCluster(ClusterDetails cluster) {
@@ -117,10 +87,6 @@ namespace CriticalPathAnalyzer.Client.Tool {
foreach (ComponentAddress address in cluster.ConnectingComponents) {
Outliner.RemoveOutline(address);
}
-
- foreach (ComponentAddress address in cluster.LinkingComponents) {
- Outliner.RemoveOutline(address);
- }
}
}
}
\ No newline at end of file
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ServerPathTracer.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ServerPathTracer.cs
index 45cf0ed..bc5732a 100644
--- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ServerPathTracer.cs
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ServerPathTracer.cs
@@ -8,15 +8,13 @@ using LogicAPI.Data;
using LogicAPI.Server.Components;
using LogicAPI.Services;
using LogicLog;
+using LogicWorld.LogicCode;
using LogicWorld.Server.Circuitry;
namespace CriticalPathAnalyzer.Server.Tool {
public class ServerPathTracer {
// Reflection/Delegate access helpers:
private static readonly Func GetCluster;
- private static readonly Func GetLinker;
-
- private static readonly Func> GetFollowers;
// Services needed to lookup wires/pegs:
private static readonly ICircuitryManager Circuits;
@@ -26,12 +24,6 @@ namespace CriticalPathAnalyzer.Server.Tool {
GetCluster = Delegator.createPropertyGetter(
Properties.getPrivate(typeof(InputPeg), "Cluster")
);
- GetLinker = Delegator.createFieldGetter(
- Fields.getPrivate(typeof(Cluster), "Linker")
- );
- GetFollowers = Delegator.createFieldGetter>(
- Fields.getPrivate(typeof(ClusterLinker), "LinkedFollowers")
- );
Circuits = ServiceGetter.getService();
World = ServiceGetter.getService();
@@ -62,10 +54,10 @@ namespace CriticalPathAnalyzer.Server.Tool {
// An output peg however can be connected to multiple clusters.
// It only makes sense to then select all these clusters as primary cluster.
var startingClusters = new HashSet();
- CollectMainClusters(start, startingClusters);
+ CollectPegClusters(start, startingClusters);
var endingClusters = new HashSet();
- CollectMainClusters(end, endingClusters);
+ CollectPegClusters(end, endingClusters);
foreach (Cluster startingCluster in startingClusters) {
// ignore already mapped clusters
@@ -204,55 +196,112 @@ namespace CriticalPathAnalyzer.Server.Tool {
// var perimeterComponents = new HashSet();
var collectedNextClusters = new HashSet();
+ var collectedNextInstantClusters = new HashSet();
foreach (Cluster cluster in node.Clusters) {
foreach (InputPeg inputPeg in cluster.ConnectedInputs) {
- if (inputPeg.LogicComponent == null) {
+ LogicComponent component = inputPeg.LogicComponent;
+ if (component == null) {
// These are regular pegs, they are not attached to any logic component, skip them
continue;
}
- // perimeterComponents.Add(inputPeg.LogicComponent.Address);
- foreach (IOutputPeg outputPeg in inputPeg.LogicComponent.Outputs) {
- CollectMainClusters(outputPeg.Address, collectedNextClusters);
+ if (component.GetType() == typeof(Delayer)) {
+ // Special handling of the delayer
+ var delayer = (Delayer) component;
+ //TODO: delayer.Data.DelayLengthInTicks;
+ CollectPegClusters(delayer.Outputs[0].Address, collectedNextClusters);
+ } else if (component.GetType() == typeof(Relay)) {
+ // Collect all next clusters connected via a relay (from the control input side)
+ if (inputPeg.Address == component.Inputs[0].Address) {
+ // the top control input
+ CollectPegClusters(component.Inputs[1].Address, collectedNextClusters);
+ CollectPegClusters(component.Inputs[2].Address, collectedNextClusters);
+ }
+ } else {
+ // Collect all next cluster connected via normal components
+ foreach (IOutputPeg outputPeg in component.Outputs) {
+ CollectPegClusters(outputPeg.Address, collectedNextClusters);
+ }
+
+ // Collect all next clusters connected via fast buffers
+ if (inputPeg.OneWayPhasicLinksFollowers != null) {
+ foreach (InputPeg followerPeg in inputPeg.OneWayPhasicLinksFollowers) {
+ CollectPegClusters(followerPeg.Address, collectedNextInstantClusters);
+ }
+ }
}
}
}
- foreach (Cluster nextCluster in collectedNextClusters) {
- // ignore already mapped clusters
- if (clusterToNodeMapping.TryGetValue(nextCluster, out int nextNodeIndex)) {
- ClusterNode nextNode = clusterNodes[nextNodeIndex];
- // only add the link, don't propagate
- nextNode.PrevNodeIndexes.Add(node.Index);
- node.NextNodes.TryAdd(nextNodeIndex, 1);
- } else {
- // var nextClusters = new HashSet();
- // var twoWayConnectedClusters = new HashSet();
- // GetLinkedClusters(cluster, nextClusters, twoWayConnectedClusters, GetFollowers);
- nextNodeIndex = clusterNodes.Count;
- var nextNode = new ClusterNode() {
- Index = nextNodeIndex,
- Clusters = new HashSet() {nextCluster},
- Time = 0,
- NextNodes = new Dictionary(),
- PrevNodeIndexes = new HashSet() {node.Index},
- };
-
- clusterNodes.Add(nextNode);
-
- node.NextNodes.TryAdd(nextNodeIndex, 1);
-
- foreach (Cluster nextNodeCluster in nextNode.Clusters) {
- clusterToNodeMapping.Add(nextNodeCluster, nextNodeIndex);
- }
+ LinkNextClusters(queue, clusterToNodeMapping, clusterNodes, collectedNextInstantClusters, node, 0);
+ LinkNextClusters(queue, clusterToNodeMapping, clusterNodes, collectedNextClusters, node, 1);
+ }
- // propagate
- queue.Enqueue(nextNode);
+ logger.Info($"Finished after {iterations} iterations");
+ }
+
+ private static HashSet GetClustersConnectedThroughRelays(Cluster cluster) {
+ var clusters = new HashSet() {cluster};
+ foreach (InputPeg inputPeg in cluster.ConnectedInputs) {
+ LogicComponent component = inputPeg.LogicComponent;
+ if (component == null) {
+ // These are regular pegs, they are not attached to any logic component, skip them
+ continue;
+ }
+
+ if (component.GetType() == typeof(Relay)) {
+ // Collect all next clusters connected via a relay (from the control input side)
+ if (inputPeg.Address == component.Inputs[1].Address) {
+ // one of the sides
+ CollectPegClusters(component.Inputs[2].Address, clusters);
+ } else if (inputPeg.Address == component.Inputs[2].Address) {
+ // the other side
+ CollectPegClusters(component.Inputs[1].Address, clusters);
}
}
}
- logger.Info($"Finished after {iterations} iterations");
+ return clusters;
+ }
+
+ private static void LinkNextClusters(Queue queue, Dictionary clusterToNodeMapping,
+ List clusterNodes, HashSet collectedNextClusters, ClusterNode node, int delay) {
+ foreach (Cluster nextCluster in collectedNextClusters) {
+ // ignore already mapped clusters
+ if (clusterToNodeMapping.TryGetValue(nextCluster, out int nextNodeIndex)) {
+ ClusterNode nextNode = clusterNodes[nextNodeIndex];
+ // only add the link, don't propagate
+ nextNode.PrevNodeIndexes.Add(node.Index);
+ node.NextNodes.TryAdd(nextNodeIndex, delay);
+ } else {
+ HashSet nextClusters = GetClustersConnectedThroughRelays(nextCluster);
+
+ if (nextClusters.Any(clusterToNodeMapping.ContainsKey)) {
+ // already discovered cluster node
+ continue;
+ }
+
+ nextNodeIndex = clusterNodes.Count;
+ var nextNode = new ClusterNode() {
+ Index = nextNodeIndex,
+ Clusters = nextClusters,
+ Time = 0,
+ NextNodes = new Dictionary(),
+ PrevNodeIndexes = new HashSet() {node.Index},
+ };
+
+ clusterNodes.Add(nextNode);
+
+ node.NextNodes.TryAdd(nextNodeIndex, delay);
+
+ foreach (Cluster nextNodeCluster in nextNode.Clusters) {
+ clusterToNodeMapping.TryAdd(nextNodeCluster, nextNodeIndex);
+ }
+
+ // propagate
+ queue.Enqueue(nextNode);
+ }
+ }
}
@@ -288,18 +337,13 @@ namespace CriticalPathAnalyzer.Server.Tool {
return cluster;
}
- private static bool GetLinkerAt(Cluster cluster, out ClusterLinker linker) {
- linker = GetLinker(cluster);
- return linker != null;
- }
-
///
/// An output peg can be connected to multiple clusters. Collect all of them.
///
/// Address of the peg
/// Found clusters get added into this hash set
/// A wire of the peg is not in the world
- private static void CollectMainClusters(PegAddress pegAddress, HashSet primaryClusters) {
+ private static void CollectPegClusters(PegAddress pegAddress, HashSet primaryClusters) {
if (pegAddress.IsInputAddress(out InputAddress inputAddress)) {
primaryClusters.Add(GetClusterAt(inputAddress));
} else {
@@ -325,48 +369,11 @@ namespace CriticalPathAnalyzer.Server.Tool {
}
}
- private static void GetLinkedClusters(
- Cluster startingPoint,
- HashSet oneWayConnectedClusters,
- HashSet twoWayConnectedClusters,
- Func> linkedLinkerGetter
- ) {
- var clustersToProcess = new Queue();
- if (!GetLinkerAt(startingPoint, out ClusterLinker startingLinker)) {
- return; // No linker on this cluster => no link => nothing to collect
- }
-
- clustersToProcess.Enqueue(startingLinker);
- twoWayConnectedClusters.Add(startingPoint);
- // While the starting cluster is no source, the algorithm needs to skip it when encountered.
- while (clustersToProcess.TryDequeue(out ClusterLinker linkerToCheck)) {
- List listOfLinkedLinkers = linkedLinkerGetter(linkerToCheck); // Is never null.
- foreach (ClusterLinker linkedLinker in listOfLinkedLinkers) {
- Cluster clusterOfLinkedLinker = linkedLinker.ClusterBeingLinked; // Should never be null.
- List listOfBackLinkers = linkedLinkerGetter(linkedLinker); // Is never null.
- if (listOfBackLinkers.Contains(linkerToCheck)) {
- // bidirectional - a relay
- // TODO: will not find a relay connection if the relay is turned off
- if (twoWayConnectedClusters.Add(clusterOfLinkedLinker)) {
- // Element was not yet present in the array, so keep looking into it!
- clustersToProcess.Enqueue(linkedLinker);
- }
- } else {
- // unidirectional - a fast buffer
- oneWayConnectedClusters.Add(clusterOfLinkedLinker);
- // stop propagation
- }
- }
- }
-
- twoWayConnectedClusters.Remove(startingPoint);
- }
private static ClusterDetails CollectClusterInformation(Cluster cluster, int time) {
var details = new ClusterDetails {
Pegs = new List(),
ConnectingComponents = new List(),
- LinkingComponents = new List(),
Color = HsvToRgb(time * 20, 1, 1),
};
@@ -380,14 +387,6 @@ namespace CriticalPathAnalyzer.Server.Tool {
// Socket
details.ConnectingComponents.Add(peg.Address.ComponentAddress);
}
-
- if ((peg.PhasicLinks != null && peg.PhasicLinks.Any())
- || (peg.OneWayPhasicLinksFollowers != null && peg.OneWayPhasicLinksFollowers.Any())
- || (peg.OneWayPhasicLinksLeaders != null && peg.OneWayPhasicLinksLeaders.Any())
- ) {
- // Relay / fast buffer
- details.LinkingComponents.Add(peg.Address.ComponentAddress);
- }
}
foreach (OutputPeg peg in outputPegs) {
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs
index 296b77e..a9f8b24 100644
--- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs
@@ -27,11 +27,6 @@ namespace CriticalPathAnalyzer.Shared.Packets.S2C {
///
[Key(1)] public List ConnectingComponents;
- ///
- /// Relays and fast buffers
- ///
- [Key(2)] public List LinkingComponents;
-
[Key(3)] public int Color;
}
}
\ No newline at end of file