Weaver: NetworkBehaviourProcessor.InjectIntoConstructor split into cctor & ctor functions

This commit is contained in:
vis2k 2021-09-28 15:38:06 +08:00
parent d7516a8c95
commit 74b9c8034e

View File

@ -91,8 +91,9 @@ public bool Process(ref bool WeavingFailed)
return true; return true;
} }
// inject initializations into constructor // inject initializations into static & instance constructor
InjectIntoConstructor(ref WeavingFailed); InjectIntoStaticConstructor(ref WeavingFailed);
InjectIntoInstanceConstructor(ref WeavingFailed);
GenerateSerialization(ref WeavingFailed); GenerateSerialization(ref WeavingFailed);
if (WeavingFailed) if (WeavingFailed)
@ -253,11 +254,10 @@ static bool RemoveFinalRetInstruction(MethodDefinition method)
return true; return true;
} }
// we need to inject several initializations into NetworkBehaviour // we need to inject several initializations into NetworkBehaviour cctor
// static and regular constructors void InjectIntoStaticConstructor(ref bool WeavingFailed)
void InjectIntoConstructor(ref bool WeavingFailed)
{ {
if (commands.Count == 0 && clientRpcs.Count == 0 && targetRpcs.Count == 0 && syncObjects.Count == 0) if (commands.Count == 0 && clientRpcs.Count == 0 && targetRpcs.Count == 0)
return; return;
// find static constructor // find static constructor
@ -284,26 +284,6 @@ void InjectIntoConstructor(ref bool WeavingFailed)
weaverTypes.Import(typeof(void))); weaverTypes.Import(typeof(void)));
} }
// find instance constructor
MethodDefinition ctor = netBehaviourSubclass.GetMethod(".ctor");
if (ctor == null)
{
Log.Error($"{netBehaviourSubclass.Name} has invalid constructor", netBehaviourSubclass);
WeavingFailed = true;
return;
}
// remove the return opcode from end of function. will add our own later.
if (!RemoveFinalRetInstruction(ctor))
{
Log.Error($"{netBehaviourSubclass.Name} has invalid constructor", ctor);
WeavingFailed = true;
return;
}
// TODO: find out if the order below matters. If it doesn't split code below into 2 functions
ILProcessor ctorWorker = ctor.Body.GetILProcessor();
ILProcessor cctorWorker = cctor.Body.GetILProcessor(); ILProcessor cctorWorker = cctor.Body.GetILProcessor();
// register all commands in cctor // register all commands in cctor
@ -326,12 +306,6 @@ void InjectIntoConstructor(ref bool WeavingFailed)
GenerateRegisterRemoteDelegate(cctorWorker, weaverTypes, weaverTypes.registerRpcDelegateReference, targetRpcInvocationFuncs[i], targetRpcs[i].Name); GenerateRegisterRemoteDelegate(cctorWorker, weaverTypes, weaverTypes.registerRpcDelegateReference, targetRpcInvocationFuncs[i], targetRpcs[i].Name);
} }
// initialize all sync objects in ctor
foreach (FieldDefinition fd in syncObjects)
{
SyncObjectInitializer.GenerateSyncObjectInitializer(ctorWorker, weaverTypes, fd);
}
// add final 'Ret' instruction to cctor // add final 'Ret' instruction to cctor
cctorWorker.Append(cctorWorker.Create(OpCodes.Ret)); cctorWorker.Append(cctorWorker.Create(OpCodes.Ret));
if (!cctorFound) if (!cctorFound)
@ -339,13 +313,45 @@ void InjectIntoConstructor(ref bool WeavingFailed)
netBehaviourSubclass.Methods.Add(cctor); netBehaviourSubclass.Methods.Add(cctor);
} }
// add final 'Ret' instruction to ctor
ctorWorker.Append(ctorWorker.Create(OpCodes.Ret));
// in case class had no cctor, it might have BeforeFieldInit, so injected cctor would be called too late // in case class had no cctor, it might have BeforeFieldInit, so injected cctor would be called too late
netBehaviourSubclass.Attributes &= ~TypeAttributes.BeforeFieldInit; netBehaviourSubclass.Attributes &= ~TypeAttributes.BeforeFieldInit;
} }
// we need to inject several initializations into NetworkBehaviour ctor
void InjectIntoInstanceConstructor(ref bool WeavingFailed)
{
if (syncObjects.Count == 0)
return;
// find instance constructor
MethodDefinition ctor = netBehaviourSubclass.GetMethod(".ctor");
if (ctor == null)
{
Log.Error($"{netBehaviourSubclass.Name} has invalid constructor", netBehaviourSubclass);
WeavingFailed = true;
return;
}
// remove the return opcode from end of function. will add our own later.
if (!RemoveFinalRetInstruction(ctor))
{
Log.Error($"{netBehaviourSubclass.Name} has invalid constructor", ctor);
WeavingFailed = true;
return;
}
ILProcessor ctorWorker = ctor.Body.GetILProcessor();
// initialize all sync objects in ctor
foreach (FieldDefinition fd in syncObjects)
{
SyncObjectInitializer.GenerateSyncObjectInitializer(ctorWorker, weaverTypes, fd);
}
// add final 'Ret' instruction to ctor
ctorWorker.Append(ctorWorker.Create(OpCodes.Ret));
}
/* /*
// This generates code like: // This generates code like:
NetworkBehaviour.RegisterCommandDelegate(base.GetType(), "CmdThrust", new NetworkBehaviour.CmdDelegate(ShipControl.InvokeCmdCmdThrust)); NetworkBehaviour.RegisterCommandDelegate(base.GetType(), "CmdThrust", new NetworkBehaviour.CmdDelegate(ShipControl.InvokeCmdCmdThrust));