Files
Continentis/Assets/Scripts/SLSUtilities/CommandQueue/CommandGroup.cs

140 lines
4.6 KiB
C#
Raw Normal View History

2026-03-20 11:56:50 -04:00
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
namespace SLSFramework.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);
}
}
}