using System;
using System.Collections;
using System.Collections.Generic;
using BaseGames.Core;
using BaseGames.Core.Events;
using BaseGames.Core.Save;
using UnityEngine;
namespace BaseGames.EventChain
{
///
/// 世界事件链管理器(架构 14_NarrativeModule §10)。
/// 订阅游戏各系统的 SO 事件频道,转发为中继 C# 事件供 ChainCondition.Register() 绑定。
/// 每当收到新事件时,检查所有链的触发条件。
///
public class EventChainManager : MonoBehaviour, ISaveable
{
[Header("所有事件链")]
[SerializeField] private EventChainSO[] _chains;
[Header("执行保护")]
[Tooltip("单个 Action 的最长执行时长(秒,unscaled time)。超时后强制跳过并记录警告。0 = 不限时。")]
[Min(0f)]
[SerializeField] private float _maxActionTimeout = 30f;
[Header("事件频道(中继)")]
[SerializeField] private StringEventChannelSO _onBossDefeated; // EVT_EnemyDied(bossId)
[SerializeField] private StringEventChannelSO _onCollectiblePickedUp; // EVT_CollectiblePickup
[SerializeField] private StringEventChannelSO _onAbilityUnlocked; // EVT_AbilityUnlocked
[SerializeField] private StringEventChannelSO _onRoomEntered; // EVT_SceneLoaded
[SerializeField] private StringEventChannelSO _onDialogueCompleted; // EVT_NpcDialogueCompleted
// ── 中继 C# 事件,供 ChainCondition.Register() 订阅 ──────────────
public event Action OnBossDefeated;
public event Action OnCollectiblePickedUp;
public event Action OnAbilityUnlocked;
public event Action OnRoomEntered;
public event Action OnDialogueCompleted;
/// 链执行完成时广播 chainId(供 ChainCompletedCondition)。
public event Action OnChainCompleted;
///
/// 世界标志变更事件(供 FlagSetCondition 事件驱动订阅,避免每帧轮询)。
/// 由 SetFlagAction.ExecuteAsync 在写入标志后调用 NotifyFlagChanged 触发。
///
public event Action OnWorldFlagChanged;
/// 通知所有 FlagSetCondition 指定标志已变更,并立即重评估标志相关链条件。
public void NotifyFlagChanged(string flagId)
{
OnWorldFlagChanged?.Invoke(flagId);
EvaluateForMask(ChainEventMask.FlagChanged);
}
///
/// 强制执行指定链,完全跳过条件检查。
/// 用于调试、关卡测试,或 QA 快速验证后续事件逻辑。
/// 仅在 Play Mode 中有效(链执行需要运行时环境)。
///
public void ForceExecute(string chainId)
{
if (_chains == null)
{
Debug.LogWarning("[EventChainManager] ForceExecute: _chains 为空,没有可执行的事件链。", this);
return;
}
foreach (var chain in _chains)
{
if (chain == null || chain.chainId != chainId) continue;
StartCoroutine(ExecuteChain(chain));
return;
}
Debug.LogWarning($"[EventChainManager] ForceExecute: 未找到 chainId='{chainId}' 的事件链。", this);
}
#if UNITY_EDITOR
///
/// Editor 专用静态事件:链执行完成时向编辑器窗口推送日志。
/// 仅在编辑器构建中存在,不产生运行时开销。
/// EventChainEditorWindow 在 OnEnable 中订阅此事件。
///
public static event Action OnChainExecutedInEditor;
#endif
private readonly HashSet _completedChains = new();
private readonly CompositeDisposable _subs = new();
// 每个链对应的事件掩码:OnEnable 后通过 BuildChainMasks 构建
private List _chainMasks;
private struct ChainMaskEntry
{
public EventChainSO chain;
public ChainEventMask mask;
}
// ── 生命周期 ──────────────────────────────────────────────────────
private void Awake()
{
// 不在此处读取存档数据——LoadAsync 尚未完成,_current 为 null。
// 已完成链的恢复由 ISaveable.OnLoad 在 LoadAsync 完成后处理。
}
private void OnEnable()
{
_onBossDefeated?.Subscribe(id => { OnBossDefeated?.Invoke(id); EvaluateForMask(ChainEventMask.Boss); }).AddTo(_subs);
_onCollectiblePickedUp?.Subscribe(id => { OnCollectiblePickedUp?.Invoke(id); EvaluateForMask(ChainEventMask.Collectible); }).AddTo(_subs);
_onAbilityUnlocked?.Subscribe(id => { OnAbilityUnlocked?.Invoke(id); EvaluateForMask(ChainEventMask.Ability); }).AddTo(_subs);
_onRoomEntered?.Subscribe(id => { OnRoomEntered?.Invoke(id); EvaluateForMask(ChainEventMask.Room); }).AddTo(_subs);
_onDialogueCompleted?.Subscribe(id => { OnDialogueCompleted?.Invoke(id); EvaluateForMask(ChainEventMask.Dialogue); }).AddTo(_subs);
ServiceLocator.GetOrDefault()?.Register(this);
// 向每个 Condition 注册中继事件
// 先重置 SO 资产上的运行时状态,防止跨 PlayMode 会话或多场景加载时状态残留
if (_chains == null) return;
foreach (var chain in _chains)
{
// 旧版 conditions[] 字段
if (chain?.conditions != null)
foreach (var cond in chain.conditions)
{
cond?.ResetState();
cond?.Register(this);
}
// 新版 conditionGroups[] 字段
if (chain?.conditionGroups != null)
foreach (var group in chain.conditionGroups)
if (group?.conditions != null)
foreach (var cond in group.conditions)
{
cond?.ResetState();
cond?.Register(this);
}
}
BuildChainMasks();
}
private void OnDisable()
{
_subs.Clear();
ServiceLocator.GetOrDefault()?.Unregister(this);
if (_chains == null) return;
foreach (var chain in _chains)
{
if (chain?.conditions != null)
foreach (var cond in chain.conditions)
cond?.Unregister(this);
if (chain?.conditionGroups != null)
foreach (var group in chain.conditionGroups)
if (group?.conditions != null)
foreach (var cond in group.conditions)
cond?.Unregister(this);
}
}
// ── ISaveable ─────────────────────────────────────────────────────────
///
/// SetChainCompleted 通过 ISaveService 直接写入 SaveData,OnSave 无需操作。
///
public void OnSave(SaveData data) { }
///
/// LoadAsync 完成后由 GameSaveManager.Register 补发,恢复本会话前已完成的链。
/// 仅恢复状态为 "Completed" 的条目;其他状态(如未来扩展的 "Failed")不影响重入检查。
///
public void OnLoad(SaveData data)
{
_completedChains.Clear();
if (data?.EventChains?.ChainStates == null) return;
foreach (var kv in data.EventChains.ChainStates)
if (kv.Value == "Completed")
_completedChains.Add(kv.Key);
}
// ── 评估逻辑 ──────────────────────────────────────────────────────
///
/// 构建每条链的 ChainEventMask(链内所有条件 RelevantEvents 的并集)。
/// OnEnable 在所有条件 Register 完毕后调用,之后事件触发只评估掩码相交的链。
///
private void BuildChainMasks()
{
_chainMasks = new List(_chains?.Length ?? 0);
if (_chains == null) return;
foreach (var chain in _chains)
{
if (chain == null) continue;
ChainEventMask mask = ChainEventMask.None;
bool hasGroups = chain.conditionGroups != null && chain.conditionGroups.Length > 0;
if (hasGroups)
{
foreach (var group in chain.conditionGroups)
if (group?.conditions != null)
foreach (var cond in group.conditions)
if (cond != null) mask |= cond.RelevantEvents;
}
else if (chain.conditions != null)
{
foreach (var cond in chain.conditions)
if (cond != null) mask |= cond.RelevantEvents;
}
// 无条件链:任何事件均可触发(等同 Any)
if (mask == ChainEventMask.None) mask = ChainEventMask.Any;
_chainMasks.Add(new ChainMaskEntry { chain = chain, mask = mask });
}
}
///
/// 懒评估:仅评估 mask 与 相交的链。
/// ChainEventMask.Any(-1)与任何非零 mask 均相交,确保自定义条件链不被跳过。
///
private void EvaluateForMask(ChainEventMask triggerMask)
{
if (_chainMasks == null) return;
foreach (var entry in _chainMasks)
{
if ((entry.mask & triggerMask) == 0) continue;
var chain = entry.chain;
if (!chain.repeatable && _completedChains.Contains(chain.chainId)) continue;
if (EvaluateChainConditions(chain)) StartCoroutine(ExecuteChain(chain));
}
}
///
/// 评估链的所有触发条件。
/// 若链配置了 ,按组逻辑评估(组内 And/Or,组间 And);
/// 否则回退到旧版 隐式 And 逻辑。
///
private static bool EvaluateChainConditions(EventChainSO chain)
{
bool hasGroups = chain.conditionGroups != null && chain.conditionGroups.Length > 0;
if (hasGroups)
{
// 组间为 And:所有组均须通过
foreach (var group in chain.conditionGroups)
{
if (group?.conditions == null || group.conditions.Length == 0) continue;
if (!EvaluateConditionGroup(group)) return false;
}
return true;
}
// 旧版:conditions[] 隐式 And
if (chain.conditions != null)
foreach (var cond in chain.conditions)
if (cond != null && !cond.IsMet()) return false;
return true;
}
/// 按组内 logic(And/Or)评估单个条件组是否通过。
private static bool EvaluateConditionGroup(ConditionGroup group)
{
if (group.logic == WorldStateFlagLogic.Or)
{
foreach (var cond in group.conditions)
if (cond != null && cond.IsMet()) return true;
return false;
}
// And(默认)
foreach (var cond in group.conditions)
if (cond != null && !cond.IsMet()) return false;
return true;
}
private IEnumerator ExecuteChain(EventChainSO chain)
{
// 防重入:一次性链立即标记为已完成
if (!chain.repeatable) _completedChains.Add(chain.chainId);
if (chain.actions != null)
foreach (var action in chain.actions)
{
if (action == null) continue;
bool actionFailed = false;
if (_maxActionTimeout > 0f)
{
bool finished = false;
Coroutine co = null;
try
{
co = StartCoroutine(SetTrueOnFinish(action.ExecuteAsync(this), () => finished = true));
}
catch (System.Exception ex)
{
Debug.LogError(
$"[EventChainManager] 链 '{chain.chainId}' 动作 '{action.GetType().Name}' 启动异常:{ex.Message}",
this);
actionFailed = true;
}
if (!actionFailed)
{
// 用 realtimeSinceStartup 计时,确保 PlayMode 暂停时超时仍能触发
float deadline = Time.realtimeSinceStartup + _maxActionTimeout;
while (!finished)
{
if (Time.realtimeSinceStartup >= deadline)
{
if (co != null) StopCoroutine(co);
Debug.LogWarning(
$"[EventChainManager] 链 '{chain.chainId}' 的动作 '{action.GetType().Name}' " +
$"执行超时({_maxActionTimeout}s),已强制跳过。");
#if UNITY_EDITOR
OnChainExecutedInEditor?.Invoke(chain.chainId,
$"超时跳过:{action.GetType().Name}(>{_maxActionTimeout}s)");
#endif
break;
}
yield return null;
}
}
}
else
{
bool exceptionThrown = false;
IEnumerator routine = null;
try { routine = action.ExecuteAsync(this); }
catch (System.Exception ex)
{
Debug.LogError(
$"[EventChainManager] 链 '{chain.chainId}' 动作 '{action.GetType().Name}' 异常:{ex.Message}",
this);
exceptionThrown = true;
}
if (!exceptionThrown && routine != null)
yield return routine;
}
if (chain.actionDelay > 0f)
yield return new WaitForSeconds(chain.actionDelay);
}
ServiceLocator.GetOrDefault()?.SetChainCompleted(chain.chainId);
OnChainCompleted?.Invoke(chain.chainId);
#if UNITY_EDITOR
OnChainExecutedInEditor?.Invoke(chain.chainId, "执行完成");
#endif
}
///
/// 将 inner 协程执行完毕后触发 onFinish 回调,供超时保护使用。
/// StopCoroutine 此协程时,内嵌的 inner(通过 yield return 直接展开)也会一并停止。
///
private static IEnumerator SetTrueOnFinish(IEnumerator inner, Action onFinish)
{
yield return inner;
onFinish();
}
}
}