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

155 lines
6.7 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.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;
}
}
}
}