two way syncvars

This commit is contained in:
Mister_Nebula 2021-05-04 19:32:05 +01:00
parent a8cb6cc36c
commit 72e3a4dfbf
6 changed files with 140 additions and 61 deletions

View File

@ -146,110 +146,125 @@ namespace QNetWeaver
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 methodDefinition = null;
MethodDefinition cctorMethodDef = null;
var flag = false;
foreach (var methodDefinition2 in m_td.Methods)
foreach (var methodDef in m_td.Methods)
{
if (methodDefinition2.Name == ".cctor")
if (methodDef.Name == ".cctor")
{
methodDefinition = methodDefinition2;
cctorMethodDef = methodDef;
flag = true;
}
}
if (methodDefinition != null)
if (cctorMethodDef != null)
{
if (methodDefinition.Body.Instructions.Count != 0)
if (cctorMethodDef.Body.Instructions.Count != 0)
{
var instruction = methodDefinition.Body.Instructions[methodDefinition.Body.Instructions.Count - 1];
if (!(instruction.OpCode == OpCodes.Ret))
var returnInstruction = cctorMethodDef.Body.Instructions[cctorMethodDef.Body.Instructions.Count - 1];
if (!(returnInstruction.OpCode == OpCodes.Ret))
{
Log.Error("No cctor for " + m_td.Name);
Log.Error("No .cctor for " + m_td.Name);
Weaver.fail = true;
return;
}
methodDefinition.Body.Instructions.RemoveAt(methodDefinition.Body.Instructions.Count - 1);
cctorMethodDef.Body.Instructions.RemoveAt(cctorMethodDef.Body.Instructions.Count - 1);
}
}
else
{
methodDefinition = new MethodDefinition(".cctor", MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, Weaver.voidType);
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 methodDefinition3 = null;
foreach (var methodDefinition4 in m_td.Methods)
MethodDefinition ctorMethodDef = null;
foreach (var methodDef in m_td.Methods)
{
if (methodDefinition4.Name == ".ctor")
if (methodDef.Name == ".ctor")
{
methodDefinition3 = methodDefinition4;
var instruction2 = methodDefinition3.Body.Instructions[methodDefinition3.Body.Instructions.Count - 1];
if (instruction2.OpCode == OpCodes.Ret)
ctorMethodDef = methodDef;
var returnInstruction = ctorMethodDef.Body.Instructions[ctorMethodDef.Body.Instructions.Count - 1];
if (returnInstruction.OpCode == OpCodes.Ret)
{
methodDefinition3.Body.Instructions.RemoveAt(methodDefinition3.Body.Instructions.Count - 1);
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);
Log.Error("No .ctor for " + m_td.Name);
return;
}
}
if (methodDefinition3 == null)
if (ctorMethodDef == null)
{
Weaver.fail = true;
Log.Error("No ctor for " + m_td.Name);
Log.Error("No .ctor for " + m_td.Name);
}
else
{
var ilprocessor = methodDefinition3.Body.GetILProcessor();
var ilprocessor2 = methodDefinition.Body.GetILProcessor();
var num = 0;
foreach (var methodDefinition5 in m_Cmds)
var ilprocessor = ctorMethodDef.Body.GetILProcessor();
var ilprocessor2 = cctorMethodDef.Body.GetILProcessor();
var commandIndex = 0;
foreach (var commandDef in m_Cmds)
{
var field = Weaver.ResolveField(m_td, "kCmd" + methodDefinition5.Name);
var hashCode = GetHashCode(m_td.Name + ":Cmd:" + methodDefinition5.Name);
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[num], field);
num++;
GenerateCommandDelegate(ilprocessor2, Weaver.registerCommandDelegateReference, m_CmdInvocationFuncs[commandIndex], field);
commandIndex++;
}
var num2 = 0;
foreach (var methodDefinition6 in m_Rpcs)
var rpcIndex = 0;
foreach (var rpcDef in m_Rpcs)
{
var field2 = Weaver.ResolveField(m_td, "kRpc" + methodDefinition6.Name);
var hashCode2 = GetHashCode(m_td.Name + ":Rpc:" + methodDefinition6.Name);
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[num2], field2);
num2++;
GenerateCommandDelegate(ilprocessor2, Weaver.registerRpcDelegateReference, m_RpcInvocationFuncs[rpcIndex], field2);
rpcIndex++;
}
var num3 = 0;
foreach (var methodDefinition7 in m_TargetRpcs)
var targetRpcIndex = 0;
foreach (var targetRpcDef in m_TargetRpcs)
{
var field3 = Weaver.ResolveField(m_td, "kTargetRpc" + methodDefinition7.Name);
var hashCode3 = GetHashCode(m_td.Name + ":TargetRpc:" + methodDefinition7.Name);
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[num3], field3);
num3++;
GenerateCommandDelegate(ilprocessor2, Weaver.registerRpcDelegateReference, m_TargetRpcInvocationFuncs[targetRpcIndex], field3);
targetRpcIndex++;
}
var num4 = 0;
foreach (var eventDefinition in m_Events)
var eventIndex = 0;
foreach (var eventDef in m_Events)
{
var field4 = Weaver.ResolveField(m_td, "kEvent" + eventDefinition.Name);
var hashCode4 = GetHashCode(m_td.Name + ":Event:" + eventDefinition.Name);
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[num4], field4);
num4++;
GenerateCommandDelegate(ilprocessor2, Weaver.registerEventDelegateReference, m_EventInvocationFuncs[eventIndex], field4);
eventIndex++;
}
var num5 = 0;
foreach (var fieldDefinition in m_SyncLists)
var syncListIndex = 0;
foreach (var syncListDef in m_SyncLists)
{
var field5 = Weaver.ResolveField(m_td, "kList" + fieldDefinition.Name);
var hashCode5 = GetHashCode(m_td.Name + ":List:" + fieldDefinition.Name);
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, fieldDefinition);
GenerateCommandDelegate(ilprocessor2, Weaver.registerSyncListDelegateReference, m_SyncListInvocationFuncs[num5], field5);
num5++;
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));
@ -257,7 +272,7 @@ namespace QNetWeaver
ilprocessor2.Append(ilprocessor2.Create(OpCodes.Ret));
if (!flag)
{
m_td.Methods.Add(methodDefinition);
m_td.Methods.Add(cctorMethodDef);
}
ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
m_td.Attributes = (m_td.Attributes & ~TypeAttributes.BeforeFieldInit);
@ -349,6 +364,7 @@ namespace QNetWeaver
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));
@ -1782,15 +1798,19 @@ namespace QNetWeaver
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0));
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldflda, fd));
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldc_I4, dirtyBit));
var noOperatorInstruction = ilprocessor.Create(OpCodes.Nop);
var returnInstruction = ilprocessor.Create(OpCodes.Ret);
CheckForHookFunction(fd, out var methodDefinition2);
if (methodDefinition2 != null)
{
var instruction = ilprocessor.Create(OpCodes.Nop);
ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.NetworkServerGetLocalClientActive));
ilprocessor.Append(ilprocessor.Create(OpCodes.Brfalse, instruction));
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, instruction));
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));
@ -1800,7 +1820,7 @@ namespace QNetWeaver
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(instruction);
ilprocessor.Append(noOperatorInstruction);
}
if (fd.FieldType.FullName == Weaver.gameObjectType.FullName)
{
@ -1813,6 +1833,15 @@ namespace QNetWeaver
var genericInstanceMethod = new GenericInstanceMethod(Weaver.setSyncVarReference);
genericInstanceMethod.GenericArguments.Add(fd.FieldType);
ilprocessor.Append(ilprocessor.Create(OpCodes.Call, genericInstanceMethod));
Weaver.DLog(m_td, " Start custom IL code", new object[0]);
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0));
ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.UBehaviourIsServer));
ilprocessor.Append(ilprocessor.Create(OpCodes.Brtrue_S, returnInstruction));
ilprocessor.Append(ilprocessor.Create(OpCodes.Ldarg_0));
ilprocessor.Append(ilprocessor.Create(OpCodes.Call, Weaver.NetworkBehaviourClientSendUpdateVars));
ilprocessor.Append(returnInstruction);
}
ilprocessor.Append(ilprocessor.Create(OpCodes.Ret));
methodDefinition.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.In, fd.FieldType));
@ -2023,8 +2052,9 @@ namespace QNetWeaver
private static int GetHashCode(string s)
{
var assembly = typeof(Unity.UNetWeaver.Program).Assembly;
var networkProcessorType = assembly.GetType("NetworkBehaviourProcessor");
return (int)networkProcessorType.GetMethod("GetHashCode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static).Invoke(null, new object[] { s });
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)

View File

@ -1118,6 +1118,8 @@ namespace QNetWeaver
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");
@ -1175,6 +1177,11 @@ namespace QNetWeaver
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");
@ -1667,6 +1674,16 @@ namespace QNetWeaver
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;
@ -1745,6 +1762,10 @@ namespace QNetWeaver
public static MethodReference NetworkWriterWriteNetworkSceneId;
public static MethodReference NetworkWriterStartMessage;
public static MethodReference NetworkWriterFinishMessage;
public static MethodReference NetworkReaderReadNetworkInstanceId;
public static MethodReference NetworkReaderReadNetworkSceneId;

View File

@ -1,5 +1,6 @@
using QuantumUNET.Components;
using QuantumUNET.Logging;
using QuantumUNET.Messages;
using QuantumUNET.Transport;
using System;
using System.Collections.Generic;
@ -53,6 +54,19 @@ namespace QuantumUNET
}
}
protected void ClientSendUpdateVars()
{
var writer = new QNetworkWriter();
writer.StartMessage(QMsgType.UpdateVars);
writer.Write(NetId);
if (OnSerialize(writer, false))
{
ClearAllDirtyBits();
writer.FinishMessage();
QClientScene.readyConnection.SendWriter(writer, GetNetworkChannel());
}
}
protected void SendCommandInternal(QNetworkWriter writer, int channelId, string cmdName)
{
if (!IsLocalPlayer && !HasAuthority)

View File

@ -109,6 +109,7 @@ namespace QuantumUNET
internal void RegisterMessageHandlers()
{
m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.UpdateVars, OnUpdateVarsMessage);
m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.Ready, OnClientReadyMessage);
m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.Command, OnCommandMessage);
m_SimpleServerSimple.RegisterHandlerSafe(QMsgType.LocalPlayerTransform, QNetworkTransform.HandleTransform);
@ -120,6 +121,19 @@ namespace QuantumUNET
maxPacketSize = hostTopology.DefaultConfig.PacketSize;
}
private static void OnUpdateVarsMessage(QNetworkMessage netMsg)
{
var networkInstanceId = netMsg.Reader.ReadNetworkId();
if (instance.m_NetworkScene.GetNetworkIdentity(networkInstanceId, out var networkIdentity))
{
networkIdentity.OnUpdateVars(netMsg.Reader, false);
}
else
{
Debug.LogError($"Did not find target for sync message for {networkInstanceId}");
}
}
public static void ListenRelay(string relayIp, int relayPort, NetworkID netGuid, SourceID sourceId, NodeID nodeId) => instance.InternalListenRelay(relayIp, relayPort, netGuid, sourceId, nodeId);
private void InternalListenRelay(string relayIp, int relayPort, NetworkID netGuid, SourceID sourceId, NodeID nodeId)

Binary file not shown.

Binary file not shown.