diff --git a/CriticalPathAnalyzer.sln.DotSettings.user b/CriticalPathAnalyzer.sln.DotSettings.user
new file mode 100644
index 0000000..6daed5b
--- /dev/null
+++ b/CriticalPathAnalyzer.sln.DotSettings.user
@@ -0,0 +1,2 @@
+
+ DoNotShowAndRun
\ No newline at end of file
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer.csproj b/CriticalPathAnalyzer/CriticalPathAnalyzer.csproj
index 0dc01cc..f63a892 100644
--- a/CriticalPathAnalyzer/CriticalPathAnalyzer.csproj
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer.csproj
@@ -56,9 +56,21 @@
..\LogicWorld\Logic_World_Data\Managed\LogicWorld.SharedCode.dll
+
+ ..\LogicWorld\Logic_World_Data\Managed\LogicWorld.Networking.dll
+
..\LogicWorld\Logic_World_Data\Managed\UnityEngine.CoreModule.dll
+
+ ..\LogicWorld\Server\Server.dll
+
+
+ ..\LogicWorld\Server\LogicAPI.Server.dll
+
+
+ ..\LogicWorld\Server\MessagePack.Annotations.dll
+
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/OnlyServerMod b/CriticalPathAnalyzer/CriticalPathAnalyzer/OnlyServerMod
new file mode 100644
index 0000000..e69de29
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/manifest.jecs b/CriticalPathAnalyzer/CriticalPathAnalyzer/manifest.jecs
index 01f6d25..470067d 100644
--- a/CriticalPathAnalyzer/CriticalPathAnalyzer/manifest.jecs
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/manifest.jecs
@@ -1,7 +1,7 @@
ID: CriticalPathAnalyzer
Name: CriticalPathAnalyzer
Author: D4VID
-Version: 0.0.1
+Version: 0.0.2
Priority: 0
Dependencies:
- HarmonyForLogicWorld
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerClient.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerClient.cs
index 5064e8f..36526ee 100644
--- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerClient.cs
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerClient.cs
@@ -1,28 +1,39 @@
-
-using CriticalPathAnalyzer.Client.Keybindings;
+using CriticalPathAnalyzer.Client.Keybindings;
+using CriticalPathAnalyzer.Client.Network;
+using CriticalPathAnalyzer.Client.Tool;
+using CriticalPathAnalyzer.Shared.Packets.S2C;
using EccsLogicWorldAPI.Client.Injectors;
using FancyInput;
using LogicAPI.Client;
using LogicLog;
namespace CriticalPathAnalyzer.Client {
+ public class CriticalPathAnalyzerClient : ClientMod {
+ public static ILogicLogger LoggerInstance;
- public class CriticalPathAnalyzerClient : ClientMod {
- public static ILogicLogger LoggerInstance;
- protected override void Initialize() {
- LoggerInstance = Logger;
- Logger.Info("CriticalPathAnalyzer mod loading");
+ protected override void Initialize() {
+ Logger.Info("CriticalPathAnalyzer mod loading");
+ LoggerInstance = Logger;
+ CriticalPathAnalyzerTool.Init(Logger);
- // Register keybindings in the settings menu
- CustomInput.Register("CriticalPathAnalyzer");
-
- // Inject our own game state
- GameStateInjector.inject(CriticalPathAnalyzerGameState.Id, typeof(CriticalPathAnalyzerGameState));
-
- // Inject a hook into the game code to check for our keybindings
- KeybindingsInjector.Inject();
-
- Logger.Info("CriticalPathAnalyzer mod loaded");
- }
- }
+ // Register keybindings in the settings menu
+ CustomInput.Register("CriticalPathAnalyzer");
+
+ // Inject our own game state
+ GameStateInjector.inject(CriticalPathAnalyzerGameState.Id, typeof(CriticalPathAnalyzerGameState));
+
+ // Inject a hook into the game code to check for our keybindings
+ KeybindingsInjector.Inject();
+
+ // Inject packet handlers
+ RawPacketHandlerInjector.addPacketHandler(new AnnounceModPacketHandler());
+ RawPacketHandlerInjector.addPacketHandler(new AnalyzePathResponseHandler());
+
+ Logger.Info("CriticalPathAnalyzer mod loaded");
+ }
+
+ public static void OnAnalyzePathResponse(AnalyzePathResponse response) {
+ LoggerInstance.Info($"Got response from server: {response.Message}");
+ }
+ }
}
\ No newline at end of file
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerGameState.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerGameState.cs
index 85613c7..cbfa027 100644
--- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerGameState.cs
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/CriticalPathAnalyzerGameState.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using CriticalPathAnalyzer.Client.Keybindings;
-using CriticalPathAnalyzer.Client.tool;
+using CriticalPathAnalyzer.Client.Tool;
using FancyInput;
using LogicUI;
using LogicWorld.GameStates;
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/network/AnalyzePathResponseHandler.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/network/AnalyzePathResponseHandler.cs
new file mode 100644
index 0000000..9204ebf
--- /dev/null
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/network/AnalyzePathResponseHandler.cs
@@ -0,0 +1,10 @@
+using CriticalPathAnalyzer.Shared.Packets.S2C;
+using LogicWorld.SharedCode.Networking;
+
+namespace CriticalPathAnalyzer.Client.Network {
+ public class AnalyzePathResponseHandler : PacketHandler {
+ public override void Handle(AnalyzePathResponse packet, HandlerContext context) {
+ CriticalPathAnalyzerClient.OnAnalyzePathResponse(packet);
+ }
+ }
+}
\ No newline at end of file
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/network/AnnounceModPacketHandler.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/network/AnnounceModPacketHandler.cs
new file mode 100644
index 0000000..0a6a61e
--- /dev/null
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/network/AnnounceModPacketHandler.cs
@@ -0,0 +1,10 @@
+using CriticalPathAnalyzer.Shared.Packets.S2C;
+using LogicWorld.SharedCode.Networking;
+
+namespace CriticalPathAnalyzer.Client.Network {
+ public class AnnounceModPacketHandler : PacketHandler {
+ public override void Handle(AnnounceModPresence packet, HandlerContext context) {
+ CriticalPathAnalyzerClient.LoggerInstance.Info($"Mod is supported on the server: version={packet.Version}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/CriticalPathAnalyzerTool.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/CriticalPathAnalyzerTool.cs
index 32a32a4..42bb191 100644
--- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/CriticalPathAnalyzerTool.cs
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/CriticalPathAnalyzerTool.cs
@@ -1,12 +1,24 @@
+using System;
+using System.Collections.Generic;
+using CriticalPathAnalyzer.Shared.Packets.C2S;
using LogicAPI.Data;
+using LogicLog;
using LogicWorld.Interfaces;
using LogicWorld.Physics;
using LogicWorld.Players;
-namespace CriticalPathAnalyzer.Client.tool {
+#pragma warning disable CS8073 // The result of the expression is always the same since a value of this type is never equal to 'null'
+
+namespace CriticalPathAnalyzer.Client.Tool {
public class CriticalPathAnalyzerTool {
- private static PegAddress _startPegAddress;
- private static PegAddress _endPegAddress;
+ private static ILogicLogger _logger;
+
+ private static PegAddress? _startPegAddress;
+ private static PegAddress? _endPegAddress;
+
+ public static void Init(ILogicLogger logger) {
+ _logger = logger;
+ }
private static PegAddress? RayCastPeg() {
// Ray-cast into the world to find what the player is looking at
@@ -37,6 +49,9 @@ namespace CriticalPathAnalyzer.Client.tool {
PegAddress? pegAddress = RayCastPeg();
if (pegAddress != null) {
_startPegAddress = pegAddress.Value;
+ if (_startPegAddress != null && _endPegAddress != null) {
+ CalculateCriticalPath();
+ }
}
}
@@ -45,6 +60,41 @@ namespace CriticalPathAnalyzer.Client.tool {
PegAddress? pegAddress = RayCastPeg();
if (pegAddress != null) {
_endPegAddress = pegAddress.Value;
+ if (_startPegAddress != null && _endPegAddress != null) {
+ CalculateCriticalPath();
+ }
+ }
+ }
+
+ private static void CalculateCriticalPath() {
+ Instances.SendData.Send(new AnalyzePathRequest {
+ RequestGuid = Guid.NewGuid(),
+ StartPegAddress = _startPegAddress.Value,
+ EndPegAddress = _endPegAddress.Value,
+ });
+ HashSet wires = Instances.MainWorld.Data.LookupPegWires(_startPegAddress.Value);
+ _logger.Info($"Start peg has {wires.Count} wires");
+
+ ComponentType andGate = Instances.MainWorld.ComponentTypes.GetComponentType("MHG.AndGate");
+ ComponentType xorGate = Instances.MainWorld.ComponentTypes.GetComponentType("MHG.XorGate");
+
+ foreach (WireAddress wireAddress in wires) {
+ Wire wire = Instances.MainWorld.Data.Lookup(wireAddress);
+ PegAddress nextPeg = wire.Point1 == _startPegAddress ? wire.Point2 : wire.Point1;
+ if (nextPeg.PegType != PegType.Input) {
+ // ignore
+ continue;
+ }
+
+ IComponentInWorld component = Instances.MainWorld.Data.Lookup(nextPeg.ComponentAddress);
+ ComponentType type = component.Data.Type;
+ if (type == andGate) {
+ _logger.Info($"Connected to AND gate");
+ } else if (type == xorGate) {
+ _logger.Info($"Connected to XOR gate");
+ } else {
+ _logger.Info($"Connected to unknown gate");
+ }
}
}
}
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/CriticalPathAnalyzerServer.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/CriticalPathAnalyzerServer.cs
new file mode 100644
index 0000000..6551dde
--- /dev/null
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/CriticalPathAnalyzerServer.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using CriticalPathAnalyzer.Server.Network;
+using CriticalPathAnalyzer.Shared.Packets.S2C;
+using EccsLogicWorldAPI.Server.Injectors;
+using EccsLogicWorldAPI.Shared.PacketWrapper;
+using LogicAPI.Data;
+using LogicAPI.Networking;
+using LogicAPI.Networking.Packets.Initialization;
+using LogicAPI.Server;
+using LogicAPI.Server.Networking;
+using LogicAPI.Server.Networking.ClientVerification;
+using LogicLog;
+using LogicWorld.Server;
+using LogicWorld.SharedCode.Networking;
+
+namespace CriticalPathAnalyzer.Server {
+ public class CriticalPathAnalyzerServer : ServerMod, IClientVerifier {
+ private const string ModId = "CriticalPathAnalyzer";
+ private const string ModVersion = "0.0.2";
+
+ private NetworkServer _networkServer;
+ private readonly Dictionary _playerHasWireTracer = new Dictionary();
+
+ public static ILogicLogger LoggerInstance;
+
+ protected override void Initialize() {
+ Logger.Info("CriticalPathAnalyzer server mod loading");
+ LoggerInstance = Logger;
+
+ _networkServer = Program.Get();
+ if (_networkServer == null) {
+ throw new Exception("Could not get Service 'NetworkServer'.");
+ }
+
+ // Inject verifier:
+ RawJoinVerifierInjector.addVerifier(this);
+ PacketHandlerManager.getCustomPacketHandler()
+ .addHandlerToEnd(new ClientJoinedPacketHandler(this));
+ RawPacketHandlerInjector.addPacketHandler(new CriticalPathAnalyzerRequestHandler(this));
+ }
+
+ public void Verify(VerificationContext ctx) {
+ bool hasMod = ctx.ApprovalPacket.ClientMods.Contains(ModId);
+ string playerName = ctx.PlayerID.Name;
+ _playerHasWireTracer[playerName] = hasMod;
+ LoggerInstance.Info($"Verifying player {playerName}: hasMod={hasMod}");
+ }
+
+ public void PlayerJoined(PlayerData playerData, HandlerContext context) {
+ _playerHasWireTracer.TryGetValue(playerData.Name, out bool hasWireTracer);
+ if (hasWireTracer) {
+ _networkServer.Send(context.Sender, new AnnounceModPresence() {
+ Version = ModVersion
+ });
+ }
+ }
+
+ public void AnalyzePath(Connection sender, Guid packetRequestGuid, PegAddress start, PegAddress end) {
+ LoggerInstance.Info("Got AnalyzePath request");
+ AnalyzePathResponse response = new AnalyzePathResponse() {
+ RequestGuid = packetRequestGuid,
+ Message = "Lmao Yeet",
+ };
+ _networkServer.Send(sender, response);
+ }
+ }
+}
\ No newline at end of file
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/network/AnalyzePathRequestHandler.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/network/AnalyzePathRequestHandler.cs
new file mode 100644
index 0000000..1a33936
--- /dev/null
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/network/AnalyzePathRequestHandler.cs
@@ -0,0 +1,16 @@
+using CriticalPathAnalyzer.Shared.Packets.C2S;
+using LogicWorld.SharedCode.Networking;
+
+namespace CriticalPathAnalyzer.Server.Network {
+ public class CriticalPathAnalyzerRequestHandler : PacketHandler {
+ private readonly CriticalPathAnalyzerServer _criticalPathAnalyzerServer;
+ public CriticalPathAnalyzerRequestHandler(CriticalPathAnalyzerServer criticalPathAnalyzerServer) {
+ _criticalPathAnalyzerServer = criticalPathAnalyzerServer;
+ }
+
+ public override void Handle(AnalyzePathRequest packet, HandlerContext context) {
+ _criticalPathAnalyzerServer.AnalyzePath(context.Sender, packet.RequestGuid, packet.StartPegAddress,
+ packet.EndPegAddress);
+ }
+ }
+}
\ No newline at end of file
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/network/ClientJoinedPacketHandler.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/network/ClientJoinedPacketHandler.cs
new file mode 100644
index 0000000..26ba933
--- /dev/null
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/network/ClientJoinedPacketHandler.cs
@@ -0,0 +1,16 @@
+using EccsLogicWorldAPI.Shared.PacketWrapper;
+using LogicAPI.Networking.Packets.Initialization;
+using LogicWorld.SharedCode.Networking;
+
+namespace CriticalPathAnalyzer.Server.Network {
+ public class ClientJoinedPacketHandler : CustomPacketHandler {
+ private readonly CriticalPathAnalyzerServer _criticalPathAnalyzerServer;
+ public ClientJoinedPacketHandler(CriticalPathAnalyzerServer criticalPathAnalyzerServer) {
+ _criticalPathAnalyzerServer = criticalPathAnalyzerServer;
+ }
+
+ public override void handle(ref bool isCancelled, ref ClientLoadedWorldPacket packet, HandlerContext context) {
+ _criticalPathAnalyzerServer.PlayerJoined(packet.PlayerData, context);
+ }
+ }
+}
\ No newline at end of file
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/c2s/AnalyzePathRequest.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/c2s/AnalyzePathRequest.cs
new file mode 100644
index 0000000..6e9a74c
--- /dev/null
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/c2s/AnalyzePathRequest.cs
@@ -0,0 +1,13 @@
+using System;
+using LogicAPI.Data;
+using LogicAPI.Networking.Packets;
+using MessagePack;
+
+namespace CriticalPathAnalyzer.Shared.Packets.C2S {
+ [MessagePackObject]
+ public class AnalyzePathRequest : Packet {
+ [Key(0)] public Guid RequestGuid;
+ [Key(1)] public PegAddress StartPegAddress;
+ [Key(2)] public PegAddress EndPegAddress;
+ }
+}
\ No newline at end of file
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs
new file mode 100644
index 0000000..102a753
--- /dev/null
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs
@@ -0,0 +1,11 @@
+using System;
+using LogicAPI.Networking.Packets;
+using MessagePack;
+
+namespace CriticalPathAnalyzer.Shared.Packets.S2C {
+ [MessagePackObject]
+ public class AnalyzePathResponse : Packet {
+ [Key(0)] public Guid RequestGuid;
+ [Key(1)] public string Message;
+ }
+}
\ No newline at end of file
diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnnounceModPresence.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnnounceModPresence.cs
new file mode 100644
index 0000000..ad53635
--- /dev/null
+++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnnounceModPresence.cs
@@ -0,0 +1,9 @@
+using LogicAPI.Networking.Packets;
+using MessagePack;
+
+namespace CriticalPathAnalyzer.Shared.Packets.S2C {
+ [MessagePackObject]
+ public class AnnounceModPresence : Packet {
+ [Key(0)] public string Version;
+ }
+}
\ No newline at end of file