Files
Gen_Hack-and-Slash-Roguelit…/Client/Assets/Scripts/Managers/DefineManager.cs

378 lines
13 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.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Data;
using UnityEngine;
using Utils;
namespace Managers
{
public class DefineManager : Singleton<DefineManager>
{
private static readonly string[] dataSetFilePath = { "Data", "Mods" };
public Dictionary<string, Dictionary<string, Define>> defines = new();
public Dictionary<string, DefinePack> packs = new();
public Dictionary<string, List<Define>> anonymousDefines = new();
/// <summary>
/// 初始化定义管理器,加载所有定义包并构建定义字典。
/// </summary>
/// <remarks>
/// 该方法执行以下操作:
/// 1. 获取指定路径下的所有子文件夹,每个子文件夹代表一个定义包。
/// 2. 遍历每个定义包,尝试加载其中的定义数据。
/// 3. 将加载的定义数据按类型分类,并存储到定义字典中。
/// </remarks>
public void Init()
{
if (packs.Count > 0)
return;
// 单线程
var packFolder = Configs.ConfigProcessor.GetSubFolders(new(dataSetFilePath));
foreach (var folder in packFolder)
{
var pack = new DefinePack();
if (pack.LoadPack(folder))
{
packs.Add(pack.packID, pack);
}
}
Dictionary<Type, FieldInfo[]> fieldCache = new();
// 需要链接的定义、需要链接的字段、链接信息
List<Tuple<Define, FieldInfo, Define>> defineCache = new();
void ProcessDefine(Define def)
{
if (def == null || def.isReferene)
return;
// 如果字段信息已经缓存,则直接使用缓存
if (!fieldCache.TryGetValue(def.GetType(), out var defineFields))
{
// 获取所有字段类型为 Define 或其派生类型的字段
defineFields = def.GetType()
.GetFields(BindingFlags.Public | BindingFlags.Instance)
.Where(field => typeof(Define).IsAssignableFrom(field.FieldType))
.ToArray();
// 缓存字段信息
fieldCache[def.GetType()] = defineFields;
}
foreach (var defineField in defineFields)
{
var defRef = (Define)defineField.GetValue(def);
if (defRef == null)
continue;
if (defRef.isReferene)
{
defineCache.Add(new Tuple<Define, FieldInfo, Define>(def, defineField, defRef));
}
else
{
if (string.IsNullOrEmpty(defRef.defName))
{
var typeName = defRef.GetType().Name;
if (!anonymousDefines.ContainsKey(typeName))
anonymousDefines.Add(typeName, new List<Define>());
anonymousDefines[typeName].Add(defRef);
}
ProcessDefine(defRef);
}
}
}
foreach (var pack in packs)
{
foreach (var (typeName, defList) in pack.Value.defines)
{
if (!defines.ContainsKey(typeName))
defines[typeName] = new Dictionary<string, Define>();
foreach (var def in defList)
{
defines[typeName][def.defName] = def;
ProcessDefine(def);
}
}
}
foreach (var defRef in defineCache)
{
if (defRef.Item1 == null)
{
Debug.LogError("defRef.Item1 为 null");
continue;
}
if (defRef.Item2 == null)
{
Debug.LogError("defRef.Item2 为 null");
continue;
}
var value = FindDefine(defRef.Item3.description, defRef.Item3.defName);
if (value == null)
{
Debug.LogError($"FindDefine 返回 null: description={defRef.Item3.description}, defName={defRef.Item3.defName}");
continue;
}
try
{
defRef.Item2.SetValue(defRef.Item1, value);
}
catch (Exception ex)
{
Debug.LogError($"SetValue 出错: {ex.Message}");
}
}
}
public void Reload()
{
defines.Clear();
packs.Clear();
anonymousDefines.Clear();
Init();
}
/// <summary>
/// 查找指定定义类型的定义名对应的 Define 对象。
/// </summary>
/// <param name="defineType">定义类型</param>
/// <param name="defineName">定义名</param>
/// <returns>如果找到,返回 Define 对象;否则返回 null。</returns>
public Define FindDefine(string defineType, string defineName)
{
if (defines.TryGetValue(defineType, out var typeDict))
{
if (typeDict.TryGetValue(defineName, out var define))
{
return define;
}
}
return null;
}
/// <summary>
/// 使用模板查找并返回指定类型的 Define 对象。
/// </summary>
/// <typeparam name="T">目标类型</typeparam>
/// <param name="defineName">定义名</param>
/// <returns>如果找到,返回转换为目标类型的 Define 对象;否则返回 null。</returns>
public T FindDefine<T>(string defineName) where T : Define
{
foreach (var typeDict in defines.Values)
{
if (typeDict.TryGetValue(defineName, out var define) && define is T result)
{
return result;
}
}
return null;
}
public DefinePack GetDefinePackage(Define define)
{
if (define == null || define.packID == null)
return null;
packs.TryGetValue(define.packID, out var pack);
return pack;
}
public string GetDefinePackageName(Define define)
{
return GetDefinePackage(define)?.Name;
}
public string GetPackagePath(string packID)
{
if (packs.TryGetValue(packID, out var pack))
{
return pack.packRootPath;
}
return null;
}
public Define[] GetAllDefine()
{
List<Define> defineList = new();
foreach (var define in defines.Values)
{
defineList.AddRange(define.Values);
}
foreach (var anonymousDefine in anonymousDefines)
{
defineList.AddRange(anonymousDefine.Value);
}
return defineList.ToArray();
}
/// <summary>
/// 查询指定类型下的所有 Define 对象。(包括匿名定义)
/// </summary>
/// <param name="defineType">定义类型(外层字典的键)。</param>
/// <returns>该类型下的 Define 数组,如果未找到则返回 null。</returns>
public Define[] QueryDefinesByType(string defineType)
{
if (string.IsNullOrEmpty(defineType))
{
Debug.LogError("查询失败:定义类型参数不能为空!");
return null;
}
List<Define> result = new List<Define>();
// 从命名定义中查询
if (defines.TryGetValue(defineType, out var namedDefinitions))
{
result.AddRange(namedDefinitions.Values);
}
// 从匿名定义中查询
if (anonymousDefines.TryGetValue(defineType, out var anonymousDefinitionList))
{
result.AddRange(anonymousDefinitionList);
}
// 如果结果为空,则返回 null
if (result.Count == 0)
{
Debug.LogWarning($"查询失败:未找到定义类型 '{defineType}'");
return null;
}
return result.ToArray();
}
/// <summary>
/// 查询指定类型下的所有 Define 对象,并尝试转换为目标类型。(包括匿名定义)
/// </summary>
/// <typeparam name="T">目标类型。</typeparam>
/// <returns>转换后的目标类型数组,如果未找到或转换失败则返回 null。</returns>
public T[] QueryDefinesByType<T>()
{
var defineType = typeof(T).Name;
List<Define> allDefines = QueryDefinesByType(defineType)?.ToList();
if (allDefines == null || allDefines.Count == 0)
{
return null;
}
try
{
// 尝试将所有 Define 对象转换为目标类型 T
var result = new List<T>();
foreach (var item in allDefines)
{
if (item is T converted)
{
result.Add(converted);
}
else
{
Debug.LogError($"类型转换失败:无法将 {item.GetType().Name} 转换为 {typeof(T).Name}");
return null;
}
}
return result.ToArray();
}
catch (Exception ex)
{
Debug.LogError($"类型转换失败:从 Define 转换为 {typeof(T).Name} 时出错。错误信息:{ex.Message}");
return null;
}
}
/// <summary>
/// 查询指定类型下的所有 Define 对象(仅包含命名定义,不包括匿名定义)。
/// </summary>
/// <param name="defineType">定义类型(外层字典的键)。</param>
/// <returns>该类型下的 Define 数组,如果未找到则返回 null。</returns>
public Define[] QueryNamedDefinesByType(string defineType)
{
if (string.IsNullOrEmpty(defineType))
{
Debug.LogError("查询失败:定义类型参数不能为空!");
return null;
}
List<Define> result = new List<Define>();
// 仅从命名定义中查询
if (defines.TryGetValue(defineType, out var namedDefinitions))
{
result.AddRange(namedDefinitions.Values);
}
// 如果结果为空,则返回 null
if (result.Count == 0)
{
Debug.LogWarning($"查询失败:未找到定义类型 '{defineType}' 的命名定义");
return null;
}
return result.ToArray();
}
/// <summary>
/// 查询指定类型下的所有 Define 对象,并尝试转换为目标类型(仅包含命名定义,不包括匿名定义)。
/// </summary>
/// <typeparam name="T">目标类型。</typeparam>
/// <returns>转换后的目标类型数组,如果未找到或转换失败则返回 null。</returns>
public T[] QueryNamedDefinesByType<T>()
{
var defineType = typeof(T).Name;
List<Define> allDefines = QueryNamedDefinesByType(defineType)?.ToList();
if (allDefines == null || allDefines.Count == 0)
{
return null;
}
try
{
// 尝试将所有 Define 对象转换为目标类型 T
var result = new List<T>();
foreach (var item in allDefines)
{
if (item is T converted)
{
result.Add(converted);
}
else
{
Debug.LogError($"类型转换失败:无法将 {item.GetType().Name} 转换为 {typeof(T).Name}");
return null;
}
}
return result.ToArray();
}
catch (Exception ex)
{
Debug.LogError($"类型转换失败:从 Define 转换为 {typeof(T).Name} 时出错。错误信息:{ex.Message}");
return null;
}
}
public override string ToString()
{
if (packs == null || packs.Count == 0)
{
return "No packs available"; // 如果集合为空或为 null返回默认信息
}
var result = new System.Text.StringBuilder();
foreach (var definePack in packs)
{
result.AppendLine(definePack.ToString()); // 每个元素占一行
}
return result.ToString();
}
}
}