Files
Continentis/Assets/Scripts/ScriptExtensions/CommandQueue/CommandBase.cs
2025-11-08 09:50:55 -05:00

104 lines
3.9 KiB
C#

using UniRx;
using System;
namespace SLSFramework.General
{
public enum ConditionFailedAction
{
Discard,
Wait
}
/*
public interface ICommand
{
/// <summary>
/// 执行指令的核心逻辑。
/// </summary>
/// <param name="context">包含了所有执行所需信息的上下文对象。</param>
/// <returns>一个代表指令完成的信号。</returns>
IObservable<Unit> Execute(CommandContext context);
void ForceComplete();
}
*/
public abstract class CommandBase
{
public bool insertAtFirst = false;
public CommandContext selfContext;
protected readonly Subject<Unit> forceCompleteSubject = new Subject<Unit>();
public void ForceComplete() => forceCompleteSubject.OnNext(Unit.Default);
// 子类必须实现这个方法,定义指令的核心行为
protected abstract IObservable<Unit> OnExecute(CommandContext outerContext);
protected virtual Func<CommandContext, bool> InnerCondition => (ctx) => true; // 默认条件为总是 true
// 子类通过重写这个 Func 来定义自己的执行条件
protected virtual Func<CommandContext, bool> OuterCondition => (ctx) => true; // 默认条件为总是 true
// 子类定义条件失败时的处理方式
protected virtual ConditionFailedAction OnConditionFailed => ConditionFailedAction.Discard;
public CommandBase(CommandContext selfContext = null)
{
this.selfContext = selfContext ?? new CommandContext();
}
public virtual CommandBase Clone()
{
CommandBase clone = (CommandBase)MemberwiseClone();
clone.selfContext = selfContext.Clone();
return clone;
}
/// <summary>
/// Execute 的公共入口。
/// 它封装了条件判断、等待、或舍弃的复杂逻辑。
/// 子类不应该重写此方法,而应该实现 OnExecute。
/// </summary>
public IObservable<Unit> Execute(CommandContext outerContext)
{
// 检查初始条件
if (InnerCondition(selfContext) && OuterCondition(outerContext))
{
// 条件满足,直接执行
return CreateAsyncOperation(() => OnExecute(outerContext));
}
// 初始条件不满足
if (OnConditionFailed == ConditionFailedAction.Discard)
{
// 策略为“舍弃”,返回一个立即完成的空操作
return Observable.Return(Unit.Default);
}
else // 策略为“等待”
{
// --- 响应式的等待逻辑 ---
return Observable.Defer(() =>
{
// Defer 用于延迟执行,确保每次重试时都重新检查条件
if (OuterCondition(outerContext)) return CreateAsyncOperation(() => OnExecute(outerContext));
// 如果条件仍不满足,则开始等待游戏状态变化
return CommandQueueManager.Instance.OnStateChanged
// 检查每次状态变化后的条件
.Where(_ => OuterCondition(outerContext))
// 我们只需要条件第一次变为 true 的那个时刻
.First()
// 当条件满足时,切换到真正的执行逻辑
.SelectMany(_ => CreateAsyncOperation(() => OnExecute(outerContext)));
});
}
}
// 包装异步操作,使其可以被强制完成
private IObservable<Unit> CreateAsyncOperation(Func<IObservable<Unit>> operationFactory)
{
return operationFactory().TakeUntil(forceCompleteSubject);
}
}
}