From 53fc08bcb5c55c12abbb3ccc4bf647cb0895b3a4 Mon Sep 17 00:00:00 2001 From: Macocian Alexandru Victor Date: Thu, 19 Feb 2026 08:14:39 -0800 Subject: [PATCH] Simplify readychecker (#1457) * Fix windows ready checker (Closes #1456) * Add extra debugging line * Extra debug info --- .../ApplicationLauncher.cs | 1 + .../GuildWarsReadyChecker.cs | 83 +------------------ 2 files changed, 2 insertions(+), 82 deletions(-) diff --git a/Daybreak.Core/Services/ApplicationLauncher/ApplicationLauncher.cs b/Daybreak.Core/Services/ApplicationLauncher/ApplicationLauncher.cs index e9d30055..52d73cc1 100644 --- a/Daybreak.Core/Services/ApplicationLauncher/ApplicationLauncher.cs +++ b/Daybreak.Core/Services/ApplicationLauncher/ApplicationLauncher.cs @@ -439,6 +439,7 @@ internal sealed class ApplicationLauncher( return (default, []); } + scopedLogger.LogDebug("Waiting for Guild Wars to be ready..."); var sw = Stopwatch.StartNew(); var isReady = await this.guildWarsReadyChecker.WaitForReady( process, diff --git a/Daybreak.Windows/Services/ApplicationLauncher/GuildWarsReadyChecker.cs b/Daybreak.Windows/Services/ApplicationLauncher/GuildWarsReadyChecker.cs index 773f0077..e995e438 100644 --- a/Daybreak.Windows/Services/ApplicationLauncher/GuildWarsReadyChecker.cs +++ b/Daybreak.Windows/Services/ApplicationLauncher/GuildWarsReadyChecker.cs @@ -3,9 +3,6 @@ using Microsoft.Extensions.Logging; using System.Core.Extensions; using System.Diagnostics; using System.Extensions.Core; -using System.Runtime.InteropServices; -using System.Text; -using static Daybreak.Windows.Utils.NativeMethods; namespace Daybreak.Windows.Services.ApplicationLauncher; @@ -17,8 +14,6 @@ internal sealed class GuildWarsReadyChecker( ILogger logger ) : IGuildWarsReadyChecker { - private const double LaunchMemoryThreshold = 200000000; - private readonly ILogger logger = logger.ThrowIfNull(); public async Task WaitForReady(Process process, TimeSpan timeout, CancellationToken cancellationToken) @@ -41,87 +36,11 @@ internal sealed class GuildWarsReadyChecker( continue; } - var windows = GetRootWindowsOfProcess(process.Id) - .Select(root => (root, GetChildWindows(root))) - .SelectMany(tuple => - { - tuple.Item2.Add(tuple.root); - return tuple.Item2; - }) - .Select(GetWindowTitle).ToList(); - - /* - * Detect when the game window has shown. Because both the updater and the game window are called Guild Wars, - * we need to look at the other windows created by the process. Especially, we need to detect the input windows - * to check when the game is ready to accept input - */ - if (!windows.Contains("Guild Wars Reforged")) - { - continue; - } - - var virtualMemory = process.VirtualMemorySize64; - if (virtualMemory < LaunchMemoryThreshold) - { - continue; - } - + scopedLogger.LogInformation("Guild Wars process is ready and running"); return true; } scopedLogger.LogError("Timed out waiting for Guild Wars to be ready"); return false; } - - private static List GetRootWindowsOfProcess(int pid) - { - var rootWindows = GetChildWindows(IntPtr.Zero); - var dsProcRootWindows = new List(); - foreach (IntPtr hWnd in rootWindows) - { - _ = GetWindowThreadProcessId(hWnd, out var lpdwProcessId); - if (lpdwProcessId == pid) - dsProcRootWindows.Add(hWnd); - } - - return dsProcRootWindows; - } - - private static List GetChildWindows(IntPtr parent) - { - var result = new List(); - var listHandle = GCHandle.Alloc(result); - try - { - var childProc = new Win32Callback(EnumWindow); - EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle)); - } - finally - { - if (listHandle.IsAllocated) - listHandle.Free(); - } - - return result; - } - - private static string GetWindowTitle(IntPtr hwnd) - { - var titleLength = GetWindowTextLength(hwnd); - var titleBuffer = new StringBuilder(titleLength); - _ = GetWindowText(hwnd, titleBuffer, titleLength + 1); - return titleBuffer.ToString(); - } - - private static bool EnumWindow(IntPtr handle, IntPtr pointer) - { - var gch = GCHandle.FromIntPtr(pointer); - if (gch.Target is not List list) - { - return false; - } - - list.Add(handle); - return true; - } }