Files
SoulliesOfficial ac98ec3aef 更新
2026-04-17 12:01:50 -04:00

140 lines
4.6 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.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
namespace SLSUtilities.General
{
/// <summary>命令组的执行模式。</summary>
public enum ExecutionMode
{
/// <summary>子命令逐条顺序执行。</summary>
Sequential,
/// <summary>子命令同时并行执行。</summary>
Parallel
}
/// <summary>
/// 命令组,将多条 <see cref="CommandBase"/> 按 Sequential 或 Parallel 模式执行。
/// 自身也是 <see cref="CommandBase"/>,可嵌套组合。
/// </summary>
public class CommandGroup : CommandBase
{
/// <summary>子命令列表。</summary>
public readonly List<CommandBase> commands = new List<CommandBase>();
/// <summary>本组的执行模式。</summary>
public readonly ExecutionMode mode;
/// <summary>
/// 组级别上下文,执行过程中会合并每条子命令的 outerContext 与 selfContext。
/// 可在组执行完成后读取聚合数据(如 DrawnCards
/// </summary>
public readonly CommandContext groupContext;
public CommandGroup(ExecutionMode mode = ExecutionMode.Sequential)
{
this.mode = mode;
groupContext = new CommandContext();
}
public CommandGroup(ExecutionMode mode, params CommandBase[] commands)
{
this.mode = mode;
groupContext = new CommandContext();
this.commands.AddRange(commands);
}
public CommandGroup(params CommandBase[] commands)
{
mode = ExecutionMode.Sequential;
groupContext = new CommandContext();
this.commands.AddRange(commands);
}
/// <summary>添加一条子命令,返回自身支持链式调用。</summary>
public CommandGroup AddCommand(CommandBase command)
{
commands.Add(command);
return this;
}
/// <summary>
/// 获取所有子命令。设 <paramref name="alsoIncludeGroups"/> 为 true 时,
/// 返回结果中也包含 <see cref="CommandGroup"/> 自身节点。
/// </summary>
public List<CommandBase> GetAllCommands(bool alsoIncludeGroups = false)
{
//CommandBase可能也是CommandGroup,需要递归获取
var allCommands = new List<CommandBase>();
if (alsoIncludeGroups)
{
allCommands.Add(this);
}
foreach (CommandBase cmd in commands)
{
if (cmd is CommandGroup group)
{
if (alsoIncludeGroups)
{
allCommands.Add(group);
}
allCommands.AddRange(group.GetAllCommands(alsoIncludeGroups));
}
else
{
allCommands.Add(cmd);
}
}
return allCommands;
}
/// <summary>获取所有指定类型的子命令(递归,包含组节点)。</summary>
public List<T> GetAllCommands<T>() where T : CommandBase
{
return GetAllCommands(true).OfType<T>().ToList();
}
/// <summary>深拷贝整个命令组及其子命令。</summary>
public override CommandBase Clone()
{
var cloned = new CommandGroup(mode);
foreach (var cmd in commands)
cloned.AddCommand(cmd.Clone());
return cloned;
}
protected override async UniTask ExecuteAsync(CommandContext outerContext)
{
if (mode == ExecutionMode.Sequential)
{
foreach (var cmd in commands)
{
await cmd.RunAsync(outerContext);
MergeContexts(cmd, outerContext);
}
}
else
{
await UniTask.WhenAll(commands.Select(cmd =>
ExecuteAndMergeAsync(cmd, outerContext)));
}
}
/// <summary>执行单条子命令并将上下文合并到 groupContext。</summary>
private async UniTask ExecuteAndMergeAsync(CommandBase cmd, CommandContext outerContext)
{
await cmd.RunAsync(outerContext);
MergeContexts(cmd, outerContext);
}
private void MergeContexts(CommandBase cmd, CommandContext outerContext)
{
groupContext.Merge(outerContext);
groupContext.Merge(cmd.selfContext);
}
}
}