From 1fd5320df2fc552bf3f61db671bb2f37b3a809d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=89=E9=B8=AD=E8=9B=8B?= Date: Sun, 8 Sep 2024 02:23:45 +0800 Subject: [PATCH] auto pathing: update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除了不必要的 `using` 语句,添加了新的 `using` 语句。 - 将 `Waypoints` 属性重命名为 `Positions`。 - 更新了 `BuildFromFilePath` 方法中的 `JsonOptions` 引用。 - 将 `Waypoint` 类移到单独的文件中,并添加了相关属性和注释。 - 添加了 `SaveToFile` 方法,用于将 `PathingTask` 对象保存到文件。 - 更新了 `PathExecutor` 中的 `TaskControl` 引用,简化了代码。 - 更新了 `PathRecorder` 的属性和方法,使用私有字段 `_pathingTask`。 - 更新了 `MapPathingPage.xaml` 的命令绑定。 - 更新了 `HotKeyPageViewModel` 和 `MapPathingViewModel` 的逻辑。 - 添加了新的 `PathingTaskConfig` 类,用于配置路径任务。 --- .../GameTask/AutoPathing/Model/PathingTask.cs | 38 +++------ .../AutoPathing/Model/PathingTaskConfig.cs | 14 ++++ .../AutoPathing/Model/PathingTaskInfo.cs | 1 - .../GameTask/AutoPathing/Model/Waypoint.cs | 26 ++++++ .../GameTask/AutoPathing/PathExecutor.cs | 80 +++++++++++-------- .../GameTask/AutoPathing/PathRecorder.cs | 44 +++++----- .../View/Pages/MapPathingPage.xaml | 5 +- .../ViewModel/Pages/HotKeyPageViewModel.cs | 15 ++-- .../ViewModel/Pages/MapPathingViewModel.cs | 34 ++++---- 9 files changed, 146 insertions(+), 111 deletions(-) create mode 100644 BetterGenshinImpact/GameTask/AutoPathing/Model/PathingTaskConfig.cs create mode 100644 BetterGenshinImpact/GameTask/AutoPathing/Model/Waypoint.cs diff --git a/BetterGenshinImpact/GameTask/AutoPathing/Model/PathingTask.cs b/BetterGenshinImpact/GameTask/AutoPathing/Model/PathingTask.cs index b5d4623d..d0e6a345 100644 --- a/BetterGenshinImpact/GameTask/AutoPathing/Model/PathingTask.cs +++ b/BetterGenshinImpact/GameTask/AutoPathing/Model/PathingTask.cs @@ -1,12 +1,8 @@ -using BetterGenshinImpact.Core.Recorder; -using BetterGenshinImpact.Core.Script.Group; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Text; using System.Text.Json; -using System.Text.Json.Serialization; -using BetterGenshinImpact.GameTask.AutoPathing.Model.Enum; namespace BetterGenshinImpact.GameTask.AutoPathing.Model; @@ -14,33 +10,17 @@ namespace BetterGenshinImpact.GameTask.AutoPathing.Model; public class PathingTask { public PathingTaskInfo Info { get; set; } = new(); - public List Waypoints { get; set; } = []; + public List Positions { get; set; } = []; public static PathingTask BuildFromFilePath(string filePath) { var json = File.ReadAllText(filePath); - return JsonSerializer.Deserialize(json, KeyMouseRecorder.JsonOptions) ?? throw new Exception("Failed to deserialize PathingTask"); + return JsonSerializer.Deserialize(json, PathRecorder.JsonOptions) ?? throw new Exception("Failed to deserialize PathingTask"); + } + + public void SaveToFile(string filePath) + { + var json = JsonSerializer.Serialize(this, PathRecorder.JsonOptions); + File.WriteAllText(filePath, json, Encoding.UTF8); } } - -[Serializable] -public class Waypoint -{ - public double X { get; set; } - public double Y { get; set; } - - /// - /// - /// - public string Type { get; set; } = WaypointType.Path.Code; - - /// - /// - /// - public string MoveMode { get; set; } = MoveModeEnum.Walk.Code; - - /// - /// - /// - public string? Action { get; set; } -} diff --git a/BetterGenshinImpact/GameTask/AutoPathing/Model/PathingTaskConfig.cs b/BetterGenshinImpact/GameTask/AutoPathing/Model/PathingTaskConfig.cs new file mode 100644 index 00000000..cc377458 --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoPathing/Model/PathingTaskConfig.cs @@ -0,0 +1,14 @@ +using BetterGenshinImpact.GameTask.AutoPathing.Model.Enum; +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace BetterGenshinImpact.GameTask.AutoPathing.Model; + +[Serializable] +public class PathingTaskConfig +{ + // 持续操作 切换某个角色 长E or 短E + // 持续疾跑 + // 边跳边走 +} diff --git a/BetterGenshinImpact/GameTask/AutoPathing/Model/PathingTaskInfo.cs b/BetterGenshinImpact/GameTask/AutoPathing/Model/PathingTaskInfo.cs index b7107fc1..e6c7ede8 100644 --- a/BetterGenshinImpact/GameTask/AutoPathing/Model/PathingTaskInfo.cs +++ b/BetterGenshinImpact/GameTask/AutoPathing/Model/PathingTaskInfo.cs @@ -1,6 +1,5 @@ using BetterGenshinImpact.GameTask.AutoPathing.Model.Enum; using System; -using System.Collections.Generic; using System.Text.Json.Serialization; namespace BetterGenshinImpact.GameTask.AutoPathing.Model; diff --git a/BetterGenshinImpact/GameTask/AutoPathing/Model/Waypoint.cs b/BetterGenshinImpact/GameTask/AutoPathing/Model/Waypoint.cs new file mode 100644 index 00000000..44754769 --- /dev/null +++ b/BetterGenshinImpact/GameTask/AutoPathing/Model/Waypoint.cs @@ -0,0 +1,26 @@ +using System; +using BetterGenshinImpact.GameTask.AutoPathing.Model.Enum; + +namespace BetterGenshinImpact.GameTask.AutoPathing.Model; + +[Serializable] +public class Waypoint +{ + public double X { get; set; } + public double Y { get; set; } + + /// + /// + /// + public string Type { get; set; } = WaypointType.Path.Code; + + /// + /// + /// + public string MoveMode { get; set; } = MoveModeEnum.Walk.Code; + + /// + /// + /// + public string? Action { get; set; } +} diff --git a/BetterGenshinImpact/GameTask/AutoPathing/PathExecutor.cs b/BetterGenshinImpact/GameTask/AutoPathing/PathExecutor.cs index dc3a3817..090fc7f2 100644 --- a/BetterGenshinImpact/GameTask/AutoPathing/PathExecutor.cs +++ b/BetterGenshinImpact/GameTask/AutoPathing/PathExecutor.cs @@ -15,6 +15,7 @@ using System.Threading.Tasks; using BetterGenshinImpact.GameTask.AutoPathing.Model.Enum; using Vanara.PInvoke; using Wpf.Ui.Violeta.Controls; +using static BetterGenshinImpact.GameTask.Common.TaskControl; namespace BetterGenshinImpact.GameTask.AutoPathing; @@ -30,22 +31,19 @@ public class PathExecutor(CancellationTokenSource cts) SystemControl.ActivateWindow(); - if (task.Waypoints.Count == 0) + if (task.Positions.Count == 0) { - TaskControl.Logger.LogWarning("没有路径点,寻路结束"); + Logger.LogWarning("没有路径点,寻路结束"); return; } - if (task.Waypoints.First().Type != WaypointType.Teleport.Code) - { - TaskControl.Logger.LogWarning("第一个路径点不是传送点,将不会进行传送"); - } + task.Positions.First().Type = WaypointType.Teleport.Code; // 这里应该判断一下自动拾取是否处于工作状态,但好像没有什么方便的读取办法 // TODO:大地图传送的时候使用游戏坐标,追踪的时候应该使用2048地图图像坐标,这里临时做转换,后续改进 var waypoints = new List(); - foreach (var waypoint in task.Waypoints) + foreach (var waypoint in task.Positions) { if (waypoint.Type == WaypointType.Teleport.Code) { @@ -66,7 +64,7 @@ public class PathExecutor(CancellationTokenSource cts) { if (waypoint.Type == WaypointType.Teleport.Code) { - TaskControl.Logger.LogInformation("正在传送到{x},{y}", waypoint.X, waypoint.Y); + Logger.LogInformation("正在传送到{x},{y}", waypoint.X, waypoint.Y); await new TpTask(cts).Tp(waypoint.X, waypoint.Y); continue; } @@ -85,11 +83,11 @@ public class PathExecutor(CancellationTokenSource cts) private async Task MoveTo(Waypoint waypoint) { - var screen = TaskControl.CaptureToRectArea(); + var screen = CaptureToRectArea(); var position = Navigation.GetPosition(screen); var targetOrientation = Navigation.GetTargetOrientation(waypoint, position); - TaskControl.Logger.LogInformation("粗略接近路径点,当前位置({x1},{y1}),目标位置({x2},{y2})", position.X, position.Y, waypoint.X, waypoint.Y); - await WaitUntilRotatedTo(targetOrientation, 10); + Logger.LogInformation("粗略接近路径点,当前位置({x1},{y1}),目标位置({x2},{y2})", position.X, position.Y, waypoint.X, waypoint.Y); + await WaitUntilRotatedTo(targetOrientation, 5); var startTime = DateTime.UtcNow; var lastPositionRecord = DateTime.UtcNow; var fastMode = false; @@ -101,21 +99,21 @@ public class PathExecutor(CancellationTokenSource cts) var now = DateTime.UtcNow; if ((now - startTime).TotalSeconds > 30) { - TaskControl.Logger.LogWarning("执行超时,跳过路径点"); + Logger.LogWarning("执行超时,跳过路径点"); break; } - screen = TaskControl.CaptureToRectArea(); + screen = CaptureToRectArea(); position = Navigation.GetPosition(screen); var distance = Navigation.GetDistance(waypoint, position); - TaskControl.Logger.LogInformation("接近目标点中,距离为{distance}", distance); + Logger.LogInformation("接近目标点中,距离为{distance}", distance); if (distance < 4) { - TaskControl.Logger.LogInformation("到达路径点附近"); + Logger.LogInformation("到达路径点附近"); break; } if (distance > 500) { - TaskControl.Logger.LogWarning("距离过远,跳过路径点"); + Logger.LogWarning("距离过远,跳过路径点"); break; } if ((now - lastPositionRecord).TotalMilliseconds > 1000) @@ -129,15 +127,15 @@ public class PathExecutor(CancellationTokenSource cts) { TaskControl.Logger.LogWarning("疑似卡死,尝试脱离并跳过路径点"); Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W); - await Task.Delay(500); + await Delay(500, cts); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_X); - await Task.Delay(500); + await Delay(500, cts); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_S); - await Task.Delay(500); + await Delay(500, cts); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_A); - await Task.Delay(500); + await Delay(500, cts); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_D); - await Task.Delay(500); + await Delay(500, cts); return; } } @@ -145,7 +143,7 @@ public class PathExecutor(CancellationTokenSource cts) // 旋转视角 var isFlying = Bv.GetMotionStatus(screen) == MotionStatus.Fly; targetOrientation = Navigation.GetTargetOrientation(waypoint, position); - RotateTo(targetOrientation, screen, isFlying ? 2 : 6); + RotateTo(targetOrientation, screen); // 根据指定方式进行移动 if (waypoint.MoveMode == MoveModeEnum.Fly.Code) { @@ -160,13 +158,13 @@ public class PathExecutor(CancellationTokenSource cts) if (isFlying) { Simulation.SendInput.Mouse.LeftButtonClick(); - await Task.Delay(1000); + await Delay(1000, cts); continue; } if (waypoint.MoveMode == MoveModeEnum.Jump.Code) { Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_SPACE); - await Task.Delay(1000); + await Delay(1000, cts); continue; } // 跑步或者游泳 @@ -182,7 +180,7 @@ public class PathExecutor(CancellationTokenSource cts) } fastMode = !fastMode; } - await Task.Delay(100); + await Delay(100, cts); } // 抬起w键 Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W); @@ -190,10 +188,10 @@ public class PathExecutor(CancellationTokenSource cts) private async Task MoveCloseTo(Waypoint waypoint) { - var screen = TaskControl.CaptureToRectArea(); + var screen = CaptureToRectArea(); var position = Navigation.GetPosition(screen); var targetOrientation = Navigation.GetTargetOrientation(waypoint, position); - TaskControl.Logger.LogInformation("精确接近路径点,当前位置({x1},{y1}),目标位置({x2},{y2})", position.X, position.Y, waypoint.X, waypoint.Y); + Logger.LogInformation("精确接近路径点,当前位置({x1},{y1}),目标位置({x2},{y2})", position.X, position.Y, waypoint.X, waypoint.Y); var isFlying = Bv.GetMotionStatus(screen) == MotionStatus.Fly; if (waypoint.MoveMode == MoveModeEnum.Fly.Code && waypoint.Action == ActionEnum.StopFlying.Code && isFlying) { @@ -209,14 +207,14 @@ public class PathExecutor(CancellationTokenSource cts) stepsTaken++; if (stepsTaken > 8) { - TaskControl.Logger.LogWarning("精确接近超时"); + Logger.LogWarning("精确接近超时"); break; } - screen = TaskControl.CaptureToRectArea(); + screen = CaptureToRectArea(); position = Navigation.GetPosition(screen); if (Navigation.GetDistance(waypoint, position) < 2) { - TaskControl.Logger.LogInformation("已到达路径点"); + Logger.LogInformation("已到达路径点"); break; } RotateTo(targetOrientation, screen); //不再改变视角 @@ -231,7 +229,7 @@ public class PathExecutor(CancellationTokenSource cts) { Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W); } - await Task.Delay(500); + await Delay(100, cts); } if (wPressed) { @@ -239,7 +237,7 @@ public class PathExecutor(CancellationTokenSource cts) } } - private int RotateTo(int targetOrientation, ImageRegion imageRegion, int controlRatio = 6) + private int RotateTo(int targetOrientation, ImageRegion imageRegion, int controlRatio = 1) { var cao = CameraOrientation.Compute(imageRegion.SrcGreyMat); var diff = (cao - targetOrientation + 180) % 360 - 180; @@ -248,7 +246,19 @@ public class PathExecutor(CancellationTokenSource cts) { return diff; } - Simulation.SendInput.Mouse.MoveMouseBy(-controlRatio * (diff + (diff > 0 ? 1 : -1)), 0); + if (Math.Abs(diff) > 90) + { + controlRatio = 5; + } + else if (Math.Abs(diff) > 30) + { + controlRatio = 3; + } + else if (Math.Abs(diff) > 5) + { + controlRatio = 2; + } + Simulation.SendInput.Mouse.MoveMouseBy(-controlRatio * diff, 0); return diff; } @@ -257,7 +267,7 @@ public class PathExecutor(CancellationTokenSource cts) int count = 0; while (true) { - var screen = TaskControl.CaptureToRectArea(); + var screen = CaptureToRectArea(); if (Math.Abs(RotateTo(targetOrientation, screen)) < maxDiff) { break; @@ -266,7 +276,7 @@ public class PathExecutor(CancellationTokenSource cts) { break; } - await Task.Delay(50); + await Delay(50, cts); count++; } } diff --git a/BetterGenshinImpact/GameTask/AutoPathing/PathRecorder.cs b/BetterGenshinImpact/GameTask/AutoPathing/PathRecorder.cs index 7dccf487..70dee3b9 100644 --- a/BetterGenshinImpact/GameTask/AutoPathing/PathRecorder.cs +++ b/BetterGenshinImpact/GameTask/AutoPathing/PathRecorder.cs @@ -1,24 +1,34 @@ -using System; -using System.Collections.Generic; -using System.Text; -using BetterGenshinImpact.GameTask.Common; -using BetterGenshinImpact.GameTask.Common.Map; -using Microsoft.Extensions.Logging; -using System.Text.Json; -using BetterGenshinImpact.Core.Config; -using System.IO; +using BetterGenshinImpact.Core.Config; using BetterGenshinImpact.GameTask.AutoPathing.Model; using BetterGenshinImpact.GameTask.AutoPathing.Model.Enum; -using BetterGenshinImpact.GameTask.Common.BgiVision; +using BetterGenshinImpact.GameTask.Common; +using BetterGenshinImpact.GameTask.Common.Map; +using BetterGenshinImpact.ViewModel.Pages; +using Microsoft.Extensions.Logging; +using System; +using System.IO; +using System.Text.Json; +using System.Text.Json.Serialization; namespace BetterGenshinImpact.GameTask.AutoPathing; public class PathRecorder { - public PathingTask PathingTask { get; set; } = new(); + public static readonly JsonSerializerOptions JsonOptions = new() + { + NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals, + Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, // 下划线 + AllowTrailingCommas = true, + ReadCommentHandling = JsonCommentHandling.Skip, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; + + private PathingTask _pathingTask = new(); public void Start() { + _pathingTask = new PathingTask(); TaskControl.Logger.LogInformation("开始路径点记录"); var waypoint = new Waypoint(); var screen = TaskControl.CaptureToRectArea(); @@ -28,7 +38,7 @@ public class PathRecorder waypoint.Y = position.Y; waypoint.Type = WaypointType.Teleport.Code; waypoint.MoveMode = MoveModeEnum.Walk.Code; - PathingTask.Waypoints.Add(waypoint); + _pathingTask.Positions.Add(waypoint); TaskControl.Logger.LogInformation("已创建初始路径点({x},{y})", waypoint.X, waypoint.Y); } @@ -56,18 +66,12 @@ public class PathRecorder // waypoint.MoveStatus = MoveStatusType.Walk.Code; // break; // } - PathingTask.Waypoints.Add(waypoint); + _pathingTask.Positions.Add(waypoint); TaskControl.Logger.LogInformation("已添加途径点({x},{y})", waypoint.X, waypoint.Y); } public void Save() { - var json = JsonSerializer.Serialize(PathingTask); - File.WriteAllText(Global.Absolute($@"log\way\{DateTime.Now:yyyy-MM-dd HH:mm:ss:ffff}.json"), json); - } - - public void Clear() - { - PathingTask = new PathingTask(); + _pathingTask.SaveToFile(Path.Combine(MapPathingViewModel.PathJsonPath, $@"{DateTime.Now:yyyy-MM-dd HH:mm:ss:ffff}.json")); } } diff --git a/BetterGenshinImpact/View/Pages/MapPathingPage.xaml b/BetterGenshinImpact/View/Pages/MapPathingPage.xaml index 80a45cf2..ccbbf345 100644 --- a/BetterGenshinImpact/View/Pages/MapPathingPage.xaml +++ b/BetterGenshinImpact/View/Pages/MapPathingPage.xaml @@ -94,10 +94,7 @@ - - diff --git a/BetterGenshinImpact/ViewModel/Pages/HotKeyPageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/HotKeyPageViewModel.cs index 72d45505..1c7d561f 100644 --- a/BetterGenshinImpact/ViewModel/Pages/HotKeyPageViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/HotKeyPageViewModel.cs @@ -453,7 +453,7 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel var pathRecording = false; HotKeySettingModels.Add(new HotKeySettingModel( - "(测试)路径记录器", + "启动/停止路径记录器", nameof(Config.HotKeyConfig.PathRecorderHotkey), Config.HotKeyConfig.PathRecorderHotkey, Config.HotKeyConfig.PathRecorderHotkeyType, @@ -465,7 +465,6 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel } else { - pathRecorder.Clear(); pathRecorder.Start(); } pathRecording = !pathRecording; @@ -473,7 +472,7 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel )); HotKeySettingModels.Add(new HotKeySettingModel( - "(测试)添加记录点", + "添加记录点", nameof(Config.HotKeyConfig.AddWaypointHotkey), Config.HotKeyConfig.AddWaypointHotkey, Config.HotKeyConfig.AddWaypointHotkeyType, @@ -493,11 +492,11 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel Config.HotKeyConfig.ExecutePathHotkeyType, (_, _) => { - if (pathRecording) - { - new TaskRunner(DispatcherTimerOperationEnum.UseCacheImageWithTrigger) - .FireAndForget(async () => await new PathExecutor(CancellationContext.Instance.Cts).Pathing(pathRecorder.PathingTask)); - } + // if (pathRecording) + // { + // new TaskRunner(DispatcherTimerOperationEnum.UseCacheImageWithTrigger) + // .FireAndForget(async () => await new PathExecutor(CancellationContext.Instance.Cts).Pathing(pathRecorder._pathingTask)); + // } } )); } diff --git a/BetterGenshinImpact/ViewModel/Pages/MapPathingViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/MapPathingViewModel.cs index d4aa218f..32960588 100644 --- a/BetterGenshinImpact/ViewModel/Pages/MapPathingViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/MapPathingViewModel.cs @@ -10,6 +10,11 @@ using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; +using System.Threading.Tasks; +using BetterGenshinImpact.Core.Script; +using BetterGenshinImpact.GameTask; +using BetterGenshinImpact.GameTask.AutoPathing; +using BetterGenshinImpact.GameTask.Model.Enum; using Wpf.Ui.Controls; using Wpf.Ui.Violeta.Controls; @@ -18,7 +23,7 @@ namespace BetterGenshinImpact.ViewModel.Pages; public partial class MapPathingViewModel : ObservableObject, INavigationAware, IViewModel { private readonly ILogger _logger = App.GetLogger(); - private readonly string jsonPath = Global.Absolute(@"User\AutoPathing"); + public static readonly string PathJsonPath = Global.Absolute(@"User\AutoPathing"); [ObservableProperty] private ObservableCollection _pathItems = []; @@ -26,7 +31,7 @@ public partial class MapPathingViewModel : ObservableObject, INavigationAware, I private void InitScriptListViewData() { _pathItems.Clear(); - var fileInfos = LoadScriptFolder(jsonPath); + var fileInfos = LoadScriptFolder(PathJsonPath); foreach (var f in fileInfos) { try @@ -65,11 +70,11 @@ public partial class MapPathingViewModel : ObservableObject, INavigationAware, I [RelayCommand] public void OnOpenScriptsFolder() { - if (!Directory.Exists(jsonPath)) + if (!Directory.Exists(PathJsonPath)) { - Directory.CreateDirectory(jsonPath); + Directory.CreateDirectory(PathJsonPath); } - Process.Start("explorer.exe", jsonPath); + Process.Start("explorer.exe", PathJsonPath); } [RelayCommand] @@ -82,13 +87,14 @@ public partial class MapPathingViewModel : ObservableObject, INavigationAware, I Process.Start("explorer.exe", item.ProjectPath); } - // [RelayCommand] - // public async Task OnStartRun(ScriptProject? item) - // { - // if (item == null) - // { - // return; - // } - // await _scriptService.RunMulti([item.FolderName]); - // } + [RelayCommand] + public async Task OnStart(PathingTask? item) + { + if (item == null) + { + return; + } + await new TaskRunner(DispatcherTimerOperationEnum.UseSelfCaptureImage) + .RunAsync(async () => await new PathExecutor(CancellationContext.Instance.Cts).Pathing(item)); + } }