From 8b31a64fbe05b93f4eb3132cb4f706956f036be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=89=E9=B8=AD=E8=9B=8B?= Date: Fri, 27 Dec 2024 00:57:18 +0800 Subject: [PATCH] new game path loader (cherry picked from commit dc853f230700093756a4613bcadcdb9570d37866) --- .../Genshin/Paths/GameExePath.cs | 4 ++ .../Genshin/Paths/RegistryGameLocator.cs | 41 ++++++++++++ .../Genshin/Paths/UnityLogGameLocator.cs | 66 +++++++++++++++++++ .../ViewModel/Pages/HomePageViewModel.cs | 19 ++++-- 4 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 BetterGenshinImpact/Genshin/Paths/RegistryGameLocator.cs create mode 100644 BetterGenshinImpact/Genshin/Paths/UnityLogGameLocator.cs diff --git a/BetterGenshinImpact/Genshin/Paths/GameExePath.cs b/BetterGenshinImpact/Genshin/Paths/GameExePath.cs index 15a0c8a9..f6f4beb0 100644 --- a/BetterGenshinImpact/Genshin/Paths/GameExePath.cs +++ b/BetterGenshinImpact/Genshin/Paths/GameExePath.cs @@ -9,6 +9,10 @@ using System.Text.RegularExpressions; namespace BetterGenshinImpact.Genshin.Paths; +/// +/// 已经弃用 +/// +[Obsolete] internal partial class GameExePath { public static readonly FrozenSet GameRegistryPaths = FrozenSet.ToFrozenSet( diff --git a/BetterGenshinImpact/Genshin/Paths/RegistryGameLocator.cs b/BetterGenshinImpact/Genshin/Paths/RegistryGameLocator.cs new file mode 100644 index 00000000..cfc3992f --- /dev/null +++ b/BetterGenshinImpact/Genshin/Paths/RegistryGameLocator.cs @@ -0,0 +1,41 @@ +using System; +using BetterGenshinImpact.GameTask.Common; +using Microsoft.Extensions.Logging; +using Microsoft.Win32; + +namespace BetterGenshinImpact.Genshin.Paths; + +/// +/// https://github.com/Scighost/Starward/blob/main/src%2FStarward%2FServices%2FLauncher%2FGameLauncherService.cs#L112-L112 +/// +public class RegistryGameLocator +{ + public static string? GetDefaultGameInstallPath() + { + try + { + var cn = Registry.GetValue($@"HKEY_CURRENT_USER\Software\miHoYo\HYP\1_1\hk4e_cn", "GameInstallPath", null) as string; + if (!string.IsNullOrEmpty(cn)) + { + return cn; + } + + var global = Registry.GetValue($@"HKEY_CURRENT_USER\Software\Cognosphere\HYP\1_0\hk4e_global", "GameInstallPath", null) as string; + if (!string.IsNullOrEmpty(global)) + { + return global; + } + + var bilibili = Registry.GetValue($@"HKEY_CURRENT_USER\Software\miHoYo\HYP\standalone\14_0\hk4e_bilibili\BilibiliGenshin\hk4e_bilibili", "GameInstallPath", null) as string; + if (!string.IsNullOrEmpty(bilibili)) + { + return bilibili; + } + } + catch (Exception e) + { + TaskControl.Logger.LogDebug(e, "Failed to locate game path."); + } + return null; + } +} \ No newline at end of file diff --git a/BetterGenshinImpact/Genshin/Paths/UnityLogGameLocator.cs b/BetterGenshinImpact/Genshin/Paths/UnityLogGameLocator.cs new file mode 100644 index 00000000..a31501d4 --- /dev/null +++ b/BetterGenshinImpact/Genshin/Paths/UnityLogGameLocator.cs @@ -0,0 +1,66 @@ +using System; +using System.IO; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using BetterGenshinImpact.GameTask.Common; +using Microsoft.Extensions.Logging; + +namespace BetterGenshinImpact.Genshin.Paths; + +/// +/// https://github.com/DGP-Studio/Snap.Hutao/blob/main/src/Snap.Hutao/Snap.Hutao/Service/Game/Locator/UnityLogGameLocator.cs +/// +public partial class UnityLogGameLocator +{ + [GeneratedRegex(@".:/.+(?:GenshinImpact|YuanShen)(?=_Data)", RegexOptions.IgnoreCase)] + private static partial Regex WarmupFileLine(); + + public static async ValueTask LocateSingleGamePathAsync() + { + try + { + string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + string logFilePathOversea = Path.Combine(appDataPath, @"..\LocalLow\miHoYo\Genshin Impact\output_log.txt"); + string logFilePathChinese = Path.Combine(appDataPath, @"..\LocalLow\miHoYo\原神\output_log.txt"); + + // Fallback to the CN server. + string logFilePath = File.Exists(logFilePathChinese) ? logFilePathChinese : logFilePathOversea; + return await LocateGamePathAsync(logFilePath).ConfigureAwait(false); + } + catch (Exception e) + { + TaskControl.Logger.LogDebug(e, "Failed to locate game path."); + return null; + } + } + + private static async ValueTask LocateGamePathAsync(string logFilePath) + { + if (!File.Exists(logFilePath)) + { + return null; + } + + string content; + try + { + await using var fileStream = new FileStream(logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + using var reader = new StreamReader(fileStream); + content = await reader.ReadToEndAsync(); + } + catch (IOException) + { + return null; + } + + Match matchResult = WarmupFileLine().Match(content); + if (!matchResult.Success) + { + return null; + } + + string entryName = $"{matchResult.Value}.exe"; + string fullPath = Path.GetFullPath(Path.Combine(matchResult.Value, "..", entryName)); + return fullPath; + } +} \ No newline at end of file diff --git a/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs index 272c44fd..7d1b323c 100644 --- a/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/HomePageViewModel.cs @@ -340,11 +340,22 @@ public partial class HomePageViewModel : ObservableObject, INavigationAware, IVi // 检查用户是否配置了原神安装目录,如果没有,尝试从注册表中读取 if (string.IsNullOrEmpty(Config.GenshinStartConfig.InstallPath)) { - var path = GameExePath.GetWithoutCloud(); - if (!string.IsNullOrEmpty(path)) + Task.Run(async () => { - Config.GenshinStartConfig.InstallPath = path; - } + var p1 = RegistryGameLocator.GetDefaultGameInstallPath(); + if (!string.IsNullOrEmpty(p1)) + { + Config.GenshinStartConfig.InstallPath = p1; + } + else + { + var path = await UnityLogGameLocator.LocateSingleGamePathAsync(); + if (!string.IsNullOrEmpty(path)) + { + Config.GenshinStartConfig.InstallPath = path; + } + } + }); } }