mirror of
https://github.com/misternebula/quantum-space-buddies.git
synced 2025-01-25 15:35:22 +00:00
2238 lines
76 KiB
C#
2238 lines
76 KiB
C#
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<MethodDefinition>(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<MethodDefinition>(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<ParameterDefinition> 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<string>();
|
|
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<FieldDefinition>();
|
|
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<MyStruct> {}\".");
|
|
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<FieldDefinition> m_SyncVars = new List<FieldDefinition>();
|
|
|
|
private List<FieldDefinition> m_SyncLists = new List<FieldDefinition>();
|
|
|
|
private List<FieldDefinition> m_SyncVarNetIds = new List<FieldDefinition>();
|
|
|
|
private List<MethodDefinition> m_Cmds = new List<MethodDefinition>();
|
|
|
|
private List<MethodDefinition> m_Rpcs = new List<MethodDefinition>();
|
|
|
|
private List<MethodDefinition> m_TargetRpcs = new List<MethodDefinition>();
|
|
|
|
private List<EventDefinition> m_Events = new List<EventDefinition>();
|
|
|
|
private List<FieldDefinition> m_SyncListStaticFields = new List<FieldDefinition>();
|
|
|
|
private List<MethodDefinition> m_CmdInvocationFuncs = new List<MethodDefinition>();
|
|
|
|
private List<MethodDefinition> m_SyncListInvocationFuncs = new List<MethodDefinition>();
|
|
|
|
private List<MethodDefinition> m_RpcInvocationFuncs = new List<MethodDefinition>();
|
|
|
|
private List<MethodDefinition> m_TargetRpcInvocationFuncs = new List<MethodDefinition>();
|
|
|
|
private List<MethodDefinition> m_EventInvocationFuncs = new List<MethodDefinition>();
|
|
|
|
private List<MethodDefinition> m_CmdCallFuncs = new List<MethodDefinition>();
|
|
|
|
private List<MethodDefinition> m_RpcCallFuncs = new List<MethodDefinition>();
|
|
|
|
private List<MethodDefinition> m_TargetRpcCallFuncs = new List<MethodDefinition>();
|
|
|
|
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";
|
|
}
|
|
}
|