168 lines
6.0 KiB
C#
168 lines
6.0 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using Continentis.MainGame.Character;
|
||
using Cysharp.Threading.Tasks;
|
||
|
||
namespace SLSUtilities.General
|
||
{
|
||
/// <summary>
|
||
/// 命令静态工厂。
|
||
/// Mod 制作者通过此类创建常用命令,无需直接实例化具体命令类。
|
||
/// </summary>
|
||
public static class Cmd
|
||
{
|
||
// ── 基础工厂 ─────────────────────────────────────────────────────
|
||
|
||
/// <summary>创建一条等待指定秒数后完成的命令。</summary>
|
||
public static CommandBase Wait(float seconds)
|
||
{
|
||
return new WaitCommand(seconds);
|
||
}
|
||
|
||
/// <summary>创建一条执行同步 Action 的命令。</summary>
|
||
public static CommandBase Do(Action action)
|
||
{
|
||
return new ActionCommand(action);
|
||
}
|
||
|
||
/// <summary>创建一条执行异步 UniTask 的命令。</summary>
|
||
public static CommandBase Do(Func<UniTask> asyncAction)
|
||
{
|
||
return new AsyncActionCommand(asyncAction);
|
||
}
|
||
|
||
/// <summary>创建一条延迟指定秒数后执行同步 Action 的命令。</summary>
|
||
public static CommandBase After(float seconds, Action action)
|
||
{
|
||
return new ActionCommand(action).SetDelay(seconds);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建一条"等待外部信号"命令。
|
||
/// 调用返回的 <paramref name="signal"/> Action 时,命令立即完成,队列继续执行。
|
||
/// 典型用法:等待玩家点击按钮确认。
|
||
/// </summary>
|
||
/// <param name="signal">外部调用此委托以释放命令。</param>
|
||
public static CommandBase WaitForSignal(out Action signal)
|
||
{
|
||
var tcs = new UniTaskCompletionSource();
|
||
signal = () => tcs.TrySetResult();
|
||
return new WaitForSignalCommand(tcs);
|
||
}
|
||
|
||
// ── 组合工厂 ─────────────────────────────────────────────────────
|
||
|
||
/// <summary>创建一个顺序执行的命令组。</summary>
|
||
public static CommandGroup Sequential(params CommandBase[] cmds)
|
||
{
|
||
return new CommandGroup(ExecutionMode.Sequential, cmds);
|
||
}
|
||
|
||
/// <summary>创建一个并行执行的命令组。</summary>
|
||
public static CommandGroup Parallel(params CommandBase[] cmds)
|
||
{
|
||
return new CommandGroup(ExecutionMode.Parallel, cmds);
|
||
}
|
||
|
||
// ── Target 遍历工厂 ───────────────────────────────────────────────
|
||
|
||
/// <summary>
|
||
/// 对 <paramref name="targets"/> 列表中的每个目标调用 <paramref name="factory"/>,
|
||
/// 将结果按顺序组合为一个 Sequential <see cref="CommandGroup"/>。
|
||
/// </summary>
|
||
public static CommandGroup ForEachTarget(
|
||
List<CharacterBase> targets,
|
||
Func<CharacterBase, CommandBase> factory)
|
||
{
|
||
var group = new CommandGroup(ExecutionMode.Sequential);
|
||
foreach (CharacterBase target in targets)
|
||
{
|
||
CharacterBase captured = target;
|
||
group.AddCommand(factory(captured));
|
||
}
|
||
return group;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 对 <paramref name="targets"/> 列表中的每个目标调用 <paramref name="factory"/>,
|
||
/// 将结果按顺序组合为一个 Sequential <see cref="CommandGroup"/>。
|
||
/// </summary>
|
||
public static CommandGroup ForEachTarget(
|
||
List<CharacterBase> targets,
|
||
Func<CharacterBase, CommandGroup> factory)
|
||
{
|
||
var group = new CommandGroup(ExecutionMode.Sequential);
|
||
foreach (CharacterBase target in targets)
|
||
{
|
||
CharacterBase captured = target;
|
||
group.AddCommand(factory(captured));
|
||
}
|
||
return group;
|
||
}
|
||
|
||
// ── 内部实现类 ────────────────────────────────────────────────────
|
||
|
||
private sealed class WaitCommand : CommandBase
|
||
{
|
||
private readonly float seconds;
|
||
|
||
public WaitCommand(float seconds)
|
||
{
|
||
this.seconds = seconds;
|
||
}
|
||
|
||
protected override async UniTask ExecuteAsync(CommandContext outerContext)
|
||
{
|
||
await UniTask.Delay(TimeSpan.FromSeconds(seconds));
|
||
}
|
||
}
|
||
|
||
private sealed class ActionCommand : CommandBase
|
||
{
|
||
private readonly Action action;
|
||
|
||
public ActionCommand(Action action)
|
||
{
|
||
this.action = action;
|
||
}
|
||
|
||
protected override UniTask ExecuteAsync(CommandContext outerContext)
|
||
{
|
||
action?.Invoke();
|
||
return UniTask.CompletedTask;
|
||
}
|
||
}
|
||
|
||
private sealed class AsyncActionCommand : CommandBase
|
||
{
|
||
private readonly Func<UniTask> asyncAction;
|
||
|
||
public AsyncActionCommand(Func<UniTask> asyncAction)
|
||
{
|
||
this.asyncAction = asyncAction;
|
||
}
|
||
|
||
protected override async UniTask ExecuteAsync(CommandContext outerContext)
|
||
{
|
||
if (asyncAction != null)
|
||
await asyncAction();
|
||
}
|
||
}
|
||
|
||
private sealed class WaitForSignalCommand : CommandBase
|
||
{
|
||
private readonly UniTaskCompletionSource tcs;
|
||
|
||
public WaitForSignalCommand(UniTaskCompletionSource tcs)
|
||
{
|
||
this.tcs = tcs;
|
||
}
|
||
|
||
protected override async UniTask ExecuteAsync(CommandContext outerContext)
|
||
{
|
||
await tcs.Task;
|
||
}
|
||
}
|
||
}
|
||
}
|