Compare commits

...

2 Commits

@ -3,6 +3,7 @@ using CriticalPathAnalyzer.Client.Network;
using CriticalPathAnalyzer.Client.Tool; using CriticalPathAnalyzer.Client.Tool;
using CriticalPathAnalyzer.Shared.Packets.S2C; using CriticalPathAnalyzer.Shared.Packets.S2C;
using EccsLogicWorldAPI.Client.Injectors; using EccsLogicWorldAPI.Client.Injectors;
using EccsLogicWorldAPI.Client.PacketIndexOrdering;
using FancyInput; using FancyInput;
using LogicAPI.Client; using LogicAPI.Client;
using LogicLog; using LogicLog;
@ -33,9 +34,11 @@ namespace CriticalPathAnalyzer.Client {
} }
); );
// Inject packet handlers // Register a handler for the server response packet
RawPacketHandlerInjector.addPacketHandler(new AnnounceModPacketHandler(Manifest.Version));
RawPacketHandlerInjector.addPacketHandler(new AnalyzePathResponseHandler()); RawPacketHandlerInjector.addPacketHandler(new AnalyzePathResponseHandler());
// Mark it as optional so that the game works even if the mod is not present on one end
PacketIndexOrdering.markModAsOptional(GetType().Assembly);
Logger.Info("CriticalPathAnalyzer mod loaded"); Logger.Info("CriticalPathAnalyzer mod loaded");
} }

@ -1,21 +0,0 @@
using System;
using CriticalPathAnalyzer.Shared.Packets.S2C;
using LogicWorld.SharedCode.Networking;
namespace CriticalPathAnalyzer.Client.Network {
public class AnnounceModPacketHandler : PacketHandler<AnnounceModPresence> {
private readonly Version _version;
public AnnounceModPacketHandler(Version version) {
_version = version;
}
public override void Handle(AnnounceModPresence packet, HandlerContext context) {
if (packet.Version == _version) {
CriticalPathAnalyzerClient.LoggerInstance.Info($"Mod is supported on the server: version={packet.Version}");
} else {
CriticalPathAnalyzerClient.LoggerInstance.Error($"Mod version mismatch: client={_version}, server={packet.Version}");
}
}
}
}

@ -1,6 +1,7 @@
using System; using System;
using CriticalPathAnalyzer.Shared.Packets.C2S; using CriticalPathAnalyzer.Shared.Packets.C2S;
using CriticalPathAnalyzer.Shared.Packets.S2C; using CriticalPathAnalyzer.Shared.Packets.S2C;
using EccsLogicWorldAPI.Client.PacketIndexOrdering;
using JimmysUnityUtilities; using JimmysUnityUtilities;
using LogicAPI.Data; using LogicAPI.Data;
using LogicLog; using LogicLog;
@ -20,8 +21,8 @@ namespace CriticalPathAnalyzer.Client.Tool {
private static AnalyzePathResponse _response; private static AnalyzePathResponse _response;
private static Node _selectedNode; private static Node _selectedNode;
private static readonly OutlineData StartOutline = new OutlineData(new Color24(0x00ff00)); private static readonly OutlineData startOutline = new OutlineData(new Color24(0x00ff00));
private static readonly OutlineData EndOutline = new OutlineData(new Color24(0x00aaff)); private static readonly OutlineData endOutline = new OutlineData(new Color24(0x00aaff));
public static void Init(ILogicLogger logger) { public static void Init(ILogicLogger logger) {
_logger = logger; _logger = logger;
@ -75,7 +76,7 @@ namespace CriticalPathAnalyzer.Client.Tool {
PegAddress pegAddress = RayCastPeg(); PegAddress pegAddress = RayCastPeg();
if (!pegAddress.IsEmpty()) { if (!pegAddress.IsEmpty()) {
Outliner.RemoveOutline(_startPegAddress); Outliner.RemoveOutline(_startPegAddress);
Outliner.Outline(pegAddress, StartOutline); Outliner.Outline(pegAddress, startOutline);
_startPegAddress = pegAddress; _startPegAddress = pegAddress;
if (!_startPegAddress.IsEmpty() && !_endPegAddress.IsEmpty()) { if (!_startPegAddress.IsEmpty() && !_endPegAddress.IsEmpty()) {
CalculateCriticalPath(); CalculateCriticalPath();
@ -120,7 +121,7 @@ namespace CriticalPathAnalyzer.Client.Tool {
PegAddress pegAddress = RayCastPeg(); PegAddress pegAddress = RayCastPeg();
if (!pegAddress.IsEmpty()) { if (!pegAddress.IsEmpty()) {
Outliner.RemoveOutline(_endPegAddress); Outliner.RemoveOutline(_endPegAddress);
Outliner.Outline(pegAddress, EndOutline); Outliner.Outline(pegAddress, endOutline);
_endPegAddress = pegAddress; _endPegAddress = pegAddress;
if (!_startPegAddress.IsEmpty() && !_endPegAddress.IsEmpty()) { if (!_startPegAddress.IsEmpty() && !_endPegAddress.IsEmpty()) {
CalculateCriticalPath(); CalculateCriticalPath();
@ -136,6 +137,11 @@ namespace CriticalPathAnalyzer.Client.Tool {
_logger.Error("Invalid pegs"); _logger.Error("Invalid pegs");
return; return;
} }
if (!PacketIndexOrdering.doesServerSupportPacket(typeof(AnalyzePathRequest))) {
_logger.Error("Server doesn't support this mod");
return;
}
_currentRequestGuid = Guid.NewGuid(); _currentRequestGuid = Guid.NewGuid();
Instances.SendData.Send(new AnalyzePathRequest { Instances.SendData.Send(new AnalyzePathRequest {

@ -1,26 +1,20 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using CriticalPathAnalyzer.Server.Network; using CriticalPathAnalyzer.Server.Network;
using CriticalPathAnalyzer.Server.Tool; using CriticalPathAnalyzer.Server.Tool;
using CriticalPathAnalyzer.Shared.Packets.S2C; using CriticalPathAnalyzer.Shared.Packets.S2C;
using EccsLogicWorldAPI.Server; using EccsLogicWorldAPI.Server;
using EccsLogicWorldAPI.Server.Injectors; using EccsLogicWorldAPI.Server.Injectors;
using EccsLogicWorldAPI.Shared.PacketWrapper; using EccsLogicWorldAPI.Server.PacketIndexOrdering;
using LogicAPI.Data; using LogicAPI.Data;
using LogicAPI.Networking; using LogicAPI.Networking;
using LogicAPI.Networking.Packets.Initialization;
using LogicAPI.Server; using LogicAPI.Server;
using LogicAPI.Server.Networking; using LogicAPI.Server.Networking;
using LogicAPI.Server.Networking.ClientVerification;
using LogicLog; using LogicLog;
using LogicWorld.SharedCode.Networking;
namespace CriticalPathAnalyzer.Server { namespace CriticalPathAnalyzer.Server {
// ReSharper disable once ClassNeverInstantiated.Global // ReSharper disable once ClassNeverInstantiated.Global
public class CriticalPathAnalyzerServer : ServerMod, IClientVerifier { public class CriticalPathAnalyzerServer : ServerMod {
private NetworkServer _networkServer; private NetworkServer _networkServer;
private readonly Dictionary<string, bool> _playerHasWireTracer = new Dictionary<string, bool>();
public static ILogicLogger LoggerInstance; public static ILogicLogger LoggerInstance;
@ -33,35 +27,11 @@ namespace CriticalPathAnalyzer.Server {
throw new Exception("Could not get Service 'NetworkServer'."); throw new Exception("Could not get Service 'NetworkServer'.");
} }
// Inject client verifier: // Register a handler for the client request packet
RawJoinVerifierInjector.addVerifier(this);
PacketHandlerManager.getCustomPacketHandler<ClientLoadedWorldPacket>()
.addHandlerToEnd(new ClientJoinedPacketHandler(this));
RawPacketHandlerInjector.addPacketHandler(new CriticalPathAnalyzerRequestHandler(this)); RawPacketHandlerInjector.addPacketHandler(new CriticalPathAnalyzerRequestHandler(this));
}
// Mark it as optional so that the game works even if the mod is not present on one end
/// <summary> PacketIndexOrdering.markModAsOptional(GetType().Assembly);
/// Gets called before a player (client) joins the server.
/// Used to check if the player has this mod installed
/// </summary>
public void Verify(VerificationContext ctx) {
bool hasMod = ctx.ApprovalPacket.ClientMods.Contains((Manifest.ID, Manifest.Version));
string playerName = ctx.PlayerID.Name;
_playerHasWireTracer[playerName] = hasMod;
LoggerInstance.Info($"Verifying player {playerName}: hasMod={hasMod}");
}
/// <summary>
/// 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.
/// </summary>
public void PlayerJoined(PlayerData playerData, HandlerContext context) {
_playerHasWireTracer.TryGetValue(playerData.Name, out bool hasWireTracer);
if (hasWireTracer) {
_networkServer.Send(context.Sender, new AnnounceModPresence() {
Version = Manifest.Version
});
}
} }
/// <summary> /// <summary>

@ -1,16 +0,0 @@
using EccsLogicWorldAPI.Shared.PacketWrapper;
using LogicAPI.Networking.Packets.Initialization;
using LogicWorld.SharedCode.Networking;
namespace CriticalPathAnalyzer.Server.Network {
public class ClientJoinedPacketHandler : CustomPacketHandler<ClientLoadedWorldPacket> {
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);
}
}
}

@ -14,19 +14,19 @@ using LogicWorld.Server.Circuitry;
namespace CriticalPathAnalyzer.Server.Tool { namespace CriticalPathAnalyzer.Server.Tool {
public class ServerPathTracer { public class ServerPathTracer {
// Reflection/Delegate access helpers: // Reflection/Delegate access helpers:
private static readonly Func<InputPeg, Cluster> GetCluster; private static readonly Func<InputPeg, Cluster> getCluster;
// Services needed to lookup wires/pegs: // Services needed to lookup wires/pegs:
private static readonly ICircuitryManager Circuits; private static readonly ICircuitryManager circuits;
private static readonly IWorldData World; private static readonly IWorldData world;
static ServerPathTracer() { static ServerPathTracer() {
GetCluster = Delegator.createPropertyGetter<InputPeg, Cluster>( getCluster = Delegator.createPropertyGetter<InputPeg, Cluster>(
Properties.getPrivate(typeof(InputPeg), "Cluster") Properties.getPrivate(typeof(InputPeg), "Cluster")
); );
Circuits = ServiceGetter.getService<ICircuitryManager>(); circuits = ServiceGetter.getService<ICircuitryManager>();
World = ServiceGetter.getService<IWorldData>(); world = ServiceGetter.getService<IWorldData>();
} }
public static bool TracePath( public static bool TracePath(
@ -342,7 +342,7 @@ namespace CriticalPathAnalyzer.Server.Tool {
/// <param name="address">Address of the peg</param> /// <param name="address">Address of the peg</param>
/// <returns>True if it exists, false if it doesn't</returns> /// <returns>True if it exists, false if it doesn't</returns>
private static bool PegExists(PegAddress address) { private static bool PegExists(PegAddress address) {
IComponentInWorld component = World.Lookup(address.ComponentAddress); IComponentInWorld component = world.Lookup(address.ComponentAddress);
if (component == null) { if (component == null) {
return false; // Component of the peg does not exist in world. return false; // Component of the peg does not exist in world.
} }
@ -353,13 +353,13 @@ namespace CriticalPathAnalyzer.Server.Tool {
} }
private static Cluster GetClusterAt(InputAddress peg) { private static Cluster GetClusterAt(InputAddress peg) {
InputPeg originPeg = Circuits.LookupInput(peg); InputPeg originPeg = circuits.LookupInput(peg);
if (originPeg == null) { if (originPeg == null) {
throw new Exception( throw new Exception(
"Tried to lookup cluster on input peg, but the peg was not present in the circuit model! This should never happen, as the peg is present in the world."); "Tried to lookup cluster on input peg, but the peg was not present in the circuit model! This should never happen, as the peg is present in the world.");
} }
Cluster cluster = GetCluster(originPeg); Cluster cluster = getCluster(originPeg);
if (cluster == null) { if (cluster == null) {
throw new Exception( throw new Exception(
"Tried to lookup cluster on input peg, but the cluster was 'null', this should never happen! As the peg is present in the world."); "Tried to lookup cluster on input peg, but the cluster was 'null', this should never happen! As the peg is present in the world.");
@ -378,13 +378,13 @@ namespace CriticalPathAnalyzer.Server.Tool {
if (pegAddress.IsInputAddress(out InputAddress inputAddress)) { if (pegAddress.IsInputAddress(out InputAddress inputAddress)) {
primaryClusters.Add(GetClusterAt(inputAddress)); primaryClusters.Add(GetClusterAt(inputAddress));
} else { } else {
HashSet<WireAddress> wires = World.LookupPegWires(pegAddress); HashSet<WireAddress> wires = world.LookupPegWires(pegAddress);
if (wires == null) { if (wires == null) {
return; return;
} }
foreach (WireAddress wireAddress in wires) { foreach (WireAddress wireAddress in wires) {
Wire wire = World.Lookup(wireAddress); Wire wire = world.Lookup(wireAddress);
if (wire == null) { if (wire == null) {
throw new Exception( throw new Exception(
"Tried to lookup wire given its address, but the world did not contain it. World must be corrupted."); "Tried to lookup wire given its address, but the world did not contain it. World must be corrupted.");

@ -1,10 +0,0 @@
using System;
using LogicAPI.Networking.Packets;
using MessagePack;
namespace CriticalPathAnalyzer.Shared.Packets.S2C {
[MessagePackObject]
public class AnnounceModPresence : Packet {
[Key(0)] public Version Version;
}
}
Loading…
Cancel
Save