Files
Continentis/Assets/Scripts/Mod/Manifests/ModManifest.cs
SoulliesOfficial c3b1561375 更新
2026-04-01 12:23:27 -04:00

294 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<string> keywordDataIDList = new List<string>();
[BoxGroup("资产列表")]
[LabelText("Card Data ID 列表")]
[ListDrawerSettings(ShowIndexLabels = false)]
public List<string> cardDataIDList = new List<string>();
[BoxGroup("资产列表")]
[LabelText("Character Data ID 列表")]
[ListDrawerSettings(ShowIndexLabels = false)]
public List<string> characterDataIDList = new List<string>();
[BoxGroup("资产列表")]
[LabelText("Equipment Data ID 列表")]
[ListDrawerSettings(ShowIndexLabels = false)]
public List<string> equipmentDataIDList = new List<string>();
[BoxGroup("资产列表")]
[LabelText("CombatNode Data ID 列表")]
[ListDrawerSettings(ShowIndexLabels = false)]
public List<string> combatDataIDList = new List<string>();
[BoxGroup("资产列表")]
[LabelText("HUD Data ID 列表")]
[ListDrawerSettings(ShowIndexLabels = false)]
public List<string> hudDataIDList = new List<string>();
[BoxGroup("本地化")]
[LabelText("本地化文件列表")]
[ListDrawerSettings(ShowIndexLabels = false)]
public List<TextAsset> localizationFiles = new List<TextAsset>();
public void SaveToDatabase(ModHost host)
{
SaveIDListToDatabase<KeywordData>(host, keywordDataIDList);
SaveIDListToDatabase<CardData>(host, cardDataIDList);
SaveIDListToDatabase<CharacterData>(host, characterDataIDList);
SaveIDListToDatabase<EquipmentData>(host, equipmentDataIDList);
SaveIDListToDatabase<CombatNodeData>(host, combatDataIDList);
SaveIDListToDatabase<HUDData>(host, hudDataIDList);
// 加载此 Mod 的 EditorBaseCollection含意图图标 Sprite 等运行时资源)
if (!string.IsNullOrEmpty(editorBaseCollectionID))
{
EditorBaseCollection coll = host.Assets.Load<EditorBaseCollection>(editorBaseCollectionID);
if (coll != null)
{
ModManager.Database.TryAdd(typeof(EditorBaseCollection), new Dictionary<string, ScriptableObject>());
if (!ModManager.Database[typeof(EditorBaseCollection)].TryAdd(editorBaseCollectionID, coll))
{
Debug.LogWarning($"[ModManifest] EditorBaseCollection '{editorBaseCollectionID}' 已存在于 Database跳过重复添加。");
}
}
else
{
Debug.LogWarning($"[ModManifest] EditorBaseCollection '{editorBaseCollectionID}' 加载失败,请确认资产已正确打包进 Mod。");
}
}
}
private void SaveIDListToDatabase<T>(ModHost host, List<string> idList) where T : ScriptableObject
{
ModManager.Database.TryAdd(typeof(T), new Dictionary<string, ScriptableObject>());
foreach (var assetName in idList)
{
T data = host.Assets.Load<T>(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<KeywordData>();
EditorUtility.SetDirty(this);
}
[FoldoutGroup("工具/分别收集")]
[Button("收集 CardData")]
private void CollectAllCardData()
{
cardDataIDList = CollectData<CardData>();
EditorUtility.SetDirty(this);
}
[FoldoutGroup("工具/分别收集")]
[Button("收集 CharacterData")]
private void CollectAllCharacterData()
{
characterDataIDList = CollectData<CharacterData>();
EditorUtility.SetDirty(this);
}
[FoldoutGroup("工具/分别收集")]
[Button("收集 EquipmentData")]
private void CollectAllEquipmentData()
{
equipmentDataIDList = CollectData<EquipmentData>();
EditorUtility.SetDirty(this);
}
[FoldoutGroup("工具/分别收集")]
[Button("收集 CombatNodeData")]
private void CollectAllCombatData()
{
combatDataIDList = CollectData<CombatNodeData>();
EditorUtility.SetDirty(this);
}
[FoldoutGroup("工具/分别收集")]
[Button("收集 HUDData")]
private void CollectAllHUDData()
{
hudDataIDList = CollectData<HUDData>();
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<string> CollectData<T>() where T : ScriptableObject
{
if (string.IsNullOrEmpty(inEditorModFolder)) return new List<string>();
string inEditorModPath = "Assets/Mods/" + inEditorModFolder;
string dataTypeName = typeof(T).Name;
string[] guids = UnityEditor.AssetDatabase.FindAssets($"t:{dataTypeName}", new[] { inEditorModPath });
List<string> collectedDataIDList = new List<string>();
foreach (string guid in guids)
{
string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid);
T data = UnityEditor.AssetDatabase.LoadAssetAtPath<T>(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<TextAsset> CollectLocalizations()
{
if (string.IsNullOrEmpty(inEditorModFolder)) return new List<TextAsset>();
string inEditorModPath = "Assets/Mods/" + inEditorModFolder;
string dataTypeName = nameof(TextAsset);
string[] guids = UnityEditor.AssetDatabase.FindAssets($"t:{dataTypeName}", new[] { inEditorModPath });
List<TextAsset> collectedTextAssets = new List<TextAsset>();
foreach (string guid in guids)
{
string path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid);
string assetFileName = System.IO.Path.GetFileNameWithoutExtension(path);
TextAsset data = UnityEditor.AssetDatabase.LoadAssetAtPath<TextAsset>(path);
if (assetFileName.Contains("Localization") || path.Contains("Localization"))
{
collectedTextAssets.Add(data);
Debug.Log($"[ModManifest] 已收集本地化文本: {assetFileName}");
}
}
Debug.Log($"[ModManifest] 已收集 {collectedTextAssets.Count} 个本地化文件。");
return collectedTextAssets;
}
}
#endif
}