(client) feat:添加事件定义,定义部分怪物
This commit is contained in:
@ -1,75 +1,154 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Data;
|
||||
using Entity;
|
||||
using Prefab;
|
||||
using UnityEngine;
|
||||
using EventWorkClass;
|
||||
using Utils;
|
||||
using Random = System.Random;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Managers
|
||||
{
|
||||
class EventManager:Singleton<EventManager>,ILaunchManager
|
||||
/// <summary>
|
||||
/// 事件管理器,负责事件的加载、注册和执行。
|
||||
/// 遵循单例模式,并在启动流程中扮演一个管理器角色。
|
||||
/// </summary>
|
||||
class EventManager : Singleton<EventManager>, ILaunchManager
|
||||
{
|
||||
private static Random _random = new();
|
||||
public EventDef[] EventDefs { get; private set; }
|
||||
/// <summary>
|
||||
/// 存储所有已加载的事件定义,键为事件名称,值为对应的事件工作类实例。
|
||||
/// </summary>
|
||||
public Dictionary<string, EventWorkClassBase> EventDefs { get; private set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前加载步骤的描述,用于启动流程的进度显示。
|
||||
/// </summary>
|
||||
public string StepDescription => "正在载入事件";
|
||||
|
||||
/// <summary>
|
||||
/// 初始化事件管理器,从定义管理器中加载所有事件定义并实例化其工作类。
|
||||
/// </summary>
|
||||
public void Init()
|
||||
{
|
||||
if(EventDefs!=null)
|
||||
// 如果事件定义已经加载,则直接返回,避免重复初始化。
|
||||
if (EventDefs != null)
|
||||
return;
|
||||
EventDefs = DefineManager.Instance.QueryDefinesByType<EventDef>();
|
||||
|
||||
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("事件管理器已清理。");
|
||||
}
|
||||
|
||||
public static void ExecuteEvent(EventDef eventDef)
|
||||
/// <summary>
|
||||
/// 执行指定名称的事件。
|
||||
/// </summary>
|
||||
/// <param name="eventName">要执行的事件的名称。</param>
|
||||
/// <param name="dimensionID">事件执行的维度ID,如果为null,将使用当前焦点的维度ID。</param>
|
||||
public void Action(string eventName, string dimensionID = null)
|
||||
{
|
||||
if(eventDef == null)
|
||||
if (EventDefs == null)
|
||||
{
|
||||
Debug.LogError($"错误:事件管理器尚未初始化或已被清理。无法执行事件 '{eventName}'。");
|
||||
return;
|
||||
if (eventDef.hediffEvent != null)
|
||||
{
|
||||
var entityList = EntityManage.Instance.FindEntitiesByFaction(Program.Instance.FocusedDimensionId,
|
||||
eventDef.hediffEvent.affiliation.defName);
|
||||
List<Entity.Entity> filteredEntitiesTraditional = new();
|
||||
foreach (var prefab in entityList)
|
||||
{
|
||||
var entity = prefab.entity;
|
||||
if (entity is Character || entity is Monster)
|
||||
{
|
||||
filteredEntitiesTraditional.Add(entity);
|
||||
}
|
||||
}
|
||||
var selectedElements = SelectRandomElements_FisherYates(filteredEntitiesTraditional, eventDef.hediffEvent.specificPawnCount);
|
||||
foreach (var selectedElement in selectedElements)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!EventDefs.ContainsKey(eventName))
|
||||
{
|
||||
Debug.LogWarning($"警告:未能找到名称为 '{eventName}' 的事件定义,已跳过执行该事件。");
|
||||
return;
|
||||
}
|
||||
// 假设 Program.Instance 和 FocusedDimensionId 存在且可访问。
|
||||
// 如果 dimensionID 为 null,则使用当前焦点维度ID。
|
||||
dimensionID ??= Program.Instance.FocusedDimensionId;
|
||||
EventDefs[eventName].Run(dimensionID);
|
||||
}
|
||||
public static List<T> SelectRandomElements_FisherYates<T>(List<T> sourceList, int count)
|
||||
|
||||
/// <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) // 默认程序集
|
||||
{
|
||||
if (sourceList == null) throw new ArgumentNullException(nameof(sourceList));
|
||||
if (count < 0) throw new ArgumentOutOfRangeException(nameof(count), "Count cannot be negative.");
|
||||
if (count == 0) return new List<T>();
|
||||
if (count >= sourceList.Count) return new List<T>(sourceList); // 如果n大于等于列表大小,则返回所有元素副本
|
||||
|
||||
List<T> result = new List<T>(count); // 预分配容量
|
||||
List<T> temp = new List<T>(sourceList); // 创建一个副本以避免修改原始列表
|
||||
|
||||
int n = temp.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
// 1. 确定要搜索的程序集。
|
||||
if (assemblyToSearch == null)
|
||||
{
|
||||
int k = _random.Next(i, n);
|
||||
result.Add(temp[k]);
|
||||
(temp[k], temp[i]) = (temp[i], temp[k]);
|
||||
// 默认从 EventWorkClassBase 所在的程序集查找,通常其实现类也会在这个程序集。
|
||||
assemblyToSearch = typeof(EventWorkClassBase).Assembly;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// 2. 构造完整的类型名称。
|
||||
string 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 实例化对象。它默认调用无参公共构造函数。
|
||||
object 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user