diff --git a/README.md b/README.md index 0b2f642..337b230 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ 自带的注入功能只有FPS调整,只保证FPS调整长期可用,你可以使用`注入选项`下方的第三方工具来使用更多功能,本项目提供的所有注入功能都不会影响游戏的公平性。 -官网:https://htserver.wdg.cloudns.ch/ +官网:https://htserver.wdg12.work/ **该版本的特点:** - 尽量保留原版功能,少重写功能,稳定性强 @@ -113,10 +113,10 @@ http://htgit.wdg.cloudns.ch/wdg1122/Snap.Metadata ![http://serverjp.wdg.cloudns.ch:3001/api/badge/10/status?style=flat-square](http://serverjp.wdg.cloudns.ch:3001/api/badge/10/status?style=flat-square) -https://htserver.wdg.cloudns.ch/api/ +https://htserver.wdg12.work/api/ --- **图片资源站:** -https://htserver.wdg.cloudns.ch/ +https://htserver.wdg12.work/ diff --git a/src/Snap.Hutao/Snap.Hutao.Installer/Package.wxs b/src/Snap.Hutao/Snap.Hutao.Installer/Package.wxs index 8abb70f..1bf16ea 100644 --- a/src/Snap.Hutao/Snap.Hutao.Installer/Package.wxs +++ b/src/Snap.Hutao/Snap.Hutao.Installer/Package.wxs @@ -3,7 +3,7 @@ diff --git a/src/Snap.Hutao/Snap.Hutao/Bootstrap.cs b/src/Snap.Hutao/Snap.Hutao/Bootstrap.cs index 0428801..357bb1e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Bootstrap.cs +++ b/src/Snap.Hutao/Snap.Hutao/Bootstrap.cs @@ -22,6 +22,11 @@ public static partial class Bootstrap private static readonly ApplicationInitializationCallback AppInitializationCallback = InitializeApp; private static Mutex? mutex; + /// + /// Gets a value indicating whether console output is enabled. + /// + public static bool ConsoleEnabled { get; private set; } + internal static void UseNamedPipeRedirection() { Debug.Assert(mutex is not null); @@ -31,6 +36,19 @@ public static partial class Bootstrap [STAThread] private static void Main(string[] args) { + // Check for console flag + ConsoleEnabled = args.Contains("--console") || args.Contains("--debug") || + Environment.GetEnvironmentVariable("HUTAO_DEBUG") == "1"; + + if (ConsoleEnabled) + { + // Allocate a console window for debug output + HutaoNativeMethods.AllocConsole(); + Console.WriteLine("[Bootstrap] Console allocated for debug output"); + Console.WriteLine($"[Bootstrap] Arguments: {string.Join(" ", args)}"); + Console.WriteLine($"[Bootstrap] Working Directory: {Environment.CurrentDirectory}"); + } + #if DEBUG System.Diagnostics.Debug.WriteLine("[Bootstrap.Main] Starting..."); #endif @@ -124,6 +142,12 @@ public static partial class Bootstrap #if DEBUG System.Diagnostics.Debug.WriteLine("[Bootstrap.Main] Exiting"); #endif + + if (ConsoleEnabled) + { + Console.WriteLine("[Bootstrap] Application exiting..."); + HutaoNativeMethods.FreeConsole(); + } } private static void InitializeApp(ApplicationInitializationCallbackParams param) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/DependencyInjection.cs b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/DependencyInjection.cs index 51d1ad4..a3d89cf 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/DependencyInjection.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/DependencyInjection.cs @@ -29,6 +29,12 @@ internal static class DependencyInjection .AddFilter(DbLoggerCategory.Query.Name, level => level >= LogLevel.Information) .AddDebug() .AddSentryTelemetry(); + + // Add console logging if console is enabled + if (Bootstrap.ConsoleEnabled) + { + builder.AddConsole(); + } }) .AddMemoryCache() diff --git a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest index 51f1c6f..ce0549b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest +++ b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest @@ -13,7 +13,7 @@ + Version="1.18.6.0" /> Snap Hutao diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx index fc26109..7464282 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx @@ -1127,12 +1127,21 @@ 无法读取或保存配置文件,请以管理员模式重试 + + 现有元数据仓库更新失败,正在重新下载 + + + 首次下载或仓库损坏,正在下载元数据 + 操作完成 操作失败 + + 检查元数据更新 + 祈愿记录上传服务有效期至 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Git/GitRepositoryService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Git/GitRepositoryService.cs index 99fcb39..6449c4d 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Git/GitRepositoryService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Git/GitRepositoryService.cs @@ -21,6 +21,7 @@ internal sealed partial class GitRepositoryService : IGitRepositoryService { private readonly AsyncKeyedLock repoLock = new(); private readonly BackgroundActivityOptions backgroundActivityOptions; + private readonly ILogger logger; private readonly IServiceProvider serviceProvider; private readonly ITaskContext taskContext; @@ -76,6 +77,7 @@ internal sealed partial class GitRepositoryService : IGitRepositoryService } catch (Exception first) { + logger.LogWarning(first, "[Metadata] Failed to update existing repository, fallback to reclone: Directory={Directory}, Url={Url}", directory, info.HttpsUrl.OriginalString); exceptions.Add(first); return EnsureRepository(activity, directory, info, true); } @@ -110,6 +112,14 @@ internal sealed partial class GitRepositoryService : IGitRepositoryService { // Increase & decrease count in the same method, so that crash in the middle can correctly count as failure. RepositoryAffinity.IncreaseFailure(info); + + // Debug: Log the initial state + bool isRepoValid = Repository.IsValid(directory); + bool directoryExists = Directory.Exists(directory); + + logger.LogInformation("[Metadata] Checking repository: Directory={Directory}, Exists={Exists}, IsValid={IsValid}, ForceInvalid={ForceInvalid}", + directory, directoryExists, isRepoValid, forceInvalid); + FetchOptions fetchOptions = new() { Depth = 1, @@ -142,10 +152,18 @@ internal sealed partial class GitRepositoryService : IGitRepositoryService CertificateCheck = static (cert, valid, host) => true, }; - if (forceInvalid || !Repository.IsValid(directory)) + if (forceInvalid || !isRepoValid) { - if (Directory.Exists(directory)) + // Debug: Log why we're cloning + string reason = forceInvalid + ? SH.ServiceGitRepositoryCloneReasonForceInvalid + : SH.ServiceGitRepositoryCloneReasonInvalidRepo; + logger.LogInformation("[Metadata] Cloning repository: Reason={Reason}, Url={Url}", reason, info.HttpsUrl.OriginalString); + activity.Update(taskContext, reason, false, false, false, false); + + if (directoryExists) { + logger.LogInformation("[Metadata] Deleting existing directory before clone"); Directory.SetReadOnly(directory, false); Directory.Delete(directory, true); } @@ -154,9 +172,15 @@ internal sealed partial class GitRepositoryService : IGitRepositoryService { Checkout = true, }); + + logger.LogInformation("[Metadata] Clone completed successfully"); } else { + // Debug: Log that we're updating + logger.LogInformation("[Metadata] Updating existing repository"); + activity.Update(taskContext, SH.ServiceGitRepositoryUpdatingExisting, false, false, false, false); + // We need to ensure local repo is up to date using (Repository repo = new(directory)) { @@ -177,17 +201,20 @@ internal sealed partial class GitRepositoryService : IGitRepositoryService repo.Network.Remotes.Update("origin", remote => remote.Url = info.HttpsUrl.OriginalString); repo.RemoveUntrackedFiles(); fetchOptions.UpdateFetchHead = false; - Commands.Fetch(repo, repo.Head.RemoteName, Array.Empty(), fetchOptions, default); + Commands.Fetch(repo, "origin", Array.Empty(), fetchOptions, default); // Manually patch .git/shallow file - File.WriteAllText(Path.Combine(directory, ".git//shallow"), string.Join("", repo.Branches.Where(static branch => branch.IsRemote).Select(static branch => $"{branch.Tip.Sha}\n"))); + File.WriteAllText(Path.Combine(directory, ".git", "shallow"), string.Join("", repo.Branches.Where(static branch => branch.IsRemote).Select(static branch => $"{branch.Tip.Sha}\n"))); Branch remoteBranch = repo.Branches["origin/main"]; Branch localBranch = repo.Branches["main"] ?? repo.CreateBranch("main", remoteBranch.Tip); repo.Branches.Update(localBranch, b => b.TrackedBranch = remoteBranch.CanonicalName); + Commands.Checkout(repo, localBranch); repo.Reset(ResetMode.Hard, remoteBranch.Tip); repo.RemoveUntrackedFiles(); } + + logger.LogInformation("[Metadata] Update completed successfully"); } RepositoryAffinity.DecreaseFailure(info); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/ThirdPartyTool/ThirdPartyToolService.cs b/src/Snap.Hutao/Snap.Hutao/Service/ThirdPartyTool/ThirdPartyToolService.cs index b359369..c580c28 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/ThirdPartyTool/ThirdPartyToolService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/ThirdPartyTool/ThirdPartyToolService.cs @@ -19,7 +19,7 @@ namespace Snap.Hutao.Service.ThirdPartyTool; [Service(ServiceLifetime.Singleton, typeof(IThirdPartyToolService))] internal sealed partial class ThirdPartyToolService : IThirdPartyToolService { - private const string ApiBaseUrl = "https://htserver.wdg.cloudns.ch/api"; + private const string ApiBaseUrl = "https://htserver.wdg12.work/api"; private const string ToolsEndpoint = "/tools"; private const string ToolInfoFileName = "tool_info.json"; diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index 5a5d6d0..c6b24cf 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -11,7 +11,7 @@ true False - 1.18.5.0 + 1.18.6.0 False False diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/ScopedPage.cs b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/ScopedPage.cs index 0fe8470..128e4d9 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/ScopedPage.cs +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/ScopedPage.cs @@ -117,10 +117,17 @@ internal partial class ScopedPage : Page if (DataContext is IViewModel viewModel) { - // Wait to ensure critical viewmodel operation is completed - using (viewModel.CriticalSection.Enter()) + try + { + // Wait to ensure critical viewmodel operation is completed. + // The view model might already be disposed when window shutdown and page unload race. + using (viewModel.CriticalSection.Enter()) + { + viewModel.Uninitialize(); + } + } + catch (OperationCanceledException) { - viewModel.Uninitialize(); } try diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/Theme/Uri.xaml b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/Theme/Uri.xaml index 85883d9..9b6db4d 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/Theme/Uri.xaml +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Control/Theme/Uri.xaml @@ -1,7 +1,7 @@ https://hut.ao/statements/bug-report.html - https://hut.ao + https://htserver.wdg12.work https://hut.ao/features/mhy-account-switch.html https://translate.hut.ao https://hut.ao/advanced/loopback.html @@ -13,32 +13,32 @@ https://launcher-webstatic.mihoyo.com/launcher-public/2024/04/15/9ebf1bc5af2d83ca5fca21adb49cf341_2571779162329842818.png - https://htserver.wdg.cloudns.ch/static/raw/AvatarCard/UI_AvatarIcon_Costume_Card.png + https://htserver.wdg12.work/static/raw/AvatarCard/UI_AvatarIcon_Costume_Card.png - https://htserver.wdg.cloudns.ch/static/raw/Bg/UI_ItemIcon_None.png + https://htserver.wdg12.work/static/raw/Bg/UI_ItemIcon_None.png - https://htserver.wdg.cloudns.ch/static/raw/Mark/UI_MarkQuest_Events_Proce.png - https://htserver.wdg.cloudns.ch/static/raw/Mark/UI_MarkQuest_Events_Start.png - https://htserver.wdg.cloudns.ch/static/raw/Mark/UI_MarkQuest_Main_Proce.png - https://htserver.wdg.cloudns.ch/static/raw/Mark/UI_MarkQuest_Main_Start.png - https://htserver.wdg.cloudns.ch/static/raw/Mark/UI_MarkTower.png + https://htserver.wdg12.work/static/raw/Mark/UI_MarkQuest_Events_Proce.png + https://htserver.wdg12.work/static/raw/Mark/UI_MarkQuest_Events_Start.png + https://htserver.wdg12.work/static/raw/Mark/UI_MarkQuest_Main_Proce.png + https://htserver.wdg12.work/static/raw/Mark/UI_MarkQuest_Main_Start.png + https://htserver.wdg12.work/static/raw/Mark/UI_MarkTower.png - https://htserver.wdg.cloudns.ch/static/raw/ItemIcon/UI_ItemIcon_106.png - https://htserver.wdg.cloudns.ch/static/raw/ItemIcon/UI_ItemIcon_204.png - https://htserver.wdg.cloudns.ch/static/raw/ItemIcon/UI_ItemIcon_210.png - https://htserver.wdg.cloudns.ch/static/raw/ItemIcon/UI_ItemIcon_220021.png + https://htserver.wdg12.work/static/raw/ItemIcon/UI_ItemIcon_106.png + https://htserver.wdg12.work/static/raw/ItemIcon/UI_ItemIcon_204.png + https://htserver.wdg12.work/static/raw/ItemIcon/UI_ItemIcon_210.png + https://htserver.wdg12.work/static/raw/ItemIcon/UI_ItemIcon_220021.png - https://htserver.wdg.cloudns.ch/static/raw/EmotionIcon/UI_EmotionIcon52.png - https://htserver.wdg.cloudns.ch/static/raw/EmotionIcon/UI_EmotionIcon71.png - https://htserver.wdg.cloudns.ch/static/raw/EmotionIcon/UI_EmotionIcon89.png - https://htserver.wdg.cloudns.ch/static/raw/EmotionIcon/UI_EmotionIcon250.png - https://htserver.wdg.cloudns.ch/static/raw/EmotionIcon/UI_EmotionIcon271.png - https://htserver.wdg.cloudns.ch/static/raw/EmotionIcon/UI_EmotionIcon272.png - https://htserver.wdg.cloudns.ch/static/raw/EmotionIcon/UI_EmotionIcon293.png - https://htserver.wdg.cloudns.ch/static/raw/EmotionIcon/UI_EmotionIcon433.png - https://htserver.wdg.cloudns.ch/static/raw/EmotionIcon/UI_EmotionIcon445.png - https://htserver.wdg.cloudns.ch/static/raw/EmotionIcon/UI_EmotionIcon585.png + https://htserver.wdg12.work/static/raw/EmotionIcon/UI_EmotionIcon52.png + https://htserver.wdg12.work/static/raw/EmotionIcon/UI_EmotionIcon71.png + https://htserver.wdg12.work/static/raw/EmotionIcon/UI_EmotionIcon89.png + https://htserver.wdg12.work/static/raw/EmotionIcon/UI_EmotionIcon250.png + https://htserver.wdg12.work/static/raw/EmotionIcon/UI_EmotionIcon271.png + https://htserver.wdg12.work/static/raw/EmotionIcon/UI_EmotionIcon272.png + https://htserver.wdg12.work/static/raw/EmotionIcon/UI_EmotionIcon293.png + https://htserver.wdg12.work/static/raw/EmotionIcon/UI_EmotionIcon433.png + https://htserver.wdg12.work/static/raw/EmotionIcon/UI_EmotionIcon445.png + https://htserver.wdg12.work/static/raw/EmotionIcon/UI_EmotionIcon585.png diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/GuideView.xaml b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/GuideView.xaml index ba42fa2..33d8956 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/GuideView.xaml +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/GuideView.xaml @@ -268,7 +268,7 @@ - + diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/FeedbackPage.xaml b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/FeedbackPage.xaml index 8739176..7ceadf0 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/FeedbackPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/FeedbackPage.xaml @@ -93,13 +93,13 @@ diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Endpoint/Hutao/HutaoEndpointsForRelease.cs b/src/Snap.Hutao/Snap.Hutao/Web/Endpoint/Hutao/HutaoEndpointsForRelease.cs index 60fd614..d7d775b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Endpoint/Hutao/HutaoEndpointsForRelease.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Endpoint/Hutao/HutaoEndpointsForRelease.cs @@ -6,9 +6,9 @@ namespace Snap.Hutao.Web.Endpoint.Hutao; [Service(ServiceLifetime.Singleton, typeof(IHutaoEndpoints), Key = HutaoEndpointsKind.Release)] internal sealed class HutaoEndpointsForRelease : IHutaoEndpoints { - string IHomaRootAccess.Root { get => "https://htserver.wdg.cloudns.ch/api"; } + string IHomaRootAccess.Root { get => "https://htserver.wdg12.work/api"; } - string IInfrastructureRootAccess.Root { get => "https://htserver.wdg.cloudns.ch/api"; } + string IInfrastructureRootAccess.Root { get => "https://htserver.wdg12.work/api"; } - string IInfrastructureRawRootAccess.RawRoot { get => "https://htserver.wdg.cloudns.ch/api"; } + string IInfrastructureRawRootAccess.RawRoot { get => "https://htserver.wdg12.work/api"; } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Endpoint/Hutao/StaticResourcesEndpoints.cs b/src/Snap.Hutao/Snap.Hutao/Web/Endpoint/Hutao/StaticResourcesEndpoints.cs index ed22b60..bb3269b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Endpoint/Hutao/StaticResourcesEndpoints.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Endpoint/Hutao/StaticResourcesEndpoints.cs @@ -5,7 +5,7 @@ namespace Snap.Hutao.Web.Endpoint.Hutao; internal static class StaticResourcesEndpoints { - public static string Root { get => "https://htserver.wdg.cloudns.ch"; } + public static string Root { get => "https://htserver.wdg12.work"; } public static Uri UIIconNone { get; } = StaticRaw("Bg", "UI_Icon_None.png").ToUri(); diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/HutaoNativeMethods.cs b/src/Snap.Hutao/Snap.Hutao/Win32/HutaoNativeMethods.cs index 0671da1..c15d32c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/HutaoNativeMethods.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/HutaoNativeMethods.cs @@ -42,6 +42,10 @@ internal static unsafe class HutaoNativeMethods // ReSharper restore InconsistentNaming public const string DllName = "Snap.Hutao.Native.dll"; + // Console APIs + public const int STD_OUTPUT_HANDLE = -11; + public const int STD_ERROR_HANDLE = -12; + public static HutaoNative HutaoCreateInstance() { nint pv = default; @@ -54,6 +58,36 @@ internal static unsafe class HutaoNativeMethods return HutaoHResultIsWin32(hr, error); } + /// + /// Allocates a new console for the calling process. + /// + /// TRUE if the function succeeds; otherwise, FALSE. + [DllImport("kernel32.dll", ExactSpelling = true)] + public static extern BOOL AllocConsole(); + + /// + /// Detaches the calling process from its console. + /// + /// TRUE if the function succeeds; otherwise, FALSE. + [DllImport("kernel32.dll", ExactSpelling = true)] + public static extern BOOL FreeConsole(); + + /// + /// Attaches the calling process to the console of the specified process. + /// + /// The identifier of the process whose console is to be used. + /// TRUE if the function succeeds; otherwise, FALSE. + [DllImport("kernel32.dll", ExactSpelling = true)] + public static extern BOOL AttachConsole(uint dwProcessId); + + /// + /// Retrieves a handle to the specified standard device. + /// + /// The standard device. + /// A handle to the specified device. + [DllImport("kernel32.dll", ExactSpelling = true)] + public static extern nint GetStdHandle(int nStdHandle); + [DllImport(DllName, CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] private static extern HRESULT HutaoCreateInstance(HutaoNative.Vftbl** ppv);