using System; using System.Collections.Generic; using System.Text.RegularExpressions; using Continentis.MainGame; using Continentis.MainGame.Base; using Continentis.MainGame.Card; using Continentis.MainGame.Character; using Continentis.MainGame.Equipment; using Continentis.MainGame.UI; using SLSFramework.UModAssistance; using Sirenix.OdinInspector; using UMod; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace Continentis.Mods { [CreateAssetMenu(fileName = "ModManifest", menuName = "Continentis/Mod/Manifest", order = 1)] public partial class ModManifest : ScriptableObject { [FoldoutGroup("Mod 基础信息")] [LabelText("Mod 名称")] public string modDisplayName; [FoldoutGroup("Mod 基础信息")] [LabelText("Mod 版本")] public string modVersion = "1.0.0"; [FoldoutGroup("Mod 基础信息")] [LabelText("作者")] public string modAuthor; [FoldoutGroup("Mod 基础信息")] [LabelText("描述"), MultiLineProperty(3)] public string modDescription; [FoldoutGroup("Mod 基础信息")] [LabelText("最低游戏版本")] public string minimumGameVersion = "0.1.0"; [BoxGroup("Mod 配置")] [LabelText("编辑器内 Mod 文件夹名")] public string inEditorModFolder; [BoxGroup("资产列表")] [LabelText("EditorBaseCollection ID")] [Tooltip("此 Mod 的 EditorBaseCollection 资产名,命名规范:ModName_EditorBaseCollection\n留空则跳过加载。")] public string editorBaseCollectionID; [BoxGroup("资产列表")] [LabelText("Keyword Data ID 列表")] [ListDrawerSettings(ShowIndexLabels = false)] public List keywordDataIDList = new List(); [BoxGroup("资产列表")] [LabelText("Card Data ID 列表")] [ListDrawerSettings(ShowIndexLabels = false)] public List cardDataIDList = new List(); [BoxGroup("资产列表")] [LabelText("Character Data ID 列表")] [ListDrawerSettings(ShowIndexLabels = false)] public List characterDataIDList = new List(); [BoxGroup("资产列表")] [LabelText("Equipment Data ID 列表")] [ListDrawerSettings(ShowIndexLabels = false)] public List equipmentDataIDList = new List(); [BoxGroup("资产列表")] [LabelText("CombatNode Data ID 列表")] [ListDrawerSettings(ShowIndexLabels = false)] public List combatDataIDList = new List(); [BoxGroup("资产列表")] [LabelText("HUD Data ID 列表")] [ListDrawerSettings(ShowIndexLabels = false)] public List hudDataIDList = new List(); [BoxGroup("本地化")] [LabelText("本地化文件列表")] [ListDrawerSettings(ShowIndexLabels = false)] public List localizationFiles = new List(); public void SaveToDatabase(ModHost host) { SaveIDListToDatabase(host, keywordDataIDList); SaveIDListToDatabase(host, cardDataIDList); SaveIDListToDatabase(host, characterDataIDList); SaveIDListToDatabase(host, equipmentDataIDList); SaveIDListToDatabase(host, combatDataIDList); SaveIDListToDatabase(host, hudDataIDList); // 加载此 Mod 的 EditorBaseCollection(含意图图标 Sprite 等运行时资源) if (!string.IsNullOrEmpty(editorBaseCollectionID)) { EditorBaseCollection coll = host.Assets.Load(editorBaseCollectionID); if (coll != null) { ModManager.Database.TryAdd(typeof(EditorBaseCollection), new Dictionary()); if (!ModManager.Database[typeof(EditorBaseCollection)].TryAdd(editorBaseCollectionID, coll)) { Debug.LogWarning($"[ModManifest] EditorBaseCollection '{editorBaseCollectionID}' 已存在于 Database,跳过重复添加。"); } } else { Debug.LogWarning($"[ModManifest] EditorBaseCollection '{editorBaseCollectionID}' 加载失败,请确认资产已正确打包进 Mod。"); } } } private void SaveIDListToDatabase(ModHost host, List idList) where T : ScriptableObject { ModManager.Database.TryAdd(typeof(T), new Dictionary()); foreach (var assetName in idList) { T data = host.Assets.Load(assetName); if (data != null) { if (!ModManager.Database[typeof(T)].TryAdd(assetName, data)) { Debug.LogWarning($"Asset '{assetName}' already exists in the database. Skipping addition."); } } } } } #if UNITY_EDITOR public partial class ModManifest { [BoxGroup("工具")] [Button("🚀 一键收集所有内容", ButtonSizes.Large)] [GUIColor(0.4f, 0.8f, 1f)] private void CollectAllContent() { if (string.IsNullOrEmpty(inEditorModFolder)) { Debug.LogError("[ModManifest] 必须先配置 '编辑器内 Mod 文件夹名' (inEditorModFolder) 才能进行收集!"); return; } CollectAllKeywordData(); CollectAllCardData(); CollectAllCharacterData(); CollectAllEquipmentData(); CollectAllCombatData(); CollectAllHUDData(); CollectAllLocalizations(); CollectEditorBaseCollection(); Debug.Log("[ModManifest] ⚡ 所有内容一键收集完成!"); } [FoldoutGroup("工具/分别收集", expanded: false)] [Button("收集 KeywordData")] private void CollectAllKeywordData() { keywordDataIDList = CollectData(); EditorUtility.SetDirty(this); } [FoldoutGroup("工具/分别收集")] [Button("收集 CardData")] private void CollectAllCardData() { cardDataIDList = CollectData(); EditorUtility.SetDirty(this); } [FoldoutGroup("工具/分别收集")] [Button("收集 CharacterData")] private void CollectAllCharacterData() { characterDataIDList = CollectData(); EditorUtility.SetDirty(this); } [FoldoutGroup("工具/分别收集")] [Button("收集 EquipmentData")] private void CollectAllEquipmentData() { equipmentDataIDList = CollectData(); EditorUtility.SetDirty(this); } [FoldoutGroup("工具/分别收集")] [Button("收集 CombatNodeData")] private void CollectAllCombatData() { combatDataIDList = CollectData(); EditorUtility.SetDirty(this); } [FoldoutGroup("工具/分别收集")] [Button("收集 HUDData")] private void CollectAllHUDData() { hudDataIDList = CollectData(); EditorUtility.SetDirty(this); } [FoldoutGroup("工具/分别收集")] [Button("收集 本地化文件")] private void CollectAllLocalizations() { localizationFiles = CollectLocalizations(); EditorUtility.SetDirty(this); } [FoldoutGroup("工具/分别收集")] [Button("收集 EditorBaseCollection")] private void CollectEditorBaseCollection() { if (string.IsNullOrEmpty(inEditorModFolder)) { Debug.LogWarning("[ModManifest] 请先配置 inEditorModFolder。"); return; } string modPath = "Assets/Mods/" + inEditorModFolder; string[] guids = UnityEditor.AssetDatabase.FindAssets($"t:{nameof(EditorBaseCollection)}", new[] { modPath }); if (guids.Length == 0) { Debug.LogWarning($"[ModManifest] 在 {modPath} 中未找到 EditorBaseCollection。"); editorBaseCollectionID = string.Empty; } else { string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[0]); editorBaseCollectionID = System.IO.Path.GetFileNameWithoutExtension(path); Debug.Log($"[ModManifest] EditorBaseCollection 已收集:{editorBaseCollectionID}"); } EditorUtility.SetDirty(this); } private List CollectData() where T : ScriptableObject { if (string.IsNullOrEmpty(inEditorModFolder)) return new List(); string inEditorModPath = "Assets/Mods/" + inEditorModFolder; string dataTypeName = typeof(T).Name; string[] guids = UnityEditor.AssetDatabase.FindAssets($"t:{dataTypeName}", new[] { inEditorModPath }); List collectedDataIDList = new List(); foreach (string guid in guids) { string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid); T data = UnityEditor.AssetDatabase.LoadAssetAtPath(path); string assetFileName = System.IO.Path.GetFileNameWithoutExtension(path); if (!Regex.IsMatch(assetFileName, @"^\w+_\w+_.+$")) { Debug.LogWarning($"[ModManifest] 资产命名可能不符合 'Type_ModName_AssetName' 标准格式: {assetFileName}"); } if (data != null) { collectedDataIDList.Add(assetFileName); } } Debug.Log($"[ModManifest] 已收集 {collectedDataIDList.Count} 个 {typeof(T).Name}。"); return collectedDataIDList; } private List CollectLocalizations() { if (string.IsNullOrEmpty(inEditorModFolder)) return new List(); string inEditorModPath = "Assets/Mods/" + inEditorModFolder; string dataTypeName = nameof(TextAsset); string[] guids = UnityEditor.AssetDatabase.FindAssets($"t:{dataTypeName}", new[] { inEditorModPath }); List collectedTextAssets = new List(); foreach (string guid in guids) { string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid); string assetFileName = System.IO.Path.GetFileNameWithoutExtension(path); TextAsset data = UnityEditor.AssetDatabase.LoadAssetAtPath(path); if (assetFileName.Contains("Localization") || path.Contains("Localization")) { collectedTextAssets.Add(data); Debug.Log($"[ModManifest] 已收集本地化文本: {assetFileName}"); } } Debug.Log($"[ModManifest] 已收集 {collectedTextAssets.Count} 个本地化文件。"); return collectedTextAssets; } } #endif }