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