mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
synclist code generator is now reusable (#624)
* refactor: Made serializer generation reusable * refactor: SyncList code generator is reusable for other structs
This commit is contained in:
parent
1d166c699a
commit
b7e977a7a3
@ -6,112 +6,13 @@ namespace Mirror.Weaver
|
||||
{
|
||||
static class SyncListProcessor
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates serialization methods for synclists
|
||||
/// </summary>
|
||||
/// <param name="td">The synclist class</param>
|
||||
public static void Process(TypeDefinition td)
|
||||
{
|
||||
// find item type
|
||||
GenericInstanceType gt = (GenericInstanceType)td.BaseType;
|
||||
if (gt.GenericArguments.Count == 0)
|
||||
{
|
||||
Weaver.Error("SyncListProcessor no generic args");
|
||||
return;
|
||||
}
|
||||
TypeReference itemType = Weaver.CurrentAssembly.MainModule.ImportReference(gt.GenericArguments[0]);
|
||||
|
||||
Weaver.DLog(td, "SyncListProcessor Start item:" + itemType.FullName);
|
||||
|
||||
Weaver.ResetRecursionCount();
|
||||
MethodReference writeItemFunc = GenerateSerialization(td, itemType);
|
||||
if (Weaver.WeavingFailed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MethodReference readItemFunc = GenerateDeserialization(td, itemType);
|
||||
|
||||
if (readItemFunc == null || writeItemFunc == null)
|
||||
return;
|
||||
|
||||
Weaver.DLog(td, "SyncListProcessor Done");
|
||||
}
|
||||
|
||||
// serialization of individual element
|
||||
static MethodReference GenerateSerialization(TypeDefinition td, TypeReference itemType)
|
||||
{
|
||||
Weaver.DLog(td, " GenerateSerialization");
|
||||
foreach (var m in td.Methods)
|
||||
{
|
||||
if (m.Name == "SerializeItem")
|
||||
return m;
|
||||
}
|
||||
|
||||
MethodDefinition serializeFunc = new MethodDefinition("SerializeItem", MethodAttributes.Public |
|
||||
MethodAttributes.Virtual |
|
||||
MethodAttributes.Public |
|
||||
MethodAttributes.HideBySig,
|
||||
Weaver.voidType);
|
||||
|
||||
serializeFunc.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkWriterType)));
|
||||
serializeFunc.Parameters.Add(new ParameterDefinition("item", ParameterAttributes.None, itemType));
|
||||
ILProcessor serWorker = serializeFunc.Body.GetILProcessor();
|
||||
|
||||
if (itemType.IsGenericInstance)
|
||||
{
|
||||
Weaver.Error("GenerateSerialization for " + Helpers.PrettyPrintType(itemType) + " failed. Struct passed into SyncList<T> can't have generic parameters");
|
||||
return null;
|
||||
}
|
||||
|
||||
MethodReference writeFunc = Weaver.GetWriteFunc(itemType);
|
||||
if (writeFunc != null)
|
||||
{
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_2));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc));
|
||||
}
|
||||
else
|
||||
{
|
||||
Weaver.Error("GenerateSerialization for " + td.Name + " unknown type [" + itemType + "/" + itemType.FullName + "]. [SyncList] member variables must be basic types.");
|
||||
return null;
|
||||
}
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ret));
|
||||
|
||||
td.Methods.Add(serializeFunc);
|
||||
return serializeFunc;
|
||||
}
|
||||
|
||||
static MethodReference GenerateDeserialization(TypeDefinition td, TypeReference itemType)
|
||||
{
|
||||
Weaver.DLog(td, " GenerateDeserialization");
|
||||
foreach (var m in td.Methods)
|
||||
{
|
||||
if (m.Name == "DeserializeItem")
|
||||
return m;
|
||||
}
|
||||
|
||||
MethodDefinition deserializeFunction = new MethodDefinition("DeserializeItem", MethodAttributes.Public |
|
||||
MethodAttributes.Virtual |
|
||||
MethodAttributes.Public |
|
||||
MethodAttributes.HideBySig,
|
||||
itemType);
|
||||
|
||||
deserializeFunction.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkReaderType)));
|
||||
|
||||
ILProcessor serWorker = deserializeFunction.Body.GetILProcessor();
|
||||
|
||||
MethodReference readerFunc = Weaver.GetReadFunc(itemType);
|
||||
if (readerFunc != null)
|
||||
{
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Call, readerFunc));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ret));
|
||||
}
|
||||
else
|
||||
{
|
||||
Weaver.Error("GenerateDeserialization for " + td.Name + " unknown type [" + itemType + "]. [SyncList] member variables must be basic types.");
|
||||
return null;
|
||||
}
|
||||
|
||||
td.Methods.Add(deserializeFunction);
|
||||
return deserializeFunction;
|
||||
SyncObjectProcessor.GenerateSerialization(td, 0, "SerializeItem", "DeserializeItem");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
124
Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs
Normal file
124
Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs
Normal file
@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
|
||||
namespace Mirror.Weaver
|
||||
{
|
||||
public static class SyncObjectProcessor
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates the serialization and deserialization methods for a specified generic argument
|
||||
/// </summary>
|
||||
/// <param name="td">The type of the class that needs serialization methods</param>
|
||||
/// <param name="genericArgument">Which generic argument to serialize, 0 is the first one</param>
|
||||
/// <param name="serializeMethod">The name of the serialize method</param>
|
||||
/// <param name="deserializeMethod">The name of the deserialize method</param>
|
||||
public static void GenerateSerialization(TypeDefinition td, int genericArgument, string serializeMethod, string deserializeMethod)
|
||||
{
|
||||
// find item type
|
||||
GenericInstanceType gt = (GenericInstanceType)td.BaseType;
|
||||
if (gt.GenericArguments.Count <= genericArgument)
|
||||
{
|
||||
Weaver.Error("SyncObjectProcessor no generic args");
|
||||
return;
|
||||
}
|
||||
TypeReference itemType = Weaver.CurrentAssembly.MainModule.ImportReference(gt.GenericArguments[genericArgument]);
|
||||
|
||||
Weaver.DLog(td, "SyncObjectProcessor Start item:" + itemType.FullName);
|
||||
|
||||
Weaver.ResetRecursionCount();
|
||||
MethodReference writeItemFunc = GenerateSerialization(serializeMethod, td, itemType);
|
||||
if (Weaver.WeavingFailed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MethodReference readItemFunc = GenerateDeserialization(deserializeMethod, td, itemType);
|
||||
|
||||
if (readItemFunc == null || writeItemFunc == null)
|
||||
return;
|
||||
|
||||
Weaver.DLog(td, "SyncObjectProcessor Done");
|
||||
}
|
||||
|
||||
// serialization of individual element
|
||||
static MethodReference GenerateSerialization(string methodName, TypeDefinition td, TypeReference itemType)
|
||||
{
|
||||
Weaver.DLog(td, " GenerateSerialization");
|
||||
foreach (var m in td.Methods)
|
||||
{
|
||||
if (m.Name == methodName)
|
||||
return m;
|
||||
}
|
||||
|
||||
MethodDefinition serializeFunc = new MethodDefinition(methodName, MethodAttributes.Public |
|
||||
MethodAttributes.Virtual |
|
||||
MethodAttributes.Public |
|
||||
MethodAttributes.HideBySig,
|
||||
Weaver.voidType);
|
||||
|
||||
serializeFunc.Parameters.Add(new ParameterDefinition("writer", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkWriterType)));
|
||||
serializeFunc.Parameters.Add(new ParameterDefinition("item", ParameterAttributes.None, itemType));
|
||||
ILProcessor serWorker = serializeFunc.Body.GetILProcessor();
|
||||
|
||||
if (itemType.IsGenericInstance)
|
||||
{
|
||||
Weaver.Error("GenerateSerialization for " + Helpers.PrettyPrintType(itemType) + " failed. Can't have generic parameters");
|
||||
return null;
|
||||
}
|
||||
|
||||
MethodReference writeFunc = Weaver.GetWriteFunc(itemType);
|
||||
if (writeFunc != null)
|
||||
{
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_2));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Call, writeFunc));
|
||||
}
|
||||
else
|
||||
{
|
||||
Weaver.Error("GenerateSerialization for " + td.Name + " unknown type [" + itemType + "/" + itemType.FullName + "]. Member variables must be basic types.");
|
||||
return null;
|
||||
}
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ret));
|
||||
|
||||
td.Methods.Add(serializeFunc);
|
||||
return serializeFunc;
|
||||
}
|
||||
|
||||
static MethodReference GenerateDeserialization(string methodName, TypeDefinition td, TypeReference itemType)
|
||||
{
|
||||
Weaver.DLog(td, " GenerateDeserialization");
|
||||
foreach (var m in td.Methods)
|
||||
{
|
||||
if (m.Name == methodName)
|
||||
return m;
|
||||
}
|
||||
|
||||
MethodDefinition deserializeFunction = new MethodDefinition(methodName, MethodAttributes.Public |
|
||||
MethodAttributes.Virtual |
|
||||
MethodAttributes.Public |
|
||||
MethodAttributes.HideBySig,
|
||||
itemType);
|
||||
|
||||
deserializeFunction.Parameters.Add(new ParameterDefinition("reader", ParameterAttributes.None, Weaver.CurrentAssembly.MainModule.ImportReference(Weaver.NetworkReaderType)));
|
||||
|
||||
ILProcessor serWorker = deserializeFunction.Body.GetILProcessor();
|
||||
|
||||
MethodReference readerFunc = Weaver.GetReadFunc(itemType);
|
||||
if (readerFunc != null)
|
||||
{
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Call, readerFunc));
|
||||
serWorker.Append(serWorker.Create(OpCodes.Ret));
|
||||
}
|
||||
else
|
||||
{
|
||||
Weaver.Error("GenerateDeserialization for " + td.Name + " unknown type [" + itemType + "]. Member variables must be basic types.");
|
||||
return null;
|
||||
}
|
||||
|
||||
td.Methods.Add(deserializeFunction);
|
||||
return deserializeFunction;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78f71efc83cde4917b7d21efa90bcc9a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -285,7 +285,7 @@ public void SyncListStructGenericGeneric()
|
||||
{
|
||||
Assert.That(CompilationFinishedHook.WeaveFailed, Is.True);
|
||||
Assert.That(m_weaverErrors.Count, Is.EqualTo(1));
|
||||
Assert.That(m_weaverErrors[0], Does.Match("Struct passed into SyncList<T> can't have generic parameters"));
|
||||
Assert.That(m_weaverErrors[0], Is.EqualTo("Mirror.Weaver error: GenerateSerialization for MyGenericStruct<Single> failed. Can't have generic parameters"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
Loading…
Reference in New Issue
Block a user