From 51e240a2a2e71db534155468c39ae53cf9c76e35 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Fri, 26 Nov 2021 15:45:19 +0000 Subject: [PATCH 1/8] aaaaa --- QSB.sln | 13 +- QuantumUNET/Components/QNetworkIdentity.cs | 128 +---- QuantumUNET/Components/QNetworkTransform.cs | 5 +- .../Components/QNetworkTransformChild.cs | 3 +- QuantumUNET/Messages/QMsgType.cs | 8 - QuantumUNET/Messages/QNetworkMessage.cs | 1 - QuantumUNET/QClientScene.cs | 52 --- QuantumUNET/QLocalClient.cs | 14 +- QuantumUNET/QNetworkBehaviour.cs | 440 +----------------- QuantumUNET/QNetworkClient.cs | 39 +- QuantumUNET/QNetworkConnection.cs | 102 +--- QuantumUNET/QNetworkServer.cs | 130 +----- QuantumUNET/QNetworkServerSimple.cs | 9 +- QuantumUNET/QULocalConnectionToClient.cs | 20 +- QuantumUNET/QULocalConnectionToServer.cs | 17 +- 15 files changed, 80 insertions(+), 901 deletions(-) diff --git a/QSB.sln b/QSB.sln index 7473e240..15709d10 100644 --- a/QSB.sln +++ b/QSB.sln @@ -1,19 +1,14 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29613.14 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QSB", "QSB\QSB.csproj", "{1F00090A-C697-4C55-B401-192F3CFB9DC2}" - ProjectSection(ProjectDependencies) = postProject - {E23551F3-C095-4F50-8BF7-85BB2661859B} = {E23551F3-C095-4F50-8BF7-85BB2661859B} - EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuantumUNET", "QuantumUNET\QuantumUNET.csproj", "{C8C53004-1508-4F86-A419-4292C188DC2A}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QSBTests", "QSBTests\QSBTests.csproj", "{2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QNetWeaver", "QNetWeaver\QNetWeaver.csproj", "{E23551F3-C095-4F50-8BF7-85BB2661859B}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2569F98D-F671-42AA-82DE-505B05CDCEF2}" ProjectSection(SolutionItems) = preProject .gitignore = .gitignore @@ -40,10 +35,6 @@ Global {2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}.Debug|Any CPU.Build.0 = Debug|Any CPU {2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}.Release|Any CPU.ActiveCfg = Release|Any CPU {2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}.Release|Any CPU.Build.0 = Release|Any CPU - {E23551F3-C095-4F50-8BF7-85BB2661859B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E23551F3-C095-4F50-8BF7-85BB2661859B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E23551F3-C095-4F50-8BF7-85BB2661859B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E23551F3-C095-4F50-8BF7-85BB2661859B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/QuantumUNET/Components/QNetworkIdentity.cs b/QuantumUNET/Components/QNetworkIdentity.cs index 08c4097f..080f2ae2 100644 --- a/QuantumUNET/Components/QNetworkIdentity.cs +++ b/QuantumUNET/Components/QNetworkIdentity.cs @@ -321,132 +321,6 @@ namespace QuantumUNET.Components } } - private bool GetInvokeComponent(int cmdHash, Type invokeClass, out QNetworkBehaviour invokeComponent) - { - QNetworkBehaviour networkBehaviour = null; - foreach (var networkBehaviour2 in m_NetworkBehaviours) - { - if (networkBehaviour2.GetType() == invokeClass || networkBehaviour2.GetType().IsSubclassOf(invokeClass)) - { - networkBehaviour = networkBehaviour2; - break; - } - } - - bool result; - if (networkBehaviour == null) - { - var cmdHashHandlerName = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); - QLog.FatalError( - $"Found no behaviour for incoming [{cmdHashHandlerName}] on {gameObject}, the server and client should have the same NetworkBehaviour instances [netId={NetId}]."); - invokeComponent = null; - result = false; - } - else - { - invokeComponent = networkBehaviour; - result = true; - } - - return result; - } - - internal void HandleSyncEvent(int cmdHash, QNetworkReader reader) - { - if (gameObject == null) - { - var cmdHashHandlerName = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); - QLog.Warning($"SyncEvent [{cmdHashHandlerName}] received for deleted object [netId={NetId}]"); - } - else if (!QNetworkBehaviour.GetInvokerForHashSyncEvent(cmdHash, out var invokeClass, out var cmdDelegate)) - { - var cmdHashHandlerName2 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); - QLog.FatalError( - $"Found no receiver for incoming [{cmdHashHandlerName2}] on {gameObject}, the server and client should have the same NetworkBehaviour instances [netId={NetId}]."); - } - else if (!GetInvokeComponent(cmdHash, invokeClass, out var obj)) - { - var cmdHashHandlerName3 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); - QLog.Warning($"SyncEvent [{cmdHashHandlerName3}] handler not found [netId={NetId}]"); - } - else - { - cmdDelegate(obj, reader); - } - } - - internal void HandleSyncList(int cmdHash, QNetworkReader reader) - { - if (gameObject == null) - { - var cmdHashHandlerName = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); - QLog.Warning($"SyncList [{cmdHashHandlerName}] received for deleted object [netId={NetId}]"); - } - else if (!QNetworkBehaviour.GetInvokerForHashSyncList(cmdHash, out var invokeClass, out var cmdDelegate)) - { - var cmdHashHandlerName2 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); - QLog.FatalError( - $"Found no receiver for incoming [{cmdHashHandlerName2}] on {gameObject}, the server and client should have the same NetworkBehaviour instances [netId={NetId}]."); - } - else if (!GetInvokeComponent(cmdHash, invokeClass, out var obj)) - { - var cmdHashHandlerName3 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); - QLog.Warning($"SyncList [{cmdHashHandlerName3}] handler not found [netId={NetId}]"); - } - else - { - cmdDelegate(obj, reader); - } - } - - internal void HandleCommand(int cmdHash, QNetworkReader reader) - { - if (gameObject == null) - { - var cmdHashHandlerName = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); - QLog.Warning($"Command [{cmdHashHandlerName}] received for deleted object [netId={NetId}]"); - } - else if (!QNetworkBehaviour.GetInvokerForHashCommand(cmdHash, out var invokeClass, out var cmdDelegate)) - { - var cmdHashHandlerName2 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); - QLog.FatalError( - $"Found no receiver for incoming [{cmdHashHandlerName2}] on {gameObject}, the server and client should have the same NetworkBehaviour instances [netId={NetId}]."); - } - else if (!GetInvokeComponent(cmdHash, invokeClass, out var obj)) - { - var cmdHashHandlerName3 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); - QLog.Warning($"Command [{cmdHashHandlerName3}] handler not found [netId={NetId}]"); - } - else - { - cmdDelegate(obj, reader); - } - } - - internal void HandleRPC(int cmdHash, QNetworkReader reader) - { - if (gameObject == null) - { - var cmdHashHandlerName = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); - QLog.Warning($"ClientRpc [{cmdHashHandlerName}] received for deleted object [netId={NetId}]"); - } - else if (!QNetworkBehaviour.GetInvokerForHashClientRpc(cmdHash, out var invokeClass, out var cmdDelegate)) - { - var cmdHashHandlerName2 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); - QLog.FatalError( - $"Found no receiver for incoming [{cmdHashHandlerName2}] on {gameObject}, the server and client should have the same NetworkBehaviour instances [netId={NetId}]."); - } - else if (!GetInvokeComponent(cmdHash, invokeClass, out var obj)) - { - var cmdHashHandlerName3 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); - QLog.Warning($"ClientRpc [{cmdHashHandlerName3}] handler not found [netId={NetId}]"); - } - else - { - cmdDelegate(obj, reader); - } - } - internal void UNetUpdate() { var num = 0U; @@ -496,7 +370,7 @@ namespace QuantumUNET.Components if (flag) { s_UpdateWriter.FinishMessage(); - QNetworkServer.SendWriterToReady(gameObject, s_UpdateWriter, j); + QNetworkServer.SendWriterToReady(gameObject, s_UpdateWriter); } } diff --git a/QuantumUNET/Components/QNetworkTransform.cs b/QuantumUNET/Components/QNetworkTransform.cs index 21cb794c..aa96caff 100644 --- a/QuantumUNET/Components/QNetworkTransform.cs +++ b/QuantumUNET/Components/QNetworkTransform.cs @@ -140,7 +140,7 @@ namespace QuantumUNET.Components _prevRotation = transform.rotation; _localTransformWriter.FinishMessage(); - QClientScene.readyConnection.SendWriter(_localTransformWriter, GetNetworkChannel()); + QClientScene.readyConnection.SendWriter(_localTransformWriter); } } @@ -200,9 +200,6 @@ namespace QuantumUNET.Components return rotation; } - public override int GetNetworkChannel() - => 1; - public override float GetNetworkSendInterval() => SendInterval; } diff --git a/QuantumUNET/Components/QNetworkTransformChild.cs b/QuantumUNET/Components/QNetworkTransformChild.cs index 79c7b1d9..dace4ee2 100644 --- a/QuantumUNET/Components/QNetworkTransformChild.cs +++ b/QuantumUNET/Components/QNetworkTransformChild.cs @@ -8,7 +8,6 @@ namespace QuantumUNET.Components { public class QNetworkTransformChild : QNetworkBehaviour { - public override int GetNetworkChannel() => 1; public override float GetNetworkSendInterval() => m_SendInterval; public Transform m_Target; public uint m_ChildIndex; @@ -246,7 +245,7 @@ namespace QuantumUNET.Components _prevPosition = m_Target.localPosition; _prevRotation = m_Target.localRotation; _localTransformWriter.FinishMessage(); - QClientScene.readyConnection.SendWriter(_localTransformWriter, GetNetworkChannel()); + QClientScene.readyConnection.SendWriter(_localTransformWriter); } } diff --git a/QuantumUNET/Messages/QMsgType.cs b/QuantumUNET/Messages/QMsgType.cs index e3e3b367..136142a1 100644 --- a/QuantumUNET/Messages/QMsgType.cs +++ b/QuantumUNET/Messages/QMsgType.cs @@ -24,14 +24,10 @@ } public const short ObjectDestroy = 1; - public const short Rpc = 2; public const short ObjectSpawn = 3; public const short Owner = 4; - public const short Command = 5; public const short LocalPlayerTransform = 6; - public const short SyncEvent = 7; public const short UpdateVars = 8; - public const short SyncList = 9; public const short ObjectSpawnScene = 10; public const short NetworkInfo = 11; public const short SpawnFinished = 12; @@ -69,14 +65,10 @@ internal static string[] msgLabels = { "none", "ObjectDestroy", - "Rpc", "ObjectSpawn", "Owner", - "Command", "LocalPlayerTransform", - "SyncEvent", "UpdateVars", - "SyncList", "ObjectSpawnScene", "NetworkInfo", "SpawnFinished", diff --git a/QuantumUNET/Messages/QNetworkMessage.cs b/QuantumUNET/Messages/QNetworkMessage.cs index e5dbc590..45bbdcc6 100644 --- a/QuantumUNET/Messages/QNetworkMessage.cs +++ b/QuantumUNET/Messages/QNetworkMessage.cs @@ -8,7 +8,6 @@ namespace QuantumUNET.Messages public short MsgType; public QNetworkConnection Connection; public QNetworkReader Reader; - public int ChannelId; public TMsg ReadMessage() where TMsg : QMessageBase, new() { diff --git a/QuantumUNET/QClientScene.cs b/QuantumUNET/QClientScene.cs index 02cf7148..eabb16e4 100644 --- a/QuantumUNET/QClientScene.cs +++ b/QuantumUNET/QClientScene.cs @@ -17,8 +17,6 @@ namespace QuantumUNET public static QNetworkConnection readyConnection { get; private set; } - public static int reconnectId { get; private set; } = -1; - public static Dictionary Objects => s_NetworkScene.localObjects; public static Dictionary Prefabs => QNetworkScene.guidToPrefab; @@ -34,7 +32,6 @@ namespace QuantumUNET readyConnection = null; ready = false; s_IsSpawnFinished = false; - reconnectId = -1; NetworkTransport.Shutdown(); NetworkTransport.Init(); } @@ -291,7 +288,6 @@ namespace QuantumUNET client.RegisterHandlerSafe(QMsgType.ObjectSpawn, OnObjectSpawn); client.RegisterHandlerSafe(QMsgType.Owner, OnOwnerMessage); client.RegisterHandlerSafe(QMsgType.UpdateVars, OnUpdateVarsMessage); - client.RegisterHandlerSafe(QMsgType.SyncList, OnSyncListMessage); client.RegisterHandlerSafe(QMsgType.ObjectSpawnScene, OnObjectSpawnScene); client.RegisterHandlerSafe(QMsgType.SpawnFinished, OnObjectSpawnFinished); client.RegisterHandlerSafe(QMsgType.ObjectHide, OnObjectDestroy); @@ -300,8 +296,6 @@ namespace QuantumUNET client.RegisterHandlerSafe(QMsgType.AnimationParameters, QNetworkAnimator.OnAnimationParametersClientMessage); } - client.RegisterHandlerSafe(QMsgType.Rpc, OnRPCMessage); - client.RegisterHandlerSafe(QMsgType.SyncEvent, OnSyncEventMessage); client.RegisterHandlerSafe(QMsgType.AnimationTrigger, QNetworkAnimator.OnAnimationTriggerClientMessage); } @@ -544,52 +538,6 @@ namespace QuantumUNET } } - private static void OnRPCMessage(QNetworkMessage netMsg) - { - var num = (int)netMsg.Reader.ReadPackedUInt32(); - var networkInstanceId = netMsg.Reader.ReadNetworkId(); - Debug.Log($"ClientScene::OnRPCMessage hash:{num} netId:{networkInstanceId}"); - if (s_NetworkScene.GetNetworkIdentity(networkInstanceId, out var networkIdentity)) - { - networkIdentity.HandleRPC(num, netMsg.Reader); - } - else - { - var cmdHashHandlerName = QNetworkBehaviour.GetCmdHashHandlerName(num); - Debug.LogWarningFormat("Could not find target object with netId:{0} for RPC call {1}", networkInstanceId, cmdHashHandlerName); - } - } - - private static void OnSyncEventMessage(QNetworkMessage netMsg) - { - var cmdHash = (int)netMsg.Reader.ReadPackedUInt32(); - var networkInstanceId = netMsg.Reader.ReadNetworkId(); - Debug.Log($"ClientScene::OnSyncEventMessage {networkInstanceId}"); - if (s_NetworkScene.GetNetworkIdentity(networkInstanceId, out var networkIdentity)) - { - networkIdentity.HandleSyncEvent(cmdHash, netMsg.Reader); - } - else - { - Debug.LogWarning($"Did not find target for SyncEvent message for {networkInstanceId}"); - } - } - - private static void OnSyncListMessage(QNetworkMessage netMsg) - { - var networkInstanceId = netMsg.Reader.ReadNetworkId(); - var cmdHash = (int)netMsg.Reader.ReadPackedUInt32(); - Debug.Log($"ClientScene::OnSyncListMessage {networkInstanceId}"); - if (s_NetworkScene.GetNetworkIdentity(networkInstanceId, out var networkIdentity)) - { - networkIdentity.HandleSyncList(cmdHash, netMsg.Reader); - } - else - { - Debug.LogWarning($"Did not find target for SyncList message for {networkInstanceId}"); - } - } - private static void OnClientAuthority(QNetworkMessage netMsg) { netMsg.ReadMessage(s_ClientAuthorityMessage); diff --git a/QuantumUNET/QLocalClient.cs b/QuantumUNET/QLocalClient.cs index 63882036..52214ae0 100644 --- a/QuantumUNET/QLocalClient.cs +++ b/QuantumUNET/QLocalClient.cs @@ -64,11 +64,10 @@ namespace QuantumUNET QClientScene.InternalAddPlayer(unetView, localPlayer.PlayerControllerId); } - private void PostInternalMessage(byte[] buffer, int channelId) + private void PostInternalMessage(byte[] buffer) { var item = m_FreeMessages.Count == 0 ? default : m_FreeMessages.Pop(); item.buffer = buffer; - item.channelId = channelId; m_InternalMsgs.Add(item); } @@ -77,7 +76,7 @@ namespace QuantumUNET var networkWriter = new QNetworkWriter(); networkWriter.StartMessage(msgType); networkWriter.FinishMessage(); - PostInternalMessage(networkWriter.AsArray(), 0); + PostInternalMessage(networkWriter.AsArray()); } private void ProcessInternalMessages() @@ -98,7 +97,6 @@ namespace QuantumUNET } s_InternalMessage.Reader.ReadInt16(); - s_InternalMessage.ChannelId = msg.channelId; s_InternalMessage.Connection = connection; s_InternalMessage.MsgType = s_InternalMessage.Reader.ReadInt16(); m_Connection.InvokeHandler(s_InternalMessage); @@ -117,16 +115,16 @@ namespace QuantumUNET } } - internal void InvokeHandlerOnClient(short msgType, QMessageBase msg, int channelId) + internal void InvokeHandlerOnClient(short msgType, QMessageBase msg) { var networkWriter = new QNetworkWriter(); networkWriter.StartMessage(msgType); msg.Serialize(networkWriter); networkWriter.FinishMessage(); - InvokeBytesOnClient(networkWriter.AsArray(), channelId); + InvokeBytesOnClient(networkWriter.AsArray()); } - internal void InvokeBytesOnClient(byte[] buffer, int channelId) => PostInternalMessage(buffer, channelId); + internal void InvokeBytesOnClient(byte[] buffer) => PostInternalMessage(buffer); private const int k_InitialFreeMessagePoolSize = 64; @@ -145,8 +143,6 @@ namespace QuantumUNET private struct InternalMsg { internal byte[] buffer; - - internal int channelId; } } } \ No newline at end of file diff --git a/QuantumUNET/QNetworkBehaviour.cs b/QuantumUNET/QNetworkBehaviour.cs index d3db0580..08bfc23d 100644 --- a/QuantumUNET/QNetworkBehaviour.cs +++ b/QuantumUNET/QNetworkBehaviour.cs @@ -67,428 +67,20 @@ namespace QuantumUNET { ClearAllDirtyBits(); writer.FinishMessage(); - QClientScene.readyConnection.SendWriter(writer, GetNetworkChannel()); + QClientScene.readyConnection.SendWriter(writer); } } - protected void SendCommandInternal(QNetworkWriter writer, int channelId, string cmdName) - { - if (!IsLocalPlayer && !HasAuthority) - { - QLog.Warning("Trying to send command for object without authority."); - } - else if (QClientScene.readyConnection == null) - { - QLog.Error($"Send command attempted with no client running [client={ConnectionToServer}]."); - } - else - { - writer.FinishMessage(); - QClientScene.readyConnection.SendWriter(writer, channelId); - } - } - - public virtual bool InvokeCommand(int cmdHash, QNetworkReader reader) => InvokeCommandDelegate(cmdHash, reader); - - protected void SendRPCInternal(QNetworkWriter writer, int channelId, string rpcName) - { - if (!IsServer) - { - QLog.Warning("ClientRpc call on un-spawned object"); - return; - } - - writer.FinishMessage(); - QNetworkServer.SendWriterToReady(gameObject, writer, channelId); - } - - protected void SendTargetRPCInternal(QNetworkConnection conn, QNetworkWriter writer, int channelId, string rpcName) - { - if (!IsServer) - { - QLog.Warning("TargetRpc call on un-spawned object"); - return; - } - - writer.FinishMessage(); - conn.SendWriter(writer, channelId); - } - - public virtual bool InvokeRPC(int cmdHash, QNetworkReader reader) => InvokeRpcDelegate(cmdHash, reader); - - protected void SendEventInternal(QNetworkWriter writer, int channelId, string eventName) + protected void SendEventInternal(QNetworkWriter writer, string eventName) { if (!QNetworkServer.active) { - QLog.Error($"Tried to send event {eventName} on channel {channelId} but QSBNetworkServer isn't active."); + QLog.Error($"Tried to send event {eventName} but QSBNetworkServer isn't active."); return; } writer.FinishMessage(); - QNetworkServer.SendWriterToReady(gameObject, writer, channelId); - } - - public virtual bool InvokeSyncEvent(int cmdHash, QNetworkReader reader) => InvokeSyncEventDelegate(cmdHash, reader); - - public virtual bool InvokeSyncList(int cmdHash, QNetworkReader reader) => InvokeSyncListDelegate(cmdHash, reader); - - protected static void RegisterCommandDelegate(Type invokeClass, int cmdHash, CmdDelegate func) - { - if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) - { - var invoker = new Invoker - { - invokeType = UNetInvokeType.Command, - invokeClass = invokeClass, - invokeFunction = func - }; - s_CmdHandlerDelegates[cmdHash] = invoker; - } - } - - protected static void RegisterRpcDelegate(Type invokeClass, int cmdHash, CmdDelegate func) - { - if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) - { - var invoker = new Invoker - { - invokeType = UNetInvokeType.ClientRpc, - invokeClass = invokeClass, - invokeFunction = func - }; - s_CmdHandlerDelegates[cmdHash] = invoker; - } - } - - protected static void RegisterEventDelegate(Type invokeClass, int cmdHash, CmdDelegate func) - { - if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) - { - var invoker = new Invoker - { - invokeType = UNetInvokeType.SyncEvent, - invokeClass = invokeClass, - invokeFunction = func - }; - s_CmdHandlerDelegates[cmdHash] = invoker; - } - } - - protected static void RegisterSyncListDelegate(Type invokeClass, int cmdHash, CmdDelegate func) - { - if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) - { - var invoker = new Invoker - { - invokeType = UNetInvokeType.SyncList, - invokeClass = invokeClass, - invokeFunction = func - }; - s_CmdHandlerDelegates[cmdHash] = invoker; - } - } - - internal static string GetInvoker(int cmdHash) - { - string result; - if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) - { - result = null; - } - else - { - var invoker = s_CmdHandlerDelegates[cmdHash]; - result = invoker.DebugString(); - } - - return result; - } - - internal static bool GetInvokerForHashCommand(int cmdHash, out Type invokeClass, out CmdDelegate invokeFunction) - => GetInvokerForHash(cmdHash, UNetInvokeType.Command, out invokeClass, out invokeFunction); - - internal static bool GetInvokerForHashClientRpc(int cmdHash, out Type invokeClass, out CmdDelegate invokeFunction) - => GetInvokerForHash(cmdHash, UNetInvokeType.ClientRpc, out invokeClass, out invokeFunction); - - internal static bool GetInvokerForHashSyncList(int cmdHash, out Type invokeClass, out CmdDelegate invokeFunction) - => GetInvokerForHash(cmdHash, UNetInvokeType.SyncList, out invokeClass, out invokeFunction); - - internal static bool GetInvokerForHashSyncEvent(int cmdHash, out Type invokeClass, out CmdDelegate invokeFunction) - => GetInvokerForHash(cmdHash, UNetInvokeType.SyncEvent, out invokeClass, out invokeFunction); - - private static bool GetInvokerForHash(int cmdHash, UNetInvokeType invokeType, out Type invokeClass, out CmdDelegate invokeFunction) - { - bool result; - if (!s_CmdHandlerDelegates.TryGetValue(cmdHash, out var invoker)) - { - QLog.Error($"GetInvokerForHash hash:{cmdHash} not found"); - invokeClass = null; - invokeFunction = null; - result = false; - } - else if (invoker == null) - { - QLog.Error($"GetInvokerForHash hash:{cmdHash} invoker null"); - invokeClass = null; - invokeFunction = null; - result = false; - } - else if (invoker.invokeType != invokeType) - { - QLog.Error($"GetInvokerForHash hash:{cmdHash} mismatched invokeType"); - invokeClass = null; - invokeFunction = null; - result = false; - } - else - { - invokeClass = invoker.invokeClass; - invokeFunction = invoker.invokeFunction; - result = true; - } - - return result; - } - - internal static void DumpInvokers() - { - QLog.Log($"DumpInvokers size:{s_CmdHandlerDelegates.Count}"); - foreach (var keyValuePair in s_CmdHandlerDelegates) - { - QLog.Log($" Invoker:{keyValuePair.Value.invokeClass}:{keyValuePair.Value.invokeFunction.GetMethodName()} {keyValuePair.Value.invokeType} {keyValuePair.Key}"); - } - } - - internal bool ContainsCommandDelegate(int cmdHash) - => s_CmdHandlerDelegates.ContainsKey(cmdHash); - - internal bool InvokeCommandDelegate(int cmdHash, QNetworkReader reader) - { - bool result; - if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) - { - result = false; - } - else - { - var invoker = s_CmdHandlerDelegates[cmdHash]; - if (invoker.invokeType != UNetInvokeType.Command) - { - result = false; - } - else - { - if (GetType() != invoker.invokeClass) - { - if (!GetType().IsSubclassOf(invoker.invokeClass)) - { - return false; - } - } - - invoker.invokeFunction(this, reader); - result = true; - } - } - - return result; - } - - internal bool InvokeRpcDelegate(int cmdHash, QNetworkReader reader) - { - bool result; - if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) - { - result = false; - } - else - { - var invoker = s_CmdHandlerDelegates[cmdHash]; - if (invoker.invokeType != UNetInvokeType.ClientRpc) - { - result = false; - } - else - { - if (GetType() != invoker.invokeClass) - { - if (!GetType().IsSubclassOf(invoker.invokeClass)) - { - return false; - } - } - - invoker.invokeFunction(this, reader); - result = true; - } - } - - return result; - } - - internal bool InvokeSyncEventDelegate(int cmdHash, QNetworkReader reader) - { - bool result; - if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) - { - result = false; - } - else - { - var invoker = s_CmdHandlerDelegates[cmdHash]; - if (invoker.invokeType != UNetInvokeType.SyncEvent) - { - result = false; - } - else - { - invoker.invokeFunction(this, reader); - result = true; - } - } - - return result; - } - - internal bool InvokeSyncListDelegate(int cmdHash, QNetworkReader reader) - { - bool result; - if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) - { - result = false; - } - else - { - var invoker = s_CmdHandlerDelegates[cmdHash]; - if (invoker.invokeType != UNetInvokeType.SyncList) - { - result = false; - } - else if (GetType() != invoker.invokeClass) - { - result = false; - } - else - { - invoker.invokeFunction(this, reader); - result = true; - } - } - - return result; - } - - internal static string GetCmdHashHandlerName(int cmdHash) - { - string result; - if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) - { - result = cmdHash.ToString(); - } - else - { - var invoker = s_CmdHandlerDelegates[cmdHash]; - result = $"{invoker.invokeType}:{invoker.invokeFunction.GetMethodName()}"; - } - - return result; - } - - private static string GetCmdHashPrefixName(int cmdHash, string prefix) - { - string result; - if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) - { - result = cmdHash.ToString(); - } - else - { - var invoker = s_CmdHandlerDelegates[cmdHash]; - var text = invoker.invokeFunction.GetMethodName(); - var num = text.IndexOf(prefix); - if (num > -1) - { - text = text.Substring(prefix.Length); - } - - result = text; - } - - return result; - } - - internal static string GetCmdHashCmdName(int cmdHash) - => GetCmdHashPrefixName(cmdHash, "InvokeCmd"); - - internal static string GetCmdHashRpcName(int cmdHash) - => GetCmdHashPrefixName(cmdHash, "InvokeRpc"); - - internal static string GetCmdHashEventName(int cmdHash) - => GetCmdHashPrefixName(cmdHash, "InvokeSyncEvent"); - - internal static string GetCmdHashListName(int cmdHash) - => GetCmdHashPrefixName(cmdHash, "InvokeSyncList"); - - protected void SetSyncVarGameObject(GameObject newGameObject, ref GameObject gameObjectField, uint dirtyBit, ref NetworkInstanceId netIdField) - { - if (!SyncVarHookGuard) - { - NetworkInstanceId networkInstanceId = default; - if (newGameObject != null) - { - var component = newGameObject.GetComponent(); - if (component != null) - { - networkInstanceId = component.NetId; - if (networkInstanceId.IsEmpty()) - { - QLog.Warning( - $"SetSyncVarGameObject GameObject {newGameObject} has a zero netId. Maybe it is not spawned yet?"); - } - } - } - - NetworkInstanceId networkInstanceId2 = default; - if (gameObjectField != null) - { - networkInstanceId2 = gameObjectField.GetComponent().NetId; - } - - if (networkInstanceId != networkInstanceId2) - { - QLog.Log( - $"SetSyncVar GameObject {GetType().Name} bit [{dirtyBit}] netfieldId:{networkInstanceId2}->{networkInstanceId}"); - SetDirtyBit(dirtyBit); - gameObjectField = newGameObject; - netIdField = networkInstanceId; - } - } - } - - protected bool SetSyncVar(T value, ref T fieldValue, uint dirtyBit) - { - var shouldSet = false; - if (value == null) - { - if (fieldValue != null) - { - shouldSet = true; - } - } - else - { - shouldSet = !value.Equals(fieldValue); - } - - if (shouldSet) - { - QLog.Log($"SetSyncVar {GetType().Name} bit [{dirtyBit}] {fieldValue}->{value}"); - - SetDirtyBit(dirtyBit); - fieldValue = value; - } - - return shouldSet; + QNetworkServer.SendWriterToReady(gameObject, writer); } public void SetDirtyBit(uint dirtyBit) => SyncVarDirtyBits |= dirtyBit; @@ -505,7 +97,7 @@ namespace QuantumUNET { if (SyncVarDirtyBits != 0U) { - return GetNetworkChannel(); + return 0; } } @@ -566,36 +158,14 @@ namespace QuantumUNET public virtual bool OnCheckObserver(QNetworkConnection conn) => true; - public virtual int GetNetworkChannel() => 0; - public virtual float GetNetworkSendInterval() => 0.1f; private float m_LastSendTime; private QNetworkIdentity m_MyView; - private static readonly Dictionary s_CmdHandlerDelegates = new(); - public delegate void CmdDelegate(QNetworkBehaviour obj, QNetworkReader reader); protected delegate void EventDelegate(List targets, QNetworkReader reader); - - protected enum UNetInvokeType - { - Command, - ClientRpc, - SyncEvent, - SyncList - } - - protected class Invoker - { - public string DebugString() => - $"{invokeType}:{invokeClass}:{invokeFunction.GetMethodName()}"; - - public UNetInvokeType invokeType; - public Type invokeClass; - public CmdDelegate invokeFunction; - } } internal static class DotNetCompatibility diff --git a/QuantumUNET/QNetworkClient.cs b/QuantumUNET/QNetworkClient.cs index 4338e843..ffc9fe62 100644 --- a/QuantumUNET/QNetworkClient.cs +++ b/QuantumUNET/QNetworkClient.cs @@ -225,7 +225,7 @@ namespace QuantumUNET return result; } - public bool SendWriter(QNetworkWriter writer, int channelId) + public bool SendWriter(QNetworkWriter writer) { bool result; if (m_Connection != null) @@ -237,7 +237,7 @@ namespace QuantumUNET } else { - result = m_Connection.SendWriter(writer, channelId); + result = m_Connection.SendWriter(writer); } } else @@ -249,7 +249,7 @@ namespace QuantumUNET return result; } - public bool SendBytes(byte[] data, int numBytes, int channelId) + public bool SendBytes(byte[] data, int numBytes) { bool result; if (m_Connection != null) @@ -261,7 +261,7 @@ namespace QuantumUNET } else { - result = m_Connection.SendBytes(data, numBytes, channelId); + result = m_Connection.SendBytes(data, numBytes); } } else @@ -273,31 +273,7 @@ namespace QuantumUNET return result; } - public bool SendUnreliable(short msgType, QMessageBase msg) - { - bool result; - if (m_Connection != null) - { - if (m_AsyncConnect != ConnectState.Connected) - { - QLog.Error("NetworkClient SendUnreliable when not connected to a server"); - result = false; - } - else - { - result = m_Connection.SendUnreliable(msgType, msg); - } - } - else - { - QLog.Error("NetworkClient SendUnreliable with no connection"); - result = false; - } - - return result; - } - - public bool SendByChannel(short msgType, QMessageBase msg, int channelId) + public bool SendByChannel(short msgType, QMessageBase msg) { bool result; if (m_Connection != null) @@ -309,7 +285,7 @@ namespace QuantumUNET } else { - result = m_Connection.SendByChannel(msgType, msg, channelId); + result = m_Connection.SendByChannel(msgType, msg); } } else @@ -503,8 +479,7 @@ namespace QuantumUNET { MsgType = QMsgType.Error, Reader = reader, - Connection = m_Connection, - ChannelId = 0 + Connection = m_Connection }); } } diff --git a/QuantumUNET/QNetworkConnection.cs b/QuantumUNET/QNetworkConnection.cs index 8ac69664..f82cd984 100644 --- a/QuantumUNET/QNetworkConnection.cs +++ b/QuantumUNET/QNetworkConnection.cs @@ -39,18 +39,14 @@ namespace QuantumUNET throw new ArgumentOutOfRangeException("Platform specific protocols are not supported on this platform"); } - m_Channels = new QChannelBuffer[channelCount]; - for (var i = 0; i < channelCount; i++) + var channelQOS = hostTopology.DefaultConfig.Channels[0]; + var bufferSize = packetSize; + if (channelQOS.QOS is QosType.ReliableFragmented or QosType.UnreliableFragmented) { - var channelQOS = hostTopology.DefaultConfig.Channels[i]; - var bufferSize = packetSize; - if (channelQOS.QOS is QosType.ReliableFragmented or QosType.UnreliableFragmented) - { - bufferSize = hostTopology.DefaultConfig.FragmentSize * 128; - } - - m_Channels[i] = new QChannelBuffer(this, bufferSize, (byte)i, IsReliableQoS(channelQOS.QOS), IsSequencedQoS(channelQOS.QOS)); + bufferSize = hostTopology.DefaultConfig.FragmentSize * 128; } + + m_Channel = new QChannelBuffer(this, bufferSize, 0, IsReliableQoS(channelQOS.QOS), IsSequencedQoS(channelQOS.QOS)); } ~QNetworkConnection() @@ -66,15 +62,12 @@ namespace QuantumUNET protected virtual void Dispose(bool disposing) { - if (!m_Disposed && m_Channels != null) + if (!m_Disposed && m_Channel != null) { - foreach (var channel in m_Channels) - { - channel.Dispose(); - } + m_Channel.Dispose(); } - m_Channels = null; + m_Channel = null; if (ClientOwnedObjects != null) { foreach (var netId in ClientOwnedObjects) @@ -95,7 +88,7 @@ namespace QuantumUNET private static bool IsReliableQoS(QosType qos) => qos is QosType.Reliable or QosType.ReliableFragmented or QosType.ReliableSequenced or QosType.ReliableStateUpdate; - public bool SetChannelOption(int channelId, ChannelOption option, int value) => m_Channels != null && channelId >= 0 && channelId < m_Channels.Length && m_Channels[channelId].SetOption(option, value); + public bool SetChannelOption(int channelId, ChannelOption option, int value) => m_Channel != null && channelId >= 0 && m_Channel.SetOption(option, value); public void Disconnect() { @@ -117,9 +110,9 @@ namespace QuantumUNET public bool CheckHandler(short msgType) => m_MessageHandlersDict.ContainsKey(msgType); - public bool InvokeHandlerNoData(short msgType) => InvokeHandler(msgType, null, 0); + public bool InvokeHandlerNoData(short msgType) => InvokeHandler(msgType, null); - public bool InvokeHandler(short msgType, QNetworkReader reader, int channelId) + public bool InvokeHandler(short msgType, QNetworkReader reader) { bool result; if (m_MessageHandlersDict.ContainsKey(msgType)) @@ -127,7 +120,6 @@ namespace QuantumUNET m_MessageInfo.MsgType = msgType; m_MessageInfo.Connection = this; m_MessageInfo.Reader = reader; - m_MessageInfo.ChannelId = channelId; var networkMessageDelegate = m_MessageHandlersDict[msgType]; if (networkMessageDelegate == null) { @@ -164,21 +156,6 @@ namespace QuantumUNET return result; } - internal void HandleFragment(QNetworkReader reader, int channelId) - { - if (channelId >= 0 && channelId < m_Channels.Length) - { - var channelBuffer = m_Channels[channelId]; - if (channelBuffer.HandleFragment(reader)) - { - var networkReader = new QNetworkReader(channelBuffer._fragmentBuffer.AsArraySegment().Array); - networkReader.ReadInt16(); - var msgType = networkReader.ReadInt16(); - InvokeHandler(msgType, networkReader, channelId); - } - } - } - public void RegisterHandler(short msgType, QNetworkMessageDelegate handler) => m_MessageHandlers.RegisterHandler(msgType, handler); public void UnregisterHandler(short msgType) => m_MessageHandlers.UnregisterHandler(msgType); @@ -234,41 +211,33 @@ namespace QuantumUNET public void FlushChannels() { - if (m_Channels != null) + if (m_Channel != null) { - foreach (var channel in m_Channels) - { - channel.CheckInternalBuffer(); - } + m_Channel.CheckInternalBuffer(); } } public void SetMaxDelay(float seconds) { - if (m_Channels != null) + if (m_Channel != null) { - foreach (var channel in m_Channels) - { - channel.MaxDelay = seconds; - } + m_Channel.MaxDelay = seconds; } } - public virtual bool Send(short msgType, QMessageBase msg) => SendByChannel(msgType, msg, 0); + public virtual bool Send(short msgType, QMessageBase msg) => SendByChannel(msgType, msg); - public virtual bool SendUnreliable(short msgType, QMessageBase msg) => SendByChannel(msgType, msg, 1); - - public virtual bool SendByChannel(short msgType, QMessageBase msg, int channelId) + public virtual bool SendByChannel(short msgType, QMessageBase msg) { m_Writer.StartMessage(msgType); msg.Serialize(m_Writer); m_Writer.FinishMessage(); - return SendWriter(m_Writer, channelId); + return SendWriter(m_Writer); } - public virtual bool SendBytes(byte[] bytes, int numBytes, int channelId) => CheckChannel(channelId) && m_Channels[channelId].SendBytes(bytes, numBytes); + public virtual bool SendBytes(byte[] bytes, int numBytes) => m_Channel.SendBytes(bytes, numBytes); - public virtual bool SendWriter(QNetworkWriter writer, int channelId) => CheckChannel(channelId) && m_Channels[channelId].SendWriter(writer); + public virtual bool SendWriter(QNetworkWriter writer) => m_Channel.SendWriter(writer); private void LogSend(byte[] bytes) { @@ -289,28 +258,6 @@ namespace QuantumUNET $"ConnectionSend con:{connectionId} bytes:{num} msgId:{num2} {stringBuilder}"); } - private bool CheckChannel(int channelId) - { - bool result; - if (m_Channels == null) - { - QLog.Warning($"Channels not initialized sending on id '{channelId}"); - result = false; - } - else if (channelId < 0 || channelId >= m_Channels.Length) - { - QLog.Error( - $"Invalid channel when sending buffered data, '{channelId}'. Current channel count is {m_Channels.Length}"); - result = false; - } - else - { - result = true; - } - - return result; - } - public void ResetStats() { } @@ -344,14 +291,13 @@ namespace QuantumUNET m_NetMsg.MsgType = num2; m_NetMsg.Reader = reader2; m_NetMsg.Connection = this; - m_NetMsg.ChannelId = channelId; networkMessageDelegate(m_NetMsg); lastMessageTime = Time.time; } } public override string ToString() => - $"hostId: {hostId} connectionId: {connectionId} isReady: {isReady} channel count: {m_Channels?.Length ?? 0}"; + $"hostId: {hostId} connectionId: {connectionId} isReady: {isReady}"; internal void AddToVisList(QNetworkIdentity uv) { @@ -394,9 +340,7 @@ namespace QuantumUNET internal void RemoveOwnedObject(QNetworkIdentity obj) => ClientOwnedObjects?.Remove(obj.NetId); - internal static void OnFragment(QNetworkMessage netMsg) => netMsg.Connection.HandleFragment(netMsg.Reader, netMsg.ChannelId); - - private QChannelBuffer[] m_Channels; + private QChannelBuffer m_Channel; private readonly QNetworkMessage m_NetMsg = new(); private QNetworkWriter m_Writer; diff --git a/QuantumUNET/QNetworkServer.cs b/QuantumUNET/QNetworkServer.cs index 019d8195..3b6bcec5 100644 --- a/QuantumUNET/QNetworkServer.cs +++ b/QuantumUNET/QNetworkServer.cs @@ -101,7 +101,6 @@ namespace QuantumUNET { m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.ClientUpdateVars, OnUpdateVarsMessage); m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.Ready, OnClientReadyMessage); - m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.Command, OnCommandMessage); m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.LocalPlayerTransform, QNetworkTransform.HandleTransform); m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.LocalChildTransform, QNetworkTransformChild.HandleChildTransform); m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.RemovePlayer, OnRemovePlayerMessage); @@ -299,7 +298,7 @@ namespace QuantumUNET return result; } - public static void SendWriterToReady(GameObject contextObj, QNetworkWriter writer, int channelId) + public static void SendWriterToReady(GameObject contextObj, QNetworkWriter writer) { var arraySegment = writer.AsArraySegment(); if (arraySegment.Count > 32767) @@ -307,10 +306,10 @@ namespace QuantumUNET throw new UnityException("NetworkWriter used buffer is too big!"); } - SendBytesToReady(contextObj, arraySegment.Array, arraySegment.Count, channelId); + SendBytesToReady(contextObj, arraySegment.Array, arraySegment.Count); } - public static void SendBytesToReady(GameObject contextObj, byte[] buffer, int numBytes, int channelId) + public static void SendBytesToReady(GameObject contextObj, byte[] buffer, int numBytes) { if (contextObj == null) { @@ -319,7 +318,7 @@ namespace QuantumUNET { if (networkConnection != null && networkConnection.isReady) { - if (!networkConnection.SendBytes(buffer, numBytes, channelId)) + if (!networkConnection.SendBytes(buffer, numBytes)) { flag = false; } @@ -343,7 +342,7 @@ namespace QuantumUNET var networkConnection2 = component.Observers[j]; if (networkConnection2.isReady) { - if (!networkConnection2.SendBytes(buffer, numBytes, channelId)) + if (!networkConnection2.SendBytes(buffer, numBytes)) { flag2 = false; } @@ -362,7 +361,7 @@ namespace QuantumUNET } } - public static void SendBytesToPlayer(GameObject player, byte[] buffer, int numBytes, int channelId) + public static void SendBytesToPlayer(GameObject player, byte[] buffer, int numBytes) { foreach (var networkConnection in connections) { @@ -372,7 +371,7 @@ namespace QuantumUNET { if (controller.IsValid && controller.Gameobject == player) { - networkConnection.SendBytes(buffer, numBytes, channelId); + networkConnection.SendBytes(buffer, numBytes); break; } } @@ -380,58 +379,7 @@ namespace QuantumUNET } } - public static bool SendUnreliableToAll(short msgType, QMessageBase msg) - { - QLog.Log($"Server.SendUnreliableToAll msgType:{msgType}"); - var flag = true; - foreach (var networkConnection in connections) - { - if (networkConnection != null) - { - flag &= networkConnection.SendUnreliable(msgType, msg); - } - } - - return flag; - } - - public static bool SendUnreliableToReady(GameObject contextObj, short msgType, QMessageBase msg) - { - QLog.Log($"Server.SendUnreliableToReady id:{msgType}"); - bool result; - if (contextObj == null) - { - foreach (var networkConnection in connections) - { - if (networkConnection != null && networkConnection.isReady) - { - networkConnection.SendUnreliable(msgType, msg); - } - } - - result = true; - } - else - { - var flag = true; - var component = contextObj.GetComponent(); - var count = component.Observers.Count; - for (var j = 0; j < count; j++) - { - var networkConnection2 = component.Observers[j]; - if (networkConnection2.isReady) - { - flag &= networkConnection2.SendUnreliable(msgType, msg); - } - } - - result = flag; - } - - return result; - } - - public static bool SendByChannelToAll(short msgType, QMessageBase msg, int channelId) + public static bool SendByChannelToAll(short msgType, QMessageBase msg) { QLog.Log($"Server.SendByChannelToAll id:{msgType}"); var flag = true; @@ -439,14 +387,14 @@ namespace QuantumUNET { if (networkConnection != null) { - flag &= networkConnection.SendByChannel(msgType, msg, channelId); + flag &= networkConnection.SendByChannel(msgType, msg); } } return flag; } - public static bool SendByChannelToReady(GameObject contextObj, short msgType, QMessageBase msg, int channelId) + public static bool SendByChannelToReady(GameObject contextObj, short msgType, QMessageBase msg) { QLog.Log($"Server.SendByChannelToReady msgType:{msgType}"); bool result; @@ -456,7 +404,7 @@ namespace QuantumUNET { if (networkConnection != null && networkConnection.isReady) { - networkConnection.SendByChannel(msgType, msg, channelId); + networkConnection.SendByChannel(msgType, msg); } } @@ -472,7 +420,7 @@ namespace QuantumUNET var networkConnection2 = component.Observers[j]; if (networkConnection2.isReady) { - flag &= networkConnection2.SendByChannel(msgType, msg, channelId); + flag &= networkConnection2.SendByChannel(msgType, msg); } } @@ -609,7 +557,7 @@ namespace QuantumUNET var writer = new QNetworkWriter(); errorMessage.Serialize(writer); var reader = new QNetworkReader(writer); - conn.InvokeHandler(34, reader, 0); + conn.InvokeHandler(34, reader); } } @@ -932,50 +880,6 @@ namespace QuantumUNET } } - private static void OnCommandMessage(QNetworkMessage netMsg) - { - var cmdHash = (int)netMsg.Reader.ReadPackedUInt32(); - var networkInstanceId = netMsg.Reader.ReadNetworkId(); - var gameObject = FindLocalObject(networkInstanceId); - if (gameObject == null) - { - QLog.Warning($"Instance not found when handling Command message [netId={networkInstanceId}]"); - } - else - { - var component = gameObject.GetComponent(); - if (component == null) - { - QLog.Warning( - $"NetworkIdentity deleted when handling Command message [netId={networkInstanceId}]"); - } - else - { - var flag = false; - foreach (var playerController in netMsg.Connection.PlayerControllers) - { - if (playerController.Gameobject != null && playerController.Gameobject.GetComponent().NetId == component.NetId) - { - flag = true; - break; - } - } - - if (!flag) - { - if (component.ClientAuthorityOwner != netMsg.Connection) - { - QLog.Warning($"Command for object without authority [netId={networkInstanceId}]"); - return; - } - } - - QLog.Log($"OnCommandMessage for netId={networkInstanceId} conn={netMsg.Connection}"); - component.HandleCommand(cmdHash, netMsg.Reader); - } - } - } - internal void SpawnObject(GameObject obj) { if (!active) @@ -1232,7 +1136,7 @@ namespace QuantumUNET public static void UnSpawn(GameObject obj) => UnSpawnObject(obj); - internal bool InvokeBytes(QULocalConnectionToServer conn, byte[] buffer, int numBytes, int channelId) + internal bool InvokeBytes(QULocalConnectionToServer conn, byte[] buffer, int numBytes) { var networkReader = new QNetworkReader(buffer); networkReader.ReadInt16(); @@ -1240,7 +1144,7 @@ namespace QuantumUNET bool result; if (handlers.ContainsKey(num) && m_LocalConnection != null) { - m_LocalConnection.InvokeHandler(num, networkReader, channelId); + m_LocalConnection.InvokeHandler(num, networkReader); result = true; } else @@ -1251,7 +1155,7 @@ namespace QuantumUNET return result; } - internal bool InvokeHandlerOnServer(QULocalConnectionToServer conn, short msgType, QMessageBase msg, int channelId) + internal bool InvokeHandlerOnServer(QULocalConnectionToServer conn, short msgType, QMessageBase msg) { bool result; if (handlers.ContainsKey(msgType) && m_LocalConnection != null) @@ -1259,7 +1163,7 @@ namespace QuantumUNET var writer = new QNetworkWriter(); msg.Serialize(writer); var reader = new QNetworkReader(writer); - m_LocalConnection.InvokeHandler(msgType, reader, channelId); + m_LocalConnection.InvokeHandler(msgType, reader); result = true; } else diff --git a/QuantumUNET/QNetworkServerSimple.cs b/QuantumUNET/QNetworkServerSimple.cs index 7e638d47..ae90345b 100644 --- a/QuantumUNET/QNetworkServerSimple.cs +++ b/QuantumUNET/QNetworkServerSimple.cs @@ -37,7 +37,6 @@ namespace QuantumUNET { var connectionConfig = new ConnectionConfig(); connectionConfig.AddChannel(QosType.ReliableSequenced); - connectionConfig.AddChannel(QosType.Unreliable); hostTopology = new HostTopology(connectionConfig, 8); } @@ -310,16 +309,16 @@ namespace QuantumUNET } } - public void SendBytesTo(int connectionId, byte[] bytes, int numBytes, int channelId) + public void SendBytesTo(int connectionId, byte[] bytes, int numBytes) { var networkConnection = FindConnection(connectionId); - networkConnection?.SendBytes(bytes, numBytes, channelId); + networkConnection?.SendBytes(bytes, numBytes); } - public void SendWriterTo(int connectionId, QNetworkWriter writer, int channelId) + public void SendWriterTo(int connectionId, QNetworkWriter writer) { var networkConnection = FindConnection(connectionId); - networkConnection?.SendWriter(writer, channelId); + networkConnection?.SendWriter(writer); } public void Disconnect(int connectionId) diff --git a/QuantumUNET/QULocalConnectionToClient.cs b/QuantumUNET/QULocalConnectionToClient.cs index adb8368d..9de58333 100644 --- a/QuantumUNET/QULocalConnectionToClient.cs +++ b/QuantumUNET/QULocalConnectionToClient.cs @@ -15,31 +15,25 @@ namespace QuantumUNET public override bool Send(short msgType, QMessageBase msg) { - LocalClient.InvokeHandlerOnClient(msgType, msg, 0); + LocalClient.InvokeHandlerOnClient(msgType, msg); return true; } - public override bool SendUnreliable(short msgType, QMessageBase msg) + public override bool SendByChannel(short msgType, QMessageBase msg) { - LocalClient.InvokeHandlerOnClient(msgType, msg, 1); + LocalClient.InvokeHandlerOnClient(msgType, msg); return true; } - public override bool SendByChannel(short msgType, QMessageBase msg, int channelId) + public override bool SendBytes(byte[] bytes, int numBytes) { - LocalClient.InvokeHandlerOnClient(msgType, msg, channelId); + LocalClient.InvokeBytesOnClient(bytes); return true; } - public override bool SendBytes(byte[] bytes, int numBytes, int channelId) + public override bool SendWriter(QNetworkWriter writer) { - LocalClient.InvokeBytesOnClient(bytes, channelId); - return true; - } - - public override bool SendWriter(QNetworkWriter writer, int channelId) - { - LocalClient.InvokeBytesOnClient(writer.AsArray(), channelId); + LocalClient.InvokeBytesOnClient(writer.AsArray()); return true; } } diff --git a/QuantumUNET/QULocalConnectionToServer.cs b/QuantumUNET/QULocalConnectionToServer.cs index 7b991ad0..0972c9db 100644 --- a/QuantumUNET/QULocalConnectionToServer.cs +++ b/QuantumUNET/QULocalConnectionToServer.cs @@ -13,15 +13,12 @@ namespace QuantumUNET } public override bool Send(short msgType, QMessageBase msg) - => m_LocalServer.InvokeHandlerOnServer(this, msgType, msg, 0); + => m_LocalServer.InvokeHandlerOnServer(this, msgType, msg); - public override bool SendUnreliable(short msgType, QMessageBase msg) - => m_LocalServer.InvokeHandlerOnServer(this, msgType, msg, 1); + public override bool SendByChannel(short msgType, QMessageBase msg) + => m_LocalServer.InvokeHandlerOnServer(this, msgType, msg); - public override bool SendByChannel(short msgType, QMessageBase msg, int channelId) - => m_LocalServer.InvokeHandlerOnServer(this, msgType, msg, channelId); - - public override bool SendBytes(byte[] bytes, int numBytes, int channelId) + public override bool SendBytes(byte[] bytes, int numBytes) { bool result; if (numBytes <= 0) @@ -31,14 +28,14 @@ namespace QuantumUNET } else { - result = m_LocalServer.InvokeBytes(this, bytes, numBytes, channelId); + result = m_LocalServer.InvokeBytes(this, bytes, numBytes); } return result; } - public override bool SendWriter(QNetworkWriter writer, int channelId) - => m_LocalServer.InvokeBytes(this, writer.AsArray(), (short)writer.AsArray().Length, channelId); + public override bool SendWriter(QNetworkWriter writer) + => m_LocalServer.InvokeBytes(this, writer.AsArray(), (short)writer.AsArray().Length); private readonly QNetworkServer m_LocalServer; } From 9fc72cbdff3912c1f25ea99296d6b8e08936c2d6 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Fri, 26 Nov 2021 17:36:14 +0000 Subject: [PATCH 2/8] stuffz --- QSB/Animation/Player/CrouchSync.cs | 20 +- QSB/Events/EventType.cs | 1 + QSB/QSB.csproj | 16 +- .../VariableSync/BaseVariableSyncer.cs | 172 ++++++++++++++++++ .../VariableSync/FloatVariableSyncer.cs | 33 ++++ QSB/Utility/VariableSync/VariableReference.cs | 22 +++ QuantumUNET/QNetworkServer.cs | 6 +- QuantumUNET/QNetworkServerSimple.cs | 2 +- 8 files changed, 254 insertions(+), 18 deletions(-) create mode 100644 QSB/Utility/VariableSync/BaseVariableSyncer.cs create mode 100644 QSB/Utility/VariableSync/FloatVariableSyncer.cs create mode 100644 QSB/Utility/VariableSync/VariableReference.cs diff --git a/QSB/Animation/Player/CrouchSync.cs b/QSB/Animation/Player/CrouchSync.cs index 9cf9cb66..c62f5c3d 100644 --- a/QSB/Animation/Player/CrouchSync.cs +++ b/QSB/Animation/Player/CrouchSync.cs @@ -1,4 +1,6 @@ -using QuantumUNET; +using QSB.Utility; +using QSB.Utility.VariableSync; +using QuantumUNET; using UnityEngine; using UnityEngine.Networking; @@ -13,14 +15,21 @@ namespace QSB.Animation.Player private PlayerCharacterController _playerController; private Animator _bodyAnim; + private VariableReference _crouchValueReference; + private FloatVariableSyncer _variableSyncer; - [SyncVar] - private float _crouchValue; + public float CrouchValue; public void Init(PlayerCharacterController playerController, Animator bodyAnim) { _playerController = playerController; _bodyAnim = bodyAnim; + + DebugLog.DebugWrite($"create reference"); + _crouchValueReference = new VariableReference(() => CrouchValue, val => CrouchValue = val); + DebugLog.DebugWrite($"add syncer"); + _variableSyncer = gameObject.AddComponent(); + _variableSyncer.FloatToSync = _crouchValueReference; } public void Update() @@ -42,7 +51,8 @@ namespace QSB.Animation.Player } var jumpChargeFraction = _playerController.GetJumpCrouchFraction(); - _crouchValue = jumpChargeFraction; + DebugLog.DebugWrite($"update reference value"); + _crouchValueReference.Value = jumpChargeFraction; } private void SyncRemoteCrouch() @@ -52,7 +62,7 @@ namespace QSB.Animation.Player return; } - CrouchParam.Target = _crouchValue; + CrouchParam.Target = CrouchValue; CrouchParam.Smooth(CrouchSmoothTime); var jumpChargeFraction = CrouchParam.Current; _bodyAnim.SetLayerWeight(CrouchLayerIndex, jumpChargeFraction); diff --git a/QSB/Events/EventType.cs b/QSB/Events/EventType.cs index b95e63e4..119011e3 100644 --- a/QSB/Events/EventType.cs +++ b/QSB/Events/EventType.cs @@ -9,6 +9,7 @@ SatelliteProjector, SatelliteProjectorSnapshot, LaunchCodes, + VariableSync, /* * SERVER EVENTS diff --git a/QSB/QSB.csproj b/QSB/QSB.csproj index 3a69917a..d0bb470f 100644 --- a/QSB/QSB.csproj +++ b/QSB/QSB.csproj @@ -331,6 +331,9 @@ + + + @@ -485,22 +488,17 @@ md "$(OwmlDir)\Mods\$(ProjectName)\assets" :: delete old config file del "$(OwmlDir)\Mods\$(ProjectName)\config.json" -:: copy files that dont need to be processed +:: copy files copy /y "$(ProjectDir)\default-config.json" "$(OwmlDir)\Mods\$(ProjectName)" copy /y "$(SolutionDir)\AssetBundles" "$(OwmlDir)\Mods\$(ProjectName)\assets" copy /y "$(ProjectDir)\manifest.json" "$(OwmlDir)\Mods\$(ProjectName)" - -:: process qsb.dll -"$(SolutionDir)\QNetWeaver\bin\$(Configuration)\QNetWeaver.exe" "$(GameDir)\OuterWilds_Data\Managed\UnityEngine.CoreModule.dll" "$(OwmlDir)\Mods\$(ProjectName)\QuantumUNET.dll" "$(ProjectDir)\lib\UnityEngine.Networking.dll" "$(SolutionDir)\WeavedFiles" "$(TargetPath)" - -:: copy processed dll -copy /y "$(SolutionDir)\WeavedFiles\QSB.dll" "$(OwmlDir)\Mods\$(ProjectName)" +copy /y "$(TargetPath)" "$(OwmlDir)\Mods\$(ProjectName)" :: copy all lib files xcopy /y "$(ProjectDir)\lib" "$(OwmlDir)\Mods\$(ProjectName)" -:: copy processed dll to unity project -copy /y "$(SolutionDir)\WeavedFiles\QSB.dll" $(UnityAssetsDir) +:: copy dll to unity project +copy /y "$(TargetPath)" $(UnityAssetsDir) :: copy quantumunet to unity project copy /y "$(OwmlDir)\Mods\$(ProjectName)\QuantumUNET.dll" $(UnityAssetsDir) :: copy game assembly to unity project diff --git a/QSB/Utility/VariableSync/BaseVariableSyncer.cs b/QSB/Utility/VariableSync/BaseVariableSyncer.cs new file mode 100644 index 00000000..d9ee5222 --- /dev/null +++ b/QSB/Utility/VariableSync/BaseVariableSyncer.cs @@ -0,0 +1,172 @@ +using QuantumUNET; +using QuantumUNET.Components; +using QuantumUNET.Logging; +using QuantumUNET.Messages; +using QuantumUNET.Transport; +using UnityEngine; +using UnityEngine.Networking; + +namespace QSB.Utility.VariableSync +{ + internal abstract class BaseVariableSyncer : QNetworkBehaviour + { + private float _lastClientSendTime; + private QNetworkWriter _localTransformWriter; + + public void Awake() + { + if (LocalPlayerAuthority) + { + _localTransformWriter = new QNetworkWriter(); + } + } + + private void Start() + { + DebugLog.DebugWrite($"add handler"); + QNetworkServer.instance.m_SimpleServerSimple.RegisterHandlerSafe((short)QSB.Events.EventType.VariableSync, HandleTransform); + } + + public override bool OnSerialize(QNetworkWriter writer, bool initialState) + { + DebugLog.DebugWrite($"ON SERIALIZE"); + + if (!initialState) + { + if (SyncVarDirtyBits == 0U) + { + writer.WritePackedUInt32(0U); + return false; + } + + writer.WritePackedUInt32(1U); + } + + WriteData(writer); + return true; + } + + public override void OnDeserialize(QNetworkReader reader, bool initialState) + { + DebugLog.DebugWrite($"ON DESERIALIZE"); + + if (!IsServer || !QNetworkServer.localClientActive) + { + if (!initialState && reader.ReadPackedUInt32() == 0U) + { + return; + } + + ReadData(reader); + } + } + + private void FixedUpdate() + { + if (!IsServer) + { + DebugLog.DebugWrite($"FIXEDUPDATE not server"); + return; + } + + if (SyncVarDirtyBits != 0U) + { + DebugLog.DebugWrite($"FIXEDUPDATE dirty!!!"); + return; + } + + if (!QNetworkServer.active) + { + DebugLog.DebugWrite($"FIXEDUPDATE server is not active!"); + return; + } + + if (GetNetworkSendInterval() != 0f && HasChanged()) + { + SetDirtyBit(1U); + } + } + + public virtual void Update() + { + if (!HasAuthority || !LocalPlayerAuthority) + { + DebugLog.DebugWrite($"UPDATE no authority"); + return; + } + + if (QNetworkServer.active) + { + DebugLog.DebugWrite($"UPDATE server active"); + return; + } + + if (Time.time - _lastClientSendTime > GetNetworkSendInterval()) + { + this.SendTransform(); + this._lastClientSendTime = Time.time; + } + } + + [Client] + private void SendTransform() + { + DebugLog.DebugWrite($"SEND TRANSFORM"); + + if (HasChanged() && QClientScene.readyConnection != null) + { + _localTransformWriter.StartMessage(6); + _localTransformWriter.Write(NetId); + WriteData(_localTransformWriter); + _localTransformWriter.FinishMessage(); + QClientScene.readyConnection.SendWriter(_localTransformWriter); + } + } + + public static void HandleTransform(QNetworkMessage netMsg) + { + DebugLog.DebugWrite($"HANDLE TRANSFORM"); + + var networkInstanceId = netMsg.Reader.ReadNetworkId(); + var gameObject = QNetworkServer.FindLocalObject(networkInstanceId); + if (gameObject == null) + { + QLog.Warning("Received NetworkTransform data for GameObject that doesn't exist"); + return; + } + + var component = gameObject.GetComponent(); + if (component == null) + { + QLog.Warning("HandleTransform null target"); + return; + } + + if (!component.LocalPlayerAuthority) + { + QLog.Warning("HandleTransform no localPlayerAuthority"); + return; + } + + if (netMsg.Connection.ClientOwnedObjects == null) + { + QLog.Warning("HandleTransform object not owned by connection"); + return; + } + + if (netMsg.Connection.ClientOwnedObjects.Contains(networkInstanceId)) + { + component.ReadData(netMsg.Reader); + } + else + { + QLog.Warning( + $"HandleTransform netId:{networkInstanceId} is not for a valid player"); + } + } + + public abstract bool HasChanged(); + public abstract void WriteData(QNetworkWriter writer); + public abstract void ReadData(QNetworkReader writer); + } +} diff --git a/QSB/Utility/VariableSync/FloatVariableSyncer.cs b/QSB/Utility/VariableSync/FloatVariableSyncer.cs new file mode 100644 index 00000000..d2210ddc --- /dev/null +++ b/QSB/Utility/VariableSync/FloatVariableSyncer.cs @@ -0,0 +1,33 @@ +using QuantumUNET; +using QuantumUNET.Transport; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace QSB.Utility.VariableSync +{ + internal class FloatVariableSyncer : BaseVariableSyncer + { + public VariableReference FloatToSync; + + public override void WriteData(QNetworkWriter writer) + { + DebugLog.DebugWrite($"write data!"); + writer.Write(FloatToSync.Value); + } + + public override void ReadData(QNetworkReader writer) + { + DebugLog.DebugWrite($"read data!"); + FloatToSync.Value = writer.ReadSingle(); + } + + public override bool HasChanged() + { + // TODO - do this!! + return true; + } + } +} diff --git a/QSB/Utility/VariableSync/VariableReference.cs b/QSB/Utility/VariableSync/VariableReference.cs new file mode 100644 index 00000000..6fb39d65 --- /dev/null +++ b/QSB/Utility/VariableSync/VariableReference.cs @@ -0,0 +1,22 @@ +using System; + +namespace QSB.Utility.VariableSync +{ + internal class VariableReference + { + private Func _getter; + private Action _setter; + + public VariableReference(Func getter, Action setter) + { + _getter = getter; + _setter = setter; + } + + public T Value + { + get => _getter(); + set => _setter(value); + } + } +} diff --git a/QuantumUNET/QNetworkServer.cs b/QuantumUNET/QNetworkServer.cs index 3b6bcec5..facae77c 100644 --- a/QuantumUNET/QNetworkServer.cs +++ b/QuantumUNET/QNetworkServer.cs @@ -38,7 +38,7 @@ namespace QuantumUNET public static bool dontListen { get; set; } - internal static QNetworkServer instance + public static QNetworkServer instance { get { @@ -1252,7 +1252,7 @@ namespace QuantumUNET private readonly HashSet m_ExternalConnections; - private readonly ServerSimpleWrapper m_SimpleServerSimple; + public readonly ServerSimpleWrapper m_SimpleServerSimple; private float m_MaxDelay = 0.1f; @@ -1266,7 +1266,7 @@ namespace QuantumUNET private static readonly QRemovePlayerMessage s_RemovePlayerMessage = new(); - private class ServerSimpleWrapper : QNetworkServerSimple + public class ServerSimpleWrapper : QNetworkServerSimple { public ServerSimpleWrapper(QNetworkServer server) => m_Server = server; diff --git a/QuantumUNET/QNetworkServerSimple.cs b/QuantumUNET/QNetworkServerSimple.cs index ae90345b..e1448a9d 100644 --- a/QuantumUNET/QNetworkServerSimple.cs +++ b/QuantumUNET/QNetworkServerSimple.cs @@ -105,7 +105,7 @@ namespace QuantumUNET serverHostId = -1; } - internal void RegisterHandlerSafe(short msgType, QNetworkMessageDelegate handler) + public void RegisterHandlerSafe(short msgType, QNetworkMessageDelegate handler) => m_MessageHandlers.RegisterHandlerSafe(msgType, handler); public void RegisterHandler(short msgType, QNetworkMessageDelegate handler) From db1888bb1927797038ac1cc8f4106fbb20aad488 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Fri, 26 Nov 2021 17:36:27 +0000 Subject: [PATCH 3/8] Revert "aaaaa" This reverts commit 51e240a2a2e71db534155468c39ae53cf9c76e35. --- QSB.sln | 13 +- QuantumUNET/Components/QNetworkIdentity.cs | 128 ++++- QuantumUNET/Components/QNetworkTransform.cs | 5 +- .../Components/QNetworkTransformChild.cs | 3 +- QuantumUNET/Messages/QMsgType.cs | 8 + QuantumUNET/Messages/QNetworkMessage.cs | 1 + QuantumUNET/QClientScene.cs | 52 +++ QuantumUNET/QLocalClient.cs | 14 +- QuantumUNET/QNetworkBehaviour.cs | 442 +++++++++++++++++- QuantumUNET/QNetworkClient.cs | 39 +- QuantumUNET/QNetworkConnection.cs | 102 +++- QuantumUNET/QNetworkServer.cs | 134 +++++- QuantumUNET/QNetworkServerSimple.cs | 9 +- QuantumUNET/QULocalConnectionToClient.cs | 20 +- QuantumUNET/QULocalConnectionToServer.cs | 17 +- 15 files changed, 904 insertions(+), 83 deletions(-) diff --git a/QSB.sln b/QSB.sln index 15709d10..7473e240 100644 --- a/QSB.sln +++ b/QSB.sln @@ -1,14 +1,19 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29613.14 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QSB", "QSB\QSB.csproj", "{1F00090A-C697-4C55-B401-192F3CFB9DC2}" + ProjectSection(ProjectDependencies) = postProject + {E23551F3-C095-4F50-8BF7-85BB2661859B} = {E23551F3-C095-4F50-8BF7-85BB2661859B} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuantumUNET", "QuantumUNET\QuantumUNET.csproj", "{C8C53004-1508-4F86-A419-4292C188DC2A}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QSBTests", "QSBTests\QSBTests.csproj", "{2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QNetWeaver", "QNetWeaver\QNetWeaver.csproj", "{E23551F3-C095-4F50-8BF7-85BB2661859B}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2569F98D-F671-42AA-82DE-505B05CDCEF2}" ProjectSection(SolutionItems) = preProject .gitignore = .gitignore @@ -35,6 +40,10 @@ Global {2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}.Debug|Any CPU.Build.0 = Debug|Any CPU {2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}.Release|Any CPU.ActiveCfg = Release|Any CPU {2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}.Release|Any CPU.Build.0 = Release|Any CPU + {E23551F3-C095-4F50-8BF7-85BB2661859B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E23551F3-C095-4F50-8BF7-85BB2661859B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E23551F3-C095-4F50-8BF7-85BB2661859B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E23551F3-C095-4F50-8BF7-85BB2661859B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/QuantumUNET/Components/QNetworkIdentity.cs b/QuantumUNET/Components/QNetworkIdentity.cs index 080f2ae2..08c4097f 100644 --- a/QuantumUNET/Components/QNetworkIdentity.cs +++ b/QuantumUNET/Components/QNetworkIdentity.cs @@ -321,6 +321,132 @@ namespace QuantumUNET.Components } } + private bool GetInvokeComponent(int cmdHash, Type invokeClass, out QNetworkBehaviour invokeComponent) + { + QNetworkBehaviour networkBehaviour = null; + foreach (var networkBehaviour2 in m_NetworkBehaviours) + { + if (networkBehaviour2.GetType() == invokeClass || networkBehaviour2.GetType().IsSubclassOf(invokeClass)) + { + networkBehaviour = networkBehaviour2; + break; + } + } + + bool result; + if (networkBehaviour == null) + { + var cmdHashHandlerName = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); + QLog.FatalError( + $"Found no behaviour for incoming [{cmdHashHandlerName}] on {gameObject}, the server and client should have the same NetworkBehaviour instances [netId={NetId}]."); + invokeComponent = null; + result = false; + } + else + { + invokeComponent = networkBehaviour; + result = true; + } + + return result; + } + + internal void HandleSyncEvent(int cmdHash, QNetworkReader reader) + { + if (gameObject == null) + { + var cmdHashHandlerName = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); + QLog.Warning($"SyncEvent [{cmdHashHandlerName}] received for deleted object [netId={NetId}]"); + } + else if (!QNetworkBehaviour.GetInvokerForHashSyncEvent(cmdHash, out var invokeClass, out var cmdDelegate)) + { + var cmdHashHandlerName2 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); + QLog.FatalError( + $"Found no receiver for incoming [{cmdHashHandlerName2}] on {gameObject}, the server and client should have the same NetworkBehaviour instances [netId={NetId}]."); + } + else if (!GetInvokeComponent(cmdHash, invokeClass, out var obj)) + { + var cmdHashHandlerName3 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); + QLog.Warning($"SyncEvent [{cmdHashHandlerName3}] handler not found [netId={NetId}]"); + } + else + { + cmdDelegate(obj, reader); + } + } + + internal void HandleSyncList(int cmdHash, QNetworkReader reader) + { + if (gameObject == null) + { + var cmdHashHandlerName = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); + QLog.Warning($"SyncList [{cmdHashHandlerName}] received for deleted object [netId={NetId}]"); + } + else if (!QNetworkBehaviour.GetInvokerForHashSyncList(cmdHash, out var invokeClass, out var cmdDelegate)) + { + var cmdHashHandlerName2 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); + QLog.FatalError( + $"Found no receiver for incoming [{cmdHashHandlerName2}] on {gameObject}, the server and client should have the same NetworkBehaviour instances [netId={NetId}]."); + } + else if (!GetInvokeComponent(cmdHash, invokeClass, out var obj)) + { + var cmdHashHandlerName3 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); + QLog.Warning($"SyncList [{cmdHashHandlerName3}] handler not found [netId={NetId}]"); + } + else + { + cmdDelegate(obj, reader); + } + } + + internal void HandleCommand(int cmdHash, QNetworkReader reader) + { + if (gameObject == null) + { + var cmdHashHandlerName = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); + QLog.Warning($"Command [{cmdHashHandlerName}] received for deleted object [netId={NetId}]"); + } + else if (!QNetworkBehaviour.GetInvokerForHashCommand(cmdHash, out var invokeClass, out var cmdDelegate)) + { + var cmdHashHandlerName2 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); + QLog.FatalError( + $"Found no receiver for incoming [{cmdHashHandlerName2}] on {gameObject}, the server and client should have the same NetworkBehaviour instances [netId={NetId}]."); + } + else if (!GetInvokeComponent(cmdHash, invokeClass, out var obj)) + { + var cmdHashHandlerName3 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); + QLog.Warning($"Command [{cmdHashHandlerName3}] handler not found [netId={NetId}]"); + } + else + { + cmdDelegate(obj, reader); + } + } + + internal void HandleRPC(int cmdHash, QNetworkReader reader) + { + if (gameObject == null) + { + var cmdHashHandlerName = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); + QLog.Warning($"ClientRpc [{cmdHashHandlerName}] received for deleted object [netId={NetId}]"); + } + else if (!QNetworkBehaviour.GetInvokerForHashClientRpc(cmdHash, out var invokeClass, out var cmdDelegate)) + { + var cmdHashHandlerName2 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); + QLog.FatalError( + $"Found no receiver for incoming [{cmdHashHandlerName2}] on {gameObject}, the server and client should have the same NetworkBehaviour instances [netId={NetId}]."); + } + else if (!GetInvokeComponent(cmdHash, invokeClass, out var obj)) + { + var cmdHashHandlerName3 = QNetworkBehaviour.GetCmdHashHandlerName(cmdHash); + QLog.Warning($"ClientRpc [{cmdHashHandlerName3}] handler not found [netId={NetId}]"); + } + else + { + cmdDelegate(obj, reader); + } + } + internal void UNetUpdate() { var num = 0U; @@ -370,7 +496,7 @@ namespace QuantumUNET.Components if (flag) { s_UpdateWriter.FinishMessage(); - QNetworkServer.SendWriterToReady(gameObject, s_UpdateWriter); + QNetworkServer.SendWriterToReady(gameObject, s_UpdateWriter, j); } } diff --git a/QuantumUNET/Components/QNetworkTransform.cs b/QuantumUNET/Components/QNetworkTransform.cs index aa96caff..21cb794c 100644 --- a/QuantumUNET/Components/QNetworkTransform.cs +++ b/QuantumUNET/Components/QNetworkTransform.cs @@ -140,7 +140,7 @@ namespace QuantumUNET.Components _prevRotation = transform.rotation; _localTransformWriter.FinishMessage(); - QClientScene.readyConnection.SendWriter(_localTransformWriter); + QClientScene.readyConnection.SendWriter(_localTransformWriter, GetNetworkChannel()); } } @@ -200,6 +200,9 @@ namespace QuantumUNET.Components return rotation; } + public override int GetNetworkChannel() + => 1; + public override float GetNetworkSendInterval() => SendInterval; } diff --git a/QuantumUNET/Components/QNetworkTransformChild.cs b/QuantumUNET/Components/QNetworkTransformChild.cs index dace4ee2..79c7b1d9 100644 --- a/QuantumUNET/Components/QNetworkTransformChild.cs +++ b/QuantumUNET/Components/QNetworkTransformChild.cs @@ -8,6 +8,7 @@ namespace QuantumUNET.Components { public class QNetworkTransformChild : QNetworkBehaviour { + public override int GetNetworkChannel() => 1; public override float GetNetworkSendInterval() => m_SendInterval; public Transform m_Target; public uint m_ChildIndex; @@ -245,7 +246,7 @@ namespace QuantumUNET.Components _prevPosition = m_Target.localPosition; _prevRotation = m_Target.localRotation; _localTransformWriter.FinishMessage(); - QClientScene.readyConnection.SendWriter(_localTransformWriter); + QClientScene.readyConnection.SendWriter(_localTransformWriter, GetNetworkChannel()); } } diff --git a/QuantumUNET/Messages/QMsgType.cs b/QuantumUNET/Messages/QMsgType.cs index 136142a1..e3e3b367 100644 --- a/QuantumUNET/Messages/QMsgType.cs +++ b/QuantumUNET/Messages/QMsgType.cs @@ -24,10 +24,14 @@ } public const short ObjectDestroy = 1; + public const short Rpc = 2; public const short ObjectSpawn = 3; public const short Owner = 4; + public const short Command = 5; public const short LocalPlayerTransform = 6; + public const short SyncEvent = 7; public const short UpdateVars = 8; + public const short SyncList = 9; public const short ObjectSpawnScene = 10; public const short NetworkInfo = 11; public const short SpawnFinished = 12; @@ -65,10 +69,14 @@ internal static string[] msgLabels = { "none", "ObjectDestroy", + "Rpc", "ObjectSpawn", "Owner", + "Command", "LocalPlayerTransform", + "SyncEvent", "UpdateVars", + "SyncList", "ObjectSpawnScene", "NetworkInfo", "SpawnFinished", diff --git a/QuantumUNET/Messages/QNetworkMessage.cs b/QuantumUNET/Messages/QNetworkMessage.cs index 45bbdcc6..e5dbc590 100644 --- a/QuantumUNET/Messages/QNetworkMessage.cs +++ b/QuantumUNET/Messages/QNetworkMessage.cs @@ -8,6 +8,7 @@ namespace QuantumUNET.Messages public short MsgType; public QNetworkConnection Connection; public QNetworkReader Reader; + public int ChannelId; public TMsg ReadMessage() where TMsg : QMessageBase, new() { diff --git a/QuantumUNET/QClientScene.cs b/QuantumUNET/QClientScene.cs index eabb16e4..02cf7148 100644 --- a/QuantumUNET/QClientScene.cs +++ b/QuantumUNET/QClientScene.cs @@ -17,6 +17,8 @@ namespace QuantumUNET public static QNetworkConnection readyConnection { get; private set; } + public static int reconnectId { get; private set; } = -1; + public static Dictionary Objects => s_NetworkScene.localObjects; public static Dictionary Prefabs => QNetworkScene.guidToPrefab; @@ -32,6 +34,7 @@ namespace QuantumUNET readyConnection = null; ready = false; s_IsSpawnFinished = false; + reconnectId = -1; NetworkTransport.Shutdown(); NetworkTransport.Init(); } @@ -288,6 +291,7 @@ namespace QuantumUNET client.RegisterHandlerSafe(QMsgType.ObjectSpawn, OnObjectSpawn); client.RegisterHandlerSafe(QMsgType.Owner, OnOwnerMessage); client.RegisterHandlerSafe(QMsgType.UpdateVars, OnUpdateVarsMessage); + client.RegisterHandlerSafe(QMsgType.SyncList, OnSyncListMessage); client.RegisterHandlerSafe(QMsgType.ObjectSpawnScene, OnObjectSpawnScene); client.RegisterHandlerSafe(QMsgType.SpawnFinished, OnObjectSpawnFinished); client.RegisterHandlerSafe(QMsgType.ObjectHide, OnObjectDestroy); @@ -296,6 +300,8 @@ namespace QuantumUNET client.RegisterHandlerSafe(QMsgType.AnimationParameters, QNetworkAnimator.OnAnimationParametersClientMessage); } + client.RegisterHandlerSafe(QMsgType.Rpc, OnRPCMessage); + client.RegisterHandlerSafe(QMsgType.SyncEvent, OnSyncEventMessage); client.RegisterHandlerSafe(QMsgType.AnimationTrigger, QNetworkAnimator.OnAnimationTriggerClientMessage); } @@ -538,6 +544,52 @@ namespace QuantumUNET } } + private static void OnRPCMessage(QNetworkMessage netMsg) + { + var num = (int)netMsg.Reader.ReadPackedUInt32(); + var networkInstanceId = netMsg.Reader.ReadNetworkId(); + Debug.Log($"ClientScene::OnRPCMessage hash:{num} netId:{networkInstanceId}"); + if (s_NetworkScene.GetNetworkIdentity(networkInstanceId, out var networkIdentity)) + { + networkIdentity.HandleRPC(num, netMsg.Reader); + } + else + { + var cmdHashHandlerName = QNetworkBehaviour.GetCmdHashHandlerName(num); + Debug.LogWarningFormat("Could not find target object with netId:{0} for RPC call {1}", networkInstanceId, cmdHashHandlerName); + } + } + + private static void OnSyncEventMessage(QNetworkMessage netMsg) + { + var cmdHash = (int)netMsg.Reader.ReadPackedUInt32(); + var networkInstanceId = netMsg.Reader.ReadNetworkId(); + Debug.Log($"ClientScene::OnSyncEventMessage {networkInstanceId}"); + if (s_NetworkScene.GetNetworkIdentity(networkInstanceId, out var networkIdentity)) + { + networkIdentity.HandleSyncEvent(cmdHash, netMsg.Reader); + } + else + { + Debug.LogWarning($"Did not find target for SyncEvent message for {networkInstanceId}"); + } + } + + private static void OnSyncListMessage(QNetworkMessage netMsg) + { + var networkInstanceId = netMsg.Reader.ReadNetworkId(); + var cmdHash = (int)netMsg.Reader.ReadPackedUInt32(); + Debug.Log($"ClientScene::OnSyncListMessage {networkInstanceId}"); + if (s_NetworkScene.GetNetworkIdentity(networkInstanceId, out var networkIdentity)) + { + networkIdentity.HandleSyncList(cmdHash, netMsg.Reader); + } + else + { + Debug.LogWarning($"Did not find target for SyncList message for {networkInstanceId}"); + } + } + private static void OnClientAuthority(QNetworkMessage netMsg) { netMsg.ReadMessage(s_ClientAuthorityMessage); diff --git a/QuantumUNET/QLocalClient.cs b/QuantumUNET/QLocalClient.cs index 52214ae0..63882036 100644 --- a/QuantumUNET/QLocalClient.cs +++ b/QuantumUNET/QLocalClient.cs @@ -64,10 +64,11 @@ namespace QuantumUNET QClientScene.InternalAddPlayer(unetView, localPlayer.PlayerControllerId); } - private void PostInternalMessage(byte[] buffer) + private void PostInternalMessage(byte[] buffer, int channelId) { var item = m_FreeMessages.Count == 0 ? default : m_FreeMessages.Pop(); item.buffer = buffer; + item.channelId = channelId; m_InternalMsgs.Add(item); } @@ -76,7 +77,7 @@ namespace QuantumUNET var networkWriter = new QNetworkWriter(); networkWriter.StartMessage(msgType); networkWriter.FinishMessage(); - PostInternalMessage(networkWriter.AsArray()); + PostInternalMessage(networkWriter.AsArray(), 0); } private void ProcessInternalMessages() @@ -97,6 +98,7 @@ namespace QuantumUNET } s_InternalMessage.Reader.ReadInt16(); + s_InternalMessage.ChannelId = msg.channelId; s_InternalMessage.Connection = connection; s_InternalMessage.MsgType = s_InternalMessage.Reader.ReadInt16(); m_Connection.InvokeHandler(s_InternalMessage); @@ -115,16 +117,16 @@ namespace QuantumUNET } } - internal void InvokeHandlerOnClient(short msgType, QMessageBase msg) + internal void InvokeHandlerOnClient(short msgType, QMessageBase msg, int channelId) { var networkWriter = new QNetworkWriter(); networkWriter.StartMessage(msgType); msg.Serialize(networkWriter); networkWriter.FinishMessage(); - InvokeBytesOnClient(networkWriter.AsArray()); + InvokeBytesOnClient(networkWriter.AsArray(), channelId); } - internal void InvokeBytesOnClient(byte[] buffer) => PostInternalMessage(buffer); + internal void InvokeBytesOnClient(byte[] buffer, int channelId) => PostInternalMessage(buffer, channelId); private const int k_InitialFreeMessagePoolSize = 64; @@ -143,6 +145,8 @@ namespace QuantumUNET private struct InternalMsg { internal byte[] buffer; + + internal int channelId; } } } \ No newline at end of file diff --git a/QuantumUNET/QNetworkBehaviour.cs b/QuantumUNET/QNetworkBehaviour.cs index 08bfc23d..d3db0580 100644 --- a/QuantumUNET/QNetworkBehaviour.cs +++ b/QuantumUNET/QNetworkBehaviour.cs @@ -67,20 +67,428 @@ namespace QuantumUNET { ClearAllDirtyBits(); writer.FinishMessage(); - QClientScene.readyConnection.SendWriter(writer); + QClientScene.readyConnection.SendWriter(writer, GetNetworkChannel()); } } - protected void SendEventInternal(QNetworkWriter writer, string eventName) + protected void SendCommandInternal(QNetworkWriter writer, int channelId, string cmdName) { - if (!QNetworkServer.active) + if (!IsLocalPlayer && !HasAuthority) { - QLog.Error($"Tried to send event {eventName} but QSBNetworkServer isn't active."); + QLog.Warning("Trying to send command for object without authority."); + } + else if (QClientScene.readyConnection == null) + { + QLog.Error($"Send command attempted with no client running [client={ConnectionToServer}]."); + } + else + { + writer.FinishMessage(); + QClientScene.readyConnection.SendWriter(writer, channelId); + } + } + + public virtual bool InvokeCommand(int cmdHash, QNetworkReader reader) => InvokeCommandDelegate(cmdHash, reader); + + protected void SendRPCInternal(QNetworkWriter writer, int channelId, string rpcName) + { + if (!IsServer) + { + QLog.Warning("ClientRpc call on un-spawned object"); return; } writer.FinishMessage(); - QNetworkServer.SendWriterToReady(gameObject, writer); + QNetworkServer.SendWriterToReady(gameObject, writer, channelId); + } + + protected void SendTargetRPCInternal(QNetworkConnection conn, QNetworkWriter writer, int channelId, string rpcName) + { + if (!IsServer) + { + QLog.Warning("TargetRpc call on un-spawned object"); + return; + } + + writer.FinishMessage(); + conn.SendWriter(writer, channelId); + } + + public virtual bool InvokeRPC(int cmdHash, QNetworkReader reader) => InvokeRpcDelegate(cmdHash, reader); + + protected void SendEventInternal(QNetworkWriter writer, int channelId, string eventName) + { + if (!QNetworkServer.active) + { + QLog.Error($"Tried to send event {eventName} on channel {channelId} but QSBNetworkServer isn't active."); + return; + } + + writer.FinishMessage(); + QNetworkServer.SendWriterToReady(gameObject, writer, channelId); + } + + public virtual bool InvokeSyncEvent(int cmdHash, QNetworkReader reader) => InvokeSyncEventDelegate(cmdHash, reader); + + public virtual bool InvokeSyncList(int cmdHash, QNetworkReader reader) => InvokeSyncListDelegate(cmdHash, reader); + + protected static void RegisterCommandDelegate(Type invokeClass, int cmdHash, CmdDelegate func) + { + if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) + { + var invoker = new Invoker + { + invokeType = UNetInvokeType.Command, + invokeClass = invokeClass, + invokeFunction = func + }; + s_CmdHandlerDelegates[cmdHash] = invoker; + } + } + + protected static void RegisterRpcDelegate(Type invokeClass, int cmdHash, CmdDelegate func) + { + if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) + { + var invoker = new Invoker + { + invokeType = UNetInvokeType.ClientRpc, + invokeClass = invokeClass, + invokeFunction = func + }; + s_CmdHandlerDelegates[cmdHash] = invoker; + } + } + + protected static void RegisterEventDelegate(Type invokeClass, int cmdHash, CmdDelegate func) + { + if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) + { + var invoker = new Invoker + { + invokeType = UNetInvokeType.SyncEvent, + invokeClass = invokeClass, + invokeFunction = func + }; + s_CmdHandlerDelegates[cmdHash] = invoker; + } + } + + protected static void RegisterSyncListDelegate(Type invokeClass, int cmdHash, CmdDelegate func) + { + if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) + { + var invoker = new Invoker + { + invokeType = UNetInvokeType.SyncList, + invokeClass = invokeClass, + invokeFunction = func + }; + s_CmdHandlerDelegates[cmdHash] = invoker; + } + } + + internal static string GetInvoker(int cmdHash) + { + string result; + if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) + { + result = null; + } + else + { + var invoker = s_CmdHandlerDelegates[cmdHash]; + result = invoker.DebugString(); + } + + return result; + } + + internal static bool GetInvokerForHashCommand(int cmdHash, out Type invokeClass, out CmdDelegate invokeFunction) + => GetInvokerForHash(cmdHash, UNetInvokeType.Command, out invokeClass, out invokeFunction); + + internal static bool GetInvokerForHashClientRpc(int cmdHash, out Type invokeClass, out CmdDelegate invokeFunction) + => GetInvokerForHash(cmdHash, UNetInvokeType.ClientRpc, out invokeClass, out invokeFunction); + + internal static bool GetInvokerForHashSyncList(int cmdHash, out Type invokeClass, out CmdDelegate invokeFunction) + => GetInvokerForHash(cmdHash, UNetInvokeType.SyncList, out invokeClass, out invokeFunction); + + internal static bool GetInvokerForHashSyncEvent(int cmdHash, out Type invokeClass, out CmdDelegate invokeFunction) + => GetInvokerForHash(cmdHash, UNetInvokeType.SyncEvent, out invokeClass, out invokeFunction); + + private static bool GetInvokerForHash(int cmdHash, UNetInvokeType invokeType, out Type invokeClass, out CmdDelegate invokeFunction) + { + bool result; + if (!s_CmdHandlerDelegates.TryGetValue(cmdHash, out var invoker)) + { + QLog.Error($"GetInvokerForHash hash:{cmdHash} not found"); + invokeClass = null; + invokeFunction = null; + result = false; + } + else if (invoker == null) + { + QLog.Error($"GetInvokerForHash hash:{cmdHash} invoker null"); + invokeClass = null; + invokeFunction = null; + result = false; + } + else if (invoker.invokeType != invokeType) + { + QLog.Error($"GetInvokerForHash hash:{cmdHash} mismatched invokeType"); + invokeClass = null; + invokeFunction = null; + result = false; + } + else + { + invokeClass = invoker.invokeClass; + invokeFunction = invoker.invokeFunction; + result = true; + } + + return result; + } + + internal static void DumpInvokers() + { + QLog.Log($"DumpInvokers size:{s_CmdHandlerDelegates.Count}"); + foreach (var keyValuePair in s_CmdHandlerDelegates) + { + QLog.Log($" Invoker:{keyValuePair.Value.invokeClass}:{keyValuePair.Value.invokeFunction.GetMethodName()} {keyValuePair.Value.invokeType} {keyValuePair.Key}"); + } + } + + internal bool ContainsCommandDelegate(int cmdHash) + => s_CmdHandlerDelegates.ContainsKey(cmdHash); + + internal bool InvokeCommandDelegate(int cmdHash, QNetworkReader reader) + { + bool result; + if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) + { + result = false; + } + else + { + var invoker = s_CmdHandlerDelegates[cmdHash]; + if (invoker.invokeType != UNetInvokeType.Command) + { + result = false; + } + else + { + if (GetType() != invoker.invokeClass) + { + if (!GetType().IsSubclassOf(invoker.invokeClass)) + { + return false; + } + } + + invoker.invokeFunction(this, reader); + result = true; + } + } + + return result; + } + + internal bool InvokeRpcDelegate(int cmdHash, QNetworkReader reader) + { + bool result; + if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) + { + result = false; + } + else + { + var invoker = s_CmdHandlerDelegates[cmdHash]; + if (invoker.invokeType != UNetInvokeType.ClientRpc) + { + result = false; + } + else + { + if (GetType() != invoker.invokeClass) + { + if (!GetType().IsSubclassOf(invoker.invokeClass)) + { + return false; + } + } + + invoker.invokeFunction(this, reader); + result = true; + } + } + + return result; + } + + internal bool InvokeSyncEventDelegate(int cmdHash, QNetworkReader reader) + { + bool result; + if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) + { + result = false; + } + else + { + var invoker = s_CmdHandlerDelegates[cmdHash]; + if (invoker.invokeType != UNetInvokeType.SyncEvent) + { + result = false; + } + else + { + invoker.invokeFunction(this, reader); + result = true; + } + } + + return result; + } + + internal bool InvokeSyncListDelegate(int cmdHash, QNetworkReader reader) + { + bool result; + if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) + { + result = false; + } + else + { + var invoker = s_CmdHandlerDelegates[cmdHash]; + if (invoker.invokeType != UNetInvokeType.SyncList) + { + result = false; + } + else if (GetType() != invoker.invokeClass) + { + result = false; + } + else + { + invoker.invokeFunction(this, reader); + result = true; + } + } + + return result; + } + + internal static string GetCmdHashHandlerName(int cmdHash) + { + string result; + if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) + { + result = cmdHash.ToString(); + } + else + { + var invoker = s_CmdHandlerDelegates[cmdHash]; + result = $"{invoker.invokeType}:{invoker.invokeFunction.GetMethodName()}"; + } + + return result; + } + + private static string GetCmdHashPrefixName(int cmdHash, string prefix) + { + string result; + if (!s_CmdHandlerDelegates.ContainsKey(cmdHash)) + { + result = cmdHash.ToString(); + } + else + { + var invoker = s_CmdHandlerDelegates[cmdHash]; + var text = invoker.invokeFunction.GetMethodName(); + var num = text.IndexOf(prefix); + if (num > -1) + { + text = text.Substring(prefix.Length); + } + + result = text; + } + + return result; + } + + internal static string GetCmdHashCmdName(int cmdHash) + => GetCmdHashPrefixName(cmdHash, "InvokeCmd"); + + internal static string GetCmdHashRpcName(int cmdHash) + => GetCmdHashPrefixName(cmdHash, "InvokeRpc"); + + internal static string GetCmdHashEventName(int cmdHash) + => GetCmdHashPrefixName(cmdHash, "InvokeSyncEvent"); + + internal static string GetCmdHashListName(int cmdHash) + => GetCmdHashPrefixName(cmdHash, "InvokeSyncList"); + + protected void SetSyncVarGameObject(GameObject newGameObject, ref GameObject gameObjectField, uint dirtyBit, ref NetworkInstanceId netIdField) + { + if (!SyncVarHookGuard) + { + NetworkInstanceId networkInstanceId = default; + if (newGameObject != null) + { + var component = newGameObject.GetComponent(); + if (component != null) + { + networkInstanceId = component.NetId; + if (networkInstanceId.IsEmpty()) + { + QLog.Warning( + $"SetSyncVarGameObject GameObject {newGameObject} has a zero netId. Maybe it is not spawned yet?"); + } + } + } + + NetworkInstanceId networkInstanceId2 = default; + if (gameObjectField != null) + { + networkInstanceId2 = gameObjectField.GetComponent().NetId; + } + + if (networkInstanceId != networkInstanceId2) + { + QLog.Log( + $"SetSyncVar GameObject {GetType().Name} bit [{dirtyBit}] netfieldId:{networkInstanceId2}->{networkInstanceId}"); + SetDirtyBit(dirtyBit); + gameObjectField = newGameObject; + netIdField = networkInstanceId; + } + } + } + + protected bool SetSyncVar(T value, ref T fieldValue, uint dirtyBit) + { + var shouldSet = false; + if (value == null) + { + if (fieldValue != null) + { + shouldSet = true; + } + } + else + { + shouldSet = !value.Equals(fieldValue); + } + + if (shouldSet) + { + QLog.Log($"SetSyncVar {GetType().Name} bit [{dirtyBit}] {fieldValue}->{value}"); + + SetDirtyBit(dirtyBit); + fieldValue = value; + } + + return shouldSet; } public void SetDirtyBit(uint dirtyBit) => SyncVarDirtyBits |= dirtyBit; @@ -97,7 +505,7 @@ namespace QuantumUNET { if (SyncVarDirtyBits != 0U) { - return 0; + return GetNetworkChannel(); } } @@ -158,14 +566,36 @@ namespace QuantumUNET public virtual bool OnCheckObserver(QNetworkConnection conn) => true; + public virtual int GetNetworkChannel() => 0; + public virtual float GetNetworkSendInterval() => 0.1f; private float m_LastSendTime; private QNetworkIdentity m_MyView; + private static readonly Dictionary s_CmdHandlerDelegates = new(); + public delegate void CmdDelegate(QNetworkBehaviour obj, QNetworkReader reader); protected delegate void EventDelegate(List targets, QNetworkReader reader); + + protected enum UNetInvokeType + { + Command, + ClientRpc, + SyncEvent, + SyncList + } + + protected class Invoker + { + public string DebugString() => + $"{invokeType}:{invokeClass}:{invokeFunction.GetMethodName()}"; + + public UNetInvokeType invokeType; + public Type invokeClass; + public CmdDelegate invokeFunction; + } } internal static class DotNetCompatibility diff --git a/QuantumUNET/QNetworkClient.cs b/QuantumUNET/QNetworkClient.cs index ffc9fe62..4338e843 100644 --- a/QuantumUNET/QNetworkClient.cs +++ b/QuantumUNET/QNetworkClient.cs @@ -225,7 +225,7 @@ namespace QuantumUNET return result; } - public bool SendWriter(QNetworkWriter writer) + public bool SendWriter(QNetworkWriter writer, int channelId) { bool result; if (m_Connection != null) @@ -237,7 +237,7 @@ namespace QuantumUNET } else { - result = m_Connection.SendWriter(writer); + result = m_Connection.SendWriter(writer, channelId); } } else @@ -249,7 +249,7 @@ namespace QuantumUNET return result; } - public bool SendBytes(byte[] data, int numBytes) + public bool SendBytes(byte[] data, int numBytes, int channelId) { bool result; if (m_Connection != null) @@ -261,7 +261,7 @@ namespace QuantumUNET } else { - result = m_Connection.SendBytes(data, numBytes); + result = m_Connection.SendBytes(data, numBytes, channelId); } } else @@ -273,7 +273,31 @@ namespace QuantumUNET return result; } - public bool SendByChannel(short msgType, QMessageBase msg) + public bool SendUnreliable(short msgType, QMessageBase msg) + { + bool result; + if (m_Connection != null) + { + if (m_AsyncConnect != ConnectState.Connected) + { + QLog.Error("NetworkClient SendUnreliable when not connected to a server"); + result = false; + } + else + { + result = m_Connection.SendUnreliable(msgType, msg); + } + } + else + { + QLog.Error("NetworkClient SendUnreliable with no connection"); + result = false; + } + + return result; + } + + public bool SendByChannel(short msgType, QMessageBase msg, int channelId) { bool result; if (m_Connection != null) @@ -285,7 +309,7 @@ namespace QuantumUNET } else { - result = m_Connection.SendByChannel(msgType, msg); + result = m_Connection.SendByChannel(msgType, msg, channelId); } } else @@ -479,7 +503,8 @@ namespace QuantumUNET { MsgType = QMsgType.Error, Reader = reader, - Connection = m_Connection + Connection = m_Connection, + ChannelId = 0 }); } } diff --git a/QuantumUNET/QNetworkConnection.cs b/QuantumUNET/QNetworkConnection.cs index f82cd984..8ac69664 100644 --- a/QuantumUNET/QNetworkConnection.cs +++ b/QuantumUNET/QNetworkConnection.cs @@ -39,14 +39,18 @@ namespace QuantumUNET throw new ArgumentOutOfRangeException("Platform specific protocols are not supported on this platform"); } - var channelQOS = hostTopology.DefaultConfig.Channels[0]; - var bufferSize = packetSize; - if (channelQOS.QOS is QosType.ReliableFragmented or QosType.UnreliableFragmented) + m_Channels = new QChannelBuffer[channelCount]; + for (var i = 0; i < channelCount; i++) { - bufferSize = hostTopology.DefaultConfig.FragmentSize * 128; - } + var channelQOS = hostTopology.DefaultConfig.Channels[i]; + var bufferSize = packetSize; + if (channelQOS.QOS is QosType.ReliableFragmented or QosType.UnreliableFragmented) + { + bufferSize = hostTopology.DefaultConfig.FragmentSize * 128; + } - m_Channel = new QChannelBuffer(this, bufferSize, 0, IsReliableQoS(channelQOS.QOS), IsSequencedQoS(channelQOS.QOS)); + m_Channels[i] = new QChannelBuffer(this, bufferSize, (byte)i, IsReliableQoS(channelQOS.QOS), IsSequencedQoS(channelQOS.QOS)); + } } ~QNetworkConnection() @@ -62,12 +66,15 @@ namespace QuantumUNET protected virtual void Dispose(bool disposing) { - if (!m_Disposed && m_Channel != null) + if (!m_Disposed && m_Channels != null) { - m_Channel.Dispose(); + foreach (var channel in m_Channels) + { + channel.Dispose(); + } } - m_Channel = null; + m_Channels = null; if (ClientOwnedObjects != null) { foreach (var netId in ClientOwnedObjects) @@ -88,7 +95,7 @@ namespace QuantumUNET private static bool IsReliableQoS(QosType qos) => qos is QosType.Reliable or QosType.ReliableFragmented or QosType.ReliableSequenced or QosType.ReliableStateUpdate; - public bool SetChannelOption(int channelId, ChannelOption option, int value) => m_Channel != null && channelId >= 0 && m_Channel.SetOption(option, value); + public bool SetChannelOption(int channelId, ChannelOption option, int value) => m_Channels != null && channelId >= 0 && channelId < m_Channels.Length && m_Channels[channelId].SetOption(option, value); public void Disconnect() { @@ -110,9 +117,9 @@ namespace QuantumUNET public bool CheckHandler(short msgType) => m_MessageHandlersDict.ContainsKey(msgType); - public bool InvokeHandlerNoData(short msgType) => InvokeHandler(msgType, null); + public bool InvokeHandlerNoData(short msgType) => InvokeHandler(msgType, null, 0); - public bool InvokeHandler(short msgType, QNetworkReader reader) + public bool InvokeHandler(short msgType, QNetworkReader reader, int channelId) { bool result; if (m_MessageHandlersDict.ContainsKey(msgType)) @@ -120,6 +127,7 @@ namespace QuantumUNET m_MessageInfo.MsgType = msgType; m_MessageInfo.Connection = this; m_MessageInfo.Reader = reader; + m_MessageInfo.ChannelId = channelId; var networkMessageDelegate = m_MessageHandlersDict[msgType]; if (networkMessageDelegate == null) { @@ -156,6 +164,21 @@ namespace QuantumUNET return result; } + internal void HandleFragment(QNetworkReader reader, int channelId) + { + if (channelId >= 0 && channelId < m_Channels.Length) + { + var channelBuffer = m_Channels[channelId]; + if (channelBuffer.HandleFragment(reader)) + { + var networkReader = new QNetworkReader(channelBuffer._fragmentBuffer.AsArraySegment().Array); + networkReader.ReadInt16(); + var msgType = networkReader.ReadInt16(); + InvokeHandler(msgType, networkReader, channelId); + } + } + } + public void RegisterHandler(short msgType, QNetworkMessageDelegate handler) => m_MessageHandlers.RegisterHandler(msgType, handler); public void UnregisterHandler(short msgType) => m_MessageHandlers.UnregisterHandler(msgType); @@ -211,33 +234,41 @@ namespace QuantumUNET public void FlushChannels() { - if (m_Channel != null) + if (m_Channels != null) { - m_Channel.CheckInternalBuffer(); + foreach (var channel in m_Channels) + { + channel.CheckInternalBuffer(); + } } } public void SetMaxDelay(float seconds) { - if (m_Channel != null) + if (m_Channels != null) { - m_Channel.MaxDelay = seconds; + foreach (var channel in m_Channels) + { + channel.MaxDelay = seconds; + } } } - public virtual bool Send(short msgType, QMessageBase msg) => SendByChannel(msgType, msg); + public virtual bool Send(short msgType, QMessageBase msg) => SendByChannel(msgType, msg, 0); - public virtual bool SendByChannel(short msgType, QMessageBase msg) + public virtual bool SendUnreliable(short msgType, QMessageBase msg) => SendByChannel(msgType, msg, 1); + + public virtual bool SendByChannel(short msgType, QMessageBase msg, int channelId) { m_Writer.StartMessage(msgType); msg.Serialize(m_Writer); m_Writer.FinishMessage(); - return SendWriter(m_Writer); + return SendWriter(m_Writer, channelId); } - public virtual bool SendBytes(byte[] bytes, int numBytes) => m_Channel.SendBytes(bytes, numBytes); + public virtual bool SendBytes(byte[] bytes, int numBytes, int channelId) => CheckChannel(channelId) && m_Channels[channelId].SendBytes(bytes, numBytes); - public virtual bool SendWriter(QNetworkWriter writer) => m_Channel.SendWriter(writer); + public virtual bool SendWriter(QNetworkWriter writer, int channelId) => CheckChannel(channelId) && m_Channels[channelId].SendWriter(writer); private void LogSend(byte[] bytes) { @@ -258,6 +289,28 @@ namespace QuantumUNET $"ConnectionSend con:{connectionId} bytes:{num} msgId:{num2} {stringBuilder}"); } + private bool CheckChannel(int channelId) + { + bool result; + if (m_Channels == null) + { + QLog.Warning($"Channels not initialized sending on id '{channelId}"); + result = false; + } + else if (channelId < 0 || channelId >= m_Channels.Length) + { + QLog.Error( + $"Invalid channel when sending buffered data, '{channelId}'. Current channel count is {m_Channels.Length}"); + result = false; + } + else + { + result = true; + } + + return result; + } + public void ResetStats() { } @@ -291,13 +344,14 @@ namespace QuantumUNET m_NetMsg.MsgType = num2; m_NetMsg.Reader = reader2; m_NetMsg.Connection = this; + m_NetMsg.ChannelId = channelId; networkMessageDelegate(m_NetMsg); lastMessageTime = Time.time; } } public override string ToString() => - $"hostId: {hostId} connectionId: {connectionId} isReady: {isReady}"; + $"hostId: {hostId} connectionId: {connectionId} isReady: {isReady} channel count: {m_Channels?.Length ?? 0}"; internal void AddToVisList(QNetworkIdentity uv) { @@ -340,7 +394,9 @@ namespace QuantumUNET internal void RemoveOwnedObject(QNetworkIdentity obj) => ClientOwnedObjects?.Remove(obj.NetId); - private QChannelBuffer m_Channel; + internal static void OnFragment(QNetworkMessage netMsg) => netMsg.Connection.HandleFragment(netMsg.Reader, netMsg.ChannelId); + + private QChannelBuffer[] m_Channels; private readonly QNetworkMessage m_NetMsg = new(); private QNetworkWriter m_Writer; diff --git a/QuantumUNET/QNetworkServer.cs b/QuantumUNET/QNetworkServer.cs index facae77c..b2c901dc 100644 --- a/QuantumUNET/QNetworkServer.cs +++ b/QuantumUNET/QNetworkServer.cs @@ -101,6 +101,7 @@ namespace QuantumUNET { m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.ClientUpdateVars, OnUpdateVarsMessage); m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.Ready, OnClientReadyMessage); + m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.Command, OnCommandMessage); m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.LocalPlayerTransform, QNetworkTransform.HandleTransform); m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.LocalChildTransform, QNetworkTransformChild.HandleChildTransform); m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.RemovePlayer, OnRemovePlayerMessage); @@ -298,7 +299,7 @@ namespace QuantumUNET return result; } - public static void SendWriterToReady(GameObject contextObj, QNetworkWriter writer) + public static void SendWriterToReady(GameObject contextObj, QNetworkWriter writer, int channelId) { var arraySegment = writer.AsArraySegment(); if (arraySegment.Count > 32767) @@ -306,10 +307,10 @@ namespace QuantumUNET throw new UnityException("NetworkWriter used buffer is too big!"); } - SendBytesToReady(contextObj, arraySegment.Array, arraySegment.Count); + SendBytesToReady(contextObj, arraySegment.Array, arraySegment.Count, channelId); } - public static void SendBytesToReady(GameObject contextObj, byte[] buffer, int numBytes) + public static void SendBytesToReady(GameObject contextObj, byte[] buffer, int numBytes, int channelId) { if (contextObj == null) { @@ -318,7 +319,7 @@ namespace QuantumUNET { if (networkConnection != null && networkConnection.isReady) { - if (!networkConnection.SendBytes(buffer, numBytes)) + if (!networkConnection.SendBytes(buffer, numBytes, channelId)) { flag = false; } @@ -342,7 +343,7 @@ namespace QuantumUNET var networkConnection2 = component.Observers[j]; if (networkConnection2.isReady) { - if (!networkConnection2.SendBytes(buffer, numBytes)) + if (!networkConnection2.SendBytes(buffer, numBytes, channelId)) { flag2 = false; } @@ -361,7 +362,7 @@ namespace QuantumUNET } } - public static void SendBytesToPlayer(GameObject player, byte[] buffer, int numBytes) + public static void SendBytesToPlayer(GameObject player, byte[] buffer, int numBytes, int channelId) { foreach (var networkConnection in connections) { @@ -371,7 +372,7 @@ namespace QuantumUNET { if (controller.IsValid && controller.Gameobject == player) { - networkConnection.SendBytes(buffer, numBytes); + networkConnection.SendBytes(buffer, numBytes, channelId); break; } } @@ -379,24 +380,24 @@ namespace QuantumUNET } } - public static bool SendByChannelToAll(short msgType, QMessageBase msg) + public static bool SendUnreliableToAll(short msgType, QMessageBase msg) { - QLog.Log($"Server.SendByChannelToAll id:{msgType}"); + QLog.Log($"Server.SendUnreliableToAll msgType:{msgType}"); var flag = true; foreach (var networkConnection in connections) { if (networkConnection != null) { - flag &= networkConnection.SendByChannel(msgType, msg); + flag &= networkConnection.SendUnreliable(msgType, msg); } } return flag; } - public static bool SendByChannelToReady(GameObject contextObj, short msgType, QMessageBase msg) + public static bool SendUnreliableToReady(GameObject contextObj, short msgType, QMessageBase msg) { - QLog.Log($"Server.SendByChannelToReady msgType:{msgType}"); + QLog.Log($"Server.SendUnreliableToReady id:{msgType}"); bool result; if (contextObj == null) { @@ -404,7 +405,7 @@ namespace QuantumUNET { if (networkConnection != null && networkConnection.isReady) { - networkConnection.SendByChannel(msgType, msg); + networkConnection.SendUnreliable(msgType, msg); } } @@ -420,7 +421,58 @@ namespace QuantumUNET var networkConnection2 = component.Observers[j]; if (networkConnection2.isReady) { - flag &= networkConnection2.SendByChannel(msgType, msg); + flag &= networkConnection2.SendUnreliable(msgType, msg); + } + } + + result = flag; + } + + return result; + } + + public static bool SendByChannelToAll(short msgType, QMessageBase msg, int channelId) + { + QLog.Log($"Server.SendByChannelToAll id:{msgType}"); + var flag = true; + foreach (var networkConnection in connections) + { + if (networkConnection != null) + { + flag &= networkConnection.SendByChannel(msgType, msg, channelId); + } + } + + return flag; + } + + public static bool SendByChannelToReady(GameObject contextObj, short msgType, QMessageBase msg, int channelId) + { + QLog.Log($"Server.SendByChannelToReady msgType:{msgType}"); + bool result; + if (contextObj == null) + { + foreach (var networkConnection in connections) + { + if (networkConnection != null && networkConnection.isReady) + { + networkConnection.SendByChannel(msgType, msg, channelId); + } + } + + result = true; + } + else + { + var flag = true; + var component = contextObj.GetComponent(); + var count = component.Observers.Count; + for (var j = 0; j < count; j++) + { + var networkConnection2 = component.Observers[j]; + if (networkConnection2.isReady) + { + flag &= networkConnection2.SendByChannel(msgType, msg, channelId); } } @@ -557,7 +609,7 @@ namespace QuantumUNET var writer = new QNetworkWriter(); errorMessage.Serialize(writer); var reader = new QNetworkReader(writer); - conn.InvokeHandler(34, reader); + conn.InvokeHandler(34, reader, 0); } } @@ -880,6 +932,50 @@ namespace QuantumUNET } } + private static void OnCommandMessage(QNetworkMessage netMsg) + { + var cmdHash = (int)netMsg.Reader.ReadPackedUInt32(); + var networkInstanceId = netMsg.Reader.ReadNetworkId(); + var gameObject = FindLocalObject(networkInstanceId); + if (gameObject == null) + { + QLog.Warning($"Instance not found when handling Command message [netId={networkInstanceId}]"); + } + else + { + var component = gameObject.GetComponent(); + if (component == null) + { + QLog.Warning( + $"NetworkIdentity deleted when handling Command message [netId={networkInstanceId}]"); + } + else + { + var flag = false; + foreach (var playerController in netMsg.Connection.PlayerControllers) + { + if (playerController.Gameobject != null && playerController.Gameobject.GetComponent().NetId == component.NetId) + { + flag = true; + break; + } + } + + if (!flag) + { + if (component.ClientAuthorityOwner != netMsg.Connection) + { + QLog.Warning($"Command for object without authority [netId={networkInstanceId}]"); + return; + } + } + + QLog.Log($"OnCommandMessage for netId={networkInstanceId} conn={netMsg.Connection}"); + component.HandleCommand(cmdHash, netMsg.Reader); + } + } + } + internal void SpawnObject(GameObject obj) { if (!active) @@ -1136,7 +1232,7 @@ namespace QuantumUNET public static void UnSpawn(GameObject obj) => UnSpawnObject(obj); - internal bool InvokeBytes(QULocalConnectionToServer conn, byte[] buffer, int numBytes) + internal bool InvokeBytes(QULocalConnectionToServer conn, byte[] buffer, int numBytes, int channelId) { var networkReader = new QNetworkReader(buffer); networkReader.ReadInt16(); @@ -1144,7 +1240,7 @@ namespace QuantumUNET bool result; if (handlers.ContainsKey(num) && m_LocalConnection != null) { - m_LocalConnection.InvokeHandler(num, networkReader); + m_LocalConnection.InvokeHandler(num, networkReader, channelId); result = true; } else @@ -1155,7 +1251,7 @@ namespace QuantumUNET return result; } - internal bool InvokeHandlerOnServer(QULocalConnectionToServer conn, short msgType, QMessageBase msg) + internal bool InvokeHandlerOnServer(QULocalConnectionToServer conn, short msgType, QMessageBase msg, int channelId) { bool result; if (handlers.ContainsKey(msgType) && m_LocalConnection != null) @@ -1163,7 +1259,7 @@ namespace QuantumUNET var writer = new QNetworkWriter(); msg.Serialize(writer); var reader = new QNetworkReader(writer); - m_LocalConnection.InvokeHandler(msgType, reader); + m_LocalConnection.InvokeHandler(msgType, reader, channelId); result = true; } else diff --git a/QuantumUNET/QNetworkServerSimple.cs b/QuantumUNET/QNetworkServerSimple.cs index e1448a9d..905c9d7b 100644 --- a/QuantumUNET/QNetworkServerSimple.cs +++ b/QuantumUNET/QNetworkServerSimple.cs @@ -37,6 +37,7 @@ namespace QuantumUNET { var connectionConfig = new ConnectionConfig(); connectionConfig.AddChannel(QosType.ReliableSequenced); + connectionConfig.AddChannel(QosType.Unreliable); hostTopology = new HostTopology(connectionConfig, 8); } @@ -309,16 +310,16 @@ namespace QuantumUNET } } - public void SendBytesTo(int connectionId, byte[] bytes, int numBytes) + public void SendBytesTo(int connectionId, byte[] bytes, int numBytes, int channelId) { var networkConnection = FindConnection(connectionId); - networkConnection?.SendBytes(bytes, numBytes); + networkConnection?.SendBytes(bytes, numBytes, channelId); } - public void SendWriterTo(int connectionId, QNetworkWriter writer) + public void SendWriterTo(int connectionId, QNetworkWriter writer, int channelId) { var networkConnection = FindConnection(connectionId); - networkConnection?.SendWriter(writer); + networkConnection?.SendWriter(writer, channelId); } public void Disconnect(int connectionId) diff --git a/QuantumUNET/QULocalConnectionToClient.cs b/QuantumUNET/QULocalConnectionToClient.cs index 9de58333..adb8368d 100644 --- a/QuantumUNET/QULocalConnectionToClient.cs +++ b/QuantumUNET/QULocalConnectionToClient.cs @@ -15,25 +15,31 @@ namespace QuantumUNET public override bool Send(short msgType, QMessageBase msg) { - LocalClient.InvokeHandlerOnClient(msgType, msg); + LocalClient.InvokeHandlerOnClient(msgType, msg, 0); return true; } - public override bool SendByChannel(short msgType, QMessageBase msg) + public override bool SendUnreliable(short msgType, QMessageBase msg) { - LocalClient.InvokeHandlerOnClient(msgType, msg); + LocalClient.InvokeHandlerOnClient(msgType, msg, 1); return true; } - public override bool SendBytes(byte[] bytes, int numBytes) + public override bool SendByChannel(short msgType, QMessageBase msg, int channelId) { - LocalClient.InvokeBytesOnClient(bytes); + LocalClient.InvokeHandlerOnClient(msgType, msg, channelId); return true; } - public override bool SendWriter(QNetworkWriter writer) + public override bool SendBytes(byte[] bytes, int numBytes, int channelId) { - LocalClient.InvokeBytesOnClient(writer.AsArray()); + LocalClient.InvokeBytesOnClient(bytes, channelId); + return true; + } + + public override bool SendWriter(QNetworkWriter writer, int channelId) + { + LocalClient.InvokeBytesOnClient(writer.AsArray(), channelId); return true; } } diff --git a/QuantumUNET/QULocalConnectionToServer.cs b/QuantumUNET/QULocalConnectionToServer.cs index 0972c9db..7b991ad0 100644 --- a/QuantumUNET/QULocalConnectionToServer.cs +++ b/QuantumUNET/QULocalConnectionToServer.cs @@ -13,12 +13,15 @@ namespace QuantumUNET } public override bool Send(short msgType, QMessageBase msg) - => m_LocalServer.InvokeHandlerOnServer(this, msgType, msg); + => m_LocalServer.InvokeHandlerOnServer(this, msgType, msg, 0); - public override bool SendByChannel(short msgType, QMessageBase msg) - => m_LocalServer.InvokeHandlerOnServer(this, msgType, msg); + public override bool SendUnreliable(short msgType, QMessageBase msg) + => m_LocalServer.InvokeHandlerOnServer(this, msgType, msg, 1); - public override bool SendBytes(byte[] bytes, int numBytes) + public override bool SendByChannel(short msgType, QMessageBase msg, int channelId) + => m_LocalServer.InvokeHandlerOnServer(this, msgType, msg, channelId); + + public override bool SendBytes(byte[] bytes, int numBytes, int channelId) { bool result; if (numBytes <= 0) @@ -28,14 +31,14 @@ namespace QuantumUNET } else { - result = m_LocalServer.InvokeBytes(this, bytes, numBytes); + result = m_LocalServer.InvokeBytes(this, bytes, numBytes, channelId); } return result; } - public override bool SendWriter(QNetworkWriter writer) - => m_LocalServer.InvokeBytes(this, writer.AsArray(), (short)writer.AsArray().Length); + public override bool SendWriter(QNetworkWriter writer, int channelId) + => m_LocalServer.InvokeBytes(this, writer.AsArray(), (short)writer.AsArray().Length, channelId); private readonly QNetworkServer m_LocalServer; } From 666e4585d738034b118d6c0e9543380e1add2d86 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Fri, 26 Nov 2021 19:33:56 +0000 Subject: [PATCH 4/8] add syncers --- AssetBundles/network | Bin 3424 -> 3780 bytes AssetBundles/network.manifest | 12 +- QSB/Animation/Player/CrouchSync.cs | 8 +- .../Thrusters/JetpackAccelerationSync.cs | 33 ++++-- QSB/QSB.csproj | 2 + .../VariableSync/BaseVariableSyncer.cs | 108 ++++-------------- .../VariableSync/BoolVariableSyncer.cs | 39 +++++++ .../VariableSync/FloatVariableSyncer.cs | 30 +++-- QSB/Utility/VariableSync/VariableReference.cs | 2 +- .../VariableSync/Vector3VariableSyncer.cs | 40 +++++++ 10 files changed, 153 insertions(+), 121 deletions(-) create mode 100644 QSB/Utility/VariableSync/BoolVariableSyncer.cs create mode 100644 QSB/Utility/VariableSync/Vector3VariableSyncer.cs diff --git a/AssetBundles/network b/AssetBundles/network index b441ce668f440927e71b93767c585e0189a47b17..8de1b060a42ca0f6d5ef58f6790e7cf7091a8986 100644 GIT binary patch delta 3694 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 MC~Ql4|F@N}k+kq1jd6MLD(;=Lu<36z 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 _crouchValueReference; - private FloatVariableSyncer _variableSyncer; + public FloatVariableSyncer CrouchVariableSyncer; public float CrouchValue; public void Init(PlayerCharacterController playerController, Animator bodyAnim) @@ -25,11 +25,8 @@ namespace QSB.Animation.Player _playerController = playerController; _bodyAnim = bodyAnim; - DebugLog.DebugWrite($"create reference"); _crouchValueReference = new VariableReference(() => CrouchValue, val => CrouchValue = val); - DebugLog.DebugWrite($"add syncer"); - _variableSyncer = gameObject.AddComponent(); - _variableSyncer.FloatToSync = _crouchValueReference; + CrouchVariableSyncer.FloatToSync = _crouchValueReference; } public void Update() @@ -51,7 +48,6 @@ namespace QSB.Animation.Player } var jumpChargeFraction = _playerController.GetJumpCrouchFraction(); - DebugLog.DebugWrite($"update reference value"); _crouchValueReference.Value = jumpChargeFraction; } diff --git a/QSB/Animation/Player/Thrusters/JetpackAccelerationSync.cs b/QSB/Animation/Player/Thrusters/JetpackAccelerationSync.cs index 94b3d5b4..7bee199a 100644 --- a/QSB/Animation/Player/Thrusters/JetpackAccelerationSync.cs +++ b/QSB/Animation/Player/Thrusters/JetpackAccelerationSync.cs @@ -1,23 +1,32 @@ -using QuantumUNET; +using QSB.Utility.VariableSync; +using QuantumUNET; using UnityEngine; -using UnityEngine.Networking; namespace QSB.Animation.Player.Thrusters { public class JetpackAccelerationSync : QNetworkBehaviour { - [SyncVar] - private Vector3 _localAcceleration; - [SyncVar] - private bool _isThrusting; + public Vector3VariableSyncer AccelerationVariableSyncer; + public BoolVariableSyncer ThrustingVariableSyncer; + public Vector3 LocalAcceleration => _accelerationValueReference.Value; + public bool IsThrusting => _thrustingValueReference.Value; + private VariableReference _accelerationValueReference; + private VariableReference _thrustingValueReference; + private Vector3 _localAcceleration; + private bool _isThrusting; private ThrusterModel _thrusterModel; - public Vector3 LocalAcceleration => _localAcceleration; - public bool IsThrusting => _isThrusting; - public void Init(ThrusterModel model) - => _thrusterModel = model; + { + _thrusterModel = model; + + _accelerationValueReference = new VariableReference(() => _localAcceleration, val => _localAcceleration = val); + AccelerationVariableSyncer.FloatToSync = _accelerationValueReference; + + _thrustingValueReference = new VariableReference(() => _isThrusting, val => _isThrusting = val); + ThrustingVariableSyncer.FloatToSync = _thrustingValueReference; + } public void Update() { @@ -31,8 +40,8 @@ namespace QSB.Animation.Player.Thrusters { if (_thrusterModel != null) { - _localAcceleration = _thrusterModel.GetLocalAcceleration(); - _isThrusting = _thrusterModel.IsTranslationalThrusterFiring(); + _accelerationValueReference.Value = _thrusterModel.GetLocalAcceleration(); + _thrustingValueReference.Value = _thrusterModel.IsTranslationalThrusterFiring(); } } } diff --git a/QSB/QSB.csproj b/QSB/QSB.csproj index d0bb470f..cfecffd8 100644 --- a/QSB/QSB.csproj +++ b/QSB/QSB.csproj @@ -332,8 +332,10 @@ + + diff --git a/QSB/Utility/VariableSync/BaseVariableSyncer.cs b/QSB/Utility/VariableSync/BaseVariableSyncer.cs index d9ee5222..e455bd4e 100644 --- a/QSB/Utility/VariableSync/BaseVariableSyncer.cs +++ b/QSB/Utility/VariableSync/BaseVariableSyncer.cs @@ -1,6 +1,4 @@ using QuantumUNET; -using QuantumUNET.Components; -using QuantumUNET.Logging; using QuantumUNET.Messages; using QuantumUNET.Transport; using UnityEngine; @@ -8,29 +6,27 @@ using UnityEngine.Networking; namespace QSB.Utility.VariableSync { - internal abstract class BaseVariableSyncer : QNetworkBehaviour + public abstract class BaseVariableSyncer : QNetworkBehaviour { private float _lastClientSendTime; - private QNetworkWriter _localTransformWriter; + private QNetworkWriter _writer; + + public abstract bool HasChanged(); + public abstract void WriteData(QNetworkWriter writer); + public abstract void ReadData(QNetworkReader writer); public void Awake() { + QNetworkServer.instance.m_SimpleServerSimple.RegisterHandlerSafe((short)QSB.Events.EventType.VariableSync, HandleVariable); + if (LocalPlayerAuthority) { - _localTransformWriter = new QNetworkWriter(); + _writer = new QNetworkWriter(); } } - private void Start() - { - DebugLog.DebugWrite($"add handler"); - QNetworkServer.instance.m_SimpleServerSimple.RegisterHandlerSafe((short)QSB.Events.EventType.VariableSync, HandleTransform); - } - public override bool OnSerialize(QNetworkWriter writer, bool initialState) { - DebugLog.DebugWrite($"ON SERIALIZE"); - if (!initialState) { if (SyncVarDirtyBits == 0U) @@ -48,8 +44,6 @@ namespace QSB.Utility.VariableSync public override void OnDeserialize(QNetworkReader reader, bool initialState) { - DebugLog.DebugWrite($"ON DESERIALIZE"); - if (!IsServer || !QNetworkServer.localClientActive) { if (!initialState && reader.ReadPackedUInt32() == 0U) @@ -63,21 +57,8 @@ namespace QSB.Utility.VariableSync private void FixedUpdate() { - if (!IsServer) + if (!IsServer || SyncVarDirtyBits != 0U || !QNetworkServer.active) { - DebugLog.DebugWrite($"FIXEDUPDATE not server"); - return; - } - - if (SyncVarDirtyBits != 0U) - { - DebugLog.DebugWrite($"FIXEDUPDATE dirty!!!"); - return; - } - - if (!QNetworkServer.active) - { - DebugLog.DebugWrite($"FIXEDUPDATE server is not active!"); return; } @@ -89,84 +70,37 @@ namespace QSB.Utility.VariableSync public virtual void Update() { - if (!HasAuthority || !LocalPlayerAuthority) + if (!HasAuthority || !LocalPlayerAuthority || QNetworkServer.active) { - DebugLog.DebugWrite($"UPDATE no authority"); - return; - } - - if (QNetworkServer.active) - { - DebugLog.DebugWrite($"UPDATE server active"); return; } if (Time.time - _lastClientSendTime > GetNetworkSendInterval()) { - this.SendTransform(); - this._lastClientSendTime = Time.time; + SendVariable(); + _lastClientSendTime = Time.time; } } [Client] - private void SendTransform() + private void SendVariable() { - DebugLog.DebugWrite($"SEND TRANSFORM"); - if (HasChanged() && QClientScene.readyConnection != null) { - _localTransformWriter.StartMessage(6); - _localTransformWriter.Write(NetId); - WriteData(_localTransformWriter); - _localTransformWriter.FinishMessage(); - QClientScene.readyConnection.SendWriter(_localTransformWriter); + _writer.StartMessage((short)QSB.Events.EventType.VariableSync); + _writer.Write(NetId); + WriteData(_writer); + _writer.FinishMessage(); + QClientScene.readyConnection.SendWriter(_writer, GetNetworkChannel()); } } - public static void HandleTransform(QNetworkMessage netMsg) + public static void HandleVariable(QNetworkMessage netMsg) { - DebugLog.DebugWrite($"HANDLE TRANSFORM"); - var networkInstanceId = netMsg.Reader.ReadNetworkId(); var gameObject = QNetworkServer.FindLocalObject(networkInstanceId); - if (gameObject == null) - { - QLog.Warning("Received NetworkTransform data for GameObject that doesn't exist"); - return; - } - var component = gameObject.GetComponent(); - if (component == null) - { - QLog.Warning("HandleTransform null target"); - return; - } - - if (!component.LocalPlayerAuthority) - { - QLog.Warning("HandleTransform no localPlayerAuthority"); - return; - } - - if (netMsg.Connection.ClientOwnedObjects == null) - { - QLog.Warning("HandleTransform object not owned by connection"); - return; - } - - if (netMsg.Connection.ClientOwnedObjects.Contains(networkInstanceId)) - { - component.ReadData(netMsg.Reader); - } - else - { - QLog.Warning( - $"HandleTransform netId:{networkInstanceId} is not for a valid player"); - } + component.ReadData(netMsg.Reader); } - - public abstract bool HasChanged(); - public abstract void WriteData(QNetworkWriter writer); - public abstract void ReadData(QNetworkReader writer); } } diff --git a/QSB/Utility/VariableSync/BoolVariableSyncer.cs b/QSB/Utility/VariableSync/BoolVariableSyncer.cs new file mode 100644 index 00000000..a3a192d3 --- /dev/null +++ b/QSB/Utility/VariableSync/BoolVariableSyncer.cs @@ -0,0 +1,39 @@ +using QuantumUNET.Transport; + +namespace QSB.Utility.VariableSync +{ + public class BoolVariableSyncer : BaseVariableSyncer + { + public VariableReference FloatToSync; + + public override void WriteData(QNetworkWriter writer) + { + if (FloatToSync == null) + { + writer.Write(0f); + } + else + { + writer.Write(FloatToSync.Value); + } + } + + public override void ReadData(QNetworkReader writer) + { + if (FloatToSync == null) + { + writer.ReadSingle(); + } + else + { + FloatToSync.Value = writer.ReadBoolean(); + } + } + + public override bool HasChanged() + { + // TODO - do this!! + return true; + } + } +} diff --git a/QSB/Utility/VariableSync/FloatVariableSyncer.cs b/QSB/Utility/VariableSync/FloatVariableSyncer.cs index d2210ddc..e0174a20 100644 --- a/QSB/Utility/VariableSync/FloatVariableSyncer.cs +++ b/QSB/Utility/VariableSync/FloatVariableSyncer.cs @@ -1,27 +1,33 @@ -using QuantumUNET; -using QuantumUNET.Transport; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using QuantumUNET.Transport; namespace QSB.Utility.VariableSync { - internal class FloatVariableSyncer : BaseVariableSyncer + public class FloatVariableSyncer : BaseVariableSyncer { public VariableReference FloatToSync; public override void WriteData(QNetworkWriter writer) { - DebugLog.DebugWrite($"write data!"); - writer.Write(FloatToSync.Value); + if (FloatToSync == null) + { + writer.Write(0f); + } + else + { + writer.Write(FloatToSync.Value); + } } public override void ReadData(QNetworkReader writer) { - DebugLog.DebugWrite($"read data!"); - FloatToSync.Value = writer.ReadSingle(); + if (FloatToSync == null) + { + writer.ReadSingle(); + } + else + { + FloatToSync.Value = writer.ReadSingle(); + } } public override bool HasChanged() diff --git a/QSB/Utility/VariableSync/VariableReference.cs b/QSB/Utility/VariableSync/VariableReference.cs index 6fb39d65..2b4849ec 100644 --- a/QSB/Utility/VariableSync/VariableReference.cs +++ b/QSB/Utility/VariableSync/VariableReference.cs @@ -2,7 +2,7 @@ namespace QSB.Utility.VariableSync { - internal class VariableReference + public class VariableReference { private Func _getter; private Action _setter; diff --git a/QSB/Utility/VariableSync/Vector3VariableSyncer.cs b/QSB/Utility/VariableSync/Vector3VariableSyncer.cs new file mode 100644 index 00000000..310cb115 --- /dev/null +++ b/QSB/Utility/VariableSync/Vector3VariableSyncer.cs @@ -0,0 +1,40 @@ +using QuantumUNET.Transport; +using UnityEngine; + +namespace QSB.Utility.VariableSync +{ + public class Vector3VariableSyncer : BaseVariableSyncer + { + public VariableReference FloatToSync; + + public override void WriteData(QNetworkWriter writer) + { + if (FloatToSync == null) + { + writer.Write(0f); + } + else + { + writer.Write(FloatToSync.Value); + } + } + + public override void ReadData(QNetworkReader writer) + { + if (FloatToSync == null) + { + writer.ReadSingle(); + } + else + { + FloatToSync.Value = writer.ReadVector3(); + } + } + + public override bool HasChanged() + { + // TODO - do this!! + return true; + } + } +} From 686a65e31ab285e4fbb4b31a53d5e7f3151a76df Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Fri, 26 Nov 2021 19:44:20 +0000 Subject: [PATCH 5/8] fix placeholder read/writes --- QSB/Utility/VariableSync/BoolVariableSyncer.cs | 4 ++-- QSB/Utility/VariableSync/Vector3VariableSyncer.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/QSB/Utility/VariableSync/BoolVariableSyncer.cs b/QSB/Utility/VariableSync/BoolVariableSyncer.cs index a3a192d3..e8c90bc7 100644 --- a/QSB/Utility/VariableSync/BoolVariableSyncer.cs +++ b/QSB/Utility/VariableSync/BoolVariableSyncer.cs @@ -10,7 +10,7 @@ namespace QSB.Utility.VariableSync { if (FloatToSync == null) { - writer.Write(0f); + writer.Write(false); } else { @@ -22,7 +22,7 @@ namespace QSB.Utility.VariableSync { if (FloatToSync == null) { - writer.ReadSingle(); + writer.ReadBoolean(); } else { diff --git a/QSB/Utility/VariableSync/Vector3VariableSyncer.cs b/QSB/Utility/VariableSync/Vector3VariableSyncer.cs index 310cb115..eee02eab 100644 --- a/QSB/Utility/VariableSync/Vector3VariableSyncer.cs +++ b/QSB/Utility/VariableSync/Vector3VariableSyncer.cs @@ -11,7 +11,7 @@ namespace QSB.Utility.VariableSync { if (FloatToSync == null) { - writer.Write(0f); + writer.Write(Vector3.zero); } else { @@ -23,7 +23,7 @@ namespace QSB.Utility.VariableSync { if (FloatToSync == null) { - writer.ReadSingle(); + writer.ReadVector3(); } else { From 47968d71e82fcc0b739208441afb3189849dd649 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Fri, 26 Nov 2021 20:05:45 +0000 Subject: [PATCH 6/8] Update BaseVariableSyncer.cs --- QSB/Utility/VariableSync/BaseVariableSyncer.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/QSB/Utility/VariableSync/BaseVariableSyncer.cs b/QSB/Utility/VariableSync/BaseVariableSyncer.cs index e455bd4e..8303879d 100644 --- a/QSB/Utility/VariableSync/BaseVariableSyncer.cs +++ b/QSB/Utility/VariableSync/BaseVariableSyncer.cs @@ -1,6 +1,7 @@ using QuantumUNET; using QuantumUNET.Messages; using QuantumUNET.Transport; +using System.Linq; using UnityEngine; using UnityEngine.Networking; @@ -89,6 +90,8 @@ namespace QSB.Utility.VariableSync { _writer.StartMessage((short)QSB.Events.EventType.VariableSync); _writer.Write(NetId); + // OPTIMIZE - cache this + _writer.Write(GetComponents().ToList().IndexOf(this)); WriteData(_writer); _writer.FinishMessage(); QClientScene.readyConnection.SendWriter(_writer, GetNetworkChannel()); @@ -98,9 +101,10 @@ namespace QSB.Utility.VariableSync public static void HandleVariable(QNetworkMessage netMsg) { var networkInstanceId = netMsg.Reader.ReadNetworkId(); + var index = netMsg.Reader.ReadInt32(); var gameObject = QNetworkServer.FindLocalObject(networkInstanceId); - var component = gameObject.GetComponent(); - component.ReadData(netMsg.Reader); + var components = gameObject.GetComponents(); + components[index].ReadData(netMsg.Reader); } } } From d79a716d4e9c6dd69b089d6be78da53043ca5d9c Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Fri, 26 Nov 2021 22:31:52 +0000 Subject: [PATCH 7/8] i dont even know anymore --- QSB/Animation/Player/CrouchSync.cs | 8 ++-- .../Thrusters/JetpackAccelerationSync.cs | 17 +++---- .../VariableSync/BaseVariableSyncer.cs | 20 +++++---- .../VariableSync/BoolVariableSyncer.cs | 41 ++++++----------- .../VariableSync/FloatVariableSyncer.cs | 41 ++++++----------- QSB/Utility/VariableSync/VariableReference.cs | 45 ++++++++++++++----- .../VariableSync/Vector3VariableSyncer.cs | 41 ++++++----------- 7 files changed, 97 insertions(+), 116 deletions(-) diff --git a/QSB/Animation/Player/CrouchSync.cs b/QSB/Animation/Player/CrouchSync.cs index 6bbedcf8..dabcf039 100644 --- a/QSB/Animation/Player/CrouchSync.cs +++ b/QSB/Animation/Player/CrouchSync.cs @@ -15,18 +15,16 @@ namespace QSB.Animation.Player private PlayerCharacterController _playerController; private Animator _bodyAnim; - private VariableReference _crouchValueReference; public FloatVariableSyncer CrouchVariableSyncer; - public float CrouchValue; + public float CrouchValue = 0f; public void Init(PlayerCharacterController playerController, Animator bodyAnim) { _playerController = playerController; _bodyAnim = bodyAnim; - _crouchValueReference = new VariableReference(() => CrouchValue, val => CrouchValue = val); - CrouchVariableSyncer.FloatToSync = _crouchValueReference; + CrouchVariableSyncer.Init(() => CrouchValue, val => CrouchValue = val); } public void Update() @@ -48,7 +46,7 @@ namespace QSB.Animation.Player } var jumpChargeFraction = _playerController.GetJumpCrouchFraction(); - _crouchValueReference.Value = jumpChargeFraction; + CrouchVariableSyncer.ValueToSync.Value = jumpChargeFraction; } private void SyncRemoteCrouch() diff --git a/QSB/Animation/Player/Thrusters/JetpackAccelerationSync.cs b/QSB/Animation/Player/Thrusters/JetpackAccelerationSync.cs index 7bee199a..d15be2c0 100644 --- a/QSB/Animation/Player/Thrusters/JetpackAccelerationSync.cs +++ b/QSB/Animation/Player/Thrusters/JetpackAccelerationSync.cs @@ -8,11 +8,9 @@ namespace QSB.Animation.Player.Thrusters { public Vector3VariableSyncer AccelerationVariableSyncer; public BoolVariableSyncer ThrustingVariableSyncer; - public Vector3 LocalAcceleration => _accelerationValueReference.Value; - public bool IsThrusting => _thrustingValueReference.Value; + public Vector3 LocalAcceleration => AccelerationVariableSyncer.ValueToSync.Value; + public bool IsThrusting => ThrustingVariableSyncer.ValueToSync.Value; - private VariableReference _accelerationValueReference; - private VariableReference _thrustingValueReference; private Vector3 _localAcceleration; private bool _isThrusting; private ThrusterModel _thrusterModel; @@ -21,11 +19,8 @@ namespace QSB.Animation.Player.Thrusters { _thrusterModel = model; - _accelerationValueReference = new VariableReference(() => _localAcceleration, val => _localAcceleration = val); - AccelerationVariableSyncer.FloatToSync = _accelerationValueReference; - - _thrustingValueReference = new VariableReference(() => _isThrusting, val => _isThrusting = val); - ThrustingVariableSyncer.FloatToSync = _thrustingValueReference; + AccelerationVariableSyncer.Init(() => _localAcceleration, val => _localAcceleration = val); + ThrustingVariableSyncer.Init(() => _isThrusting, val => _isThrusting = val); } public void Update() @@ -40,8 +35,8 @@ namespace QSB.Animation.Player.Thrusters { if (_thrusterModel != null) { - _accelerationValueReference.Value = _thrusterModel.GetLocalAcceleration(); - _thrustingValueReference.Value = _thrusterModel.IsTranslationalThrusterFiring(); + AccelerationVariableSyncer.ValueToSync.Value = _thrusterModel.GetLocalAcceleration(); + ThrustingVariableSyncer.ValueToSync.Value = _thrusterModel.IsTranslationalThrusterFiring(); } } } diff --git a/QSB/Utility/VariableSync/BaseVariableSyncer.cs b/QSB/Utility/VariableSync/BaseVariableSyncer.cs index 8303879d..6e881405 100644 --- a/QSB/Utility/VariableSync/BaseVariableSyncer.cs +++ b/QSB/Utility/VariableSync/BaseVariableSyncer.cs @@ -11,12 +11,13 @@ namespace QSB.Utility.VariableSync { private float _lastClientSendTime; private QNetworkWriter _writer; + private int _index; + protected bool _ready; - public abstract bool HasChanged(); public abstract void WriteData(QNetworkWriter writer); public abstract void ReadData(QNetworkReader writer); - public void Awake() + public virtual void Awake() { QNetworkServer.instance.m_SimpleServerSimple.RegisterHandlerSafe((short)QSB.Events.EventType.VariableSync, HandleVariable); @@ -26,6 +27,9 @@ namespace QSB.Utility.VariableSync } } + public virtual void Start() + => _index = GetComponents().ToList().IndexOf(this); + public override bool OnSerialize(QNetworkWriter writer, bool initialState) { if (!initialState) @@ -58,12 +62,12 @@ namespace QSB.Utility.VariableSync private void FixedUpdate() { - if (!IsServer || SyncVarDirtyBits != 0U || !QNetworkServer.active) + if (!IsServer || SyncVarDirtyBits != 0U || !QNetworkServer.active || !_ready) { return; } - if (GetNetworkSendInterval() != 0f && HasChanged()) + if (GetNetworkSendInterval() != 0f) { SetDirtyBit(1U); } @@ -71,7 +75,7 @@ namespace QSB.Utility.VariableSync public virtual void Update() { - if (!HasAuthority || !LocalPlayerAuthority || QNetworkServer.active) + if (!HasAuthority || !LocalPlayerAuthority || QNetworkServer.active || !_ready) { return; } @@ -86,12 +90,12 @@ namespace QSB.Utility.VariableSync [Client] private void SendVariable() { - if (HasChanged() && QClientScene.readyConnection != null) + // TODO - this sends a message, even when the value hasnt changed! this is really bad! + if (QClientScene.readyConnection != null) { _writer.StartMessage((short)QSB.Events.EventType.VariableSync); _writer.Write(NetId); - // OPTIMIZE - cache this - _writer.Write(GetComponents().ToList().IndexOf(this)); + _writer.Write(_index); WriteData(_writer); _writer.FinishMessage(); QClientScene.readyConnection.SendWriter(_writer, GetNetworkChannel()); diff --git a/QSB/Utility/VariableSync/BoolVariableSyncer.cs b/QSB/Utility/VariableSync/BoolVariableSyncer.cs index e8c90bc7..58040b6b 100644 --- a/QSB/Utility/VariableSync/BoolVariableSyncer.cs +++ b/QSB/Utility/VariableSync/BoolVariableSyncer.cs @@ -1,39 +1,26 @@ using QuantumUNET.Transport; +using System; namespace QSB.Utility.VariableSync { public class BoolVariableSyncer : BaseVariableSyncer { - public VariableReference FloatToSync; + public VariableReference ValueToSync { get; private set; } = new(); + + public void Init(Func getter, Action setter) + { + ValueToSync.Getter = getter; + ValueToSync.Setter = setter; + _ready = true; + } + + public void OnDestroy() + => _ready = false; public override void WriteData(QNetworkWriter writer) - { - if (FloatToSync == null) - { - writer.Write(false); - } - else - { - writer.Write(FloatToSync.Value); - } - } + => writer.Write(ValueToSync.Value); public override void ReadData(QNetworkReader writer) - { - if (FloatToSync == null) - { - writer.ReadBoolean(); - } - else - { - FloatToSync.Value = writer.ReadBoolean(); - } - } - - public override bool HasChanged() - { - // TODO - do this!! - return true; - } + => ValueToSync.Value = writer.ReadBoolean(); } } diff --git a/QSB/Utility/VariableSync/FloatVariableSyncer.cs b/QSB/Utility/VariableSync/FloatVariableSyncer.cs index e0174a20..37cbe735 100644 --- a/QSB/Utility/VariableSync/FloatVariableSyncer.cs +++ b/QSB/Utility/VariableSync/FloatVariableSyncer.cs @@ -1,39 +1,26 @@ using QuantumUNET.Transport; +using System; namespace QSB.Utility.VariableSync { public class FloatVariableSyncer : BaseVariableSyncer { - public VariableReference FloatToSync; + public VariableReference ValueToSync { get; private set; } = new(); + + public void Init(Func getter, Action setter) + { + ValueToSync.Getter = getter; + ValueToSync.Setter = setter; + _ready = true; + } + + public void OnDestroy() + => _ready = false; public override void WriteData(QNetworkWriter writer) - { - if (FloatToSync == null) - { - writer.Write(0f); - } - else - { - writer.Write(FloatToSync.Value); - } - } + => writer.Write(ValueToSync.Value); public override void ReadData(QNetworkReader writer) - { - if (FloatToSync == null) - { - writer.ReadSingle(); - } - else - { - FloatToSync.Value = writer.ReadSingle(); - } - } - - public override bool HasChanged() - { - // TODO - do this!! - return true; - } + => ValueToSync.Value = writer.ReadSingle(); } } diff --git a/QSB/Utility/VariableSync/VariableReference.cs b/QSB/Utility/VariableSync/VariableReference.cs index 2b4849ec..783d1e62 100644 --- a/QSB/Utility/VariableSync/VariableReference.cs +++ b/QSB/Utility/VariableSync/VariableReference.cs @@ -1,22 +1,45 @@ -using System; +using QSB.Player; +using System; namespace QSB.Utility.VariableSync { public class VariableReference { - private Func _getter; - private Action _setter; - - public VariableReference(Func getter, Action setter) - { - _getter = getter; - _setter = setter; - } + public Func Getter; + public Action Setter; public T Value { - get => _getter(); - set => _setter(value); + get + { + if (Getter != null) + { + return Getter(); + } + else + { + if (QSBPlayerManager.LocalPlayer.IsReady) + { + DebugLog.ToConsole($"Warning - Getter is null!", OWML.Common.MessageType.Warning); + } + + return default; + } + } + set + { + if (Setter != null) + { + Setter(value); + } + else + { + if (QSBPlayerManager.LocalPlayer.IsReady) + { + DebugLog.ToConsole($"Warning - Setter is null!", OWML.Common.MessageType.Warning); + } + } + } } } } diff --git a/QSB/Utility/VariableSync/Vector3VariableSyncer.cs b/QSB/Utility/VariableSync/Vector3VariableSyncer.cs index eee02eab..bc91b37b 100644 --- a/QSB/Utility/VariableSync/Vector3VariableSyncer.cs +++ b/QSB/Utility/VariableSync/Vector3VariableSyncer.cs @@ -1,40 +1,27 @@ using QuantumUNET.Transport; +using System; using UnityEngine; namespace QSB.Utility.VariableSync { public class Vector3VariableSyncer : BaseVariableSyncer { - public VariableReference FloatToSync; + public VariableReference ValueToSync { get; private set; } = new(); + + public void Init(Func getter, Action setter) + { + ValueToSync.Getter = getter; + ValueToSync.Setter = setter; + _ready = true; + } + + public void OnDestroy() + => _ready = false; public override void WriteData(QNetworkWriter writer) - { - if (FloatToSync == null) - { - writer.Write(Vector3.zero); - } - else - { - writer.Write(FloatToSync.Value); - } - } + => writer.Write(ValueToSync.Value); public override void ReadData(QNetworkReader writer) - { - if (FloatToSync == null) - { - writer.ReadVector3(); - } - else - { - FloatToSync.Value = writer.ReadVector3(); - } - } - - public override bool HasChanged() - { - // TODO - do this!! - return true; - } + => ValueToSync.Value = writer.ReadVector3(); } } From fe7e35ffadda588fc95a407d7d405d6653e6c727 Mon Sep 17 00:00:00 2001 From: Mister_Nebula <41904486+misternebula@users.noreply.github.com> Date: Fri, 26 Nov 2021 22:33:31 +0000 Subject: [PATCH 8/8] remove qnetweaver --- QNetWeaver/Helpers.cs | 236 --- QNetWeaver/Log.cs | 21 - QNetWeaver/MessageClassProcessor.cs | 174 -- QNetWeaver/MonoBehaviourProcessor.cs | 143 -- QNetWeaver/NetworkBehaviourProcessor.cs | 2237 ----------------------- QNetWeaver/Program.cs | 64 - QNetWeaver/Properties/AssemblyInfo.cs | 35 - QNetWeaver/QNetWeaver.csproj | 86 - QNetWeaver/SyncListStructProcessor.cs | 309 ---- QNetWeaver/Weaver.cs | 2038 --------------------- QNetWeaver/WeaverLists.cs | 38 - QNetWeaver/app.config | 3 - QNetWeaver/lib/Unity.UNetWeaver.dll | Bin 95744 -> 0 bytes QNetWeaver/packages.config | 4 - QSB.sln | 13 +- 15 files changed, 2 insertions(+), 5399 deletions(-) delete mode 100644 QNetWeaver/Helpers.cs delete mode 100644 QNetWeaver/Log.cs delete mode 100644 QNetWeaver/MessageClassProcessor.cs delete mode 100644 QNetWeaver/MonoBehaviourProcessor.cs delete mode 100644 QNetWeaver/NetworkBehaviourProcessor.cs delete mode 100644 QNetWeaver/Program.cs delete mode 100644 QNetWeaver/Properties/AssemblyInfo.cs delete mode 100644 QNetWeaver/QNetWeaver.csproj delete mode 100644 QNetWeaver/SyncListStructProcessor.cs delete mode 100644 QNetWeaver/Weaver.cs delete mode 100644 QNetWeaver/WeaverLists.cs delete mode 100644 QNetWeaver/app.config delete mode 100644 QNetWeaver/lib/Unity.UNetWeaver.dll delete mode 100644 QNetWeaver/packages.config diff --git a/QNetWeaver/Helpers.cs b/QNetWeaver/Helpers.cs deleted file mode 100644 index aed3161d..00000000 --- a/QNetWeaver/Helpers.cs +++ /dev/null @@ -1,236 +0,0 @@ -using Mono.Cecil; -using Mono.Cecil.Cil; -using Mono.Cecil.Mdb; -using Mono.Cecil.Pdb; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; - -namespace QNetWeaver -{ - internal class Helpers - { - public static string UnityEngineDLLDirectoryName() - { - var directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase); - return (directoryName == null) ? null : directoryName.Replace("file:\\", ""); - } - - public static ISymbolReaderProvider GetSymbolReaderProvider(string inputFile) - { - var text = inputFile.Substring(0, inputFile.Length - 4); - ISymbolReaderProvider result; - if (File.Exists(text + ".pdb")) - { - Console.WriteLine("Symbols will be read from " + text + ".pdb"); - result = new PdbReaderProvider(); - } - else if (File.Exists(text + ".dll.mdb")) - { - Console.WriteLine("Symbols will be read from " + text + ".dll.mdb"); - result = new MdbReaderProvider(); - } - else - { - Console.WriteLine("No symbols for " + inputFile); - result = null; - } - - return result; - } - - public static bool InheritsFromSyncList(TypeReference typeRef) - { - try - { - if (typeRef.IsValueType) - { - return false; - } - - foreach (var typeReference in ResolveInheritanceHierarchy(typeRef)) - { - if (typeReference.IsGenericInstance) - { - var typeDefinition = typeReference.Resolve(); - if (typeDefinition.HasGenericParameters && typeDefinition.FullName == Weaver.SyncListType.FullName) - { - return true; - } - } - } - } - catch - { - } - - return false; - } - - public static IEnumerable ResolveInheritanceHierarchy(TypeReference type) - { - if (type.IsValueType) - { - yield return type; - yield return Weaver.valueTypeType; - yield return Weaver.objectType; - yield break; - } - - while (type != null && type.FullName != Weaver.objectType.FullName) - { - yield return type; - try - { - var typeDefinition = type.Resolve(); - if (typeDefinition == null) - { - break; - } - - type = typeDefinition.BaseType; - } - catch - { - break; - } - } - - yield return Weaver.objectType; - yield break; - } - - public static string DestinationFileFor(string outputDir, string assemblyPath) - { - var fileName = Path.GetFileName(assemblyPath); - return Path.Combine(outputDir, fileName); - } - - public static string PrettyPrintType(TypeReference type) - { - string result; - if (type.IsGenericInstance) - { - var genericInstanceType = (GenericInstanceType)type; - var text = genericInstanceType.Name.Substring(0, genericInstanceType.Name.Length - 2); - var text2 = "<"; - var text3 = ", "; - IEnumerable genericArguments = genericInstanceType.GenericArguments; - result = text + text2 + string.Join(text3, Enumerable.ToArray(Enumerable.Select(genericArguments, new Func(PrettyPrintType)))) + ">"; - } - else if (type.HasGenericParameters) - { - result = type.Name.Substring(0, type.Name.Length - 2) + "<" + string.Join(", ", Enumerable.ToArray(Enumerable.Select(type.GenericParameters, (GenericParameter x) => x.Name))) + ">"; - } - else - { - result = type.Name; - } - - return result; - } - - public static ReaderParameters ReaderParameters(string assemblyPath, IEnumerable extraPaths, IAssemblyResolver assemblyResolver, string unityEngineDLLPath, string unityUNetDLLPath) - { - var readerParameters = new ReaderParameters(); - if (assemblyResolver == null) - { - assemblyResolver = new DefaultAssemblyResolver(); - } - - var addSearchDirectoryHelper = new Helpers.AddSearchDirectoryHelper(assemblyResolver); - addSearchDirectoryHelper.AddSearchDirectory(Path.GetDirectoryName(assemblyPath)); - addSearchDirectoryHelper.AddSearchDirectory(UnityEngineDLLDirectoryName()); - addSearchDirectoryHelper.AddSearchDirectory(Path.GetDirectoryName(unityEngineDLLPath)); - addSearchDirectoryHelper.AddSearchDirectory(Path.GetDirectoryName(unityUNetDLLPath)); - if (extraPaths != null) - { - foreach (var directory in extraPaths) - { - addSearchDirectoryHelper.AddSearchDirectory(directory); - } - } - - readerParameters.AssemblyResolver = assemblyResolver; - readerParameters.SymbolReaderProvider = GetSymbolReaderProvider(assemblyPath); - return readerParameters; - } - - public static WriterParameters GetWriterParameters(ReaderParameters readParams) - { - var writerParameters = new WriterParameters(); - if (readParams.SymbolReaderProvider is PdbReaderProvider) - { - writerParameters.SymbolWriterProvider = new PdbWriterProvider(); - } - else if (readParams.SymbolReaderProvider is MdbReaderProvider) - { - writerParameters.SymbolWriterProvider = new MdbWriterProvider(); - } - - return writerParameters; - } - - public static TypeReference MakeGenericType(TypeReference self, params TypeReference[] arguments) - { - if (self.GenericParameters.Count != arguments.Length) - { - throw new ArgumentException(); - } - - var genericInstanceType = new GenericInstanceType(self); - foreach (var item in arguments) - { - genericInstanceType.GenericArguments.Add(item); - } - - return genericInstanceType; - } - - public static MethodReference MakeHostInstanceGeneric(MethodReference self, params TypeReference[] arguments) - { - var methodReference = new MethodReference(self.Name, self.ReturnType, MakeGenericType(self.DeclaringType, arguments)) - { - HasThis = self.HasThis, - ExplicitThis = self.ExplicitThis, - CallingConvention = self.CallingConvention - }; - foreach (var parameterDefinition in self.Parameters) - { - methodReference.Parameters.Add(new ParameterDefinition(parameterDefinition.ParameterType)); - } - - foreach (var genericParameter in self.GenericParameters) - { - methodReference.GenericParameters.Add(new GenericParameter(genericParameter.Name, methodReference)); - } - - return methodReference; - } - - private class AddSearchDirectoryHelper - { - public AddSearchDirectoryHelper(IAssemblyResolver assemblyResolver) - { - var method = assemblyResolver.GetType().GetMethod("AddSearchDirectory", (BindingFlags)20, null, new Type[] - { - typeof(string) - }, null); - if (method == null) - { - throw new Exception("Assembly resolver doesn't implement AddSearchDirectory method."); - } - - _addSearchDirectory = (Helpers.AddSearchDirectoryHelper.AddSearchDirectoryDelegate)Delegate.CreateDelegate(typeof(Helpers.AddSearchDirectoryHelper.AddSearchDirectoryDelegate), assemblyResolver, method); - } - - public void AddSearchDirectory(string directory) => _addSearchDirectory(directory); - - private readonly Helpers.AddSearchDirectoryHelper.AddSearchDirectoryDelegate _addSearchDirectory; - - private delegate void AddSearchDirectoryDelegate(string directory); - } - } -} diff --git a/QNetWeaver/Log.cs b/QNetWeaver/Log.cs deleted file mode 100644 index 7e358fae..00000000 --- a/QNetWeaver/Log.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace QNetWeaver -{ - public static class Log - { - public static void Warning(string msg) - { - Console.ForegroundColor = ConsoleColor.Yellow; - Console.WriteLine($"WARN : {msg}"); - Console.ResetColor(); - } - - public static void Error(string msg) - { - Console.ForegroundColor = ConsoleColor.DarkRed; - Console.WriteLine($"ERR : {msg}"); - Console.ResetColor(); - } - } -} diff --git a/QNetWeaver/MessageClassProcessor.cs b/QNetWeaver/MessageClassProcessor.cs deleted file mode 100644 index 9e4ffe7e..00000000 --- a/QNetWeaver/MessageClassProcessor.cs +++ /dev/null @@ -1,174 +0,0 @@ -using Mono.Cecil; -using Mono.Cecil.Cil; - -namespace QNetWeaver -{ - internal class MessageClassProcessor - { - public MessageClassProcessor(TypeDefinition td) - { - Weaver.DLog(td, "MessageClassProcessor for " + td.Name, new object[0]); - m_td = td; - } - - public void Process() - { - Weaver.DLog(m_td, "MessageClassProcessor Start", new object[0]); - Weaver.ResetRecursionCount(); - GenerateSerialization(); - if (!Weaver.fail) - { - GenerateDeSerialization(); - Weaver.DLog(m_td, "MessageClassProcessor Done", new object[0]); - } - } - - private void GenerateSerialization() - { - Weaver.DLog(m_td, " MessageClass GenerateSerialization", new object[0]); - foreach (var methodDefinition in m_td.Methods) - { - if (methodDefinition.Name == "Serialize") - { - Weaver.DLog(m_td, " Abort - is Serialize", new object[0]); - return; - } - } - - if (m_td.Fields.Count != 0) - { - foreach (var fieldDefinition in m_td.Fields) - { - if (fieldDefinition.FieldType.FullName == m_td.FullName) - { - Weaver.fail = true; - Log.Error(string.Concat(new string[] - { - "GenerateSerialization for ", - m_td.Name, - " [", - fieldDefinition.FullName, - "]. [MessageBase] member cannot be self referencing." - })); - return; - } - } - - var methodDefinition2 = new MethodDefinition("Serialize", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, Weaver.voidType); - methodDefinition2.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType))); - var ilprocessor = methodDefinition2.Body.GetILProcessor(); - foreach (var fieldDefinition2 in m_td.Fields) - { - if (!fieldDefinition2.IsStatic && !fieldDefinition2.IsPrivate && !fieldDefinition2.IsSpecialName) - { - if (fieldDefinition2.FieldType.Resolve().HasGenericParameters) - { - Weaver.fail = true; - Log.Error(string.Concat(new object[] - { - "GenerateSerialization for ", - m_td.Name, - " [", - fieldDefinition2.FieldType, - "/", - fieldDefinition2.FieldType.FullName, - "]. [MessageBase] member cannot have generic parameters." - })); - return; - } - - if (fieldDefinition2.FieldType.Resolve().IsInterface) - { - Weaver.fail = true; - Log.Error(string.Concat(new object[] - { - "GenerateSerialization for ", - m_td.Name, - " [", - fieldDefinition2.FieldType, - "/", - fieldDefinition2.FieldType.FullName, - "]. [MessageBase] member cannot be an interface." - })); - return; - } - - var writeFunc = Weaver.GetWriteFunc(fieldDefinition2.FieldType); - if (writeFunc == null) - { - Weaver.fail = true; - Log.Error(string.Concat(new object[] - { - "GenerateSerialization for ", - m_td.Name, - " unknown type [", - fieldDefinition2.FieldType, - "/", - fieldDefinition2.FieldType.FullName, - "]. [MessageBase] member variables must be basic types." - })); - return; - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, fieldDefinition2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, writeFunc)); - } - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - m_td.Methods.Add(methodDefinition2); - } - } - - private void GenerateDeSerialization() - { - Weaver.DLog(m_td, " GenerateDeserialization", new object[0]); - foreach (var methodDefinition in m_td.Methods) - { - if (methodDefinition.Name == "Deserialize") - { - return; - } - } - - if (m_td.Fields.Count != 0) - { - var methodDefinition2 = new MethodDefinition("Deserialize", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, Weaver.voidType); - methodDefinition2.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType))); - var ilprocessor = methodDefinition2.Body.GetILProcessor(); - foreach (var fieldDefinition in m_td.Fields) - { - if (!fieldDefinition.IsStatic && !fieldDefinition.IsPrivate && !fieldDefinition.IsSpecialName) - { - var readFunc = Weaver.GetReadFunc(fieldDefinition.FieldType); - if (readFunc == null) - { - Weaver.fail = true; - Log.Error(string.Concat(new object[] - { - "GenerateDeSerialization for ", - m_td.Name, - " unknown type [", - fieldDefinition.FieldType, - "]. [SyncVar] member variables must be basic types." - })); - return; - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, readFunc)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stfld, fieldDefinition)); - } - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - m_td.Methods.Add(methodDefinition2); - } - } - - private TypeDefinition m_td; - } -} diff --git a/QNetWeaver/MonoBehaviourProcessor.cs b/QNetWeaver/MonoBehaviourProcessor.cs deleted file mode 100644 index f974afe9..00000000 --- a/QNetWeaver/MonoBehaviourProcessor.cs +++ /dev/null @@ -1,143 +0,0 @@ -using Mono.Cecil; - -namespace QNetWeaver -{ - internal class MonoBehaviourProcessor - { - public MonoBehaviourProcessor(TypeDefinition td) => m_td = td; - - public void Process() - { - ProcessSyncVars(); - ProcessMethods(); - } - - private void ProcessSyncVars() - { - foreach (var fieldDefinition in m_td.Fields) - { - foreach (var customAttribute in fieldDefinition.CustomAttributes) - { - if (customAttribute.AttributeType.FullName == Weaver.SyncVarType.FullName) - { - Log.Error(string.Concat(new string[] - { - "Script ", - m_td.FullName, - " uses [SyncVar] ", - fieldDefinition.Name, - " but is not a NetworkBehaviour." - })); - Weaver.fail = true; - } - } - - if (Helpers.InheritsFromSyncList(fieldDefinition.FieldType)) - { - Log.Error(string.Format("Script {0} defines field {1} with type {2}, but it's not a NetworkBehaviour", m_td.FullName, fieldDefinition.Name, Helpers.PrettyPrintType(fieldDefinition.FieldType))); - Weaver.fail = true; - } - } - } - - private void ProcessMethods() - { - foreach (var methodDefinition in m_td.Methods) - { - foreach (var customAttribute in methodDefinition.CustomAttributes) - { - if (customAttribute.AttributeType.FullName == Weaver.CommandType.FullName) - { - Log.Error(string.Concat(new string[] - { - "Script ", - m_td.FullName, - " uses [Command] ", - methodDefinition.Name, - " but is not a NetworkBehaviour." - })); - Weaver.fail = true; - } - - if (customAttribute.AttributeType.FullName == Weaver.ClientRpcType.FullName) - { - Log.Error(string.Concat(new string[] - { - "Script ", - m_td.FullName, - " uses [ClientRpc] ", - methodDefinition.Name, - " but is not a NetworkBehaviour." - })); - Weaver.fail = true; - } - - if (customAttribute.AttributeType.FullName == Weaver.TargetRpcType.FullName) - { - Log.Error(string.Concat(new string[] - { - "Script ", - m_td.FullName, - " uses [TargetRpc] ", - methodDefinition.Name, - " but is not a NetworkBehaviour." - })); - Weaver.fail = true; - } - - var text = customAttribute.Constructor.DeclaringType.ToString(); - if (text == "UnityEngine.Networking.ServerAttribute") - { - Log.Error(string.Concat(new string[] - { - "Script ", - m_td.FullName, - " uses the attribute [Server] on the method ", - methodDefinition.Name, - " but is not a NetworkBehaviour." - })); - Weaver.fail = true; - } - else if (text == "UnityEngine.Networking.ServerCallbackAttribute") - { - Log.Error(string.Concat(new string[] - { - "Script ", - m_td.FullName, - " uses the attribute [ServerCallback] on the method ", - methodDefinition.Name, - " but is not a NetworkBehaviour." - })); - Weaver.fail = true; - } - else if (text == "UnityEngine.Networking.ClientAttribute") - { - Log.Error(string.Concat(new string[] - { - "Script ", - m_td.FullName, - " uses the attribute [Client] on the method ", - methodDefinition.Name, - " but is not a NetworkBehaviour." - })); - Weaver.fail = true; - } - else if (text == "UnityEngine.Networking.ClientCallbackAttribute") - { - Log.Error(string.Concat(new string[] - { - "Script ", - m_td.FullName, - " uses the attribute [ClientCallback] on the method ", - methodDefinition.Name, - " but is not a NetworkBehaviour." - })); - Weaver.fail = true; - } - } - } - } - - private TypeDefinition m_td; - } -} diff --git a/QNetWeaver/NetworkBehaviourProcessor.cs b/QNetWeaver/NetworkBehaviourProcessor.cs deleted file mode 100644 index 7f4eb714..00000000 --- a/QNetWeaver/NetworkBehaviourProcessor.cs +++ /dev/null @@ -1,2237 +0,0 @@ -using Mono.Cecil; -using Mono.Cecil.Cil; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace QNetWeaver -{ - internal class NetworkBehaviourProcessor - { - public NetworkBehaviourProcessor(TypeDefinition td) - { - Weaver.DLog(td, "NetworkBehaviourProcessor", new object[0]); - m_td = td; - } - - public void Process() - { - if (m_td.HasGenericParameters) - { - Weaver.fail = true; - Log.Error("NetworkBehaviour " + m_td.Name + " cannot have generic parameters"); - } - else - { - Weaver.DLog(m_td, "Process Start", new object[0]); - ProcessVersion(); - ProcessSyncVars(); - Weaver.ResetRecursionCount(); - ProcessMethods(); - ProcessEvents(); - if (!Weaver.fail) - { - GenerateNetworkSettings(); - GenerateConstants(); - Weaver.ResetRecursionCount(); - GenerateSerialization(); - if (!Weaver.fail) - { - GenerateDeSerialization(); - GeneratePreStartClient(); - Weaver.DLog(m_td, "Process Done", new object[0]); - } - } - } - } - - private static void WriteClientActiveCheck(ILProcessor worker, string mdName, Instruction label, string errString) - { - worker.Append(worker.Create(OpCodes.Call, Weaver.NetworkClientGetActive)); - worker.Append(worker.Create(OpCodes.Brtrue, label)); - worker.Append(worker.Create(OpCodes.Ldstr, errString + " " + mdName + " called on server.")); - worker.Append(worker.Create(OpCodes.Call, Weaver.logErrorReference)); - worker.Append(worker.Create(OpCodes.Ret)); - worker.Append(label); - } - - private static void WriteServerActiveCheck(ILProcessor worker, string mdName, Instruction label, string errString) - { - worker.Append(worker.Create(OpCodes.Call, Weaver.NetworkServerGetActive)); - worker.Append(worker.Create(OpCodes.Brtrue, label)); - worker.Append(worker.Create(OpCodes.Ldstr, errString + " " + mdName + " called on client.")); - worker.Append(worker.Create(OpCodes.Call, Weaver.logErrorReference)); - worker.Append(worker.Create(OpCodes.Ret)); - worker.Append(label); - } - - private static void WriteSetupLocals(ILProcessor worker) - { - worker.Body.InitLocals = true; - worker.Body.Variables.Add(new VariableDefinition(Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType))); - } - - private static void WriteCreateWriter(ILProcessor worker) - { - worker.Append(worker.Create(OpCodes.Newobj, Weaver.NetworkWriterCtor)); - worker.Append(worker.Create(OpCodes.Stloc_0)); - worker.Append(worker.Create(OpCodes.Ldloc_0)); - } - - private static void WriteMessageSize(ILProcessor worker) - { - worker.Append(worker.Create(OpCodes.Ldc_I4_0)); - worker.Append(worker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWriteInt16)); - } - - private static void WriteMessageId(ILProcessor worker, int msgId) - { - worker.Append(worker.Create(OpCodes.Ldloc_0)); - worker.Append(worker.Create(OpCodes.Ldc_I4, msgId)); - worker.Append(worker.Create(OpCodes.Conv_U2)); - worker.Append(worker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWriteInt16)); - } - - private static bool WriteArguments(ILProcessor worker, MethodDefinition md, string errString, bool skipFirst) - { - short num = 1; - foreach (var parameterDefinition in md.Parameters) - { - if (num == 1 && skipFirst) - { - num += 1; - } - else - { - var writeFunc = Weaver.GetWriteFunc(parameterDefinition.ParameterType); - if (writeFunc == null) - { - Log.Error(string.Concat(new object[] - { - "WriteArguments for ", - md.Name, - " type ", - parameterDefinition.ParameterType, - " not supported" - })); - Weaver.fail = true; - return false; - } - - worker.Append(worker.Create(OpCodes.Ldloc_0)); - worker.Append(worker.Create(OpCodes.Ldarg, num)); - worker.Append(worker.Create(OpCodes.Call, writeFunc)); - num += 1; - } - } - - return true; - } - - private void ProcessVersion() - { - foreach (var methodDefinition in m_td.Methods) - { - if (methodDefinition.Name == "UNetVersion") - { - return; - } - } - - var methodDefinition2 = new MethodDefinition("UNetVersion", MethodAttributes.Private, Weaver.voidType); - var ilprocessor = methodDefinition2.Body.GetILProcessor(); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - m_td.Methods.Add(methodDefinition2); - } - - private void GenerateConstants() - { - if (m_Cmds.Count != 0 || m_Rpcs.Count != 0 || m_TargetRpcs.Count != 0 || m_Events.Count != 0 || m_SyncLists.Count != 0) - { - Weaver.DLog(m_td, " GenerateConstants ", new object[0]); - MethodDefinition cctorMethodDef = null; - - var flag = false; - foreach (var methodDef in m_td.Methods) - { - if (methodDef.Name == ".cctor") - { - cctorMethodDef = methodDef; - flag = true; - } - } - - if (cctorMethodDef != null) - { - if (cctorMethodDef.Body.Instructions.Count != 0) - { - var returnInstruction = cctorMethodDef.Body.Instructions[cctorMethodDef.Body.Instructions.Count - 1]; - if (!(returnInstruction.OpCode == OpCodes.Ret)) - { - Log.Error("No .cctor for " + m_td.Name); - Weaver.fail = true; - return; - } - - cctorMethodDef.Body.Instructions.RemoveAt(cctorMethodDef.Body.Instructions.Count - 1); - } - } - else - { - Weaver.DLog(m_td, " No. cctor found, making... ", new object[0]); - cctorMethodDef = new MethodDefinition(".cctor", MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, Weaver.voidType); - } - - MethodDefinition ctorMethodDef = null; - foreach (var methodDef in m_td.Methods) - { - if (methodDef.Name == ".ctor") - { - ctorMethodDef = methodDef; - var returnInstruction = ctorMethodDef.Body.Instructions[ctorMethodDef.Body.Instructions.Count - 1]; - if (returnInstruction.OpCode == OpCodes.Ret) - { - Weaver.DLog(m_td, " Found .ctor ", new object[0]); - ctorMethodDef.Body.Instructions.RemoveAt(ctorMethodDef.Body.Instructions.Count - 1); - break; - } - - Weaver.fail = true; - Log.Error("No .ctor for " + m_td.Name); - return; - } - } - - if (ctorMethodDef == null) - { - Weaver.fail = true; - Log.Error("No .ctor for " + m_td.Name); - } - else - { - var ilprocessor = ctorMethodDef.Body.GetILProcessor(); - var ilprocessor2 = cctorMethodDef.Body.GetILProcessor(); - - var commandIndex = 0; - foreach (var commandDef in m_Cmds) - { - Weaver.DLog(m_td, $" Found command {commandDef.Name}", new object[0]); - var field = Weaver.ResolveField(m_td, "kCmd" + commandDef.Name); - Weaver.DLog(m_td, $" got field", new object[0]); - var hashCode = GetHashCode(m_td.Name + ":Cmd:" + commandDef.Name); - Weaver.DLog(m_td, $" got hashcode", new object[0]); - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Ldc_I4, hashCode)); - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Stsfld, field)); - - GenerateCommandDelegate(ilprocessor2, Weaver.registerCommandDelegateReference, m_CmdInvocationFuncs[commandIndex], field); - commandIndex++; - } - - var rpcIndex = 0; - foreach (var rpcDef in m_Rpcs) - { - var field2 = Weaver.ResolveField(m_td, "kRpc" + rpcDef.Name); - var hashCode2 = GetHashCode(m_td.Name + ":Rpc:" + rpcDef.Name); - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Ldc_I4, hashCode2)); - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Stsfld, field2)); - GenerateCommandDelegate(ilprocessor2, Weaver.registerRpcDelegateReference, m_RpcInvocationFuncs[rpcIndex], field2); - rpcIndex++; - } - - var targetRpcIndex = 0; - foreach (var targetRpcDef in m_TargetRpcs) - { - var field3 = Weaver.ResolveField(m_td, "kTargetRpc" + targetRpcDef.Name); - var hashCode3 = GetHashCode(m_td.Name + ":TargetRpc:" + targetRpcDef.Name); - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Ldc_I4, hashCode3)); - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Stsfld, field3)); - GenerateCommandDelegate(ilprocessor2, Weaver.registerRpcDelegateReference, m_TargetRpcInvocationFuncs[targetRpcIndex], field3); - targetRpcIndex++; - } - - var eventIndex = 0; - foreach (var eventDef in m_Events) - { - var field4 = Weaver.ResolveField(m_td, "kEvent" + eventDef.Name); - var hashCode4 = GetHashCode(m_td.Name + ":Event:" + eventDef.Name); - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Ldc_I4, hashCode4)); - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Stsfld, field4)); - GenerateCommandDelegate(ilprocessor2, Weaver.registerEventDelegateReference, m_EventInvocationFuncs[eventIndex], field4); - eventIndex++; - } - - var syncListIndex = 0; - foreach (var syncListDef in m_SyncLists) - { - var field5 = Weaver.ResolveField(m_td, "kList" + syncListDef.Name); - var hashCode5 = GetHashCode(m_td.Name + ":List:" + syncListDef.Name); - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Ldc_I4, hashCode5)); - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Stsfld, field5)); - GenerateSyncListInstanceInitializer(ilprocessor, syncListDef); - GenerateCommandDelegate(ilprocessor2, Weaver.registerSyncListDelegateReference, m_SyncListInvocationFuncs[syncListIndex], field5); - syncListIndex++; - } - - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Ldstr, m_td.Name)); - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Ldc_I4, m_QosChannel)); - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Call, Weaver.RegisterBehaviourReference)); - ilprocessor2.Append(ilprocessor2.Create(OpCodes.Ret)); - if (!flag) - { - m_td.Methods.Add(cctorMethodDef); - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - m_td.Attributes = (m_td.Attributes & ~TypeAttributes.BeforeFieldInit); - if (m_SyncLists.Count != 0) - { - MethodDefinition methodDefinition8 = null; - var flag2 = false; - foreach (var methodDefinition9 in m_td.Methods) - { - if (methodDefinition9.Name == "Awake") - { - methodDefinition8 = methodDefinition9; - flag2 = true; - } - } - - if (methodDefinition8 != null) - { - if (methodDefinition8.Body.Instructions.Count != 0) - { - var instruction3 = methodDefinition8.Body.Instructions[methodDefinition8.Body.Instructions.Count - 1]; - if (!(instruction3.OpCode == OpCodes.Ret)) - { - Log.Error("No awake for " + m_td.Name); - Weaver.fail = true; - return; - } - - methodDefinition8.Body.Instructions.RemoveAt(methodDefinition8.Body.Instructions.Count - 1); - } - } - else - { - methodDefinition8 = new MethodDefinition("Awake", MethodAttributes.Private, Weaver.voidType); - } - - var ilprocessor3 = methodDefinition8.Body.GetILProcessor(); - if (!flag2) - { - CheckForCustomBaseClassAwakeMethod(ilprocessor3); - } - - var num6 = 0; - foreach (var fd in m_SyncLists) - { - GenerateSyncListInitializer(ilprocessor3, fd, num6); - num6++; - } - - ilprocessor3.Append(ilprocessor3.Create(OpCodes.Ret)); - if (!flag2) - { - m_td.Methods.Add(methodDefinition8); - } - } - } - } - } - - private void CheckForCustomBaseClassAwakeMethod(ILProcessor awakeWorker) - { - var baseType = m_td.BaseType; - while (baseType.FullName != Weaver.NetworkBehaviourType.FullName) - { - var methodDefinition = Enumerable.FirstOrDefault(baseType.Resolve().Methods, (MethodDefinition x) => x.Name == "Awake" && !x.HasParameters); - if (methodDefinition != null) - { - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldarg_0)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Call, methodDefinition)); - break; - } - - baseType = baseType.Resolve().BaseType; - } - } - - private void GenerateSyncListInstanceInitializer(ILProcessor ctorWorker, FieldDefinition fd) - { - foreach (var instruction in ctorWorker.Body.Instructions) - { - if (instruction.OpCode.Code == Code.Stfld) - { - var fieldDefinition = (FieldDefinition)instruction.Operand; - if (fieldDefinition.DeclaringType == fd.DeclaringType && fieldDefinition.Name == fd.Name) - { - return; - } - } - } - - var method = Weaver.scriptDef.MainModule.ImportReference(Enumerable.First(fd.FieldType.Resolve().Methods, (MethodDefinition x) => x.Name == ".ctor" && !x.HasParameters)); - ctorWorker.Append(ctorWorker.Create(OpCodes.Ldarg_0)); - ctorWorker.Append(ctorWorker.Create(OpCodes.Newobj, method)); - ctorWorker.Append(ctorWorker.Create(OpCodes.Stfld, fd)); - } - - private void GenerateCommandDelegate(ILProcessor awakeWorker, MethodReference registerMethod, MethodDefinition func, FieldReference field) - { - Weaver.DLog(m_td, " GenerateCommandDelegate ", new object[0]); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldtoken, m_td)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Call, Weaver.getTypeFromHandleReference)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldsfld, field)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldnull)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldftn, func)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Newobj, Weaver.CmdDelegateConstructor)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Call, registerMethod)); - } - - private void GenerateSyncListInitializer(ILProcessor awakeWorker, FieldReference fd, int index) - { - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldarg_0)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldfld, fd)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldarg_0)); - awakeWorker.Append(awakeWorker.Create(OpCodes.Ldsfld, m_SyncListStaticFields[index])); - var genericInstanceType = (GenericInstanceType)fd.FieldType.Resolve().BaseType; - genericInstanceType = (GenericInstanceType)Weaver.scriptDef.MainModule.ImportReference(genericInstanceType); - var typeReference = genericInstanceType.GenericArguments[0]; - var method = Helpers.MakeHostInstanceGeneric(Weaver.SyncListInitBehaviourReference, new TypeReference[] - { - typeReference - }); - awakeWorker.Append(awakeWorker.Create(OpCodes.Callvirt, method)); - Weaver.scriptDef.MainModule.ImportReference(method); - } - - private void GenerateSerialization() - { - Weaver.DLog(m_td, " NetworkBehaviour GenerateSerialization", new object[0]); - foreach (var methodDefinition in m_td.Methods) - { - if (methodDefinition.Name == "OnSerialize") - { - Weaver.DLog(m_td, " Abort - is OnSerialize", new object[0]); - return; - } - } - - var methodDefinition2 = new MethodDefinition("OnSerialize", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, Weaver.boolType); - methodDefinition2.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType))); - methodDefinition2.Parameters.Add(new ParameterDefinition("forceAll", ParameterAttributes.None, Weaver.boolType)); - var ilprocessor = methodDefinition2.Body.GetILProcessor(); - methodDefinition2.Body.InitLocals = true; - var item = new VariableDefinition(Weaver.boolType); - methodDefinition2.Body.Variables.Add(item); - var flag = false; - - if (m_td.BaseType.FullName != Weaver.NetworkBehaviourType.FullName) - { - var methodReference = Weaver.ResolveMethod(m_td.BaseType, "OnSerialize"); - if (methodReference != null) - { - var item2 = new VariableDefinition(Weaver.boolType); - methodDefinition2.Body.Variables.Add(item2); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, methodReference)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_1)); - flag = true; - } - } - - if (m_SyncVars.Count == 0) - { - Weaver.DLog(m_td, " No syncvars", new object[0]); - if (flag) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Or)); - } - else - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - m_td.Methods.Add(methodDefinition2); - } - else - { - Weaver.DLog(m_td, " Syncvars exist", new object[0]); - var instruction = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brfalse, instruction)); - foreach (var fieldDefinition in m_SyncVars) - { - Weaver.DLog(m_td, $" For {fieldDefinition.Name}", new object[0]); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, fieldDefinition)); - var writeFunc = Weaver.GetWriteFunc(fieldDefinition.FieldType); - if (writeFunc == null) - { - Weaver.fail = true; - Log.Error(string.Concat(new object[] - { - "GenerateSerialization for ", - m_td.Name, - " unknown type [", - fieldDefinition.FieldType, - "]. UNet [SyncVar] member variables must be basic types." - })); - return; - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, writeFunc)); - } - - Weaver.DLog(m_td, $" Finish foreach 1", new object[0]); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - ilprocessor.Append(instruction); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_0)); - var num = Weaver.GetSyncVarStart(m_td.BaseType.FullName); - foreach (var fieldDefinition2 in m_SyncVars) - { - Weaver.DLog(m_td, $" For {fieldDefinition2.Name}", new object[0]); - var instruction2 = ilprocessor.Create(OpCodes.Nop); - Weaver.DLog(m_td, $" Got instruction2", new object[0]); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - Weaver.DLog(m_td, $" call dirtbits reference", new object[0]); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.NetworkBehaviourDirtyBitsReference)); - Weaver.DLog(m_td, $" finish call dirtbits reference", new object[0]); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4, 1 << num)); - ilprocessor.Append(ilprocessor.Create(OpCodes.And)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brfalse, instruction2)); - Weaver.DLog(m_td, $" writing dirtycheck", new object[0]); - WriteDirtyCheck(ilprocessor, true); - Weaver.DLog(m_td, $" done writing dirtycheck", new object[0]); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, fieldDefinition2)); - Weaver.DLog(m_td, $" Getting writeFunc2", new object[0]); - var writeFunc2 = Weaver.GetWriteFunc(fieldDefinition2.FieldType); - Weaver.DLog(m_td, $" Got writeFunc2", new object[0]); - if (writeFunc2 == null) - { - Log.Error(string.Concat(new object[] - { - "GenerateSerialization for ", - m_td.Name, - " unknown type [", - fieldDefinition2.FieldType, - "]. UNet [SyncVar] member variables must be basic types." - })); - Weaver.fail = true; - return; - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, writeFunc2)); - ilprocessor.Append(instruction2); - num++; - } - - Weaver.DLog(m_td, $" Finish foreach 2", new object[0]); - WriteDirtyCheck(ilprocessor, false); - if (Weaver.generateLogErrors) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldstr, "Injected Serialize " + m_td.Name)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.logErrorReference)); - } - - if (flag) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Or)); - } - else - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - m_td.Methods.Add(methodDefinition2); - Weaver.DLog(m_td, $" Finish", new object[0]); - } - - Weaver.DLog(m_td, $" Finish", new object[0]); - } - - private static void WriteDirtyCheck(ILProcessor serWorker, bool reset) - { - var instruction = serWorker.Create(OpCodes.Nop); - serWorker.Append(serWorker.Create(OpCodes.Ldloc_0)); - serWorker.Append(serWorker.Create(OpCodes.Brtrue, instruction)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); - serWorker.Append(serWorker.Create(OpCodes.Ldarg_0)); - serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkBehaviourDirtyBitsReference)); - serWorker.Append(serWorker.Create(OpCodes.Callvirt, Weaver.NetworkWriterWritePacked32)); - if (reset) - { - serWorker.Append(serWorker.Create(OpCodes.Ldc_I4_1)); - serWorker.Append(serWorker.Create(OpCodes.Stloc_0)); - } - - serWorker.Append(instruction); - } - - private static int GetChannelId(FieldDefinition field) - { - var result = 0; - foreach (var customAttribute in field.CustomAttributes) - { - if (customAttribute.AttributeType.FullName == Weaver.SyncVarType.FullName) - { - foreach (var customAttributeNamedArgument in customAttribute.Fields) - { - if (customAttributeNamedArgument.Name == "channel") - { - result = (int)customAttributeNamedArgument.Argument.Value; - break; - } - } - } - } - - return result; - } - - private bool CheckForHookFunction(FieldDefinition syncVar, out MethodDefinition foundMethod) - { - foundMethod = null; - foreach (var customAttribute in syncVar.CustomAttributes) - { - if (customAttribute.AttributeType.FullName == Weaver.SyncVarType.FullName) - { - foreach (var customAttributeNamedArgument in customAttribute.Fields) - { - if (customAttributeNamedArgument.Name == "hook") - { - var text = customAttributeNamedArgument.Argument.Value as string; - foreach (var methodDefinition in m_td.Methods) - { - if (methodDefinition.Name == text) - { - if (methodDefinition.Parameters.Count != 1) - { - Log.Error("SyncVar Hook function " + text + " must have one argument " + m_td.Name); - Weaver.fail = true; - return false; - } - - if (methodDefinition.Parameters[0].ParameterType != syncVar.FieldType) - { - Log.Error("SyncVar Hook function " + text + " has wrong type signature for " + m_td.Name); - Weaver.fail = true; - return false; - } - - foundMethod = methodDefinition; - return true; - } - } - - Log.Error("SyncVar Hook function " + text + " not found for " + m_td.Name); - Weaver.fail = true; - return false; - } - } - } - } - - return true; - } - - private void GenerateNetworkChannelSetting(int channel) - { - var methodDefinition = new MethodDefinition("GetNetworkChannel", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, Weaver.int32Type); - var ilprocessor = methodDefinition.Body.GetILProcessor(); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4, channel)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - m_td.Methods.Add(methodDefinition); - } - - private void GenerateNetworkIntervalSetting(float interval) - { - var methodDefinition = new MethodDefinition("GetNetworkSendInterval", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, Weaver.singleType); - var ilprocessor = methodDefinition.Body.GetILProcessor(); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_R4, interval)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - m_td.Methods.Add(methodDefinition); - } - - private void GenerateNetworkSettings() - { - foreach (var customAttribute in m_td.CustomAttributes) - { - if (customAttribute.AttributeType.FullName == Weaver.NetworkSettingsType.FullName) - { - foreach (var customAttributeNamedArgument in customAttribute.Fields) - { - if (customAttributeNamedArgument.Name == "channel") - { - if ((int)customAttributeNamedArgument.Argument.Value == 0) - { - continue; - } - - if (HasMethod("GetNetworkChannel")) - { - Log.Error("GetNetworkChannel, is already implemented, please make sure you either use NetworkSettings or GetNetworkChannel"); - Weaver.fail = true; - return; - } - - m_QosChannel = (int)customAttributeNamedArgument.Argument.Value; - GenerateNetworkChannelSetting(m_QosChannel); - } - - if (customAttributeNamedArgument.Name == "sendInterval") - { - if (Math.Abs((float)customAttributeNamedArgument.Argument.Value - 0.1f) > 1E-05f) - { - if (HasMethod("GetNetworkSendInterval")) - { - Log.Error("GetNetworkSendInterval, is already implemented, please make sure you either use NetworkSettings or GetNetworkSendInterval"); - Weaver.fail = true; - return; - } - - GenerateNetworkIntervalSetting((float)customAttributeNamedArgument.Argument.Value); - } - } - } - } - } - } - - private void GeneratePreStartClient() - { - m_NetIdFieldCounter = 0; - MethodDefinition methodDefinition = null; - ILProcessor ilprocessor = null; - foreach (var methodDefinition2 in m_td.Methods) - { - if (methodDefinition2.Name == "PreStartClient") - { - return; - } - } - - foreach (var fieldDefinition in m_SyncVars) - { - if (fieldDefinition.FieldType.FullName == Weaver.gameObjectType.FullName) - { - if (methodDefinition == null) - { - methodDefinition = new MethodDefinition("PreStartClient", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, Weaver.voidType); - ilprocessor = methodDefinition.Body.GetILProcessor(); - } - - var field = m_SyncVarNetIds[m_NetIdFieldCounter]; - m_NetIdFieldCounter++; - var instruction = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldflda, field)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.NetworkInstanceIsEmpty)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brtrue, instruction)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, field)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.FindLocalObjectReference)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stfld, fieldDefinition)); - ilprocessor.Append(instruction); - } - } - - if (methodDefinition != null) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - m_td.Methods.Add(methodDefinition); - } - } - - private void GenerateDeSerialization() - { - Weaver.DLog(m_td, " GenerateDeSerialization", new object[0]); - m_NetIdFieldCounter = 0; - foreach (var methodDefinition in m_td.Methods) - { - if (methodDefinition.Name == "OnDeserialize") - { - return; - } - } - - var methodDefinition2 = new MethodDefinition("OnDeserialize", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, Weaver.voidType); - methodDefinition2.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType))); - methodDefinition2.Parameters.Add(new ParameterDefinition("initialState", ParameterAttributes.None, Weaver.boolType)); - var ilprocessor = methodDefinition2.Body.GetILProcessor(); - if (m_td.BaseType.FullName != Weaver.NetworkBehaviourType.FullName) - { - var methodReference = Weaver.ResolveMethod(m_td.BaseType, "OnDeserialize"); - if (methodReference != null) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, methodReference)); - } - } - - if (m_SyncVars.Count == 0) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - m_td.Methods.Add(methodDefinition2); - } - else - { - var instruction = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brfalse, instruction)); - foreach (var fieldDefinition in m_SyncVars) - { - var readByReferenceFunc = Weaver.GetReadByReferenceFunc(fieldDefinition.FieldType); - if (readByReferenceFunc != null) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, fieldDefinition)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, readByReferenceFunc)); - } - else - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - if (fieldDefinition.FieldType.FullName == Weaver.gameObjectType.FullName) - { - var field = m_SyncVarNetIds[m_NetIdFieldCounter]; - m_NetIdFieldCounter++; - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadNetworkInstanceId)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stfld, field)); - } - else - { - var readFunc = Weaver.GetReadFunc(fieldDefinition.FieldType); - if (readFunc == null) - { - Log.Error(string.Concat(new object[] - { - "GenerateDeSerialization for ", - m_td.Name, - " unknown type [", - fieldDefinition.FieldType, - "]. UNet [SyncVar] member variables must be basic types." - })); - Weaver.fail = true; - return; - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, readFunc)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stfld, fieldDefinition)); - } - } - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - ilprocessor.Append(instruction); - methodDefinition2.Body.InitLocals = true; - var item = new VariableDefinition(Weaver.int32Type); - methodDefinition2.Body.Variables.Add(item); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.NetworkReaderReadPacked32)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_0)); - var num = Weaver.GetSyncVarStart(m_td.BaseType.FullName); - foreach (var fieldDefinition2 in m_SyncVars) - { - var instruction2 = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4, 1 << num)); - ilprocessor.Append(ilprocessor.Create(OpCodes.And)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brfalse, instruction2)); - var readByReferenceFunc2 = Weaver.GetReadByReferenceFunc(fieldDefinition2.FieldType); - if (readByReferenceFunc2 != null) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, fieldDefinition2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, readByReferenceFunc2)); - } - else - { - var readFunc2 = Weaver.GetReadFunc(fieldDefinition2.FieldType); - if (readFunc2 == null) - { - Log.Error(string.Concat(new object[] - { - "GenerateDeSerialization for ", - m_td.Name, - " unknown type [", - fieldDefinition2.FieldType, - "]. UNet [SyncVar] member variables must be basic types." - })); - Weaver.fail = true; - return; - } - - if (!CheckForHookFunction(fieldDefinition2, out var methodDefinition3)) - { - return; - } - - if (methodDefinition3 == null) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, readFunc2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stfld, fieldDefinition2)); - } - else - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, readFunc2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, methodDefinition3)); - } - } - - ilprocessor.Append(instruction2); - num++; - } - - if (Weaver.generateLogErrors) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldstr, "Injected Deserialize " + m_td.Name)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.logErrorReference)); - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - m_td.Methods.Add(methodDefinition2); - } - } - - private bool ProcessNetworkReaderParameters(MethodDefinition md, ILProcessor worker, bool skipFirst) - { - var num = 0; - foreach (var parameterDefinition in md.Parameters) - { - if (num++ != 0 || !skipFirst) - { - var readFunc = Weaver.GetReadFunc(parameterDefinition.ParameterType); - if (readFunc == null) - { - Log.Error(string.Concat(new object[] - { - "ProcessNetworkReaderParameters for ", - m_td.Name, - ":", - md.Name, - " type ", - parameterDefinition.ParameterType, - " not supported" - })); - Weaver.fail = true; - return false; - } - - worker.Append(worker.Create(OpCodes.Ldarg_1)); - worker.Append(worker.Create(OpCodes.Call, readFunc)); - if (parameterDefinition.ParameterType.FullName == Weaver.singleType.FullName) - { - worker.Append(worker.Create(OpCodes.Conv_R4)); - } - else if (parameterDefinition.ParameterType.FullName == Weaver.doubleType.FullName) - { - worker.Append(worker.Create(OpCodes.Conv_R8)); - } - } - } - - return true; - } - - private MethodDefinition ProcessCommandInvoke(MethodDefinition md) - { - var methodDefinition = new MethodDefinition("InvokeCmd" + md.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType); - var ilprocessor = methodDefinition.Body.GetILProcessor(); - var label = ilprocessor.Create(OpCodes.Nop); - WriteServerActiveCheck(ilprocessor, md.Name, label, "Command"); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Castclass, m_td)); - MethodDefinition result; - if (!ProcessNetworkReaderParameters(md, ilprocessor, false)) - { - result = null; - } - else - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, md)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - AddInvokeParameters(methodDefinition.Parameters); - result = methodDefinition; - } - - return result; - } - - private static void AddInvokeParameters(ICollection collection) - { - collection.Add(new ParameterDefinition("obj", ParameterAttributes.None, Weaver.NetworkBehaviourType2)); - collection.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType))); - } - - private MethodDefinition ProcessCommandCall(MethodDefinition md, CustomAttribute ca) - { - var methodDefinition = new MethodDefinition("Call" + md.Name, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.HideBySig, Weaver.voidType); - foreach (var parameterDefinition in md.Parameters) - { - methodDefinition.Parameters.Add(new ParameterDefinition(parameterDefinition.Name, ParameterAttributes.None, parameterDefinition.ParameterType)); - } - - var ilprocessor = methodDefinition.Body.GetILProcessor(); - var label = ilprocessor.Create(OpCodes.Nop); - WriteSetupLocals(ilprocessor); - if (Weaver.generateLogErrors) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldstr, "Call Command function " + md.Name)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.logErrorReference)); - } - - WriteClientActiveCheck(ilprocessor, md.Name, label, "Command function"); - var instruction = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.UBehaviourIsServer)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brfalse, instruction)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - for (var i = 0; i < md.Parameters.Count; i++) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg, i + 1)); - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, md)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - ilprocessor.Append(instruction); - WriteCreateWriter(ilprocessor); - WriteMessageSize(ilprocessor); - WriteMessageId(ilprocessor, 5); - var fieldDefinition = new FieldDefinition("kCmd" + md.Name, FieldAttributes.Private | FieldAttributes.Static, Weaver.int32Type); - m_td.Fields.Add(fieldDefinition); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldsfld, fieldDefinition)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.NetworkWriterWritePacked32)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.getComponentReference)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.getUNetIdReference)); - var writeFunc = Weaver.GetWriteFunc(Weaver.NetworkInstanceIdType); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, writeFunc)); - MethodDefinition result; - if (!WriteArguments(ilprocessor, md, "Command", false)) - { - result = null; - } - else - { - var value = 0; - foreach (var customAttributeNamedArgument in ca.Fields) - { - if (customAttributeNamedArgument.Name == "channel") - { - value = (int)customAttributeNamedArgument.Argument.Value; - } - } - - var text = md.Name; - var num = text.IndexOf("InvokeCmd"); - if (num > -1) - { - text = text.Substring("InvokeCmd".Length); - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4, value)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldstr, text)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.sendCommandInternal)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - result = methodDefinition; - } - - return result; - } - - private MethodDefinition ProcessTargetRpcInvoke(MethodDefinition md) - { - var methodDefinition = new MethodDefinition("InvokeRpc" + md.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType); - var ilprocessor = methodDefinition.Body.GetILProcessor(); - var label = ilprocessor.Create(OpCodes.Nop); - WriteClientActiveCheck(ilprocessor, md.Name, label, "TargetRPC"); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Castclass, m_td)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.ReadyConnectionReference)); - MethodDefinition result; - if (!ProcessNetworkReaderParameters(md, ilprocessor, true)) - { - result = null; - } - else - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, md)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - AddInvokeParameters(methodDefinition.Parameters); - result = methodDefinition; - } - - return result; - } - - private MethodDefinition ProcessRpcInvoke(MethodDefinition md) - { - var methodDefinition = new MethodDefinition("InvokeRpc" + md.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType); - var ilprocessor = methodDefinition.Body.GetILProcessor(); - var label = ilprocessor.Create(OpCodes.Nop); - WriteClientActiveCheck(ilprocessor, md.Name, label, "RPC"); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Castclass, m_td)); - MethodDefinition result; - if (!ProcessNetworkReaderParameters(md, ilprocessor, false)) - { - result = null; - } - else - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, md)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - AddInvokeParameters(methodDefinition.Parameters); - result = methodDefinition; - } - - return result; - } - - private MethodDefinition ProcessTargetRpcCall(MethodDefinition md, CustomAttribute ca) - { - var methodDefinition = new MethodDefinition("Call" + md.Name, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.HideBySig, Weaver.voidType); - foreach (var parameterDefinition in md.Parameters) - { - methodDefinition.Parameters.Add(new ParameterDefinition(parameterDefinition.Name, ParameterAttributes.None, parameterDefinition.ParameterType)); - } - - var ilprocessor = methodDefinition.Body.GetILProcessor(); - var label = ilprocessor.Create(OpCodes.Nop); - WriteSetupLocals(ilprocessor); - WriteServerActiveCheck(ilprocessor, md.Name, label, "TargetRPC Function"); - var instruction = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Isinst, Weaver.ULocalConnectionToServerType)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brfalse, instruction)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldstr, string.Format("TargetRPC Function {0} called on connection to server", md.Name))); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.logErrorReference)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - ilprocessor.Append(instruction); - WriteCreateWriter(ilprocessor); - WriteMessageSize(ilprocessor); - WriteMessageId(ilprocessor, 2); - var fieldDefinition = new FieldDefinition("kTargetRpc" + md.Name, FieldAttributes.Private | FieldAttributes.Static, Weaver.int32Type); - m_td.Fields.Add(fieldDefinition); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldsfld, fieldDefinition)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.NetworkWriterWritePacked32)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.getComponentReference)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.getUNetIdReference)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.NetworkWriterWriteNetworkInstanceId)); - MethodDefinition result; - if (!WriteArguments(ilprocessor, md, "TargetRPC", true)) - { - result = null; - } - else - { - var value = 0; - foreach (var customAttributeNamedArgument in ca.Fields) - { - if (customAttributeNamedArgument.Name == "channel") - { - value = (int)customAttributeNamedArgument.Argument.Value; - } - } - - var text = md.Name; - var num = text.IndexOf("InvokeTargetRpc"); - if (num > -1) - { - text = text.Substring("InvokeTargetRpc".Length); - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4, value)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldstr, text)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.sendTargetRpcInternal)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - result = methodDefinition; - } - - return result; - } - - private MethodDefinition ProcessRpcCall(MethodDefinition md, CustomAttribute ca) - { - var methodDefinition = new MethodDefinition("Call" + md.Name, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.HideBySig, Weaver.voidType); - foreach (var parameterDefinition in md.Parameters) - { - methodDefinition.Parameters.Add(new ParameterDefinition(parameterDefinition.Name, ParameterAttributes.None, parameterDefinition.ParameterType)); - } - - var ilprocessor = methodDefinition.Body.GetILProcessor(); - var label = ilprocessor.Create(OpCodes.Nop); - WriteSetupLocals(ilprocessor); - WriteServerActiveCheck(ilprocessor, md.Name, label, "RPC Function"); - WriteCreateWriter(ilprocessor); - WriteMessageSize(ilprocessor); - WriteMessageId(ilprocessor, 2); - var fieldDefinition = new FieldDefinition("kRpc" + md.Name, FieldAttributes.Private | FieldAttributes.Static, Weaver.int32Type); - m_td.Fields.Add(fieldDefinition); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldsfld, fieldDefinition)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.NetworkWriterWritePacked32)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.getComponentReference)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.getUNetIdReference)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.NetworkWriterWriteNetworkInstanceId)); - MethodDefinition result; - if (!WriteArguments(ilprocessor, md, "RPC", false)) - { - result = null; - } - else - { - var value = 0; - foreach (var customAttributeNamedArgument in ca.Fields) - { - if (customAttributeNamedArgument.Name == "channel") - { - value = (int)customAttributeNamedArgument.Argument.Value; - } - } - - var text = md.Name; - var num = text.IndexOf("InvokeRpc"); - if (num > -1) - { - text = text.Substring("InvokeRpc".Length); - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4, value)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldstr, text)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.sendRpcInternal)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - result = methodDefinition; - } - - return result; - } - - private bool ProcessMethodsValidateFunction(MethodReference md, CustomAttribute ca, string actionType) - { - bool result; - if (md.ReturnType.FullName == Weaver.IEnumeratorType.FullName) - { - Log.Error(string.Concat(new string[] - { - actionType, - " function [", - m_td.FullName, - ":", - md.Name, - "] cannot be a coroutine" - })); - Weaver.fail = true; - result = false; - } - else if (md.ReturnType.FullName != Weaver.voidType.FullName) - { - Log.Error(string.Concat(new string[] - { - actionType, - " function [", - m_td.FullName, - ":", - md.Name, - "] must have a void return type." - })); - Weaver.fail = true; - result = false; - } - else if (md.HasGenericParameters) - { - Log.Error(string.Concat(new string[] - { - actionType, - " [", - m_td.FullName, - ":", - md.Name, - "] cannot have generic parameters" - })); - Weaver.fail = true; - result = false; - } - else - { - result = true; - } - - return result; - } - - private bool ProcessMethodsValidateParameters(MethodReference md, CustomAttribute ca, string actionType) - { - var i = 0; - while (i < md.Parameters.Count) - { - var parameterDefinition = md.Parameters[i]; - bool result; - if (parameterDefinition.IsOut) - { - Log.Error(string.Concat(new string[] - { - actionType, - " function [", - m_td.FullName, - ":", - md.Name, - "] cannot have out parameters" - })); - Weaver.fail = true; - result = false; - } - else if (parameterDefinition.IsOptional) - { - Log.Error(string.Concat(new string[] - { - actionType, - "function [", - m_td.FullName, - ":", - md.Name, - "] cannot have optional parameters" - })); - Weaver.fail = true; - result = false; - } - else if (parameterDefinition.ParameterType.Resolve().IsAbstract) - { - Log.Error(string.Concat(new string[] - { - actionType, - " function [", - m_td.FullName, - ":", - md.Name, - "] cannot have abstract parameters" - })); - Weaver.fail = true; - result = false; - } - else if (parameterDefinition.ParameterType.IsByReference) - { - Log.Error(string.Concat(new string[] - { - actionType, - " function [", - m_td.FullName, - ":", - md.Name, - "] cannot have ref parameters" - })); - Weaver.fail = true; - result = false; - } - else - { - if (!(parameterDefinition.ParameterType.FullName == Weaver.NetworkConnectionType.FullName) || (ca.AttributeType.FullName == Weaver.TargetRpcType.FullName && i == 0)) - { - if (Weaver.IsDerivedFrom(parameterDefinition.ParameterType.Resolve(), Weaver.ComponentType)) - { - if (parameterDefinition.ParameterType.FullName != Weaver.NetworkIdentityType.FullName) - { - Log.Error(string.Concat(new string[] - { - actionType, - " function [", - m_td.FullName, - ":", - md.Name, - "] parameter [", - parameterDefinition.Name, - "] is of the type [", - parameterDefinition.ParameterType.Name, - "] which is a Component. You cannot pass a Component to a remote call. Try passing data from within the component." - })); - Weaver.fail = true; - return false; - } - } - - i++; - continue; - } - - Log.Error(string.Concat(new string[] - { - actionType, - " [", - m_td.FullName, - ":", - md.Name, - "] cannot use a NetworkConnection as a parameter. To access a player object's connection on the server use connectionToClient" - })); - Log.Error("Name: " + ca.AttributeType.FullName + " parameter: " + md.Parameters[0].ParameterType.FullName); - Weaver.fail = true; - result = false; - } - - return result; - } - - return true; - } - - private bool ProcessMethodsValidateCommand(MethodDefinition md, CustomAttribute ca) - { - bool result; - if (md.Name.Length > 2 && md.Name.Substring(0, 3) != "Cmd") - { - Log.Error(string.Concat(new string[] - { - "Command function [", - m_td.FullName, - ":", - md.Name, - "] doesnt have 'Cmd' prefix" - })); - Weaver.fail = true; - result = false; - } - else if (md.IsStatic) - { - Log.Error(string.Concat(new string[] - { - "Command function [", - m_td.FullName, - ":", - md.Name, - "] cant be a static method" - })); - Weaver.fail = true; - result = false; - } - else - { - result = (ProcessMethodsValidateFunction(md, ca, "Command") && ProcessMethodsValidateParameters(md, ca, "Command")); - } - - return result; - } - - private bool ProcessMethodsValidateTargetRpc(MethodDefinition md, CustomAttribute ca) - { - var length = "Target".Length; - bool result; - if (md.Name.Length > length && md.Name.Substring(0, length) != "Target") - { - Log.Error(string.Concat(new string[] - { - "Target Rpc function [", - m_td.FullName, - ":", - md.Name, - "] doesnt have 'Target' prefix" - })); - Weaver.fail = true; - result = false; - } - else if (md.IsStatic) - { - Log.Error(string.Concat(new string[] - { - "TargetRpc function [", - m_td.FullName, - ":", - md.Name, - "] cant be a static method" - })); - Weaver.fail = true; - result = false; - } - else if (!ProcessMethodsValidateFunction(md, ca, "Target Rpc")) - { - result = false; - } - else if (md.Parameters.Count < 1) - { - Log.Error(string.Concat(new string[] - { - "Target Rpc function [", - m_td.FullName, - ":", - md.Name, - "] must have a NetworkConnection as the first parameter" - })); - Weaver.fail = true; - result = false; - } - else if (md.Parameters[0].ParameterType.FullName != Weaver.NetworkConnectionType.FullName) - { - Log.Error(string.Concat(new string[] - { - "Target Rpc function [", - m_td.FullName, - ":", - md.Name, - "] first parameter must be a NetworkConnection" - })); - Weaver.fail = true; - result = false; - } - else - { - result = ProcessMethodsValidateParameters(md, ca, "Target Rpc"); - } - - return result; - } - - private bool ProcessMethodsValidateRpc(MethodDefinition md, CustomAttribute ca) - { - bool result; - if (md.Name.Length > 2 && md.Name.Substring(0, 3) != "Rpc") - { - Log.Error(string.Concat(new string[] - { - "Rpc function [", - m_td.FullName, - ":", - md.Name, - "] doesnt have 'Rpc' prefix" - })); - Weaver.fail = true; - result = false; - } - else if (md.IsStatic) - { - Log.Error(string.Concat(new string[] - { - "ClientRpc function [", - m_td.FullName, - ":", - md.Name, - "] cant be a static method" - })); - Weaver.fail = true; - result = false; - } - else - { - result = (ProcessMethodsValidateFunction(md, ca, "Rpc") && ProcessMethodsValidateParameters(md, ca, "Rpc")); - } - - return result; - } - - private void ProcessMethods() - { - var hashSet = new HashSet(); - foreach (var methodDefinition in m_td.Methods) - { - Weaver.ResetRecursionCount(); - foreach (var customAttribute in methodDefinition.CustomAttributes) - { - if (customAttribute.AttributeType.FullName == Weaver.CommandType.FullName) - { - if (!ProcessMethodsValidateCommand(methodDefinition, customAttribute)) - { - return; - } - - if (hashSet.Contains(methodDefinition.Name)) - { - Log.Error(string.Concat(new string[] - { - "Duplicate Command name [", - m_td.FullName, - ":", - methodDefinition.Name, - "]" - })); - Weaver.fail = true; - return; - } - - hashSet.Add(methodDefinition.Name); - m_Cmds.Add(methodDefinition); - var methodDefinition2 = ProcessCommandInvoke(methodDefinition); - if (methodDefinition2 != null) - { - m_CmdInvocationFuncs.Add(methodDefinition2); - } - - var methodDefinition3 = ProcessCommandCall(methodDefinition, customAttribute); - if (methodDefinition3 != null) - { - m_CmdCallFuncs.Add(methodDefinition3); - Weaver.lists.replacedMethods.Add(methodDefinition); - Weaver.lists.replacementMethods.Add(methodDefinition3); - } - - break; - } - else if (customAttribute.AttributeType.FullName == Weaver.TargetRpcType.FullName) - { - if (!ProcessMethodsValidateTargetRpc(methodDefinition, customAttribute)) - { - return; - } - - if (hashSet.Contains(methodDefinition.Name)) - { - Log.Error(string.Concat(new string[] - { - "Duplicate Target Rpc name [", - m_td.FullName, - ":", - methodDefinition.Name, - "]" - })); - Weaver.fail = true; - return; - } - - hashSet.Add(methodDefinition.Name); - m_TargetRpcs.Add(methodDefinition); - var methodDefinition4 = ProcessTargetRpcInvoke(methodDefinition); - if (methodDefinition4 != null) - { - m_TargetRpcInvocationFuncs.Add(methodDefinition4); - } - - var methodDefinition5 = ProcessTargetRpcCall(methodDefinition, customAttribute); - if (methodDefinition5 != null) - { - m_TargetRpcCallFuncs.Add(methodDefinition5); - Weaver.lists.replacedMethods.Add(methodDefinition); - Weaver.lists.replacementMethods.Add(methodDefinition5); - } - - break; - } - else if (customAttribute.AttributeType.FullName == Weaver.ClientRpcType.FullName) - { - if (!ProcessMethodsValidateRpc(methodDefinition, customAttribute)) - { - return; - } - - if (hashSet.Contains(methodDefinition.Name)) - { - Log.Error(string.Concat(new string[] - { - "Duplicate ClientRpc name [", - m_td.FullName, - ":", - methodDefinition.Name, - "]" - })); - Weaver.fail = true; - return; - } - - hashSet.Add(methodDefinition.Name); - m_Rpcs.Add(methodDefinition); - var methodDefinition6 = ProcessRpcInvoke(methodDefinition); - if (methodDefinition6 != null) - { - m_RpcInvocationFuncs.Add(methodDefinition6); - } - - var methodDefinition7 = ProcessRpcCall(methodDefinition, customAttribute); - if (methodDefinition7 != null) - { - m_RpcCallFuncs.Add(methodDefinition7); - Weaver.lists.replacedMethods.Add(methodDefinition); - Weaver.lists.replacementMethods.Add(methodDefinition7); - } - - break; - } - } - } - - foreach (var item in m_CmdInvocationFuncs) - { - m_td.Methods.Add(item); - } - - foreach (var item2 in m_CmdCallFuncs) - { - m_td.Methods.Add(item2); - } - - foreach (var item3 in m_RpcInvocationFuncs) - { - m_td.Methods.Add(item3); - } - - foreach (var item4 in m_TargetRpcInvocationFuncs) - { - m_td.Methods.Add(item4); - } - - foreach (var item5 in m_RpcCallFuncs) - { - m_td.Methods.Add(item5); - } - - foreach (var item6 in m_TargetRpcCallFuncs) - { - m_td.Methods.Add(item6); - } - } - - private MethodDefinition ProcessEventInvoke(EventDefinition ed) - { - FieldDefinition fieldDefinition = null; - foreach (var fieldDefinition2 in m_td.Fields) - { - if (fieldDefinition2.FullName == ed.FullName) - { - fieldDefinition = fieldDefinition2; - break; - } - } - - MethodDefinition result; - if (fieldDefinition == null) - { - Weaver.DLog(m_td, "ERROR: no event field?!", new object[0]); - Weaver.fail = true; - result = null; - } - else - { - var methodDefinition = new MethodDefinition("InvokeSyncEvent" + ed.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType); - var ilprocessor = methodDefinition.Body.GetILProcessor(); - var label = ilprocessor.Create(OpCodes.Nop); - var instruction = ilprocessor.Create(OpCodes.Nop); - WriteClientActiveCheck(ilprocessor, ed.Name, label, "Event"); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Castclass, m_td)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, fieldDefinition)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brtrue, instruction)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - ilprocessor.Append(instruction); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Castclass, m_td)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, fieldDefinition)); - var methodReference = Weaver.ResolveMethod(fieldDefinition.FieldType, "Invoke"); - if (!ProcessNetworkReaderParameters(methodReference.Resolve(), ilprocessor, false)) - { - result = null; - } - else - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, methodReference)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - AddInvokeParameters(methodDefinition.Parameters); - result = methodDefinition; - } - } - - return result; - } - - private MethodDefinition ProcessEventCall(EventDefinition ed, CustomAttribute ca) - { - var methodReference = Weaver.ResolveMethod(ed.EventType, "Invoke"); - var methodDefinition = new MethodDefinition("Call" + ed.Name, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.HideBySig, Weaver.voidType); - foreach (var parameterDefinition in methodReference.Parameters) - { - methodDefinition.Parameters.Add(new ParameterDefinition(parameterDefinition.Name, ParameterAttributes.None, parameterDefinition.ParameterType)); - } - - var ilprocessor = methodDefinition.Body.GetILProcessor(); - var label = ilprocessor.Create(OpCodes.Nop); - WriteSetupLocals(ilprocessor); - WriteServerActiveCheck(ilprocessor, ed.Name, label, "Event"); - WriteCreateWriter(ilprocessor); - WriteMessageSize(ilprocessor); - WriteMessageId(ilprocessor, 7); - var fieldDefinition = new FieldDefinition("kEvent" + ed.Name, FieldAttributes.Private | FieldAttributes.Static, Weaver.int32Type); - m_td.Fields.Add(fieldDefinition); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldsfld, fieldDefinition)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.NetworkWriterWritePacked32)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.getComponentReference)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.getUNetIdReference)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.NetworkWriterWriteNetworkInstanceId)); - MethodDefinition result; - if (!WriteArguments(ilprocessor, methodReference.Resolve(), "SyncEvent", false)) - { - result = null; - } - else - { - var value = 0; - foreach (var customAttributeNamedArgument in ca.Fields) - { - if (customAttributeNamedArgument.Name == "channel") - { - value = (int)customAttributeNamedArgument.Argument.Value; - } - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4, value)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldstr, ed.Name)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.sendEventInternal)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - result = methodDefinition; - } - - return result; - } - - private void ProcessEvents() - { - foreach (var eventDefinition in m_td.Events) - { - foreach (var customAttribute in eventDefinition.CustomAttributes) - { - if (customAttribute.AttributeType.FullName == Weaver.SyncEventType.FullName) - { - if (eventDefinition.Name.Length > 4 && eventDefinition.Name.Substring(0, 5) != "Event") - { - Log.Error(string.Concat(new string[] - { - "Event [", - m_td.FullName, - ":", - eventDefinition.FullName, - "] doesnt have 'Event' prefix" - })); - Weaver.fail = true; - return; - } - - if (eventDefinition.EventType.Resolve().HasGenericParameters) - { - Log.Error(string.Concat(new string[] - { - "Event [", - m_td.FullName, - ":", - eventDefinition.FullName, - "] cannot have generic parameters" - })); - Weaver.fail = true; - return; - } - - m_Events.Add(eventDefinition); - var methodDefinition = ProcessEventInvoke(eventDefinition); - if (methodDefinition == null) - { - return; - } - - m_td.Methods.Add(methodDefinition); - m_EventInvocationFuncs.Add(methodDefinition); - Weaver.DLog(m_td, "ProcessEvent " + eventDefinition, new object[0]); - var methodDefinition2 = ProcessEventCall(eventDefinition, customAttribute); - m_td.Methods.Add(methodDefinition2); - Weaver.lists.replacedEvents.Add(eventDefinition); - Weaver.lists.replacementEvents.Add(methodDefinition2); - Weaver.DLog(m_td, " Event: " + eventDefinition.Name, new object[0]); - break; - } - } - } - } - - private static MethodDefinition ProcessSyncVarGet(FieldDefinition fd, string originalName) - { - var methodDefinition = new MethodDefinition("get_Network" + originalName, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.SpecialName, fd.FieldType); - var ilprocessor = methodDefinition.Body.GetILProcessor(); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, fd)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - methodDefinition.Body.Variables.Add(new VariableDefinition(fd.FieldType)); - methodDefinition.Body.InitLocals = true; - methodDefinition.SemanticsAttributes = MethodSemanticsAttributes.Getter; - return methodDefinition; - } - - private MethodDefinition ProcessSyncVarSet(FieldDefinition fd, string originalName, int dirtyBit, FieldDefinition netFieldId) - { - var methodDefinition = new MethodDefinition("set_Network" + originalName, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.SpecialName, Weaver.voidType); - var ilprocessor = methodDefinition.Body.GetILProcessor(); - - var noOperatorInstruction = ilprocessor.Create(OpCodes.Nop); - var returnInstruction = ilprocessor.Create(OpCodes.Ret); - - CheckForHookFunction(fd, out var methodDefinition2); - if (methodDefinition2 != null) - { - - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.NetworkServerGetLocalClientActive)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brfalse, noOperatorInstruction)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.getSyncVarHookGuard)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brtrue, noOperatorInstruction)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.setSyncVarHookGuard)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, methodDefinition2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.setSyncVarHookGuard)); - ilprocessor.Append(noOperatorInstruction); - } - - if (fd.FieldType.FullName == Weaver.gameObjectType.FullName) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldflda, netFieldId)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.setSyncVarGameObjectReference)); - } - else - { - var genericInstanceMethod = new GenericInstanceMethod(Weaver.setSyncVarReference); - genericInstanceMethod.GenericArguments.Add(fd.FieldType); - - var index11 = ilprocessor.Create(OpCodes.Ldarg_0); - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.UBehaviourIsServer)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brfalse_S, index11)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldflda, fd)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4, dirtyBit)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, genericInstanceMethod)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Pop)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - ilprocessor.Append(index11); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldflda, fd)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4, dirtyBit)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, genericInstanceMethod)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brfalse_S, returnInstruction)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.NetworkBehaviourClientSendUpdateVars)); - } - - ilprocessor.Append(returnInstruction); - methodDefinition.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.In, fd.FieldType)); - methodDefinition.SemanticsAttributes = MethodSemanticsAttributes.Setter; - return methodDefinition; - } - - private void ProcessSyncVar(FieldDefinition fd, int dirtyBit) - { - var name = fd.Name; - Weaver.lists.replacedFields.Add(fd); - Weaver.DLog(m_td, $"Found SyncVar {fd.Name} of type {fd.FieldType}", new object[0]); - FieldDefinition fieldDefinition = null; - if (fd.FieldType.FullName == Weaver.gameObjectType.FullName) - { - fieldDefinition = new FieldDefinition("___" + fd.Name + "NetId", FieldAttributes.Private, Weaver.NetworkInstanceIdType); - m_SyncVarNetIds.Add(fieldDefinition); - Weaver.lists.netIdFields.Add(fieldDefinition); - } - - var methodDefinition = ProcessSyncVarGet(fd, name); - var methodDefinition2 = ProcessSyncVarSet(fd, name, dirtyBit, fieldDefinition); - var item = new PropertyDefinition("Network" + name, PropertyAttributes.None, fd.FieldType) - { - GetMethod = methodDefinition, - SetMethod = methodDefinition2 - }; - m_td.Methods.Add(methodDefinition); - m_td.Methods.Add(methodDefinition2); - m_td.Properties.Add(item); - Weaver.lists.replacementProperties.Add(methodDefinition2); - } - - private static MethodDefinition ProcessSyncListInvoke(FieldDefinition fd) - { - var methodDefinition = new MethodDefinition("InvokeSyncList" + fd.Name, MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType); - var ilprocessor = methodDefinition.Body.GetILProcessor(); - var label = ilprocessor.Create(OpCodes.Nop); - WriteClientActiveCheck(ilprocessor, fd.Name, label, "SyncList"); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Castclass, fd.DeclaringType)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, fd)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - var genericInstanceType = (GenericInstanceType)fd.FieldType.Resolve().BaseType; - genericInstanceType = (GenericInstanceType)Weaver.scriptDef.MainModule.ImportReference(genericInstanceType); - var typeReference = genericInstanceType.GenericArguments[0]; - var method = Helpers.MakeHostInstanceGeneric(Weaver.SyncListInitHandleMsg, new TypeReference[] - { - typeReference - }); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, method)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - AddInvokeParameters(methodDefinition.Parameters); - return methodDefinition; - } - - private FieldDefinition ProcessSyncList(FieldDefinition fd, int dirtyBit) - { - var methodDefinition = ProcessSyncListInvoke(fd); - m_SyncListInvocationFuncs.Add(methodDefinition); - return new FieldDefinition("kList" + fd.Name, FieldAttributes.Private | FieldAttributes.Static, Weaver.int32Type); - } - - private void ProcessSyncVars() - { - var num = 0; - var num2 = Weaver.GetSyncVarStart(m_td.BaseType.FullName); - m_SyncVarNetIds.Clear(); - var list = new List(); - foreach (var fieldDefinition in m_td.Fields) - { - foreach (var customAttribute in fieldDefinition.CustomAttributes) - { - if (customAttribute.AttributeType.FullName == Weaver.SyncVarType.FullName) - { - var typeDefinition = fieldDefinition.FieldType.Resolve(); - if (Weaver.IsDerivedFrom(typeDefinition, Weaver.NetworkBehaviourType)) - { - Log.Error("SyncVar [" + fieldDefinition.FullName + "] cannot be derived from NetworkBehaviour."); - Weaver.fail = true; - return; - } - - if (Weaver.IsDerivedFrom(typeDefinition, Weaver.ScriptableObjectType)) - { - Log.Error("SyncVar [" + fieldDefinition.FullName + "] cannot be derived from ScriptableObject."); - Weaver.fail = true; - return; - } - - if ((ushort)(fieldDefinition.Attributes & FieldAttributes.Static) != 0) - { - Log.Error("SyncVar [" + fieldDefinition.FullName + "] cannot be static."); - Weaver.fail = true; - return; - } - - if (typeDefinition.HasGenericParameters) - { - Log.Error("SyncVar [" + fieldDefinition.FullName + "] cannot have generic parameters."); - Weaver.fail = true; - return; - } - - if (typeDefinition.IsInterface) - { - Log.Error("SyncVar [" + fieldDefinition.FullName + "] cannot be an interface."); - Weaver.fail = true; - return; - } - - var name = typeDefinition.Module.Name; - if (name != Weaver.scriptDef.MainModule.Name && name != Weaver.UnityAssemblyDefinition.MainModule.Name && name != Weaver.QNetAssemblyDefinition.MainModule.Name && name != Weaver.corLib.Name && name != "System.Runtime.dll") - { - Log.Error($"SyncVar [{fieldDefinition.FullName}] is from an inaccessible module! : [{name}]"); - Weaver.fail = true; - return; - } - - if (fieldDefinition.FieldType.IsArray) - { - Log.Error("SyncVar [" + fieldDefinition.FullName + "] cannot be an array. Use a SyncList instead."); - Weaver.fail = true; - return; - } - - if (Helpers.InheritsFromSyncList(fieldDefinition.FieldType)) - { - Log.Warning(string.Format("Script class [{0}] has [SyncVar] attribute on SyncList field {1}, SyncLists should not be marked with SyncVar.", m_td.FullName, fieldDefinition.Name)); - break; - } - - m_SyncVars.Add(fieldDefinition); - ProcessSyncVar(fieldDefinition, 1 << num2); - num2++; - num++; - if (num2 == 32) - { - Log.Error(string.Concat(new object[] - { - "Script class [", - m_td.FullName, - "] has too many SyncVars (", - 32, - "). (This could include base classes)" - })); - Weaver.fail = true; - return; - } - - break; - } - } - - if (fieldDefinition.FieldType.FullName.Contains("UnityEngine.Networking.SyncListStruct")) - { - Log.Error("SyncListStruct member variable [" + fieldDefinition.FullName + "] must use a dervied class, like \"class MySyncList : SyncListStruct {}\"."); - Weaver.fail = true; - return; - } - - if (Weaver.IsDerivedFrom(fieldDefinition.FieldType.Resolve(), Weaver.SyncListType)) - { - if (fieldDefinition.IsStatic) - { - Log.Error(string.Concat(new string[] - { - "SyncList [", - m_td.FullName, - ":", - fieldDefinition.FullName, - "] cannot be a static" - })); - Weaver.fail = true; - return; - } - - m_SyncVars.Add(fieldDefinition); - m_SyncLists.Add(fieldDefinition); - list.Add(ProcessSyncList(fieldDefinition, 1 << num2)); - num2++; - num++; - if (num2 == 32) - { - Log.Error(string.Concat(new object[] - { - "Script class [", - m_td.FullName, - "] has too many SyncVars (", - 32, - "). (This could include base classes)" - })); - Weaver.fail = true; - return; - } - } - } - - foreach (var fieldDefinition2 in list) - { - m_td.Fields.Add(fieldDefinition2); - m_SyncListStaticFields.Add(fieldDefinition2); - } - - foreach (var item in m_SyncVarNetIds) - { - m_td.Fields.Add(item); - } - - foreach (var item2 in m_SyncListInvocationFuncs) - { - m_td.Methods.Add(item2); - } - - Weaver.SetNumSyncVars(m_td.FullName, num); - } - - private static int GetHashCode(string s) - { - var assembly = typeof(Unity.UNetWeaver.Program).Assembly; - var networkProcessorType = assembly.GetType("Unity.UNetWeaver.NetworkBehaviourProcessor"); - var methodInfo = networkProcessorType.GetMethod("GetHashCode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); - return (int)methodInfo.Invoke(null, new object[] { s }); - } - - private bool HasMethod(string name) - { - foreach (var methodDefinition in m_td.Methods) - { - if (methodDefinition.Name == name) - { - return true; - } - } - - return false; - } - - private List m_SyncVars = new List(); - - private List m_SyncLists = new List(); - - private List m_SyncVarNetIds = new List(); - - private List m_Cmds = new List(); - - private List m_Rpcs = new List(); - - private List m_TargetRpcs = new List(); - - private List m_Events = new List(); - - private List m_SyncListStaticFields = new List(); - - private List m_CmdInvocationFuncs = new List(); - - private List m_SyncListInvocationFuncs = new List(); - - private List m_RpcInvocationFuncs = new List(); - - private List m_TargetRpcInvocationFuncs = new List(); - - private List m_EventInvocationFuncs = new List(); - - private List m_CmdCallFuncs = new List(); - - private List m_RpcCallFuncs = new List(); - - private List m_TargetRpcCallFuncs = new List(); - - private const int k_SyncVarLimit = 32; - - private int m_QosChannel; - - private TypeDefinition m_td; - - private int m_NetIdFieldCounter; - - private const string k_CmdPrefix = "InvokeCmd"; - - private const string k_RpcPrefix = "InvokeRpc"; - - private const string k_TargetRpcPrefix = "InvokeTargetRpc"; - } -} diff --git a/QNetWeaver/Program.cs b/QNetWeaver/Program.cs deleted file mode 100644 index 8891e550..00000000 --- a/QNetWeaver/Program.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.IO; - -namespace QNetWeaver -{ - public class Program - { - private static void Main(string[] args) - { - Console.WriteLine("Start weaving process."); - - if (args.Length == 0) - { - Log.Error("No args supplied!"); - } - - var unityEngine = args[0]; - var qnetDLL = args[1]; - var unetDLL = args[2]; - var outputDirectory = args[3]; - var assembly = args[4]; - - CheckDLLPath(unityEngine); - CheckDLLPath(qnetDLL); - CheckDLLPath(unetDLL); - CheckOutputDirectory(outputDirectory); - CheckAssemblyPath(assembly); - Weaver.WeaveAssemblies(assembly, null, null, outputDirectory, unityEngine, qnetDLL, unetDLL); - } - - private static void CheckDLLPath(string path) - { - Console.WriteLine($"Check dll {path} ..."); - if (!File.Exists(path)) - { - throw new Exception("dll could not be located at " + path + "!"); - } - - Console.WriteLine($"Path OK!"); - } - - private static void CheckAssemblyPath(string assemblyPath) - { - Console.WriteLine($"Check assembly path {assemblyPath} ..."); - if (!File.Exists(assemblyPath)) - { - throw new Exception("Assembly " + assemblyPath + " does not exist!"); - } - - Console.WriteLine($"Assembly Path OK!"); - } - - private static void CheckOutputDirectory(string outputDir) - { - Console.WriteLine($"Check output path {outputDir} ..."); - if (!Directory.Exists(outputDir)) - { - Directory.CreateDirectory(outputDir); - } - - Console.WriteLine($"Output Path OK!"); - } - } -} diff --git a/QNetWeaver/Properties/AssemblyInfo.cs b/QNetWeaver/Properties/AssemblyInfo.cs deleted file mode 100644 index ad8f0317..00000000 --- a/QNetWeaver/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("QNetWeaver")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("QNetWeaver")] -[assembly: AssemblyCopyright("Copyright © 2021")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("e23551f3-c095-4f50-8bf7-85bb2661859b")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/QNetWeaver/QNetWeaver.csproj b/QNetWeaver/QNetWeaver.csproj deleted file mode 100644 index 78b108ed..00000000 --- a/QNetWeaver/QNetWeaver.csproj +++ /dev/null @@ -1,86 +0,0 @@ - - - - - Debug - AnyCPU - {E23551F3-C095-4F50-8BF7-85BB2661859B} - Exe - QNetWeaver - QNetWeaver - v4.8 - 512 - true - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - true - false - - - 9.0 - - - - ..\packages\Mono.Cecil.0.11.4\lib\net40\Mono.Cecil.dll - - - ..\packages\Mono.Cecil.0.11.4\lib\net40\Mono.Cecil.Mdb.dll - - - ..\packages\Mono.Cecil.0.11.4\lib\net40\Mono.Cecil.Pdb.dll - - - ..\packages\Mono.Cecil.0.11.4\lib\net40\Mono.Cecil.Rocks.dll - - - - - - - - - False - lib\Unity.UNetWeaver.dll - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/QNetWeaver/SyncListStructProcessor.cs b/QNetWeaver/SyncListStructProcessor.cs deleted file mode 100644 index 30bc3d4b..00000000 --- a/QNetWeaver/SyncListStructProcessor.cs +++ /dev/null @@ -1,309 +0,0 @@ -using Mono.Cecil; -using Mono.Cecil.Cil; - -namespace QNetWeaver -{ - internal class SyncListStructProcessor - { - public SyncListStructProcessor(TypeDefinition typeDef) - { - Weaver.DLog(typeDef, "SyncListStructProcessor for " + typeDef.Name, new object[0]); - m_TypeDef = typeDef; - } - - public void Process() - { - var genericInstanceType = (GenericInstanceType)m_TypeDef.BaseType; - if (genericInstanceType.GenericArguments.Count == 0) - { - Weaver.fail = true; - Log.Error("SyncListStructProcessor no generic args"); - } - else - { - m_ItemType = Weaver.scriptDef.MainModule.ImportReference(genericInstanceType.GenericArguments[0]); - Weaver.DLog(m_TypeDef, "SyncListStructProcessor Start item:" + m_ItemType.FullName, new object[0]); - Weaver.ResetRecursionCount(); - var methodReference = GenerateSerialization(); - if (!Weaver.fail) - { - var methodReference2 = GenerateDeserialization(); - if (methodReference2 != null && methodReference != null) - { - GenerateReadFunc(methodReference2); - GenerateWriteFunc(methodReference); - Weaver.DLog(m_TypeDef, "SyncListStructProcessor Done", new object[0]); - } - } - } - } - - private void GenerateReadFunc(MethodReference readItemFunc) - { - var text = "_ReadStruct" + m_TypeDef.Name + "_"; - if (m_TypeDef.DeclaringType != null) - { - text += m_TypeDef.DeclaringType.Name; - } - else - { - text += "None"; - } - - var methodDefinition = new MethodDefinition(text, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType); - methodDefinition.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType))); - methodDefinition.Parameters.Add(new ParameterDefinition("instance", ParameterAttributes.None, m_TypeDef)); - methodDefinition.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type)); - methodDefinition.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type)); - methodDefinition.Body.InitLocals = true; - var ilprocessor = methodDefinition.Body.GetILProcessor(); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.NetworkReadUInt16)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - var method = Helpers.MakeHostInstanceGeneric(Weaver.SyncListClear, new TypeReference[] - { - m_ItemType - }); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, method)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_1)); - var instruction = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(ilprocessor.Create(OpCodes.Br, instruction)); - var instruction2 = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(instruction2); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, readItemFunc)); - var self = Weaver.ResolveMethod(Weaver.SyncListStructType, "AddInternal"); - var method2 = Helpers.MakeHostInstanceGeneric(self, new TypeReference[] - { - m_ItemType - }); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, method2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Add)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Conv_U2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_1)); - ilprocessor.Append(instruction); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Blt, instruction2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - Weaver.RegisterReadByReferenceFunc(m_TypeDef.FullName, methodDefinition); - } - - private void GenerateWriteFunc(MethodReference writeItemFunc) - { - var text = "_WriteStruct" + m_TypeDef.GetElementType().Name + "_"; - if (m_TypeDef.DeclaringType != null) - { - text += m_TypeDef.DeclaringType.Name; - } - else - { - text += "None"; - } - - var methodDefinition = new MethodDefinition(text, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, Weaver.voidType); - methodDefinition.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType))); - methodDefinition.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(m_TypeDef))); - methodDefinition.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type)); - methodDefinition.Body.Variables.Add(new VariableDefinition(Weaver.uint16Type)); - methodDefinition.Body.InitLocals = true; - var ilprocessor = methodDefinition.Body.GetILProcessor(); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - var self = Weaver.ResolveMethod(Weaver.SyncListStructType, "get_Count"); - var method = Helpers.MakeHostInstanceGeneric(self, new TypeReference[] - { - m_ItemType - }); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, method)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, Weaver.NetworkWriteUInt16)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_1)); - var instruction = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(ilprocessor.Create(OpCodes.Br, instruction)); - var instruction2 = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(instruction2); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1)); - var self2 = Weaver.ResolveMethod(Weaver.SyncListStructType, "GetItem"); - var method2 = Helpers.MakeHostInstanceGeneric(self2, new TypeReference[] - { - m_ItemType - }); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, method2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Callvirt, writeItemFunc)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Add)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Conv_U2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_1)); - ilprocessor.Append(instruction); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Blt, instruction2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - Weaver.RegisterWriteFunc(m_TypeDef.FullName, methodDefinition); - } - - private MethodReference GenerateSerialization() - { - Weaver.DLog(m_TypeDef, " SyncListStruct GenerateSerialization", new object[0]); - foreach (var methodDefinition in m_TypeDef.Methods) - { - if (methodDefinition.Name == "SerializeItem") - { - Weaver.DLog(m_TypeDef, " Abort - is SerializeItem", new object[0]); - return methodDefinition; - } - } - - var methodDefinition2 = new MethodDefinition("SerializeItem", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, Weaver.voidType); - methodDefinition2.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkWriterType))); - methodDefinition2.Parameters.Add(new ParameterDefinition("item", ParameterAttributes.None, m_ItemType)); - var ilprocessor = methodDefinition2.Body.GetILProcessor(); - MethodReference result; - if (m_ItemType.IsGenericInstance) - { - Weaver.fail = true; - Log.Error("GenerateSerialization for " + Helpers.PrettyPrintType(m_ItemType) + " failed. Struct passed into SyncListStruct can't have generic parameters"); - result = null; - } - else - { - foreach (var fieldDefinition in m_ItemType.Resolve().Fields) - { - if (!fieldDefinition.IsStatic && !fieldDefinition.IsPrivate && !fieldDefinition.IsSpecialName) - { - var fieldReference = Weaver.scriptDef.MainModule.ImportReference(fieldDefinition); - var typeDefinition = fieldReference.FieldType.Resolve(); - if (typeDefinition.HasGenericParameters) - { - Weaver.fail = true; - Log.Error(string.Concat(new object[] - { - "GenerateSerialization for ", - m_TypeDef.Name, - " [", - typeDefinition, - "/", - typeDefinition.FullName, - "]. UNet [MessageBase] member cannot have generic parameters." - })); - return null; - } - - if (typeDefinition.IsInterface) - { - Weaver.fail = true; - Log.Error(string.Concat(new object[] - { - "GenerateSerialization for ", - m_TypeDef.Name, - " [", - typeDefinition, - "/", - typeDefinition.FullName, - "]. UNet [MessageBase] member cannot be an interface." - })); - return null; - } - - var writeFunc = Weaver.GetWriteFunc(fieldDefinition.FieldType); - if (writeFunc == null) - { - Weaver.fail = true; - Log.Error(string.Concat(new object[] - { - "GenerateSerialization for ", - m_TypeDef.Name, - " unknown type [", - typeDefinition, - "/", - typeDefinition.FullName, - "]. UNet [MessageBase] member variables must be basic types." - })); - return null; - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, fieldReference)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, writeFunc)); - } - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - m_TypeDef.Methods.Add(methodDefinition2); - result = methodDefinition2; - } - - return result; - } - - private MethodReference GenerateDeserialization() - { - Weaver.DLog(m_TypeDef, " GenerateDeserialization", new object[0]); - foreach (var methodDefinition in m_TypeDef.Methods) - { - if (methodDefinition.Name == "DeserializeItem") - { - return methodDefinition; - } - } - - var methodDefinition2 = new MethodDefinition("DeserializeItem", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig, m_ItemType); - methodDefinition2.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.scriptDef.MainModule.ImportReference(Weaver.NetworkReaderType))); - var ilprocessor = methodDefinition2.Body.GetILProcessor(); - ilprocessor.Body.InitLocals = true; - ilprocessor.Body.Variables.Add(new VariableDefinition(m_ItemType)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloca, 0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Initobj, m_ItemType)); - foreach (var fieldDefinition in m_ItemType.Resolve().Fields) - { - if (!fieldDefinition.IsStatic && !fieldDefinition.IsPrivate && !fieldDefinition.IsSpecialName) - { - var fieldReference = Weaver.scriptDef.MainModule.ImportReference(fieldDefinition); - var typeDefinition = fieldReference.FieldType.Resolve(); - var readFunc = Weaver.GetReadFunc(fieldDefinition.FieldType); - if (readFunc == null) - { - Weaver.fail = true; - Log.Error(string.Concat(new object[] - { - "GenerateDeserialization for ", - m_TypeDef.Name, - " unknown type [", - typeDefinition, - "]. UNet [SyncVar] member variables must be basic types." - })); - return null; - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloca, 0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, readFunc)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stfld, fieldReference)); - } - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - m_TypeDef.Methods.Add(methodDefinition2); - return methodDefinition2; - } - - private TypeDefinition m_TypeDef; - - private TypeReference m_ItemType; - } -} diff --git a/QNetWeaver/Weaver.cs b/QNetWeaver/Weaver.cs deleted file mode 100644 index 8f3ee305..00000000 --- a/QNetWeaver/Weaver.cs +++ /dev/null @@ -1,2038 +0,0 @@ -using Mono.Cecil; -using Mono.Cecil.Cil; -using Mono.Cecil.Mdb; -using Mono.Cecil.Pdb; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; - -namespace QNetWeaver -{ - internal class Weaver - { - public static void ResetRecursionCount() => s_RecursionCount = 0; - - public static bool CanBeResolved(TypeReference parent) - { - while (parent != null) - { - bool result; - if (parent.Scope.Name == "Windows") - { - result = false; - } - else - { - if (!(parent.Scope.Name == "mscorlib")) - { - try - { - parent = parent.Resolve().BaseType; - } - catch - { - return false; - } - - continue; - } - - var typeDefinition = parent.Resolve(); - result = (typeDefinition != null); - } - - return result; - } - - return true; - } - - public static bool IsArrayType(TypeReference variable) => (!variable.IsArray || !((ArrayType)variable).ElementType.IsArray) && (!variable.IsArray || ((ArrayType)variable).Rank <= 1); - - public static void DLog(TypeDefinition td, string fmt, params object[] args) - { - if (m_DebugFlag) - { - Console.WriteLine("[" + td.Name + "] " + string.Format(fmt, args)); - } - } - - public static int GetSyncVarStart(string className) - { - int result; - if (lists.numSyncVars.ContainsKey(className)) - { - var num = lists.numSyncVars[className]; - result = num; - } - else - { - result = 0; - } - - return result; - } - - public static void SetNumSyncVars(string className, int num) => lists.numSyncVars[className] = num; - - public static MethodReference GetWriteFunc(TypeReference variable) - { - MethodReference result; - if (s_RecursionCount++ > 128) - { - Log.Error("GetWriteFunc recursion depth exceeded for " + variable.Name + ". Check for self-referencing member variables."); - fail = true; - result = null; - } - else - { - if (lists.writeFuncs.ContainsKey(variable.FullName)) - { - var methodReference = lists.writeFuncs[variable.FullName]; - if (methodReference.Parameters[0].ParameterType.IsArray == variable.IsArray) - { - return methodReference; - } - } - - if (variable.IsByReference) - { - Log.Error("GetWriteFunc variable.IsByReference error."); - result = null; - } - else - { - MethodDefinition methodDefinition; - if (variable.IsArray) - { - var elementType = variable.GetElementType(); - var writeFunc = GetWriteFunc(elementType); - if (writeFunc == null) - { - return null; - } - - methodDefinition = GenerateArrayWriteFunc(variable, writeFunc); - } - else - { - if (variable.Resolve().IsEnum) - { - return NetworkWriterWriteInt32; - } - - methodDefinition = GenerateWriterFunction(variable); - } - - if (methodDefinition == null) - { - result = null; - } - else - { - RegisterWriteFunc(variable.FullName, methodDefinition); - result = methodDefinition; - } - } - } - - return result; - } - - public static void RegisterWriteFunc(string name, MethodDefinition newWriterFunc) - { - lists.writeFuncs[name] = newWriterFunc; - lists.generatedWriteFunctions.Add(newWriterFunc); - ConfirmGeneratedCodeClass(scriptDef.MainModule); - lists.generateContainerClass.Methods.Add(newWriterFunc); - } - - public static MethodReference GetReadByReferenceFunc(TypeReference variable) - { - MethodReference result; - if (lists.readByReferenceFuncs.ContainsKey(variable.FullName)) - { - result = lists.readByReferenceFuncs[variable.FullName]; - } - else - { - result = null; - } - - return result; - } - - public static MethodReference GetReadFunc(TypeReference variable) - { - if (lists.readFuncs.ContainsKey(variable.FullName)) - { - var methodReference = lists.readFuncs[variable.FullName]; - if (methodReference.ReturnType.IsArray == variable.IsArray) - { - return methodReference; - } - } - - var typeDefinition = variable.Resolve(); - MethodReference result; - if (typeDefinition == null) - { - Log.Error("GetReadFunc unsupported type " + variable.FullName); - result = null; - } - else if (variable.IsByReference) - { - Log.Error("GetReadFunc variable.IsByReference error."); - result = null; - } - else - { - MethodDefinition methodDefinition; - if (variable.IsArray) - { - var elementType = variable.GetElementType(); - var readFunc = GetReadFunc(elementType); - if (readFunc == null) - { - return null; - } - - methodDefinition = GenerateArrayReadFunc(variable, readFunc); - } - else - { - if (typeDefinition.IsEnum) - { - return NetworkReaderReadInt32; - } - - methodDefinition = GenerateReadFunction(variable); - } - - if (methodDefinition == null) - { - Log.Error("GetReadFunc unable to generate function for:" + variable.FullName); - result = null; - } - else - { - RegisterReadFunc(variable.FullName, methodDefinition); - result = methodDefinition; - } - } - - return result; - } - - public static void RegisterReadByReferenceFunc(string name, MethodDefinition newReaderFunc) - { - lists.readByReferenceFuncs[name] = newReaderFunc; - lists.generatedReadFunctions.Add(newReaderFunc); - ConfirmGeneratedCodeClass(scriptDef.MainModule); - lists.generateContainerClass.Methods.Add(newReaderFunc); - } - - public static void RegisterReadFunc(string name, MethodDefinition newReaderFunc) - { - lists.readFuncs[name] = newReaderFunc; - lists.generatedReadFunctions.Add(newReaderFunc); - ConfirmGeneratedCodeClass(scriptDef.MainModule); - lists.generateContainerClass.Methods.Add(newReaderFunc); - } - - private static MethodDefinition GenerateArrayReadFunc(TypeReference variable, MethodReference elementReadFunc) - { - MethodDefinition result; - if (!IsArrayType(variable)) - { - Log.Error(variable.FullName + " is an unsupported array type. Jagged and multidimensional arrays are not supported"); - result = null; - } - else - { - var text = "_ReadArray" + variable.GetElementType().Name + "_"; - if (variable.DeclaringType != null) - { - text += variable.DeclaringType.Name; - } - else - { - text += "None"; - } - - var methodDefinition = new MethodDefinition(text, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, variable); - methodDefinition.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, scriptDef.MainModule.ImportReference(NetworkReaderType))); - methodDefinition.Body.Variables.Add(new VariableDefinition(int32Type)); - methodDefinition.Body.Variables.Add(new VariableDefinition(variable)); - methodDefinition.Body.Variables.Add(new VariableDefinition(int32Type)); - methodDefinition.Body.InitLocals = true; - var ilprocessor = methodDefinition.Body.GetILProcessor(); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, NetworkReadUInt16)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - var instruction = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brtrue, instruction)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Newarr, variable.GetElementType())); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - ilprocessor.Append(instruction); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Newarr, variable.GetElementType())); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_2)); - var instruction2 = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(ilprocessor.Create(OpCodes.Br, instruction2)); - var instruction3 = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(instruction3); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldelema, variable.GetElementType())); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, elementReadFunc)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stobj, variable.GetElementType())); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Add)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_2)); - ilprocessor.Append(instruction2); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Blt, instruction3)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - result = methodDefinition; - } - - return result; - } - - private static MethodDefinition GenerateArrayWriteFunc(TypeReference variable, MethodReference elementWriteFunc) - { - MethodDefinition result; - if (!IsArrayType(variable)) - { - Log.Error(variable.FullName + " is an unsupported array type. Jagged and multidimensional arrays are not supported"); - result = null; - } - else - { - var text = "_WriteArray" + variable.GetElementType().Name + "_"; - if (variable.DeclaringType != null) - { - text += variable.DeclaringType.Name; - } - else - { - text += "None"; - } - - var methodDefinition = new MethodDefinition(text, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, voidType); - methodDefinition.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, scriptDef.MainModule.ImportReference(NetworkWriterType))); - methodDefinition.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, scriptDef.MainModule.ImportReference(variable))); - methodDefinition.Body.Variables.Add(new VariableDefinition(uint16Type)); - methodDefinition.Body.Variables.Add(new VariableDefinition(uint16Type)); - methodDefinition.Body.InitLocals = true; - var ilprocessor = methodDefinition.Body.GetILProcessor(); - var instruction = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Brtrue, instruction)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, NetworkWriteUInt16)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - ilprocessor.Append(instruction); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldlen)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Conv_I4)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Conv_U2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, NetworkWriteUInt16)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_1)); - var instruction2 = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(ilprocessor.Create(OpCodes.Br, instruction2)); - var instruction3 = ilprocessor.Create(OpCodes.Nop); - ilprocessor.Append(instruction3); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldelema, variable.GetElementType())); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldobj, variable.GetElementType())); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, elementWriteFunc)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Add)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Conv_U2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_1)); - ilprocessor.Append(instruction2); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldlen)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Conv_I4)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Blt, instruction3)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - result = methodDefinition; - } - - return result; - } - - private static MethodDefinition GenerateWriterFunction(TypeReference variable) - { - MethodDefinition result; - if (!IsValidTypeToGenerate(variable.Resolve())) - { - result = null; - } - else - { - var text = "_Write" + variable.Name + "_"; - if (variable.DeclaringType != null) - { - text += variable.DeclaringType.Name; - } - else - { - text += "None"; - } - - var methodDefinition = new MethodDefinition(text, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, voidType); - methodDefinition.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, scriptDef.MainModule.ImportReference(NetworkWriterType))); - methodDefinition.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, scriptDef.MainModule.ImportReference(variable))); - var ilprocessor = methodDefinition.Body.GetILProcessor(); - var num = 0U; - foreach (var fieldDefinition in variable.Resolve().Fields) - { - if (!fieldDefinition.IsStatic && !fieldDefinition.IsPrivate) - { - if (fieldDefinition.FieldType.Resolve().HasGenericParameters) - { - fail = true; - Log.Error(string.Concat(new object[] - { - "WriteReadFunc for ", - fieldDefinition.Name, - " [", - fieldDefinition.FieldType, - "/", - fieldDefinition.FieldType.FullName, - "]. Cannot have generic parameters." - })); - return null; - } - - if (fieldDefinition.FieldType.Resolve().IsInterface) - { - fail = true; - Log.Error(string.Concat(new object[] - { - "WriteReadFunc for ", - fieldDefinition.Name, - " [", - fieldDefinition.FieldType, - "/", - fieldDefinition.FieldType.FullName, - "]. Cannot be an interface." - })); - return null; - } - - var writeFunc = GetWriteFunc(fieldDefinition.FieldType); - if (writeFunc == null) - { - Log.Error(string.Concat(new object[] - { - "WriteReadFunc for ", - fieldDefinition.Name, - " type ", - fieldDefinition.FieldType, - " no supported" - })); - fail = true; - return null; - } - - num += 1U; - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_1)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldfld, fieldDefinition)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, writeFunc)); - } - } - - if (num == 0U) - { - Log.Warning("The class / struct " + variable.Name + " has no public or non-static fields to serialize"); - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - result = methodDefinition; - } - - return result; - } - - private static MethodDefinition GenerateReadFunction(TypeReference variable) - { - MethodDefinition result; - if (!IsValidTypeToGenerate(variable.Resolve())) - { - result = null; - } - else - { - var text = "_Read" + variable.Name + "_"; - if (variable.DeclaringType != null) - { - text += variable.DeclaringType.Name; - } - else - { - text += "None"; - } - - var methodDefinition = new MethodDefinition(text, MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig, variable); - methodDefinition.Body.Variables.Add(new VariableDefinition(variable)); - methodDefinition.Body.InitLocals = true; - methodDefinition.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, scriptDef.MainModule.ImportReference(NetworkReaderType))); - var ilprocessor = methodDefinition.Body.GetILProcessor(); - if (variable.IsValueType) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloca, 0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Initobj, variable)); - } - else - { - var methodDefinition2 = ResolveDefaultPublicCtor(variable); - if (methodDefinition2 == null) - { - Log.Error("The class " + variable.Name + " has no default constructor or it's private, aborting."); - return null; - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Newobj, methodDefinition2)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stloc_0)); - } - - var num = 0U; - foreach (var fieldDefinition in variable.Resolve().Fields) - { - if (!fieldDefinition.IsStatic && !fieldDefinition.IsPrivate) - { - if (variable.IsValueType) - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloca, 0)); - } - else - { - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc, 0)); - } - - var readFunc = GetReadFunc(fieldDefinition.FieldType); - if (readFunc == null) - { - Log.Error(string.Concat(new object[] - { - "GetReadFunc for ", - fieldDefinition.Name, - " type ", - fieldDefinition.FieldType, - " no supported" - })); - fail = true; - return null; - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Call, readFunc)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Stfld, fieldDefinition)); - num += 1U; - } - } - - if (num == 0U) - { - Log.Warning("The class / struct " + variable.Name + " has no public or non-static fields to serialize"); - } - - ilprocessor.Append(ilprocessor.Create(OpCodes.Ldloc_0)); - ilprocessor.Append(ilprocessor.Create(OpCodes.Ret)); - result = methodDefinition; - } - - return result; - } - - private static Instruction GetEventLoadInstruction(ModuleDefinition moduleDef, TypeDefinition td, MethodDefinition md, int iCount, FieldReference foundEventField) - { - while (iCount > 0) - { - iCount--; - var instruction = md.Body.Instructions[iCount]; - if (instruction.OpCode == OpCodes.Ldfld) - { - if (instruction.Operand == foundEventField) - { - DLog(td, " " + instruction.Operand, new object[0]); - return instruction; - } - } - } - - return null; - } - - private static void ProcessInstructionMethod(ModuleDefinition moduleDef, TypeDefinition td, MethodDefinition md, Instruction instr, MethodReference opMethodRef, int iCount) - { - if (opMethodRef.Name == "Invoke") - { - var flag = false; - while (iCount > 0 && !flag) - { - iCount--; - var instruction = md.Body.Instructions[iCount]; - if (instruction.OpCode == OpCodes.Ldfld) - { - var fieldReference = instruction.Operand as FieldReference; - for (var i = 0; i < lists.replacedEvents.Count; i++) - { - var eventDefinition = lists.replacedEvents[i]; - if (eventDefinition.Name == fieldReference.Name) - { - instr.Operand = lists.replacementEvents[i]; - instruction.OpCode = OpCodes.Nop; - flag = true; - break; - } - } - } - } - } - else if (lists.replacementMethodNames.Contains(opMethodRef.FullName)) - { - for (var j = 0; j < lists.replacedMethods.Count; j++) - { - var methodDefinition = lists.replacedMethods[j]; - if (opMethodRef.FullName == methodDefinition.FullName) - { - instr.Operand = lists.replacementMethods[j]; - break; - } - } - } - } - - private static void ConfirmGeneratedCodeClass(ModuleDefinition moduleDef) - { - if (lists.generateContainerClass == null) - { - lists.generateContainerClass = new TypeDefinition("Unity", "GeneratedNetworkCode", TypeAttributes.Public | TypeAttributes.AutoClass | TypeAttributes.BeforeFieldInit, objectType); - var methodDefinition = new MethodDefinition(".ctor", MethodAttributes.FamANDAssem | MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, voidType); - methodDefinition.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); - methodDefinition.Body.Instructions.Add(Instruction.Create(OpCodes.Call, ResolveMethod(objectType, ".ctor"))); - methodDefinition.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); - lists.generateContainerClass.Methods.Add(methodDefinition); - } - } - - private static void ProcessInstructionField(TypeDefinition td, MethodDefinition md, Instruction i, FieldDefinition opField) - { - if (!(md.Name == ".ctor") && !(md.Name == "OnDeserialize")) - { - for (var j = 0; j < lists.replacedFields.Count; j++) - { - var fieldDefinition = lists.replacedFields[j]; - if (opField == fieldDefinition) - { - i.OpCode = OpCodes.Call; - i.Operand = lists.replacementProperties[j]; - break; - } - } - } - } - - private static void ProcessInstruction(ModuleDefinition moduleDef, TypeDefinition td, MethodDefinition md, Instruction i, int iCount) - { - if (i.OpCode == OpCodes.Call || i.OpCode == OpCodes.Callvirt) - { - var methodReference = i.Operand as MethodReference; - if (methodReference != null) - { - ProcessInstructionMethod(moduleDef, td, md, i, methodReference, iCount); - } - } - - if (i.OpCode == OpCodes.Stfld) - { - var fieldDefinition = i.Operand as FieldDefinition; - if (fieldDefinition != null) - { - ProcessInstructionField(td, md, i, fieldDefinition); - } - } - } - - private static void InjectGuardParameters(MethodDefinition md, ILProcessor worker, Instruction top) - { - var num = (!md.Resolve().IsStatic) ? 1 : 0; - for (var i = 0; i < md.Parameters.Count; i++) - { - var parameterDefinition = md.Parameters[i]; - if (parameterDefinition.IsOut) - { - var elementType = parameterDefinition.ParameterType.GetElementType(); - if (elementType.IsPrimitive) - { - worker.InsertBefore(top, worker.Create(OpCodes.Ldarg, i + num)); - worker.InsertBefore(top, worker.Create(OpCodes.Ldc_I4_0)); - worker.InsertBefore(top, worker.Create(OpCodes.Stind_I4)); - } - else - { - md.Body.Variables.Add(new VariableDefinition(elementType)); - md.Body.InitLocals = true; - worker.InsertBefore(top, worker.Create(OpCodes.Ldarg, i + num)); - worker.InsertBefore(top, worker.Create(OpCodes.Ldloca_S, (byte)(md.Body.Variables.Count - 1))); - worker.InsertBefore(top, worker.Create(OpCodes.Initobj, elementType)); - worker.InsertBefore(top, worker.Create(OpCodes.Ldloc, md.Body.Variables.Count - 1)); - worker.InsertBefore(top, worker.Create(OpCodes.Stobj, elementType)); - } - } - } - } - - private static void InjectGuardReturnValue(MethodDefinition md, ILProcessor worker, Instruction top) - { - if (md.ReturnType.FullName != voidType.FullName) - { - if (md.ReturnType.IsPrimitive) - { - worker.InsertBefore(top, worker.Create(OpCodes.Ldc_I4_0)); - } - else - { - md.Body.Variables.Add(new VariableDefinition(md.ReturnType)); - md.Body.InitLocals = true; - worker.InsertBefore(top, worker.Create(OpCodes.Ldloca_S, (byte)(md.Body.Variables.Count - 1))); - worker.InsertBefore(top, worker.Create(OpCodes.Initobj, md.ReturnType)); - worker.InsertBefore(top, worker.Create(OpCodes.Ldloc, md.Body.Variables.Count - 1)); - } - } - } - - private static void InjectServerGuard(ModuleDefinition moduleDef, TypeDefinition td, MethodDefinition md, bool logWarning) - { - if (!IsNetworkBehaviour(td)) - { - Log.Error("[Server] guard on non-NetworkBehaviour script at [" + md.FullName + "]"); - } - else - { - var ilprocessor = md.Body.GetILProcessor(); - var instruction = md.Body.Instructions[0]; - ilprocessor.InsertBefore(instruction, ilprocessor.Create(OpCodes.Call, NetworkServerGetActive)); - ilprocessor.InsertBefore(instruction, ilprocessor.Create(OpCodes.Brtrue, instruction)); - if (logWarning) - { - ilprocessor.InsertBefore(instruction, ilprocessor.Create(OpCodes.Ldstr, "[Server] function '" + md.FullName + "' called on client")); - ilprocessor.InsertBefore(instruction, ilprocessor.Create(OpCodes.Call, logWarningReference)); - } - - InjectGuardParameters(md, ilprocessor, instruction); - InjectGuardReturnValue(md, ilprocessor, instruction); - ilprocessor.InsertBefore(instruction, ilprocessor.Create(OpCodes.Ret)); - } - } - - private static void InjectClientGuard(ModuleDefinition moduleDef, TypeDefinition td, MethodDefinition md, bool logWarning) - { - if (!IsNetworkBehaviour(td)) - { - Log.Error("[Client] guard on non-NetworkBehaviour script at [" + md.FullName + "]"); - } - else - { - var ilprocessor = md.Body.GetILProcessor(); - var instruction = md.Body.Instructions[0]; - ilprocessor.InsertBefore(instruction, ilprocessor.Create(OpCodes.Call, NetworkClientGetActive)); - ilprocessor.InsertBefore(instruction, ilprocessor.Create(OpCodes.Brtrue, instruction)); - if (logWarning) - { - ilprocessor.InsertBefore(instruction, ilprocessor.Create(OpCodes.Ldstr, "[Client] function '" + md.FullName + "' called on server")); - ilprocessor.InsertBefore(instruction, ilprocessor.Create(OpCodes.Call, logWarningReference)); - } - - InjectGuardParameters(md, ilprocessor, instruction); - InjectGuardReturnValue(md, ilprocessor, instruction); - ilprocessor.InsertBefore(instruction, ilprocessor.Create(OpCodes.Ret)); - } - } - - private static void ProcessSiteMethod(ModuleDefinition moduleDef, TypeDefinition td, MethodDefinition md) - { - if (!(md.Name == ".cctor") && !(md.Name == "OnUnserializeVars")) - { - var text = md.Name.Substring(0, Math.Min(md.Name.Length, 4)); - if (!(text == "UNet")) - { - text = md.Name.Substring(0, Math.Min(md.Name.Length, 7)); - if (!(text == "CallCmd")) - { - text = md.Name.Substring(0, Math.Min(md.Name.Length, 9)); - if (!(text == "InvokeCmd") && !(text == "InvokeRpc") && !(text == "InvokeSyn")) - { - if (md.Body != null && md.Body.Instructions != null) - { - foreach (var customAttribute in md.CustomAttributes) - { - if (customAttribute.Constructor.DeclaringType.ToString() == "UnityEngine.Networking.ServerAttribute") - { - InjectServerGuard(moduleDef, td, md, true); - } - else if (customAttribute.Constructor.DeclaringType.ToString() == "UnityEngine.Networking.ServerCallbackAttribute") - { - InjectServerGuard(moduleDef, td, md, false); - } - else if (customAttribute.Constructor.DeclaringType.ToString() == "UnityEngine.Networking.ClientAttribute") - { - InjectClientGuard(moduleDef, td, md, true); - } - else if (customAttribute.Constructor.DeclaringType.ToString() == "UnityEngine.Networking.ClientCallbackAttribute") - { - InjectClientGuard(moduleDef, td, md, false); - } - } - - var num = 0; - foreach (var i in md.Body.Instructions) - { - ProcessInstruction(moduleDef, td, md, i, num); - num++; - } - } - } - } - } - } - } - - private static void ProcessSiteClass(ModuleDefinition moduleDef, TypeDefinition td) - { - foreach (var md in td.Methods) - { - ProcessSiteMethod(moduleDef, td, md); - } - - foreach (var td2 in td.NestedTypes) - { - ProcessSiteClass(moduleDef, td2); - } - } - - private static void ProcessSitesModule(ModuleDefinition moduleDef) - { - var now = DateTime.Now; - foreach (var typeDefinition in moduleDef.Types) - { - if (typeDefinition.IsClass) - { - ProcessSiteClass(moduleDef, typeDefinition); - } - } - - if (lists.generateContainerClass != null) - { - moduleDef.Types.Add(lists.generateContainerClass); - scriptDef.MainModule.ImportReference(lists.generateContainerClass); - foreach (var method in lists.generatedReadFunctions) - { - scriptDef.MainModule.ImportReference(method); - } - - foreach (var method2 in lists.generatedWriteFunctions) - { - scriptDef.MainModule.ImportReference(method2); - } - } - - Console.WriteLine(string.Concat(new object[] - { - " ProcessSitesModule ", - moduleDef.Name, - " elapsed time:", - DateTime.Now - now - })); - } - - private static void ProcessPropertySites() => ProcessSitesModule(scriptDef.MainModule); - - private static bool ProcessMessageType(TypeDefinition td) - { - var messageClassProcessor = new MessageClassProcessor(td); - messageClassProcessor.Process(); - return true; - } - - private static bool ProcessSyncListStructType(TypeDefinition td) - { - var syncListStructProcessor = new SyncListStructProcessor(td); - syncListStructProcessor.Process(); - return true; - } - - private static void ProcessMonoBehaviourType(TypeDefinition td) - { - var monoBehaviourProcessor = new MonoBehaviourProcessor(td); - monoBehaviourProcessor.Process(); - } - - private static bool ProcessNetworkBehaviourType(TypeDefinition td) - { - foreach (var methodDefinition in td.Resolve().Methods) - { - if (methodDefinition.Name == "UNetVersion") - { - DLog(td, " Already processed", new object[0]); - return false; - } - } - - DLog(td, "Found NetworkBehaviour " + td.FullName, new object[0]); - var networkBehaviourProcessor = new NetworkBehaviourProcessor(td); - networkBehaviourProcessor.Process(); - return true; - } - - public static MethodReference ResolveMethod(TypeReference t, string name) - { - MethodReference result; - if (t == null) - { - Log.Error("Type missing for " + name); - fail = true; - result = null; - } - else - { - foreach (var methodDefinition in t.Resolve().Methods) - { - if (methodDefinition.Name == name) - { - return scriptDef.MainModule.ImportReference(methodDefinition); - } - } - - Log.Error($"ResolveMethod failed - Couldn't find {name} in {t.Name}"); - foreach (var methodDefinition2 in t.Resolve().Methods) - { - Log.Error("- has method " + methodDefinition2.Name); - } - - fail = true; - result = null; - } - - return result; - } - - private static MethodReference ResolveMethodWithArg(TypeReference t, string name, TypeReference argType) - { - foreach (var methodDefinition in t.Resolve().Methods) - { - if (methodDefinition.Name == name) - { - if (methodDefinition.Parameters.Count == 1) - { - if (methodDefinition.Parameters[0].ParameterType.FullName == argType.FullName) - { - return scriptDef.MainModule.ImportReference(methodDefinition); - } - } - } - } - - Log.Error(string.Concat(new object[] - { - "ResolveMethodWithArg failed ", - t.Name, - "::", - name, - " ", - argType - })); - fail = true; - return null; - } - - private static MethodDefinition ResolveDefaultPublicCtor(TypeReference variable) - { - foreach (var methodDefinition in variable.Resolve().Methods) - { - if (methodDefinition.Name == ".ctor" && methodDefinition.Resolve().IsPublic && methodDefinition.Parameters.Count == 0) - { - return methodDefinition; - } - } - - return null; - } - - private static GenericInstanceMethod ResolveMethodGeneric(TypeReference t, string name, TypeReference genericType) - { - foreach (var methodDefinition in t.Resolve().Methods) - { - if (methodDefinition.Name == name) - { - if (methodDefinition.Parameters.Count == 0) - { - if (methodDefinition.GenericParameters.Count == 1) - { - var method = scriptDef.MainModule.ImportReference(methodDefinition); - var genericInstanceMethod = new GenericInstanceMethod(method); - genericInstanceMethod.GenericArguments.Add(genericType); - if (genericInstanceMethod.GenericArguments[0].FullName == genericType.FullName) - { - return genericInstanceMethod; - } - } - } - } - } - - Log.Error(string.Concat(new object[] - { - "ResolveMethodGeneric failed ", - t.Name, - "::", - name, - " ", - genericType - })); - fail = true; - return null; - } - - public static FieldReference ResolveField(TypeReference t, string name) - { - foreach (var fieldDefinition in t.Resolve().Fields) - { - if (fieldDefinition.Name == name) - { - return scriptDef.MainModule.ImportReference(fieldDefinition); - } - } - - return null; - } - - public static MethodReference ResolveProperty(TypeReference t, string name) - { - foreach (var propertyDefinition in t.Resolve().Properties) - { - if (propertyDefinition.Name == name) - { - return scriptDef.MainModule.ImportReference(propertyDefinition.GetMethod); - } - } - - Log.Error($"ResolveProperty failed - Couldn't find {name} in {t.Name}"); - return null; - } - - private static void SetupUnityTypes() - { - vector2Type = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Vector2"); - if (vector2Type == null) - { - Log.Error("Vector2Type is null!"); - } - - vector3Type = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Vector3"); - vector4Type = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Vector4"); - colorType = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Color"); - color32Type = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Color32"); - quaternionType = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Quaternion"); - rectType = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Rect"); - planeType = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Plane"); - rayType = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Ray"); - matrixType = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Matrix4x4"); - gameObjectType = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.GameObject"); - if (gameObjectType == null) - { - Log.Error("GameObjectType is null!"); - } - - transformType = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Transform"); - unityObjectType = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Object"); - - hashType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkHash128"); - - NetworkClientType = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.QNetworkClient"); - NetworkServerType = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.QNetworkServer"); - NetworkCRCType = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.QNetworkCRC"); - - SyncVarType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncVarAttribute"); - - CommandType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.CommandAttribute"); - - ClientRpcType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.ClientRpcAttribute"); - - TargetRpcType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.TargetRpcAttribute"); - - SyncEventType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncEventAttribute"); - - SyncListType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncList`1"); - - NetworkSettingsType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkSettingsAttribute"); - - SyncListFloatType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncListFloat"); - - SyncListIntType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncListInt"); - - SyncListUIntType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncListUInt"); - - SyncListBoolType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncListBool"); - - SyncListStringType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncListString"); - - } - - private static void SetupCorLib() - { - var name = AssemblyNameReference.Parse("mscorlib"); - var parameters = new ReaderParameters - { - AssemblyResolver = scriptDef.MainModule.AssemblyResolver - }; - corLib = scriptDef.MainModule.AssemblyResolver.Resolve(name, parameters).MainModule; - } - - private static TypeReference ImportCorLibType(string fullName) - { - var type = corLib.GetType(fullName) ?? Enumerable.First(corLib.ExportedTypes, (ExportedType t) => t.FullName == fullName).Resolve(); - return scriptDef.MainModule.ImportReference(type); - } - - private static void SetupTargetTypes() - { - SetupCorLib(); - voidType = ImportCorLibType("System.Void"); - singleType = ImportCorLibType("System.Single"); - doubleType = ImportCorLibType("System.Double"); - decimalType = ImportCorLibType("System.Decimal"); - boolType = ImportCorLibType("System.Boolean"); - stringType = ImportCorLibType("System.String"); - int64Type = ImportCorLibType("System.Int64"); - uint64Type = ImportCorLibType("System.UInt64"); - int32Type = ImportCorLibType("System.Int32"); - uint32Type = ImportCorLibType("System.UInt32"); - int16Type = ImportCorLibType("System.Int16"); - uint16Type = ImportCorLibType("System.UInt16"); - byteType = ImportCorLibType("System.Byte"); - sbyteType = ImportCorLibType("System.SByte"); - charType = ImportCorLibType("System.Char"); - objectType = ImportCorLibType("System.Object"); - valueTypeType = ImportCorLibType("System.ValueType"); - typeType = ImportCorLibType("System.Type"); - IEnumeratorType = ImportCorLibType("System.Collections.IEnumerator"); - MemoryStreamType = ImportCorLibType("System.IO.MemoryStream"); - - NetworkReaderType = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.Transport.QNetworkReader"); - - NetworkReaderDef = NetworkReaderType.Resolve(); - NetworkReaderCtor = ResolveMethod(NetworkReaderDef, ".ctor"); - - NetworkWriterType = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.Transport.QNetworkWriter"); - - NetworkWriterDef = NetworkWriterType.Resolve(); - NetworkWriterCtor = ResolveMethod(NetworkWriterDef, ".ctor"); - MemoryStreamCtor = ResolveMethod(MemoryStreamType, ".ctor"); - - NetworkInstanceIdType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkInstanceId"); - NetworkSceneIdType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkSceneId"); - NetworkInstanceIdType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkInstanceId"); - NetworkSceneIdType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.NetworkSceneId"); - - NetworkServerGetActive = ResolveMethod(NetworkServerType, "get_active"); - NetworkServerGetLocalClientActive = ResolveMethod(NetworkServerType, "get_localClientActive"); - NetworkClientGetActive = ResolveMethod(NetworkClientType, "get_active"); - NetworkReaderReadInt32 = ResolveMethod(NetworkReaderType, "ReadInt32"); - NetworkWriterWriteInt32 = ResolveMethodWithArg(NetworkWriterType, "Write", int32Type); - NetworkWriterWriteInt16 = ResolveMethodWithArg(NetworkWriterType, "Write", int16Type); - NetworkReaderReadPacked32 = ResolveMethod(NetworkReaderType, "ReadPackedUInt32"); - NetworkReaderReadPacked64 = ResolveMethod(NetworkReaderType, "ReadPackedUInt64"); - NetworkReaderReadByte = ResolveMethod(NetworkReaderType, "ReadByte"); - NetworkWriterWritePacked32 = ResolveMethod(NetworkWriterType, "WritePackedUInt32"); - NetworkWriterWritePacked64 = ResolveMethod(NetworkWriterType, "WritePackedUInt64"); - NetworkWriterWriteNetworkInstanceId = ResolveMethodWithArg(NetworkWriterType, "Write", NetworkInstanceIdType); - NetworkWriterWriteNetworkSceneId = ResolveMethodWithArg(NetworkWriterType, "Write", NetworkSceneIdType); - NetworkWriterStartMessage = ResolveMethod(NetworkWriterType, "StartMessage"); - NetworkWriterFinishMessage = ResolveMethod(NetworkWriterType, "FinishMessage"); - NetworkReaderReadNetworkInstanceId = ResolveMethod(NetworkReaderType, "ReadNetworkId"); - NetworkReaderReadNetworkSceneId = ResolveMethod(NetworkReaderType, "ReadSceneId"); - NetworkInstanceIsEmpty = ResolveMethod(NetworkInstanceIdType, "IsEmpty"); - NetworkReadUInt16 = ResolveMethod(NetworkReaderType, "ReadUInt16"); - NetworkWriteUInt16 = ResolveMethodWithArg(NetworkWriterType, "Write", uint16Type); - - CmdDelegateReference = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.QNetworkBehaviour/CmdDelegate"); - - CmdDelegateConstructor = ResolveMethod(CmdDelegateReference, ".ctor"); - Console.WriteLine("gameobject"); - scriptDef.MainModule.ImportReference(gameObjectType); - Console.WriteLine("transform"); - scriptDef.MainModule.ImportReference(transformType); - - TypeReference type = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.Components.QNetworkIdentity"); - - Console.WriteLine("type"); - NetworkIdentityType = scriptDef.MainModule.ImportReference(type); - Console.WriteLine("networkinstanceidtype"); - NetworkInstanceIdType = scriptDef.MainModule.ImportReference(NetworkInstanceIdType); - SyncListFloatReadType = ResolveMethod(SyncListFloatType, "ReadReference"); - SyncListIntReadType = ResolveMethod(SyncListIntType, "ReadReference"); - SyncListUIntReadType = ResolveMethod(SyncListUIntType, "ReadReference"); - SyncListBoolReadType = ResolveMethod(SyncListBoolType, "ReadReference"); - SyncListStringReadType = ResolveMethod(SyncListStringType, "ReadReference"); - SyncListFloatWriteType = ResolveMethod(SyncListFloatType, "WriteInstance"); - SyncListIntWriteType = ResolveMethod(SyncListIntType, "WriteInstance"); - SyncListUIntWriteType = ResolveMethod(SyncListUIntType, "WriteInstance"); - SyncListBoolWriteType = ResolveMethod(SyncListBoolType, "WriteInstance"); - SyncListStringWriteType = ResolveMethod(SyncListStringType, "WriteInstance"); - - NetworkBehaviourType = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.QNetworkBehaviour"); - - Console.WriteLine("networkbehaviourtype"); - NetworkBehaviourType2 = scriptDef.MainModule.ImportReference(NetworkBehaviourType); - - NetworkConnectionType = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.QNetworkConnection"); - - MonoBehaviourType = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.MonoBehaviour"); - ScriptableObjectType = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.ScriptableObject"); - - NetworkConnectionType = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.QNetworkConnection"); - - NetworkConnectionType = scriptDef.MainModule.ImportReference(NetworkConnectionType); - - ULocalConnectionToServerType = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.QULocalConnectionToServer"); - - ULocalConnectionToServerType = scriptDef.MainModule.ImportReference(ULocalConnectionToServerType); - - ULocalConnectionToClientType = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.QULocalConnectionToClient"); - - ULocalConnectionToClientType = scriptDef.MainModule.ImportReference(ULocalConnectionToClientType); - - MessageBaseType = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.Messages.QMessageBase"); - SyncListStructType = UNetAssemblyDefinition.MainModule.GetType("UnityEngine.Networking.SyncListStruct`1"); - - NetworkBehaviourDirtyBitsReference = ResolveProperty(NetworkBehaviourType, "SyncVarDirtyBits"); - NetworkBehaviourOnSerialize = ResolveMethod(NetworkBehaviourType, "OnSerialize"); - NetworkBehaviourClearAllDirtyBits = ResolveMethod(NetworkBehaviourType, "ClearAllDirtyBits"); - NetworkBehaviourGetNetworkChannel = ResolveMethod(NetworkBehaviourType, "GetNetworkChannel"); - NetworkBehaviourClientSendUpdateVars = ResolveMethod(NetworkBehaviourType, "ClientSendUpdateVars"); - NetworkConnectionSendWriter = ResolveMethod(NetworkConnectionType, "SendWriter"); - ComponentType = UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Component"); - - ClientSceneType = QNetAssemblyDefinition.MainModule.GetType("QuantumUNET.QClientScene"); - - FindLocalObjectReference = ResolveMethod(ClientSceneType, "FindLocalObject"); - RegisterBehaviourReference = ResolveMethod(NetworkCRCType, "RegisterBehaviour"); - ReadyConnectionReference = ResolveMethod(ClientSceneType, "get_readyConnection"); - getComponentReference = ResolveMethodGeneric(ComponentType, "GetComponent", NetworkIdentityType); - getUNetIdReference = ResolveMethod(type, "get_NetId"); - gameObjectInequality = ResolveMethod(unityObjectType, "op_Inequality"); - UBehaviourIsServer = ResolveMethod(NetworkBehaviourType, "get_IsServer"); - getPlayerIdReference = ResolveMethod(NetworkBehaviourType, "get_PlayerControllerId"); - setSyncVarReference = ResolveMethod(NetworkBehaviourType, "SetSyncVar"); - setSyncVarHookGuard = ResolveMethod(NetworkBehaviourType, "set_SyncVarHookGuard"); - getSyncVarHookGuard = ResolveMethod(NetworkBehaviourType, "get_SyncVarHookGuard"); - setSyncVarGameObjectReference = ResolveMethod(NetworkBehaviourType, "SetSyncVarGameObject"); - registerCommandDelegateReference = ResolveMethod(NetworkBehaviourType, "RegisterCommandDelegate"); - registerRpcDelegateReference = ResolveMethod(NetworkBehaviourType, "RegisterRpcDelegate"); - registerEventDelegateReference = ResolveMethod(NetworkBehaviourType, "RegisterEventDelegate"); - registerSyncListDelegateReference = ResolveMethod(NetworkBehaviourType, "RegisterSyncListDelegate"); - getTypeReference = ResolveMethod(objectType, "GetType"); - getTypeFromHandleReference = ResolveMethod(typeType, "GetTypeFromHandle"); - logErrorReference = ResolveMethod(UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Debug"), "LogError"); - logWarningReference = ResolveMethod(UnityAssemblyDefinition.MainModule.GetType("UnityEngine.Debug"), "LogWarning"); - sendCommandInternal = ResolveMethod(NetworkBehaviourType, "SendCommandInternal"); - sendRpcInternal = ResolveMethod(NetworkBehaviourType, "SendRPCInternal"); - sendTargetRpcInternal = ResolveMethod(NetworkBehaviourType, "SendTargetRPCInternal"); - sendEventInternal = ResolveMethod(NetworkBehaviourType, "SendEventInternal"); - Console.WriteLine("synclisttype"); - SyncListType = scriptDef.MainModule.ImportReference(SyncListType); - SyncListInitBehaviourReference = ResolveMethod(SyncListType, "InitializeBehaviour"); - SyncListInitHandleMsg = ResolveMethod(SyncListType, "HandleMsg"); - SyncListClear = ResolveMethod(SyncListType, "Clear"); - } - - private static void SetupReadFunctions() - { - var weaverLists = lists; - var dictionary = new Dictionary - { - { singleType.FullName, ResolveMethod(NetworkReaderType, "ReadSingle") }, - { doubleType.FullName, ResolveMethod(NetworkReaderType, "ReadDouble") }, - { boolType.FullName, ResolveMethod(NetworkReaderType, "ReadBoolean") }, - { stringType.FullName, ResolveMethod(NetworkReaderType, "ReadString") }, - { int64Type.FullName, NetworkReaderReadPacked64 }, - { uint64Type.FullName, NetworkReaderReadPacked64 }, - { int32Type.FullName, NetworkReaderReadPacked32 }, - { uint32Type.FullName, NetworkReaderReadPacked32 }, - { int16Type.FullName, NetworkReaderReadPacked32 }, - { uint16Type.FullName, NetworkReaderReadPacked32 }, - { byteType.FullName, NetworkReaderReadPacked32 }, - { sbyteType.FullName, NetworkReaderReadPacked32 }, - { charType.FullName, NetworkReaderReadPacked32 }, - { decimalType.FullName, ResolveMethod(NetworkReaderType, "ReadDecimal") }, - { vector2Type.FullName, ResolveMethod(NetworkReaderType, "ReadVector2") }, - { vector3Type.FullName, ResolveMethod(NetworkReaderType, "ReadVector3") }, - { vector4Type.FullName, ResolveMethod(NetworkReaderType, "ReadVector4") }, - { colorType.FullName, ResolveMethod(NetworkReaderType, "ReadColor") }, - { color32Type.FullName, ResolveMethod(NetworkReaderType, "ReadColor32") }, - { quaternionType.FullName, ResolveMethod(NetworkReaderType, "ReadQuaternion") }, - { rectType.FullName, ResolveMethod(NetworkReaderType, "ReadRect") }, - { planeType.FullName, ResolveMethod(NetworkReaderType, "ReadPlane") }, - { rayType.FullName, ResolveMethod(NetworkReaderType, "ReadRay") }, - { matrixType.FullName, ResolveMethod(NetworkReaderType, "ReadMatrix4x4") }, - { hashType.FullName, ResolveMethod(NetworkReaderType, "ReadNetworkHash128") }, - { gameObjectType.FullName, ResolveMethod(NetworkReaderType, "ReadGameObject") }, - { NetworkIdentityType.FullName, ResolveMethod(NetworkReaderType, "ReadNetworkIdentity") }, - { NetworkInstanceIdType.FullName, NetworkReaderReadNetworkInstanceId }, - { NetworkSceneIdType.FullName, NetworkReaderReadNetworkSceneId }, - { transformType.FullName, ResolveMethod(NetworkReaderType, "ReadTransform") }, - { "System.Byte[]", ResolveMethod(NetworkReaderType, "ReadBytesAndSize") } - }; - weaverLists.readFuncs = dictionary; - var weaverLists2 = lists; - dictionary = new Dictionary - { - { SyncListFloatType.FullName, SyncListFloatReadType }, - { SyncListIntType.FullName, SyncListIntReadType }, - { SyncListUIntType.FullName, SyncListUIntReadType }, - { SyncListBoolType.FullName, SyncListBoolReadType }, - { SyncListStringType.FullName, SyncListStringReadType } - }; - weaverLists2.readByReferenceFuncs = dictionary; - } - - private static void SetupWriteFunctions() - { - var weaverLists = lists; - var dictionary = new Dictionary - { - { singleType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", singleType) }, - { doubleType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", doubleType) }, - { boolType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", boolType) }, - { stringType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", stringType) }, - { int64Type.FullName, NetworkWriterWritePacked64 }, - { uint64Type.FullName, NetworkWriterWritePacked64 }, - { int32Type.FullName, NetworkWriterWritePacked32 }, - { uint32Type.FullName, NetworkWriterWritePacked32 }, - { int16Type.FullName, NetworkWriterWritePacked32 }, - { uint16Type.FullName, NetworkWriterWritePacked32 }, - { byteType.FullName, NetworkWriterWritePacked32 }, - { sbyteType.FullName, NetworkWriterWritePacked32 }, - { charType.FullName, NetworkWriterWritePacked32 }, - { decimalType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", decimalType) }, - { vector2Type.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", vector2Type) }, - { vector3Type.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", vector3Type) }, - { vector4Type.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", vector4Type) }, - { colorType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", colorType) }, - { color32Type.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", color32Type) }, - { quaternionType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", quaternionType) }, - { rectType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", rectType) }, - { planeType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", planeType) }, - { rayType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", rayType) }, - { matrixType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", matrixType) }, - { hashType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", hashType) }, - { gameObjectType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", gameObjectType) }, - { NetworkIdentityType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", NetworkIdentityType) }, - { NetworkInstanceIdType.FullName, NetworkWriterWriteNetworkInstanceId }, - { NetworkSceneIdType.FullName, NetworkWriterWriteNetworkSceneId }, - { transformType.FullName, ResolveMethodWithArg(NetworkWriterType, "Write", transformType) }, - { "System.Byte[]", ResolveMethod(NetworkWriterType, "WriteBytesFull") }, - { SyncListFloatType.FullName, SyncListFloatWriteType }, - { SyncListIntType.FullName, SyncListIntWriteType }, - { SyncListUIntType.FullName, SyncListUIntWriteType }, - { SyncListBoolType.FullName, SyncListBoolWriteType }, - { SyncListStringType.FullName, SyncListStringWriteType } - }; - weaverLists.writeFuncs = dictionary; - } - - private static bool IsNetworkBehaviour(TypeDefinition td) - { - bool result; - if (!td.IsClass) - { - result = false; - } - else - { - var baseType = td.BaseType; - while (baseType != null) - { - if (baseType.FullName == NetworkBehaviourType.FullName) - { - return true; - } - - try - { - baseType = baseType.Resolve().BaseType; - } - catch (AssemblyResolutionException) - { - break; - } - } - - result = false; - } - - return result; - } - - public static bool IsDerivedFrom(TypeDefinition td, TypeReference baseClass) - { - bool result; - if (!td.IsClass) - { - result = false; - } - else - { - var baseType = td.BaseType; - while (baseType != null) - { - var text = baseType.FullName; - var num = text.IndexOf('<'); - if (num != -1) - { - text = text.Substring(0, num); - } - - if (text == baseClass.FullName) - { - return true; - } - - try - { - baseType = baseType.Resolve().BaseType; - } - catch (AssemblyResolutionException) - { - break; - } - } - - result = false; - } - - return result; - } - - public static bool IsValidTypeToGenerate(TypeDefinition variable) - { - var name = scriptDef.MainModule.Name; - bool result; - if (variable.Module.Name != name) - { - Log.Error(string.Concat(new string[] - { - "parameter [", - variable.Name, - "] is of the type [", - variable.FullName, - "] is not a valid type, please make sure to use a valid type." - })); - fail = true; - fail = true; - result = false; - } - else - { - result = true; - } - - return result; - } - - private static void CheckMonoBehaviour(TypeDefinition td) - { - if (IsDerivedFrom(td, MonoBehaviourType)) - { - ProcessMonoBehaviourType(td); - } - } - - private static bool CheckNetworkBehaviour(TypeDefinition td) - { - bool result; - if (!td.IsClass) - { - result = false; - } - else if (!IsNetworkBehaviour(td)) - { - CheckMonoBehaviour(td); - result = false; - } - else - { - var list = new List(); - var typeDefinition = td; - while (typeDefinition != null) - { - if (typeDefinition.FullName == NetworkBehaviourType.FullName) - { - break; - } - - try - { - list.Insert(0, typeDefinition); - typeDefinition = typeDefinition.BaseType.Resolve(); - } - catch (AssemblyResolutionException) - { - break; - } - } - - var flag = false; - foreach (var td2 in list) - { - flag |= ProcessNetworkBehaviourType(td2); - } - - result = flag; - } - - return result; - } - - private static bool CheckMessageBase(TypeDefinition td) - { - bool result; - if (!td.IsClass) - { - result = false; - } - else - { - var flag = false; - var baseType = td.BaseType; - while (baseType != null) - { - if (baseType.FullName == MessageBaseType.FullName) - { - flag |= ProcessMessageType(td); - break; - } - - try - { - baseType = baseType.Resolve().BaseType; - } - catch (AssemblyResolutionException) - { - break; - } - } - - foreach (var td2 in td.NestedTypes) - { - flag |= CheckMessageBase(td2); - } - - result = flag; - } - - return result; - } - - private static bool CheckSyncListStruct(TypeDefinition td) - { - bool result; - if (!td.IsClass) - { - result = false; - } - else - { - var flag = false; - var baseType = td.BaseType; - while (baseType != null) - { - if (baseType.FullName.Contains("SyncListStruct")) - { - flag |= ProcessSyncListStructType(td); - break; - } - - try - { - baseType = baseType.Resolve().BaseType; - } - catch (AssemblyResolutionException) - { - break; - } - } - - foreach (var td2 in td.NestedTypes) - { - flag |= CheckSyncListStruct(td2); - } - - result = flag; - } - - return result; - } - - private static bool Weave(string assName, IEnumerable dependencies, IAssemblyResolver assemblyResolver, string unityEngineDLLPath, string unityUNetDLLPath, string outputDir) - { - var readerParameters = Helpers.ReaderParameters(assName, dependencies, assemblyResolver, unityEngineDLLPath, unityUNetDLLPath); - scriptDef = AssemblyDefinition.ReadAssembly(assName, readerParameters); - SetupTargetTypes(); - SetupReadFunctions(); - SetupWriteFunctions(); - var mainModule = scriptDef.MainModule; - Console.WriteLine("Script Module: {0}", mainModule.Name); - var flag = false; - for (var i = 0; i < 2; i++) - { - var stopwatch = Stopwatch.StartNew(); - foreach (var typeDefinition in mainModule.Types) - { - if (typeDefinition.IsClass && CanBeResolved(typeDefinition.BaseType)) - { - try - { - if (i == 0) - { - flag |= CheckSyncListStruct(typeDefinition); - } - else - { - flag |= CheckNetworkBehaviour(typeDefinition); - flag |= CheckMessageBase(typeDefinition); - } - } - catch (Exception ex) - { - if (scriptDef.MainModule.SymbolReader != null) - { - scriptDef.MainModule.SymbolReader.Dispose(); - } - - fail = true; - throw ex; - } - } - - if (fail) - { - if (scriptDef.MainModule.SymbolReader != null) - { - scriptDef.MainModule.SymbolReader.Dispose(); - } - - return false; - } - } - - stopwatch.Stop(); - Console.WriteLine(string.Concat(new object[] - { - "Pass: ", - i, - " took ", - stopwatch.ElapsedMilliseconds, - " milliseconds" - })); - } - - if (flag) - { - foreach (var methodDefinition in lists.replacedMethods) - { - lists.replacementMethodNames.Add(methodDefinition.FullName); - } - - try - { - ProcessPropertySites(); - } - catch (Exception ex2) - { - Log.Error("ProcessPropertySites exception: " + ex2); - if (scriptDef.MainModule.SymbolReader != null) - { - scriptDef.MainModule.SymbolReader.Dispose(); - } - - return false; - } - - if (fail) - { - if (scriptDef.MainModule.SymbolReader != null) - { - scriptDef.MainModule.SymbolReader.Dispose(); - } - - return false; - } - - var fileName = Helpers.DestinationFileFor(outputDir, assName); - var writerParameters = Helpers.GetWriterParameters(readerParameters); - if (writerParameters.SymbolWriterProvider is PdbWriterProvider) - { - writerParameters.SymbolWriterProvider = new MdbWriterProvider(); - var text = Path.ChangeExtension(assName, ".pdb"); - File.Delete(text); - } - - scriptDef.Write(fileName, writerParameters); - } - - if (scriptDef.MainModule.SymbolReader != null) - { - scriptDef.MainModule.SymbolReader.Dispose(); - } - - return true; - } - - public static bool WeaveAssemblies(string assembly, IEnumerable dependencies, IAssemblyResolver assemblyResolver, string outputDir, string unityEngineDLLPath, string unityQNetDLLPath, string unityUNetDLLPath) - { - fail = false; - lists = new WeaverLists(); - Console.WriteLine($"load unity engine from {unityEngineDLLPath}"); - UnityAssemblyDefinition = AssemblyDefinition.ReadAssembly(unityEngineDLLPath); - Console.WriteLine($"load qnet from {unityQNetDLLPath}"); - QNetAssemblyDefinition = AssemblyDefinition.ReadAssembly(unityQNetDLLPath); - Console.WriteLine($"load unet from {unityUNetDLLPath}"); - UNetAssemblyDefinition = AssemblyDefinition.ReadAssembly(unityUNetDLLPath); - SetupUnityTypes(); - try - { - if (!Weave(assembly, dependencies, assemblyResolver, unityEngineDLLPath, unityQNetDLLPath, outputDir)) - { - return false; - } - } - catch (Exception ex) - { - Log.Error("Exception :" + ex); - return false; - } - - corLib = null; - return true; - } - - public static TypeReference NetworkBehaviourType; - - public static TypeReference NetworkBehaviourType2; - - public static TypeReference MonoBehaviourType; - - public static TypeReference ScriptableObjectType; - - public static TypeReference NetworkConnectionType; - - public static TypeReference ULocalConnectionToServerType; - - public static TypeReference ULocalConnectionToClientType; - - public static TypeReference MessageBaseType; - - public static TypeReference SyncListStructType; - - public static MethodReference NetworkBehaviourDirtyBitsReference; - - public static MethodReference NetworkBehaviourOnSerialize; - - public static MethodReference NetworkBehaviourClearAllDirtyBits; - - public static MethodReference NetworkBehaviourGetNetworkChannel; - - public static MethodReference NetworkConnectionSendWriter; - - public static MethodReference NetworkBehaviourClientSendUpdateVars; - - public static TypeReference NetworkClientType; - - public static TypeReference NetworkServerType; - - public static TypeReference NetworkCRCType; - - public static TypeReference NetworkReaderType; - - public static TypeDefinition NetworkReaderDef; - - public static TypeReference NetworkWriterType; - - public static TypeDefinition NetworkWriterDef; - - public static MethodReference NetworkWriterCtor; - - public static MethodReference NetworkReaderCtor; - - public static TypeReference MemoryStreamType; - - public static MethodReference MemoryStreamCtor; - - public static MethodReference getComponentReference; - - public static MethodReference getUNetIdReference; - - public static MethodReference getPlayerIdReference; - - public static TypeReference NetworkIdentityType; - - public static TypeReference NetworkInstanceIdType; - - public static TypeReference NetworkSceneIdType; - - public static TypeReference IEnumeratorType; - - public static TypeReference ClientSceneType; - - public static MethodReference FindLocalObjectReference; - - public static MethodReference RegisterBehaviourReference; - - public static MethodReference ReadyConnectionReference; - - public static TypeReference ComponentType; - - public static TypeReference CmdDelegateReference; - - public static MethodReference CmdDelegateConstructor; - - public static MethodReference NetworkReaderReadInt32; - - public static MethodReference NetworkWriterWriteInt32; - - public static MethodReference NetworkWriterWriteInt16; - - public static MethodReference NetworkServerGetActive; - - public static MethodReference NetworkServerGetLocalClientActive; - - public static MethodReference NetworkClientGetActive; - - public static MethodReference UBehaviourIsServer; - - public static MethodReference NetworkReaderReadPacked32; - - public static MethodReference NetworkReaderReadPacked64; - - public static MethodReference NetworkReaderReadByte; - - public static MethodReference NetworkWriterWritePacked32; - - public static MethodReference NetworkWriterWritePacked64; - - public static MethodReference NetworkWriterWriteNetworkInstanceId; - - public static MethodReference NetworkWriterWriteNetworkSceneId; - - public static MethodReference NetworkWriterStartMessage; - - public static MethodReference NetworkWriterFinishMessage; - - public static MethodReference NetworkReaderReadNetworkInstanceId; - - public static MethodReference NetworkReaderReadNetworkSceneId; - - public static MethodReference NetworkInstanceIsEmpty; - - public static MethodReference NetworkReadUInt16; - - public static MethodReference NetworkWriteUInt16; - - public static TypeReference SyncVarType; - - public static TypeReference CommandType; - - public static TypeReference ClientRpcType; - - public static TypeReference TargetRpcType; - - public static TypeReference SyncEventType; - - public static TypeReference SyncListType; - - public static MethodReference SyncListInitBehaviourReference; - - public static MethodReference SyncListInitHandleMsg; - - public static MethodReference SyncListClear; - - public static TypeReference NetworkSettingsType; - - public static TypeReference SyncListFloatType; - - public static TypeReference SyncListIntType; - - public static TypeReference SyncListUIntType; - - public static TypeReference SyncListBoolType; - - public static TypeReference SyncListStringType; - - public static MethodReference SyncListFloatReadType; - - public static MethodReference SyncListIntReadType; - - public static MethodReference SyncListUIntReadType; - - public static MethodReference SyncListStringReadType; - - public static MethodReference SyncListBoolReadType; - - public static MethodReference SyncListFloatWriteType; - - public static MethodReference SyncListIntWriteType; - - public static MethodReference SyncListUIntWriteType; - - public static MethodReference SyncListBoolWriteType; - - public static MethodReference SyncListStringWriteType; - - public static TypeReference voidType; - - public static TypeReference singleType; - - public static TypeReference doubleType; - - public static TypeReference decimalType; - - public static TypeReference boolType; - - public static TypeReference stringType; - - public static TypeReference int64Type; - - public static TypeReference uint64Type; - - public static TypeReference int32Type; - - public static TypeReference uint32Type; - - public static TypeReference int16Type; - - public static TypeReference uint16Type; - - public static TypeReference byteType; - - public static TypeReference sbyteType; - - public static TypeReference charType; - - public static TypeReference objectType; - - public static TypeReference valueTypeType; - - public static TypeReference vector2Type; - - public static TypeReference vector3Type; - - public static TypeReference vector4Type; - - public static TypeReference colorType; - - public static TypeReference color32Type; - - public static TypeReference quaternionType; - - public static TypeReference rectType; - - public static TypeReference rayType; - - public static TypeReference planeType; - - public static TypeReference matrixType; - - public static TypeReference hashType; - - public static TypeReference typeType; - - public static TypeReference gameObjectType; - - public static TypeReference transformType; - - public static TypeReference unityObjectType; - - public static MethodReference gameObjectInequality; - - public static MethodReference setSyncVarReference; - - public static MethodReference setSyncVarHookGuard; - - public static MethodReference getSyncVarHookGuard; - - public static MethodReference setSyncVarGameObjectReference; - - public static MethodReference registerCommandDelegateReference; - - public static MethodReference registerRpcDelegateReference; - - public static MethodReference registerEventDelegateReference; - - public static MethodReference registerSyncListDelegateReference; - - public static MethodReference getTypeReference; - - public static MethodReference getTypeFromHandleReference; - - public static MethodReference logErrorReference; - - public static MethodReference logWarningReference; - - public static MethodReference sendCommandInternal; - - public static MethodReference sendRpcInternal; - - public static MethodReference sendTargetRpcInternal; - - public static MethodReference sendEventInternal; - - public static WeaverLists lists; - - public static AssemblyDefinition scriptDef; - - public static ModuleDefinition corLib; - - public static AssemblyDefinition UnityAssemblyDefinition; - - public static AssemblyDefinition QNetAssemblyDefinition; - - public static AssemblyDefinition UNetAssemblyDefinition; - - private static bool m_DebugFlag = true; - - public static bool fail; - - public static bool generateLogErrors = false; - - private const int MaxRecursionCount = 128; - - private static int s_RecursionCount; - } -} diff --git a/QNetWeaver/WeaverLists.cs b/QNetWeaver/WeaverLists.cs deleted file mode 100644 index e8a96c60..00000000 --- a/QNetWeaver/WeaverLists.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Mono.Cecil; -using System.Collections.Generic; - -namespace QNetWeaver -{ - internal class WeaverLists - { - public List replacedFields = new List(); - - public List replacementProperties = new List(); - - public List netIdFields = new List(); - - public List replacedMethods = new List(); - - public List replacementMethods = new List(); - - public HashSet replacementMethodNames = new HashSet(); - - public List replacedEvents = new List(); - - public List replacementEvents = new List(); - - public Dictionary readFuncs; - - public Dictionary readByReferenceFuncs; - - public Dictionary writeFuncs; - - public List generatedReadFunctions = new List(); - - public List generatedWriteFunctions = new List(); - - public TypeDefinition generateContainerClass; - - public Dictionary numSyncVars = new Dictionary(); - } -} diff --git a/QNetWeaver/app.config b/QNetWeaver/app.config deleted file mode 100644 index 3e0e37cf..00000000 --- a/QNetWeaver/app.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/QNetWeaver/lib/Unity.UNetWeaver.dll b/QNetWeaver/lib/Unity.UNetWeaver.dll deleted file mode 100644 index 84c5baec9aa1f0bca7c20a9f938c21c05566a088..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95744 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

w-b!l1f!cb-gZvRB7-1;oDXsyacvu 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 diff --git a/QNetWeaver/packages.config b/QNetWeaver/packages.config deleted file mode 100644 index 2f488523..00000000 --- a/QNetWeaver/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/QSB.sln b/QSB.sln index 7473e240..15709d10 100644 --- a/QSB.sln +++ b/QSB.sln @@ -1,19 +1,14 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29613.14 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QSB", "QSB\QSB.csproj", "{1F00090A-C697-4C55-B401-192F3CFB9DC2}" - ProjectSection(ProjectDependencies) = postProject - {E23551F3-C095-4F50-8BF7-85BB2661859B} = {E23551F3-C095-4F50-8BF7-85BB2661859B} - EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuantumUNET", "QuantumUNET\QuantumUNET.csproj", "{C8C53004-1508-4F86-A419-4292C188DC2A}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QSBTests", "QSBTests\QSBTests.csproj", "{2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QNetWeaver", "QNetWeaver\QNetWeaver.csproj", "{E23551F3-C095-4F50-8BF7-85BB2661859B}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2569F98D-F671-42AA-82DE-505B05CDCEF2}" ProjectSection(SolutionItems) = preProject .gitignore = .gitignore @@ -40,10 +35,6 @@ Global {2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}.Debug|Any CPU.Build.0 = Debug|Any CPU {2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}.Release|Any CPU.ActiveCfg = Release|Any CPU {2FE8256C-0CB6-48F1-A4C0-5FA18A1846A3}.Release|Any CPU.Build.0 = Release|Any CPU - {E23551F3-C095-4F50-8BF7-85BB2661859B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E23551F3-C095-4F50-8BF7-85BB2661859B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E23551F3-C095-4F50-8BF7-85BB2661859B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E23551F3-C095-4F50-8BF7-85BB2661859B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE