Files

241 lines
12 KiB
C#
Raw Permalink 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.Linq;
using Data;
using UnityEngine;
using Utils;
using System.Threading.Tasks; // 导入异步命名空间
namespace Managers
{
/// <summary>
/// 阵营管理器,负责管理游戏中的所有阵营定义及其相互关系。
/// 继承自 <see cref="Utils.Singleton{T}" /> ,确保全局只有一个实例。
/// </summary>
public class AffiliationManager : Singleton<AffiliationManager>, ILaunchManager
{
/// <summary>
/// 存储所有已加载的阵营定义,键为阵营的唯一名称,值为对应的 <see cref="AffiliationDef" /> 对象。
/// </summary>
private readonly Dictionary<string, AffiliationDef> _affiliations = new();
public bool Completed { get; set; } // Renamed from Loaded to Completed
public string StepDescription => "正在区分派系";
private string _playerAffiliation;
public string PlayerAffiliation
{
get
{
if (string.IsNullOrEmpty(_playerAffiliation))
{
_playerAffiliation = Configs.ConfigManager.Instance.GetValue<string>("playerAffiliation");
}
return _playerAffiliation;
}
}
/// <summary>
/// 初始化阵营管理器,从 <see cref="DefineManager" /> 加载所有 <see cref="AffiliationDef" />。
/// 在首次需要阵营数据时调用。
/// </summary>
public async Task Init() // Changed to async Task
{
// 如果管理器已经初始化完成,则直接返回,避免重复加载。
if (Completed) return;
var affiliationList = DefineManager.Instance.QueryDefinesByType<AffiliationDef>();
if (affiliationList == null || affiliationList.Length == 0)
{
// 记录警告,说明未能加载任何阵营定义。
Debug.LogWarning("未找到任何 AffiliationDef 或阵营列表为空。");
Completed = true; // 即使没有加载到,也标记为完成,避免后续重复尝试
await Task.CompletedTask; // 返回一个已完成的Task
return;
}
foreach (var affiliation in affiliationList)
// 尝试将阵营定义添加到字典中。如果名称已存在,则记录错误。
if (!_affiliations.TryAdd(affiliation.defName, affiliation))
Debug.LogError($"添加阵营 '{affiliation.defName}' 失败。已存在同名阵营。");
// 验证并修复加载后的阵营关系,以确保数据一致性。
ValidateAndFixRelationships();
Completed = true; // 标记为完成
await Task.CompletedTask; // 返回一个已完成的Task
}
/// <summary>
/// 清理所有已加载的阵营定义。
/// 在游戏会话结束或需要重新加载所有定义时调用。
/// </summary>
public void Clear()
{
_affiliations.Clear();
Completed = false; // 清理后标记为未完成下次需要时可重新Init
_playerAffiliation = null;
}
/// <summary>
/// 根据阵营定义名称获取其默认名称。
/// </summary>
/// <param name="defName">阵营的定义名称。</param>
/// <returns>阵营的默认名称或传入的defName若未找到并给出警告。</returns>
public string GetAffiliationName(string defName)
{
if (_affiliations.TryGetValue(defName, out var affiliationDef))
{
return affiliationDef.defName;
}
Debug.LogWarning($"获取阵营名称失败: 阵营 '{defName}' 不存在。");
// 根据实际需求,这里可以抛出异常、返回空字符串或返回 defName 本身。
// 暂时返回 defName但警告。
return defName;
}
/// <summary>
/// 获取两个阵营间的关系。
/// </summary>
/// <param name="affiliation1">第一个阵营的 <see cref="AffiliationDef" /> 对象。</param>
/// <param name="affiliation2">第二个阵营的 <see cref="AffiliationDef" /> 对象。</param>
/// <returns>两个阵营之间的 <see cref="Relation" />。</returns>
public Relation GetRelation(AffiliationDef affiliation1, AffiliationDef affiliation2)
{
// 如果任一阵营定义为空,则返回中立关系。
if (affiliation1 == null || affiliation2 == null) return Relation.Neutral;
return GetRelation(affiliation1.defName, affiliation2.defName);
}
public Relation GetRelation(Entity.Entity entity1, Entity.Entity entity2)
{
// 如果任一实体为空,则返回中立关系。
if (entity1 == null || entity2 == null) return Relation.Neutral;
return GetRelation(entity1.affiliation, entity2.affiliation);
}
/// <summary>
/// 获取两个阵营名称之间的关系。
/// </summary>
/// <param name="factionName1">第一个阵营的名称。</param>
/// <param name="factionName2">第二个阵营的名称。</param>
/// <returns>两个阵营之间的 <see cref="Relation" />。</returns>
public Relation GetRelation(string factionName1, string factionName2)
{
// 如果查询的是同一个阵营,则默认为友好关系。
if (factionName1 == factionName2) return Relation.Friendly;
// 获取第一个阵营的定义。如果不存在,则返回中立关系。
// (无法通过一个不存在的阵营来判断与其相关的任何关系)。
if (!_affiliations.TryGetValue(factionName1, out var faction1))
{
return Relation.Neutral;
}
// 获取第二个阵营的定义。如果不存在,则使用第一个阵营的默认关系。
// (如果只有第二个阵营不存在,第一个阵营可以决定其对未知阵营的态度)。
if (!_affiliations.TryGetValue(factionName2, out _))
{
return faction1.defaultRelation;
}
// 检查 faction1 是否将 faction2 明确列为敌对。
if (faction1.hostileFactions != null && faction1.hostileFactions.Contains(factionName2))
return Relation.Hostile;
// 检查 faction1 是否将 faction2 明确列为友好。
if (faction1.friendlyFactions != null && faction1.friendlyFactions.Contains(factionName2))
return Relation.Friendly;
// 检查 faction1 是否将 faction2 明确列为中立。
if (faction1.neutralFactions != null && faction1.neutralFactions.Contains(factionName2))
return Relation.Neutral;
// 如果 faction1 没有明确设置与 faction2 的关系,则使用 faction1 的默认关系。
return faction1.defaultRelation;
}
/// <summary>
/// 设置两个阵营之间的关系。
/// </summary>
/// <param name="factionName1">第一个阵营的名称。</param>
/// <param name="factionName2">第二个阵营的名称。</param>
/// <param name="relation">要设置的 <see cref="Relation" />。</param>
/// <exception cref="ArgumentException">当尝试设置同一个阵营的关系或其中一个阵营不存在时抛出。</exception>
/// <exception cref="ArgumentOutOfRangeException">当传入的关系类型无效时抛出。</exception>
public void SetRelation(string factionName1, string factionName2, Relation relation)
{
// 不能设置自己与自己的关系。
if (factionName1 == factionName2) throw new ArgumentException("不能设置同一个阵营之间的关系");
// 确保两个阵营都存在。
if (!_affiliations.TryGetValue(factionName1, out var faction1) ||
!_affiliations.TryGetValue(factionName2, out _))
throw new ArgumentException("一个或两个阵营不存在");
// 确保关系列表已初始化,避免空引用异常。
faction1.hostileFactions ??= new List<string>();
faction1.friendlyFactions ??= new List<string>();
faction1.neutralFactions ??= new List<string>();
// 先移除 factionName2 在 faction1 所有关系列表中的现有关系。
faction1.hostileFactions.Remove(factionName2);
faction1.friendlyFactions.Remove(factionName2);
faction1.neutralFactions.Remove(factionName2);
// 根据传入的关系类型,将 factionName2 添加到对应列表中。
switch (relation)
{
case Relation.Hostile:
faction1.hostileFactions.Add(factionName2);
break;
case Relation.Friendly:
faction1.friendlyFactions.Add(factionName2);
break;
case Relation.Neutral:
faction1.neutralFactions.Add(factionName2);
break;
default:
// 如果传入的关系类型无效,抛出异常。
throw new ArgumentOutOfRangeException(nameof(relation), relation, null);
}
}
/// <summary>
/// 检查并修复所有阵营之间的关系,以确保没有冲突。
/// 修复遵循优先级规则:友好关系优先于敌对关系,敌对关系优先于中立关系。
/// </summary>
private void ValidateAndFixRelationships()
{
foreach (var faction in _affiliations.Values)
{
// 确保所有关系列表已初始化,避免空引用异常。
faction.hostileFactions ??= new List<string>();
faction.friendlyFactions ??= new List<string>();
faction.neutralFactions ??= new List<string>();
// 遍历并检查所有敌对阵营。由于可能修改列表,使用 ToList() 创建副本进行遍历。
foreach (var hostileFaction in faction.hostileFactions.ToList())
{
// 如果敌对阵营同时存在于友好列表中,则移除其敌对关系(友好关系具有更高优先级)。
if (faction.friendlyFactions.Contains(hostileFaction))
{
faction.hostileFactions.Remove(hostileFaction);
continue; // 继续检查下一个敌对阵营。
}
// 如果敌对阵营同时存在于中立列表中,则移除其中立关系(敌对关系具有更高优先级)。
if (faction.neutralFactions.Contains(hostileFaction))
faction.neutralFactions.Remove(hostileFaction);
}
// 遍历并检查所有中立阵营。由于可能修改列表,使用 ToList() 创建副本进行遍历。
foreach (var neutralFaction in faction.neutralFactions.ToList())
// 如果中立阵营同时存在于友好列表中,则移除其中立关系(友好关系具有更高优先级)。
if (faction.friendlyFactions.Contains(neutralFaction))
faction.neutralFactions.Remove(neutralFaction);
}
}
}
}