diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/FancyInput/ContextMetadata.jecs b/CriticalPathAnalyzer/CriticalPathAnalyzer/FancyInput/ContextMetadata.jecs index 0544baa..1f57727 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/FancyInput/ContextMetadata.jecs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/FancyInput/ContextMetadata.jecs @@ -1,4 +1,6 @@ +# Define two contexts - one for keybindings used during the building state and one for the tool's state CriticalPathAnalyzer.CriticalPathAnalyzerBuilding: + # This keybinding is used during the game's standard building state - need to inject into the build actions InjectTriggersInto: - MHG.BuildActions Triggers: diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/FancyInput/TriggerMetadata.jecs b/CriticalPathAnalyzer/CriticalPathAnalyzer/FancyInput/TriggerMetadata.jecs index 77de273..8de3166 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/FancyInput/TriggerMetadata.jecs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/FancyInput/TriggerMetadata.jecs @@ -1,3 +1,4 @@ +# Define all available keybindings of the mod CriticalPathAnalyzer.OpenPathAnalyzer: Heading: "CriticalPathAnalyzer" DefaultBinding: diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerClient.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerClient.cs index 81db8fe..51c7c2b 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerClient.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerClient.cs @@ -24,14 +24,18 @@ namespace CriticalPathAnalyzer.Client { // Inject a hook into the game code to check for our keybindings KeybindingsInjector.Inject(); - + // Inject packet handlers - RawPacketHandlerInjector.addPacketHandler(new AnnounceModPacketHandler(Manifest.Version)); - RawPacketHandlerInjector.addPacketHandler(new AnalyzePathResponseHandler()); + RawPacketHandlerInjector.addPacketHandler(new AnnounceModPacketHandler(Manifest.Version)); + RawPacketHandlerInjector.addPacketHandler(new AnalyzePathResponseHandler()); Logger.Info("CriticalPathAnalyzer mod loaded"); } + /// + /// Handler method for the server's analysis response. + /// Gets called from the AnalyzePathResponseHandler packet handler class + /// public static void OnAnalyzePathResponse(AnalyzePathResponse response) { LoggerInstance.Info($"Got response from server"); CriticalPathAnalyzerTool.HandleResponse(response); diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerGameState.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerGameState.cs index 68e5c70..d731641 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerGameState.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerGameState.cs @@ -9,9 +9,17 @@ namespace CriticalPathAnalyzer.Client { public class CriticalPathAnalyzerGameState : GameState { public const string Id = "CriticalPathAnalyzerTool"; - public override bool MouseLocked => true; public override string TextID => Id; + /// + /// Locked mouse means you look around when you move it. + /// False would display the cursor to be able to click on UI elements. + /// + public override bool MouseLocked => true; + + /// + /// This list gets printed on the game's top left UI panel which displays the currently available keybindings + /// public override IEnumerable HelpScreenTriggers => new InputTrigger[] { UITrigger.Back, CriticalPathAnalyzerTrigger.AnalyzePathStart, @@ -19,10 +27,16 @@ namespace CriticalPathAnalyzer.Client { CriticalPathAnalyzerTrigger.DisplayLoop, }; + /// + /// Called when the game transitions into this game state i.e. after pressing the configured keybinding + /// public override void OnEnter() { CriticalPathAnalyzerClient.LoggerInstance.Info("CPA enter"); } + /// + /// Ran every frame when inside this game state + /// public override void OnRun() { if (CustomInput.DownThisFrame(UITrigger.Back)) { GameStateManager.TransitionBackToBuildingState(); @@ -35,6 +49,9 @@ namespace CriticalPathAnalyzer.Client { } } + /// + /// Called when the game transitions away from this game state i.e. after pressing the back keybinding + /// public override void OnExit() { CriticalPathAnalyzerClient.LoggerInstance.Info("CPA exit"); CriticalPathAnalyzerTool.Clear(); diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/keybindings/CriticalPathAnalyzerContext.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/keybindings/CriticalPathAnalyzerContext.cs index 4e149e7..5e1472b 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/keybindings/CriticalPathAnalyzerContext.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/keybindings/CriticalPathAnalyzerContext.cs @@ -1,4 +1,5 @@ namespace CriticalPathAnalyzer.Client.Keybindings { + // Define two contexts - one for keybindings used during the building state and one for the tool's state public enum CriticalPathAnalyzerContext { CriticalPathAnalyzerBuilding, CriticalPathAnalyzerTool, diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/keybindings/CriticalPathAnalyzerTrigger.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/keybindings/CriticalPathAnalyzerTrigger.cs index 9d1094f..ac63061 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/keybindings/CriticalPathAnalyzerTrigger.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/keybindings/CriticalPathAnalyzerTrigger.cs @@ -1,4 +1,5 @@ namespace CriticalPathAnalyzer.Client.Keybindings { + // Define all available keybindings of the mod public enum CriticalPathAnalyzerTrigger { None, OpenPathAnalyzer, diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/network/AnalyzePathResponseHandler.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/network/AnalyzePathResponseHandler.cs index 9204ebf..bfb4068 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/network/AnalyzePathResponseHandler.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/network/AnalyzePathResponseHandler.cs @@ -4,6 +4,7 @@ using LogicWorld.SharedCode.Networking; namespace CriticalPathAnalyzer.Client.Network { public class AnalyzePathResponseHandler : PacketHandler { public override void Handle(AnalyzePathResponse packet, HandlerContext context) { + // Pass the packet to the client mod CriticalPathAnalyzerClient.OnAnalyzePathResponse(packet); } } diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/CriticalPathAnalyzerTool.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/CriticalPathAnalyzerTool.cs index e09e463..96ab410 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/CriticalPathAnalyzerTool.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/CriticalPathAnalyzerTool.cs @@ -26,6 +26,9 @@ namespace CriticalPathAnalyzer.Client.Tool { _logger = logger; } + /// + /// Remove all highlights + /// public static void Clear() { PathHighlighter.RemoveHighlighting(); Outliner.RemoveOutline(_startPegAddress); @@ -34,6 +37,10 @@ namespace CriticalPathAnalyzer.Client.Tool { _endPegAddress = PegAddress.Empty; } + /// + /// Cast a ray from the player's camera to find a peg or a wire the player is looking at. + /// + /// The peg's address or peg address of an input in case of a wire private static PegAddress RayCastPeg() { // Ray-cast into the world to find what the player is looking at HitInfo hitInfo = PlayerCaster.CameraCast(Masks.Environment | Masks.Structure | Masks.Peg | Masks.Wire); @@ -58,6 +65,9 @@ namespace CriticalPathAnalyzer.Client.Tool { return PegAddress.Empty; } + /// + /// Try to select the start of the path. + /// public static void SelectPathStart() { _logger.Info("Analyze Path Start"); PegAddress pegAddress = RayCastPeg(); @@ -71,6 +81,9 @@ namespace CriticalPathAnalyzer.Client.Tool { } } + /// + /// Try to select the end of the path. + /// public static void SelectPathEnd() { _logger.Info("Analyze Path End"); PegAddress pegAddress = RayCastPeg(); @@ -84,6 +97,9 @@ namespace CriticalPathAnalyzer.Client.Tool { } } + /// + /// Remove standard highlighting and only highlight clusters that form a loop. + /// public static void DisplayLoop() { if (_response == null) { _logger.Error("Got no response - cannot display loop"); @@ -94,6 +110,9 @@ namespace CriticalPathAnalyzer.Client.Tool { PathHighlighter.HighlightWires(_response.LoopingClusters); } + /// + /// Send a request to the server to analyze the path between the selected start and end pegs. + /// private static void CalculateCriticalPath() { if (_startPegAddress.IsEmpty() || _endPegAddress.IsEmpty()) { _logger.Error("Invalid pegs"); @@ -108,6 +127,11 @@ namespace CriticalPathAnalyzer.Client.Tool { }); } + /// + /// Handle incoming response packet from the server. + /// Highlight pegs and wires involved in the circuit with their color based on their delay from the start. + /// + /// The server's response packet public static void HandleResponse(AnalyzePathResponse response) { if (_currentRequestGuid != response.RequestGuid) { // Not matching Guid, old or wrong request, discard. diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/PathHighlighter.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/PathHighlighter.cs index e2c8014..965ef4c 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/PathHighlighter.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/PathHighlighter.cs @@ -36,6 +36,9 @@ namespace CriticalPathAnalyzer.Client.Tool { // } } + /// + /// Highlight all pegs and wires of the given cluster. + /// private static void HighlightCluster(ClusterDetails cluster) { IWorldData world = Instances.MainWorld.Data; diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/CriticalPathAnalyzerServer.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/CriticalPathAnalyzerServer.cs index efed7aa..e400c2c 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/CriticalPathAnalyzerServer.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/CriticalPathAnalyzerServer.cs @@ -34,13 +34,17 @@ namespace CriticalPathAnalyzer.Server { throw new Exception("Could not get Service 'NetworkServer'."); } - // Inject verifier: + // Inject client verifier: RawJoinVerifierInjector.addVerifier(this); PacketHandlerManager.getCustomPacketHandler() .addHandlerToEnd(new ClientJoinedPacketHandler(this)); RawPacketHandlerInjector.addPacketHandler(new CriticalPathAnalyzerRequestHandler(this)); } + /// + /// Gets called before a player (client) joins the server. + /// Used to check if the player has this mod installed + /// public void Verify(VerificationContext ctx) { bool hasMod = ctx.ApprovalPacket.ClientMods.Contains(Manifest.ID); string playerName = ctx.PlayerID.Name; @@ -48,6 +52,10 @@ namespace CriticalPathAnalyzer.Server { LoggerInstance.Info($"Verifying player {playerName}: hasMod={hasMod}"); } + /// + /// Gets called after verifying a connecting player. + /// If the player has this mod installed, send a packet informing about the mod's presence on the server. + /// public void PlayerJoined(PlayerData playerData, HandlerContext context) { _playerHasWireTracer.TryGetValue(playerData.Name, out bool hasWireTracer); if (hasWireTracer) { @@ -57,6 +65,10 @@ namespace CriticalPathAnalyzer.Server { } } + /// + /// Gets called from the AnalyzePathRequestHandler. + /// Use the tool to trace the path and send back a response. + /// public void AnalyzePath(Connection sender, Guid requestGuid, PegAddress start, PegAddress end) { LoggerInstance.Info("Got AnalyzePath request"); if (!ServerPathTracer.TracePath(requestGuid, start, end, out AnalyzePathResponse response)) { diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ServerPathTracer.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ServerPathTracer.cs index df7f69c..cd949e9 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ServerPathTracer.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ServerPathTracer.cs @@ -192,6 +192,11 @@ namespace CriticalPathAnalyzer.Server.Tool { } + /// + /// Check if the peg exists in the world + /// + /// Address of the peg + /// True if it exists, false if it doesn't private static bool PegExists(PegAddress address) { IComponentInWorld component = World.Lookup(address.ComponentAddress); if (component == null) { @@ -224,6 +229,12 @@ namespace CriticalPathAnalyzer.Server.Tool { 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) { if (pegAddress.IsInputAddress(out InputAddress inputAddress)) { primaryClusters.Add(GetClusterAt(inputAddress)); diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs index 7f771b7..473f20d 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs @@ -11,6 +11,7 @@ namespace CriticalPathAnalyzer.Shared.Packets.S2C { [Key(1)] public List Clusters; [Key(2)] public int CriticalPathLength; + [Key(3)] public List LoopingClusters; // [Key(4)] public List PerimeterComponents; // [Key(5)] public List NextClusters; @@ -18,9 +19,21 @@ namespace CriticalPathAnalyzer.Shared.Packets.S2C { [MessagePackObject] public sealed class ClusterDetails { + /// + /// List of all pegs inside the cluster + /// [Key(0)] public List Pegs; - [Key(1)] public List ConnectingComponents; // Sockets - [Key(2)] public List LinkingComponents; // Relays, fast buffers + + /// + /// Sockets + /// + [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