279 lines
11 KiB
C#
279 lines
11 KiB
C#
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("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<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();
|
||
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("收集 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
|
||
} |