From 4243972eebb83875afc9eb115fe8cc9ad7b472c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=89=E9=B8=AD=E8=9B=8B?= Date: Sun, 21 Jul 2024 12:42:39 +0800 Subject: [PATCH] script async test --- .../Core/Script/CancellationContext.cs | 24 ++++ .../Core/Script/Dependence/Genshin.cs | 12 ++ .../Core/Script/Dependence/GlobalMethod.cs | 11 ++ .../{ => Core}/Script/Dependence/Log.cs | 2 +- .../{ => Core}/Script/EngineExtend.cs | 8 +- .../AutoTrackPath/Model/GiWorldPosition.cs | 4 +- .../GameTask/BaseTaskThread.cs | 120 ------------------ .../GameTask/Common/BgiVision/TpTask.cs | 10 +- BetterGenshinImpact/GameTask/TaskRunner.cs | 22 +++- .../Script/Dependence/Genshin.cs | 5 - .../Script/Dependence/GlobalMethod.cs | 12 -- .../View/Controls/Webview/WebpagePanel.cs | 2 +- .../ViewModel/Pages/ScriptControlViewModel.cs | 38 ++++-- 13 files changed, 104 insertions(+), 166 deletions(-) create mode 100644 BetterGenshinImpact/Core/Script/CancellationContext.cs create mode 100644 BetterGenshinImpact/Core/Script/Dependence/Genshin.cs create mode 100644 BetterGenshinImpact/Core/Script/Dependence/GlobalMethod.cs rename BetterGenshinImpact/{ => Core}/Script/Dependence/Log.cs (91%) rename BetterGenshinImpact/{ => Core}/Script/EngineExtend.cs (76%) delete mode 100644 BetterGenshinImpact/GameTask/BaseTaskThread.cs delete mode 100644 BetterGenshinImpact/Script/Dependence/Genshin.cs delete mode 100644 BetterGenshinImpact/Script/Dependence/GlobalMethod.cs diff --git a/BetterGenshinImpact/Core/Script/CancellationContext.cs b/BetterGenshinImpact/Core/Script/CancellationContext.cs new file mode 100644 index 00000000..1a419d82 --- /dev/null +++ b/BetterGenshinImpact/Core/Script/CancellationContext.cs @@ -0,0 +1,24 @@ +using BetterGenshinImpact.Model; +using System.Threading; + +namespace BetterGenshinImpact.Core.Script; + +public class CancellationContext : Singleton +{ + public CancellationTokenSource Cts { get; set; } = new(); + + public void Set() + { + Cts = new CancellationTokenSource(); + } + + public void Cancel() + { + Cts.Cancel(); + } + + public void Clear() + { + Cts.Dispose(); + } +} diff --git a/BetterGenshinImpact/Core/Script/Dependence/Genshin.cs b/BetterGenshinImpact/Core/Script/Dependence/Genshin.cs new file mode 100644 index 00000000..be35d0fb --- /dev/null +++ b/BetterGenshinImpact/Core/Script/Dependence/Genshin.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; +using BetterGenshinImpact.GameTask.Common.BgiVision; + +namespace BetterGenshinImpact.Core.Script.Dependence; + +public class Genshin +{ + public async Task Tp(double x, double y) + { + await new TpTask(CancellationContext.Instance.Cts).Tp(x, y); + } +} diff --git a/BetterGenshinImpact/Core/Script/Dependence/GlobalMethod.cs b/BetterGenshinImpact/Core/Script/Dependence/GlobalMethod.cs new file mode 100644 index 00000000..7ea4cd97 --- /dev/null +++ b/BetterGenshinImpact/Core/Script/Dependence/GlobalMethod.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; + +namespace BetterGenshinImpact.Core.Script.Dependence; + +public class GlobalMethod +{ + public static async Task Sleep(int millisecondsTimeout) + { + await Task.Delay(millisecondsTimeout, CancellationContext.Instance.Cts.Token); + } +} diff --git a/BetterGenshinImpact/Script/Dependence/Log.cs b/BetterGenshinImpact/Core/Script/Dependence/Log.cs similarity index 91% rename from BetterGenshinImpact/Script/Dependence/Log.cs rename to BetterGenshinImpact/Core/Script/Dependence/Log.cs index 825120d0..59f2cce7 100644 --- a/BetterGenshinImpact/Script/Dependence/Log.cs +++ b/BetterGenshinImpact/Core/Script/Dependence/Log.cs @@ -1,6 +1,6 @@ using Microsoft.Extensions.Logging; -namespace BetterGenshinImpact.Script.Dependence; +namespace BetterGenshinImpact.Core.Script.Dependence; public class Log { diff --git a/BetterGenshinImpact/Script/EngineExtend.cs b/BetterGenshinImpact/Core/Script/EngineExtend.cs similarity index 76% rename from BetterGenshinImpact/Script/EngineExtend.cs rename to BetterGenshinImpact/Core/Script/EngineExtend.cs index 8cdc2968..2892254f 100644 --- a/BetterGenshinImpact/Script/EngineExtend.cs +++ b/BetterGenshinImpact/Core/Script/EngineExtend.cs @@ -1,8 +1,8 @@ -using BetterGenshinImpact.Script.Dependence; -using System.Threading.Tasks; +using System.Threading.Tasks; using Microsoft.ClearScript; +using BetterGenshinImpact.Core.Script.Dependence; -namespace BetterGenshinImpact.Script; +namespace BetterGenshinImpact.Core.Script; public class EngineExtend { @@ -11,7 +11,7 @@ public class EngineExtend // engine.AddHostObject("xHost", new ExtendedHostFunctions()); // 有越权的安全风险 // 添加我的自定义实例化对象 - engine.AddHostObject("gi", new Script.Dependence.Genshin()); + engine.AddHostObject("genshin", new Dependence.Genshin()); engine.AddHostObject("log", new Log()); // 添加方法 diff --git a/BetterGenshinImpact/GameTask/AutoTrackPath/Model/GiWorldPosition.cs b/BetterGenshinImpact/GameTask/AutoTrackPath/Model/GiWorldPosition.cs index 977e85ad..ac0b42da 100644 --- a/BetterGenshinImpact/GameTask/AutoTrackPath/Model/GiWorldPosition.cs +++ b/BetterGenshinImpact/GameTask/AutoTrackPath/Model/GiWorldPosition.cs @@ -28,6 +28,6 @@ public class GiWorldPosition /// public decimal[] Position { get; set; } = new decimal[3]; - public double X => (double)Position[2]; // a - public double Y => (double)Position[0]; // c + public double X => (double)Position[2]; // c + public double Y => (double)Position[0]; // a } diff --git a/BetterGenshinImpact/GameTask/BaseTaskThread.cs b/BetterGenshinImpact/GameTask/BaseTaskThread.cs deleted file mode 100644 index f96790c4..00000000 --- a/BetterGenshinImpact/GameTask/BaseTaskThread.cs +++ /dev/null @@ -1,120 +0,0 @@ -using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Exception; -using BetterGenshinImpact.GameTask.Model; -using BetterGenshinImpact.GameTask.Model.Enum; -using BetterGenshinImpact.Service.Notification; -using BetterGenshinImpact.View.Drawable; -using BetterGenshinImpact.ViewModel.Pages; -using Microsoft.Extensions.Logging; -using System; -using System.Threading.Tasks; -using static BetterGenshinImpact.GameTask.Common.TaskControl; - -namespace BetterGenshinImpact.GameTask; - -/// -/// 和触发器的区别:任务不需要持续捕获游戏图像 -/// -public class BaseTaskThread -{ - private readonly ILogger _logger = App.GetLogger(); - - protected BaseTaskParam _taskParam; - - protected BaseTaskThread(BaseTaskParam taskParam) - { - _taskParam = taskParam; - } - - /// - /// 加锁并独立运行任务 - /// - /// - /// - public async Task StandaloneRunAsync(bool useLock = true) - { - // 加锁 - var hasLock = false; - if (useLock) - { - hasLock = await TaskSemaphore.WaitAsync(0); - if (!hasLock) - { - _logger.LogError("{Name} 启动失败:当前存在正在运行中的独立任务,请不要重复执行任务!", _taskParam.Name); - return; - } - } - - try - { - _logger.LogInformation("→ {Text}", _taskParam.Name + "启动!"); - - // 初始化 - Init(); - - // 发送运行任务通知 - SendNotification(); - - await OnRunAsync(); - } - catch (NormalEndException e) - { - _logger.LogInformation("{Name} 中断:{Msg}", _taskParam.Name, e.Message); - SendNotification(); - } - catch (Exception e) - { - _logger.LogError(e.Message); - _logger.LogDebug(e.StackTrace); - SendNotification(); - } - finally - { - End(); - _logger.LogInformation("→ {Text}", _taskParam.Name + "结束"); - - // 释放锁 - if (useLock && hasLock) - { - TaskSemaphore.Release(); - } - } - } - - /// - /// 任务运行逻辑 - /// - /// - public virtual async Task OnRunAsync() - { - await Task.Delay(0); - } - - public void Init() - { - if (_taskParam.TriggerOperation == DispatcherTimerOperationEnum.StopTimer) - { - TaskTriggerDispatcher.Instance().SetCacheCaptureMode(DispatcherCaptureModeEnum.Stop); - } - else if (_taskParam.TriggerOperation == DispatcherTimerOperationEnum.UseCacheImage) - { - TaskTriggerDispatcher.Instance().SetCacheCaptureMode(DispatcherCaptureModeEnum.OnlyCacheCapture); - } - } - - public void End() - { - VisionContext.Instance().DrawContent.ClearAll(); - if (_taskParam.TriggerOperation == DispatcherTimerOperationEnum.StopTimer) - { - TaskTriggerDispatcher.Instance().SetCacheCaptureMode(DispatcherCaptureModeEnum.Start); - } - else if (_taskParam.TriggerOperation == DispatcherTimerOperationEnum.UseCacheImage) - { - TaskTriggerDispatcher.Instance().SetCacheCaptureMode(DispatcherCaptureModeEnum.CacheCaptureWithTrigger); - } - } - - public void SendNotification() - { - } -} diff --git a/BetterGenshinImpact/GameTask/Common/BgiVision/TpTask.cs b/BetterGenshinImpact/GameTask/Common/BgiVision/TpTask.cs index 68a619cf..d35699b9 100644 --- a/BetterGenshinImpact/GameTask/Common/BgiVision/TpTask.cs +++ b/BetterGenshinImpact/GameTask/Common/BgiVision/TpTask.cs @@ -45,7 +45,7 @@ public class TpTask(CancellationTokenSource cts) // M 打开地图识别当前位置,中心点为当前位置 Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_M); - Sleep(1000); + await Delay(1000, cts); // 计算传送点位置离哪个地图切换后的中心点最近,切换到该地图 await SwitchRecentlyCountryMap(x, y); @@ -179,6 +179,10 @@ public class TpTask(CancellationTokenSource cts) if (mapScaleButtonRa.IsExist()) { var rect = BigMap.Instance.GetBigMapPositionByFeatureMatch(ra.SrcGreyMat); + if (rect == Rect.Empty) + { + throw new InvalidOperationException("识别大地图位置失败"); + } Debug.WriteLine("识别大地图在全地图位置矩形:" + rect); const int s = 4 * 2; // 相对1024做4倍缩放 return MapCoordinate.Main2048ToGame(new Rect(rect.X * s, rect.Y * s, rect.Width * s, rect.Height * s)); @@ -235,14 +239,14 @@ public class TpTask(CancellationTokenSource cts) if (minCountry != "当前位置") { GameCaptureRegion.GameRegionClick((rect, scale) => (rect.Width - 160 * scale, rect.Height - 60 * scale)); - await Delay(200, cts); + await Delay(300, cts); var ra = GetRectAreaFromDispatcher(); var list = ra.FindMulti(new RecognitionObject { RecognitionType = RecognitionTypes.Ocr, RegionOfInterest = new Rect(ra.Width / 2, 0, ra.Width / 2, ra.Height) }); - list.FirstOrDefault(r => r.Text.Contains(minCountry))?.Click(); + list.FirstOrDefault(r => r.Text.Length == minCountry.Length && !r.Text.Contains("委托") && r.Text.Contains(minCountry))?.Click(); Logger.LogInformation("切换到区域:{Country}", minCountry); await Delay(500, cts); } diff --git a/BetterGenshinImpact/GameTask/TaskRunner.cs b/BetterGenshinImpact/GameTask/TaskRunner.cs index 61d10cd7..265e13bc 100644 --- a/BetterGenshinImpact/GameTask/TaskRunner.cs +++ b/BetterGenshinImpact/GameTask/TaskRunner.cs @@ -1,12 +1,13 @@ -using System; +using BetterGenshinImpact.Core.Script; using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Exception; -using BetterGenshinImpact.GameTask.Model; using BetterGenshinImpact.GameTask.Model.Enum; using BetterGenshinImpact.View.Drawable; using Microsoft.Extensions.Logging; +using System; using System.Threading.Tasks; +using System.Windows.Forms; +using BetterGenshinImpact.GameTask.Common; using static BetterGenshinImpact.GameTask.Common.TaskControl; -using System.Threading; namespace BetterGenshinImpact.GameTask; @@ -15,7 +16,7 @@ namespace BetterGenshinImpact.GameTask; /// public class TaskRunner { - private readonly ILogger _logger = App.GetLogger(); + private readonly ILogger _logger = App.GetLogger(); private readonly DispatcherTimerOperationEnum _timerOperation = DispatcherTimerOperationEnum.None; @@ -49,12 +50,17 @@ public class TaskRunner { _logger.LogInformation("→ {Text}", _name + "任务启动!"); + // 激活原神窗口 + SystemControl.ActivateWindow(); + // 初始化 Init(); // 发送运行任务通知 SendNotification(); + CancellationContext.Instance.Set(); + await action(); } catch (NormalEndException e) @@ -74,6 +80,8 @@ public class TaskRunner _logger.LogInformation("→ {Text}", _name + "任务结束"); SendNotification(); + CancellationContext.Instance.Clear(); + // 释放锁 if (hasLock) { @@ -82,6 +90,11 @@ public class TaskRunner } } + public void FireAndForget(Func action) + { + Task.Run(() => RunAsync(action)); + } + public void Init() { if (_timerOperation == DispatcherTimerOperationEnum.StopTimer) @@ -91,6 +104,7 @@ public class TaskRunner else if (_timerOperation == DispatcherTimerOperationEnum.UseCacheImage) { TaskTriggerDispatcher.Instance().SetCacheCaptureMode(DispatcherCaptureModeEnum.OnlyCacheCapture); + Sleep(TaskContext.Instance().Config.TriggerInterval * 5, CancellationContext.Instance.Cts); // 等待缓存图像 } } diff --git a/BetterGenshinImpact/Script/Dependence/Genshin.cs b/BetterGenshinImpact/Script/Dependence/Genshin.cs deleted file mode 100644 index 64d0a563..00000000 --- a/BetterGenshinImpact/Script/Dependence/Genshin.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace BetterGenshinImpact.Script.Dependence; - -public class Genshin -{ -} diff --git a/BetterGenshinImpact/Script/Dependence/GlobalMethod.cs b/BetterGenshinImpact/Script/Dependence/GlobalMethod.cs deleted file mode 100644 index 0ccde7c1..00000000 --- a/BetterGenshinImpact/Script/Dependence/GlobalMethod.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; - -namespace BetterGenshinImpact.Script.Dependence; - -public class GlobalMethod -{ - public static async Task Sleep(int millisecondsTimeout) - { - await Task.Delay(millisecondsTimeout); - } -} diff --git a/BetterGenshinImpact/View/Controls/Webview/WebpagePanel.cs b/BetterGenshinImpact/View/Controls/Webview/WebpagePanel.cs index 3068536e..9126f063 100644 --- a/BetterGenshinImpact/View/Controls/Webview/WebpagePanel.cs +++ b/BetterGenshinImpact/View/Controls/Webview/WebpagePanel.cs @@ -28,7 +28,7 @@ public class WebpagePanel : UserControl { CreationProperties = new CoreWebView2CreationProperties { - UserDataFolder = Path.Combine(new FileInfo(Environment.ProcessPath!).DirectoryName!, @"WebView2_Data\\") + UserDataFolder = Path.Combine(new FileInfo(Environment.ProcessPath!).DirectoryName!, @"WebView2Data\\") } }; _webView.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted; diff --git a/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs index bf8b2c01..d60e428d 100644 --- a/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs @@ -1,17 +1,17 @@ -using BetterGenshinImpact.Model; +using BetterGenshinImpact.Core.Script; +using BetterGenshinImpact.Model; using CommunityToolkit.Mvvm.ComponentModel; using Microsoft.ClearScript; using Microsoft.ClearScript.V8; using System.Collections.ObjectModel; using System.Diagnostics; -using BetterGenshinImpact.Script.Dependence; -using Vanara.PInvoke; -using Wpf.Ui.Controls; -using static System.Net.Mime.MediaTypeNames; -using Microsoft.ClearScript.JavaScript; +using System.Threading; using System.Threading.Tasks; +using BetterGenshinImpact.GameTask; +using BetterGenshinImpact.GameTask.Common.BgiVision; +using Wpf.Ui.Controls; +using BetterGenshinImpact.GameTask.Model.Enum; using System; -using BetterGenshinImpact.Script; namespace BetterGenshinImpact.ViewModel.Pages; @@ -49,12 +49,22 @@ public partial class ScriptControlViewModel : ObservableObject, INavigationAware EngineExtend.InitHost(engine); // 执行脚本 - engine.Execute(@" -(async function() { - log.info('等待 {m} s', 3); - await sleep(3000); - log.info('test {name}', '你好'); -})(); -"); + // new TaskRunner(DispatcherTimerOperationEnum.UseCacheImage).FireAndForget(async () => + // await new TpTask(CancellationContext.Instance.Cts) + // .Tp(3452.310059, 2290.465088)); + + new TaskRunner(DispatcherTimerOperationEnum.UseCacheImage).FireAndForget(async () => + { + await (Task)engine.Evaluate(@" + (async function() { + log.info('等待 {m} s', 1); + await sleep(1000); + log.info('测试 {name}', 'TP方法'); + await genshin.tp(3452.310059,2290.465088); + log.warn('TP完成'); + await sleep(1000); + })(); + "); + }); } }