Merge pull request #726 from babalae/feat-cts

refactor: CancellationTokenSource -> CancellationToken
This commit is contained in:
辉鸭蛋 2024-10-19 13:10:38 +08:00 committed by GitHub
commit 790d42cee0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 278 additions and 256 deletions

View File

@ -9,7 +9,7 @@ public class AutoPathingScript(string rootPath)
public async Task Run(string json) public async Task Run(string json)
{ {
var task = PathingTask.BuildFromJson(json); var task = PathingTask.BuildFromJson(json);
await new PathExecutor(CancellationContext.Instance.Cts).Pathing(task); await new PathExecutor(CancellationContext.Instance.Cts.Token).Pathing(task);
} }
public async Task RunFile(string path) public async Task RunFile(string path)

View File

@ -77,7 +77,7 @@ public class Dispatcher
{ {
return; return;
} }
await new AutoDomainTask(new AutoDomainParam(0, path)).Start(CancellationContext.Instance.Cts); await new AutoDomainTask(new AutoDomainParam(0, path)).Start(CancellationContext.Instance.Cts.Token);
break; break;
case "AutoMusicGame": case "AutoMusicGame":

View File

@ -37,7 +37,7 @@ public class Genshin
/// <returns></returns> /// <returns></returns>
public async Task Tp(double x, double y) public async Task Tp(double x, double y)
{ {
await new TpTask(CancellationContext.Instance.Cts).Tp(x, y); await new TpTask(CancellationContext.Instance.Cts.Token).Tp(x, y);
} }
/// <summary> /// <summary>

View File

@ -137,7 +137,7 @@ public partial class ScriptGroupProject : ObservableObject
// 加载并执行 // 加载并执行
var task = PathingTask.BuildFromFilePath(Path.Combine(MapPathingViewModel.PathJsonPath, FolderName, Name)); var task = PathingTask.BuildFromFilePath(Path.Combine(MapPathingViewModel.PathJsonPath, FolderName, Name));
TaskTriggerDispatcher.Instance().AddTrigger("AutoPick", null); TaskTriggerDispatcher.Instance().AddTrigger("AutoPick", null);
await new PathExecutor(CancellationContext.Instance.Cts).Pathing(task); await new PathExecutor(CancellationContext.Instance.Cts.Token).Pathing(task);
} }
else else
{ {

View File

@ -1,7 +1,6 @@
using BetterGenshinImpact.Core.Config; using BetterGenshinImpact.Core.Config;
using BetterGenshinImpact.Core.Recognition.OCR; using BetterGenshinImpact.Core.Recognition.OCR;
using BetterGenshinImpact.Core.Recognition.ONNX; using BetterGenshinImpact.Core.Recognition.ONNX;
using BetterGenshinImpact.Core.Script;
using BetterGenshinImpact.Core.Simulator; using BetterGenshinImpact.Core.Simulator;
using BetterGenshinImpact.GameTask.AutoFight; using BetterGenshinImpact.GameTask.AutoFight;
using BetterGenshinImpact.GameTask.AutoFight.Assets; using BetterGenshinImpact.GameTask.AutoFight.Assets;
@ -26,7 +25,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Vanara.PInvoke; using Vanara.PInvoke;
using static BetterGenshinImpact.GameTask.Common.TaskControl; using static BetterGenshinImpact.GameTask.Common.TaskControl;
using static Vanara.PInvoke.Gdi32; using static Vanara.PInvoke.Kernel32;
using static Vanara.PInvoke.User32; using static Vanara.PInvoke.User32;
namespace BetterGenshinImpact.GameTask.AutoDomain; namespace BetterGenshinImpact.GameTask.AutoDomain;
@ -43,7 +42,7 @@ public class AutoDomainTask : ISoloTask
private readonly CombatScriptBag _combatScriptBag; private readonly CombatScriptBag _combatScriptBag;
private CancellationTokenSource? _cts; private CancellationToken _ct;
public AutoDomainTask(AutoDomainParam taskParam) public AutoDomainTask(AutoDomainParam taskParam)
{ {
@ -60,9 +59,9 @@ public class AutoDomainTask : ISoloTask
_combatScriptBag = CombatScriptParser.ReadAndParse(_taskParam.CombatStrategyPath); _combatScriptBag = CombatScriptParser.ReadAndParse(_taskParam.CombatStrategyPath);
} }
public async Task Start(CancellationTokenSource cts) public async Task Start(CancellationToken ct)
{ {
_cts = cts; _ct = ct;
AutoFightAssets.DestroyInstance(); AutoFightAssets.DestroyInstance();
Init(); Init();
@ -169,7 +168,7 @@ public class AutoDomainTask : ISoloTask
Simulation.SendInput.Keyboard.KeyPress(VK.VK_F); Simulation.SendInput.Keyboard.KeyPress(VK.VK_F);
Logger.LogInformation("自动秘境:{Text}", "进入秘境"); Logger.LogInformation("自动秘境:{Text}", "进入秘境");
// 秘境开门动画 5s // 秘境开门动画 5s
Sleep(5000, _cts); Sleep(5000, _ct);
} }
int retryTimes = 0, clickCount = 0; int retryTimes = 0, clickCount = 0;
@ -183,11 +182,11 @@ public class AutoDomainTask : ISoloTask
clickCount++; clickCount++;
} }
Sleep(1500, _cts); Sleep(1500, _ct);
} }
// 载入动画 // 载入动画
Sleep(3000, _cts); Sleep(3000, _ct);
} }
private void CloseDomainTip() private void CloseDomainTip()
@ -200,16 +199,16 @@ public class AutoDomainTask : ISoloTask
using var cactRectArea = CaptureToRectArea().Find(AutoFightContext.Instance.FightAssets.ClickAnyCloseTipRa); using var cactRectArea = CaptureToRectArea().Find(AutoFightContext.Instance.FightAssets.ClickAnyCloseTipRa);
if (!cactRectArea.IsEmpty()) if (!cactRectArea.IsEmpty())
{ {
Sleep(1000, _cts); Sleep(1000, _ct);
cactRectArea.Click(); cactRectArea.Click();
break; break;
} }
// todo 添加小地图角标位置检测 防止有人手点了 // todo 添加小地图角标位置检测 防止有人手点了
Sleep(1000, _cts); Sleep(1000, _ct);
} }
Sleep(1500, _cts); Sleep(1500, _ct);
} }
private List<CombatCommand> FindCombatScriptAndSwitchAvatar(CombatScenes combatScenes) private List<CombatCommand> FindCombatScriptAndSwitchAvatar(CombatScenes combatScenes)
@ -226,7 +225,7 @@ public class AutoDomainTask : ISoloTask
/// </summary> /// </summary>
private async Task WalkToPressF() private async Task WalkToPressF()
{ {
if (_cts.Token.IsCancellationRequested) if (_ct.IsCancellationRequested)
{ {
return; return;
} }
@ -243,12 +242,12 @@ public class AutoDomainTask : ISoloTask
try try
{ {
while (!_cts.Token.IsCancellationRequested) while (!_ct.IsCancellationRequested)
{ {
using var fRectArea = Common.TaskControl.CaptureToRectArea().Find(AutoPickAssets.Instance.FRo); using var fRectArea = Common.TaskControl.CaptureToRectArea().Find(AutoPickAssets.Instance.FRo);
if (fRectArea.IsEmpty()) if (fRectArea.IsEmpty())
{ {
Sleep(100, _cts); Sleep(100, _ct);
} }
else else
{ {
@ -273,8 +272,8 @@ public class AutoDomainTask : ISoloTask
private Task StartFight(CombatScenes combatScenes, List<CombatCommand> combatCommands) private Task StartFight(CombatScenes combatScenes, List<CombatCommand> combatCommands)
{ {
CancellationTokenSource cts = new(); CancellationTokenSource cts = new();
_cts.Token.Register(cts.Cancel); _ct.Register(cts.Cancel);
combatScenes.BeforeTask(cts); combatScenes.BeforeTask(cts.Token);
// 战斗操作 // 战斗操作
var combatTask = new Task(() => var combatTask = new Task(() =>
{ {
@ -307,7 +306,7 @@ public class AutoDomainTask : ISoloTask
// 对局结束检测 // 对局结束检测
var domainEndTask = DomainEndDetectionTask(cts); var domainEndTask = DomainEndDetectionTask(cts);
// 自动吃药 // 自动吃药
var autoEatRecoveryHpTask = AutoEatRecoveryHpTask(cts); var autoEatRecoveryHpTask = AutoEatRecoveryHpTask(cts.Token);
combatTask.Start(); combatTask.Start();
domainEndTask.Start(); domainEndTask.Start();
autoEatRecoveryHpTask.Start(); autoEatRecoveryHpTask.Start();
@ -316,7 +315,7 @@ public class AutoDomainTask : ISoloTask
private void EndFightWait() private void EndFightWait()
{ {
if (_cts.Token.IsCancellationRequested) if (_ct.IsCancellationRequested)
{ {
return; return;
} }
@ -325,7 +324,7 @@ public class AutoDomainTask : ISoloTask
if (s > 0) if (s > 0)
{ {
Logger.LogInformation("战斗结束后等待 {Second} 秒", s); Logger.LogInformation("战斗结束后等待 {Second} 秒", s);
Sleep((int)(s * 1000), _cts); Sleep((int)(s * 1000), _ct);
} }
} }
@ -338,7 +337,7 @@ public class AutoDomainTask : ISoloTask
{ {
try try
{ {
while (!_cts.Token.IsCancellationRequested) while (!_ct.IsCancellationRequested)
{ {
if (IsDomainEnd()) if (IsDomainEnd())
{ {
@ -346,7 +345,7 @@ public class AutoDomainTask : ISoloTask
break; break;
} }
await Delay(1000, cts); await Delay(1000, cts.Token);
} }
} }
catch catch
@ -378,7 +377,7 @@ public class AutoDomainTask : ISoloTask
return false; return false;
} }
private Task AutoEatRecoveryHpTask(CancellationTokenSource cts) private Task AutoEatRecoveryHpTask(CancellationToken ct)
{ {
return new Task(async () => return new Task(async () =>
{ {
@ -394,7 +393,7 @@ public class AutoDomainTask : ISoloTask
try try
{ {
while (!_cts.Token.IsCancellationRequested) while (!_ct.IsCancellationRequested)
{ {
if (IsLowHealth()) if (IsLowHealth())
{ {
@ -404,13 +403,13 @@ public class AutoDomainTask : ISoloTask
// TODO 吃饱了会一直吃 // TODO 吃饱了会一直吃
} }
await Delay(500, cts); await Delay(500, ct);
} }
} }
catch catch
{ {
} }
}, cts.Token); }, ct);
} }
private bool IsLowHealth() private bool IsLowHealth()
@ -442,10 +441,10 @@ public class AutoDomainTask : ISoloTask
private Task FindPetrifiedTree() private Task FindPetrifiedTree()
{ {
CancellationTokenSource treeCts = new(); CancellationTokenSource treeCts = new();
_cts.Token.Register(treeCts.Cancel); _ct.Register(treeCts.Cancel);
// 中键回正视角 // 中键回正视角
Simulation.SendInput.Mouse.MiddleButtonClick(); Simulation.SendInput.Mouse.MiddleButtonClick();
Sleep(900, _cts); Sleep(900, _ct);
// 左右移动直到石化古树位于屏幕中心任务 // 左右移动直到石化古树位于屏幕中心任务
var moveAvatarTask = MoveAvatarHorizontallyTask(treeCts); var moveAvatarTask = MoveAvatarHorizontallyTask(treeCts);
@ -467,7 +466,7 @@ public class AutoDomainTask : ISoloTask
var noDetectCount = 0; var noDetectCount = 0;
var prevKey = VK.VK_A; var prevKey = VK.VK_A;
var backwardsAndForwardsCount = 0; var backwardsAndForwardsCount = 0;
while (!_cts.Token.IsCancellationRequested) while (!_ct.IsCancellationRequested)
{ {
var treeRect = DetectTree(CaptureToRectArea()); var treeRect = DetectTree(CaptureToRectArea());
if (treeRect != Rect.Empty) if (treeRect != Rect.Empty)
@ -550,7 +549,7 @@ public class AutoDomainTask : ISoloTask
else else
{ {
_simulator.KeyPress(VK.VK_W, 60); _simulator.KeyPress(VK.VK_W, 60);
Sleep(500, _cts); Sleep(500, _ct);
treeCts.Cancel(); treeCts.Cancel();
break; break;
} }
@ -595,12 +594,12 @@ public class AutoDomainTask : ISoloTask
{ {
// 左右移动5次说明已经在树中心了 // 左右移动5次说明已经在树中心了
_simulator.KeyPress(VK.VK_W, 60); _simulator.KeyPress(VK.VK_W, 60);
Sleep(500, _cts); Sleep(500, _ct);
treeCts.Cancel(); treeCts.Cancel();
break; break;
} }
Sleep(60, _cts); Sleep(60, _ct);
} }
VisionContext.Instance().DrawContent.ClearAll(); VisionContext.Instance().DrawContent.ClearAll();
@ -701,7 +700,7 @@ public class AutoDomainTask : ISoloTask
private bool GettingTreasure(bool recognizeResin, bool isLastTurn) private bool GettingTreasure(bool recognizeResin, bool isLastTurn)
{ {
// 等待窗口弹出 // 等待窗口弹出
Sleep(1500, _cts); Sleep(1500, _ct);
// 优先使用浓缩树脂 // 优先使用浓缩树脂
var retryTimes = 0; var retryTimes = 0;
@ -720,22 +719,22 @@ public class AutoDomainTask : ISoloTask
useCondensedResinRa.Click(); useCondensedResinRa.Click();
// 点两下 #224 #218 // 点两下 #224 #218
// 解决水龙王按下左键后没松开,然后后续点击按下就没反应了 // 解决水龙王按下左键后没松开,然后后续点击按下就没反应了
Sleep(400, _cts); Sleep(400, _ct);
useCondensedResinRa.Click(); useCondensedResinRa.Click();
break; break;
} }
Sleep(800, _cts); Sleep(800, _ct);
} }
Sleep(1000, _cts); Sleep(1000, _ct);
var captureArea = TaskContext.Instance().SystemInfo.CaptureAreaRect; var captureArea = TaskContext.Instance().SystemInfo.CaptureAreaRect;
for (var i = 0; i < 30; i++) for (var i = 0; i < 30; i++)
{ {
// 跳过领取动画 // 跳过领取动画
GameCaptureRegion.GameRegionClick((size, scale) => (size.Width - 140 * scale, 53 * scale)); GameCaptureRegion.GameRegionClick((size, scale) => (size.Width - 140 * scale, 53 * scale));
Sleep(200, _cts); Sleep(200, _ct);
GameCaptureRegion.GameRegionClick((size, scale) => (size.Width - 140 * scale, 53 * scale)); GameCaptureRegion.GameRegionClick((size, scale) => (size.Width - 140 * scale, 53 * scale));
// 优先点击继续 // 优先点击继续
@ -779,7 +778,7 @@ public class AutoDomainTask : ISoloTask
} }
} }
Sleep(300, _cts); Sleep(300, _ct);
} }
throw new NormalEndException("未检测到秘境结束,可能是背包物品已满。"); throw new NormalEndException("未检测到秘境结束,可能是背包物品已满。");

View File

@ -21,7 +21,7 @@ public class AutoFightTask : ISoloTask
private readonly CombatScriptBag _combatScriptBag; private readonly CombatScriptBag _combatScriptBag;
private CancellationTokenSource? _cts; private CancellationToken _ct;
private readonly BgiYoloV8Predictor _predictor; private readonly BgiYoloV8Predictor _predictor;
@ -38,9 +38,9 @@ public class AutoFightTask : ISoloTask
} }
} }
public async Task Start(CancellationTokenSource cts) public async Task Start(CancellationToken ct)
{ {
_cts = cts; _ct = ct;
LogScreenResolution(); LogScreenResolution();
var combatScenes = new CombatScenes().InitializeTeam(CaptureToRectArea()); var combatScenes = new CombatScenes().InitializeTeam(CaptureToRectArea());
@ -53,9 +53,9 @@ public class AutoFightTask : ISoloTask
// 新的取消token // 新的取消token
var cts2 = new CancellationTokenSource(); var cts2 = new CancellationTokenSource();
cts.Token.Register(cts2.Cancel); ct.Register(cts2.Cancel);
combatScenes.BeforeTask(cts2); combatScenes.BeforeTask(cts2.Token);
// 战斗操作 // 战斗操作
var fightTask = Task.Run(() => var fightTask = Task.Run(() =>
@ -97,7 +97,7 @@ public class AutoFightTask : ISoloTask
break; break;
} }
Sleep(1000, cts2); Sleep(1000, cts2.Token);
} }
} }
catch (Exception e) catch (Exception e)
@ -138,11 +138,11 @@ public class AutoFightTask : ISoloTask
{ {
// 旋转完毕后都没有检测到血条和怪物位置则按L键确认战斗结束 // 旋转完毕后都没有检测到血条和怪物位置则按L键确认战斗结束
List<int> angles = [0, 90, 180, 270]; List<int> angles = [0, 90, 180, 270];
var rotateTask = new CameraRotateTask(_cts!); var rotateTask = new CameraRotateTask(_ct);
foreach (var a in angles) foreach (var a in angles)
{ {
await rotateTask.WaitUntilRotatedTo(a, 5, 30); await rotateTask.WaitUntilRotatedTo(a, 5, 30);
await Delay(1000, _cts!); // 等待视角稳定 await Delay(1000, _ct!); // 等待视角稳定
if (HasFightFlag(CaptureToRectArea())) if (HasFightFlag(CaptureToRectArea()))
{ {
return false; return false;

View File

@ -72,7 +72,7 @@ public class Avatar
/// <summary> /// <summary>
/// 任务取消令牌 /// 任务取消令牌
/// </summary> /// </summary>
public CancellationTokenSource? Cts { get; set; } public CancellationToken Ct { get; set; }
/// <summary> /// <summary>
/// 战斗场景 /// 战斗场景
@ -106,7 +106,7 @@ public class Avatar
if (!confirmRectArea.IsEmpty()) if (!confirmRectArea.IsEmpty())
{ {
Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_ESCAPE); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_ESCAPE);
Sleep(600, Cts); Sleep(600, Ct);
Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_M); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_M);
throw new Exception("存在角色被击败,按 M 键打开地图,并停止自动秘境。"); throw new Exception("存在角色被击败,按 M 键打开地图,并停止自动秘境。");
} }
@ -120,7 +120,7 @@ public class Avatar
{ {
for (var i = 0; i < 30; i++) for (var i = 0; i < 30; i++)
{ {
if (Cts is { IsCancellationRequested: true }) if (Ct is { IsCancellationRequested: true })
{ {
return; return;
} }
@ -137,7 +137,7 @@ public class Avatar
AutoFightContext.Instance.Simulator.KeyPress(User32.VK.VK_1 + (byte)Index - 1); AutoFightContext.Instance.Simulator.KeyPress(User32.VK.VK_1 + (byte)Index - 1);
// Debug.WriteLine($"切换到{Index}号位"); // Debug.WriteLine($"切换到{Index}号位");
// Cv2.ImWrite($"log/切换.png", content.CaptureRectArea.SrcMat); // Cv2.ImWrite($"log/切换.png", content.CaptureRectArea.SrcMat);
Sleep(250, Cts); Sleep(250, Ct);
} }
} }
@ -248,14 +248,14 @@ public class Avatar
{ {
while (ms >= 0) while (ms >= 0)
{ {
if (Cts is { IsCancellationRequested: true }) if (Ct is { IsCancellationRequested: true })
{ {
return; return;
} }
AutoFightContext.Instance.Simulator.LeftButtonClick(); AutoFightContext.Instance.Simulator.LeftButtonClick();
ms -= 200; ms -= 200;
Sleep(200, Cts); Sleep(200, Ct);
} }
} }
@ -266,7 +266,7 @@ public class Avatar
{ {
for (var i = 0; i < 1; i++) for (var i = 0; i < 1; i++)
{ {
if (Cts is { IsCancellationRequested: true }) if (Ct is { IsCancellationRequested: true })
{ {
return; return;
} }
@ -276,7 +276,7 @@ public class Avatar
if (Name == "纳西妲") if (Name == "纳西妲")
{ {
AutoFightContext.Instance.Simulator.KeyDown(User32.VK.VK_E); AutoFightContext.Instance.Simulator.KeyDown(User32.VK.VK_E);
Sleep(300, Cts); Sleep(300, Ct);
for (int j = 0; j < 10; j++) for (int j = 0; j < 10; j++)
{ {
Simulation.SendInput.Mouse.MoveMouseBy(1000, 0); Simulation.SendInput.Mouse.MoveMouseBy(1000, 0);
@ -296,7 +296,7 @@ public class Avatar
AutoFightContext.Instance.Simulator.KeyPress(User32.VK.VK_E); AutoFightContext.Instance.Simulator.KeyPress(User32.VK.VK_E);
} }
Sleep(200, Cts); Sleep(200, Ct);
var region = CaptureToRectArea(); var region = CaptureToRectArea();
ThrowWhenDefeated(region); ThrowWhenDefeated(region);
@ -331,13 +331,13 @@ public class Avatar
// var isBurstReleased = false; // var isBurstReleased = false;
for (var i = 0; i < 10; i++) for (var i = 0; i < 10; i++)
{ {
if (Cts is { IsCancellationRequested: true }) if (Ct is { IsCancellationRequested: true })
{ {
return; return;
} }
AutoFightContext.Instance.Simulator.KeyPress(User32.VK.VK_Q); AutoFightContext.Instance.Simulator.KeyPress(User32.VK.VK_Q);
Sleep(200, Cts); Sleep(200, Ct);
var region = CaptureToRectArea(); var region = CaptureToRectArea();
ThrowWhenDefeated(region); ThrowWhenDefeated(region);
@ -345,7 +345,7 @@ public class Avatar
if (notActiveCount == 0) if (notActiveCount == 0)
{ {
// isBurstReleased = true; // isBurstReleased = true;
Sleep(1500, Cts); Sleep(1500, Ct);
return; return;
} }
// else // else
@ -381,7 +381,7 @@ public class Avatar
/// </summary> /// </summary>
public void Dash(int ms = 0) public void Dash(int ms = 0)
{ {
if (Cts is { IsCancellationRequested: true }) if (Ct is { IsCancellationRequested: true })
{ {
return; return;
} }
@ -398,7 +398,7 @@ public class Avatar
public void Walk(string key, int ms) public void Walk(string key, int ms)
{ {
if (Cts is { IsCancellationRequested: true }) if (Ct is { IsCancellationRequested: true })
{ {
return; return;
} }
@ -473,7 +473,7 @@ public class Avatar
AutoFightContext.Instance.Simulator.LeftButtonDown(); AutoFightContext.Instance.Simulator.LeftButtonDown();
while (ms >= 0) while (ms >= 0)
{ {
if (Cts is { IsCancellationRequested: true }) if (Ct is { IsCancellationRequested: true })
{ {
return; return;
} }

View File

@ -188,11 +188,11 @@ public class CombatScenes : IDisposable
return avatars; return avatars;
} }
public void BeforeTask(CancellationTokenSource cts) public void BeforeTask(CancellationToken ct)
{ {
for (var i = 0; i < AvatarCount; i++) for (var i = 0; i < AvatarCount; i++)
{ {
Avatars[i].Cts = cts; Avatars[i].Ct = ct;
} }
} }

View File

@ -53,7 +53,7 @@ public class OneKeyFightTask : Singleton<OneKeyFightTask>
if (_cts == null || _cts.Token.IsCancellationRequested) if (_cts == null || _cts.Token.IsCancellationRequested)
{ {
_cts = new CancellationTokenSource(); _cts = new CancellationTokenSource();
_fightTask = FightTask(_cts); _fightTask = FightTask(_cts.Token);
if (!_fightTask.IsCompleted) if (!_fightTask.IsCompleted)
{ {
_fightTask.Start(); _fightTask.Start();
@ -65,7 +65,7 @@ public class OneKeyFightTask : Singleton<OneKeyFightTask>
if (_cts == null || _cts.Token.IsCancellationRequested) if (_cts == null || _cts.Token.IsCancellationRequested)
{ {
_cts = new CancellationTokenSource(); _cts = new CancellationTokenSource();
_fightTask = FightTask(_cts); _fightTask = FightTask(_cts.Token);
if (!_fightTask.IsCompleted) if (!_fightTask.IsCompleted)
{ {
_fightTask.Start(); _fightTask.Start();
@ -126,14 +126,14 @@ public class OneKeyFightTask : Singleton<OneKeyFightTask>
/// <summary> /// <summary>
/// 循环执行战斗宏 /// 循环执行战斗宏
/// </summary> /// </summary>
private Task FightTask(CancellationTokenSource cts) private Task FightTask(CancellationToken ct)
{ {
// 切换截图模式 // 切换截图模式
var dispatcherCaptureMode = TaskTriggerDispatcher.Instance().GetCacheCaptureMode(); var dispatcherCaptureMode = TaskTriggerDispatcher.Instance().GetCacheCaptureMode();
if (dispatcherCaptureMode != DispatcherCaptureModeEnum.CacheCaptureWithTrigger) if (dispatcherCaptureMode != DispatcherCaptureModeEnum.CacheCaptureWithTrigger)
{ {
TaskTriggerDispatcher.Instance().SetCacheCaptureMode(DispatcherCaptureModeEnum.CacheCaptureWithTrigger); TaskTriggerDispatcher.Instance().SetCacheCaptureMode(DispatcherCaptureModeEnum.CacheCaptureWithTrigger);
Sleep(TaskContext.Instance().Config.TriggerInterval * 2, cts); // 等待缓存图像 Sleep(TaskContext.Instance().Config.TriggerInterval * 2, ct); // 等待缓存图像
} }
var imageRegion = CaptureToRectArea(); var imageRegion = CaptureToRectArea();
@ -162,7 +162,7 @@ public class OneKeyFightTask : Singleton<OneKeyFightTask>
return new Task(() => return new Task(() =>
{ {
Logger.LogInformation("→ {Name}执行宏", activeAvatar.Name); Logger.LogInformation("→ {Name}执行宏", activeAvatar.Name);
while (!cts.Token.IsCancellationRequested && IsEnabled()) while (!ct.IsCancellationRequested && IsEnabled())
{ {
if (IsHoldOnMode() && !_isKeyDown) if (IsHoldOnMode() && !_isKeyDown)
{ {

View File

@ -5,11 +5,11 @@ namespace BetterGenshinImpact.GameTask.AutoGeniusInvokation;
public class AutoGeniusInvokationTask(GeniusInvokationTaskParam taskParam) : ISoloTask public class AutoGeniusInvokationTask(GeniusInvokationTaskParam taskParam) : ISoloTask
{ {
public Task Start(CancellationTokenSource cts) public Task Start(CancellationToken ct)
{ {
// 读取策略信息 // 读取策略信息
var duel = ScriptParser.Parse(taskParam.StrategyContent); var duel = ScriptParser.Parse(taskParam.StrategyContent);
duel.Run(cts); duel.Run(ct);
return Task.CompletedTask; return Task.CompletedTask;
} }
} }

View File

@ -61,15 +61,15 @@ public class GeniusInvokationControl
public static bool OutputImageWhenError = true; public static bool OutputImageWhenError = true;
private CancellationTokenSource? _cts; private CancellationToken _ct;
private readonly AutoGeniusInvokationAssets _assets = AutoGeniusInvokationAssets.Instance; private readonly AutoGeniusInvokationAssets _assets = AutoGeniusInvokationAssets.Instance;
// private IGameCapture? _gameCapture; // private IGameCapture? _gameCapture;
public void Init(CancellationTokenSource cts) public void Init(CancellationToken ct)
{ {
_cts = cts; _ct = ct;
// _gameCapture = taskParam.Dispatcher.GameCapture; // _gameCapture = taskParam.Dispatcher.GameCapture;
} }
@ -103,7 +103,7 @@ public class GeniusInvokationControl
{ {
NewRetry.Do(() => NewRetry.Do(() =>
{ {
if (_cts is { IsCancellationRequested: true }) if (_ct is { IsCancellationRequested: true })
{ {
return; return;
} }
@ -115,7 +115,7 @@ public class GeniusInvokationControl
} }
}, TimeSpan.FromSeconds(1), 100); }, TimeSpan.FromSeconds(1), 100);
if (_cts is { IsCancellationRequested: true }) if (_ct is { IsCancellationRequested: true })
{ {
throw new TaskCanceledException("任务取消"); throw new TaskCanceledException("任务取消");
} }

View File

@ -1,11 +1,9 @@
using BetterGenshinImpact.Core.Recognition.OpenCv; using BetterGenshinImpact.Core.Recognition.OpenCv;
using BetterGenshinImpact.Core.Script;
using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Assets; using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Assets;
using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Exception; using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Exception;
using BetterGenshinImpact.GameTask.Common; using BetterGenshinImpact.GameTask.Common;
using BetterGenshinImpact.Service.Notification; using BetterGenshinImpact.Service.Notification;
using BetterGenshinImpact.View.Drawable; using BetterGenshinImpact.View.Drawable;
using BetterGenshinImpact.ViewModel.Pages;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using OpenCvSharp; using OpenCvSharp;
using System; using System;
@ -50,25 +48,22 @@ public class Duel
/// </summary> /// </summary>
public int CurrentDiceCount { get; set; } = 0; public int CurrentDiceCount { get; set; } = 0;
public CancellationTokenSource Cts { get; set; } = default!;
private int _keqingECount = 0; private int _keqingECount = 0;
public async Task RunAsync(CancellationTokenSource cts) public async Task RunAsync(CancellationToken ct)
{ {
await Task.Run(() => { Run(cts); }); await Task.Run(() => { Run(ct); }, ct);
} }
public void Run(CancellationTokenSource cts) public void Run(CancellationToken ct)
{ {
Cts = cts;
try try
{ {
AutoGeniusInvokationAssets.DestroyInstance(); AutoGeniusInvokationAssets.DestroyInstance();
LogScreenResolution(); LogScreenResolution();
NotificationHelper.SendTaskNotificationUsing(b => b.GeniusInvocation().Started().Build()); // TODO 需要移动 NotificationHelper.SendTaskNotificationUsing(b => b.GeniusInvocation().Started().Build()); // TODO 需要移动
GeniusInvokationControl.GetInstance().Init(Cts); GeniusInvokationControl.GetInstance().Init(ct);
// 对局准备 选择初始手牌 // 对局准备 选择初始手牌
GeniusInvokationControl.GetInstance().CommonDuelPrepare(); GeniusInvokationControl.GetInstance().CommonDuelPrepare();

View File

@ -1,5 +1,4 @@
using BetterGenshinImpact.Core.Script; using BetterGenshinImpact.Core.Simulator;
using BetterGenshinImpact.Core.Simulator;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using OpenCvSharp; using OpenCvSharp;
using System; using System;
@ -28,7 +27,7 @@ public class AutoMusicGameTask(AutoMusicGameParam taskParam) : ISoloTask
private readonly IntPtr _hWnd = TaskContext.Instance().GameHandle; private readonly IntPtr _hWnd = TaskContext.Instance().GameHandle;
public Task Start(CancellationTokenSource cts) public Task Start(CancellationToken ct)
{ {
Init(); Init();
@ -43,16 +42,16 @@ public class AutoMusicGameTask(AutoMusicGameParam taskParam) : ISoloTask
{ {
var (x, y) = gameCaptureRegion.ConvertPositionToGameCaptureRegion((int)(keyValuePair.Value * assetScale), (int)(_keyY * assetScale)); var (x, y) = gameCaptureRegion.ConvertPositionToGameCaptureRegion((int)(keyValuePair.Value * assetScale), (int)(_keyY * assetScale));
// 添加任务 // 添加任务
taskList.Add(taskFactory.StartNew(() => DoWhitePressWin32(cts, keyValuePair.Key, new Point(x, y)))); taskList.Add(taskFactory.StartNew(() => DoWhitePressWin32(ct, keyValuePair.Key, new Point(x, y))));
} }
Task.WaitAll([.. taskList]); Task.WaitAll([.. taskList]);
return Task.CompletedTask; return Task.CompletedTask;
} }
private void DoWhitePressWin32(CancellationTokenSource cts, User32.VK key, Point point) private void DoWhitePressWin32(CancellationToken ct, User32.VK key, Point point)
{ {
while (!cts.Token.IsCancellationRequested) while (!ct.IsCancellationRequested)
{ {
Thread.Sleep(10); Thread.Sleep(10);
// Stopwatch sw = new(); // Stopwatch sw = new();
@ -64,7 +63,7 @@ public class AutoMusicGameTask(AutoMusicGameParam taskParam) : ISoloTask
if (c.B < 220) if (c.B < 220)
{ {
KeyDown(key); KeyDown(key);
while (!cts.Token.IsCancellationRequested) while (!ct.IsCancellationRequested)
{ {
Thread.Sleep(10); Thread.Sleep(10);
hdc = User32.GetDC(_hWnd); hdc = User32.GetDC(_hWnd);

View File

@ -9,7 +9,7 @@ using static BetterGenshinImpact.GameTask.Common.TaskControl;
namespace BetterGenshinImpact.GameTask.AutoPathing; namespace BetterGenshinImpact.GameTask.AutoPathing;
public class CameraRotateTask(CancellationTokenSource cts) public class CameraRotateTask(CancellationToken ct)
{ {
private readonly double _dpi = TaskContext.Instance().DpiScale; private readonly double _dpi = TaskContext.Instance().DpiScale;
@ -59,7 +59,7 @@ public class CameraRotateTask(CancellationTokenSource cts)
public async Task WaitUntilRotatedTo(int targetOrientation, int maxDiff, int maxTryTimes = 50) public async Task WaitUntilRotatedTo(int targetOrientation, int maxDiff, int maxTryTimes = 50)
{ {
int count = 0; int count = 0;
while (!cts.IsCancellationRequested) while (!ct.IsCancellationRequested)
{ {
var screen = CaptureToRectArea(); var screen = CaptureToRectArea();
if (Math.Abs(RotateToApproach(targetOrientation, screen)) < maxDiff) if (Math.Abs(RotateToApproach(targetOrientation, screen)) < maxDiff)
@ -73,7 +73,7 @@ public class CameraRotateTask(CancellationTokenSource cts)
break; break;
} }
await Delay(50, cts); await Delay(50, ct);
count++; count++;
} }
} }

View File

@ -11,12 +11,12 @@ namespace BetterGenshinImpact.GameTask.AutoPathing.Handler;
internal class AutoFightHandler : IActionHandler internal class AutoFightHandler : IActionHandler
{ {
public async Task RunAsync(CancellationTokenSource cts) public async Task RunAsync(CancellationToken ct)
{ {
await StartFight(cts); await StartFight(ct);
} }
private async Task StartFight(CancellationTokenSource cts) private async Task StartFight(CancellationToken ct)
{ {
TaskControl.Logger.LogInformation("执行 {Text}", "自动战斗"); TaskControl.Logger.LogInformation("执行 {Text}", "自动战斗");
// 爷们要战斗 // 爷们要战斗
@ -26,7 +26,7 @@ internal class AutoFightHandler : IActionHandler
PickDropsAfterFightEnabled = true PickDropsAfterFightEnabled = true
}; };
var fightSoloTask = new AutoFightTask(taskParams); var fightSoloTask = new AutoFightTask(taskParams);
await fightSoloTask.Start(cts); await fightSoloTask.Start(ct);
} }
private string GetFightStrategy() private string GetFightStrategy()

View File

@ -13,7 +13,7 @@ namespace BetterGenshinImpact.GameTask.AutoPathing.Handler;
/// </summary> /// </summary>
public class ElementalSkillHandler : IActionHandler public class ElementalSkillHandler : IActionHandler
{ {
public Task RunAsync(CancellationTokenSource cts) public Task RunAsync(CancellationToken ct)
{ {
TaskControl.Logger.LogInformation("执行 {Text}", "释放元素战技"); TaskControl.Logger.LogInformation("执行 {Text}", "释放元素战技");
Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_E); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_E);

View File

@ -5,5 +5,5 @@ namespace BetterGenshinImpact.GameTask.AutoPathing.Handler;
public interface IActionHandler public interface IActionHandler
{ {
Task RunAsync(CancellationTokenSource cts); Task RunAsync(CancellationToken ct);
} }

View File

@ -15,13 +15,13 @@ public class NahidaCollectHandler : IActionHandler
{ {
private DateTime lastETime = DateTime.MinValue; private DateTime lastETime = DateTime.MinValue;
public async Task RunAsync(CancellationTokenSource cts) public async Task RunAsync(CancellationToken ct)
{ {
Logger.LogInformation("执行 {Nhd} 长按E转圈拾取", "纳西妲"); Logger.LogInformation("执行 {Nhd} 长按E转圈拾取", "纳西妲");
var cd = DateTime.Now - lastETime; var cd = DateTime.Now - lastETime;
if (cd < TimeSpan.FromSeconds(10)) if (cd < TimeSpan.FromSeconds(10))
{ {
await Delay((int)((6 - cd.TotalSeconds + 0.5) * 1000), cts); await Delay((int)((6 - cd.TotalSeconds + 0.5) * 1000), ct);
} }
var dpi = TaskContext.Instance().DpiScale; var dpi = TaskContext.Instance().DpiScale;
@ -30,21 +30,21 @@ public class NahidaCollectHandler : IActionHandler
int i = 60; int i = 60;
// 视角拉到最下面 // 视角拉到最下面
Simulation.SendInput.Mouse.MoveMouseBy(0, 10000); Simulation.SendInput.Mouse.MoveMouseBy(0, 10000);
await Delay(200, cts); await Delay(200, ct);
// 按住E技能 无死角扫码 // 按住E技能 无死角扫码
Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_E); Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_E);
await Delay(200, cts); await Delay(200, ct);
// 先地面来一圈 // 先地面来一圈
for (int j = 0; j < 15; j++) for (int j = 0; j < 15; j++)
{ {
Simulation.SendInput.Mouse.MoveMouseBy(x, 500); Simulation.SendInput.Mouse.MoveMouseBy(x, 500);
await Delay(30, cts); await Delay(30, ct);
} }
// 然后抬斜向转圈 // 然后抬斜向转圈
while (!cts.IsCancellationRequested && i > 0) while (!ct.IsCancellationRequested && i > 0)
{ {
i--; i--;
if (i == 40) if (i == 40)
@ -53,17 +53,17 @@ public class NahidaCollectHandler : IActionHandler
} }
Simulation.SendInput.Mouse.MoveMouseBy(x, y); Simulation.SendInput.Mouse.MoveMouseBy(x, y);
await Delay(30, cts); await Delay(30, ct);
} }
Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_E); Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_E);
lastETime = DateTime.Now; lastETime = DateTime.Now;
await Delay(1000, cts); await Delay(1000, ct);
// 恢复视角 // 恢复视角
Simulation.SendInput.Mouse.MiddleButtonClick(); Simulation.SendInput.Mouse.MiddleButtonClick();
await Delay(1000, cts); await Delay(1000, ct);
} }
} }

View File

@ -11,7 +11,7 @@ namespace BetterGenshinImpact.GameTask.AutoPathing.Handler;
/// </summary> /// </summary>
public class NormalAttackHandler : IActionHandler public class NormalAttackHandler : IActionHandler
{ {
public Task RunAsync(CancellationTokenSource cts) public Task RunAsync(CancellationToken ct)
{ {
TaskControl.Logger.LogInformation("执行 {Text}", "普通攻击"); TaskControl.Logger.LogInformation("执行 {Text}", "普通攻击");

View File

@ -14,11 +14,11 @@ namespace BetterGenshinImpact.GameTask.AutoPathing.Handler;
/// </summary> /// </summary>
public class PickAroundHandler : IActionHandler public class PickAroundHandler : IActionHandler
{ {
public async Task RunAsync(CancellationTokenSource cts) public async Task RunAsync(CancellationToken ct)
{ {
var screen = CaptureToRectArea(); var screen = CaptureToRectArea();
var angle = 0; var angle = 0;
CameraRotateTask rotateTask = new(cts); CameraRotateTask rotateTask = new(ct);
TaskControl.Logger.LogInformation("执行 {Text}", "小范围内自动拾取"); TaskControl.Logger.LogInformation("执行 {Text}", "小范围内自动拾取");
await rotateTask.WaitUntilRotatedTo(angle, 5); await rotateTask.WaitUntilRotatedTo(angle, 5);
Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W); Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W);
@ -29,7 +29,7 @@ public class PickAroundHandler : IActionHandler
rotateTask.RotateToApproach(angle, screen); rotateTask.RotateToApproach(angle, screen);
Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_SPACE); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_SPACE);
Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_F); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_F);
await Delay(100, cts); await Delay(100, ct);
if (DateTime.UtcNow - startTime > TimeSpan.FromSeconds(5)) if (DateTime.UtcNow - startTime > TimeSpan.FromSeconds(5))
break; break;
} }

View File

@ -20,10 +20,10 @@ using static BetterGenshinImpact.GameTask.Common.TaskControl;
namespace BetterGenshinImpact.GameTask.AutoPathing; namespace BetterGenshinImpact.GameTask.AutoPathing;
public class PathExecutor(CancellationTokenSource cts) public class PathExecutor(CancellationToken ct)
{ {
private readonly CameraRotateTask _rotateTask = new(cts); private readonly CameraRotateTask _rotateTask = new(ct);
private readonly TrapEscaper _trapEscaper = new(cts); private readonly TrapEscaper _trapEscaper = new(ct);
public async Task Pathing(PathingTask task) public async Task Pathing(PathingTask task)
{ {
@ -37,7 +37,7 @@ public class PathExecutor(CancellationTokenSource cts)
var waypoints = ConvertWaypointsForTrack(task.Positions); var waypoints = ConvertWaypointsForTrack(task.Positions);
await Delay(100, cts); await Delay(100, ct);
Navigation.WarmUp(); // 提前加载地图特征点 Navigation.WarmUp(); // 提前加载地图特征点
try try
@ -85,7 +85,7 @@ public class PathExecutor(CancellationTokenSource cts)
private async Task HandleTeleportWaypoint(WaypointForTrack waypoint) private async Task HandleTeleportWaypoint(WaypointForTrack waypoint)
{ {
var forceTp = waypoint.Action == ActionEnum.ForceTp.Code; var forceTp = waypoint.Action == ActionEnum.ForceTp.Code;
var (tpX, tpY) = await new TpTask(cts).Tp(waypoint.GameX, waypoint.GameY, forceTp); var (tpX, tpY) = await new TpTask(ct).Tp(waypoint.GameX, waypoint.GameY, forceTp);
var (tprX, tprY) = MapCoordinate.GameToMain2048(tpX, tpY); var (tprX, tprY) = MapCoordinate.GameToMain2048(tpX, tpY);
EntireMap.Instance.SetPrevPosition((float)tprX, (float)tprY); // 通过上一个位置直接进行局部特征匹配 EntireMap.Instance.SetPrevPosition((float)tprX, (float)tprY); // 通过上一个位置直接进行局部特征匹配
} }
@ -105,7 +105,7 @@ public class PathExecutor(CancellationTokenSource cts)
// 按下w一直走 // 按下w一直走
Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W); Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W);
while (!cts.IsCancellationRequested) while (!ct.IsCancellationRequested)
{ {
var now = DateTime.UtcNow; var now = DateTime.UtcNow;
if ((now - startTime).TotalSeconds > 240) if ((now - startTime).TotalSeconds > 240)
@ -168,7 +168,7 @@ public class PathExecutor(CancellationTokenSource cts)
{ {
Debug.WriteLine("未进入飞行状态,按下空格"); Debug.WriteLine("未进入飞行状态,按下空格");
Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_SPACE); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_SPACE);
await Delay(200, cts); await Delay(200, ct);
} }
continue; continue;
@ -177,7 +177,7 @@ public class PathExecutor(CancellationTokenSource cts)
if (waypoint.MoveMode == MoveModeEnum.Jump.Code) if (waypoint.MoveMode == MoveModeEnum.Jump.Code)
{ {
Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_SPACE); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_SPACE);
await Delay(200, cts); await Delay(200, ct);
continue; continue;
} }
@ -210,7 +210,7 @@ public class PathExecutor(CancellationTokenSource cts)
} }
} }
await Delay(100, cts); await Delay(100, ct);
} }
// 抬起w键 // 抬起w键
@ -228,12 +228,12 @@ public class PathExecutor(CancellationTokenSource cts)
//下落攻击接近目的地 //下落攻击接近目的地
Logger.LogInformation("动作:下落攻击"); Logger.LogInformation("动作:下落攻击");
Simulation.SendInput.Mouse.LeftButtonClick(); Simulation.SendInput.Mouse.LeftButtonClick();
await Delay(1000, cts); await Delay(1000, ct);
} }
await _rotateTask.WaitUntilRotatedTo(targetOrientation, 2); await _rotateTask.WaitUntilRotatedTo(targetOrientation, 2);
var stepsTaken = 0; var stepsTaken = 0;
while (!cts.IsCancellationRequested) while (!ct.IsCancellationRequested)
{ {
stepsTaken++; stepsTaken++;
if (stepsTaken > 20) if (stepsTaken > 20)
@ -254,13 +254,13 @@ public class PathExecutor(CancellationTokenSource cts)
await _rotateTask.WaitUntilRotatedTo(targetOrientation, 2); await _rotateTask.WaitUntilRotatedTo(targetOrientation, 2);
// 小碎步接近 // 小碎步接近
Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W).Sleep(60).KeyUp(User32.VK.VK_W); Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W).Sleep(60).KeyUp(User32.VK.VK_W);
await Delay(50, cts); await Delay(50, ct);
} }
Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W); Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W);
// 到达目的地后停顿一秒 // 到达目的地后停顿一秒
await Delay(1000, cts); await Delay(1000, ct);
} }
private async Task AfterMoveToTarget(Waypoint waypoint) private async Task AfterMoveToTarget(Waypoint waypoint)
@ -270,8 +270,8 @@ public class PathExecutor(CancellationTokenSource cts)
|| waypoint.Action == ActionEnum.Fight.Code) || waypoint.Action == ActionEnum.Fight.Code)
{ {
var handler = ActionFactory.GetHandler(waypoint.Action); var handler = ActionFactory.GetHandler(waypoint.Action);
await handler.RunAsync(cts); await handler.RunAsync(ct);
await Delay(800, cts); await Delay(800, ct);
} }
} }
} }

View File

@ -10,9 +10,9 @@ using static BetterGenshinImpact.GameTask.Common.TaskControl;
namespace BetterGenshinImpact.GameTask.AutoPathing; namespace BetterGenshinImpact.GameTask.AutoPathing;
public class TrapEscaper(CancellationTokenSource cts) public class TrapEscaper(CancellationToken ct)
{ {
private readonly CameraRotateTask _rotateTask = new(cts); private readonly CameraRotateTask _rotateTask = new(ct);
private static readonly Random _random = new Random(); private static readonly Random _random = new Random();
private int _lastActionIndex = 0; private int _lastActionIndex = 0;
public static DateTime LastActionTime = DateTime.UtcNow; public static DateTime LastActionTime = DateTime.UtcNow;
@ -39,7 +39,7 @@ public class TrapEscaper(CancellationTokenSource cts)
// 按下w一直走 // 按下w一直走
Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W); Simulation.SendInput.Keyboard.KeyDown(User32.VK.VK_W);
while (!cts.IsCancellationRequested) while (!ct.IsCancellationRequested)
{ {
var now = DateTime.UtcNow; var now = DateTime.UtcNow;
if ((now - LastActionTime).TotalSeconds > 5) if ((now - LastActionTime).TotalSeconds > 5)
@ -106,7 +106,7 @@ public class TrapEscaper(CancellationTokenSource cts)
continue; continue;
} }
await Delay(100, cts); await Delay(100, ct);
} }
// 抬起w键 // 抬起w键
@ -119,9 +119,9 @@ public class TrapEscaper(CancellationTokenSource cts)
// 脱离攀爬状态 // 脱离攀爬状态
Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W); Simulation.SendInput.Keyboard.KeyUp(User32.VK.VK_W);
Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_X); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_X);
await Delay(75, cts); await Delay(75, ct);
Simulation.SendInput.Mouse.LeftButtonClick(); Simulation.SendInput.Mouse.LeftButtonClick();
await Delay(500, cts); await Delay(500, ct);
TimeSpan timeSinceLastAction = DateTime.UtcNow - LastActionTime; TimeSpan timeSinceLastAction = DateTime.UtcNow - LastActionTime;

View File

@ -13,7 +13,6 @@ using BetterGenshinImpact.GameTask.Model.Area;
using BetterGenshinImpact.GameTask.QuickTeleport.Assets; using BetterGenshinImpact.GameTask.QuickTeleport.Assets;
using BetterGenshinImpact.Helpers; using BetterGenshinImpact.Helpers;
using BetterGenshinImpact.View.Drawable; using BetterGenshinImpact.View.Drawable;
using BetterGenshinImpact.ViewModel.Pages;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using OpenCvSharp; using OpenCvSharp;
using System; using System;
@ -38,7 +37,7 @@ public class AutoTrackTask(AutoTrackParam param) : BaseIndependentTask
/// </summary> /// </summary>
private Rect _missionDistanceRect = Rect.Empty; private Rect _missionDistanceRect = Rect.Empty;
private CancellationTokenSource? _cts; private CancellationToken _ct;
public async void Start() public async void Start()
{ {
@ -56,7 +55,7 @@ public class AutoTrackTask(AutoTrackParam param) : BaseIndependentTask
Logger.LogInformation("→ {Text}", "自动追踪,启动!"); Logger.LogInformation("→ {Text}", "自动追踪,启动!");
_cts = CancellationContext.Instance.Cts; _ct = CancellationContext.Instance.Cts.Token;
TrackMission(); TrackMission();
} }
@ -90,20 +89,20 @@ public class AutoTrackTask(AutoTrackParam param) : BaseIndependentTask
var paimonMenuRa = ra.Find(ElementAssets.Instance.PaimonMenuRo); var paimonMenuRa = ra.Find(ElementAssets.Instance.PaimonMenuRo);
if (!paimonMenuRa.IsExist()) if (!paimonMenuRa.IsExist())
{ {
Sleep(5000, _cts); Sleep(5000, _ct);
return; return;
} }
// 任务文字有动效等待2s重新截图 // 任务文字有动效等待2s重新截图
Simulation.SendInput.Mouse.MoveMouseBy(0, 7000); Simulation.SendInput.Mouse.MoveMouseBy(0, 7000);
Sleep(2000, _cts); Sleep(2000, _ct);
// OCR 任务文字 在小地图下方 // OCR 任务文字 在小地图下方
var textRaList = OcrMissionTextRaList(paimonMenuRa); var textRaList = OcrMissionTextRaList(paimonMenuRa);
if (textRaList.Count == 0) if (textRaList.Count == 0)
{ {
Logger.LogInformation("未找到任务文字"); Logger.LogInformation("未找到任务文字");
Sleep(5000, _cts); Sleep(5000, _ct);
return; return;
} }
@ -115,14 +114,14 @@ public class AutoTrackTask(AutoTrackParam param) : BaseIndependentTask
// 距离大于150米先传送到最近的传送点 // 距离大于150米先传送到最近的传送点
// J 打开任务 切换追踪打开地图 中心点就是任务点 // J 打开任务 切换追踪打开地图 中心点就是任务点
Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_J); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_J);
Sleep(800, _cts); Sleep(800, _ct);
// TODO 识别是否在任务界面 // TODO 识别是否在任务界面
// 切换追踪 // 切换追踪
var btn = ra.Derive(CaptureRect.Width - 250, CaptureRect.Height - 60); var btn = ra.Derive(CaptureRect.Width - 250, CaptureRect.Height - 60);
btn.Click(); btn.Click();
Sleep(200, _cts); Sleep(200, _ct);
btn.Click(); btn.Click();
Sleep(1500, _cts); Sleep(1500, _ct);
// 寻找所有传送点 // 寻找所有传送点
ra = CaptureToRectArea(); ra = CaptureToRectArea();
@ -146,7 +145,7 @@ public class AutoTrackTask(AutoTrackParam param) : BaseIndependentTask
ra.Derive(nearestRect).Click(); ra.Derive(nearestRect).Click();
// 等待自动传送完成 // 等待自动传送完成
Sleep(2000, _cts); Sleep(2000, _ct);
if (Bv.IsInBigMapUi(CaptureToRectArea())) if (Bv.IsInBigMapUi(CaptureToRectArea()))
{ {
@ -154,7 +153,7 @@ public class AutoTrackTask(AutoTrackParam param) : BaseIndependentTask
} }
else else
{ {
Sleep(500, _cts); Sleep(500, _ct);
NewRetry.Do(() => NewRetry.Do(() =>
{ {
if (!Bv.IsInMainUi(CaptureToRectArea())) if (!Bv.IsInMainUi(CaptureToRectArea()))
@ -181,7 +180,7 @@ public class AutoTrackTask(AutoTrackParam param) : BaseIndependentTask
{ {
// V键直接追踪 // V键直接追踪
Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_V); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_V);
Sleep(3000, _cts); Sleep(3000, _ct);
var ra = CaptureToRectArea(); var ra = CaptureToRectArea();
var blueTrackPointRa = ra.Find(ElementAssets.Instance.BlueTrackPoint); var blueTrackPointRa = ra.Find(ElementAssets.Instance.BlueTrackPoint);
@ -204,7 +203,7 @@ public class AutoTrackTask(AutoTrackParam param) : BaseIndependentTask
// { // {
int prevMoveX = 0; int prevMoveX = 0;
bool wDown = false; bool wDown = false;
while (!_cts.Token.IsCancellationRequested) while (!_ct.IsCancellationRequested)
{ {
var ra = CaptureToRectArea(); var ra = CaptureToRectArea();
var blueTrackPointRa = ra.Find(ElementAssets.Instance.BlueTrackPoint); var blueTrackPointRa = ra.Find(ElementAssets.Instance.BlueTrackPoint);

View File

@ -13,7 +13,6 @@ using BetterGenshinImpact.Helpers;
using BetterGenshinImpact.Helpers.Extensions; using BetterGenshinImpact.Helpers.Extensions;
using BetterGenshinImpact.Service; using BetterGenshinImpact.Service;
using BetterGenshinImpact.View.Drawable; using BetterGenshinImpact.View.Drawable;
using BetterGenshinImpact.ViewModel.Pages;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using OpenCvSharp; using OpenCvSharp;
using System; using System;
@ -45,7 +44,7 @@ public class AutoTrackPathTask
// 视角偏移移动单位 // 视角偏移移动单位
private const int CharMovingUnit = 500; private const int CharMovingUnit = 500;
private CancellationTokenSource? _cts; private CancellationToken _ct;
public AutoTrackPathTask(AutoTrackPathParam taskParam) public AutoTrackPathTask(AutoTrackPathParam taskParam)
{ {
@ -67,7 +66,7 @@ public class AutoTrackPathTask
return; return;
} }
_cts = CancellationContext.Instance.Cts; _ct = CancellationContext.Instance.Cts.Token;
Init(); Init();
@ -102,19 +101,14 @@ public class AutoTrackPathTask
SystemControl.ActivateWindow(); SystemControl.ActivateWindow();
Logger.LogInformation("→ {Text}", "自动路线,启动!"); Logger.LogInformation("→ {Text}", "自动路线,启动!");
TaskTriggerDispatcher.Instance().SetCacheCaptureMode(DispatcherCaptureModeEnum.OnlyCacheCapture); TaskTriggerDispatcher.Instance().SetCacheCaptureMode(DispatcherCaptureModeEnum.OnlyCacheCapture);
Sleep(TaskContext.Instance().Config.TriggerInterval * 5, _cts); // 等待缓存图像 Sleep(TaskContext.Instance().Config.TriggerInterval * 5, _ct); // 等待缓存图像
}
public void Stop()
{
_cts.Cancel();
} }
public async Task DoTask() public async Task DoTask()
{ {
// 1. 传送到最近的传送点 // 1. 传送到最近的传送点
var first = _way.WayPointList[0]; // 解析路线,第一个点为起点 var first = _way.WayPointList[0]; // 解析路线,第一个点为起点
await new TpTask(_cts).Tp(first.Pt.X, first.Pt.Y); await new TpTask(_ct).Tp(first.Pt.X, first.Pt.Y);
// 2. 等待传送完成 // 2. 等待传送完成
Sleep(1000); Sleep(1000);
@ -136,23 +130,23 @@ public class AutoTrackPathTask
// 4. 针对点位进行直线追踪 // 4. 针对点位进行直线追踪
var trackCts = new CancellationTokenSource(); var trackCts = new CancellationTokenSource();
_cts.Token.Register(trackCts.Cancel); _ct.Register(trackCts.Cancel);
var trackTask = Track(_way.WayPointList, angleOffset, trackCts); var trackTask = Track(_way.WayPointList, angleOffset, trackCts);
trackTask.Start(); trackTask.Start();
var refreshStatusTask = RefreshStatus(trackCts); var refreshStatusTask = RefreshStatus(trackCts.Token);
refreshStatusTask.Start(); refreshStatusTask.Start();
var jumpTask = Jump(trackCts); var jumpTask = Jump(trackCts.Token);
jumpTask.Start(); jumpTask.Start();
await Task.WhenAll(trackTask, refreshStatusTask, jumpTask); await Task.WhenAll(trackTask, refreshStatusTask, jumpTask);
} }
private MotionStatus _motionStatus = MotionStatus.Normal; private MotionStatus _motionStatus = MotionStatus.Normal;
public Task Jump(CancellationTokenSource trackCts) public Task Jump(CancellationToken trackCt)
{ {
return new Task(() => return new Task(() =>
{ {
while (!_cts.Token.IsCancellationRequested && !trackCts.Token.IsCancellationRequested) while (!_ct.IsCancellationRequested && !trackCt.IsCancellationRequested)
{ {
if (_motionStatus == MotionStatus.Normal) if (_motionStatus == MotionStatus.Normal)
{ {
@ -178,11 +172,11 @@ public class AutoTrackPathTask
private double _targetAngle = 0; private double _targetAngle = 0;
public Task RefreshStatus(CancellationTokenSource trackCts) public Task RefreshStatus(CancellationToken trackCt)
{ {
return new Task(() => return new Task(() =>
{ {
while (!_cts.Token.IsCancellationRequested && !trackCts.Token.IsCancellationRequested) while (!_ct.IsCancellationRequested && !trackCt.IsCancellationRequested)
{ {
using var ra = CaptureToRectArea(); using var ra = CaptureToRectArea();
_motionStatus = Bv.GetMotionStatus(ra); _motionStatus = Bv.GetMotionStatus(ra);
@ -210,7 +204,7 @@ public class AutoTrackPathTask
return new Task(() => return new Task(() =>
{ {
var currIndex = 0; var currIndex = 0;
while (!_cts.IsCancellationRequested) while (!_ct.IsCancellationRequested)
{ {
var ra = CaptureToRectArea(); var ra = CaptureToRectArea();
var miniMapMat = GetMiniMapMat(ra) ?? throw new InvalidOperationException("当前不在主界面"); var miniMapMat = GetMiniMapMat(ra) ?? throw new InvalidOperationException("当前不在主界面");

View File

@ -37,7 +37,7 @@ public class PathPointRecorder : Singleton<PathPointRecorder>
TaskTriggerDispatcher.Instance().SetCacheCaptureMode(DispatcherCaptureModeEnum.OnlyCacheCapture); TaskTriggerDispatcher.Instance().SetCacheCaptureMode(DispatcherCaptureModeEnum.OnlyCacheCapture);
_recordTaskCts = new CancellationTokenSource(); _recordTaskCts = new CancellationTokenSource();
_recordTask = RecordTask(_recordTaskCts); _recordTask = RecordTask(_recordTaskCts.Token);
_recordTask.Start(); _recordTask.Start();
} }
else else
@ -58,17 +58,17 @@ public class PathPointRecorder : Singleton<PathPointRecorder>
} }
} }
public Task RecordTask(CancellationTokenSource cts) public Task RecordTask(CancellationToken ct)
{ {
return new Task(() => return new Task(() =>
{ {
GiPath way = new(); GiPath way = new();
while (!cts.Token.IsCancellationRequested) while (!ct.IsCancellationRequested)
{ {
try try
{ {
Sleep(10, cts); Sleep(10, ct);
var ra = CaptureToRectArea(); var ra = CaptureToRectArea();
// 小地图匹配 // 小地图匹配
@ -76,7 +76,7 @@ public class PathPointRecorder : Singleton<PathPointRecorder>
var p = MatchTemplateHelper.MatchTemplate(ra.SrcGreyMat, tar, TemplateMatchModes.CCoeffNormed, null, 0.9); var p = MatchTemplateHelper.MatchTemplate(ra.SrcGreyMat, tar, TemplateMatchModes.CCoeffNormed, null, 0.9);
if (p.X == 0 || p.Y == 0) if (p.X == 0 || p.Y == 0)
{ {
Sleep(50, cts); Sleep(50, ct);
continue; continue;
} }
@ -88,7 +88,7 @@ public class PathPointRecorder : Singleton<PathPointRecorder>
} }
else else
{ {
Sleep(50, cts); Sleep(50, ct);
} }
} }
catch (Exception e) catch (Exception e)
@ -100,6 +100,6 @@ public class PathPointRecorder : Singleton<PathPointRecorder>
File.WriteAllText(Global.Absolute($@"log\way\{DateTime.Now:yyyy-MM-dd HHmmssffff}.json"), JsonSerializer.Serialize(way, ConfigService.JsonOptions)); File.WriteAllText(Global.Absolute($@"log\way\{DateTime.Now:yyyy-MM-dd HHmmssffff}.json"), JsonSerializer.Serialize(way, ConfigService.JsonOptions));
#endif #endif
Logger.LogInformation("路线录制结束"); Logger.LogInformation("路线录制结束");
}, cts.Token); }, ct);
} }
} }

View File

@ -25,7 +25,7 @@ namespace BetterGenshinImpact.GameTask.AutoTrackPath;
/// <summary> /// <summary>
/// 传送任务 /// 传送任务
/// </summary> /// </summary>
public class TpTask(CancellationTokenSource cts) public class TpTask(CancellationToken ct)
{ {
private readonly QuickTeleportAssets _assets = QuickTeleportAssets.Instance; private readonly QuickTeleportAssets _assets = QuickTeleportAssets.Instance;
@ -55,7 +55,7 @@ public class TpTask(CancellationTokenSource cts)
if (!Bv.IsInBigMapUi(ra1)) if (!Bv.IsInBigMapUi(ra1))
{ {
Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_M); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_M);
await Delay(1000, cts); await Delay(1000, ct);
} }
// 计算传送点位置离哪个地图切换后的中心点最近,切换到该地图 // 计算传送点位置离哪个地图切换后的中心点最近,切换到该地图
@ -79,13 +79,13 @@ public class TpTask(CancellationTokenSource cts)
ra.ClickTo((int)clickX, (int)clickY); ra.ClickTo((int)clickX, (int)clickY);
// 触发一次快速传送功能 // 触发一次快速传送功能
await Delay(500, cts); await Delay(500, ct);
await ClickTpPoint(CaptureToRectArea()); await ClickTpPoint(CaptureToRectArea());
// 等待传送完成 // 等待传送完成
for (var i = 0; i < 20; i++) for (var i = 0; i < 20; i++)
{ {
await Delay(1200, cts); await Delay(1200, ct);
using var ra3 = CaptureToRectArea(); using var ra3 = CaptureToRectArea();
if (Bv.IsInMainUi(ra3)) if (Bv.IsInMainUi(ra3))
{ {
@ -161,7 +161,7 @@ public class TpTask(CancellationTokenSource cts)
{ {
// 传送点未激活或不存在 按ESC回到大地图界面 // 传送点未激活或不存在 按ESC回到大地图界面
Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_ESCAPE); Simulation.SendInput.Keyboard.KeyPress(User32.VK.VK_ESCAPE);
await Delay(300, cts); await Delay(300, ct);
throw; throw;
} }
catch (Exception e) catch (Exception e)
@ -231,14 +231,14 @@ public class TpTask(CancellationTokenSource cts)
var moveUnit = dx > 0 ? 20 : -20; var moveUnit = dx > 0 ? 20 : -20;
GameCaptureRegion.GameRegionMove((rect, _) => (rect.Width / 2d + Random.Shared.Next(-rect.Width / 6, rect.Width / 6), rect.Height / 2d + Random.Shared.Next(-rect.Height / 6, rect.Height / 6))); GameCaptureRegion.GameRegionMove((rect, _) => (rect.Width / 2d + Random.Shared.Next(-rect.Width / 6, rect.Width / 6), rect.Height / 2d + Random.Shared.Next(-rect.Height / 6, rect.Height / 6)));
Simulation.SendInput.Mouse.LeftButtonDown(); Simulation.SendInput.Mouse.LeftButtonDown();
await Delay(200, cts); await Delay(200, ct);
for (var i = 0; i < dx / moveUnit; i++) for (var i = 0; i < dx / moveUnit; i++)
{ {
Simulation.SendInput.Mouse.MoveMouseBy(moveUnit, 0).Sleep(60); // 60 保证没有惯性 Simulation.SendInput.Mouse.MoveMouseBy(moveUnit, 0).Sleep(60); // 60 保证没有惯性
} }
Simulation.SendInput.Mouse.LeftButtonUp(); Simulation.SendInput.Mouse.LeftButtonUp();
await Delay(200, cts); await Delay(200, ct);
} }
public async Task MouseMoveMapY(int dy) public async Task MouseMoveMapY(int dy)
@ -246,7 +246,7 @@ public class TpTask(CancellationTokenSource cts)
var moveUnit = dy > 0 ? 20 : -20; var moveUnit = dy > 0 ? 20 : -20;
GameCaptureRegion.GameRegionMove((rect, _) => (rect.Width / 2d + Random.Shared.Next(-rect.Width / 6, rect.Width / 6), rect.Height / 2d + Random.Shared.Next(-rect.Height / 6, rect.Height / 6))); GameCaptureRegion.GameRegionMove((rect, _) => (rect.Width / 2d + Random.Shared.Next(-rect.Width / 6, rect.Width / 6), rect.Height / 2d + Random.Shared.Next(-rect.Height / 6, rect.Height / 6)));
Simulation.SendInput.Mouse.LeftButtonDown(); Simulation.SendInput.Mouse.LeftButtonDown();
await Delay(200, cts); await Delay(200, ct);
// 原神地图在小范围内移动是无效的,所以先随便移动一下,所以肯定少移动一次 // 原神地图在小范围内移动是无效的,所以先随便移动一下,所以肯定少移动一次
for (var i = 0; i < dy / moveUnit; i++) for (var i = 0; i < dy / moveUnit; i++)
{ {
@ -254,7 +254,7 @@ public class TpTask(CancellationTokenSource cts)
} }
Simulation.SendInput.Mouse.LeftButtonUp(); Simulation.SendInput.Mouse.LeftButtonUp();
await Delay(200, cts); await Delay(200, ct);
} }
public Point2f GetPositionFromBigMap() public Point2f GetPositionFromBigMap()
@ -363,7 +363,7 @@ public class TpTask(CancellationTokenSource cts)
if (Bv.BigMapIsUnderground(ra2)) if (Bv.BigMapIsUnderground(ra2))
{ {
ra2.Find(_assets.MapUndergroundToGroundButtonRo).Click(); ra2.Find(_assets.MapUndergroundToGroundButtonRo).Click();
await Delay(200, cts); await Delay(200, ct);
} }
// 识别当前位置 // 识别当前位置
@ -392,7 +392,7 @@ public class TpTask(CancellationTokenSource cts)
if (minCountry != "当前位置") if (minCountry != "当前位置")
{ {
GameCaptureRegion.GameRegionClick((rect, scale) => (rect.Width - 160 * scale, rect.Height - 60 * scale)); GameCaptureRegion.GameRegionClick((rect, scale) => (rect.Width - 160 * scale, rect.Height - 60 * scale));
await Delay(300, cts); await Delay(300, ct);
var ra = CaptureToRectArea(); var ra = CaptureToRectArea();
var list = ra.FindMulti(new RecognitionObject var list = ra.FindMulti(new RecognitionObject
{ {
@ -401,7 +401,7 @@ public class TpTask(CancellationTokenSource cts)
}); });
list.FirstOrDefault(r => r.Text.Length == minCountry.Length && !r.Text.Contains("委托") && 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); Logger.LogInformation("切换到区域:{Country}", minCountry);
await Delay(500, cts); await Delay(500, ct);
return true; return true;
} }
@ -442,7 +442,7 @@ public class TpTask(CancellationTokenSource cts)
{ {
var time = TaskContext.Instance().Config.QuickTeleportConfig.WaitTeleportPanelDelay; var time = TaskContext.Instance().Config.QuickTeleportConfig.WaitTeleportPanelDelay;
time = time < 300 ? 300 : time; time = time < 300 ? 300 : time;
await Delay(time, cts); await Delay(time, ct);
if (!CheckTeleportButton(CaptureToRectArea())) if (!CheckTeleportButton(CaptureToRectArea()))
{ {
// 没传送确认图标说明点开的是未激活传送锚点 // 没传送确认图标说明点开的是未激活传送锚点
@ -514,4 +514,4 @@ public class TpTask(CancellationTokenSource cts)
return hasMapChooseIcon; return hasMapChooseIcon;
} }
} }

View File

@ -1,5 +1,4 @@
using BetterGenshinImpact.Core.Recognition.OCR; using BetterGenshinImpact.Core.Recognition.OCR;
using BetterGenshinImpact.Core.Script;
using BetterGenshinImpact.Core.Simulator; using BetterGenshinImpact.Core.Simulator;
using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Exception; using BetterGenshinImpact.GameTask.AutoGeniusInvokation.Exception;
using BetterGenshinImpact.GameTask.AutoWood.Assets; using BetterGenshinImpact.GameTask.AutoWood.Assets;
@ -8,7 +7,6 @@ using BetterGenshinImpact.GameTask.Common;
using BetterGenshinImpact.GameTask.Model.Area; using BetterGenshinImpact.GameTask.Model.Area;
using BetterGenshinImpact.Genshin.Settings; using BetterGenshinImpact.Genshin.Settings;
using BetterGenshinImpact.View.Drawable; using BetterGenshinImpact.View.Drawable;
using BetterGenshinImpact.ViewModel.Pages;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
@ -42,7 +40,7 @@ public partial class AutoWoodTask : ISoloTask
private readonly WoodTaskParam _taskParam; private readonly WoodTaskParam _taskParam;
private CancellationTokenSource? _cts; private CancellationToken _ct;
public AutoWoodTask(WoodTaskParam taskParam) public AutoWoodTask(WoodTaskParam taskParam)
{ {
@ -53,11 +51,11 @@ public partial class AutoWoodTask : ISoloTask
_printer = new WoodStatisticsPrinter(_assets); _printer = new WoodStatisticsPrinter(_assets);
} }
public Task Start(CancellationTokenSource cts) public Task Start(CancellationToken ct)
{ {
var runTimeWatch = new Stopwatch(); var runTimeWatch = new Stopwatch();
_cts = cts; _ct = ct;
_printer.Cts = _cts; _printer.Ct = _ct;
try try
{ {
@ -106,14 +104,14 @@ public partial class AutoWoodTask : ISoloTask
} }
Logger.LogInformation("第{Cnt}次伐木", i + 1); Logger.LogInformation("第{Cnt}次伐木", i + 1);
if (_cts.IsCancellationRequested) if (_ct.IsCancellationRequested)
{ {
break; break;
} }
Felling(_taskParam, i + 1 == _taskParam.WoodRoundNum); Felling(_taskParam, i + 1 == _taskParam.WoodRoundNum);
VisionContext.Instance().DrawContent.ClearAll(); VisionContext.Instance().DrawContent.ClearAll();
Sleep(500, _cts); Sleep(500, _ct);
} }
return Task.CompletedTask; return Task.CompletedTask;
@ -146,7 +144,7 @@ public partial class AutoWoodTask : ISoloTask
"杉木", "竹节", "却砂木", "松木", "萃华木", "桦木", "孔雀木", "梦见木", "御伽木" "杉木", "竹节", "却砂木", "松木", "萃华木", "桦木", "孔雀木", "梦见木", "御伽木"
]; ];
public CancellationTokenSource? Cts { get; set; } public CancellationToken Ct { get; set; }
[GeneratedRegex("([^\\d\\n]+)[×x](\\d+)")] [GeneratedRegex("([^\\d\\n]+)[×x](\\d+)")]
private static partial Regex _parseWoodStatisticsRegex(); private static partial Regex _parseWoodStatisticsRegex();
@ -217,7 +215,7 @@ public partial class AutoWoodTask : ISoloTask
private void SleepDurationBetweenOcrs(WoodTaskParam taskParam) private void SleepDurationBetweenOcrs(WoodTaskParam taskParam)
{ {
Sleep(_firstWoodOcr ? 300 : 100, Cts); Sleep(_firstWoodOcr ? 300 : 100, Ct);
} }
private string WoodTextAreaOcr() private string WoodTextAreaOcr()
@ -433,7 +431,7 @@ public partial class AutoWoodTask : ISoloTask
{ {
NewRetry.Do(() => NewRetry.Do(() =>
{ {
Sleep(1, _cts); Sleep(1, _ct);
using var contentRegion = CaptureToRectArea(); using var contentRegion = CaptureToRectArea();
using var ra = contentRegion.Find(_assets.TheBoonOfTheElderTreeRo); using var ra = contentRegion.Find(_assets.TheBoonOfTheElderTreeRo);
if (ra.IsEmpty()) if (ra.IsEmpty())
@ -447,12 +445,12 @@ public partial class AutoWoodTask : ISoloTask
Simulation.SendInput.Keyboard.KeyPress(_zKey); Simulation.SendInput.Keyboard.KeyPress(_zKey);
Debug.WriteLine("[AutoWood] Z"); Debug.WriteLine("[AutoWood] Z");
Sleep(500, _cts); Sleep(500, _ct);
}, TimeSpan.FromSeconds(1), 120); }, TimeSpan.FromSeconds(1), 120);
} }
Sleep(300, _cts); Sleep(300, _ct);
Sleep(TaskContext.Instance().Config.AutoWoodConfig.AfterZSleepDelay, _cts); Sleep(TaskContext.Instance().Config.AutoWoodConfig.AfterZSleepDelay, _ct);
} }
private void PressEsc(WoodTaskParam taskParam) private void PressEsc(WoodTaskParam taskParam)
@ -465,13 +463,13 @@ public partial class AutoWoodTask : ISoloTask
// Simulation.SendInput.Keyboard.KeyPress(VK.VK_ESCAPE); // Simulation.SendInput.Keyboard.KeyPress(VK.VK_ESCAPE);
// } // }
Debug.WriteLine("[AutoWood] Esc"); Debug.WriteLine("[AutoWood] Esc");
Sleep(800, _cts); Sleep(800, _ct);
// 确认在菜单界面 // 确认在菜单界面
try try
{ {
NewRetry.Do(() => NewRetry.Do(() =>
{ {
Sleep(1, _cts); Sleep(1, _ct);
using var contentRegion = CaptureToRectArea(); using var contentRegion = CaptureToRectArea();
using var ra = contentRegion.Find(_assets.MenuBagRo); using var ra = contentRegion.Find(_assets.MenuBagRo);
if (ra.IsEmpty()) if (ra.IsEmpty())
@ -492,7 +490,7 @@ public partial class AutoWoodTask : ISoloTask
Debug.WriteLine("[AutoWood] Click exit button"); Debug.WriteLine("[AutoWood] Click exit button");
Sleep(500, _cts); Sleep(500, _ct);
// 点击确认 // 点击确认
using var contentRegion = CaptureToRectArea(); using var contentRegion = CaptureToRectArea();
@ -508,14 +506,14 @@ public partial class AutoWoodTask : ISoloTask
{ {
if (_login3rdParty.IsAvailabled) if (_login3rdParty.IsAvailabled)
{ {
Sleep(1, _cts); Sleep(1, _ct);
_login3rdParty.Login(_cts); _login3rdParty.Login(_ct);
} }
var clickCnt = 0; var clickCnt = 0;
for (var i = 0; i < 50; i++) for (var i = 0; i < 50; i++)
{ {
Sleep(1, _cts); Sleep(1, _ct);
using var contentRegion = CaptureToRectArea(); using var contentRegion = CaptureToRectArea();
using var ra = contentRegion.Find(_assets.EnterGameRo); using var ra = contentRegion.Find(_assets.EnterGameRo);
@ -529,12 +527,12 @@ public partial class AutoWoodTask : ISoloTask
{ {
if (clickCnt > 2) if (clickCnt > 2)
{ {
Sleep(5000, _cts); Sleep(5000, _ct);
break; break;
} }
} }
Sleep(1000, _cts); Sleep(1000, _ct);
} }
if (clickCnt == 0) if (clickCnt == 0)

View File

@ -76,11 +76,11 @@ internal sealed class Login3rdParty
} }
} }
public void Login(CancellationTokenSource cts) public void Login(CancellationToken ct)
{ {
int failCount = default; int failCount = default;
while (!LoginPrivate(cts)) while (!LoginPrivate(ct))
{ {
// It is necessary to support exitable trying. // It is necessary to support exitable trying.
// Can exit trying when over than 10s. // Can exit trying when over than 10s.
@ -90,12 +90,12 @@ internal sealed class Login3rdParty
break; break;
} }
Debug.WriteLine($"[AutoWood] Fail to check login button {failCount} time(s)."); Debug.WriteLine($"[AutoWood] Fail to check login button {failCount} time(s).");
Sleep(500, cts); Sleep(500, ct);
} }
Debug.WriteLine("[AutoWood] Exit while check login button."); Debug.WriteLine("[AutoWood] Exit while check login button.");
} }
private bool LoginPrivate(CancellationTokenSource cts) private bool LoginPrivate(CancellationToken ct)
{ {
if (Type == The3rdPartyType.Bilibili) if (Type == The3rdPartyType.Bilibili)
{ {
@ -104,7 +104,7 @@ internal sealed class Login3rdParty
if (GetBHWnd(process) != IntPtr.Zero) if (GetBHWnd(process) != IntPtr.Zero)
{ {
// Just for login WebUI fadein chattering // Just for login WebUI fadein chattering
Sleep(4000, cts); Sleep(4000, ct);
var p = TaskContext.Instance() var p = TaskContext.Instance()
.SystemInfo.CaptureAreaRect.GetCenterPoint() .SystemInfo.CaptureAreaRect.GetCenterPoint()
@ -114,7 +114,7 @@ internal sealed class Login3rdParty
Debug.WriteLine("[AutoWood] Click login button for the B one"); Debug.WriteLine("[AutoWood] Click login button for the B one");
// Just for login WebUI fadeout chattering // Just for login WebUI fadeout chattering
Sleep(3000, cts); Sleep(3000, ct);
if (GetBHWnd(process) != IntPtr.Zero) if (GetBHWnd(process) != IntPtr.Zero)
{ {

View File

@ -39,9 +39,73 @@ public class TaskControl
Thread.Sleep(millisecondsTimeout); Thread.Sleep(millisecondsTimeout);
} }
public static void Sleep(int millisecondsTimeout, CancellationTokenSource? cts) // public static void Sleep(int millisecondsTimeout, CancellationTokenSource? cts)
// {
// if (cts is { IsCancellationRequested: true })
// {
// throw new NormalEndException("取消自动任务");
// }
//
// if (millisecondsTimeout <= 0)
// {
// return;
// }
//
// NewRetry.Do(() =>
// {
// if (cts is { IsCancellationRequested: true })
// {
// throw new NormalEndException("取消自动任务");
// }
//
// if (!SystemControl.IsGenshinImpactActiveByProcess())
// {
// Logger.LogInformation("当前获取焦点的窗口不是原神,暂停");
// throw new RetryException("当前获取焦点的窗口不是原神");
// }
// }, TimeSpan.FromSeconds(1), 100);
// Thread.Sleep(millisecondsTimeout);
// if (cts is { IsCancellationRequested: true })
// {
// throw new NormalEndException("取消自动任务");
// }
// }
// public static async Task Delay(int millisecondsTimeout, CancellationTokenSource cts)
// {
// if (cts is { IsCancellationRequested: true })
// {
// throw new NormalEndException("取消自动任务");
// }
//
// if (millisecondsTimeout <= 0)
// {
// return;
// }
//
// NewRetry.Do(() =>
// {
// if (cts is { IsCancellationRequested: true })
// {
// throw new NormalEndException("取消自动任务");
// }
//
// if (!SystemControl.IsGenshinImpactActiveByProcess())
// {
// Logger.LogInformation("当前获取焦点的窗口不是原神,暂停");
// throw new RetryException("当前获取焦点的窗口不是原神");
// }
// }, TimeSpan.FromSeconds(1), 100);
// await Task.Delay(millisecondsTimeout, cts.Token);
// if (cts is { IsCancellationRequested: true })
// {
// throw new NormalEndException("取消自动任务");
// }
// }
public static void Sleep(int millisecondsTimeout, CancellationToken ct)
{ {
if (cts is { IsCancellationRequested: true }) if (ct.IsCancellationRequested)
{ {
throw new NormalEndException("取消自动任务"); throw new NormalEndException("取消自动任务");
} }
@ -53,7 +117,7 @@ public class TaskControl
NewRetry.Do(() => NewRetry.Do(() =>
{ {
if (cts is { IsCancellationRequested: true }) if (ct.IsCancellationRequested)
{ {
throw new NormalEndException("取消自动任务"); throw new NormalEndException("取消自动任务");
} }
@ -65,15 +129,15 @@ public class TaskControl
} }
}, TimeSpan.FromSeconds(1), 100); }, TimeSpan.FromSeconds(1), 100);
Thread.Sleep(millisecondsTimeout); Thread.Sleep(millisecondsTimeout);
if (cts is { IsCancellationRequested: true }) if (ct.IsCancellationRequested)
{ {
throw new NormalEndException("取消自动任务"); throw new NormalEndException("取消自动任务");
} }
} }
public static async Task Delay(int millisecondsTimeout, CancellationTokenSource cts) public static async Task Delay(int millisecondsTimeout, CancellationToken ct)
{ {
if (cts is { IsCancellationRequested: true }) if (ct is { IsCancellationRequested: true })
{ {
throw new NormalEndException("取消自动任务"); throw new NormalEndException("取消自动任务");
} }
@ -85,7 +149,7 @@ public class TaskControl
NewRetry.Do(() => NewRetry.Do(() =>
{ {
if (cts is { IsCancellationRequested: true }) if (ct is { IsCancellationRequested: true })
{ {
throw new NormalEndException("取消自动任务"); throw new NormalEndException("取消自动任务");
} }
@ -96,8 +160,8 @@ public class TaskControl
throw new RetryException("当前获取焦点的窗口不是原神"); throw new RetryException("当前获取焦点的窗口不是原神");
} }
}, TimeSpan.FromSeconds(1), 100); }, TimeSpan.FromSeconds(1), 100);
await Task.Delay(millisecondsTimeout, cts.Token); await Task.Delay(millisecondsTimeout, ct);
if (cts is { IsCancellationRequested: true }) if (ct is { IsCancellationRequested: true })
{ {
throw new NormalEndException("取消自动任务"); throw new NormalEndException("取消自动任务");
} }

View File

@ -5,5 +5,5 @@ namespace BetterGenshinImpact.GameTask;
public interface ISoloTask public interface ISoloTask
{ {
Task Start(CancellationTokenSource cts); Task Start(CancellationToken ct);
} }

View File

@ -1,26 +0,0 @@
using BetterGenshinImpact.GameTask.Model.Enum;
using System.Threading;
namespace BetterGenshinImpact.GameTask.Model;
/// <summary>
/// 独立任务参数基类
/// </summary>
public class TaskRunnerParam
{
public string Name { get; set; } = string.Empty;
public CancellationTokenSource Cts { get; set; }
/// <summary>
/// 针对实时触发器的操作
/// </summary>
public DispatcherTimerOperationEnum TriggerOperation { get; set; } = DispatcherTimerOperationEnum.None;
public bool UseLock { get; set; }
public TaskRunnerParam(CancellationTokenSource cts)
{
this.Cts = cts;
}
}

View File

@ -102,7 +102,7 @@ public class TaskRunner
public async Task RunSoloTaskAsync(ISoloTask soloTask) public async Task RunSoloTaskAsync(ISoloTask soloTask)
{ {
await Task.Run(() => RunAsync(async () => await soloTask.Start(CancellationContext.Instance.Cts))); await Task.Run(() => RunAsync(async () => await soloTask.Start(CancellationContext.Instance.Cts.Token)));
} }
public void Init() public void Init()

View File

@ -465,7 +465,7 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel
Config.HotKeyConfig.RecBigMapPosHotkeyType, Config.HotKeyConfig.RecBigMapPosHotkeyType,
(_, _) => (_, _) =>
{ {
var p = new TpTask(new CancellationTokenSource()).GetPositionFromBigMap(); var p = new TpTask(new CancellationToken()).GetPositionFromBigMap();
_logger.LogInformation("大地图位置:{Position}", p); _logger.LogInformation("大地图位置:{Position}", p);
} }
)); ));
@ -561,7 +561,7 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel
(_, _) => (_, _) =>
{ {
NahidaCollectHandler handler = new NahidaCollectHandler(); NahidaCollectHandler handler = new NahidaCollectHandler();
handler.RunAsync(new CancellationTokenSource()); handler.RunAsync(new CancellationToken());
} }
)); ));
debugDirectory.Children.Add(new HotKeySettingModel( debugDirectory.Children.Add(new HotKeySettingModel(