From a06f0fcdb2e5f0a5bd3ed484ca948b8df238e775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=89=E9=B8=AD=E8=9B=8B?= Date: Mon, 9 Sep 2024 21:57:48 +0800 Subject: [PATCH] auto pathing: fix not releasing the mouse and keyboard when stopping tasks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新日志和黑名单 移除 `PathExecutor.cs` 中的无用引用,重构 `Pathing` 方法,添加 `InitializePathing` 和 `ConvertWaypoints` 方法,提取传送点处理逻辑到 `HandleTeleportWaypoint` 方法。修改 `TpTask.cs` 中的日志格式为浮点数格式。将 `TaskRunner.cs` 中的 `FireAndForgetAsync` 方法重命名为 `RunThreadAsync`,并在 `ScriptService.cs` 中相应替换调用。为 `DpiHelper.cs` 中的 `ScaleY` 属性添加注释。更新 `pick_black_lists.json`,添加新的黑名单项 `"摆放巧像"`。在 `MapPathingViewModel.cs` 中添加 `_mapViewer` 字段,并在 `OnOpenMapViewer` 方法中使用。 --- .../GameTask/AutoPathing/PathExecutor.cs | 87 +++++++++++-------- .../GameTask/AutoTrackPath/TpTask.cs | 2 +- BetterGenshinImpact/GameTask/TaskRunner.cs | 2 +- BetterGenshinImpact/Helpers/DpiHelper.cs | 3 + BetterGenshinImpact/Service/ScriptService.cs | 4 +- .../User/pick_black_lists.json | 1 + .../ViewModel/Pages/MapPathingViewModel.cs | 5 +- 7 files changed, 64 insertions(+), 40 deletions(-) diff --git a/BetterGenshinImpact/GameTask/AutoPathing/PathExecutor.cs b/BetterGenshinImpact/GameTask/AutoPathing/PathExecutor.cs index 466d5e95..6a6c0451 100644 --- a/BetterGenshinImpact/GameTask/AutoPathing/PathExecutor.cs +++ b/BetterGenshinImpact/GameTask/AutoPathing/PathExecutor.cs @@ -2,7 +2,6 @@ using BetterGenshinImpact.GameTask.AutoPathing.Model; using BetterGenshinImpact.GameTask.AutoPathing.Model.Enum; using BetterGenshinImpact.GameTask.AutoTrackPath; -using BetterGenshinImpact.GameTask.Common; using BetterGenshinImpact.GameTask.Common.BgiVision; using BetterGenshinImpact.GameTask.Common.Map; using BetterGenshinImpact.GameTask.Model.Area; @@ -16,7 +15,6 @@ using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; -using BetterGenshinImpact.Helpers; using Vanara.PInvoke; using static BetterGenshinImpact.GameTask.Common.TaskControl; @@ -28,22 +26,59 @@ public class PathExecutor(CancellationTokenSource cts) public async Task Pathing(PathingTask task) { - _dpi = DpiHelper.ScaleY; - if (task.Positions.Count == 0) + _dpi = TaskContext.Instance().DpiScale; + if (!task.Positions.Any()) { Logger.LogWarning("没有路径点,寻路结束"); return; } - task.Positions.First().Type = WaypointType.Teleport.Code; + InitializePathing(task); - // 初始化查看地图 + var waypoints = ConvertWaypoints(task.Positions); + + await Delay(100, cts); + Navigation.WarmUp(); // 提前加载地图特征点 + + try + { + foreach (var waypoint in waypoints) + { + if (waypoint.Type == WaypointType.Teleport.Code) + { + await HandleTeleportWaypoint(waypoint); + } + else + { + // Path不用走得很近,Target需要接近,但都需要先移动到对应位置 + await MoveTo(waypoint); + + if (waypoint.Type == WaypointType.Target.Code || !string.IsNullOrEmpty(waypoint.Action)) + { + await MoveCloseTo(waypoint); + } + } + } + } + finally + { + // 不管咋样,松开所有按键 + Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W); + Simulation.SendInput.Mouse.RightButtonUp(); + } + } + + private void InitializePathing(PathingTask task) + { + task.Positions.First().Type = WaypointType.Teleport.Code; WeakReferenceMessenger.Default.Send(new PropertyChangedMessage(this, "UpdateCurrentPathing", new object(), task)); + } - // 大地图传送的时候使用游戏坐标,追踪的时候应该使用2048地图图像坐标,这里临时做转换,后续改进 + private List ConvertWaypoints(List positions) + { var waypoints = new List(); - foreach (var waypoint in task.Positions) + foreach (var waypoint in positions) { if (waypoint.Type == WaypointType.Teleport.Code) { @@ -59,30 +94,14 @@ public class PathExecutor(CancellationTokenSource cts) (waypointCopy.X, waypointCopy.Y) = MapCoordinate.GameToMain2048(waypoint.X, waypoint.Y); waypoints.Add(waypointCopy); } + return waypoints; + } - await Delay(100, cts); - Navigation.WarmUp(); // 提前加载地图特征点 - - foreach (var waypoint in waypoints) - { - if (waypoint.Type == WaypointType.Teleport.Code) - { - // Logger.LogInformation("正在传送到{x},{y}", waypoint.X, waypoint.Y); - var (tpX, tpY) = await new TpTask(cts).Tp(waypoint.X, waypoint.Y); - var (tprX, tprY) = MapCoordinate.GameToMain2048(tpX, tpY); - EntireMap.Instance.SetPrevPosition((float)tprX, (float)tprY); // 通过上一个位置直接进行局部特征匹配 - continue; - } - - // Path不用走得很近,Target需要接近,但都需要先移动到对应位置 - - await MoveTo(waypoint); - - if (waypoint.Type == WaypointType.Target.Code || !string.IsNullOrEmpty(waypoint.Action)) - { - await MoveCloseTo(waypoint); - } - } + private async Task HandleTeleportWaypoint(Waypoint waypoint) + { + var (tpX, tpY) = await new TpTask(cts).Tp(waypoint.X, waypoint.Y); + var (tprX, tprY) = MapCoordinate.GameToMain2048(tpX, tpY); + EntireMap.Instance.SetPrevPosition((float)tprX, (float)tprY); // 通过上一个位置直接进行局部特征匹配 } private async Task MoveTo(Waypoint waypoint) @@ -90,7 +109,7 @@ public class PathExecutor(CancellationTokenSource cts) var screen = CaptureToRectArea(); var position = Navigation.GetPosition(screen); var targetOrientation = Navigation.GetTargetOrientation(waypoint, position); - Logger.LogInformation("粗略接近途经点,位置({x2},{y2})", waypoint.X, waypoint.Y); + Logger.LogInformation("粗略接近途经点,位置({x2},{y2})", $"{waypoint.X:F1}", $"{waypoint.Y:F1}"); await WaitUntilRotatedTo(targetOrientation, 5); var startTime = DateTime.UtcNow; var lastPositionRecord = DateTime.UtcNow; @@ -195,7 +214,7 @@ public class PathExecutor(CancellationTokenSource cts) var screen = CaptureToRectArea(); var position = Navigation.GetPosition(screen); var targetOrientation = Navigation.GetTargetOrientation(waypoint, position); - Logger.LogInformation("精确接近目标点,位置({x2},{y2})", waypoint.X, waypoint.Y); + Logger.LogInformation("精确接近目标点,位置({x2},{y2})", $"{waypoint.X:F1}", $"{waypoint.Y:F1}"); if (waypoint.MoveMode == MoveModeEnum.Fly.Code && waypoint.Action == ActionEnum.StopFlying.Code) { //下落攻击接近目的地 @@ -239,8 +258,6 @@ public class PathExecutor(CancellationTokenSource cts) { Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W); } - // 不管咋样,抬起w键 - Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W); } private int RotateTo(int targetOrientation, ImageRegion imageRegion, double controlRatio = 1) diff --git a/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs b/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs index 0c29bd44..5403802e 100644 --- a/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs +++ b/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs @@ -37,7 +37,7 @@ public class TpTask(CancellationTokenSource cts) { // 获取最近的传送点位置 var (x, y) = GetRecentlyTpPoint(tpX, tpY); - Logger.LogInformation("({TpX},{TpY}) 最近的传送点位置 ({X},{Y})", tpX, tpY, x, y); + Logger.LogInformation("({TpX},{TpY}) 最近的传送点位置 ({X},{Y})", $"{tpX:F1}", $"{tpY:F1}", $"{x:F1}", $"{y:F1}"); // M 打开地图识别当前位置,中心点为当前位置 using var ra1 = CaptureToRectArea(); diff --git a/BetterGenshinImpact/GameTask/TaskRunner.cs b/BetterGenshinImpact/GameTask/TaskRunner.cs index 9d5981d3..97a98215 100644 --- a/BetterGenshinImpact/GameTask/TaskRunner.cs +++ b/BetterGenshinImpact/GameTask/TaskRunner.cs @@ -94,7 +94,7 @@ public class TaskRunner Task.Run(() => RunAsync(action)); } - public async Task FireAndForgetAsync(Func action) + public async Task RunThreadAsync(Func action) { await Task.Run(() => RunAsync(action)); } diff --git a/BetterGenshinImpact/Helpers/DpiHelper.cs b/BetterGenshinImpact/Helpers/DpiHelper.cs index 2b618592..7abd2afb 100644 --- a/BetterGenshinImpact/Helpers/DpiHelper.cs +++ b/BetterGenshinImpact/Helpers/DpiHelper.cs @@ -8,6 +8,9 @@ namespace BetterGenshinImpact.Helpers; public class DpiHelper { + /// + /// 只能主线程调用 + /// public static float ScaleY => GetScaleY(); private static float GetScaleY() diff --git a/BetterGenshinImpact/Service/ScriptService.cs b/BetterGenshinImpact/Service/ScriptService.cs index 525feda1..e05df48d 100644 --- a/BetterGenshinImpact/Service/ScriptService.cs +++ b/BetterGenshinImpact/Service/ScriptService.cs @@ -44,7 +44,7 @@ public partial class ScriptService(HomePageViewModel homePageViewModel) : IScrip // 循环执行所有脚本 var timerOperation = hasTimer ? DispatcherTimerOperationEnum.UseCacheImageWithTriggerEmpty : DispatcherTimerOperationEnum.UseSelfCaptureImage; await new TaskRunner(timerOperation) - .RunAsync(async () => + .RunThreadAsync(async () => { foreach (var project in projects) { @@ -145,7 +145,7 @@ public partial class ScriptService(HomePageViewModel homePageViewModel) : IScrip var timerOperation = hasTimer ? DispatcherTimerOperationEnum.UseCacheImageWithTriggerEmpty : DispatcherTimerOperationEnum.UseSelfCaptureImage; await new TaskRunner(timerOperation) - .FireAndForgetAsync(async () => + .RunThreadAsync(async () => { foreach (var project in list) { diff --git a/BetterGenshinImpact/User/pick_black_lists.json b/BetterGenshinImpact/User/pick_black_lists.json index 745ff11c..ab9ee3c0 100644 --- a/BetterGenshinImpact/User/pick_black_lists.json +++ b/BetterGenshinImpact/User/pick_black_lists.json @@ -2,6 +2,7 @@ "石之轮", "幻想真境剧诗", "开始演奏", + "摆放巧像", "摹刻巧像", "摹刻码像", "募刻巧像", diff --git a/BetterGenshinImpact/ViewModel/Pages/MapPathingViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/MapPathingViewModel.cs index 738957b1..2a506794 100644 --- a/BetterGenshinImpact/ViewModel/Pages/MapPathingViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/MapPathingViewModel.cs @@ -28,6 +28,8 @@ public partial class MapPathingViewModel : ObservableObject, INavigationAware, I [ObservableProperty] private ObservableCollection _pathItems = []; + private MapViewer? _mapViewer; + private void InitScriptListViewData() { _pathItems.Clear(); @@ -106,6 +108,7 @@ public partial class MapPathingViewModel : ObservableObject, INavigationAware, I [RelayCommand] public void OnOpenMapViewer() { - new MapViewer().Show(); + _mapViewer ??= new MapViewer(); + _mapViewer.Show(); } }