From bc74dcd6ee8b9990633083042d6e47b09879dc8e Mon Sep 17 00:00:00 2001 From: D4VID Date: Sun, 16 Feb 2025 19:15:00 +0100 Subject: [PATCH] Exchange packets between server and client --- CriticalPathAnalyzer.sln.DotSettings.user | 2 + .../CriticalPathAnalyzer.csproj | 12 ++++ .../CriticalPathAnalyzer/OnlyServerMod | 0 .../CriticalPathAnalyzer/manifest.jecs | 2 +- .../src/client/CriticalPathAnalyzerClient.cs | 49 ++++++++----- .../client/CriticalPathAnalyzerGameState.cs | 2 +- .../network/AnalyzePathResponseHandler.cs | 10 +++ .../network/AnnounceModPacketHandler.cs | 10 +++ .../client/tool/CriticalPathAnalyzerTool.cs | 56 ++++++++++++++- .../src/server/CriticalPathAnalyzerServer.cs | 69 +++++++++++++++++++ .../network/AnalyzePathRequestHandler.cs | 16 +++++ .../network/ClientJoinedPacketHandler.cs | 16 +++++ .../shared/packets/c2s/AnalyzePathRequest.cs | 13 ++++ .../shared/packets/s2c/AnalyzePathResponse.cs | 11 +++ .../shared/packets/s2c/AnnounceModPresence.cs | 9 +++ 15 files changed, 253 insertions(+), 24 deletions(-) create mode 100644 CriticalPathAnalyzer.sln.DotSettings.user create mode 100644 CriticalPathAnalyzer/CriticalPathAnalyzer/OnlyServerMod create mode 100644 CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/network/AnalyzePathResponseHandler.cs create mode 100644 CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/network/AnnounceModPacketHandler.cs create mode 100644 CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/CriticalPathAnalyzerServer.cs create mode 100644 CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/network/AnalyzePathRequestHandler.cs create mode 100644 CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/network/ClientJoinedPacketHandler.cs create mode 100644 CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/c2s/AnalyzePathRequest.cs create mode 100644 CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs create mode 100644 CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnnounceModPresence.cs 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