using System.Reflection; using Milimoe.FunGame.Core.Interface.Addons; using Milimoe.FunGame.Core.Library.Common.Addon; using Milimoe.FunGame.Core.Library.Constant; namespace Milimoe.FunGame.Core.Service { internal class AddonManager { /// /// 已加载的插件DLL名称对应的路径 /// internal static Dictionary PluginFilePaths { get; } = []; /// /// 已加载的模组DLL名称对应的路径 /// internal static Dictionary ModuleFilePaths { get; } = []; /// /// 从plugins目录加载所有插件 /// /// /// /// /// internal static Dictionary LoadPlugins(Dictionary plugins, Dictionary delegates, params object[] otherobjs) { if (!Directory.Exists(ReflectionSet.PluginFolderPath)) return plugins; string[] dlls = Directory.GetFiles(ReflectionSet.PluginFolderPath, "*.dll"); foreach (string dll in dlls) { // 加载目录下所有的DLL Assembly assembly = Assembly.LoadFrom(dll); foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(Plugin)))) { if (AddAddonInstances(type, plugins, (instance) => { if (instance.Load(otherobjs)) { instance.Controller = new(instance, delegates); return true; } return false; })) { AddDictionary(PluginFilePaths, assembly, dll); } } } return plugins; } /// /// 从plugins目录加载所有Server插件 /// /// /// /// /// internal static Dictionary LoadServerPlugins(Dictionary plugins, Dictionary delegates, params object[] otherobjs) { if (!Directory.Exists(ReflectionSet.PluginFolderPath)) return plugins; string[] dlls = Directory.GetFiles(ReflectionSet.PluginFolderPath, "*.dll"); foreach (string dll in dlls) { // 加载目录下所有的DLL Assembly assembly = Assembly.LoadFrom(dll); foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(ServerPlugin)))) { if (AddAddonInstances(type, plugins, (instance) => { if (instance.Load(otherobjs)) { instance.Controller = new(instance, delegates); return true; } return false; })) { AddDictionary(PluginFilePaths, assembly, dll); } } } return plugins; } /// /// 从plugins目录加载所有WebAPI插件 /// /// /// /// /// internal static Dictionary LoadWebAPIPlugins(Dictionary plugins, Dictionary delegates, params object[] otherobjs) { if (!Directory.Exists(ReflectionSet.PluginFolderPath)) return plugins; string[] dlls = Directory.GetFiles(ReflectionSet.PluginFolderPath, "*.dll"); foreach (string dll in dlls) { // 加载目录下所有的DLL Assembly assembly = Assembly.LoadFrom(dll); foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(WebAPIPlugin)))) { if (AddAddonInstances(type, plugins, (instance) => { if (instance.Load(otherobjs)) { instance.Controller = new(instance, delegates); return true; } return false; })) { AddDictionary(PluginFilePaths, assembly, dll); } } } return plugins; } /// /// 从modules目录加载所有模组 /// /// /// /// /// /// /// /// internal static Dictionary LoadGameModules(Dictionary modules, Dictionary characters, Dictionary skills, Dictionary items, Dictionary delegates, params object[] otherobjs) { if (!Directory.Exists(ReflectionSet.GameModuleFolderPath)) return modules; string[] dlls = Directory.GetFiles(ReflectionSet.GameModuleFolderPath, "*.dll"); foreach (string dll in dlls) { Assembly assembly = Assembly.LoadFrom(dll); foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => typeof(IAddon).IsAssignableFrom(type))) { bool isAdded = false; if (type.IsSubclassOf(typeof(GameModule))) { isAdded = AddAddonInstances(type, modules, (instance) => { if (instance.Load(otherobjs)) { instance.Controller = new(instance, delegates); return true; } return false; }); } else if (type.IsSubclassOf(typeof(CharacterModule))) { isAdded = AddAddonInstances(type, characters, (instance) => instance.Load(otherobjs)); } else if (type.IsSubclassOf(typeof(SkillModule))) { isAdded = AddAddonInstances(type, skills, (instance) => instance.Load(otherobjs)); } else if (type.IsSubclassOf(typeof(ItemModule))) { isAdded = AddAddonInstances(type, items, (instance) => instance.Load(otherobjs)); } if (isAdded) { AddDictionary(ModuleFilePaths, assembly, dll); } } } return modules; } /// /// 从modules目录加载所有适用于服务器的模组 /// /// /// /// /// /// /// /// internal static Dictionary LoadGameModulesForServer(Dictionary servers, Dictionary characters, Dictionary skills, Dictionary items, Dictionary delegates, params object[] otherobjs) { if (!Directory.Exists(ReflectionSet.GameModuleFolderPath)) return servers; string[] dlls = Directory.GetFiles(ReflectionSet.GameModuleFolderPath, "*.dll"); foreach (string dll in dlls) { Assembly assembly = Assembly.LoadFrom(dll); foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => typeof(IAddon).IsAssignableFrom(type))) { bool isAdded = false; if (type.IsSubclassOf(typeof(GameModuleServer))) { isAdded = AddAddonInstances(type, servers, (instance) => { if (instance.Load(otherobjs)) { instance.Controller = new(instance, delegates); return true; } return false; }); } else if (type.IsSubclassOf(typeof(CharacterModule))) { isAdded = AddAddonInstances(type, characters, (instance) => instance.Load(otherobjs)); } else if (type.IsSubclassOf(typeof(SkillModule))) { isAdded = AddAddonInstances(type, skills, (instance) => instance.Load(otherobjs)); } else if (type.IsSubclassOf(typeof(ItemModule))) { isAdded = AddAddonInstances(type, items, (instance) => instance.Load(otherobjs)); } if (isAdded) { AddDictionary(ModuleFilePaths, assembly, dll); } } } return servers; } /// /// 从maps目录加载所有地图 /// /// /// /// internal static Dictionary LoadGameMaps(Dictionary maps, params object[] objs) { if (!Directory.Exists(ReflectionSet.GameMapFolderPath)) return maps; string[] dlls = Directory.GetFiles(ReflectionSet.GameMapFolderPath, "*.dll"); foreach (string dll in dlls) { Assembly assembly = Assembly.LoadFrom(dll); foreach (Type type in assembly.GetTypes().AsEnumerable().Where(type => type.IsSubclassOf(typeof(GameMap)))) { if (AddAddonInstances(type, maps, (instance) => instance.Load(objs))) { AddDictionary(ModuleFilePaths, assembly, dll); } } } return maps; } /// /// 添加构造好的模组类实例到字典中 /// /// 加载的类型 /// 循环程序集的类型 /// 实例的字典 /// 加载时触发的检查方法,返回false不添加 private static bool AddAddonInstances(Type type, Dictionary dictionary, Func? isadd = null) where T : IAddon { bool isAdded = false; T? instance = (T?)Activator.CreateInstance(type); if (instance != null) { string name = instance.Name; if (!string.IsNullOrWhiteSpace(name) && (isadd == null || isadd(instance))) { dictionary.TryAdd(name.Trim(), instance); isAdded = true; } } return isAdded; } private static void AddDictionary(Dictionary dict, Assembly assembly, string dllpath) { string filename = assembly.GetName().Name?.Trim() ?? ""; if (filename != "") dict.TryAdd(filename, dllpath); } } }