Implement networking API functionality
This commit is contained in:
parent
8b470aa690
commit
6db837b11a
24 changed files with 1147 additions and 10 deletions
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
using User;
|
||||
|
||||
namespace CLre.API.App
|
||||
{
|
||||
|
@ -54,6 +55,12 @@ namespace CLre.API.App
|
|||
remove => GameFrameworkEngine.gameFrameworkExit += value;
|
||||
}
|
||||
|
||||
public static event EventHandler<GameJoin> GameJoin
|
||||
{
|
||||
add => ClientGameJoinSequence_OnUserValidated_Patch.gameJoin += value;
|
||||
remove => ClientGameJoinSequence_OnUserValidated_Patch.gameJoin += value;
|
||||
}
|
||||
|
||||
public static string Version
|
||||
{
|
||||
get => Game.Utilities.VersionReader.GetVersion();
|
||||
|
@ -114,4 +121,27 @@ namespace CLre.API.App
|
|||
return AccessTools.Method("FrontEnd.FrontEndGuiEngine:SetMainMenuEnabled");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO patch OnUserValidationFailed as well
|
||||
[HarmonyPatch]
|
||||
class ClientGameJoinSequence_OnUserValidated_Patch
|
||||
{
|
||||
internal static event EventHandler<GameJoin> gameJoin;
|
||||
|
||||
[HarmonyPostfix]
|
||||
public static void AfterMethodCall(object __instance, ref SerializedAccountInfo validated)
|
||||
{
|
||||
if (gameJoin != null) gameJoin(__instance, new GameJoin
|
||||
{
|
||||
Success = true,
|
||||
Data = validated,
|
||||
});
|
||||
}
|
||||
|
||||
[HarmonyTargetMethod]
|
||||
public static MethodBase Target()
|
||||
{
|
||||
return AccessTools.Method("MultiplayerClient.ClientGameJoinSequence:OnUserValidated");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
using User;
|
||||
|
||||
namespace CLre.API.App
|
||||
{
|
||||
|
||||
|
@ -8,4 +10,10 @@ namespace CLre.API.App
|
|||
public struct GameExit{}
|
||||
|
||||
public struct MenuReady{}
|
||||
|
||||
public struct GameJoin
|
||||
{
|
||||
public bool Success;
|
||||
public SerializedAccountInfo Data;
|
||||
}
|
||||
}
|
83
CLre/API/Synergy/ClientHandshakeEngine.cs
Normal file
83
CLre/API/Synergy/ClientHandshakeEngine.cs
Normal file
|
@ -0,0 +1,83 @@
|
|||
using System.Collections;
|
||||
using CLre.API.Engines;
|
||||
using GameNetworkLayer.Shared;
|
||||
using HarmonyLib;
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace CLre.API.Synergy
|
||||
{
|
||||
public class ClientHandshakeEngine : GameObsoleteEnginePreBuild
|
||||
{
|
||||
internal static ClientHandshakeEngine Instance = null;
|
||||
|
||||
internal const NetworkDispatcherCode CLre_HANDSHAKE_NETCODE = (NetworkDispatcherCode) 218;
|
||||
|
||||
private Utility.Reflection.INetMsgClientSender_SendMessage<SerializedCLreHandshake> _sendMessage;
|
||||
|
||||
private Utility.Reflection.INetMsgClientListener_RegisterListener<SerializedCLreHandshake> _registerListener;
|
||||
|
||||
public override void Ready()
|
||||
{
|
||||
//Utility.Logging.MetaLog("Building send message delegate");
|
||||
_sendMessage =
|
||||
Utility.Reflection.MethodAsDelegate<Utility.Reflection.INetMsgClientSender_SendMessage<SerializedCLreHandshake>>(
|
||||
"GameNetworkLayer.Client.NetMessageClientSender:SendMessage",
|
||||
generics: new [] {typeof(SerializedCLreHandshake)},
|
||||
instance: MainLevel_BuildClasses_Patch.netMessageSender);
|
||||
|
||||
//Utility.Logging.MetaLog("Building register listener delegate");
|
||||
_registerListener =
|
||||
Utility.Reflection.MethodAsDelegate<Utility.Reflection.INetMsgClientListener_RegisterListener<SerializedCLreHandshake>>(
|
||||
"GameNetworkLayer.Client.NetMessageClientListener:RegisterListener",
|
||||
generics: new [] {typeof(SerializedCLreHandshake)},
|
||||
instance: MainLevel_BuildClasses_Patch.netMessageListener);
|
||||
_registerListener(CLre_HANDSHAKE_NETCODE, OnHandshakeReceived);
|
||||
}
|
||||
|
||||
public void OnHandshakeReceived(ref SerializedCLreHandshake p)
|
||||
{
|
||||
// TODO validate handshake msg
|
||||
Utility.Logging.MetaLog($"Received CLre handshake! {p}");
|
||||
}
|
||||
|
||||
public override IEntitiesDB entitiesDB { get; set; }
|
||||
public override IEntityFactory entityFactory { get; set; }
|
||||
|
||||
public IEnumerator Sender(SerializedCLreHandshake payload)
|
||||
{
|
||||
yield return null;
|
||||
Utility.Logging.MetaLog("Sending Client CLre handshake");
|
||||
_sendMessage(CLre_HANDSHAKE_NETCODE, ref payload);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
Instance = new ClientHandshakeEngine();
|
||||
}
|
||||
|
||||
public ClientHandshakeEngine(): base()
|
||||
{
|
||||
App.Client.GameJoin += (_, __) =>
|
||||
{
|
||||
SerializedCLreHandshake payload = SerializedCLreHandshake.Current();
|
||||
Sender(payload).Run();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(GameFramework.MainLevel), "BuildClasses")]
|
||||
class MainLevel_BuildClasses_Patch
|
||||
{
|
||||
internal static object netMessageListener;
|
||||
|
||||
internal static object netMessageSender;
|
||||
|
||||
[HarmonyPostfix]
|
||||
public static void AfterMethodCall(object ____netMessageListener, object ____netMessageSender)
|
||||
{
|
||||
netMessageListener = ____netMessageListener;
|
||||
netMessageSender = ____netMessageSender;
|
||||
}
|
||||
}
|
||||
}
|
94
CLre/API/Synergy/ClientMessagingEngine.cs
Normal file
94
CLre/API/Synergy/ClientMessagingEngine.cs
Normal file
|
@ -0,0 +1,94 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using GameNetworkLayer.Shared;
|
||||
using Svelto.Context;
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace CLre.API.Synergy
|
||||
{
|
||||
class ClientMessagingEngine: Engines.GameObsoleteEnginePostBuild, IWaitForFrameworkDestruction, IWaitForFrameworkInitialization
|
||||
{
|
||||
private struct MessageQueueItem
|
||||
{
|
||||
public SerializedCLreMessage msg;
|
||||
public NetworkDispatcherCode code;
|
||||
}
|
||||
|
||||
private Utility.Reflection.INetMsgClientSender_SendMessage<SerializedCLreMessage> _sendMessage;
|
||||
|
||||
private Utility.Reflection.INetMsgClientListener_RegisterListener<SerializedCLreMessage> _registerListener;
|
||||
|
||||
private Queue<MessageQueueItem> _messageQueue = new Queue<MessageQueueItem>(10);
|
||||
|
||||
private bool _isRunning = false;
|
||||
|
||||
public override void Ready()
|
||||
{
|
||||
//Utility.Logging.MetaLog("Building send message delegate");
|
||||
_sendMessage =
|
||||
Utility.Reflection.MethodAsDelegate<Utility.Reflection.INetMsgClientSender_SendMessage<SerializedCLreMessage>>(
|
||||
"GameNetworkLayer.Client.NetMessageClientSender:SendMessage",
|
||||
generics: new [] {typeof(SerializedCLreMessage)},
|
||||
instance: MainLevel_BuildClasses_Patch.netMessageSender);
|
||||
|
||||
//Utility.Logging.MetaLog("Building register listener delegate");
|
||||
_registerListener =
|
||||
Utility.Reflection.MethodAsDelegate<Utility.Reflection.INetMsgClientListener_RegisterListener<SerializedCLreMessage>>(
|
||||
"GameNetworkLayer.Client.NetMessageClientListener:RegisterListener",
|
||||
generics: new [] {typeof(SerializedCLreMessage)},
|
||||
instance: MainLevel_BuildClasses_Patch.netMessageListener);
|
||||
_registerListener(Message.CLre_MESSAGE_NETCODE, OnMessageReceived);
|
||||
}
|
||||
|
||||
private void OnMessageReceived(ref SerializedCLreMessage data)
|
||||
{
|
||||
Message.HandleMessageReceive(ref data);
|
||||
}
|
||||
|
||||
internal void EnqueueMessage(ref SerializedCLreMessage msg)
|
||||
{
|
||||
_messageQueue.Enqueue(new MessageQueueItem
|
||||
{
|
||||
msg = msg,
|
||||
code = Message.CLre_MESSAGE_NETCODE,
|
||||
});
|
||||
}
|
||||
|
||||
public override IEntitiesDB entitiesDB { get; set; }
|
||||
public override IEntityFactory entityFactory { get; set; }
|
||||
|
||||
public ClientMessagingEngine(): base()
|
||||
{
|
||||
App.Client.GameJoin += (_, __) => { MessageSender().Run(); };
|
||||
}
|
||||
|
||||
public IEnumerator MessageSender()
|
||||
{
|
||||
while (!_isRunning)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
while (_isRunning)
|
||||
{
|
||||
while (_messageQueue.Count != 0)
|
||||
{
|
||||
MessageQueueItem item = _messageQueue.Dequeue();
|
||||
API.Utility.Logging.MetaLog($"Sending message with id {item.msg.Id}");
|
||||
_sendMessage(item.code, ref item.msg);
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnFrameworkDestroyed()
|
||||
{
|
||||
_isRunning = false;
|
||||
}
|
||||
|
||||
public void OnFrameworkInitialized()
|
||||
{
|
||||
_isRunning = true;
|
||||
}
|
||||
}
|
||||
}
|
51
CLre/API/Synergy/Message.cs
Normal file
51
CLre/API/Synergy/Message.cs
Normal file
|
@ -0,0 +1,51 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using GameNetworkLayer.Shared;
|
||||
|
||||
namespace CLre.API.Synergy
|
||||
{
|
||||
public static class Message
|
||||
{
|
||||
internal const NetworkDispatcherCode CLre_MESSAGE_NETCODE = (NetworkDispatcherCode) 219;
|
||||
|
||||
private static readonly Dictionary<uint, Action<ReceiveMessageArgs>> handlers =
|
||||
new Dictionary<uint, Action<ReceiveMessageArgs>>();
|
||||
|
||||
private static readonly ClientMessagingEngine msgEngine = new ClientMessagingEngine();
|
||||
|
||||
public static void SendCLreMessage(ref SerializedCLreMessage message)
|
||||
{
|
||||
msgEngine.EnqueueMessage(ref message);
|
||||
}
|
||||
|
||||
public static void RegisterListener(uint id, Action<ReceiveMessageArgs> handler)
|
||||
{
|
||||
if (handlers.TryGetValue(id, out Action<ReceiveMessageArgs> existing))
|
||||
{
|
||||
existing += handler;
|
||||
handlers[id] = existing;
|
||||
}
|
||||
else
|
||||
{
|
||||
handlers[id] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void HandleMessageReceive(ref SerializedCLreMessage msg)
|
||||
{
|
||||
ReceiveMessageArgs payload = new ReceiveMessageArgs
|
||||
{
|
||||
Message = msg,
|
||||
};
|
||||
if (handlers.TryGetValue(msg.Id, out Action<ReceiveMessageArgs> h))
|
||||
{
|
||||
h(payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct ReceiveMessageArgs
|
||||
{
|
||||
public SerializedCLreMessage Message;
|
||||
}
|
||||
}
|
161
CLre/API/Synergy/SerializedCLreHandshake.cs
Normal file
161
CLre/API/Synergy/SerializedCLreHandshake.cs
Normal file
|
@ -0,0 +1,161 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NetworkFramework.Shared;
|
||||
|
||||
namespace CLre.API.Synergy
|
||||
{
|
||||
public struct SerializedCLreHandshake: ISerializedNetData
|
||||
{
|
||||
private byte major;
|
||||
private byte minor;
|
||||
private byte patch;
|
||||
|
||||
private HandshakeFlag flags;
|
||||
|
||||
private List<string> modInfo;
|
||||
|
||||
public Version Version
|
||||
{
|
||||
get => new Version(major, minor, patch);
|
||||
set
|
||||
{
|
||||
major = (byte)value.Major;
|
||||
minor = (byte)value.Minor;
|
||||
patch = (byte)value.Build;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> Mods
|
||||
{
|
||||
get => modInfo.ToArray();
|
||||
set
|
||||
{
|
||||
modInfo.Clear();
|
||||
foreach (var mod in value)
|
||||
{
|
||||
modInfo.Add(mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Serialize()
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
using (BinaryWriter writer = new BinaryWriter(stream))
|
||||
{
|
||||
// version
|
||||
writer.Write(major);
|
||||
writer.Write(minor);
|
||||
writer.Write(patch);
|
||||
writer.Write((uint)flags);
|
||||
writer.Write(modInfo.Count);
|
||||
foreach (string mod in modInfo)
|
||||
{
|
||||
writer.Write(mod);
|
||||
}
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Deserialize(byte[] data)
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryReader reader = new BinaryReader(stream))
|
||||
{
|
||||
// version
|
||||
major = reader.ReadByte();
|
||||
minor = reader.ReadByte();
|
||||
patch = reader.ReadByte();
|
||||
flags = (HandshakeFlag) reader.ReadUInt32();
|
||||
int modCount = reader.ReadInt32();
|
||||
modInfo = new List<string>(modCount);
|
||||
for (int i = 0; i < modCount; i++)
|
||||
{
|
||||
modInfo.Add(reader.ReadString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasFlag(HandshakeFlag f)
|
||||
{
|
||||
return (flags & f) != HandshakeFlag.None;
|
||||
}
|
||||
|
||||
public void SetFlag(HandshakeFlag f)
|
||||
{
|
||||
flags |= f;
|
||||
}
|
||||
|
||||
public void UnsetFlag(HandshakeFlag f)
|
||||
{
|
||||
flags &= ~f;
|
||||
}
|
||||
|
||||
public static SerializedCLreHandshake Current()
|
||||
{
|
||||
Version v = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
List<string> mods = new List<string>();
|
||||
foreach (var plugin in IllusionInjector.PluginManager.Plugins)
|
||||
{
|
||||
mods.Add(plugin.Name);
|
||||
}
|
||||
|
||||
return new SerializedCLreHandshake
|
||||
{
|
||||
major = (byte) v.Major,
|
||||
minor = (byte) v.Minor,
|
||||
patch = (byte) v.Build,
|
||||
flags = HandshakeFlag.Client,
|
||||
modInfo = mods,
|
||||
};
|
||||
}
|
||||
|
||||
public static SerializedCLreHandshake RequireCLre()
|
||||
{
|
||||
Version v = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
List<string> mods = new List<string>(new []{Assembly.GetExecutingAssembly().GetName().Name});
|
||||
|
||||
return new SerializedCLreHandshake
|
||||
{
|
||||
major = (byte) v.Major,
|
||||
minor = (byte) v.Minor,
|
||||
patch = (byte) v.Build,
|
||||
flags = HandshakeFlag.Client | HandshakeFlag.RequireAll,
|
||||
modInfo = mods,
|
||||
};
|
||||
}
|
||||
|
||||
public static SerializedCLreHandshake Empty()
|
||||
{
|
||||
return new SerializedCLreHandshake
|
||||
{
|
||||
major = 0,
|
||||
minor = 0,
|
||||
patch = 0,
|
||||
modInfo = new List<string>(),
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"CLre {Version} ({modInfo.Count} mods)";
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum HandshakeFlag : uint
|
||||
{
|
||||
None = 0,
|
||||
Client = 1,
|
||||
Server = 1 << 1,
|
||||
RequireAll = 1 << 2,
|
||||
OptionalAll = 1 << 3,
|
||||
Confirm = 1 << 4,
|
||||
}
|
||||
}
|
44
CLre/API/Synergy/SerializedCLreMessage.cs
Normal file
44
CLre/API/Synergy/SerializedCLreMessage.cs
Normal file
|
@ -0,0 +1,44 @@
|
|||
using System.IO;
|
||||
using NetworkFramework.Shared;
|
||||
|
||||
namespace CLre.API.Synergy
|
||||
{
|
||||
public struct SerializedCLreMessage: ISerializedNetData
|
||||
{
|
||||
public uint Id;
|
||||
public byte[] Data;
|
||||
|
||||
public byte[] Serialize()
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
using (BinaryWriter writer = new BinaryWriter(stream))
|
||||
{
|
||||
writer.Write(Id);
|
||||
writer.Write(Data.Length);
|
||||
foreach (byte b in Data)
|
||||
{
|
||||
writer.Write(b);
|
||||
}
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Deserialize(byte[] data)
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryReader reader = new BinaryReader(stream))
|
||||
{
|
||||
Id = reader.ReadUInt32();
|
||||
Data = new byte[reader.ReadInt32()];
|
||||
for (int i = 0; i < Data.Length; i++)
|
||||
{
|
||||
Data[i] = reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -98,13 +98,23 @@ namespace CLre.API.Tools
|
|||
{
|
||||
//Utility.Logging.Log($"Sending ISerializedNetData {data.GetType().FullName} (code: {code.ToString()})");
|
||||
Traverse d = Traverse.Create(data);
|
||||
StringBuilder sb = new StringBuilder($"Sending ISerializedNetData {data.GetType().FullName} (code: {code.ToString()})");
|
||||
string codeName = (short) code > 217 ? "CUSTOM" : code.ToString();
|
||||
StringBuilder sb = new StringBuilder($"Sending ISerializedNetData {data.GetType().FullName} (code: {codeName} {(short)code})");
|
||||
foreach (string fieldName in d.Fields())
|
||||
{
|
||||
Traverse field = d.Field(fieldName);
|
||||
sb.Append("\n");
|
||||
sb.Append("\"");
|
||||
sb.Append(fieldName.Substring(fieldName.IndexOf('<')+1, fieldName.LastIndexOf('>')-1));
|
||||
int start = fieldName.IndexOf('<');
|
||||
int len = fieldName.LastIndexOf('>');
|
||||
if (start != -1 && len > 0)
|
||||
{
|
||||
sb.Append(fieldName.Substring(start+1, len-1));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(fieldName);
|
||||
}
|
||||
sb.Append("\": ");
|
||||
sb.Append(field.GetValue());
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using GameNetworkLayer.Client;
|
||||
using GameNetworkLayer.Shared;
|
||||
using HarmonyLib;
|
||||
using NetworkFramework.Shared;
|
||||
|
@ -29,6 +30,10 @@ namespace CLre.API.Utility
|
|||
|
||||
public delegate object[] SendMessage<T>(NetworkDispatcherCode dispatcherCode, ref T value) where T : struct, ISerializedNetData;
|
||||
|
||||
public delegate void INetMsgClientSender_SendMessage<T>(NetworkDispatcherCode code, ref T value) where T : struct, ISerializedNetData;
|
||||
|
||||
public delegate void INetMsgClientListener_RegisterListener<T>(NetworkDispatcherCode code, NetCBClient<T> proc) where T: struct, ISerializedNetData;
|
||||
|
||||
// useful reflection functions
|
||||
public static TFuncProto BuildDelegate<TFuncProto>(MethodInfo method) where TFuncProto : Delegate
|
||||
{
|
||||
|
|
17
CLre/CLre.cs
17
CLre/CLre.cs
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Text;
|
||||
using CLre.API.Characters;
|
||||
using CLre.API.Synergy;
|
||||
using CLre.API.Tools;
|
||||
using GameNetworkLayer.Shared;
|
||||
using HarmonyLib;
|
||||
|
@ -51,6 +52,9 @@ namespace CLre
|
|||
Fixes.MiniScreenHelper.Init();
|
||||
Fixes.UnderStructureCollider.Init();
|
||||
|
||||
// API init
|
||||
API.Synergy.ClientHandshakeEngine.Init();
|
||||
|
||||
// misc
|
||||
LogIPAPlugins();
|
||||
Fixes.BugfixAttributeUtility.LogBugfixes();
|
||||
|
@ -72,9 +76,22 @@ namespace CLre
|
|||
NetClientSender.GetLogMethod(netData));
|
||||
API.Utility.Logging.MetaLog("Patched SendMessage<Shared.Inventory.HandheldEquipmentRequest>");
|
||||
|
||||
netData = typeof(API.Synergy.SerializedCLreHandshake);
|
||||
NetClientSender.DebugSendMessage(netData, harmonyInstance,
|
||||
NetClientSender.GetLogMethod(netData));
|
||||
API.Utility.Logging.MetaLog("Patched SendMessage<SerializedCLreHandshake>");
|
||||
|
||||
NetClientListener.DebugReceiveMessage(NetworkDispatcherCode.EACMessageServerToClient,
|
||||
NetClientListener.Log);
|
||||
|
||||
NetClientListener.DebugReceiveMessage(API.Synergy.ClientHandshakeEngine.CLre_HANDSHAKE_NETCODE,
|
||||
NetClientListener.Log);
|
||||
|
||||
NetClientListener.DebugReceiveMessage(NetworkDispatcherCode.SendIsPvEToClient,
|
||||
NetClientListener.Log);
|
||||
|
||||
API.Utility.Logging.MetaLog($"Highest NetworkDispatcherCode number is {(int) NetworkDispatcherCode.StructureDestroyed} damn it Photon");
|
||||
|
||||
// API debug and testing
|
||||
API.App.Client.InitComplete += (_, __) =>
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Version>0.0.2</Version>
|
||||
<Version>0.0.3</Version>
|
||||
<Authors>NGnius</Authors>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://git.exmods.org/NGnius/CLre</PackageProjectUrl>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using GameNetworkLayer.Shared;
|
||||
using GameServer;
|
||||
using HarmonyLib;
|
||||
using NetworkFramework.Server;
|
||||
using Svelto.Context;
|
||||
|
||||
namespace CLre_server.API.MainServer
|
||||
|
@ -46,6 +48,24 @@ namespace CLre_server.API.MainServer
|
|||
remove => ServerReadyEngine.serverFrameworkDestroyed -= value;
|
||||
}
|
||||
|
||||
public event EventHandler<StartedEventArgs> Connected
|
||||
{
|
||||
add => PhotonNetwork_ConnectUsingSettings_Patch.postConnect += value;
|
||||
remove => PhotonNetwork_ConnectUsingSettings_Patch.postConnect -= value;
|
||||
}
|
||||
|
||||
public event EventHandler<PlayerConnectArgs> PlayerConnect
|
||||
{
|
||||
add => MainGameServer_SetupContainer_Patch.playerConnected += value;
|
||||
remove => MainGameServer_SetupContainer_Patch.playerConnected -= value;
|
||||
}
|
||||
|
||||
public event EventHandler<PlayerConnectArgs> PlayerDisconnect
|
||||
{
|
||||
add => MainGameServer_SetupContainer_Patch.playerDisconnected += value;
|
||||
remove => MainGameServer_SetupContainer_Patch.playerDisconnected -= value;
|
||||
}
|
||||
|
||||
// properties
|
||||
|
||||
public GameServerSettings GameServerSettings
|
||||
|
@ -73,6 +93,9 @@ namespace CLre_server.API.MainServer
|
|||
[HarmonyPostfix]
|
||||
public static void AfterMethodCall(GameServerSettings ____gameServerSettings)
|
||||
{
|
||||
#if DEBUG
|
||||
Utility.Logging.MetaLog("Got GameServerSettings");
|
||||
#endif
|
||||
_gameServerSettings = ____gameServerSettings;
|
||||
}
|
||||
|
||||
|
@ -144,4 +167,38 @@ namespace CLre_server.API.MainServer
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(GameServer.GameFramework.MainGameServer), "SetupContainer")]
|
||||
class MainGameServer_SetupContainer_Patch
|
||||
{
|
||||
internal static event EventHandler<PlayerConnectArgs> playerConnected;
|
||||
|
||||
internal static event EventHandler<PlayerConnectArgs> playerDisconnected;
|
||||
|
||||
private static GameServer.GameFramework.MainGameServer mgs = null;
|
||||
|
||||
[HarmonyPostfix]
|
||||
public static void AfterMethodCall(GameServer.GameFramework.MainGameServer __instance, ref IPlayerConnectedCallbacks ____playerConnectedCallbacks)
|
||||
{
|
||||
mgs = __instance;
|
||||
____playerConnectedCallbacks.OnPlayerConnected += OnConnect;
|
||||
____playerConnectedCallbacks.OnPlayerDisconnected += OnDisconnect;
|
||||
}
|
||||
|
||||
public static void OnConnect(int playerId)
|
||||
{
|
||||
if (playerConnected != null) playerConnected(mgs, new PlayerConnectArgs
|
||||
{
|
||||
PlayerId = playerId,
|
||||
});
|
||||
}
|
||||
|
||||
public static void OnDisconnect(int playerId)
|
||||
{
|
||||
if (playerDisconnected != null) playerDisconnected(mgs, new PlayerConnectArgs
|
||||
{
|
||||
PlayerId = playerId,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using CLre_server.API.Engines;
|
||||
using Game.DataLoader;
|
||||
using GameServer;
|
||||
|
@ -22,8 +23,8 @@ namespace CLre_server.API.MainServer
|
|||
{
|
||||
photonVersion = PhotonNetwork.gameVersion,
|
||||
photonRegion = PhotonNetwork.CloudRegion,
|
||||
gameGuid = gss.GetGameGuid(),
|
||||
worldName = gss.GetWorldName(),
|
||||
gameGuid = gss == null ? "" : gss.GetGameGuid(),
|
||||
worldName = gss == null ? "" : gss.GetWorldName(),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -37,8 +38,8 @@ namespace CLre_server.API.MainServer
|
|||
{
|
||||
photonVersion = PhotonNetwork.gameVersion,
|
||||
photonRegion = PhotonNetwork.CloudRegion,
|
||||
gameGuid = gss.GetGameGuid(),
|
||||
worldName = gss.GetWorldName(),
|
||||
gameGuid = gss == null ? "" : gss.GetGameGuid(),
|
||||
worldName = gss == null ? "" : gss.GetWorldName(),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -11,4 +11,9 @@ namespace CLre_server.API.MainServer
|
|||
}
|
||||
|
||||
public struct StopEventArgs{}
|
||||
|
||||
public struct PlayerConnectArgs
|
||||
{
|
||||
public int PlayerId;
|
||||
}
|
||||
}
|
95
CLre_server/API/MainServer/UserVerification.cs
Normal file
95
CLre_server/API/MainServer/UserVerification.cs
Normal file
|
@ -0,0 +1,95 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using GameNetworkLayer.Shared;
|
||||
using HarmonyLib;
|
||||
using Svelto.Context;
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace CLre_server.API.MainServer
|
||||
{
|
||||
public class UserVerification
|
||||
{
|
||||
public static UserVerification Instance { get; internal set; }
|
||||
|
||||
private delegate void DisconnectPlayer_VerificationFailedProto(int playerId, string error);
|
||||
private delegate void DisconnectPlayerProto(int playerId, NetworkDispatcherCode code);
|
||||
|
||||
private readonly DisconnectPlayer_VerificationFailedProto _disconnectPlayerVerificationFailed;
|
||||
private readonly DisconnectPlayerProto _disconnectPlayer;
|
||||
|
||||
// This doesn't seem to do actually generate a popup, but it will stop the player from loading in
|
||||
/*public void DisconnectPlayer_VerificationFailed(int playerId, string error)
|
||||
{
|
||||
_disconnectPlayerVerificationFailed(playerId, error);
|
||||
}*/
|
||||
|
||||
public void DisconnectPlayer(int playerId, NetworkDispatcherCode code = NetworkDispatcherCode.ModVerificationFail)
|
||||
{
|
||||
_disconnectPlayer(playerId, code);
|
||||
}
|
||||
|
||||
internal UserVerification(IQueryingEntitiesEngine uvs)
|
||||
{
|
||||
Type uvsType = AccessTools.TypeByName("User.Server.UserVerificationServer");
|
||||
_disconnectPlayerVerificationFailed =
|
||||
Utility.Reflection.MethodAsDelegate<DisconnectPlayer_VerificationFailedProto>(uvsType,
|
||||
"DisconnectPlayer_VerificationFailed",
|
||||
//parameters: new [] {typeof(int), typeof(string)},
|
||||
instance: uvs);
|
||||
|
||||
_disconnectPlayer =
|
||||
Utility.Reflection.MethodAsDelegate<DisconnectPlayerProto>(uvsType, "DisconnectPlayer", instance: uvs);
|
||||
}
|
||||
}
|
||||
|
||||
// This seems to think that __instance is always simply a System.Object (caused by Harmony?), which doesn't work
|
||||
/*[HarmonyPatch]
|
||||
class UserVerificationServer_Constructor_Patch
|
||||
{
|
||||
|
||||
private static IQueryingEntitiesEngine uvs = null;
|
||||
|
||||
[HarmonyPrefix]
|
||||
public static void BeforeMethodCall()
|
||||
{
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
public static void AfterMethodCall(IQueryingEntitiesEngine __instance)
|
||||
{
|
||||
uvs = __instance;
|
||||
UserVerification.Instance = new UserVerification(__instance);
|
||||
}
|
||||
|
||||
[HarmonyTargetMethod]
|
||||
public static MethodBase Target()
|
||||
{
|
||||
return AccessTools.Constructor(AccessTools.TypeByName("User.Server.UserVerificationServer"));
|
||||
}
|
||||
}*/
|
||||
|
||||
[HarmonyPatch]
|
||||
class MainGameServer_CreatePlayerDisconnectionSequence_Patch
|
||||
{
|
||||
|
||||
private static IQueryingEntitiesEngine uvs = null;
|
||||
|
||||
[HarmonyPrefix]
|
||||
public static void BeforeMethodCall()
|
||||
{
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
public static void AfterMethodCall(IQueryingEntitiesEngine userVerificationEng)
|
||||
{
|
||||
uvs = userVerificationEng;
|
||||
UserVerification.Instance = new UserVerification(userVerificationEng);
|
||||
}
|
||||
|
||||
[HarmonyTargetMethod]
|
||||
public static MethodBase Target()
|
||||
{
|
||||
return AccessTools.Method("GameServer.GameFramework.MainGameServer:CreatePlayerDisconnectionSequence");
|
||||
}
|
||||
}
|
||||
}
|
68
CLre_server/API/Synergy/Message.cs
Normal file
68
CLre_server/API/Synergy/Message.cs
Normal file
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using GameNetworkLayer.Shared;
|
||||
|
||||
namespace CLre_server.API.Synergy
|
||||
{
|
||||
public static class Message
|
||||
{
|
||||
internal const NetworkDispatcherCode CLre_MESSAGE_NETCODE = (NetworkDispatcherCode) 219;
|
||||
|
||||
private static readonly Dictionary<uint, Action<ReceiveMessageArgs>> handlers =
|
||||
new Dictionary<uint, Action<ReceiveMessageArgs>>();
|
||||
|
||||
private static readonly ServerMessagingEngine msgEngine = new ServerMessagingEngine();
|
||||
|
||||
private static readonly List<int> clrePlayers = new List<int>();
|
||||
|
||||
public static void SendToAllCLreClients(ref SerializedCLreMessage message)
|
||||
{
|
||||
foreach (var playerId in clrePlayers)
|
||||
{
|
||||
SendCLreMessage(playerId, ref message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SendCLreMessage(int playerId, ref SerializedCLreMessage message)
|
||||
{
|
||||
msgEngine.EnqueueMessage(playerId, ref message);
|
||||
}
|
||||
|
||||
public static void RegisterListener(uint id, Action<ReceiveMessageArgs> handler)
|
||||
{
|
||||
if (handlers.TryGetValue(id, out Action<ReceiveMessageArgs> existing))
|
||||
{
|
||||
existing += handler;
|
||||
handlers[id] = existing;
|
||||
}
|
||||
else
|
||||
{
|
||||
handlers[id] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void HandleMessageReceive(int playerId, ref SerializedCLreMessage msg)
|
||||
{
|
||||
ReceiveMessageArgs payload = new ReceiveMessageArgs
|
||||
{
|
||||
Message = msg,
|
||||
PlayerId = playerId,
|
||||
};
|
||||
if (handlers.TryGetValue(msg.Id, out Action<ReceiveMessageArgs> h))
|
||||
{
|
||||
h(payload);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void RegisterCLreClient(int playerId)
|
||||
{
|
||||
clrePlayers.Add(playerId);
|
||||
}
|
||||
}
|
||||
|
||||
public struct ReceiveMessageArgs
|
||||
{
|
||||
public SerializedCLreMessage Message;
|
||||
public int PlayerId;
|
||||
}
|
||||
}
|
161
CLre_server/API/Synergy/SerializedCLreHandshake.cs
Normal file
161
CLre_server/API/Synergy/SerializedCLreHandshake.cs
Normal file
|
@ -0,0 +1,161 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using NetworkFramework.Shared;
|
||||
|
||||
namespace CLre_server.API.Synergy
|
||||
{
|
||||
struct SerializedCLreHandshake: ISerializedNetData
|
||||
{
|
||||
private byte major;
|
||||
private byte minor;
|
||||
private byte patch;
|
||||
|
||||
private HandshakeFlag flags;
|
||||
|
||||
private List<string> modInfo;
|
||||
|
||||
public Version Version
|
||||
{
|
||||
get => new Version(major, minor, patch);
|
||||
set
|
||||
{
|
||||
major = (byte)value.Major;
|
||||
minor = (byte)value.Minor;
|
||||
patch = (byte)value.Build;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> Mods
|
||||
{
|
||||
get => modInfo.ToArray();
|
||||
set
|
||||
{
|
||||
modInfo.Clear();
|
||||
foreach (var mod in value)
|
||||
{
|
||||
modInfo.Add(mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Serialize()
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
using (BinaryWriter writer = new BinaryWriter(stream))
|
||||
{
|
||||
// version
|
||||
writer.Write(major);
|
||||
writer.Write(minor);
|
||||
writer.Write(patch);
|
||||
writer.Write((uint)flags);
|
||||
writer.Write(modInfo.Count);
|
||||
foreach (string mod in modInfo)
|
||||
{
|
||||
writer.Write(mod);
|
||||
}
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Deserialize(byte[] data)
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryReader reader = new BinaryReader(stream))
|
||||
{
|
||||
// version
|
||||
major = reader.ReadByte();
|
||||
minor = reader.ReadByte();
|
||||
patch = reader.ReadByte();
|
||||
flags = (HandshakeFlag) reader.ReadUInt32();
|
||||
int modCount = reader.ReadInt32();
|
||||
modInfo = new List<string>(modCount);
|
||||
for (int i = 0; i < modCount; i++)
|
||||
{
|
||||
modInfo.Add(reader.ReadString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasFlag(HandshakeFlag f)
|
||||
{
|
||||
return (flags & f) != HandshakeFlag.None;
|
||||
}
|
||||
|
||||
public void SetFlag(HandshakeFlag f)
|
||||
{
|
||||
flags |= f;
|
||||
}
|
||||
|
||||
public void UnsetFlag(HandshakeFlag f)
|
||||
{
|
||||
flags &= ~f;
|
||||
}
|
||||
|
||||
public static SerializedCLreHandshake Current()
|
||||
{
|
||||
Version v = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
List<string> mods = new List<string>();
|
||||
foreach (var plugin in IllusionInjector.PluginManager.Plugins)
|
||||
{
|
||||
mods.Add(plugin.Name);
|
||||
}
|
||||
|
||||
return new SerializedCLreHandshake
|
||||
{
|
||||
major = (byte) v.Major,
|
||||
minor = (byte) v.Minor,
|
||||
patch = (byte) v.Build,
|
||||
flags = HandshakeFlag.Server,
|
||||
modInfo = mods,
|
||||
};
|
||||
}
|
||||
|
||||
public static SerializedCLreHandshake RequireCLre()
|
||||
{
|
||||
Version v = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
List<string> mods = new List<string>(new []{Assembly.GetExecutingAssembly().GetName().Name});
|
||||
|
||||
return new SerializedCLreHandshake
|
||||
{
|
||||
major = (byte) v.Major,
|
||||
minor = (byte) v.Minor,
|
||||
patch = (byte) v.Build,
|
||||
flags = HandshakeFlag.Client | HandshakeFlag.RequireAll,
|
||||
modInfo = mods,
|
||||
};
|
||||
}
|
||||
|
||||
public static SerializedCLreHandshake Empty()
|
||||
{
|
||||
return new SerializedCLreHandshake
|
||||
{
|
||||
major = 0,
|
||||
minor = 0,
|
||||
patch = 0,
|
||||
modInfo = new List<string>(),
|
||||
};
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"CLre {Version} ({modInfo.Count} mods)";
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum HandshakeFlag : uint
|
||||
{
|
||||
None = 0,
|
||||
Client = 1,
|
||||
Server = 1 << 1,
|
||||
RequireAll = 1 << 2,
|
||||
OptionalAll = 1 << 3,
|
||||
Confirm = 1 << 4,
|
||||
}
|
||||
}
|
44
CLre_server/API/Synergy/SerializedCLreMessage.cs
Normal file
44
CLre_server/API/Synergy/SerializedCLreMessage.cs
Normal file
|
@ -0,0 +1,44 @@
|
|||
using System.IO;
|
||||
using NetworkFramework.Shared;
|
||||
|
||||
namespace CLre_server.API.Synergy
|
||||
{
|
||||
public struct SerializedCLreMessage: ISerializedNetData
|
||||
{
|
||||
public uint Id;
|
||||
public byte[] Data;
|
||||
|
||||
public byte[] Serialize()
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
using (BinaryWriter writer = new BinaryWriter(stream))
|
||||
{
|
||||
writer.Write(Id);
|
||||
writer.Write(Data.Length);
|
||||
foreach (byte b in Data)
|
||||
{
|
||||
writer.Write(b);
|
||||
}
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Deserialize(byte[] data)
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream(data))
|
||||
{
|
||||
using (BinaryReader reader = new BinaryReader(stream))
|
||||
{
|
||||
Id = reader.ReadUInt32();
|
||||
Data = new byte[reader.ReadInt32()];
|
||||
for (int i = 0; i < Data.Length; i++)
|
||||
{
|
||||
Data[i] = reader.ReadByte();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
78
CLre_server/API/Synergy/ServerHandshakeEngine.cs
Normal file
78
CLre_server/API/Synergy/ServerHandshakeEngine.cs
Normal file
|
@ -0,0 +1,78 @@
|
|||
using System.Collections;
|
||||
using GameNetworkLayer.Shared;
|
||||
using HarmonyLib;
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace CLre_server.API.Synergy
|
||||
{
|
||||
class ServerHandshakeEngine : Engines.ServerEnginePreBuild
|
||||
{
|
||||
internal static ServerHandshakeEngine Instance = null;
|
||||
|
||||
internal const NetworkDispatcherCode CLre_HANDSHAKE_NETCODE = (NetworkDispatcherCode) 218;
|
||||
|
||||
private Utility.Reflection.INetMsgServerSender_SendMessage<SerializedCLreHandshake> _sendMessage;
|
||||
|
||||
private Utility.Reflection.INetMsgServerListener_RegisterListener<SerializedCLreHandshake> _registerListener;
|
||||
|
||||
public override void Ready()
|
||||
{
|
||||
Utility.Logging.MetaLog("Building send message delegate");
|
||||
_sendMessage =
|
||||
Utility.Reflection.MethodAsDelegate<Utility.Reflection.INetMsgServerSender_SendMessage<SerializedCLreHandshake>>(
|
||||
"GameNetworkLayer.Server.NetMessageServerSender:SendMessage",
|
||||
generics: new [] {typeof(SerializedCLreHandshake)},
|
||||
instance: MainGameServer_SetupContainer_Patch.netMessageSender);
|
||||
|
||||
Utility.Logging.MetaLog("Building register listener delegate");
|
||||
_registerListener =
|
||||
Utility.Reflection.MethodAsDelegate<Utility.Reflection.INetMsgServerListener_RegisterListener<SerializedCLreHandshake>>(
|
||||
"GameNetworkLayer.Server.NetMessageServerListener:RegisterListener",
|
||||
generics: new [] {typeof(SerializedCLreHandshake)},
|
||||
instance: MainGameServer_SetupContainer_Patch.netMessageListener);
|
||||
_registerListener(CLre_HANDSHAKE_NETCODE, OnHandshakeReceived);
|
||||
}
|
||||
|
||||
public void OnHandshakeReceived(int playerId, ref SerializedCLreHandshake p)
|
||||
{
|
||||
// TODO validate handshake msg
|
||||
Utility.Logging.MetaLog($"Received CLre handshake from player {playerId}! {p}");
|
||||
Message.RegisterCLreClient(playerId);
|
||||
SerializedCLreHandshake payload = SerializedCLreHandshake.Current();
|
||||
payload.SetFlag(HandshakeFlag.Confirm);
|
||||
Sender(payload, playerId).Run();
|
||||
}
|
||||
|
||||
public override IEntitiesDB entitiesDB { get; set; }
|
||||
public override IEntityFactory entityFactory { get; set; }
|
||||
|
||||
public IEnumerator Sender(SerializedCLreHandshake payload, int playerId)
|
||||
{
|
||||
yield return null;
|
||||
Utility.Logging.MetaLog("Sending Server CLre handshake");
|
||||
_sendMessage(CLre_HANDSHAKE_NETCODE, ref payload, playerId);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
internal static void Init()
|
||||
{
|
||||
Instance = new ServerHandshakeEngine();
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(GameServer.GameFramework.MainGameServer), "SetupContainer")]
|
||||
class MainGameServer_SetupContainer_Patch
|
||||
{
|
||||
internal static object netMessageListener;
|
||||
|
||||
internal static object netMessageSender;
|
||||
|
||||
[HarmonyPostfix]
|
||||
public static void AfterMethodCall(object ____netMessageListener, object ____netMessageSender)
|
||||
{
|
||||
Utility.Logging.MetaLog($"Got NetMessage objects");
|
||||
netMessageListener = ____netMessageListener;
|
||||
netMessageSender = ____netMessageSender;
|
||||
}
|
||||
}
|
||||
}
|
96
CLre_server/API/Synergy/ServerMessagingEngine.cs
Normal file
96
CLre_server/API/Synergy/ServerMessagingEngine.cs
Normal file
|
@ -0,0 +1,96 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using GameNetworkLayer.Shared;
|
||||
using Svelto.Context;
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace CLre_server.API.Synergy
|
||||
{
|
||||
class ServerMessagingEngine: Engines.ServerEnginePreBuild, IWaitForFrameworkDestruction, IWaitForFrameworkInitialization
|
||||
{
|
||||
private struct MessageQueueItem
|
||||
{
|
||||
public SerializedCLreMessage msg;
|
||||
public int playerId;
|
||||
public NetworkDispatcherCode code;
|
||||
}
|
||||
|
||||
private Utility.Reflection.INetMsgServerSender_SendMessage<SerializedCLreMessage> _sendMessage;
|
||||
|
||||
private Utility.Reflection.INetMsgServerListener_RegisterListener<SerializedCLreMessage> _registerListener;
|
||||
|
||||
private Queue<MessageQueueItem> _messageQueue = new Queue<MessageQueueItem>(10);
|
||||
|
||||
private bool _isRunning = false;
|
||||
|
||||
public override void Ready()
|
||||
{
|
||||
//Utility.Logging.MetaLog("Building send message delegate");
|
||||
_sendMessage =
|
||||
Utility.Reflection.MethodAsDelegate<Utility.Reflection.INetMsgServerSender_SendMessage<SerializedCLreMessage>>(
|
||||
"GameNetworkLayer.Server.NetMessageServerSender:SendMessage",
|
||||
generics: new [] {typeof(SerializedCLreMessage)},
|
||||
instance: MainGameServer_SetupContainer_Patch.netMessageSender);
|
||||
|
||||
//Utility.Logging.MetaLog("Building register listener delegate");
|
||||
_registerListener =
|
||||
Utility.Reflection.MethodAsDelegate<Utility.Reflection.INetMsgServerListener_RegisterListener<SerializedCLreMessage>>(
|
||||
"GameNetworkLayer.Server.NetMessageServerListener:RegisterListener",
|
||||
generics: new [] {typeof(SerializedCLreMessage)},
|
||||
instance: MainGameServer_SetupContainer_Patch.netMessageListener);
|
||||
_registerListener(Message.CLre_MESSAGE_NETCODE, OnMessageReceived);
|
||||
}
|
||||
|
||||
private void OnMessageReceived(int playerId, ref SerializedCLreMessage data)
|
||||
{
|
||||
Message.HandleMessageReceive(playerId, ref data);
|
||||
}
|
||||
|
||||
internal void EnqueueMessage(int playerId, ref SerializedCLreMessage msg)
|
||||
{
|
||||
_messageQueue.Enqueue(new MessageQueueItem
|
||||
{
|
||||
msg = msg,
|
||||
playerId = playerId,
|
||||
code = Message.CLre_MESSAGE_NETCODE,
|
||||
});
|
||||
}
|
||||
|
||||
public override IEntitiesDB entitiesDB { get; set; }
|
||||
public override IEntityFactory entityFactory { get; set; }
|
||||
|
||||
public ServerMessagingEngine(): base()
|
||||
{
|
||||
MainServer.Server.Instance.Connected += (_, __) => { MessageSender().Run(); };
|
||||
}
|
||||
|
||||
public IEnumerator MessageSender()
|
||||
{
|
||||
while (!_isRunning)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
while (_isRunning)
|
||||
{
|
||||
while (_messageQueue.Count != 0)
|
||||
{
|
||||
MessageQueueItem item = _messageQueue.Dequeue();
|
||||
API.Utility.Logging.MetaLog($"Sending message with id {item.msg.Id}");
|
||||
_sendMessage(item.code, ref item.msg, item.playerId);
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnFrameworkDestroyed()
|
||||
{
|
||||
_isRunning = false;
|
||||
}
|
||||
|
||||
public void OnFrameworkInitialized()
|
||||
{
|
||||
_isRunning = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -98,13 +98,23 @@ namespace CLre_server.API.Tools
|
|||
{
|
||||
//Utility.Logging.Log($"Sending ISerializedNetData {data.GetType().FullName} (code: {code.ToString()})");
|
||||
Traverse d = Traverse.Create(data);
|
||||
StringBuilder sb = new StringBuilder($"Sending ISerializedNetData {data.GetType().FullName} (code: {code.ToString()})");
|
||||
string codeName = (short) code > 217 ? "CUSTOM" : code.ToString();
|
||||
StringBuilder sb = new StringBuilder($"Sending ISerializedNetData {data.GetType().FullName} (code: {codeName} {(short)code})");
|
||||
foreach (string fieldName in d.Fields())
|
||||
{
|
||||
Traverse field = d.Field(fieldName);
|
||||
sb.Append("\n");
|
||||
sb.Append("\"");
|
||||
sb.Append(fieldName.Substring(fieldName.IndexOf('<')+1, fieldName.LastIndexOf('>')-1));
|
||||
int start = fieldName.IndexOf('<');
|
||||
int len = fieldName.LastIndexOf('>');
|
||||
if (start != -1 && len > 0)
|
||||
{
|
||||
sb.Append(fieldName.Substring(start+1, len-1));
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(fieldName);
|
||||
}
|
||||
sb.Append("\": ");
|
||||
sb.Append(field.GetValue());
|
||||
}
|
||||
|
|
|
@ -29,6 +29,11 @@ namespace CLre_server.API.Utility
|
|||
|
||||
public delegate object[] SendMessage<T>(NetworkDispatcherCode dispatcherCode, ref T value) where T : struct, ISerializedNetData;
|
||||
|
||||
public delegate void INetMsgServerSender_SendMessage<T>(NetworkDispatcherCode code, ref T value, int playerId) where T : struct, ISerializedNetData;
|
||||
|
||||
public delegate void INetMsgServerListener_RegisterListener<T>(NetworkDispatcherCode code, NetCBServer<T> proc) where T: struct, ISerializedNetData;
|
||||
|
||||
|
||||
// useful reflection functions
|
||||
public static TFuncProto BuildDelegate<TFuncProto>(MethodInfo method) where TFuncProto : Delegate
|
||||
{
|
||||
|
|
|
@ -44,6 +44,9 @@ namespace CLre_server
|
|||
// patches for bugs
|
||||
Fixes.InitLogSooner.Init();
|
||||
|
||||
// API init
|
||||
API.Synergy.ServerHandshakeEngine.Init();
|
||||
|
||||
// misc
|
||||
LogIPAPlugins(); // log plugins again so they show up in the log, and not just stdout
|
||||
Fixes.BugfixAttributeUtility.LogBugfixes(); // log bugfixes that are applied
|
||||
|
@ -60,9 +63,20 @@ namespace CLre_server
|
|||
NetServerSender.GetLogMethod(netData));
|
||||
API.Utility.Logging.MetaLog("Patched SendMessage<Shared.Inventory.HandheldEquipmentRequest>");
|
||||
|
||||
netData = typeof(API.Synergy.SerializedCLreHandshake);
|
||||
NetServerSender.DebugSendMessage(netData, harmonyInstance,
|
||||
NetServerSender.GetLogMethod(netData));
|
||||
API.Utility.Logging.MetaLog("Patched SendMessage<SerializedCLreHandshake>");
|
||||
|
||||
NetServerListener.DebugReceiveMessage(NetworkDispatcherCode.EACMessageServerToClient,
|
||||
NetServerListener.Log);
|
||||
|
||||
NetServerListener.DebugReceiveMessage(NetworkDispatcherCode.SendIsPvEToClient,
|
||||
NetServerListener.Log);
|
||||
|
||||
NetServerListener.DebugReceiveMessage(API.Synergy.ServerHandshakeEngine.CLre_HANDSHAKE_NETCODE,
|
||||
NetServerListener.Log);
|
||||
|
||||
// API debug and testing
|
||||
API.MainServer.Server.Instance.FrameworkReady += (_, __) => API.Utility.Logging.MetaLog("(!) Server framework ready for business");
|
||||
API.MainServer.Server.Instance.FrameworkExit += (_, __) => API.Utility.Logging.MetaLog("(!) Server framework shutting down"); // this seems to never happen
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Version>0.0.2</Version>
|
||||
<Version>0.0.3</Version>
|
||||
<Authors>NGnius</Authors>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://git.exmods.org/NGnius/CLre</PackageProjectUrl>
|
||||
|
|
Loading…
Reference in a new issue