diff --git a/Assets/Mirror/Editor/Weaver/Processors/SyncListProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/SyncListProcessor.cs index cade18f3d..9878ba70c 100644 --- a/Assets/Mirror/Editor/Weaver/Processors/SyncListProcessor.cs +++ b/Assets/Mirror/Editor/Weaver/Processors/SyncListProcessor.cs @@ -4,114 +4,15 @@ namespace Mirror.Weaver { - static class SyncListProcessor + static class SyncListProcessor { + /// + /// Generates serialization methods for synclists + /// + /// The synclist class 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 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"); } } } diff --git a/Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs new file mode 100644 index 000000000..bb2ad49eb --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs @@ -0,0 +1,124 @@ +using System; +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace Mirror.Weaver +{ + public static class SyncObjectProcessor + { + /// + /// Generates the serialization and deserialization methods for a specified generic argument + /// + /// The type of the class that needs serialization methods + /// Which generic argument to serialize, 0 is the first one + /// The name of the serialize method + /// The name of the deserialize method + 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; + } + } +} diff --git a/Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs.meta b/Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs.meta new file mode 100644 index 000000000..0efe434a2 --- /dev/null +++ b/Assets/Mirror/Editor/Weaver/Processors/SyncObjectProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 78f71efc83cde4917b7d21efa90bcc9a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Mirror/Tests/WeaverTest.cs b/Assets/Mirror/Tests/WeaverTest.cs index e0512bf99..00244a085 100644 --- a/Assets/Mirror/Tests/WeaverTest.cs +++ b/Assets/Mirror/Tests/WeaverTest.cs @@ -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 can't have generic parameters")); + Assert.That(m_weaverErrors[0], Is.EqualTo("Mirror.Weaver error: GenerateSerialization for MyGenericStruct failed. Can't have generic parameters")); } [Test]