using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; using SLSFramework.General; using UMod; using UMod.Scripting; using UnityEngine; using Object = UnityEngine.Object; namespace SLSFramework.UModAssistance { public static partial class ModManager { public static ModHost LoadMod(IModInfo modInfo) { string modName = modInfo.NameInfo.ModName; ModHost host = Mod.Load(Mod.DefaultDirectory.GetModPath(modName)); LoadedMods.Add(modName, host); Debug.Log($"Mod '{modName}' loaded successfully."); return host; } } public static partial class ModManager { public static readonly SerializableDictionary LoadedMods = new SerializableDictionary(); public static readonly Dictionary> Database = new Dictionary>(); public static bool IsValidAssetName(string assetName) => Regex.IsMatch(assetName, @"^\w+_\w+_.+$"); /// /// Get asset by its name, automatically determining which mod it belongs to. /// /// Name of the asset MUST in the format "Type_ModName_AssetName" public static T GetAsset(string assetName) where T : Object { //命名符合“Type_ModName_AssetName”格式规范 if (IsValidAssetName(assetName)) { string assumeModName = assetName.Split('_')[1]; if (LoadedMods.TryGetValue(assumeModName, out ModHost host)) { T asset = host.Assets.Load(assetName); if (asset != null) { return asset; } } Debug.LogWarning($"Mod '{assumeModName}' is not loaded, or cannot get asset '{assetName}'."); } else { Debug.LogError($"Please check the name format (Type_ModName_AssetName) of this asset, '{assetName}'."); } return null; } /// /// Get asset from specified mod. /// /// Name of the mod /// Name of the asset, recommend name format "Type_ModName_AssetName" public static T GetAsset(string modName, string assetName) where T : Object { if (!IsValidAssetName(assetName)) { Debug.LogWarning($"Asset name '{assetName}' does not follow the 'Type_ModName_AssetName' format."); } if (LoadedMods.TryGetValue(modName, out ModHost host)) { return host.Assets.Load(assetName); } Debug.LogWarning($"Mod '{modName}' is not loaded, or cannot get asset '{assetName}'."); return null; } public static bool TryGetData(string assetName, out T data) where T : ScriptableObject { return (data = GetData(assetName)) != null; } /// /// Get data (Scriptable Objects, loaded by data manifest) from the database by its name and type. /// /// Name of the asset public static T GetData(string assetName) where T : ScriptableObject { if (!IsValidAssetName(assetName)) { Debug.LogWarning($"Asset name '{assetName}' does not follow the 'Type_ModName_AssetName' format."); } Type assetType = typeof(T); if (Database.TryGetValue(assetType, out Dictionary assets)) { if (assets.TryGetValue(assetName, out ScriptableObject asset)) { return asset as T; } else { Debug.LogWarning($"Data Asset '{assetName}' of type '{assetType}' not found in database."); return null; } } else { Debug.LogWarning($"No assets of type '{assetType}' found in database."); return null; } } } public partial class ModManager { public static readonly Dictionary TypeRegistry = new Dictionary(); /// /// 从一个已加载的Mod中,查找所有指定基类的子类,并将其注册到全局字典中。 /// /// 已加载的ModHost对象 /// 要查找的基类,例如 typeof(CardLogicBase) public static void RegisterTypesFromMod(ModHost host, Type baseType) { if (host?.ScriptDomain == null) { return; } int countBefore = TypeRegistry.Count; // 遍历Mod包含的所有程序集(DLLs) foreach (ScriptAssembly assembly in host.ScriptDomain.Assemblies) { // assembly.RawAssembly 是 uMod 封装的真实 System.Reflection.Assembly 对象 var typesInAssembly = assembly.RawAssembly.GetTypes() .Where(t => baseType.IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface); foreach (var type in typesInAssembly) { if (!TypeRegistry.ContainsKey(type.Name)) { TypeRegistry.Add(type.Name, type); Debug.Log($"Registered script type '{type.FullName}' from mod '{host.CurrentMod.NameInfo.ModName}'."); } else { // 处理命名冲突:如果不同Mod中存在同名的类,后加载的会被忽略 Debug.LogWarning($"Duplicate script type name found: '{type.Name}'. The existing type from assembly '{TypeRegistry[type.Name].Assembly.FullName}' will be kept."); } } } int countAfter = TypeRegistry.Count; if (countAfter > countBefore) { Debug.Log($"Registered {countAfter - countBefore} new script types deriving from '{baseType.Name}' from mod '{host.CurrentMod.NameInfo.ModName}'."); } } public static Type GetType(string typeName) { if (TypeRegistry.TryGetValue(typeName, out Type type)) { return type; } Debug.LogWarning($"Type '{typeName}' not found in TypeRegistry."); return null; } public static T CreateInstance(string typeName) where T : class { Type type = GetType(typeName); if (type != null && typeof(T).IsAssignableFrom(type)) { return Activator.CreateInstance(type) as T; } Debug.LogWarning($"Cannot create instance of type '{typeName}' as it is not found or not assignable to '{typeof(T).Name}'."); return null; } public static T CreateInstance(string typeName, params object[] parameters) where T : class { Type type = GetType(typeName); if (type != null && typeof(T).IsAssignableFrom(type)) { return Activator.CreateInstance(type, parameters) as T; } Debug.LogWarning($"Cannot create instance of type '{typeName}' as it is not found or not assignable to '{typeof(T).Name}'."); return null; } } }