155 lines
6.7 KiB
C#
155 lines
6.7 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Reflection;
|
||
using Data;
|
||
using EventWorkClass;
|
||
using Utils;
|
||
using UnityEngine;
|
||
|
||
namespace Managers
|
||
{
|
||
/// <summary>
|
||
/// 事件管理器,负责事件的加载、注册和执行。
|
||
/// 遵循单例模式,并在启动流程中扮演一个管理器角色。
|
||
/// </summary>
|
||
class EventManager : Singleton<EventManager>, ILaunchManager
|
||
{
|
||
/// <summary>
|
||
/// 存储所有已加载的事件定义,键为事件名称,值为对应的事件工作类实例。
|
||
/// </summary>
|
||
public Dictionary<string, EventWorkClassBase> EventDefs { get; private set; } = null;
|
||
|
||
/// <summary>
|
||
/// 获取当前加载步骤的描述,用于启动流程的进度显示。
|
||
/// </summary>
|
||
public string StepDescription => "正在载入事件";
|
||
|
||
/// <summary>
|
||
/// 初始化事件管理器,从定义管理器中加载所有事件定义并实例化其工作类。
|
||
/// </summary>
|
||
public void Init()
|
||
{
|
||
// 如果事件定义已经加载,则直接返回,避免重复初始化。
|
||
if (EventDefs != null)
|
||
return;
|
||
|
||
var defs = DefineManager.Instance.QueryDefinesByType<EventDef>();
|
||
EventDefs = new Dictionary<string, EventWorkClassBase>();
|
||
foreach (var def in defs)
|
||
{
|
||
if (EventDefs.ContainsKey(def.defName))
|
||
{
|
||
Debug.LogWarning($"警告:事件名称重复,已跳过加载名称为 {def.defName} 的事件定义。");
|
||
continue;
|
||
}
|
||
var eventWorker = GetAndInstantiateEventWorker(def.workClass);
|
||
if (eventWorker == null)
|
||
{
|
||
Debug.LogWarning($"警告:未能找到或实例化名称为 '{def.workClass}' 的事件工作类,已跳过加载名称为 '{def.defName}' 的事件定义。");
|
||
continue;
|
||
}
|
||
eventWorker.Init(def.value);
|
||
EventDefs.Add(def.defName, eventWorker);
|
||
}
|
||
Debug.Log($"事件管理器初始化完成,共载入 {EventDefs.Count} 个事件。");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清理事件管理器,释放所有已加载的事件定义。
|
||
/// </summary>
|
||
public void Clear()
|
||
{
|
||
EventDefs = null;
|
||
Debug.Log("事件管理器已清理。");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 执行指定名称的事件。
|
||
/// </summary>
|
||
/// <param name="eventName">要执行的事件的名称。</param>
|
||
/// <param name="dimensionID">事件执行的维度ID,如果为null,将使用当前焦点的维度ID。</param>
|
||
public void Action(string eventName, string dimensionID = null)
|
||
{
|
||
if (EventDefs == null)
|
||
{
|
||
Debug.LogError($"错误:事件管理器尚未初始化或已被清理。无法执行事件 '{eventName}'。");
|
||
return;
|
||
}
|
||
|
||
if (!EventDefs.ContainsKey(eventName))
|
||
{
|
||
Debug.LogWarning($"警告:未能找到名称为 '{eventName}' 的事件定义,已跳过执行该事件。");
|
||
return;
|
||
}
|
||
// 假设 Program.Instance 和 FocusedDimensionId 存在且可访问。
|
||
// 如果 dimensionID 为 null,则使用当前焦点维度ID。
|
||
dimensionID ??= Program.Instance.FocusedDimensionId;
|
||
EventDefs[eventName].Run(dimensionID);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据类名从指定命名空间和程序集下获取并实例化一个 <see cref="EventWorkClassBase"/> 的子类。
|
||
/// </summary>
|
||
/// <param name="className">要实例化的类的短名称(不包含命名空间)。</param>
|
||
/// <param name="targetNamespace">目标类所在的完整命名空间。</param>
|
||
/// <param name="assemblyToSearch">要搜索的程序集。如果为 null,将搜索 <see cref="EventWorkClassBase"/> 所在的程序集。</param>
|
||
/// <returns>实例化后的 <see cref="EventWorkClassBase"/> 对象,如果找不到或不符合条件则返回 null。</returns>
|
||
public static EventWorkClassBase GetAndInstantiateEventWorker(
|
||
string className,
|
||
string targetNamespace = "EventWorkClass", // 默认命名空间
|
||
Assembly assemblyToSearch = null) // 默认程序集
|
||
{
|
||
// 1. 确定要搜索的程序集。
|
||
if (assemblyToSearch == null)
|
||
{
|
||
// 默认从 EventWorkClassBase 所在的程序集查找,通常其实现类也会在这个程序集。
|
||
assemblyToSearch = typeof(EventWorkClassBase).Assembly;
|
||
}
|
||
|
||
// 2. 构造完整的类型名称。
|
||
var fullTypeName = $"{targetNamespace}.{className}";
|
||
Type targetType = null;
|
||
|
||
// 3. 尝试直接从程序集获取类型。
|
||
targetType = assemblyToSearch.GetType(fullTypeName);
|
||
|
||
// 4. 进行类型检查。
|
||
if (targetType == null)
|
||
{
|
||
Debug.LogError($"错误:在程序集 '{assemblyToSearch.FullName}' 的命名空间 '{targetNamespace}' 中未找到类 '{className}'。");
|
||
return null;
|
||
}
|
||
// 检查是否是 EventWorkClassBase 的子类。
|
||
if (!typeof(EventWorkClassBase).IsAssignableFrom(targetType))
|
||
{
|
||
Debug.LogError($"错误:类 '{fullTypeName}' 不是 '{typeof(EventWorkClassBase).FullName}' 的子类。");
|
||
return null;
|
||
}
|
||
// 检查是否可以实例化(非抽象类,非接口)。
|
||
if (targetType.IsAbstract || targetType.IsInterface)
|
||
{
|
||
Debug.LogError($"错误:类 '{fullTypeName}' 是抽象类或接口,不能直接实例化。");
|
||
return null;
|
||
}
|
||
|
||
// 5. 实例化对象。
|
||
try
|
||
{
|
||
// 使用 Activator.CreateInstance 实例化对象。它默认调用无参公共构造函数。
|
||
var instance = Activator.CreateInstance(targetType);
|
||
return instance as EventWorkClassBase;
|
||
}
|
||
catch (MissingMethodException ex)
|
||
{
|
||
Debug.LogError($"错误:类 '{fullTypeName}' 没有公共的无参构造函数。详情: {ex.Message}");
|
||
return null;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.LogError($"实例化类 '{fullTypeName}' 时发生未知错误。详情: {ex.Message}");
|
||
return null;
|
||
}
|
||
}
|
||
}
|
||
}
|