예제 #1
0
        private static void PostFindPluginTypes(Dictionary <string, List <PluginInfo> > __result, string directory,
                                                Func <TypeDefinition, PluginInfo> typeSelector, Func <AssemblyDefinition, bool> assemblyFilter,
                                                string cacheName)
        {
            // Prevent recursion
            if (directory != Paths.PluginPath)
            {
                return;
            }

            MultiFolderLoader.Logger.LogInfo("Finding plugins from mods...");
            foreach (var pluginDir in ModManager.GetPluginDirs())
            {
                var result = TypeLoader.FindPluginTypes(pluginDir, typeSelector, assemblyFilter, cacheName);
                foreach (var kv in result)
                {
                    __result[kv.Key] = kv.Value;
                }
            }

            shouldSaveCache = true;
            if (cacheName != null)
            {
                TypeLoader.SaveAssemblyCache(cacheName, __result);
            }
        }
예제 #2
0
        /// <summary>
        ///     Adds all patchers from all managed assemblies specified in a directory.
        /// </summary>
        /// <param name="directory">Directory to search patcher DLLs from.</param>
        /// <param name="patcherLocator">A function that locates assembly patchers in a given managed assembly.</param>
        public static void AddPatchersFromDirectory(string directory)
        {
            if (!Directory.Exists(directory))
            {
                return;
            }

            var sortedPatchers = new SortedDictionary <string, PatcherPlugin>();

            var patchers = TypeLoader.FindPluginTypes(directory, ToPatcherPlugin);

            foreach (var keyValuePair in patchers)
            {
                var assemblyPath      = keyValuePair.Key;
                var patcherCollection = keyValuePair.Value;

                if (patcherCollection.Count == 0)
                {
                    continue;
                }

                var ass = Assembly.LoadFile(assemblyPath);

                foreach (var patcherPlugin in patcherCollection)
                {
                    try
                    {
                        var type = ass.GetType(patcherPlugin.TypeName);

                        var methods = type.GetMethods(ALL);

                        patcherPlugin.Initializer = CreateDelegate <Action>(methods.FirstOrDefault(m => m.Name.Equals("Initialize", StringComparison.InvariantCultureIgnoreCase) &&
                                                                                                   m.GetParameters().Length == 0 &&
                                                                                                   m.ReturnType == typeof(void)));

                        patcherPlugin.Finalizer = CreateDelegate <Action>(methods.FirstOrDefault(m => m.Name.Equals("Finish", StringComparison.InvariantCultureIgnoreCase) &&
                                                                                                 m.GetParameters().Length == 0 &&
                                                                                                 m.ReturnType == typeof(void)));

                        patcherPlugin.TargetDLLs = CreateDelegate <Func <IEnumerable <string> > >(type.GetProperty("TargetDLLs", ALL).GetGetMethod());

                        var patcher = methods.FirstOrDefault(m => m.Name.Equals("Patch", StringComparison.CurrentCultureIgnoreCase) &&
                                                             m.ReturnType == typeof(void) &&
                                                             m.GetParameters().Length == 1 &&
                                                             (m.GetParameters()[0].ParameterType == typeof(AssemblyDefinition) ||
                                                              m.GetParameters()[0].ParameterType == typeof(AssemblyDefinition).MakeByRefType()));

                        patcherPlugin.Patcher = (ref AssemblyDefinition pAss) =>
                        {
                            //we do the array fuckery here to get the ref result out
                            object[] args = { pAss };

                            patcher.Invoke(null, args);

                            pAss = (AssemblyDefinition)args[0];
                        };

                        sortedPatchers.Add($"{ass.GetName().Name}/{type.FullName}", patcherPlugin);
                    }
                    catch (Exception e)
                    {
                        Logger.LogError($"Failed to load patcher [{patcherPlugin.TypeName}]: {e.Message}");
                        if (e is ReflectionTypeLoadException re)
                        {
                            Logger.LogDebug(TypeLoader.TypeLoadExceptionToString(re));
                        }
                        else
                        {
                            Logger.LogDebug(e.ToString());
                        }
                    }
                }

                Logger.Log(patcherCollection.Any() ? LogLevel.Info : LogLevel.Debug,
                           $"Loaded {patcherCollection.Count} patcher methods from {ass.GetName().FullName}");
            }

            foreach (KeyValuePair <string, PatcherPlugin> patcher in sortedPatchers)
            {
                AddPatcher(patcher.Value);
            }
        }