diff --git a/BetterGenshinImpact/GameTask/AutoWood/AutoWoodTask.cs b/BetterGenshinImpact/GameTask/AutoWood/AutoWoodTask.cs index 3f5e685c..072a1f8a 100644 --- a/BetterGenshinImpact/GameTask/AutoWood/AutoWoodTask.cs +++ b/BetterGenshinImpact/GameTask/AutoWood/AutoWoodTask.cs @@ -7,6 +7,8 @@ using BetterGenshinImpact.View.Drawable; using BetterGenshinImpact.ViewModel.Pages; using Microsoft.Extensions.Logging; using System; +using System.Diagnostics; +using System.Threading; using System.Windows; using WindowsInput; using static BetterGenshinImpact.GameTask.Common.TaskControl; @@ -39,6 +41,12 @@ public class AutoWoodTask try { Logger.LogInformation("→ {Text} 设置伐木总次数:{Cnt}", "自动伐木,启动!", taskParam.WoodRoundNum); + + _login3rdParty.RefreshAvailabled(); + if (_login3rdParty.Type == Login3rdParty.The3rdPartyType.Bilibili) + { + Logger.LogInformation("自动伐木启用B服模式"); + } SystemControl.ActivateWindow(); for (var i = 0; i < taskParam.WoodRoundNum; i++) { @@ -48,11 +56,6 @@ public class AutoWoodTask break; } - _login3rdParty.RefreshAvailabled(); - if (_login3rdParty.Type == Login3rdParty.The3rdPartyType.Bilibili) - { - Logger.LogInformation("自动伐木启用B服模式"); - } Felling(taskParam); VisionContext.Instance().DrawContent.ClearAll(); Sleep(500, taskParam.Cts); @@ -90,17 +93,28 @@ public class AutoWoodTask private void PressZ(WoodTaskParam taskParam) { + // IMPORTANT: MUST try focus before press Z + SystemControl.Focus(TaskContext.Instance().GameHandle); + if (_first) { var content = CaptureToContent(taskParam.Dispatcher.GameCapture); var ra = content.CaptureRectArea.Find(_assets.TheBoonOfTheElderTreeRo); if (ra.IsEmpty()) { +#if TEST_WITHOUT_Z_ITEM throw new NormalEndException("请先装备小道具「王树瑞佑」!"); +#else + Thread.Sleep(2000); + Simulation.SendInput.Keyboard.KeyPress(VirtualKeyCode.VK_Z); + Debug.WriteLine("[AutoWood] Z"); + _first = false; +#endif } else { Simulation.SendInput.Keyboard.KeyPress(VirtualKeyCode.VK_Z); + Debug.WriteLine("[AutoWood] Z"); _first = false; } } @@ -113,10 +127,16 @@ public class AutoWoodTask var ra = content.CaptureRectArea.Find(_assets.TheBoonOfTheElderTreeRo); if (ra.IsEmpty()) { +#if TEST_WITHOUT_Z_ITEM throw new RetryException("未找到「王树瑞佑」"); +#else + Thread.Sleep(15000); +#endif } Simulation.SendInput.Keyboard.KeyPress(VirtualKeyCode.VK_Z); + Debug.WriteLine("[AutoWood] Z"); + Sleep(500, taskParam.Cts); }, TimeSpan.FromSeconds(1), 120); } @@ -126,6 +146,7 @@ public class AutoWoodTask private void PressEsc(WoodTaskParam taskParam) { Simulation.SendInput.Keyboard.KeyPress(VirtualKeyCode.ESCAPE); + Debug.WriteLine("[AutoWood] Esc"); Sleep(800, taskParam.Cts); // 确认在菜单界面 try @@ -147,31 +168,35 @@ public class AutoWoodTask Logger.LogInformation("仍旧点击退出按钮"); } - // 点击退出 var captureArea = TaskContext.Instance().SystemInfo.CaptureAreaRect; var assetScale = TaskContext.Instance().SystemInfo.AssetScale; _clickOffset.Click((int)(50 * assetScale), captureArea.Height - (int)(50 * assetScale)); + Debug.WriteLine("[AutoWood] Click exit button"); Sleep(500, taskParam.Cts); // 点击确认 var content = CaptureToContent(taskParam.Dispatcher.GameCapture); - content.CaptureRectArea.Find(_assets.ConfirmRo, ra => { ra.ClickCenter(); }); + content.CaptureRectArea.Find(_assets.ConfirmRo, ra => + { + ra.ClickCenter(); + Debug.WriteLine("[AutoWood] Click confirm button"); + }); } private void EnterGame(WoodTaskParam taskParam) { + if (_login3rdParty.IsAvailabled) + { + Sleep(1, taskParam.Cts); + _login3rdParty.Login(taskParam.Cts); + } + NewRetry.Do(() => { Sleep(1, taskParam.Cts); - if (_login3rdParty.IsAvailabled) - { - _login3rdParty.Login(taskParam.Cts); - Sleep(2000, taskParam.Cts); - } - var content = CaptureToContent(taskParam.Dispatcher.GameCapture); var ra = content.CaptureRectArea.Find(_assets.EnterGameRo); if (ra.IsEmpty()) @@ -182,6 +207,7 @@ public class AutoWoodTask { Simulation.SendInput.Mouse.LeftButtonClick(); Sleep(5000, taskParam.Cts); + Debug.WriteLine("[AutoWood] Click entry text"); } }, TimeSpan.FromSeconds(1), 50); } diff --git a/BetterGenshinImpact/GameTask/AutoWood/Utils/Login3rdParty.cs b/BetterGenshinImpact/GameTask/AutoWood/Utils/Login3rdParty.cs index c0c387e4..326aece7 100644 --- a/BetterGenshinImpact/GameTask/AutoWood/Utils/Login3rdParty.cs +++ b/BetterGenshinImpact/GameTask/AutoWood/Utils/Login3rdParty.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; -using System.Threading.Tasks; using Vanara.PInvoke; using static BetterGenshinImpact.GameTask.Common.TaskControl; @@ -77,15 +76,23 @@ internal sealed class Login3rdParty } } - public async void Login(CancellationTokenSource cts) + public void Login(CancellationTokenSource cts) { - await Task.Run(() => + int failCount = default; + + while (!LoginPrivate(cts)) { - while (!LoginPrivate(cts)) + // It is necessary to support exitable trying. + // Can exit trying when over than 10s. + if (++failCount > 20) { - Sleep(500, cts); + Debug.WriteLine("[AutoWood] Give up to check login button and don't try again."); + break; } - }, cts.Token); + Debug.WriteLine($"[AutoWood] Fail to check login button {failCount} time(s)."); + Sleep(500, cts); + } + Debug.WriteLine("[AutoWood] Exit while check login button."); } private bool LoginPrivate(CancellationTokenSource cts) @@ -127,10 +134,11 @@ internal sealed class Login3rdParty } // Just for login WebUI chattering - Sleep(400, cts); + Sleep(2000, cts); var p = TaskContext.Instance().SystemInfo.CaptureAreaRect.GetCenterPoint(); p.Add(new(0, 125)).Click(); + Debug.WriteLine("[AutoWood] Click login button for the B one"); return true; } return false; diff --git a/BetterGenshinImpact/GameTask/SystemControl.cs b/BetterGenshinImpact/GameTask/SystemControl.cs index 9d60b678..cdc9f193 100644 --- a/BetterGenshinImpact/GameTask/SystemControl.cs +++ b/BetterGenshinImpact/GameTask/SystemControl.cs @@ -1,15 +1,10 @@ using BetterGenshinImpact.Core.Simulator; -using Fischless.GameCapture; -using Microsoft.Xaml.Behaviors.Media; using System; using System.Diagnostics; -using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Vanara.PInvoke; -using WindowsInput; -using Wpf.Ui.Appearance; namespace BetterGenshinImpact.GameTask; @@ -51,9 +46,9 @@ public class SystemControl return hWnd == TaskContext.Instance().GameHandle; } - public static IntPtr GetForegroundWindowHandle() + public static nint GetForegroundWindowHandle() { - return (IntPtr)User32.GetForegroundWindow(); + return (nint)User32.GetForegroundWindow(); } public static nint FindHandleByProcessName(params string[] names) @@ -85,7 +80,7 @@ public class SystemControl } } - public static Process? GetProcessByHandle(IntPtr hWnd) + public static Process? GetProcessByHandle(nint hWnd) { try { @@ -105,7 +100,7 @@ public class SystemControl /// /// /// - public static RECT GetWindowRect(IntPtr hWnd) + public static RECT GetWindowRect(nint hWnd) { // User32.GetWindowRect(hWnd, out var windowRect); DwmApi.DwmGetWindowAttribute(hWnd, DwmApi.DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS, out var windowRect); @@ -117,7 +112,7 @@ public class SystemControl /// /// /// - public static RECT GetGameScreenRect(IntPtr hWnd) + public static RECT GetGameScreenRect(nint hWnd) { User32.GetClientRect(hWnd, out var clientRect); return clientRect; @@ -128,7 +123,7 @@ public class SystemControl /// /// /// - public static RECT GetCaptureRect(IntPtr hWnd) + public static RECT GetCaptureRect(nint hWnd) { var windowRect = GetWindowRect(hWnd); var gameScreenRect = GetGameScreenRect(hWnd); @@ -139,7 +134,7 @@ public class SystemControl return new RECT(left, top, right, bottom); } - public static void ActivateWindow(IntPtr hWnd) + public static void ActivateWindow(nint hWnd) { User32.ShowWindow(hWnd, ShowWindowCommand.SW_RESTORE); User32.SetForegroundWindow(hWnd); @@ -154,6 +149,20 @@ public class SystemControl ActivateWindow(TaskContext.Instance().GameHandle); } + public static void Focus(nint hWnd) + { + if (User32.IsWindow(hWnd)) + { + _ = User32.SendMessage(hWnd, User32.WindowMessage.WM_SYSCOMMAND, User32.SysCommand.SC_RESTORE, 0); + _ = User32.SetForegroundWindow(hWnd); + while (User32.IsIconic(hWnd)) + { + continue; + } + _ = User32.BringWindowToTop(hWnd); + } + } + public static bool IsFullScreenMode(IntPtr hWnd) { if (hWnd == IntPtr.Zero)