quantum-space-buddies/MirrorWeaver/QSBReaderWriterProcessor.cs

63 lines
2.2 KiB
C#
Raw Normal View History

2022-01-27 08:27:41 +00:00
using Mirror;
using Mirror.Weaver;
using Mono.Cecil;
namespace MirrorWeaver
{
public static class QSBReaderWriterProcessor
{
/// <summary>
/// finds usages of the generic read/write methods and generates read/write functions for them.
/// <para/>
2022-01-27 08:41:06 +00:00
/// traverses from non generic classes up thru base types
2022-01-27 08:27:41 +00:00
/// in order to replace generic parameters with their corresponding generic arguments.
/// </summary>
public static void Process(AssemblyDefinition assembly, Writers writers, Readers readers, ref bool weavingFailed)
{
var NetworkWriter_Write = assembly.MainModule.ImportReference(typeof(NetworkWriter).GetMethod(nameof(NetworkWriter.Write)));
var NetworkReader_Read = assembly.MainModule.ImportReference(typeof(NetworkReader).GetMethod(nameof(NetworkReader.Read)));
foreach (var type in assembly.MainModule.GetTypes())
{
2022-01-27 08:41:06 +00:00
if (type.HasGenericParameters) continue;
2022-01-27 08:27:41 +00:00
TypeReference currentType = type;
while (currentType != null)
{
foreach (var method in currentType.Resolve().Methods)
{
if (!method.HasBody) continue;
foreach (var instruction in method.Body.Instructions)
{
if (instruction.Operand is not GenericInstanceMethod calledMethod) continue;
if (calledMethod.DeclaringType.Name == NetworkWriter_Write.DeclaringType.Name &&
calledMethod.Name == NetworkWriter_Write.Name)
{
var argType = calledMethod.GenericArguments[0];
if (argType is GenericParameter genericParameter && genericParameter.Owner == currentType.Resolve())
argType = ((GenericInstanceType)currentType).GenericArguments[genericParameter.Position];
writers.GetWriteFunc(argType, ref weavingFailed);
}
else if (calledMethod.DeclaringType.Name == NetworkReader_Read.DeclaringType.Name &&
calledMethod.Name == NetworkReader_Read.Name)
{
var argType = calledMethod.GenericArguments[0];
if (argType is GenericParameter genericParameter && genericParameter.Owner == currentType.Resolve())
argType = ((GenericInstanceType)currentType).GenericArguments[genericParameter.Position];
readers.GetReadFunc(argType, ref weavingFailed);
}
}
}
currentType = currentType.Resolve()?.BaseType;
}
}
}
}
}