CLre/CLre_server/API/Tools/NetServerListener.cs

101 lines
3.5 KiB
C#

using System.Reflection;
using System.Text;
using GameNetworkLayer.Shared;
using HarmonyLib;
using Svelto.DataStructures;
using Svelto.DataStructures.Experimental;
namespace CLre_server.API.Tools
{
public class NetServerListener
{
internal static bool isEnabled = false;
private static FasterDictionary<short, FasterList<NetReceiveMessageCallback>> callbacks = new FasterDictionary<short,FasterList<NetReceiveMessageCallback>>();
public delegate void NetReceiveMessageCallback(NetworkDispatcherCode code, byte[] data, int playerId);
public static void Enable()
{
isEnabled = true;
}
public static void Disable()
{
isEnabled = false;
}
public static void DebugReceiveMessage(NetworkDispatcherCode code, NetReceiveMessageCallback callback)
{
short key = (short)code;
if (callbacks.TryGetValue(key, out FasterList<NetReceiveMessageCallback> handlers))
{
handlers.Add(callback);
}
else
{
FasterList<NetReceiveMessageCallback> newHandlers = new FasterList<NetReceiveMessageCallback>(new [] {callback});
callbacks.Add(key, newHandlers);
}
}
internal static bool RunDebugCallbacks(NetworkDispatcherCode code, byte[] data, int playerId)
{
short key = (short)code;
if (callbacks.TryGetValue(key, out FasterList<NetReceiveMessageCallback> handlers))
{
foreach (NetReceiveMessageCallback callback in handlers)
{
callback(code, data, playerId);
}
return true;
}
else
{
return false;
}
}
public static void Log(NetworkDispatcherCode code, byte[] data, int playerId)
{
StringBuilder sb = new StringBuilder("Received ");
sb.Append(code.ToString());
sb.Append(" for player #");
sb.Append(playerId);
sb.Append(": 0x");
foreach (byte b in data)
{
sb.Append(b.ToString("X"));
}
Utility.Logging.Log(sb.ToString());
}
}
[HarmonyPatch]
class NetMessageClientListener_HandleAllMessages_Patch
{
[HarmonyPrefix]
public static void BeforeMethodCall(object ____deserializer, int playerId, object value)
{
if (!NetServerListener.isEnabled) return;
// TODO optimize this to not use Traverse
Traverse result = Traverse.Create(____deserializer).Method("Deserialize", value);
NetworkDispatcherCode code = result.Field<NetworkDispatcherCode>("dispatcherCode").Value;
byte[] data = result.Field<byte[]>("bytes").Value;
if (data == null)
{
Utility.Logging.LogWarning("Network message data was deserialized as null");
return;
}
bool isHandled = NetServerListener.RunDebugCallbacks(code, data, playerId);
if (!isHandled) Utility.Logging.Log($"Received network message for player {playerId} (code: {code.ToString()}, len: {data.Length})");
}
[HarmonyTargetMethod]
public static MethodBase Target()
{
return AccessTools.Method("GameNetworkLayer.Server.NetMessageServerListener:HandleAllMessages");
}
}
}