quantum-space-buddies/MirrorWeaver/QSBReaderWriterProcessor.cs

90 lines
2.6 KiB
C#
Raw Permalink Normal View History

2022-01-27 08:27:41 +00:00
using Mirror;
using Mirror.Weaver;
using Mono.Cecil;
using System;
using System.Diagnostics;
2022-01-27 08:27:41 +00:00
2022-03-03 03:46:33 +00:00
namespace MirrorWeaver;
public static class QSBReaderWriterProcessor
2022-01-27 08:27:41 +00:00
{
2022-03-03 03:46:33 +00:00
/// <summary>
/// finds usages of the generic read/write methods and generates read/write functions for them.
/// <para/>
/// traverses from non generic classes up thru base types
/// in order to replace generic parameters with their corresponding generic arguments.
/// </summary>
public static bool Process(ModuleDefinition module, Writers writers, Readers readers, ref bool weavingFailed)
2022-01-27 08:27:41 +00:00
{
2022-03-03 03:46:33 +00:00
var sw = Stopwatch.StartNew();
2022-03-03 03:46:33 +00:00
var NetworkWriter_Write = typeof(NetworkWriter).GetMethod(nameof(NetworkWriter.Write));
var NetworkReader_Read = typeof(NetworkReader).GetMethod(nameof(NetworkReader.Read));
2022-01-27 08:27:41 +00:00
2022-03-03 03:46:33 +00:00
var count = 0;
foreach (var type in module.GetTypes())
{
if (type.HasGenericParameters)
{
2022-03-03 03:46:33 +00:00
continue;
}
2022-03-03 03:46:33 +00:00
TypeReference currentType = type;
while (currentType != null)
{
var currentTypeDef = currentType.Resolve();
foreach (var method in currentTypeDef.Methods)
{
2022-03-03 03:46:33 +00:00
if (!method.HasBody)
{
continue;
}
foreach (var instruction in method.Body.Instructions)
2022-01-27 08:27:41 +00:00
{
2022-03-03 03:46:33 +00:00
if (instruction.Operand is not GenericInstanceMethod calledMethod)
{
continue;
}
2022-02-25 05:43:40 +00:00
2022-03-03 03:46:33 +00:00
if (calledMethod.DeclaringType.FullName == NetworkWriter_Write.DeclaringType.FullName &&
calledMethod.Name == NetworkWriter_Write.Name)
2022-01-27 08:27:41 +00:00
{
2022-03-03 03:46:33 +00:00
var argType = calledMethod.GenericArguments[0];
2022-01-27 08:27:41 +00:00
if (currentType is GenericInstanceType genericInstanceType &&
argType is GenericParameter genericParameter &&
genericParameter.Owner == currentTypeDef)
{
argType = genericInstanceType.GenericArguments[genericParameter.Position];
2022-01-27 08:27:41 +00:00
}
2022-03-03 03:46:33 +00:00
writers.GetWriteFunc(argType, ref weavingFailed);
count++;
}
else if (calledMethod.DeclaringType.FullName == NetworkReader_Read.DeclaringType.FullName &&
calledMethod.Name == NetworkReader_Read.Name)
{
var argType = calledMethod.GenericArguments[0];
if (currentType is GenericInstanceType genericInstanceType &&
argType is GenericParameter genericParameter &&
genericParameter.Owner == currentTypeDef)
2022-03-03 03:46:33 +00:00
{
argType = genericInstanceType.GenericArguments[genericParameter.Position];
}
2022-03-03 03:46:33 +00:00
readers.GetReadFunc(argType, ref weavingFailed);
count++;
2022-01-27 08:27:41 +00:00
}
}
}
currentType = currentTypeDef.BaseType?.ApplyGenericParameters(currentType);
2022-03-03 03:46:33 +00:00
}
}
2022-03-03 03:46:33 +00:00
Console.WriteLine($"got/generated {count} read/write funcs in {sw.ElapsedMilliseconds} ms");
return count > 0;
2022-01-27 08:27:41 +00:00
}
}