mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-05-17 09:26:50 +08:00
修复B服登录与重登陆 (#1965)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using BetterGenshinImpact.Core.Recognition.OpenCv;
|
||||
using BetterGenshinImpact.Core.Recognition.OpenCv;
|
||||
using BetterGenshinImpact.Helpers.Extensions;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
@@ -7,6 +7,8 @@ using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using BetterGenshinImpact.GameTask.Model.Area;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Vanara.PInvoke;
|
||||
using static BetterGenshinImpact.GameTask.Common.TaskControl;
|
||||
|
||||
@@ -89,9 +91,11 @@ internal sealed class Login3rdParty
|
||||
Debug.WriteLine("[AutoWood] Give up to check login button and don't try again.");
|
||||
break;
|
||||
}
|
||||
|
||||
Debug.WriteLine($"[AutoWood] Fail to check login button {failCount} time(s).");
|
||||
Sleep(500, ct);
|
||||
}
|
||||
|
||||
Debug.WriteLine("[AutoWood] Exit while check login button.");
|
||||
}
|
||||
|
||||
@@ -101,31 +105,56 @@ internal sealed class Login3rdParty
|
||||
{
|
||||
if (Process.GetProcessesByName("YuanShen").FirstOrDefault() is Process process)
|
||||
{
|
||||
if (GetBHWnd(process) != IntPtr.Zero)
|
||||
// 使用新的B服登录逻辑
|
||||
var (loginWindow, windowType) = GetBiliLoginWindow(process);
|
||||
if (loginWindow != IntPtr.Zero)
|
||||
{
|
||||
// Just for login WebUI fadein chattering
|
||||
Sleep(4000, ct);
|
||||
|
||||
var p = TaskContext.Instance()
|
||||
.SystemInfo.CaptureAreaRect.GetCenterPoint()
|
||||
.Add(new(0, 85));
|
||||
|
||||
p.Click();
|
||||
Debug.WriteLine("[AutoWood] Click login button for the B one");
|
||||
|
||||
// Just for login WebUI fadeout chattering
|
||||
Sleep(3000, ct);
|
||||
|
||||
if (GetBHWnd(process) != IntPtr.Zero)
|
||||
// if (windowType.Contains("协议"))
|
||||
// {
|
||||
// // 点击协议窗口
|
||||
// var p = TaskContext.Instance()
|
||||
// .SystemInfo.CaptureAreaRect.GetCenterPoint()
|
||||
// .Add(new(40, 60));
|
||||
// p.Click();
|
||||
// Debug.WriteLine("[AutoWood] Click protocol window for Bilibili");
|
||||
// // Sleep(2000, ct);
|
||||
// Thread.Sleep(3000);
|
||||
//
|
||||
// // 检查窗口是否还存在
|
||||
// var (remainingWindow, remainingType) = GetBiliLoginWindow(process);
|
||||
// if (remainingWindow == IntPtr.Zero || !remainingType.Contains("协议"))
|
||||
// {
|
||||
// // 协议窗口已消失,继续等待登录窗口
|
||||
// return false; // 继续循环等待登录窗口
|
||||
// }
|
||||
//
|
||||
// return false; // 协议窗口仍然存在,继续尝试
|
||||
// }
|
||||
if (windowType.Contains("登录"))
|
||||
{
|
||||
// 点击登录窗口
|
||||
var p = TaskContext.Instance()
|
||||
.SystemInfo.CaptureAreaRect.GetCenterPoint()
|
||||
.Add(new(0, 90));
|
||||
p.Click();
|
||||
Debug.WriteLine("[AutoWood] Click login button for the B one [LAST CHANCE]");
|
||||
}
|
||||
Debug.WriteLine("[AutoWood] Click login window for Bilibili");
|
||||
// Sleep(2000, ct);
|
||||
Thread.Sleep(3000);
|
||||
|
||||
return true;
|
||||
// 检查窗口是否还存在
|
||||
var (remainingWindow, remainingType) = GetBiliLoginWindow(process);
|
||||
if (remainingWindow != IntPtr.Zero)
|
||||
{
|
||||
p.Click();
|
||||
Debug.WriteLine("[AutoWood] Bilibili login successful");
|
||||
}
|
||||
return true; // 登录成功
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
return false; // 没有找到登录窗口
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@@ -135,37 +164,72 @@ internal sealed class Login3rdParty
|
||||
}
|
||||
}
|
||||
|
||||
static nint GetBHWnd(Process process)
|
||||
static (IntPtr windowHandle, string windowType) GetBiliLoginWindow(Process process)
|
||||
{
|
||||
nint bHWnd = IntPtr.Zero;
|
||||
IntPtr bHWnd = IntPtr.Zero;
|
||||
string windowType = "";
|
||||
|
||||
_ = User32.EnumWindows((HWND hWnd, nint lParam) =>
|
||||
User32.EnumWindows((hWnd, lParam) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
_ = User32.GetWindowThreadProcessId(hWnd, out uint pid);
|
||||
|
||||
if (pid == process.Id)
|
||||
// 获取窗口标题
|
||||
int titleLength = User32.GetWindowTextLength(hWnd);
|
||||
if (titleLength > 0)
|
||||
{
|
||||
int capacity = User32.GetWindowTextLength(hWnd);
|
||||
StringBuilder title = new(capacity + 1);
|
||||
_ = User32.GetWindowText(hWnd, title, title.Capacity);
|
||||
StringBuilder title = new StringBuilder(titleLength + 1);
|
||||
User32.GetWindowText(hWnd, title, title.Capacity);
|
||||
|
||||
Debug.WriteLine($"[AutoWood] Enum Windows result is {title}");
|
||||
if (title.ToString().Contains("bilibili", StringComparison.OrdinalIgnoreCase))
|
||||
string titleText = title.ToString();
|
||||
|
||||
// 检查是否是B服登录窗口(通过标题匹配)
|
||||
if (titleText.Contains("bilibili", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
bHWnd = (nint)hWnd;
|
||||
return false;
|
||||
// 检查窗口所有者是否是原神进程
|
||||
var owner = User32.GetWindow(hWnd, User32.GetWindowCmd.GW_OWNER);
|
||||
if (owner != IntPtr.Zero)
|
||||
{
|
||||
User32.GetWindowThreadProcessId(owner, out uint ownerPid);
|
||||
if (ownerPid == process.Id)
|
||||
{
|
||||
// 检查窗口是否可见和启用
|
||||
bool isVisible = User32.IsWindowVisible(hWnd);
|
||||
bool isEnabled = User32.IsWindowEnabled(hWnd);
|
||||
|
||||
// 检查协议窗口
|
||||
if (titleText.Contains("协议", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
bHWnd = hWnd.DangerousGetHandle();
|
||||
windowType = "协议";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查登录窗口
|
||||
if (titleText.Contains("登录", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
bHWnd = hWnd.DangerousGetHandle();
|
||||
windowType = "登录";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
///
|
||||
Debug.WriteLine($"[AutoWood] 枚举窗口时出错: {ex.Message}");
|
||||
}
|
||||
|
||||
return true;
|
||||
}, IntPtr.Zero);
|
||||
|
||||
return bHWnd;
|
||||
return (bHWnd, windowType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,8 @@ public class ExitAndReloginJob
|
||||
_login3rdParty.RefreshAvailabled();
|
||||
if (_login3rdParty is { Type: Login3rdParty.The3rdPartyType.Bilibili, IsAvailabled: true })
|
||||
{
|
||||
await Delay(1, ct);
|
||||
// await Delay(1, ct);
|
||||
Thread.Sleep(100);
|
||||
_login3rdParty.Login(ct);
|
||||
Logger.LogInformation("退出重登启用 B 服模式");
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ public class GameLoadingTrigger : ITaskTrigger
|
||||
private readonly GameLoadingAssets _assets;
|
||||
|
||||
private readonly GenshinStartConfig _config = TaskContext.Instance().Config.GenshinStartConfig;
|
||||
private static ILogger<GameLoadingTrigger> _logger = App.GetLogger<GameLoadingTrigger>();
|
||||
|
||||
|
||||
// private int _enterGameClickCount = 0;
|
||||
@@ -74,10 +75,12 @@ public class GameLoadingTrigger : ITaskTrigger
|
||||
if (_config.RecordGameTimeEnabled)
|
||||
{
|
||||
FileName = Path.GetFileName(_config.InstallPath);
|
||||
if (FileName == "GenshinImpact.exe") {
|
||||
if (FileName == "GenshinImpact.exe")
|
||||
{
|
||||
GameServer = "hk4e_global";
|
||||
StartStarward();
|
||||
}
|
||||
|
||||
if (FileName == "YuanShen.exe")
|
||||
{
|
||||
string iniPath = Path.GetDirectoryName(_config.InstallPath) + "//config.ini";
|
||||
@@ -91,7 +94,8 @@ public class GameLoadingTrigger : ITaskTrigger
|
||||
try
|
||||
{
|
||||
iniContent = File.ReadAllText(iniPath);
|
||||
Regex regex = new Regex(pattern, RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
|
||||
Regex regex = new Regex(pattern,
|
||||
RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
|
||||
Match match = regex.Match(iniContent);
|
||||
channelValue = match.Success ? match.Groups[1].Value : "";
|
||||
}
|
||||
@@ -106,12 +110,13 @@ public class GameLoadingTrigger : ITaskTrigger
|
||||
GameServer = "hk4e_cn";
|
||||
StartStarward();
|
||||
}
|
||||
|
||||
if (channelValue == "14")
|
||||
{
|
||||
GameServer = "hk4e_bilibili";
|
||||
StartStarward();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Debug.WriteLine($"[GameLoading] 从文件读取到游戏区服:{GameServer}");
|
||||
// 这里注册表的优先级要比读取文件低,因为使用starward安装原神不会写入注册表
|
||||
@@ -152,7 +157,9 @@ public class GameLoadingTrigger : ITaskTrigger
|
||||
{
|
||||
try
|
||||
{
|
||||
var cn = Registry.GetValue($@"HKEY_CURRENT_USER\Software\miHoYo\HYP\1_1\hk4e_cn", "GameInstallPath", null) as string;
|
||||
var cn =
|
||||
Registry.GetValue($@"HKEY_CURRENT_USER\Software\miHoYo\HYP\1_1\hk4e_cn", "GameInstallPath",
|
||||
null) as string;
|
||||
if (!string.IsNullOrEmpty(cn))
|
||||
{
|
||||
var filePath = Path.Combine(cn, "YuanShen.exe");
|
||||
@@ -160,7 +167,8 @@ public class GameLoadingTrigger : ITaskTrigger
|
||||
return GameServer;
|
||||
}
|
||||
|
||||
var global = Registry.GetValue($@"HKEY_CURRENT_USER\Software\Cognosphere\HYP\1_0\hk4e_global", "GameInstallPath", null) as string;
|
||||
var global = Registry.GetValue($@"HKEY_CURRENT_USER\Software\Cognosphere\HYP\1_0\hk4e_global",
|
||||
"GameInstallPath", null) as string;
|
||||
if (!string.IsNullOrEmpty(global))
|
||||
{
|
||||
var filePath = Path.Combine(global, "GenshinImpact.exe");
|
||||
@@ -168,19 +176,21 @@ public class GameLoadingTrigger : ITaskTrigger
|
||||
return GameServer;
|
||||
}
|
||||
|
||||
var bilibili = Registry.GetValue($@"HKEY_CURRENT_USER\Software\miHoYo\HYP\standalone\14_0\hk4e_cn\umfgRO5gh5\hk4e_cn", "GameInstallPath", null) as string;
|
||||
var bilibili =
|
||||
Registry.GetValue($@"HKEY_CURRENT_USER\Software\miHoYo\HYP\standalone\14_0\hk4e_cn\umfgRO5gh5\hk4e_cn",
|
||||
"GameInstallPath", null) as string;
|
||||
if (!string.IsNullOrEmpty(bilibili))
|
||||
{
|
||||
var filePath = Path.Combine(bilibili, "YuanShen.exe");
|
||||
GameServer = "hk4e_bilibili";
|
||||
return GameServer;
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
TaskControl.Logger.LogDebug(e, "获取服务器失败");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -209,6 +219,7 @@ public class GameLoadingTrigger : ITaskTrigger
|
||||
// 如果访问注册表时发生错误,记录调试信息
|
||||
Debug.WriteLine($"[GameLoading] 检查 Starward 协议时发生错误: {ex.Message}");
|
||||
}
|
||||
|
||||
// 如果键不存在或不符合条件,返回 false
|
||||
return false;
|
||||
}
|
||||
@@ -220,6 +231,7 @@ public class GameLoadingTrigger : ITaskTrigger
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_prevExecuteTime = DateTime.Now;
|
||||
// 5min 后自动停止
|
||||
if ((DateTime.Now - _triggerStartTime).TotalMinutes >= 5)
|
||||
@@ -261,6 +273,7 @@ public class GameLoadingTrigger : ITaskTrigger
|
||||
{
|
||||
TaskControl.Logger.LogWarning("B服判断异常: " + ex.Message);
|
||||
}
|
||||
|
||||
// 官服流程:先识别并点击顶号或切号的后一次“进入游戏”弹窗按钮
|
||||
if (!isBili)
|
||||
{
|
||||
@@ -271,44 +284,75 @@ public class GameLoadingTrigger : ITaskTrigger
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 官服流程:点击进入游戏按钮(作为外层包装)
|
||||
using var ra = content.CaptureRectArea.Find(_assets.EnterGameRo);
|
||||
if (!ra.IsEmpty())
|
||||
{
|
||||
if (isBili)
|
||||
{
|
||||
// B服流程:处理登录窗口
|
||||
if (!biliLoginClicked)
|
||||
{
|
||||
int failCount = 0;
|
||||
while (true)
|
||||
{
|
||||
var process = Process.GetProcessesByName("YuanShen").FirstOrDefault();
|
||||
if (process != null && GetBiliLoginWindow(process) != IntPtr.Zero)
|
||||
var (loginWindow, windowType) = GetBiliLoginWindow(process);
|
||||
if (process != null && loginWindow != IntPtr.Zero)
|
||||
{
|
||||
GameCaptureRegion.GameRegion1080PPosClick(960, 630);
|
||||
TaskControl.Sleep(3000, CancellationToken.None);
|
||||
if (GetBiliLoginWindow(process) != IntPtr.Zero)
|
||||
if (windowType.Contains("协议"))
|
||||
{
|
||||
GameCaptureRegion.GameRegion1080PPosClick(960, 630);
|
||||
// 点击协议窗口
|
||||
GameCaptureRegion.GameRegion1080PPosClick(1000, 600);
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// 检查窗口是否还存在
|
||||
var (remainingWindow, remainingType) = GetBiliLoginWindow(process);
|
||||
if (remainingWindow == IntPtr.Zero || !remainingType.Contains("协议"))
|
||||
{
|
||||
// 协议窗口已消失,继续等待登录窗口
|
||||
continue;
|
||||
}
|
||||
failCount++;
|
||||
continue;
|
||||
}
|
||||
if (windowType.Contains("登录"))
|
||||
{
|
||||
// 点击登录窗口
|
||||
GameCaptureRegion.GameRegion1080PPosClick(960, 630);
|
||||
Thread.Sleep(2000);
|
||||
|
||||
// 检查窗口是否还存在
|
||||
var (remainingWindow, remainingType) = GetBiliLoginWindow(process);
|
||||
if (remainingWindow == IntPtr.Zero)
|
||||
{
|
||||
biliLoginClicked = true;
|
||||
break; // 登录成功,跳出循环
|
||||
}
|
||||
failCount++;
|
||||
continue;
|
||||
}
|
||||
biliLoginClicked = true;
|
||||
break;
|
||||
}
|
||||
failCount++;
|
||||
|
||||
if (failCount > 20)
|
||||
{
|
||||
break;
|
||||
}
|
||||
TaskControl.Sleep(500, CancellationToken.None);
|
||||
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
}
|
||||
// B服登录点击后,等待一小段时间再执行官服点击逻辑
|
||||
TaskControl.Sleep(5000, CancellationToken.None);
|
||||
|
||||
Thread.Sleep(5000);
|
||||
ClickEnterGameButton();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 官服流程:直接点击进入游戏按钮
|
||||
ClickEnterGameButton();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -333,30 +377,74 @@ public class GameLoadingTrigger : ITaskTrigger
|
||||
}
|
||||
|
||||
// B服登录窗口检测(参考Login3rdParty)
|
||||
private static IntPtr GetBiliLoginWindow(Process process)
|
||||
private static (IntPtr windowHandle, string windowType) GetBiliLoginWindow(Process process)
|
||||
{
|
||||
IntPtr bHWnd = IntPtr.Zero;
|
||||
string windowType = "";
|
||||
|
||||
User32.EnumWindows((hWnd, lParam) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
User32.GetWindowThreadProcessId(hWnd, out uint pid);
|
||||
if (pid == process.Id)
|
||||
// 获取窗口标题
|
||||
int titleLength = User32.GetWindowTextLength(hWnd);
|
||||
if (titleLength > 0)
|
||||
{
|
||||
int capacity = User32.GetWindowTextLength(hWnd);
|
||||
StringBuilder title = new(capacity + 1);
|
||||
StringBuilder title = new StringBuilder(titleLength + 1);
|
||||
User32.GetWindowText(hWnd, title, title.Capacity);
|
||||
if (title.ToString().Contains("bilibili", StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
string titleText = title.ToString();
|
||||
// _logger.LogInformation($"窗口标题: {titleText}");
|
||||
|
||||
// 检查是否是B服登录窗口(通过标题匹配)
|
||||
if (titleText.Contains("bilibili", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
bHWnd = hWnd.DangerousGetHandle();
|
||||
return false;
|
||||
// 检查窗口所有者是否是原神进程
|
||||
var owner = User32.GetWindow(hWnd, User32.GetWindowCmd.GW_OWNER);
|
||||
if (owner != IntPtr.Zero)
|
||||
{
|
||||
User32.GetWindowThreadProcessId(owner, out uint ownerPid);
|
||||
if (ownerPid == process.Id)
|
||||
{
|
||||
// 检查窗口是否可见和启用
|
||||
bool isVisible = User32.IsWindowVisible(hWnd);
|
||||
bool isEnabled = User32.IsWindowEnabled(hWnd);
|
||||
|
||||
// 检查协议窗口
|
||||
if (titleText.Contains("协议", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
bHWnd = hWnd.DangerousGetHandle();
|
||||
windowType = "协议";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查登录窗口
|
||||
if (titleText.Contains("登录", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
bHWnd = hWnd.DangerousGetHandle();
|
||||
windowType = "登录";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogDebug($"枚举窗口时出错: {ex.Message}");
|
||||
}
|
||||
|
||||
return true;
|
||||
}, IntPtr.Zero);
|
||||
return bHWnd;
|
||||
|
||||
return (bHWnd, windowType);
|
||||
}
|
||||
|
||||
private void ClickEnterGameButton()
|
||||
|
||||
Reference in New Issue
Block a user