Readers: remove static WeavingFailed references

This commit is contained in:
vis2k 2021-08-20 21:25:56 +08:00
parent c358358f1d
commit 2a1929f7f1
8 changed files with 62 additions and 62 deletions

View File

@ -79,7 +79,7 @@ protected static void InvokeCmdCmdThrust(NetworkBehaviour obj, NetworkReader rea
((ShipControl)obj).CmdThrust(reader.ReadSingle(), (int)reader.ReadPackedUInt32());
}
*/
public static MethodDefinition ProcessCommandInvoke(WeaverTypes weaverTypes, Readers readers, Logger Log, TypeDefinition td, MethodDefinition method, MethodDefinition cmdCallFunc)
public static MethodDefinition ProcessCommandInvoke(WeaverTypes weaverTypes, Readers readers, Logger Log, TypeDefinition td, MethodDefinition method, MethodDefinition cmdCallFunc, ref bool WeavingFailed)
{
MethodDefinition cmd = new MethodDefinition(Weaver.InvokeRpcPrefix + method.Name,
MethodAttributes.Family | MethodAttributes.Static | MethodAttributes.HideBySig,
@ -94,7 +94,7 @@ public static MethodDefinition ProcessCommandInvoke(WeaverTypes weaverTypes, Rea
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Castclass, td);
if (!NetworkBehaviourProcessor.ReadArguments(method, readers, Log, worker, RemoteCallType.Command))
if (!NetworkBehaviourProcessor.ReadArguments(method, readers, Log, worker, RemoteCallType.Command, ref WeavingFailed))
return null;
AddSenderConnection(method, worker);

View File

@ -576,7 +576,7 @@ void DeserializeNetworkIdentityField(WeaverTypes weaverTypes, FieldDefinition sy
// reader. for 'reader.Read()' below
worker.Emit(OpCodes.Ldarg_1);
// Read()
worker.Emit(OpCodes.Call, readers.GetReadFunc(weaverTypes.Import<uint>()));
worker.Emit(OpCodes.Call, readers.GetReadFunc(weaverTypes.Import<uint>(), ref WeavingFailed));
// netId
worker.Emit(OpCodes.Stfld, netIdField);
@ -677,7 +677,7 @@ void DeserializeNetworkBehaviourField(WeaverTypes weaverTypes, FieldDefinition s
// reader. for 'reader.Read()' below
worker.Emit(OpCodes.Ldarg_1);
// Read()
worker.Emit(OpCodes.Call, readers.GetReadFunc(weaverTypes.Import<NetworkBehaviour.NetworkBehaviourSyncVar>()));
worker.Emit(OpCodes.Call, readers.GetReadFunc(weaverTypes.Import<NetworkBehaviour.NetworkBehaviourSyncVar>(), ref WeavingFailed));
// netId
worker.Emit(OpCodes.Stfld, netIdField);
@ -741,7 +741,7 @@ void DeserializeNormalField(WeaverTypes weaverTypes, FieldDefinition syncVar, IL
}
*/
MethodReference readFunc = readers.GetReadFunc(syncVar.FieldType);
MethodReference readFunc = readers.GetReadFunc(syncVar.FieldType, ref WeavingFailed);
if (readFunc == null)
{
Log.Error($"{syncVar.Name} has unsupported type. Use a supported Mirror type instead", syncVar);
@ -861,7 +861,7 @@ void GenerateDeSerialization(ref bool WeavingFailed)
// get dirty bits
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
serWorker.Append(serWorker.Create(OpCodes.Call, readers.GetReadFunc(weaverTypes.Import<ulong>())));
serWorker.Append(serWorker.Create(OpCodes.Call, readers.GetReadFunc(weaverTypes.Import<ulong>(), ref WeavingFailed)));
serWorker.Append(serWorker.Create(OpCodes.Stloc_0));
// conditionally read each syncvar
@ -891,7 +891,7 @@ void GenerateDeSerialization(ref bool WeavingFailed)
netBehaviourSubclass.Methods.Add(serialize);
}
public static bool ReadArguments(MethodDefinition method, Readers readers, Logger Log, ILProcessor worker, RemoteCallType callType)
public static bool ReadArguments(MethodDefinition method, Readers readers, Logger Log, ILProcessor worker, RemoteCallType callType, ref bool WeavingFailed)
{
// read each argument
// example result
@ -921,7 +921,7 @@ public static bool ReadArguments(MethodDefinition method, Readers readers, Logge
}
MethodReference readFunc = readers.GetReadFunc(param.ParameterType);
MethodReference readFunc = readers.GetReadFunc(param.ParameterType, ref WeavingFailed);
if (readFunc == null)
{
@ -1125,7 +1125,7 @@ void ProcessClientRpc(HashSet<string> names, MethodDefinition md, CustomAttribut
// need null check here because ProcessRpcCall returns null if it can't write all the args
if (rpcCallFunc == null) { return; }
MethodDefinition rpcFunc = RpcProcessor.ProcessRpcInvoke(weaverTypes, writers, readers, Log, netBehaviourSubclass, md, rpcCallFunc);
MethodDefinition rpcFunc = RpcProcessor.ProcessRpcInvoke(weaverTypes, writers, readers, Log, netBehaviourSubclass, md, rpcCallFunc, ref WeavingFailed);
if (rpcFunc != null)
{
clientRpcInvocationFuncs.Add(rpcFunc);
@ -1155,7 +1155,7 @@ void ProcessTargetRpc(HashSet<string> names, MethodDefinition md, CustomAttribut
MethodDefinition rpcCallFunc = TargetRpcProcessor.ProcessTargetRpcCall(weaverTypes, writers, Log, netBehaviourSubclass, md, targetRpcAttr, ref WeavingFailed);
MethodDefinition rpcFunc = TargetRpcProcessor.ProcessTargetRpcInvoke(weaverTypes, readers, Log, netBehaviourSubclass, md, rpcCallFunc);
MethodDefinition rpcFunc = TargetRpcProcessor.ProcessTargetRpcInvoke(weaverTypes, readers, Log, netBehaviourSubclass, md, rpcCallFunc, ref WeavingFailed);
if (rpcFunc != null)
{
targetRpcInvocationFuncs.Add(rpcFunc);
@ -1192,7 +1192,7 @@ void ProcessCommand(HashSet<string> names, MethodDefinition md, CustomAttribute
MethodDefinition cmdCallFunc = CommandProcessor.ProcessCommandCall(weaverTypes, writers, Log, netBehaviourSubclass, md, commandAttr, ref WeavingFailed);
MethodDefinition cmdFunc = CommandProcessor.ProcessCommandInvoke(weaverTypes, readers, Log, netBehaviourSubclass, md, cmdCallFunc);
MethodDefinition cmdFunc = CommandProcessor.ProcessCommandInvoke(weaverTypes, readers, Log, netBehaviourSubclass, md, cmdCallFunc, ref WeavingFailed);
if (cmdFunc != null)
{
commandInvocationFuncs.Add(cmdFunc);

View File

@ -11,7 +11,7 @@ namespace Mirror.Weaver
{
public static class ReaderWriterProcessor
{
public static bool Process(AssemblyDefinition CurrentAssembly, Writers writers, Readers readers)
public static bool Process(AssemblyDefinition CurrentAssembly, Writers writers, Readers readers, ref bool WeavingFailed)
{
foreach (Assembly unityAsm in CompilationPipeline.GetAssemblies())
{
@ -20,15 +20,15 @@ public static bool Process(AssemblyDefinition CurrentAssembly, Writers writers,
using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver())
using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(unityAsm.outputPath, new ReaderParameters { ReadWrite = false, ReadSymbols = false, AssemblyResolver = asmResolver }))
{
ProcessAssemblyClasses(CurrentAssembly, assembly, writers, readers);
ProcessAssemblyClasses(CurrentAssembly, assembly, writers, readers, ref WeavingFailed);
}
}
}
return ProcessAssemblyClasses(CurrentAssembly, CurrentAssembly, writers, readers);
return ProcessAssemblyClasses(CurrentAssembly, CurrentAssembly, writers, readers, ref WeavingFailed);
}
static bool ProcessAssemblyClasses(AssemblyDefinition CurrentAssembly, AssemblyDefinition assembly, Writers writers, Readers readers)
static bool ProcessAssemblyClasses(AssemblyDefinition CurrentAssembly, AssemblyDefinition assembly, Writers writers, Readers readers, ref bool WeavingFailed)
{
bool modified = false;
foreach (TypeDefinition klass in assembly.MainModule.Types)
@ -46,24 +46,24 @@ static bool ProcessAssemblyClasses(AssemblyDefinition CurrentAssembly, AssemblyD
foreach (TypeDefinition klass in assembly.MainModule.Types)
{
// if assembly has any network message then it is modified
modified |= LoadMessageReadWriter(CurrentAssembly.MainModule, writers, readers, klass);
modified |= LoadMessageReadWriter(CurrentAssembly.MainModule, writers, readers, klass, ref WeavingFailed);
}
return modified;
}
static bool LoadMessageReadWriter(ModuleDefinition module, Writers writers, Readers readers, TypeDefinition klass)
static bool LoadMessageReadWriter(ModuleDefinition module, Writers writers, Readers readers, TypeDefinition klass, ref bool WeavingFailed)
{
bool modified = false;
if (!klass.IsAbstract && !klass.IsInterface && klass.ImplementsInterface<NetworkMessage>())
{
readers.GetReadFunc(module.ImportReference(klass));
readers.GetReadFunc(module.ImportReference(klass), ref WeavingFailed);
writers.GetWriteFunc(module.ImportReference(klass));
modified = true;
}
foreach (TypeDefinition td in klass.NestedTypes)
{
modified |= LoadMessageReadWriter(module, writers, readers, td);
modified |= LoadMessageReadWriter(module, writers, readers, td, ref WeavingFailed);
}
return modified;
}

View File

@ -6,7 +6,7 @@ namespace Mirror.Weaver
// Processes [Rpc] methods in NetworkBehaviour
public static class RpcProcessor
{
public static MethodDefinition ProcessRpcInvoke(WeaverTypes weaverTypes, Writers writers, Readers readers, Logger Log, TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc)
public static MethodDefinition ProcessRpcInvoke(WeaverTypes weaverTypes, Writers writers, Readers readers, Logger Log, TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc, ref bool WeavingFailed)
{
MethodDefinition rpc = new MethodDefinition(
Weaver.InvokeRpcPrefix + md.Name,
@ -22,7 +22,7 @@ public static MethodDefinition ProcessRpcInvoke(WeaverTypes weaverTypes, Writers
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Castclass, td);
if (!NetworkBehaviourProcessor.ReadArguments(md, readers, Log, worker, RemoteCallType.ClientRpc))
if (!NetworkBehaviourProcessor.ReadArguments(md, readers, Log, worker, RemoteCallType.ClientRpc, ref WeavingFailed))
return null;
// invoke actual command function

View File

@ -22,7 +22,7 @@ public static List<FieldDefinition> FindSyncObjectsFields(Writers writers, Reade
continue;
}
GenerateReadersAndWriters(writers, readers, fd.FieldType);
GenerateReadersAndWriters(writers, readers, fd.FieldType, ref WeavingFailed);
syncObjects.Add(fd);
}
@ -33,7 +33,7 @@ public static List<FieldDefinition> FindSyncObjectsFields(Writers writers, Reade
}
// Generates serialization methods for synclists
static void GenerateReadersAndWriters(Writers writers, Readers readers, TypeReference tr)
static void GenerateReadersAndWriters(Writers writers, Readers readers, TypeReference tr, ref bool WeavingFailed)
{
if (tr is GenericInstanceType genericInstance)
{
@ -41,7 +41,7 @@ static void GenerateReadersAndWriters(Writers writers, Readers readers, TypeRefe
{
if (!argument.IsGenericParameter)
{
readers.GetReadFunc(argument);
readers.GetReadFunc(argument, ref WeavingFailed);
writers.GetWriteFunc(argument);
}
}
@ -49,7 +49,7 @@ static void GenerateReadersAndWriters(Writers writers, Readers readers, TypeRefe
if (tr != null)
{
GenerateReadersAndWriters(writers, readers, tr.Resolve().BaseType);
GenerateReadersAndWriters(writers, readers, tr.Resolve().BaseType, ref WeavingFailed);
}
}
}

View File

@ -13,7 +13,7 @@ public static bool HasNetworkConnectionParameter(MethodDefinition md)
md.Parameters[0].ParameterType.Is<NetworkConnection>();
}
public static MethodDefinition ProcessTargetRpcInvoke(WeaverTypes weaverTypes, Readers readers, Logger Log, TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc)
public static MethodDefinition ProcessTargetRpcInvoke(WeaverTypes weaverTypes, Readers readers, Logger Log, TypeDefinition td, MethodDefinition md, MethodDefinition rpcCallFunc, ref bool WeavingFailed)
{
MethodDefinition rpc = new MethodDefinition(Weaver.InvokeRpcPrefix + md.Name, MethodAttributes.Family |
MethodAttributes.Static |
@ -45,7 +45,7 @@ public static MethodDefinition ProcessTargetRpcInvoke(WeaverTypes weaverTypes, R
}
// process reader parameters and skip first one if first one is NetworkConnection
if (!NetworkBehaviourProcessor.ReadArguments(md, readers, Log, worker, RemoteCallType.TargetRpc))
if (!NetworkBehaviourProcessor.ReadArguments(md, readers, Log, worker, RemoteCallType.TargetRpc, ref WeavingFailed))
return null;
// invoke actual command function

View File

@ -49,7 +49,7 @@ void RegisterReadFunc(TypeReference typeReference, MethodDefinition newReaderFun
}
// Finds existing reader for type, if non exists trys to create one
public MethodReference GetReadFunc(TypeReference variable)
public MethodReference GetReadFunc(TypeReference variable, ref bool WeavingFailed)
{
if (readFuncs.TryGetValue(variable, out MethodReference foundFunc))
{
@ -58,11 +58,11 @@ public MethodReference GetReadFunc(TypeReference variable)
else
{
TypeReference importedVariable = assembly.MainModule.ImportReference(variable);
return GenerateReader(importedVariable);
return GenerateReader(importedVariable, ref WeavingFailed);
}
}
MethodReference GenerateReader(TypeReference variableReference)
MethodReference GenerateReader(TypeReference variableReference, ref bool WeavingFailed)
{
// Arrays are special, if we resolve them, we get the element type,
// so the following ifs might choke on it for scriptable objects
@ -73,11 +73,11 @@ MethodReference GenerateReader(TypeReference variableReference)
if (variableReference.IsMultidimensionalArray())
{
Log.Error($"{variableReference.Name} is an unsupported type. Multidimensional arrays are not supported", variableReference);
Weaver.WeavingFailed = true;
WeavingFailed = true;
return null;
}
return GenerateReadCollection(variableReference, variableReference.GetElementType(), nameof(NetworkReaderExtensions.ReadArray));
return GenerateReadCollection(variableReference, variableReference.GetElementType(), nameof(NetworkReaderExtensions.ReadArray), ref WeavingFailed);
}
TypeDefinition variableDefinition = variableReference.Resolve();
@ -86,32 +86,32 @@ MethodReference GenerateReader(TypeReference variableReference)
if (variableDefinition == null)
{
Log.Error($"{variableReference.Name} is not a supported type", variableReference);
Weaver.WeavingFailed = true;
WeavingFailed = true;
return null;
}
else if (variableReference.IsByReference)
{
// error??
Log.Error($"Cannot pass type {variableReference.Name} by reference", variableReference);
Weaver.WeavingFailed = true;
WeavingFailed = true;
return null;
}
// use existing func for known types
if (variableDefinition.IsEnum)
{
return GenerateEnumReadFunc(variableReference);
return GenerateEnumReadFunc(variableReference, ref WeavingFailed);
}
else if (variableDefinition.Is(typeof(ArraySegment<>)))
{
return GenerateArraySegmentReadFunc(variableReference);
return GenerateArraySegmentReadFunc(variableReference, ref WeavingFailed);
}
else if (variableDefinition.Is(typeof(List<>)))
{
GenericInstanceType genericInstance = (GenericInstanceType)variableReference;
TypeReference elementType = genericInstance.GenericArguments[0];
return GenerateReadCollection(variableReference, elementType, nameof(NetworkReaderExtensions.ReadList));
return GenerateReadCollection(variableReference, elementType, nameof(NetworkReaderExtensions.ReadList), ref WeavingFailed);
}
else if (variableReference.IsDerivedFrom<NetworkBehaviour>())
{
@ -122,41 +122,41 @@ MethodReference GenerateReader(TypeReference variableReference)
if (variableDefinition.IsDerivedFrom<UnityEngine.Component>())
{
Log.Error($"Cannot generate reader for component type {variableReference.Name}. Use a supported type or provide a custom reader", variableReference);
Weaver.WeavingFailed = true;
WeavingFailed = true;
return null;
}
if (variableReference.Is<UnityEngine.Object>())
{
Log.Error($"Cannot generate reader for {variableReference.Name}. Use a supported type or provide a custom reader", variableReference);
Weaver.WeavingFailed = true;
WeavingFailed = true;
return null;
}
if (variableReference.Is<UnityEngine.ScriptableObject>())
{
Log.Error($"Cannot generate reader for {variableReference.Name}. Use a supported type or provide a custom reader", variableReference);
Weaver.WeavingFailed = true;
WeavingFailed = true;
return null;
}
if (variableDefinition.HasGenericParameters)
{
Log.Error($"Cannot generate reader for generic variable {variableReference.Name}. Use a supported type or provide a custom reader", variableReference);
Weaver.WeavingFailed = true;
WeavingFailed = true;
return null;
}
if (variableDefinition.IsInterface)
{
Log.Error($"Cannot generate reader for interface {variableReference.Name}. Use a supported type or provide a custom reader", variableReference);
Weaver.WeavingFailed = true;
WeavingFailed = true;
return null;
}
if (variableDefinition.IsAbstract)
{
Log.Error($"Cannot generate reader for abstract class {variableReference.Name}. Use a supported type or provide a custom reader", variableReference);
Weaver.WeavingFailed = true;
WeavingFailed = true;
return null;
}
return GenerateClassOrStructReadFunction(variableReference);
return GenerateClassOrStructReadFunction(variableReference, ref WeavingFailed);
}
MethodReference GetNetworkBehaviourReader(TypeReference variableReference)
@ -173,7 +173,7 @@ MethodReference GetNetworkBehaviourReader(TypeReference variableReference)
return readFunc;
}
MethodDefinition GenerateEnumReadFunc(TypeReference variable)
MethodDefinition GenerateEnumReadFunc(TypeReference variable, ref bool WeavingFailed)
{
MethodDefinition readerFunc = GenerateReaderFunction(variable);
@ -182,14 +182,14 @@ MethodDefinition GenerateEnumReadFunc(TypeReference variable)
worker.Emit(OpCodes.Ldarg_0);
TypeReference underlyingType = variable.Resolve().GetEnumUnderlyingType();
MethodReference underlyingFunc = GetReadFunc(underlyingType);
MethodReference underlyingFunc = GetReadFunc(underlyingType, ref WeavingFailed);
worker.Emit(OpCodes.Call, underlyingFunc);
worker.Emit(OpCodes.Ret);
return readerFunc;
}
MethodDefinition GenerateArraySegmentReadFunc(TypeReference variable)
MethodDefinition GenerateArraySegmentReadFunc(TypeReference variable, ref bool WeavingFailed)
{
GenericInstanceType genericInstance = (GenericInstanceType)variable;
TypeReference elementType = genericInstance.GenericArguments[0];
@ -201,7 +201,7 @@ MethodDefinition GenerateArraySegmentReadFunc(TypeReference variable)
// $array = reader.Read<[T]>()
ArrayType arrayType = elementType.MakeArrayType();
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Call, GetReadFunc(arrayType));
worker.Emit(OpCodes.Call, GetReadFunc(arrayType, ref WeavingFailed));
// return new ArraySegment<T>($array);
worker.Emit(OpCodes.Newobj, weaverTypes.ArraySegmentConstructorReference.MakeHostInstanceGeneric(assembly.MainModule, genericInstance));
@ -227,11 +227,11 @@ MethodDefinition GenerateReaderFunction(TypeReference variable)
return readerFunc;
}
MethodDefinition GenerateReadCollection(TypeReference variable, TypeReference elementType, string readerFunction)
MethodDefinition GenerateReadCollection(TypeReference variable, TypeReference elementType, string readerFunction, ref bool WeavingFailed)
{
MethodDefinition readerFunc = GenerateReaderFunction(variable);
// generate readers for the element
GetReadFunc(elementType);
GetReadFunc(elementType, ref WeavingFailed);
ModuleDefinition module = assembly.MainModule;
TypeReference readerExtensions = module.ImportReference(typeof(NetworkReaderExtensions));
@ -252,7 +252,7 @@ MethodDefinition GenerateReadCollection(TypeReference variable, TypeReference el
return readerFunc;
}
MethodDefinition GenerateClassOrStructReadFunction(TypeReference variable)
MethodDefinition GenerateClassOrStructReadFunction(TypeReference variable, ref bool WeavingFailed)
{
MethodDefinition readerFunc = GenerateReaderFunction(variable);
@ -264,23 +264,23 @@ MethodDefinition GenerateClassOrStructReadFunction(TypeReference variable)
TypeDefinition td = variable.Resolve();
if (!td.IsValueType)
GenerateNullCheck(worker);
GenerateNullCheck(worker, ref WeavingFailed);
CreateNew(variable, worker, td);
ReadAllFields(variable, worker);
CreateNew(variable, worker, td, ref WeavingFailed);
ReadAllFields(variable, worker, ref WeavingFailed);
worker.Emit(OpCodes.Ldloc_0);
worker.Emit(OpCodes.Ret);
return readerFunc;
}
void GenerateNullCheck(ILProcessor worker)
void GenerateNullCheck(ILProcessor worker, ref bool WeavingFailed)
{
// if (!reader.ReadBoolean()) {
// return null;
// }
worker.Emit(OpCodes.Ldarg_0);
worker.Emit(OpCodes.Call, GetReadFunc(weaverTypes.Import<bool>()));
worker.Emit(OpCodes.Call, GetReadFunc(weaverTypes.Import<bool>(), ref WeavingFailed));
Instruction labelEmptyArray = worker.Create(OpCodes.Nop);
worker.Emit(OpCodes.Brtrue, labelEmptyArray);
@ -291,7 +291,7 @@ void GenerateNullCheck(ILProcessor worker)
}
// Initialize the local variable with a new instance
void CreateNew(TypeReference variable, ILProcessor worker, TypeDefinition td)
void CreateNew(TypeReference variable, ILProcessor worker, TypeDefinition td, ref bool WeavingFailed)
{
if (variable.IsValueType)
{
@ -313,7 +313,7 @@ void CreateNew(TypeReference variable, ILProcessor worker, TypeDefinition td)
if (ctor == null)
{
Log.Error($"{variable.Name} can't be deserialized because it has no default constructor", variable);
Weaver.WeavingFailed = true;
WeavingFailed = true;
return;
}
@ -324,14 +324,14 @@ void CreateNew(TypeReference variable, ILProcessor worker, TypeDefinition td)
}
}
void ReadAllFields(TypeReference variable, ILProcessor worker)
void ReadAllFields(TypeReference variable, ILProcessor worker, ref bool WeavingFailed)
{
foreach (FieldDefinition field in variable.FindAllPublicFields())
{
// mismatched ldloca/ldloc for struct/class combinations is invalid IL, which causes crash at runtime
OpCode opcode = variable.IsValueType ? OpCodes.Ldloca : OpCodes.Ldloc;
worker.Emit(opcode, 0);
MethodReference readFunc = GetReadFunc(field.FieldType);
MethodReference readFunc = GetReadFunc(field.FieldType, ref WeavingFailed);
if (readFunc != null)
{
worker.Emit(OpCodes.Ldarg_0);
@ -340,7 +340,7 @@ void ReadAllFields(TypeReference variable, ILProcessor worker)
else
{
Log.Error($"{field.Name} has an unsupported type", field);
Weaver.WeavingFailed = true;
WeavingFailed = true;
}
FieldReference fieldRef = assembly.MainModule.ImportReference(field);

View File

@ -156,7 +156,7 @@ public static bool Weave(AssemblyDefinition asmDef)
System.Diagnostics.Stopwatch rwstopwatch = System.Diagnostics.Stopwatch.StartNew();
// Need to track modified from ReaderWriterProcessor too because it could find custom read/write functions or create functions for NetworkMessages
bool modified = ReaderWriterProcessor.Process(CurrentAssembly, writers, readers);
bool modified = ReaderWriterProcessor.Process(CurrentAssembly, writers, readers, ref WeavingFailed);
rwstopwatch.Stop();
Console.WriteLine($"Find all reader and writers took {rwstopwatch.ElapsedMilliseconds} milliseconds");