Ejemplo n.º 1
0
        public AssemblyDefinition Weave(ICompiledAssembly compiledAssembly)
        {
            try
            {
                CurrentAssembly = AssemblyDefinitionFor(compiledAssembly);

                ModuleDefinition module = CurrentAssembly.MainModule;
                readers = new Readers(module, logger);
                writers = new Writers(module, logger);
                var rwstopwatch = System.Diagnostics.Stopwatch.StartNew();
                propertySiteProcessor = new PropertySiteProcessor();
                var rwProcessor = new ReaderWriterProcessor(module, readers, writers);

                bool modified = rwProcessor.Process();
                rwstopwatch.Stop();
                Console.WriteLine($"Find all reader and writers took {rwstopwatch.ElapsedMilliseconds} milliseconds");

                Console.WriteLine($"Script Module: {module.Name}");

                modified |= WeaveModule(module);

                if (!modified)
                    return CurrentAssembly;

                rwProcessor.InitializeReaderAndWriters();

                return CurrentAssembly;
            }
            catch (Exception e)
            {
                logger.Error("Exception :" + e);
                return null;
            }
        }
Ejemplo n.º 2
0
        static bool WeaveModule(ModuleDefinition moduleDefinition)
        {
            try
            {
                bool modified = false;

                var watch = System.Diagnostics.Stopwatch.StartNew();

                watch.Start();
                foreach (TypeDefinition td in moduleDefinition.Types)
                {
                    if (td.IsClass && td.BaseType.CanBeResolved())
                    {
                        modified |= WeaveNetworkBehavior(td);
                        modified |= ServerClientAttributeProcessor.Process(td);
                    }
                }
                watch.Stop();
                Console.WriteLine("Weave behaviours and messages took" + watch.ElapsedMilliseconds + " milliseconds");

                if (modified)
                {
                    PropertySiteProcessor.Process(moduleDefinition);
                }

                return(modified);
            }
            catch (Exception ex)
            {
                Error(ex.ToString());
                throw new Exception(ex.Message, ex);
            }
        }
Ejemplo n.º 3
0
 public SyncVarProcessor(ModuleDefinition module, Readers readers, Writers writers, PropertySiteProcessor propertySiteProcessor, IWeaverLogger logger)
 {
     this.module  = module;
     this.readers = readers;
     this.writers = writers;
     this.propertySiteProcessor = propertySiteProcessor;
     this.logger = logger;
 }
Ejemplo n.º 4
0
        static bool Weave(string assName, IEnumerable <string> dependencies)
        {
            using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver())
                using (CurrentAssembly = AssemblyDefinition.ReadAssembly(assName, new ReaderParameters {
                    ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver
                }))
                {
                    asmResolver.AddSearchDirectory(Path.GetDirectoryName(assName));
                    asmResolver.AddSearchDirectory(Helpers.UnityEngineDllDirectoryName());
                    if (dependencies != null)
                    {
                        foreach (string path in dependencies)
                        {
                            asmResolver.AddSearchDirectory(path);
                        }
                    }

                    WeaverTypes.SetupTargetTypes(CurrentAssembly);
                    // WeaverList depends on WeaverTypes setup because it uses Import
                    WeaveLists = new WeaverLists();


                    System.Diagnostics.Stopwatch rwstopwatch = System.Diagnostics.Stopwatch.StartNew();
                    // Need to track modified from ReaderWriterProcessor too because it could find custom read/write functions or create functions for NetworkMessages
                    bool modified = ReaderWriterProcessor.Process(CurrentAssembly);
                    rwstopwatch.Stop();
                    Console.WriteLine($"Find all reader and writers took {rwstopwatch.ElapsedMilliseconds} milliseconds");

                    ModuleDefinition moduleDefinition = CurrentAssembly.MainModule;
                    Console.WriteLine($"Script Module: {moduleDefinition.Name}");

                    modified |= WeaveModule(moduleDefinition);

                    if (WeavingFailed)
                    {
                        return(false);
                    }

                    if (modified)
                    {
                        PropertySiteProcessor.Process(moduleDefinition);

                        // add class that holds read/write functions
                        moduleDefinition.Types.Add(WeaveLists.generateContainerClass);

                        ReaderWriterProcessor.InitializeReaderAndWriters(CurrentAssembly);

                        // write to outputDir if specified, otherwise perform in-place write
                        WriterParameters writeParams = new WriterParameters {
                            WriteSymbols = true
                        };
                        CurrentAssembly.Write(writeParams);
                    }
                }

            return(true);
        }
Ejemplo n.º 5
0
        static bool WeaveModule(ModuleDefinition moduleDefinition)
        {
            try
            {
                bool modified = false;

                // We need to do 2 passes, because SyncListStructs might be referenced from other modules, so we must make sure we generate them first.
                System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
                foreach (TypeDefinition td in moduleDefinition.Types)
                {
                    if (td.IsClass && td.BaseType.CanBeResolved())
                    {
                        modified |= WeaveSyncObject(td);
                    }
                }
                watch.Stop();
                Console.WriteLine("Weave sync objects took " + watch.ElapsedMilliseconds + " milliseconds");

                watch.Start();
                foreach (TypeDefinition td in moduleDefinition.Types)
                {
                    if (td.IsClass && td.BaseType.CanBeResolved())
                    {
                        modified |= WeaveNetworkBehavior(td);
                        modified |= WeaveMessage(td);
                        modified |= ServerClientAttributeProcessor.Process(td);
                    }
                }
                watch.Stop();
                Console.WriteLine("Weave behaviours and messages took" + watch.ElapsedMilliseconds + " milliseconds");


                if (modified)
                {
                    PropertySiteProcessor.Process(moduleDefinition);
                }

                return(modified);
            }
            catch (Exception ex)
            {
                Error(ex.ToString());
                throw new Exception(ex.Message, ex);
            }
        }
Ejemplo n.º 6
0
        private AssemblyDefinition Weave(string compiledAssembly)
        {
            try
            {
                CurrentAssembly =
                    AssemblyDefinition.ReadAssembly(compiledAssembly);

                var module = CurrentAssembly.MainModule;
                readers = new Readers(module, logger);
                writers = new Writers(module, logger);
                var rwstopwatch = Stopwatch.StartNew();
                propertySiteProcessor = new PropertySiteProcessor();
                var rwProcessor = new ReaderWriterProcessor(module, readers, writers);

                bool modified = rwProcessor.Process();
                rwstopwatch.Stop();
                Console.WriteLine(
                    $"Find all reader and writers took {rwstopwatch.ElapsedMilliseconds} milliseconds");

                Console.WriteLine($"Script Module: {module.Name}");

                modified |= WeaveModule(module);

                if (!modified)
                    return CurrentAssembly;

                rwProcessor.InitializeReaderAndWriters();

                Directory.CreateDirectory(Path.GetDirectoryName(compiledAssembly) + "\\weave\\");

                CurrentAssembly.Write(Path.GetDirectoryName(compiledAssembly) + "\\weave\\" +
                                      Path.GetFileName(compiledAssembly));

                return CurrentAssembly;

            }
            catch (Exception e)
            {
                logger.Error("Exception :" + e.StackTrace);
                return null;
            }
#endif
        }
Ejemplo n.º 7
0
        static bool Weave(string assName, AssemblyDefinition unityAssembly, AssemblyDefinition mirrorAssembly, IEnumerable <string> dependencies, string unityEngineDLLPath, string mirrorNetDLLPath, string outputDir)
        {
            using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver())
                using (CurrentAssembly = AssemblyDefinition.ReadAssembly(assName, new ReaderParameters {
                    ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver
                }))
                {
                    asmResolver.AddSearchDirectory(Path.GetDirectoryName(assName));
                    asmResolver.AddSearchDirectory(Helpers.UnityEngineDllDirectoryName());
                    asmResolver.AddSearchDirectory(Path.GetDirectoryName(unityEngineDLLPath));
                    asmResolver.AddSearchDirectory(Path.GetDirectoryName(mirrorNetDLLPath));
                    if (dependencies != null)
                    {
                        foreach (string path in dependencies)
                        {
                            asmResolver.AddSearchDirectory(path);
                        }
                    }

                    WeaverTypes.SetupTargetTypes(unityAssembly, mirrorAssembly, CurrentAssembly);
                    System.Diagnostics.Stopwatch rwstopwatch = System.Diagnostics.Stopwatch.StartNew();
                    ReaderWriterProcessor.Process(CurrentAssembly);
                    rwstopwatch.Stop();
                    Console.WriteLine("Find all reader and writers took " + rwstopwatch.ElapsedMilliseconds + " milliseconds");

                    ModuleDefinition moduleDefinition = CurrentAssembly.MainModule;
                    Console.WriteLine("Script Module: {0}", moduleDefinition.Name);

                    bool modified = WeaveModule(moduleDefinition);

                    if (WeavingFailed)
                    {
                        return(false);
                    }

                    if (modified)
                    {
                        // this must be done for ALL code, not just NetworkBehaviours
                        try
                        {
                            PropertySiteProcessor.Process(moduleDefinition);
                        }
                        catch (Exception e)
                        {
                            Log.Error("ProcessPropertySites exception: " + e);
                            return(false);
                        }

                        if (WeavingFailed)
                        {
                            return(false);
                        }

                        // write to outputDir if specified, otherwise perform in-place write
                        WriterParameters writeParams = new WriterParameters {
                            WriteSymbols = true
                        };
                        if (!string.IsNullOrEmpty(outputDir))
                        {
                            CurrentAssembly.Write(Helpers.DestinationFileFor(outputDir, assName), writeParams);
                        }
                        else
                        {
                            CurrentAssembly.Write(writeParams);
                        }
                    }
                }

            return(true);
        }
Ejemplo n.º 8
0
        static bool Weave(string assName, IEnumerable <string> dependencies, IAssemblyResolver assemblyResolver, string unityEngineDLLPath, string mirrorNetDLLPath, string outputDir)
        {
            using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver())
                using (CurrentAssembly = AssemblyDefinition.ReadAssembly(assName, new ReaderParameters {
                    ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver
                }))
                {
                    asmResolver.AddSearchDirectory(Path.GetDirectoryName(assName));
                    asmResolver.AddSearchDirectory(Helpers.UnityEngineDLLDirectoryName());
                    asmResolver.AddSearchDirectory(Path.GetDirectoryName(unityEngineDLLPath));
                    asmResolver.AddSearchDirectory(Path.GetDirectoryName(mirrorNetDLLPath));
                    if (dependencies != null)
                    {
                        foreach (string path in dependencies)
                        {
                            asmResolver.AddSearchDirectory(path);
                        }
                    }

                    SetupTargetTypes();
                    Readers.Init(CurrentAssembly);
                    Writers.Init(CurrentAssembly);

                    ModuleDefinition moduleDefinition = CurrentAssembly.MainModule;
                    Console.WriteLine("Script Module: {0}", moduleDefinition.Name);

                    // Process each NetworkBehaviour
                    bool didWork = false;

                    // We need to do 2 passes, because SyncListStructs might be referenced from other modules, so we must make sure we generate them first.
                    for (int pass = 0; pass < 2; pass++)
                    {
                        System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
                        foreach (TypeDefinition td in moduleDefinition.Types)
                        {
                            if (td.IsClass && td.BaseType.CanBeResolved())
                            {
                                try
                                {
                                    if (pass == 0)
                                    {
                                        didWork |= CheckSyncList(td);
                                    }
                                    else
                                    {
                                        didWork |= CheckNetworkBehaviour(td);
                                        didWork |= CheckMessageBase(td);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Weaver.Error(ex.Message);
                                    throw ex;
                                }
                            }

                            if (WeavingFailed)
                            {
                                return(false);
                            }
                        }
                        watch.Stop();
                        Console.WriteLine("Pass: "******" took " + watch.ElapsedMilliseconds + " milliseconds");
                    }

                    if (didWork)
                    {
                        // this must be done for ALL code, not just NetworkBehaviours
                        try
                        {
                            PropertySiteProcessor.ProcessSitesModule(CurrentAssembly.MainModule);
                        }
                        catch (Exception e)
                        {
                            Log.Error("ProcessPropertySites exception: " + e);
                            return(false);
                        }

                        if (WeavingFailed)
                        {
                            //Log.Error("Failed phase II.");
                            return(false);
                        }

                        // write to outputDir if specified, otherwise perform in-place write
                        WriterParameters writeParams = new WriterParameters {
                            WriteSymbols = true
                        };
                        if (outputDir != null)
                        {
                            CurrentAssembly.Write(Helpers.DestinationFileFor(outputDir, assName), writeParams);
                        }
                        else
                        {
                            CurrentAssembly.Write(writeParams);
                        }
                    }
                }

            return(true);
        }
 public NetworkBehaviourProcessor(TypeDefinition td, Readers readers, Writers writers, PropertySiteProcessor propertySiteProcessor, IWeaverLogger logger)
 {
     Weaver.DLog(td, "NetworkBehaviourProcessor");
     netBehaviourSubclass = td;
     this.logger          = logger;
     serverRpcProcessor   = new ServerRpcProcessor(netBehaviourSubclass.Module, readers, writers, logger);
     clientRpcProcessor   = new ClientRpcProcessor(netBehaviourSubclass.Module, readers, writers, logger);
     syncVarProcessor     = new SyncVarProcessor(netBehaviourSubclass.Module, readers, writers, propertySiteProcessor, logger);
     syncObjectProcessor  = new SyncObjectProcessor(readers, writers, logger);
 }
Ejemplo n.º 10
0
        static bool Weave(string assName, IEnumerable <string> dependencies, IAssemblyResolver assemblyResolver, string unityEngineDLLPath, string mirrorNetDLLPath, string outputDir)
        {
            ReaderParameters readParams = Helpers.ReaderParameters(assName, dependencies, assemblyResolver, unityEngineDLLPath, mirrorNetDLLPath);

            using (CurrentAssembly = AssemblyDefinition.ReadAssembly(assName, readParams))
            {
                SetupTargetTypes();
                Readers.Init(CurrentAssembly);
                Writers.Init(CurrentAssembly);

                ModuleDefinition moduleDefinition = CurrentAssembly.MainModule;
                Console.WriteLine("Script Module: {0}", moduleDefinition.Name);

                // Process each NetworkBehaviour
                bool didWork = false;

                // We need to do 2 passes, because SyncListStructs might be referenced from other modules, so we must make sure we generate them first.
                for (int pass = 0; pass < 2; pass++)
                {
                    System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew();
                    foreach (TypeDefinition td in moduleDefinition.Types)
                    {
                        if (td.IsClass && td.BaseType.CanBeResolved())
                        {
                            try
                            {
                                if (pass == 0)
                                {
                                    didWork |= CheckSyncList(td);
                                }
                                else
                                {
                                    didWork |= CheckNetworkBehaviour(td);
                                    didWork |= CheckMessageBase(td);
                                }
                            }
                            catch (Exception ex)
                            {
                                if (CurrentAssembly.MainModule.SymbolReader != null)
                                {
                                    CurrentAssembly.MainModule.SymbolReader.Dispose();
                                }
                                Weaver.Error(ex.Message);
                                throw ex;
                            }
                        }

                        if (WeavingFailed)
                        {
                            if (CurrentAssembly.MainModule.SymbolReader != null)
                            {
                                CurrentAssembly.MainModule.SymbolReader.Dispose();
                            }
                            return(false);
                        }
                    }
                    watch.Stop();
                    Console.WriteLine("Pass: "******" took " + watch.ElapsedMilliseconds + " milliseconds");
                }

                if (didWork)
                {
                    // this must be done for ALL code, not just NetworkBehaviours
                    try
                    {
                        PropertySiteProcessor.ProcessSitesModule(CurrentAssembly.MainModule);
                    }
                    catch (Exception e)
                    {
                        Log.Error("ProcessPropertySites exception: " + e);
                        if (CurrentAssembly.MainModule.SymbolReader != null)
                        {
                            CurrentAssembly.MainModule.SymbolReader.Dispose();
                        }
                        return(false);
                    }

                    if (WeavingFailed)
                    {
                        //Log.Error("Failed phase II.");
                        if (CurrentAssembly.MainModule.SymbolReader != null)
                        {
                            CurrentAssembly.MainModule.SymbolReader.Dispose();
                        }
                        return(false);
                    }

                    string dest = Helpers.DestinationFileFor(outputDir, assName);
                    //Console.WriteLine ("Output:" + dest);

                    WriterParameters writeParams = Helpers.GetWriterParameters(readParams);
                    CurrentAssembly.Write(dest, writeParams);
                }

                if (CurrentAssembly.MainModule.SymbolReader != null)
                {
                    CurrentAssembly.MainModule.SymbolReader.Dispose();
                }
            }

            return(true);
        }
        // Weave takes an AssemblyDefinition to be compatible with both old and
        // new weavers:
        // * old takes a filepath, new takes a in-memory byte[]
        // * old uses DefaultAssemblyResolver with added dependencies paths,
        //   new uses ...?
        //
        // => assembly: the one we are currently weaving (MyGame.dll)
        // => resolver: useful in case we need to resolve any of the assembly's
        //              assembly.MainModule.AssemblyReferences.
        //              -> we can resolve ANY of them given that the resolver
        //                 works properly (need custom one for ILPostProcessor)
        //              -> IMPORTANT: .Resolve() takes an AssemblyNameReference.
        //                 those from assembly.MainModule.AssemblyReferences are
        //                 guaranteed to be resolve-able.
        //                 Parsing from a string for Library/.../Mirror.dll
        //                 would not be guaranteed to be resolve-able because
        //                 for ILPostProcessor we can't assume where Mirror.dll
        //                 is etc.
        public bool Weave(AssemblyDefinition assembly, IAssemblyResolver resolver, out bool modified)
        {
            WeavingFailed = false;
            modified      = false;
            try
            {
                Resolver        = resolver;
                CurrentAssembly = assembly;

                // fix "No writer found for ..." error
                // https://github.com/vis2k/Mirror/issues/2579
                // -> when restarting Unity, weaver would try to weave a DLL
                //    again
                // -> resulting in two GeneratedNetworkCode classes (see ILSpy)
                // -> the second one wouldn't have all the writer types setup
                if (CurrentAssembly.MainModule.ContainsClass(GeneratedCodeNamespace, GeneratedCodeClassName))
                {
                    //Log.Warning($"Weaver: skipping {CurrentAssembly.Name} because already weaved");
                    return(true);
                }

                weaverTypes = new WeaverTypes(CurrentAssembly, Log, ref WeavingFailed);

                // weaverTypes are needed for CreateGeneratedCodeClass
                CreateGeneratedCodeClass();

                // WeaverList depends on WeaverTypes setup because it uses Import
                weaverLists = new WeaverLists();

                // initialize readers & writers with this assembly.
                // we need to do this in every Process() call.
                // otherwise we would get
                // "System.ArgumentException: Member ... is declared in another module and needs to be imported"
                // errors when still using the previous module's reader/writer funcs.
                writers = new Writers(CurrentAssembly, weaverTypes, GeneratedCodeClass, Log);
                readers = new Readers(CurrentAssembly, weaverTypes, GeneratedCodeClass, Log);

                Stopwatch rwstopwatch = Stopwatch.StartNew();
                // Need to track modified from ReaderWriterProcessor too because it could find custom read/write functions or create functions for NetworkMessages
                modified = ReaderWriterProcessor.Process(CurrentAssembly, resolver, Log, writers, readers, ref WeavingFailed);
                rwstopwatch.Stop();
                Console.WriteLine($"Find all reader and writers took {rwstopwatch.ElapsedMilliseconds} milliseconds");

                ModuleDefinition moduleDefinition = CurrentAssembly.MainModule;
                Console.WriteLine($"Script Module: {moduleDefinition.Name}");

                modified |= WeaveModule(moduleDefinition);

                if (WeavingFailed)
                {
                    return(false);
                }

                if (modified)
                {
                    PropertySiteProcessor.Process(moduleDefinition, weaverLists);

                    // add class that holds read/write functions
                    moduleDefinition.Types.Add(GeneratedCodeClass);

                    ReaderWriterProcessor.InitializeReaderAndWriters(CurrentAssembly, weaverTypes, writers, readers, GeneratedCodeClass);

                    // DO NOT WRITE here.
                    // CompilationFinishedHook writes to the file.
                    // ILPostProcessor writes to in-memory assembly.
                    // it depends on the caller.
                    //CurrentAssembly.Write(new WriterParameters{ WriteSymbols = true });
                }

                return(true);
            }
            catch (Exception e)
            {
                Log.Error("Exception :" + e);
                WeavingFailed = true;
                return(false);
            }
        }
Ejemplo n.º 12
0
        static bool Weave(string assName, IEnumerable <string> dependencies)
        {
            using (DefaultAssemblyResolver asmResolver = new DefaultAssemblyResolver())
                using (CurrentAssembly = AssemblyDefinition.ReadAssembly(assName, new ReaderParameters {
                    ReadWrite = true, ReadSymbols = true, AssemblyResolver = asmResolver
                }))
                {
                    asmResolver.AddSearchDirectory(Path.GetDirectoryName(assName));
                    asmResolver.AddSearchDirectory(Helpers.UnityEngineDllDirectoryName());
                    if (dependencies != null)
                    {
                        foreach (string path in dependencies)
                        {
                            asmResolver.AddSearchDirectory(path);
                        }
                    }

                    // fix "No writer found for ..." error
                    // https://github.com/vis2k/Mirror/issues/2579
                    // -> when restarting Unity, weaver would try to weave a DLL
                    //    again
                    // -> resulting in two GeneratedNetworkCode classes (see ILSpy)
                    // -> the second one wouldn't have all the writer types setup
                    if (ContainsGeneratedCodeClass(CurrentAssembly.MainModule))
                    {
                        //Log.Warning($"Weaver: skipping {CurrentAssembly.Name} because already weaved");
                        return(true);
                    }

                    WeaverTypes.SetupTargetTypes(CurrentAssembly);

                    CreateGeneratedCodeClass();

                    // WeaverList depends on WeaverTypes setup because it uses Import
                    WeaveLists = new WeaverLists();

                    System.Diagnostics.Stopwatch rwstopwatch = System.Diagnostics.Stopwatch.StartNew();
                    // Need to track modified from ReaderWriterProcessor too because it could find custom read/write functions or create functions for NetworkMessages
                    bool modified = ReaderWriterProcessor.Process(CurrentAssembly);
                    rwstopwatch.Stop();
                    Console.WriteLine($"Find all reader and writers took {rwstopwatch.ElapsedMilliseconds} milliseconds");

                    ModuleDefinition moduleDefinition = CurrentAssembly.MainModule;
                    Console.WriteLine($"Script Module: {moduleDefinition.Name}");

                    modified |= WeaveModule(moduleDefinition);

                    if (WeavingFailed)
                    {
                        return(false);
                    }

                    if (modified)
                    {
                        PropertySiteProcessor.Process(moduleDefinition);

                        // add class that holds read/write functions
                        moduleDefinition.Types.Add(GeneratedCodeClass);

                        ReaderWriterProcessor.InitializeReaderAndWriters(CurrentAssembly);

                        // write to outputDir if specified, otherwise perform in-place write
                        WriterParameters writeParams = new WriterParameters {
                            WriteSymbols = true
                        };
                        CurrentAssembly.Write(writeParams);
                    }
                }

            return(true);
        }