diff --git a/Assets/Mirror/Editor/Weaver/Extensions.cs b/Assets/Mirror/Editor/Weaver/Extensions.cs
index 5b5acad21..21535d620 100644
--- a/Assets/Mirror/Editor/Weaver/Extensions.cs
+++ b/Assets/Mirror/Editor/Weaver/Extensions.cs
@@ -139,6 +139,22 @@ public static MethodReference MakeHostInstanceGeneric(this MethodReference self,
return Weaver.CurrentAssembly.MainModule.ImportReference(reference);
}
+ ///
+ /// Given a field of a generic class such as Writer.write,
+ /// and a generic instance such as ArraySegment`int
+ /// Creates a reference to the specialized method ArraySegment`int`.get_Count
+ /// Note that calling ArraySegment`T.get_Count directly gives an invalid IL error
+ ///
+ ///
+ /// Generic Instance eg Writer
+ ///
+ public static FieldReference SpecializeField(this FieldReference self, GenericInstanceType instanceType)
+ {
+ FieldReference reference = new FieldReference(self.Name, self.FieldType, instanceType);
+
+ return Weaver.CurrentAssembly.MainModule.ImportReference(reference);
+ }
+
public static CustomAttribute GetCustomAttribute(this ICustomAttributeProvider method)
{
foreach (CustomAttribute ca in method.CustomAttributes)
diff --git a/Assets/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs b/Assets/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs
index cb6d269a1..bd860ed80 100644
--- a/Assets/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs
+++ b/Assets/Mirror/Editor/Weaver/Processors/ReaderWriterProcessor.cs
@@ -1,7 +1,11 @@
// finds all readers and writers and register them
-using System.IO;
+using System;
+using System.Linq;
using Mono.CecilX;
+using Mono.CecilX.Cil;
+using UnityEditor;
using UnityEditor.Compilation;
+using UnityEngine;
namespace Mirror.Weaver
{
@@ -14,20 +18,12 @@ public static void Process(AssemblyDefinition CurrentAssembly)
foreach (Assembly unityAsm in CompilationPipeline.GetAssemblies())
{
- if (unityAsm.name != CurrentAssembly.Name.Name)
+ if (unityAsm.name == "Mirror")
{
- try
+ using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver())
+ using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(unityAsm.outputPath, new ReaderParameters { ReadWrite = false, ReadSymbols = false, AssemblyResolver = asmResolver }))
{
- using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver())
- using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(unityAsm.outputPath, new ReaderParameters { ReadWrite = false, ReadSymbols = false, AssemblyResolver = asmResolver }))
- {
- ProcessAssemblyClasses(CurrentAssembly, assembly);
- }
- }
- catch (FileNotFoundException)
- {
- // During first import, this gets called before some assemblies
- // are built, just skip them
+ ProcessAssemblyClasses(CurrentAssembly, assembly);
}
}
}
@@ -97,5 +93,54 @@ static void LoadDeclaredReaders(AssemblyDefinition currentAssembly, TypeDefiniti
Readers.Register(method.ReturnType, currentAssembly.MainModule.ImportReference(method));
}
}
+
+ private static bool IsEditorAssembly(AssemblyDefinition currentAssembly)
+ {
+ return currentAssembly.MainModule.AssemblyReferences.Any(assemblyReference =>
+ assemblyReference.Name == nameof(UnityEditor)
+ ) ;
+ }
+
+ ///
+ /// Creates a method that will store all the readers and writers into
+ /// and
+ ///
+ /// The method will be marked InitializeOnLoadMethodAttribute so it gets
+ /// executed before mirror runtime code
+ ///
+ ///
+ public static void InitializeReaderAndWriters(AssemblyDefinition currentAssembly)
+ {
+ var rwInitializer = new MethodDefinition("InitReadWriters", MethodAttributes.Public |
+ MethodAttributes.Static,
+ WeaverTypes.Import(typeof(void)));
+
+ System.Reflection.ConstructorInfo attributeconstructor = typeof(RuntimeInitializeOnLoadMethodAttribute).GetConstructor(new [] { typeof(RuntimeInitializeLoadType)});
+
+ CustomAttribute customAttributeRef = new CustomAttribute(currentAssembly.MainModule.ImportReference(attributeconstructor));
+ customAttributeRef.ConstructorArguments.Add(new CustomAttributeArgument(WeaverTypes.Import(), RuntimeInitializeLoadType.BeforeSceneLoad));
+ rwInitializer.CustomAttributes.Add(customAttributeRef);
+
+ if (IsEditorAssembly(currentAssembly))
+ {
+ // editor assembly, add InitializeOnLoadMethod too. Useful for the editor tests
+ System.Reflection.ConstructorInfo initializeOnLoadConstructor = typeof(InitializeOnLoadMethodAttribute).GetConstructor(new Type[0]);
+ CustomAttribute initializeCustomConstructorRef = new CustomAttribute(currentAssembly.MainModule.ImportReference(initializeOnLoadConstructor));
+ rwInitializer.CustomAttributes.Add(initializeCustomConstructorRef);
+ }
+
+ ILProcessor worker = rwInitializer.Body.GetILProcessor();
+
+ Writers.InitializeWriters(worker);
+ Readers.InitializeReaders(worker);
+
+ worker.Append(worker.Create(OpCodes.Ret));
+
+ Weaver.WeaveLists.ConfirmGeneratedCodeClass();
+ TypeDefinition generateClass = Weaver.WeaveLists.generateContainerClass;
+
+ generateClass.Methods.Add(rwInitializer);
+ }
+
}
}
diff --git a/Assets/Mirror/Editor/Weaver/Readers.cs b/Assets/Mirror/Editor/Weaver/Readers.cs
index 244b21e20..6aa3a7ca9 100644
--- a/Assets/Mirror/Editor/Weaver/Readers.cs
+++ b/Assets/Mirror/Editor/Weaver/Readers.cs
@@ -411,5 +411,40 @@ static void ReadAllFields(TypeReference variable, ILProcessor worker)
fields++;
}
}
+
+ ///
+ /// Save a delegate for each one of the readers into
+ ///
+ ///
+ internal static void InitializeReaders(ILProcessor worker)
+ {
+ ModuleDefinition module = Weaver.CurrentAssembly.MainModule;
+
+ TypeReference genericReaderClassRef = module.ImportReference(typeof(Reader<>));
+
+ System.Reflection.FieldInfo fieldInfo = typeof(Reader<>).GetField(nameof(Reader