Weaver: worker.Append(worker.Create(Opcode)) replaced with worker.Emit(Opcode)

This commit is contained in:
vis2k 2021-02-09 17:14:58 +08:00
parent 7ba6a9ab0b
commit 020f79a8d2
9 changed files with 285 additions and 286 deletions

View File

@ -52,21 +52,20 @@ public static MethodDefinition ProcessCommandCall(TypeDefinition td, MethodDefin
// invoke internal send and return
// load 'base.' to call the SendCommand function with
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldtoken, td));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldtoken, td);
// invokerClass
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.getTypeFromHandleReference));
worker.Append(worker.Create(OpCodes.Ldstr, cmdName));
worker.Emit(OpCodes.Call, WeaverTypes.getTypeFromHandleReference);
worker.Emit(OpCodes.Ldstr, cmdName);
// writer
worker.Append(worker.Create(OpCodes.Ldloc_0));
worker.Append(worker.Create(OpCodes.Ldc_I4, channel));
worker.Append(worker.Create(ignoreAuthority ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.sendCommandInternal));
worker.Emit(OpCodes.Ldloc_0);
worker.Emit(OpCodes.Ldc_I4, channel);
worker.Emit(ignoreAuthority ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
worker.Emit(OpCodes.Call, WeaverTypes.sendCommandInternal);
NetworkBehaviourProcessor.WriteRecycleWriter(worker);
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ret);
return cmd;
}
@ -93,8 +92,8 @@ public static MethodDefinition ProcessCommandInvoke(TypeDefinition td, MethodDef
NetworkBehaviourProcessor.WriteServerActiveCheck(worker, method.Name, label, "Command");
// setup for reader
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Castclass, td));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Castclass, td);
if (!NetworkBehaviourProcessor.ReadArguments(method, worker, RemoteCallType.Command))
return null;
@ -102,8 +101,8 @@ public static MethodDefinition ProcessCommandInvoke(TypeDefinition td, MethodDef
AddSenderConnection(method, worker);
// invoke actual command function
worker.Append(worker.Create(OpCodes.Callvirt, cmdCallFunc));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Callvirt, cmdCallFunc);
worker.Emit(OpCodes.Ret);
NetworkBehaviourProcessor.AddInvokeParameters(cmd.Parameters);
@ -119,7 +118,7 @@ static void AddSenderConnection(MethodDefinition method, ILProcessor worker)
{
// NetworkConnection is 3nd arg (arg0 is "obj" not "this" because method is static)
// example: static void InvokeCmdCmdSendCommand(NetworkBehaviour obj, NetworkReader reader, NetworkConnection connection)
worker.Append(worker.Create(OpCodes.Ldarg_2));
worker.Emit(OpCodes.Ldarg_2);
}
}
}

View File

@ -105,12 +105,12 @@ public bool Process()
public static void WriteClientActiveCheck(ILProcessor worker, string mdName, Instruction label, string errString)
{
// client active check
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.NetworkClientGetActive));
worker.Append(worker.Create(OpCodes.Brtrue, label));
worker.Emit(OpCodes.Call, WeaverTypes.NetworkClientGetActive);
worker.Emit(OpCodes.Brtrue, label);
worker.Append(worker.Create(OpCodes.Ldstr, errString + " " + mdName + " called on server."));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.logErrorReference));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ldstr, errString + " " + mdName + " called on server.");
worker.Emit(OpCodes.Call, WeaverTypes.logErrorReference);
worker.Emit(OpCodes.Ret);
worker.Append(label);
}
/*
@ -121,12 +121,12 @@ public static void WriteClientActiveCheck(ILProcessor worker, string mdName, Ins
public static void WriteServerActiveCheck(ILProcessor worker, string mdName, Instruction label, string errString)
{
// server active check
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.NetworkServerGetActive));
worker.Append(worker.Create(OpCodes.Brtrue, label));
worker.Emit(OpCodes.Call, WeaverTypes.NetworkServerGetActive);
worker.Emit(OpCodes.Brtrue, label);
worker.Append(worker.Create(OpCodes.Ldstr, errString + " " + mdName + " called on client."));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.logErrorReference));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ldstr, errString + " " + mdName + " called on client.");
worker.Emit(OpCodes.Call, WeaverTypes.logErrorReference);
worker.Emit(OpCodes.Ret);
worker.Append(label);
}
@ -139,15 +139,15 @@ public static void WriteSetupLocals(ILProcessor worker)
public static void WriteCreateWriter(ILProcessor worker)
{
// create writer
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.GetPooledWriterReference));
worker.Append(worker.Create(OpCodes.Stloc_0));
worker.Emit(OpCodes.Call, WeaverTypes.GetPooledWriterReference);
worker.Emit(OpCodes.Stloc_0);
}
public static void WriteRecycleWriter(ILProcessor worker)
{
// NetworkWriterPool.Recycle(writer);
worker.Append(worker.Create(OpCodes.Ldloc_0));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.RecycleWriterReference));
worker.Emit(OpCodes.Ldloc_0);
worker.Emit(OpCodes.Call, WeaverTypes.RecycleWriterReference);
}
public static bool WriteArguments(ILProcessor worker, MethodDefinition method, RemoteCallType callType)
@ -189,11 +189,11 @@ public static bool WriteArguments(ILProcessor worker, MethodDefinition method, R
// use built-in writer func on writer object
// NetworkWriter object
worker.Append(worker.Create(OpCodes.Ldloc_0));
worker.Emit(OpCodes.Ldloc_0);
// add argument to call
worker.Append(worker.Create(OpCodes.Ldarg, argNum));
worker.Emit(OpCodes.Ldarg, argNum);
// call writer extension method
worker.Append(worker.Create(OpCodes.Call, writeFunc));
worker.Emit(OpCodes.Call, writeFunc);
argNum += 1;
}
return true;
@ -214,7 +214,7 @@ public static void MarkAsProcessed(TypeDefinition td)
{
MethodDefinition versionMethod = new MethodDefinition(ProcessedFunctionName, MethodAttributes.Private, WeaverTypes.Import(typeof(void)));
ILProcessor worker = versionMethod.Body.GetILProcessor();
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ret);
td.Methods.Add(versionMethod);
}
}
@ -323,15 +323,15 @@ void GenerateConstants()
*/
void GenerateRegisterRemoteDelegate(ILProcessor worker, MethodReference registerMethod, MethodDefinition func, string cmdName)
{
worker.Append(worker.Create(OpCodes.Ldtoken, netBehaviourSubclass));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.getTypeFromHandleReference));
worker.Append(worker.Create(OpCodes.Ldstr, cmdName));
worker.Append(worker.Create(OpCodes.Ldnull));
worker.Append(worker.Create(OpCodes.Ldftn, func));
worker.Emit(OpCodes.Ldtoken, netBehaviourSubclass);
worker.Emit(OpCodes.Call, WeaverTypes.getTypeFromHandleReference);
worker.Emit(OpCodes.Ldstr, cmdName);
worker.Emit(OpCodes.Ldnull);
worker.Emit(OpCodes.Ldftn, func);
worker.Append(worker.Create(OpCodes.Newobj, WeaverTypes.CmdDelegateConstructor));
worker.Emit(OpCodes.Newobj, WeaverTypes.CmdDelegateConstructor);
//
worker.Append(worker.Create(OpCodes.Call, registerMethod));
worker.Emit(OpCodes.Call, registerMethod);
}
void GenerateRegisterCommandDelegate(ILProcessor worker, MethodReference registerMethod, MethodDefinition func, CmdResult cmdResult)
@ -339,17 +339,17 @@ void GenerateRegisterCommandDelegate(ILProcessor worker, MethodReference registe
string cmdName = cmdResult.method.Name;
bool ignoreAuthority = cmdResult.ignoreAuthority;
worker.Append(worker.Create(OpCodes.Ldtoken, netBehaviourSubclass));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.getTypeFromHandleReference));
worker.Append(worker.Create(OpCodes.Ldstr, cmdName));
worker.Append(worker.Create(OpCodes.Ldnull));
worker.Append(worker.Create(OpCodes.Ldftn, func));
worker.Emit(OpCodes.Ldtoken, netBehaviourSubclass);
worker.Emit(OpCodes.Call, WeaverTypes.getTypeFromHandleReference);
worker.Emit(OpCodes.Ldstr, cmdName);
worker.Emit(OpCodes.Ldnull);
worker.Emit(OpCodes.Ldftn, func);
worker.Append(worker.Create(OpCodes.Newobj, WeaverTypes.CmdDelegateConstructor));
worker.Emit(OpCodes.Newobj, WeaverTypes.CmdDelegateConstructor);
worker.Append(worker.Create(ignoreAuthority ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0));
worker.Emit(ignoreAuthority ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
worker.Append(worker.Create(OpCodes.Call, registerMethod));
worker.Emit(OpCodes.Call, registerMethod);
}
void GenerateSerialization()
@ -384,34 +384,34 @@ void GenerateSerialization()
if (baseSerialize != null)
{
// base
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Emit(OpCodes.Ldarg_0);
// writer
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Emit(OpCodes.Ldarg_1);
// forceAll
worker.Append(worker.Create(OpCodes.Ldarg_2));
worker.Append(worker.Create(OpCodes.Call, baseSerialize));
worker.Emit(OpCodes.Ldarg_2);
worker.Emit(OpCodes.Call, baseSerialize);
// set dirtyLocal to result of base.OnSerialize()
worker.Append(worker.Create(OpCodes.Stloc_0));
worker.Emit(OpCodes.Stloc_0);
}
// Generates: if (forceAll);
Instruction initialStateLabel = worker.Create(OpCodes.Nop);
// forceAll
worker.Append(worker.Create(OpCodes.Ldarg_2));
worker.Append(worker.Create(OpCodes.Brfalse, initialStateLabel));
worker.Emit(OpCodes.Ldarg_2);
worker.Emit(OpCodes.Brfalse, initialStateLabel);
foreach (FieldDefinition syncVar in syncVars)
{
// Generates a writer call for each sync variable
// writer
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Emit(OpCodes.Ldarg_1);
// this
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, syncVar));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, syncVar);
MethodReference writeFunc = Writers.GetWriteFunc(syncVar.FieldType);
if (writeFunc != null)
{
worker.Append(worker.Create(OpCodes.Call, writeFunc));
worker.Emit(OpCodes.Call, writeFunc);
}
else
{
@ -423,8 +423,8 @@ void GenerateSerialization()
// always return true if forceAll
// Generates: return true
worker.Append(worker.Create(OpCodes.Ldc_I4_1));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ldc_I4_1);
worker.Emit(OpCodes.Ret);
// Generates: end if (forceAll);
worker.Append(initialStateLabel);
@ -432,12 +432,12 @@ void GenerateSerialization()
// write dirty bits before the data fields
// Generates: writer.WritePackedUInt64 (base.get_syncVarDirtyBits ());
// writer
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Emit(OpCodes.Ldarg_1);
// base
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.NetworkBehaviourDirtyBitsReference));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Call, WeaverTypes.NetworkBehaviourDirtyBitsReference);
MethodReference writeUint64Func = Writers.GetWriteFunc(WeaverTypes.Import<ulong>());
worker.Append(worker.Create(OpCodes.Call, writeUint64Func));
worker.Emit(OpCodes.Call, writeUint64Func);
// generate a writer call for any dirty variable in this class
@ -449,24 +449,24 @@ void GenerateSerialization()
// Generates: if ((base.get_syncVarDirtyBits() & 1uL) != 0uL)
// base
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.NetworkBehaviourDirtyBitsReference));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Call, WeaverTypes.NetworkBehaviourDirtyBitsReference);
// 8 bytes = long
worker.Append(worker.Create(OpCodes.Ldc_I8, 1L << dirtyBit));
worker.Append(worker.Create(OpCodes.And));
worker.Append(worker.Create(OpCodes.Brfalse, varLabel));
worker.Emit(OpCodes.Ldc_I8, 1L << dirtyBit);
worker.Emit(OpCodes.And);
worker.Emit(OpCodes.Brfalse, varLabel);
// Generates a call to the writer for that field
// writer
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Emit(OpCodes.Ldarg_1);
// base
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, syncVar));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, syncVar);
MethodReference writeFunc = Writers.GetWriteFunc(syncVar.FieldType);
if (writeFunc != null)
{
worker.Append(worker.Create(OpCodes.Call, writeFunc));
worker.Emit(OpCodes.Call, writeFunc);
}
else
{
@ -475,9 +475,9 @@ void GenerateSerialization()
}
// something was dirty
worker.Append(worker.Create(OpCodes.Ldc_I4_1));
worker.Emit(OpCodes.Ldc_I4_1);
// set dirtyLocal to true
worker.Append(worker.Create(OpCodes.Stloc_0));
worker.Emit(OpCodes.Stloc_0);
worker.Append(varLabel);
dirtyBit += 1;
@ -485,13 +485,13 @@ void GenerateSerialization()
if (Weaver.GenerateLogErrors)
{
worker.Append(worker.Create(OpCodes.Ldstr, "Injected Serialize " + netBehaviourSubclass.Name));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.logErrorReference));
worker.Emit(OpCodes.Ldstr, "Injected Serialize " + netBehaviourSubclass.Name);
worker.Emit(OpCodes.Call, WeaverTypes.logErrorReference);
}
// generate: return dirtyLocal
worker.Append(worker.Create(OpCodes.Ldloc_0));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ldloc_0);
worker.Emit(OpCodes.Ret);
netBehaviourSubclass.Methods.Add(serialize);
}
@ -547,16 +547,16 @@ void DeserializeNetworkIdentityField(FieldDefinition syncVar, ILProcessor worker
// uint oldNetId = ___qNetId;
VariableDefinition oldNetId = new VariableDefinition(WeaverTypes.Import<uint>());
deserialize.Body.Variables.Add(oldNetId);
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, netIdField));
worker.Append(worker.Create(OpCodes.Stloc, oldNetId));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, netIdField);
worker.Emit(OpCodes.Stloc, oldNetId);
// GameObject/NetworkIdentity oldSyncVar = syncvar.getter;
VariableDefinition oldSyncVar = new VariableDefinition(syncVar.FieldType);
deserialize.Body.Variables.Add(oldSyncVar);
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, syncVar));
worker.Append(worker.Create(OpCodes.Stloc, oldSyncVar));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, syncVar);
worker.Emit(OpCodes.Stloc, oldSyncVar);
// read id and store in netId field BEFORE calling the hook
// -> this makes way more sense. by definition, the hook is
@ -568,13 +568,13 @@ void DeserializeNetworkIdentityField(FieldDefinition syncVar, ILProcessor worker
// values BEFORE the hook even returned and hence BEFORE the
// actual value was even set.
// put 'this.' onto stack for 'this.netId' below
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Emit(OpCodes.Ldarg_0);
// reader. for 'reader.Read()' below
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Emit(OpCodes.Ldarg_1);
// Read()
worker.Append(worker.Create(OpCodes.Call, Readers.GetReadFunc(WeaverTypes.Import<uint>())));
worker.Emit(OpCodes.Call, Readers.GetReadFunc(WeaverTypes.Import<uint>()));
// netId
worker.Append(worker.Create(OpCodes.Stfld, netIdField));
worker.Emit(OpCodes.Stfld, netIdField);
if (hookMethod != null)
{
@ -600,17 +600,17 @@ void DeserializeNetworkIdentityField(FieldDefinition syncVar, ILProcessor worker
Instruction syncVarEqualLabel = worker.Create(OpCodes.Nop);
// 'this.' for 'this.SyncVarEqual'
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Emit(OpCodes.Ldarg_0);
// 'oldNetId'
worker.Append(worker.Create(OpCodes.Ldloc, oldNetId));
worker.Emit(OpCodes.Ldloc, oldNetId);
// 'ref this.__netId'
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldflda, netIdField));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, netIdField);
// call the function
GenericInstanceMethod syncVarEqualGm = new GenericInstanceMethod(WeaverTypes.syncVarEqualReference);
syncVarEqualGm.GenericArguments.Add(netIdField.FieldType);
worker.Append(worker.Create(OpCodes.Call, syncVarEqualGm));
worker.Append(worker.Create(OpCodes.Brtrue, syncVarEqualLabel));
worker.Emit(OpCodes.Call, syncVarEqualGm);
worker.Emit(OpCodes.Brtrue, syncVarEqualLabel);
// call the hook
// Generates: OnValueChanged(oldValue, this.syncVar);
@ -655,16 +655,16 @@ void DeserializeNetworkBehaviourField(FieldDefinition syncVar, ILProcessor worke
// uint oldNetId = ___qNetId;
VariableDefinition oldNetId = new VariableDefinition(WeaverTypes.Import<NetworkBehaviour.NetworkBehaviourSyncVar>());
deserialize.Body.Variables.Add(oldNetId);
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, netIdField));
worker.Append(worker.Create(OpCodes.Stloc, oldNetId));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, netIdField);
worker.Emit(OpCodes.Stloc, oldNetId);
// GameObject/NetworkIdentity oldSyncVar = syncvar.getter;
VariableDefinition oldSyncVar = new VariableDefinition(syncVar.FieldType);
deserialize.Body.Variables.Add(oldSyncVar);
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, syncVar));
worker.Append(worker.Create(OpCodes.Stloc, oldSyncVar));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, syncVar);
worker.Emit(OpCodes.Stloc, oldSyncVar);
// read id and store in netId field BEFORE calling the hook
// -> this makes way more sense. by definition, the hook is
@ -676,13 +676,13 @@ void DeserializeNetworkBehaviourField(FieldDefinition syncVar, ILProcessor worke
// values BEFORE the hook even returned and hence BEFORE the
// actual value was even set.
// put 'this.' onto stack for 'this.netId' below
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Emit(OpCodes.Ldarg_0);
// reader. for 'reader.Read()' below
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Emit(OpCodes.Ldarg_1);
// Read()
worker.Append(worker.Create(OpCodes.Call, Readers.GetReadFunc(WeaverTypes.Import<NetworkBehaviour.NetworkBehaviourSyncVar>())));
worker.Emit(OpCodes.Call, Readers.GetReadFunc(WeaverTypes.Import<NetworkBehaviour.NetworkBehaviourSyncVar>()));
// netId
worker.Append(worker.Create(OpCodes.Stfld, netIdField));
worker.Emit(OpCodes.Stfld, netIdField);
if (hookMethod != null)
{
@ -708,17 +708,17 @@ void DeserializeNetworkBehaviourField(FieldDefinition syncVar, ILProcessor worke
Instruction syncVarEqualLabel = worker.Create(OpCodes.Nop);
// 'this.' for 'this.SyncVarEqual'
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Emit(OpCodes.Ldarg_0);
// 'oldNetId'
worker.Append(worker.Create(OpCodes.Ldloc, oldNetId));
worker.Emit(OpCodes.Ldloc, oldNetId);
// 'ref this.__netId'
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldflda, netIdField));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, netIdField);
// call the function
GenericInstanceMethod syncVarEqualGm = new GenericInstanceMethod(WeaverTypes.syncVarEqualReference);
syncVarEqualGm.GenericArguments.Add(netIdField.FieldType);
worker.Append(worker.Create(OpCodes.Call, syncVarEqualGm));
worker.Append(worker.Create(OpCodes.Brtrue, syncVarEqualLabel));
worker.Emit(OpCodes.Call, syncVarEqualGm);
worker.Emit(OpCodes.Brtrue, syncVarEqualLabel);
// call the hook
// Generates: OnValueChanged(oldValue, this.syncVar);
@ -942,17 +942,17 @@ public static bool ReadArguments(MethodDefinition method, ILProcessor worker, Re
return false;
}
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Append(worker.Create(OpCodes.Call, readFunc));
worker.Emit(OpCodes.Ldarg_1);
worker.Emit(OpCodes.Call, readFunc);
// conversion.. is this needed?
if (param.ParameterType.Is<float>())
{
worker.Append(worker.Create(OpCodes.Conv_R4));
worker.Emit(OpCodes.Conv_R4);
}
else if (param.ParameterType.Is<double>())
{
worker.Append(worker.Create(OpCodes.Conv_R8));
worker.Emit(OpCodes.Conv_R8);
}
}
return true;

View File

@ -165,7 +165,7 @@ public static void InitializeReaderAndWriters(AssemblyDefinition currentAssembly
Writers.InitializeWriters(worker);
Readers.InitializeReaders(worker);
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ret);
TypeDefinition generateClass = Weaver.WeaveLists.generateContainerClass;

View File

@ -21,15 +21,15 @@ public static MethodDefinition ProcessRpcInvoke(TypeDefinition td, MethodDefinit
NetworkBehaviourProcessor.WriteClientActiveCheck(worker, md.Name, label, "RPC");
// setup for reader
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Castclass, td));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Castclass, td);
if (!NetworkBehaviourProcessor.ReadArguments(md, worker, RemoteCallType.ClientRpc))
return null;
// invoke actual command function
worker.Append(worker.Create(OpCodes.Callvirt, rpcCallFunc));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Callvirt, rpcCallFunc);
worker.Emit(OpCodes.Ret);
NetworkBehaviourProcessor.AddInvokeParameters(rpc.Parameters);
td.Methods.Add(rpc);
@ -68,8 +68,8 @@ public static MethodDefinition ProcessRpcCall(TypeDefinition td, MethodDefinitio
if (Weaver.GenerateLogErrors)
{
worker.Append(worker.Create(OpCodes.Ldstr, "Call ClientRpc function " + md.Name));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.logErrorReference));
worker.Emit(OpCodes.Ldstr, "Call ClientRpc function " + md.Name);
worker.Emit(OpCodes.Call, WeaverTypes.logErrorReference);
}
NetworkBehaviourProcessor.WriteCreateWriter(worker);
@ -84,20 +84,20 @@ public static MethodDefinition ProcessRpcCall(TypeDefinition td, MethodDefinitio
// invoke SendInternal and return
// this
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldtoken, td));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldtoken, td);
// invokerClass
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.getTypeFromHandleReference));
worker.Append(worker.Create(OpCodes.Ldstr, rpcName));
worker.Emit(OpCodes.Call, WeaverTypes.getTypeFromHandleReference);
worker.Emit(OpCodes.Ldstr, rpcName);
// writer
worker.Append(worker.Create(OpCodes.Ldloc_0));
worker.Append(worker.Create(OpCodes.Ldc_I4, channel));
worker.Append(worker.Create(excludeOwner ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0));
worker.Append(worker.Create(OpCodes.Callvirt, WeaverTypes.sendRpcInternal));
worker.Emit(OpCodes.Ldloc_0);
worker.Emit(OpCodes.Ldc_I4, channel);
worker.Emit(excludeOwner ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
worker.Emit(OpCodes.Callvirt, WeaverTypes.sendRpcInternal);
NetworkBehaviourProcessor.WriteRecycleWriter(worker);
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ret);
return rpc;
}

View File

@ -37,11 +37,11 @@ public static bool ImplementsSyncObject(TypeReference typeRef)
*/
static void GenerateSyncObjectRegistration(ILProcessor worker, FieldDefinition fd)
{
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, fd));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, fd);
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.InitSyncObjectReference));
worker.Emit(OpCodes.Call, WeaverTypes.InitSyncObjectReference);
}
}
}

View File

@ -86,46 +86,46 @@ public static MethodDefinition GenerateSyncVarGetter(FieldDefinition fd, string
{
// return this.GetSyncVarGameObject(ref field, uint netId);
// this.
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, netFieldId));
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldflda, fd));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.getSyncVarGameObjectReference));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, netFieldId);
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, fd);
worker.Emit(OpCodes.Call, WeaverTypes.getSyncVarGameObjectReference);
worker.Emit(OpCodes.Ret);
}
// [SyncVar] NetworkIdentity?
else if (fd.FieldType.Is<NetworkIdentity>())
{
// return this.GetSyncVarNetworkIdentity(ref field, uint netId);
// this.
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, netFieldId));
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldflda, fd));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.getSyncVarNetworkIdentityReference));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, netFieldId);
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, fd);
worker.Emit(OpCodes.Call, WeaverTypes.getSyncVarNetworkIdentityReference);
worker.Emit(OpCodes.Ret);
}
else if (fd.FieldType.IsDerivedFrom<NetworkBehaviour>())
{
// return this.GetSyncVarNetworkBehaviour<T>(ref field, uint netId);
// this.
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, netFieldId));
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldflda, fd));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, netFieldId);
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, fd);
MethodReference getFunc = WeaverTypes.getSyncVarNetworkBehaviourReference.MakeGeneric(fd.FieldType);
worker.Append(worker.Create(OpCodes.Call, getFunc));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Call, getFunc);
worker.Emit(OpCodes.Ret);
}
// [SyncVar] int, string, etc.
else
{
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, fd));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, fd);
worker.Emit(OpCodes.Ret);
}
get.Body.Variables.Add(new VariableDefinition(fd.FieldType));
@ -149,94 +149,94 @@ public static MethodDefinition GenerateSyncVarSetter(TypeDefinition td, FieldDef
Instruction endOfMethod = worker.Create(OpCodes.Nop);
// this
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Emit(OpCodes.Ldarg_0);
// new value to set
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Emit(OpCodes.Ldarg_1);
// reference to field to set
// make generic version of SetSyncVar with field type
if (fd.FieldType.Is<UnityEngine.GameObject>())
{
// reference to netId Field to set
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, netFieldId));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, netFieldId);
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.syncVarGameObjectEqualReference));
worker.Emit(OpCodes.Call, WeaverTypes.syncVarGameObjectEqualReference);
}
else if (fd.FieldType.Is<NetworkIdentity>())
{
// reference to netId Field to set
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, netFieldId));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, netFieldId);
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.syncVarNetworkIdentityEqualReference));
worker.Emit(OpCodes.Call, WeaverTypes.syncVarNetworkIdentityEqualReference);
}
else if (fd.FieldType.IsDerivedFrom<NetworkBehaviour>())
{
// reference to netId Field to set
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, netFieldId));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, netFieldId);
MethodReference getFunc = WeaverTypes.syncVarNetworkBehaviourEqualReference.MakeGeneric(fd.FieldType);
worker.Append(worker.Create(OpCodes.Call, getFunc));
worker.Emit(OpCodes.Call, getFunc);
}
else
{
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldflda, fd));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, fd);
GenericInstanceMethod syncVarEqualGm = new GenericInstanceMethod(WeaverTypes.syncVarEqualReference);
syncVarEqualGm.GenericArguments.Add(fd.FieldType);
worker.Append(worker.Create(OpCodes.Call, syncVarEqualGm));
worker.Emit(OpCodes.Call, syncVarEqualGm);
}
worker.Append(worker.Create(OpCodes.Brtrue, endOfMethod));
worker.Emit(OpCodes.Brtrue, endOfMethod);
// T oldValue = value;
// TODO for GO/NI we need to backup the netId don't we?
VariableDefinition oldValue = new VariableDefinition(fd.FieldType);
set.Body.Variables.Add(oldValue);
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldfld, fd));
worker.Append(worker.Create(OpCodes.Stloc, oldValue));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldfld, fd);
worker.Emit(OpCodes.Stloc, oldValue);
// this
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Emit(OpCodes.Ldarg_0);
// new value to set
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Emit(OpCodes.Ldarg_1);
// reference to field to set
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldflda, fd));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, fd);
// dirty bit
// 8 byte integer aka long
worker.Append(worker.Create(OpCodes.Ldc_I8, dirtyBit));
worker.Emit(OpCodes.Ldc_I8, dirtyBit);
if (fd.FieldType.Is<UnityEngine.GameObject>())
{
// reference to netId Field to set
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldflda, netFieldId));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, netFieldId);
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.setSyncVarGameObjectReference));
worker.Emit(OpCodes.Call, WeaverTypes.setSyncVarGameObjectReference);
}
else if (fd.FieldType.Is<NetworkIdentity>())
{
// reference to netId Field to set
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldflda, netFieldId));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, netFieldId);
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.setSyncVarNetworkIdentityReference));
worker.Emit(OpCodes.Call, WeaverTypes.setSyncVarNetworkIdentityReference);
}
else if (fd.FieldType.IsDerivedFrom<NetworkBehaviour>())
{
// reference to netId Field to set
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldflda, netFieldId));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldflda, netFieldId);
MethodReference getFunc = WeaverTypes.setSyncVarNetworkBehaviourReference.MakeGeneric(fd.FieldType);
worker.Append(worker.Create(OpCodes.Call, getFunc));
worker.Emit(OpCodes.Call, getFunc);
}
else
{
@ -245,7 +245,7 @@ public static MethodDefinition GenerateSyncVarSetter(TypeDefinition td, FieldDef
gm.GenericArguments.Add(fd.FieldType);
// invoke SetSyncVar
worker.Append(worker.Create(OpCodes.Call, gm));
worker.Emit(OpCodes.Call, gm);
}
MethodDefinition hookMethod = GetHookMethod(td, fd);
@ -254,35 +254,35 @@ public static MethodDefinition GenerateSyncVarSetter(TypeDefinition td, FieldDef
{
//if (NetworkServer.localClientActive && !getSyncVarHookGuard(dirtyBit))
Instruction label = worker.Create(OpCodes.Nop);
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.NetworkServerGetLocalClientActive));
worker.Append(worker.Create(OpCodes.Brfalse, label));
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldc_I8, dirtyBit));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.getSyncVarHookGuard));
worker.Append(worker.Create(OpCodes.Brtrue, label));
worker.Emit(OpCodes.Call, WeaverTypes.NetworkServerGetLocalClientActive);
worker.Emit(OpCodes.Brfalse, label);
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldc_I8, dirtyBit);
worker.Emit(OpCodes.Call, WeaverTypes.getSyncVarHookGuard);
worker.Emit(OpCodes.Brtrue, label);
// setSyncVarHookGuard(dirtyBit, true);
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldc_I8, dirtyBit));
worker.Append(worker.Create(OpCodes.Ldc_I4_1));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.setSyncVarHookGuard));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldc_I8, dirtyBit);
worker.Emit(OpCodes.Ldc_I4_1);
worker.Emit(OpCodes.Call, WeaverTypes.setSyncVarHookGuard);
// call hook (oldValue, newValue)
// Generates: OnValueChanged(oldValue, value);
WriteCallHookMethodUsingArgument(worker, hookMethod, oldValue);
// setSyncVarHookGuard(dirtyBit, false);
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldc_I8, dirtyBit));
worker.Append(worker.Create(OpCodes.Ldc_I4_0));
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.setSyncVarHookGuard));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldc_I8, dirtyBit);
worker.Emit(OpCodes.Ldc_I4_0);
worker.Emit(OpCodes.Call, WeaverTypes.setSyncVarHookGuard);
worker.Append(label);
}
worker.Append(endOfMethod);
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ret);
set.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.In, fd.FieldType));
set.SemanticsAttributes = MethodSemanticsAttributes.Setter;
@ -429,7 +429,7 @@ static void WriteCallHookMethod(ILProcessor worker, MethodDefinition hookMethod,
void WriteOldValue()
{
worker.Append(worker.Create(OpCodes.Ldloc, oldValue));
worker.Emit(OpCodes.Ldloc, oldValue);
}
void WriteNewValue()
@ -437,14 +437,14 @@ void WriteNewValue()
// write arg1 or this.field
if (newValue == null)
{
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Emit(OpCodes.Ldarg_1);
}
else
{
// this.
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Emit(OpCodes.Ldarg_0);
// syncvar.get
worker.Append(worker.Create(OpCodes.Ldfld, newValue));
worker.Emit(OpCodes.Ldfld, newValue);
}
}
@ -456,7 +456,7 @@ void WriteStartFunctionCall()
{
// this before method call
// e.g. this.onValueChanged
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Emit(OpCodes.Ldarg_0);
}
}
@ -465,7 +465,7 @@ void WriteEndFunctionCall()
{
// only use Callvirt when not static
OpCode opcode = hookMethod.IsStatic ? OpCodes.Call : OpCodes.Callvirt;
worker.Append(worker.Create(opcode, hookMethod));
worker.Emit(opcode, hookMethod);
}
}
}

View File

@ -28,15 +28,15 @@ public static MethodDefinition ProcessTargetRpcInvoke(TypeDefinition td, MethodD
NetworkBehaviourProcessor.WriteClientActiveCheck(worker, md.Name, label, "TargetRPC");
// setup for reader
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Castclass, td));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Castclass, td);
// NetworkConnection parameter is optional
if (HasNetworkConnectionParameter(md))
{
// if call has NetworkConnection write clients connection as first arg
//ClientScene.readyconnection
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.ReadyConnectionReference));
worker.Emit(OpCodes.Call, WeaverTypes.ReadyConnectionReference);
}
// process reader parameters and skip first one if first one is NetworkConnection
@ -44,8 +44,8 @@ public static MethodDefinition ProcessTargetRpcInvoke(TypeDefinition td, MethodD
return null;
// invoke actual command function
worker.Append(worker.Create(OpCodes.Callvirt, rpcCallFunc));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Callvirt, rpcCallFunc);
worker.Emit(OpCodes.Ret);
NetworkBehaviourProcessor.AddInvokeParameters(rpc.Parameters);
td.Methods.Add(rpc);
@ -104,29 +104,29 @@ public static MethodDefinition ProcessTargetRpcCall(TypeDefinition td, MethodDef
// invoke SendInternal and return
// this
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Emit(OpCodes.Ldarg_0);
if (HasNetworkConnectionParameter(md))
{
// connection
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Emit(OpCodes.Ldarg_1);
}
else
{
// null
worker.Append(worker.Create(OpCodes.Ldnull));
worker.Emit(OpCodes.Ldnull);
}
worker.Append(worker.Create(OpCodes.Ldtoken, td));
worker.Emit(OpCodes.Ldtoken, td);
// invokerClass
worker.Append(worker.Create(OpCodes.Call, WeaverTypes.getTypeFromHandleReference));
worker.Append(worker.Create(OpCodes.Ldstr, rpcName));
worker.Emit(OpCodes.Call, WeaverTypes.getTypeFromHandleReference);
worker.Emit(OpCodes.Ldstr, rpcName);
// writer
worker.Append(worker.Create(OpCodes.Ldloc_0));
worker.Append(worker.Create(OpCodes.Ldc_I4, targetRpcAttr.GetField("channel", 0)));
worker.Append(worker.Create(OpCodes.Callvirt, WeaverTypes.sendTargetRpcInternal));
worker.Emit(OpCodes.Ldloc_0);
worker.Emit(OpCodes.Ldc_I4, targetRpcAttr.GetField("channel", 0));
worker.Emit(OpCodes.Callvirt, WeaverTypes.sendTargetRpcInternal);
NetworkBehaviourProcessor.WriteRecycleWriter(worker);
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ret);
return rpc;
}

View File

@ -157,13 +157,13 @@ static MethodDefinition GenerateEnumReadFunc(TypeReference variable)
ILProcessor worker = readerFunc.Body.GetILProcessor();
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Emit(OpCodes.Ldarg_0);
TypeReference underlyingType = variable.Resolve().GetEnumUnderlyingType();
MethodReference underlyingFunc = GetReadFunc(underlyingType);
worker.Append(worker.Create(OpCodes.Call, underlyingFunc));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Call, underlyingFunc);
worker.Emit(OpCodes.Ret);
return readerFunc;
}
@ -178,12 +178,12 @@ static MethodDefinition GenerateArraySegmentReadFunc(TypeReference variable)
// $array = reader.Read<[T]>()
ArrayType arrayType = elementType.MakeArrayType();
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Call, GetReadFunc(arrayType)));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Call, GetReadFunc(arrayType));
// return new ArraySegment<T>($array);
worker.Append(worker.Create(OpCodes.Newobj, WeaverTypes.ArraySegmentConstructorReference.MakeHostInstanceGeneric(genericInstance)));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Newobj, WeaverTypes.ArraySegmentConstructorReference.MakeHostInstanceGeneric(genericInstance));
worker.Emit(OpCodes.Ret);
return readerFunc;
}
@ -222,10 +222,10 @@ static MethodDefinition GenerateReadCollection(TypeReference variable, TypeRefer
// return reader.ReadList<T>();
ILProcessor worker = readerFunc.Body.GetILProcessor();
worker.Append(worker.Create(OpCodes.Ldarg_0)); // reader
worker.Append(worker.Create(OpCodes.Call, methodRef)); // Read
worker.Emit(OpCodes.Ldarg_0); // reader
worker.Emit(OpCodes.Call, methodRef); // Read
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ret);
return readerFunc;
}
@ -247,8 +247,8 @@ static MethodDefinition GenerateClassOrStructReadFunction(TypeReference variable
CreateNew(variable, worker, td);
ReadAllFields(variable, worker);
worker.Append(worker.Create(OpCodes.Ldloc_0));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ldloc_0);
worker.Emit(OpCodes.Ret);
return readerFunc;
}
@ -257,14 +257,14 @@ static void GenerateNullCheck(ILProcessor worker)
// if (!reader.ReadBoolean()) {
// return null;
// }
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Call, GetReadFunc(WeaverTypes.Import<bool>())));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Call, GetReadFunc(WeaverTypes.Import<bool>()));
Instruction labelEmptyArray = worker.Create(OpCodes.Nop);
worker.Append(worker.Create(OpCodes.Brtrue, labelEmptyArray));
worker.Emit(OpCodes.Brtrue, labelEmptyArray);
// return null
worker.Append(worker.Create(OpCodes.Ldnull));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ldnull);
worker.Emit(OpCodes.Ret);
worker.Append(labelEmptyArray);
}
@ -274,15 +274,15 @@ static void CreateNew(TypeReference variable, ILProcessor worker, TypeDefinition
if (variable.IsValueType)
{
// structs are created with Initobj
worker.Append(worker.Create(OpCodes.Ldloca, 0));
worker.Append(worker.Create(OpCodes.Initobj, variable));
worker.Emit(OpCodes.Ldloca, 0);
worker.Emit(OpCodes.Initobj, variable);
}
else if (td.IsDerivedFrom<UnityEngine.ScriptableObject>())
{
GenericInstanceMethod genericInstanceMethod = new GenericInstanceMethod(WeaverTypes.ScriptableObjectCreateInstanceMethod);
genericInstanceMethod.GenericArguments.Add(variable);
worker.Append(worker.Create(OpCodes.Call, genericInstanceMethod));
worker.Append(worker.Create(OpCodes.Stloc_0));
worker.Emit(OpCodes.Call, genericInstanceMethod);
worker.Emit(OpCodes.Stloc_0);
}
else
{
@ -296,8 +296,8 @@ static void CreateNew(TypeReference variable, ILProcessor worker, TypeDefinition
MethodReference ctorRef = Weaver.CurrentAssembly.MainModule.ImportReference(ctor);
worker.Append(worker.Create(OpCodes.Newobj, ctorRef));
worker.Append(worker.Create(OpCodes.Stloc_0));
worker.Emit(OpCodes.Newobj, ctorRef);
worker.Emit(OpCodes.Stloc_0);
}
}
@ -307,12 +307,12 @@ static void ReadAllFields(TypeReference variable, ILProcessor worker)
{
// mismatched ldloca/ldloc for struct/class combinations is invalid IL, which causes crash at runtime
OpCode opcode = variable.IsValueType ? OpCodes.Ldloca : OpCodes.Ldloc;
worker.Append(worker.Create(opcode, 0));
worker.Emit(opcode, 0);
MethodReference readFunc = GetReadFunc(field.FieldType);
if (readFunc != null)
{
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Call, readFunc));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Call, readFunc);
}
else
{
@ -320,7 +320,7 @@ static void ReadAllFields(TypeReference variable, ILProcessor worker)
}
FieldReference fieldRef = Weaver.CurrentAssembly.MainModule.ImportReference(field);
worker.Append(worker.Create(OpCodes.Stfld, fieldRef));
worker.Emit(OpCodes.Stfld, fieldRef);
}
}
@ -346,16 +346,16 @@ internal static void InitializeReaders(ILProcessor worker)
MethodReference readFunc = kvp.Value;
// create a Func<NetworkReader, T> delegate
worker.Append(worker.Create(OpCodes.Ldnull));
worker.Append(worker.Create(OpCodes.Ldftn, readFunc));
worker.Emit(OpCodes.Ldnull);
worker.Emit(OpCodes.Ldftn, readFunc);
GenericInstanceType funcGenericInstance = funcRef.MakeGenericInstanceType(networkReaderRef, targetType);
MethodReference funcConstructorInstance = funcConstructorRef.MakeHostInstanceGeneric(funcGenericInstance);
worker.Append(worker.Create(OpCodes.Newobj, funcConstructorInstance));
worker.Emit(OpCodes.Newobj, funcConstructorInstance);
// save it in Reader<T>.read
GenericInstanceType genericInstance = genericReaderClassRef.MakeGenericInstanceType(targetType);
FieldReference specializedField = fieldRef.SpecializeField(genericInstance);
worker.Append(worker.Create(OpCodes.Stsfld, specializedField));
worker.Emit(OpCodes.Stsfld, specializedField);
}
}

View File

@ -171,11 +171,11 @@ static MethodDefinition GenerateEnumWriteFunc(TypeReference variable)
MethodReference underlyingWriter = GetWriteFunc(variable.Resolve().GetEnumUnderlyingType());
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Append(worker.Create(OpCodes.Call, underlyingWriter));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldarg_1);
worker.Emit(OpCodes.Call, underlyingWriter);
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ret);
return writerFunc;
}
@ -209,7 +209,7 @@ static MethodDefinition GenerateClassOrStructWriterFunction(TypeReference variab
if (!WriteAllFields(variable, worker))
return null;
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ret);
return writerFunc;
}
@ -223,18 +223,18 @@ static void WriteNullCheck(ILProcessor worker)
//
Instruction labelNotNull = worker.Create(OpCodes.Nop);
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Append(worker.Create(OpCodes.Brtrue, labelNotNull));
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldc_I4_0));
worker.Append(worker.Create(OpCodes.Call, GetWriteFunc(WeaverTypes.Import<bool>())));
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ldarg_1);
worker.Emit(OpCodes.Brtrue, labelNotNull);
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldc_I4_0);
worker.Emit(OpCodes.Call, GetWriteFunc(WeaverTypes.Import<bool>()));
worker.Emit(OpCodes.Ret);
worker.Append(labelNotNull);
// write.WriteBoolean(true);
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldc_I4_1));
worker.Append(worker.Create(OpCodes.Call, GetWriteFunc(WeaverTypes.Import<bool>())));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldc_I4_1);
worker.Emit(OpCodes.Call, GetWriteFunc(WeaverTypes.Import<bool>()));
}
/// <summary>
@ -255,10 +255,10 @@ static bool WriteAllFields(TypeReference variable, ILProcessor worker)
FieldReference fieldRef = Weaver.CurrentAssembly.MainModule.ImportReference(field);
fields++;
worker.Append(worker.Create(OpCodes.Ldarg_0));
worker.Append(worker.Create(OpCodes.Ldarg_1));
worker.Append(worker.Create(OpCodes.Ldfld, fieldRef));
worker.Append(worker.Create(OpCodes.Call, writeFunc));
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Ldarg_1);
worker.Emit(OpCodes.Ldfld, fieldRef);
worker.Emit(OpCodes.Call, writeFunc);
}
return true;
@ -290,12 +290,12 @@ static MethodDefinition GenerateCollectionWriter(TypeReference variable, TypeRef
// reader.WriteArray<T>(array);
ILProcessor worker = writerFunc.Body.GetILProcessor();
worker.Append(worker.Create(OpCodes.Ldarg_0)); // writer
worker.Append(worker.Create(OpCodes.Ldarg_1)); // collection
worker.Emit(OpCodes.Ldarg_0); // writer
worker.Emit(OpCodes.Ldarg_1); // collection
worker.Append(worker.Create(OpCodes.Call, methodRef)); // WriteArray
worker.Emit(OpCodes.Call, methodRef); // WriteArray
worker.Append(worker.Create(OpCodes.Ret));
worker.Emit(OpCodes.Ret);
return writerFunc;
}
@ -322,16 +322,16 @@ internal static void InitializeWriters(ILProcessor worker)
MethodReference writeFunc = kvp.Value;
// create a Action<NetworkWriter, T> delegate
worker.Append(worker.Create(OpCodes.Ldnull));
worker.Append(worker.Create(OpCodes.Ldftn, writeFunc));
worker.Emit(OpCodes.Ldnull);
worker.Emit(OpCodes.Ldftn, writeFunc);
GenericInstanceType actionGenericInstance = actionRef.MakeGenericInstanceType(networkWriterRef, targetType);
MethodReference actionRefInstance = actionConstructorRef.MakeHostInstanceGeneric(actionGenericInstance);
worker.Append(worker.Create(OpCodes.Newobj, actionRefInstance));
worker.Emit(OpCodes.Newobj, actionRefInstance);
// save it in Writer<T>.write
GenericInstanceType genericInstance = genericWriterClassRef.MakeGenericInstanceType(targetType);
FieldReference specializedField = fieldRef.SpecializeField(genericInstance);
worker.Append(worker.Create(OpCodes.Stsfld, specializedField));
worker.Emit(OpCodes.Stsfld, specializedField);
}
}