修复B服登录与重登陆 (#1965)

This commit is contained in:
zdAnQi
2025-07-31 14:10:41 +08:00
committed by GitHub
parent 1d49a0bd26
commit bdfaf91be9
3 changed files with 218 additions and 65 deletions

View File

@@ -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);
}
}

View File

@@ -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 服模式");
}

View File

@@ -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()