From 36f5c361e5ac3719c17065f8a5a8232679c7f048 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Fri, 20 Sep 2024 11:55:47 +0800 Subject: [PATCH 01/99] Update FUNDING.yml --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 24f634194..82dead90c 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -10,4 +10,4 @@ liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -custom: https://afdian.net/a/DismissedLight +custom: https://afdian.com/a/DismissedLight From 8a2bcc74a9b3cd9add268e445395433e63e53773 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Sat, 19 Oct 2024 18:15:59 +0800 Subject: [PATCH 02/99] Update SH.resx --- src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx index aeb147c1c..88dd962e8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx @@ -1923,7 +1923,7 @@ 当前选中的游戏目录 {0} 已损坏,请手动删除文件夹后重新安装游戏 - 使用米游社用户登录失败,请重新登录 + 使用 米游社 / HoYoLAB 用户登录失败,请重新登录 切换服务器失败 @@ -2745,10 +2745,10 @@ 启用 - 使用当前选中的米游社用户登录,仅支持官服 + 使用当前选中的 米游社 / HoYoLAB 用户登录,不支持渠道服 - 使用米游社用户登录 + 使用 米游社 / HoYoLAB 用户登录 充分利用支持高动态范围的显示器获得更亮、更生动、更精细的画面 From b998a885f33dd6bf85013891eaa5b7156924020e Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Sun, 20 Oct 2024 12:26:30 +0800 Subject: [PATCH 03/99] add apk icon --- .../Snap.Hutao/Core/RuntimeOptions.cs | 23 +++++++++--------- .../hoyolab_ic_launcher_foreground.webp | Bin 0 -> 714 bytes .../ThirdParty/miyoushe_ic_launcher.png | Bin 0 -> 2352 bytes src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj | 4 +++ .../Specialized/ThirdPartyIconConverter.cs | 9 ++++++- .../Snap.Hutao/UI/Xaml/View/UserView.xaml | 6 +++-- .../ViewModel/User/UserViewModel.cs | 3 ++- 7 files changed, 29 insertions(+), 16 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Resource/ThirdParty/hoyolab_ic_launcher_foreground.webp create mode 100644 src/Snap.Hutao/Snap.Hutao/Resource/ThirdParty/miyoushe_ic_launcher.png diff --git a/src/Snap.Hutao/Snap.Hutao/Core/RuntimeOptions.cs b/src/Snap.Hutao/Snap.Hutao/Core/RuntimeOptions.cs index 2e01bd2ce..99245c22c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/RuntimeOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/RuntimeOptions.cs @@ -3,40 +3,39 @@ namespace Snap.Hutao.Core; -[Obsolete("This class only exist for binding purpose")] [Injection(InjectAs.Singleton)] internal sealed class RuntimeOptions { - [Obsolete] + [Obsolete("This property only exist for binding purpose")] public Version Version { get => HutaoRuntime.Version; } - [Obsolete] + [Obsolete("This property only exist for binding purpose")] public string UserAgent { get => HutaoRuntime.UserAgent; } - [Obsolete] + [Obsolete("This property only exist for binding purpose")] public string DataFolder { get => HutaoRuntime.DataFolder; } - [Obsolete] + [Obsolete("This property only exist for binding purpose")] public string LocalCache { get => HutaoRuntime.LocalCache; } - [Obsolete] + [Obsolete("This property only exist for binding purpose")] public string FamilyName { get => HutaoRuntime.FamilyName; } - [Obsolete] + [Obsolete("This property only exist for binding purpose")] public string DeviceId { get => HutaoRuntime.DeviceId; } - [Obsolete] + [Obsolete("This property only exist for binding purpose")] public string WebView2Version { get => HutaoRuntime.WebView2Version.Version; } - [Obsolete] + [Obsolete("This property only exist for binding purpose")] public bool IsWebView2Supported { get => HutaoRuntime.WebView2Version.Supported; } - [Obsolete] + [Obsolete("This property only exist for binding purpose")] public bool IsElevated { get => HutaoRuntime.IsProcessElevated; } - [Obsolete] + [Obsolete("This property only exist for binding purpose")] public bool IsToastAvailable { get => HutaoRuntime.IsAppNotificationEnabled; } - [Obsolete] + [Obsolete("This property only exist for binding purpose")] public DateTimeOffset AppLaunchTime { get => HutaoRuntime.LaunchTime; } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/ThirdParty/hoyolab_ic_launcher_foreground.webp b/src/Snap.Hutao/Snap.Hutao/Resource/ThirdParty/hoyolab_ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..2473f15fced7973be752eab7a1b1563a2ef9f8d1 GIT binary patch literal 714 zcmWIYbaOkz#J~{l>J$(bU=hK^z`!5?#Qb0c6!Gx`%IfnUU=|Q(wVsq4di70lLA(7S zb#bS{cJ=Gu<1%;j=0=B}t88-R+xRt}-B~&%zOeSY-1d#Rt55y<|9GBI5W~^{< zGbit~bH1=Gw}yegevWNJdx#xV+5>)(|FQ937w-75_p;58vOUr)dlZzrD}oe?#oA5; zte>9xQhmzxnpXur%6ZRNeG*v=B6j@g?^!p)=OGJ+LgNGmxetnN4apkft35b4I3ya= zK1|x(>E-vd!-0FcjIaeGi;4gf2a6K}Baf2OVTG19o}N#=Tte@b%rQM5^)~)v{$i6T z{+9hGzx01G@yPvKIOUP|*Oh0)9qq5J`V@L>?^&Ib5>m@|#%U=mNL(Ya*rACj>Cww0 zPMbQsEBt@wey+dpPbGE@b-Bvl?{X;BqZSN0VHP1f5Gf}k(l8UeXZ#tCj zGc`advAg%_&Py?D-U=Tn8v zff?6UPHMAh3po)eI(=R2=~G2LhP?Il?_Ye%dbmJSUCKsYeph|Poo%{>uXNR>CqI7v z{pZs48yDt&@CnK;x@rFZUwozo&$LTcMQ_X--@Lmk{8#qtR;Iw}XE)U*r1|V~ye~Ze zv`5hKYYRD3X1u;z@rAubVY<2hM<0bXdtUMja5|-X|Gv?Ai={`jsr%u*b>|u{9u0Q& zeYce5by-zeUfR^vYp?uHn0zyOt=QX+r~h_!TxAakcJ%ZErZEdAPhaM@Kn5tuc>qa9 n1|}E{l4H>T%kcn7Ci@RyHdqgfGnmaAkdzwED8RtV2<8F+b!|7*5evTBmXimtb9%W4JbZWH-l3z_w{^g+OVm9CCfx{gSS2vSD}Iq#cH% z3>JO>MQ8=2!%;jq1cgBm6)bYfF@hY0QWz*uz)|E-U;xK&lO|LKq-JKbo89Mq-tT$e z=lwQwvWCBvnDA`FF&N_Z zO1Y!8(avGKAbX8KlwHsm^!gFnU>Gzc=m$bR)G!zHNIpA$GkTuLTFXXhL4x=RJ58~?1yAFROLcNfC%36 zad27@%G{)(1;J@W(5FSiQSJXbIFd&cqBwt{QV=SWD3GuKdJ&(BG|^E({ybTe)jatb z)X~SGLg)!lwRndt6zWu&j)(z7S&&3Nism_yft<)e!fayz!MRu$0T^f@TvkD(+%7Y4 ziEM-|)2C{{CqSJI@f#(?1gtjE?BdLXOAtANV_BAPxmgP#*ccH28d%K06p0_9NXWyW zp!uqF9ue_a91atgPIG34W@$PtIoXtIO<~OGDQ1h6C%^>-)t@_;wTqwVoa2YB{W%Jj-`262q`Ys`&^!RSc=C2{(xh8}4!c zLeHA*#YlVT7TVzT%jl~G{fNGtpbynaL9d>w`T6S&hE{De9m%k^h7UbOL#l55A!Zb8oK1CEe0>Mc9J&;5S+XJL$k9^Y z!UN^&7CPcDwyUctjTt`c+Vop}lv2Jr3qLknsI4}3zq3Do`}JM13s>Hqd2pVm4b|iD zD`WjhCy!;-4!pkz%)uWGg6U8MHD}CEG zwclK`o7`0W`3d{|>TkM^JiDs0`qIMmtF?#6SKOBl+?%;|TJ4`F2e&ugP5tanf}>;q zn5s^fM?RRcr@pFp!@7pAOKwis7av$#G;sB!_{2-x@)4l2A?bF`UpI-Eiq*5r6N9&% zU)<N literal 0 HcmV?d00001 diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index 4ed9c48d8..1194b211d 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -100,6 +100,8 @@ + + @@ -292,6 +294,8 @@ + + diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Data/Converter/Specialized/ThirdPartyIconConverter.cs b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Data/Converter/Specialized/ThirdPartyIconConverter.cs index 460fb9a8a..2acd3199e 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Data/Converter/Specialized/ThirdPartyIconConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/Data/Converter/Specialized/ThirdPartyIconConverter.cs @@ -7,9 +7,16 @@ namespace Snap.Hutao.UI.Xaml.Data.Converter.Specialized; internal sealed partial class ThirdPartyIconConverter : ValueConverter { + public const string TwitterName = "X (Twitter)"; + public override BitmapIcon Convert(string from) { - Uri uri = $"ms-appx:///Resource/ThirdParty/{from}.png".ToUri(); + Uri uri = from switch + { + TwitterName => $"ms-appx:///Resource/ThirdParty/Twitter.png".ToUri(), + _ => $"ms-appx:///Resource/ThirdParty/{from}.png".ToUri(), + }; + return new() { ShowAsMonochrome = false, diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/UserView.xaml b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/UserView.xaml index 207230f0f..c13e229c8 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/UserView.xaml +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/UserView.xaml @@ -302,11 +302,12 @@ Background="{ThemeResource CardBackgroundFillColorDefaultBrush}" BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}" BorderThickness="0,0,1,0"> + @@ -329,11 +330,12 @@ + diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs index bce6ae1f4..a9f3cefc9 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/User/UserViewModel.cs @@ -17,6 +17,7 @@ using Snap.Hutao.Service.SignIn; using Snap.Hutao.Service.User; using Snap.Hutao.UI.Xaml.Behavior.Action; +using Snap.Hutao.UI.Xaml.Data.Converter.Specialized; using Snap.Hutao.UI.Xaml.View.Dialog; using Snap.Hutao.UI.Xaml.View.Window.WebView2; using Snap.Hutao.Web.Hoyolab; @@ -48,7 +49,7 @@ internal sealed partial class UserViewModel : ObservableObject public AdvancedDbCollectionView? Users { get => users; set => SetProperty(ref users, value); } - public List> OverseaThirdPartyKinds { get; } = CollectionsNameValue.FromEnum(); + public List> OverseaThirdPartyKinds { get; } = CollectionsNameValue.FromEnum(static kind => kind is OverseaThirdPartyKind.Twitter ? ThirdPartyIconConverter.TwitterName : kind.ToString()); internal void HandleUserOptionResult(UserOptionResult optionResult, string uid) { From f9285e77262999a02e6b931a817aed55124bc09a Mon Sep 17 00:00:00 2001 From: Masterain Date: Sun, 20 Oct 2024 04:08:01 -0700 Subject: [PATCH 04/99] New Crowdin updates (#2039) --- .../Resource/Localization/SH.en.resx | 136 +++++++-- .../Resource/Localization/SH.fr.resx | 78 +++++ .../Resource/Localization/SH.id.resx | 78 +++++ .../Resource/Localization/SH.ja.resx | 287 +++++++++++------- .../Resource/Localization/SH.ko.resx | 78 +++++ .../Resource/Localization/SH.pt.resx | 78 +++++ .../Resource/Localization/SH.ru.resx | 78 +++++ .../Resource/Localization/SH.vi.resx | 78 +++++ .../Resource/Localization/SH.zh-Hant.resx | 78 +++++ 9 files changed, 836 insertions(+), 133 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx index 7ec895678..dcaabadf7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx @@ -743,7 +743,7 @@ Need EXACT same string in game - Heal bonus + Incoming Healing Bonus HP @@ -782,7 +782,7 @@ Need EXACT same string in game - Cooldown reduction + CD Reduction Enhancement Progression Calculator: N/A @@ -1014,13 +1014,13 @@ Game path not found in Unity log file - Inventory data parse failed + Manifest parse failed - Not enough disk space, {0}is required, {1} left + Insufficient disk space, need {0}, remaining {1} - Installing Games + Installing Game Pre-downloading resources @@ -1086,7 +1086,7 @@ Error reading process modules' memory: could not read valid value in given address - Failed to unlock frame rate:x{0:X8} + Failed to unlock frame rate:0x{0:X8} Wish history data backup service will expire at \n{0:yyyy.MM.dd HH:mm:ss} @@ -1146,25 +1146,25 @@ Can't get user information with entered Cookie - Append Attribute Recommendation + Additional Property Recommendation - Rational Champion Attribute Recommendations + Circlet of Logos Property Recommendation - Empty Grail Property Recommendation + Goblet of Eonothem Property Recommendation - Sand Properties Recommendations + Sands of Eon Property Recommendation Copy Image - Fetching inventory data + Fetching manifest - Please complete authentication + Please complete the verification Achievements @@ -1308,16 +1308,16 @@ Add or update to current Enhancement Progression Plan - Always create new adopted target items + Always create new entries Save Method - Overwrite existing adopted items + Overwrite existing entries - Keep existing target items + Keep existing entries Daily Commission Availability Notification @@ -1376,6 +1376,30 @@ Input wish history URL manually + + Game Server + + + Currently selected directory is HDD, SSD is recommended + + + Set the game installation directory + + + Install Game + + + Chinese + + + English + + + Japanese + + + Korean + Input request Url with composit template @@ -1505,6 +1529,15 @@ Update + + Please enter an account + + + Enter your password + + + Login to your account + Take me there @@ -1676,6 +1709,9 @@ Character showcase is disabled. Please activate it in the game. + + {0} characters in total + Failed to copy role details @@ -1701,7 +1737,7 @@ No plan has been created and selected - There is already a foster project for this item + There is already a cultivation entry for this item Successfully added to current plan @@ -1821,7 +1857,7 @@ Local version: {0} - Pre-download for {0} is on + {0} Version pre-download is now available Latest version: {0} @@ -1833,19 +1869,19 @@ Canceling - Installation completed + Installation complete - Predownload completed + Pre-download complete - Fix Completed + Fix complete - Update completed + Update complete - The game is complete, no need to fix + The game integrity is intact, no need to fix I've Read and Agreed Conditions Above @@ -1880,9 +1916,15 @@ Import failed + + The currently selected user and game server do not match. Please re-select + The currently selected game directory {0} is corrupted. Please manually delete the folder and reinstall the game + + Login failed with MiYouShe/HoYooLAB user. Please login again + Convert server failed @@ -1953,7 +1995,7 @@ Failed to save game path - The current data directory `{0}' contains one or more reanalytics points (Reparse points) that may cause some data folders to work properly. Please go to set the change path + The current data directory '{0}' contains one or more reparse points, which may cause some of the functions that depend on the data folder to not work properly, please go to Settings to change the path. Export failed @@ -2025,7 +2067,7 @@ Export - Charged achievements only + Daily quest achievements only Import from Clipboard @@ -2139,7 +2181,7 @@ Material Checklist - Unbundled priority + Uncollected First Material Statistics @@ -2232,7 +2274,7 @@ Do Not Disturb - Long Effect Points + Long-Term Encounter Points Verify Current User and Role @@ -2601,7 +2643,7 @@ Game Options - Install Games + Install Game Pre-download @@ -2673,7 +2715,7 @@ You need to convert to a server that matches the launcher before updating the version - Adjust Camera Vision, Default 45 + Adjust FOV, Default 45 Adjust FOV @@ -2702,6 +2744,12 @@ Enabled + + Use the currently selected MiYouShe/HoYoLAB user to log in, Bilibili is not supported. + + + Sign in with MiYouShe/HoYoLAB user + Take advantage of monitors that support HDR for brighter, more vivid, and more detailed pictures @@ -3011,6 +3059,12 @@ When setting the game path, please select the game program (Yuanshen.exe or GenshinImpact.exe) instead of the game launcher (launcher.exe) + + Select the mode in which to save the image after clicking the share button + + + Share Save Mode + Shell Experience @@ -3071,6 +3125,9 @@ Webview2 Runtime + + WebView + Second Half @@ -3281,6 +3338,12 @@ Official Tools + + Login + + + Trilateral Login + Web Login @@ -3351,7 +3414,7 @@ Weapon WIKI - Take a screenshot of this window, find a suitable feedback path in the feedback center and send it to the UNDG. + Please take a screenshot of this window and find the appropriate feedback channel in the Feedback Center and send it to the development team. An unrecoverable fatal error has occurred @@ -3383,6 +3446,21 @@ Copied to clipboard + + Save shared image + + + Image saving failed + + + Image saved successfully + + + Copy to clipboard + + + Save as file + All Archon Quest Completed diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.fr.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.fr.resx index 55e490d6d..fd8f60316 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.fr.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.fr.resx @@ -1376,6 +1376,30 @@ 手动输入祈愿记录 Url + + 游戏服务器 + + + 当前选择目录为HDD,建议使用SSD + + + 设置游戏安装目录 + + + 安装游戏 + + + 汉语 + + + 英语 + + + 日语 + + + 韩语 + 请输入请求接口的 Url 复合模板 @@ -1505,6 +1529,15 @@ 更新 + + 请输入账号 + + + 请输入密码 + + + 账号密码登录 + 立即前往 @@ -1676,6 +1709,9 @@ 角色展柜尚未开启,请前往游戏操作后重试 + + 共 {0} 位角色 + 复制角色详情失败 @@ -1880,9 +1916,15 @@ 导入失败 + + 当前选中用户和游戏服务器不匹配,请重新选择 + 当前选中的游戏目录 {0} 已损坏,请手动删除文件夹后重新安装游戏 + + 使用 米游社 / HoYoLAB 用户登录失败,请重新登录 + 切换服务器失败 @@ -2702,6 +2744,12 @@ 启用 + + 使用当前选中的 米游社 / HoYoLAB 用户登录,不支持渠道服 + + + 使用 米游社 / HoYoLAB 用户登录 + 充分利用支持高动态范围的显示器获得更亮、更生动、更精细的画面 @@ -3011,6 +3059,12 @@ 设置游戏路径时,请选择游戏本体(YuanShen.exe 或 GenshinImpact.exe)而不是启动器(launcher.exe) + + 选择点击分享按钮后保存图片的模式 + + + 分享保存模式 + Shell 体验 @@ -3071,6 +3125,9 @@ Webview2 运行时 + + WebView + 下半 @@ -3281,6 +3338,12 @@ 旅行工具 + + 账密登录 + + + 三方登录 + 网页登录 @@ -3383,6 +3446,21 @@ 已复制到剪贴板 + + 保存分享图片 + + + 图片保存失败 + + + 图片保存成功 + + + 复制到剪贴板 + + + 保存为文件 + 所有魔神任务已完成 diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.id.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.id.resx index 31073e691..41aad211e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.id.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.id.resx @@ -1376,6 +1376,30 @@ Masukan histori wish URL secara manual + + 游戏服务器 + + + 当前选择目录为HDD,建议使用SSD + + + 设置游戏安装目录 + + + 安装游戏 + + + 汉语 + + + 英语 + + + 日语 + + + 韩语 + Masukkan URL permintaan dengan template Composit @@ -1505,6 +1529,15 @@ 更新 + + 请输入账号 + + + Masukkan kata sandi + + + 账号密码登录 + Tuju saya kesana @@ -1676,6 +1709,9 @@ Pameran karakter dinonaktifkan. Silakan aktifkan di dalam permainan. + + 共 {0} 位角色 + 复制角色详情失败 @@ -1880,9 +1916,15 @@ Gagal Impor + + 当前选中用户和游戏服务器不匹配,请重新选择 + 当前选中的游戏目录 {0} 已损坏,请手动删除文件夹后重新安装游戏 + + 使用 米游社 / HoYoLAB 用户登录失败,请重新登录 + Konversi server gagal @@ -2702,6 +2744,12 @@ Aktifkan + + 使用当前选中的 米游社 / HoYoLAB 用户登录,不支持渠道服 + + + 使用 米游社 / HoYoLAB 用户登录 + Manfaatkan tampilan yang mendukung rentang dinamis tinggi untuk gambar yang lebih terang, lebih jelas, dan lebih detail @@ -3011,6 +3059,12 @@ Saat mengatur jalur permainan, pilih program permainan (Yuanshen.exe atau GenshinImpact.exe) bukan peluncur permainan (launcher.exe) + + 选择点击分享按钮后保存图片的模式 + + + 分享保存模式 + Pengalaman Shell @@ -3071,6 +3125,9 @@ Webview2 Runtime + + WebView + 下半 @@ -3281,6 +3338,12 @@ Official Tools + + 账密登录 + + + 三方登录 + Web Login @@ -3383,6 +3446,21 @@ Disalin ke clipboard + + 保存分享图片 + + + 图片保存失败 + + + 图片保存成功 + + + 复制到剪贴板 + + + 保存为文件 + 所有魔神任务已完成 diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ja.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ja.resx index f5a514fa8..51009089b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ja.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ja.resx @@ -190,7 +190,7 @@ 胡桃がリアルタイムノートを更新するために使用するタスクです。編集や削除をしないでください! - セマフォが解放され、操作がキャンセルされました + セマフォが既に解放され、操作が取り消されました WebView2 ランタイムが検出されませんでした @@ -641,22 +641,22 @@ 無効なUIDです。 - 深境螺旋のデータをアップロードに失敗しました。現行の期間のデータではありません。 + 深淵の記録をアップロードに失敗しました。現行の期間のデータではありません。 深境螺旋のデータをアップロードに失敗しました。現在の UID の記録はまだ処理中であるため、操作を繰り返さないでください。 - 深境螺旋のデータをアップロードしました。胡桃クラウドの利用期間延長特典を受け取りました。 + 深淵の記録をアップロードしました。胡桃サービスの祈願保存期限を受け取りました。 - 深境螺旋のデータをアップロードしましたが、胡桃クラウドへログインしていないため、利用期間特典を受け取ることは出来ません。 + 深淵の記録をアップロードしましたが、胡桃通行証へログインしていないため、祈願保存期限を受け取りませんでした。 - 深境螺旋のデータをアップロードしましたが、ユーザーが見つからなかったため、利用期間特典を受け取ることができませんでした。 + 深淵の記録をアップロードしましたが、ユーザーが見つからなかったため、祈願保存期限を受け取りませんでした。 - 深境螺旋のデータをアップロードしました。今期は二回以上アップロードしているため、利用期間特典を受け取ることは出来ません。 + 深淵の記録をアップロードしましたが、今期の初回アップロードではないため、祈願保存期限を受け取りませんでした。 {0} つのアチーブメントを追加 | {1} つのアチーブメントを更新 |{2} つのアチーブメントを削除 @@ -1183,7 +1183,7 @@ アチーブメント集計 - すべてのアイテムのコピーが利用可能になるまで + すべての秘境が挑戦できます 誕生日を迎えるキャラはいません @@ -1234,7 +1234,7 @@ UP 獲得平均数 - ピックアップ + UP 予測 @@ -1377,6 +1377,30 @@ 祈願履歴 URL を手動で入力する + + ゲームサーバー + + + 現在選択されているディレクトリは HDD ですが、SSD を推奨します + + + ゲームのインストール場所を設定 + + + ゲームをインストール + + + 中国語 + + + 英語 + + + 日本語 + + + 韓国語 + リクエスト URL の複合テンプレートを入力してください @@ -1506,6 +1530,15 @@ アップデート + + アカウントを入力してください + + + パスワードを入力してください + + + アカウントやパスワードでログインする + すぐに移動 @@ -1612,7 +1645,7 @@ 深境螺旋集計 - すべての通知をクリア + すべて消去 折りたたむ @@ -1677,6 +1710,9 @@ キャラクターラインナップが未配置か非表示です。ゲーム内のプロフィール編集で設定してください + + キャラ総計 {0} 人 + キャラ詳細をコピーに失敗しました @@ -1881,9 +1917,15 @@ インポート失敗 + + 現在選択されているユーザーとサーバーが一致しません。もう一度選択してください。 + 現在選択されているゲームパス {0} が壊れています。フォルダーを手動で削除しゲームを再インストールしてください + + 米游社 / HoYoLAB ユーザーでログインに失敗しました。もう一度ログインしてください + サーバーの切り替えができませんでした @@ -1954,16 +1996,16 @@ ゲームパスの保存に失敗しました - データディレクトリ'{0}'には1つまたは複数のアナリティクスが存在します。一部の依存関係データフォルダが正常に機能しませんので経路を変更してください。 + 現在のデータディレクトリ '{0}' には1つ以上の再解析ポイント (Reparse points) が含まれている為、データフォルダに依存する一部の機能が正常に動作しなくなるかもしれない故、設定へパスを変更してください! エクスポート失敗 - エクスポートに成功しました + エクスポート成功 - UID の重複を避けるために、インポートされたUIGFファイルには UID の重複送信 + インポートされた UIGF ファイルには、UID が重複した祈願履歴が含まれています インポート失敗 @@ -1972,7 +2014,7 @@ インポートされた UIGFファイルには、祈願データが含まれていません。 - データをインポートするには UID を指定する必要があります。 + データをインポートするには少なくとも UID を1つ選択してください インポート成功 @@ -1984,10 +2026,10 @@ ユーザー [{0}] の Cookie をコピーしました - このCookieが不完全のため、操作できません + この Cookie が不完全で、操作できません - このCookieが無効のため、操作できません + この Cookie が無効ので、操作できません ユーザー [{0}] を削除しました @@ -1996,10 +2038,10 @@ ユーザー [{0}] の Cookie が更新されました。 - ビューリソースが解放され、操作がキャンセルされました + ビューリソースが既に解放され、操作が取り消されました - 胡桃を利用できるようになりました + これで胡桃が使えるようになりました! ダウンロード完了 @@ -2008,7 +2050,7 @@ 完了 - レスポンスストリームに有効なコンテンツタイプが含まれていない + レスポンスストリームが有効なコンテンツタイプではありません 待機中 @@ -2020,7 +2062,7 @@ 新規アーカイブ - 続けるにはアーカイブを作成してください + まず「新規アーカイブ」を作成して続けよう! エクスポート @@ -2044,7 +2086,7 @@ 実績名 · 説明 ·バージョン· 番号で検索 - 未達成順にソート + 未達成に優先 イベント @@ -2077,7 +2119,7 @@ テキストをクリップボードにコピー - キャラクターの元素タイプ + ステータス情報 初期付与のサブOP @@ -2122,13 +2164,13 @@ 新規 - 続けるには、まず「育成計画」を立てよう + まず「新規育成計画」を作成して続けよう! 育成計画の項目は後から他のページでも追加できます。 - マイ キャラクターと武器を育成計画に追加します + マイキャラクターと武器を育成計画に追加します 育成素材 @@ -2140,7 +2182,7 @@ 素材リスト - 未集束優先 + 収集未完成に優先 素材情報 @@ -2158,13 +2200,13 @@ 現在の育成計画を削除 - キャラクターの育成計画を追加する + 任意のキャラを育成計画に追加する - 武器の育成計画を追加する + 任意の武器を育成計画に追加する - リアルタイムのメモを追加 + リアルタイムノートを追加 リアルタイムノートを追加して定期的に更新できます @@ -2173,7 +2215,7 @@ 追加 - 冒険ポイントのステータス + 修練ポイント情報 リアルタイムノートが更新後に指定の Webhook へデータを送信します。 @@ -2200,7 +2242,7 @@ 更新間隔 - 通知をクリックするまで画面上に表示したままにします。 + 通知が操作センターに自動的収まる事を防ぎます リマインド通知 @@ -2209,7 +2251,7 @@ カードを削除 - 今週の消費半減は消化済 + 今週の残り消費半減回数 自動更新 @@ -2218,7 +2260,7 @@ 指定間隔でリアルタイムノートを更新します - これらの設定は管理者モードでない時のみ変更できます。 + これらのオプションは非管理者モードでのみ変更できます。 更新 @@ -2230,13 +2272,13 @@ プレイ中に通知をオフ - おやすみモード + 集中モード - 長効率練点 + 長期修練ポイント - 現在のユーザーとUIDを確認する + 現在のユーザーとキャラを認証 質問や提案を検索 @@ -2257,16 +2299,16 @@ 解除済み - ループバック制限解除の設定 + Loopback 制限を解除する - 引き続き連絡をしてください + 引き続き連絡を取り合いましょう 機能ガイド - Githubでは報告された問題を常に優先しています + GitHub で報告された問題には常に優先順位をつけています 開発ロードマップ @@ -2275,13 +2317,13 @@ 検索結果はありません - 胡桃のサービス状態 + 胡桃サービス可用性の監視モニター 胡桃サービス - すべて更新 + 完全更新 エクスポート @@ -2302,7 +2344,7 @@ このUIDのクラウドバックアップを削除する - デベロッパーアカウントは利用期限がありません + 開発者アカウントは無期限にサービスを利用できます 胡桃クラウドのサービス期限が切れました。 @@ -2311,7 +2353,7 @@ このUidのクラウドバックアップをダウンロードする - 各シーズンの深境螺旋の記録を初めてアップロードすると3日間のフリーライセンスが付与されます。 + 毎期の深境螺旋記録を初回アップロードすると、胡桃クラウドの使用が3日間無料になります。 螺旋の記録をアップロード @@ -2341,25 +2383,26 @@ 情報更新 - フェッチ + 取得 - Urlを入力する + 手動で URL を入力 - 旅人が用意したUrlで祈願履歴を更新 + 旅人さんが提供した URLで祈願履歴を更新します - SToken 更新 + SToken で更新 - 現在のユーザーのCookieで祈願履歴を表示する + 現在のユーザーの Cookie で祈願履歴を更新します + - ゲーム内ブラウザキャッシュで更新 + ウェブキャッシュで更新 - ゲーム内ブラウザのキャッシュで祈願履歴を更新 + ゲーム内ブラウザーのキャッシュで祈願履歴を更新します 現在のアーカイブを削除する @@ -2374,7 +2417,7 @@ 一覧 - 統計 + グローバル祈願統計 武器 @@ -2383,7 +2426,7 @@ 胡桃はあなたのためにゲームを {0} 回起動しました - 胡桃を {0} 回起動しました + あなたは胡桃を {0} 回起動しました 旅人、テイワットへようこそ! @@ -2479,7 +2522,7 @@ アカウント作成 - パスワードを忘れました + パスワードをリセット 削除されたアカウントのデータは永久的に削除され、復元することは出来ません。 @@ -2497,7 +2540,7 @@ ゲームスタート - 上級者向け設定 + 高度な機能 指定した解像度に素早く切り替えます @@ -2515,10 +2558,10 @@ ボーダーレス - タッチパネル レイアウトを有効化します。キーボードとマウスは使えなくなります。 + 内蔵のタッチレイアウトを有効し、キーボードとマウスは使えなくなります。 - ゲーム内ブラウザには対応していません。ウィンドウの切り替え操作などによりゲームが強制終了する可能性があります。 + ゲーム内の埋め込みブラウザとの互換性がなく、ウィンドウ切り替えなどの操作でゲームが強制終了することがあります。 排他的フルスクリーン @@ -2533,22 +2576,22 @@ 外観 - ゲームのウィンドウの高さを上書き + ゲームのウィンドウの高さを上書きします。 高さ - ゲームのウィンドウの幅を上書き + ゲームのウィンドウの幅を上書きします。 - ゲーム開始時の動作を変更します。 + ゲーム開始時のデフォルト動作を変更します。 - コマンドラインパラメーター + 起動のパラメーター ゲーム起動後 Better GI を開始してみ、自動化任務しようとします @@ -2563,19 +2606,19 @@ これらの設定はゲームが正常に起動した時のみ保存されます。 - 光の描画から霧を削除 + 照明レンダリングの霧を除去する - チームを削除 + 霧を取り除く - 予約済み + 保留 削除 - ゲームをプレイしている時に、Discord Activityのステータスを変更します。 + ゲーム中に Discord Activity のステータスを設定します。 Discord Activity @@ -2587,7 +2630,7 @@ インタープロセス - 指定したディスプレイで実行 + 指定したディスプレイで実行します。 モニター @@ -2611,13 +2654,13 @@ 事前ダウンロードは完成しました - ゲームを更新します + ゲームを更新 ゲームを修復 - ゲームの開始後にStarward ランチャーを起動し、プレイ時間の統計を確認してみてください。 + ゲームの開始後に Starward を起動してみ、プレイ時間の統計を行おうとします。 プレイ時間 @@ -2629,28 +2672,28 @@ レジストリ - 増分パック + 差分パッケージ リソースダウンロード - クライアント + 完全パッケージ 事前ダウンロード - ゲームのフォルダを選択 + ゲームのパスを選択 - このアカウントはリアルタイムノート通知 UID として連携されていません。 + このアカウントはリアルタイムノート通知 UID に連携されていません。 - 現在のユーザのUIDを連携する + 現在のユーザー UID を連携する - ゲーム内でアカウントを切り替えたり、インターネット環境を変更した場合は再検出が必要です。 + ゲーム内でアカウントを切り替える場合、ネットワーク環境が変わった後に手動で再検出する必要があります。 検出 @@ -2680,19 +2723,19 @@ 視界を調整 - FX同期を無効にするには、より高パフォーマンスなグラフィックカードをサポートするために、ゲーム内のFPSの設定と -1を設定すると、すべてのフレームレートは無制限に設定されます。 + より高い FPS をサポートするために高性能な GPU を必要とします。ゲーム内の「垂直同期」を無効にし、無制限のフレームレートのために値を -1 に設定してください。 フレームレート上限解除 - ロック解除フレームレート変更方法の変更 + フレームレートの解除方法を変更 - ロック解除モード + 解除方法 - エラー コード31-4302。このオプションを有効にした場合、グラデーションと霧の調整が無効になり、ゲームの起動前に切り替わるようにできます。 + エラーコード 31-4302 が発生した場合はこのオプションを有効にします。有効にすると、視野と霧の調整が無効になり、ゲームを開始する前にこのスイッチを切り替えた場合にのみ有効になります 互換モード @@ -2703,14 +2746,20 @@ 有効 + + 今は選ばれている 米游社 / HoYoLAB ユーザーを使用してログインします。世界樹サーバーはサポートされていません + + + 米游社 / HoYoLAB ユーザーでログイン + - HDRをサポートするディスプレイを活用して、より明るく鮮やかなグラフィックを実現します。 + HDR に対応したモニターを活用すれば、より明るく、より鮮やかで、より精細な画像が得られます Windows HDR - HoYoLab UIDを入力してください + HoYoLAB UIDを入力してください あなたが[MiHoYo 通行証アカウント]にログインするために埋め込みウェブビューを使用しており、[サインしました]ボタンをクリックするとこのクライアントが貴方の Cookie データを取得します。このウェブビューで開始されたすべてのネットワーク通信は、あなたのコンピュータと MiHoYo 公式サーバーの間でのみ行われます。 @@ -2719,7 +2768,7 @@ ログインしました - MiHoYo BBS通行証でログイン + 下のウィンドウから MiHoYo 通行証でログインします スクリーンショットフォルダを開く @@ -2767,7 +2816,7 @@ イメージキャッシュはここに格納されます - キャッシュフォルダ + キャッシュ フォルダー 胡桃通行証 @@ -2779,7 +2828,7 @@ 新規作成 - 管理者として実行できるショートカットを作成します + 管理者権限でデスクトップショートカットを作成します ショートカットを作成する @@ -2788,31 +2837,31 @@ 実行 - 潜在的に危険な機能 + 危険な機能 デベロッパーが明確に指示しない限り、以下の機能を有効にすべきではありません。 - ユーザーデータ/メタデータはここに格納 + ユーザーデータ / メタデータ ここに保存 - データフォルダ + データ フォルダー 削除 - 祈願履歴を更新した際、検証キーの有効期限が切れた等のエラーが表示された場合は、この操作を行うと良いでしょう。 + 祈願履歴の更新時に、認証キーの有効期限切れエラーが頻繁に発生する場合は、この操作をお試しください。 ゲーム内ブラウザキャッシュを削除する - ユーザーテーブルに保存されている記録を削除し、特定のアカウントの競合などの問題を修正します。 + ユーザーテーブルに保存されている記録を全部削除し、特定のアカウントの競合などの問題を修正します。 - 保存されたすべてのユーザーを削除 + すべてのユーザーを削除する デバイス ID @@ -2821,7 +2870,7 @@ IP: {0} サーバー: {1} - デバイスのIP + デバイス IP ダウンロード @@ -2836,10 +2885,10 @@ 管理者モードで再起動 - 祈願履歴のないイベント限定祈願を祈願履歴に表示するかを変更します。 + 祈願履歴のない過去の祈願を表示または隠します - 祈願を行っていない過去のイベント祈願を表示する + 無記録の過去の祈願 非表示 @@ -2848,7 +2897,7 @@ 表示 - 利用規則に違反する可能性のある機能『ゲームランチャー - 上級者向け設定』を有効にしました。ユーザーご自身がそれによって生じる結果について、一切の責任を負うものとなります。 + あなたは原神の利用規約に違反する可能性のある「ゲームランチャー - 高度な機能」をアンロックしています。いかなる不利な結果に対してもご自身で責任を負うものとなります。 フィードバック @@ -2920,7 +2969,7 @@ 胡桃アカウント - 胡桃クラウドのサービスをベースにした様々な機能が制限なく利用できます + 胡桃クラウドのサービスに基づくあらゆる機能が制限なく利用できます。 認定済みの共同開発者 @@ -2932,16 +2981,16 @@ ログアウト - テスト段階のあらゆる機能を使用できます。 + あらゆるテスト機能を制限なく使用できます。 - 胡桃の運用と開発または保守 + 胡桃の開発 / 保守 - 胡桃クラウドの引き替えコードを一部のユーザーに配布する事があります。 + 胡桃クラウドの引き換えコードを一部のユーザーに配布することがあります。 - 引き替えコードの使用 + 引き換えコードの使用 登録 @@ -2953,10 +3002,10 @@ アカウントの削除 - 原神およびSnap Hutaoの利用規約を全て熟読し、その後に『ゲームランチャー - 上級者向け設定』を有効にします。 + 私は原神及び Snap Hutao の利用規約を全て熟読し、その後に「ゲームランチャー - 高度な機能」を有効にします。 - 上級者向け設定を有効にする + 高度な機能 オートクリック機能のショートカットキーを変更します @@ -2977,7 +3026,7 @@ 公式サイト - カスタム背景を設定する / bmp、git、ico、jpg、jpeg、png、tiff、webp形式をサポートしています + カスタム背景画像、 bmp / gif / ico / jpg / jpeg / png / tiff / webp 形式をサポートしています カスタム背景フォルダーを開く @@ -3010,7 +3059,13 @@ ゲーム本体の場所を開く - ゲームのパスを設定する際、本体(YuanShen.exe または GenshinImpact.exe)を選んでください。ランチャー(launcher.exe)ではありません + ゲームパスを設定する際、ランチャー(launcher.exe)ではなく、本体(YuanShen.exe または GenshinImpact.exe)を選択してください。 + + + 共有ボタンをクリックした後、画像を保存するモードを選択します + + + 共有の保存モード Shell エクスペリエンス @@ -3072,6 +3127,9 @@ Webview2 ランタイム + + WebView + 後半 @@ -3079,7 +3137,7 @@ 前半 - おすすめ聖遺物 + 推奨組み合わせ 育成素材 @@ -3091,7 +3149,7 @@ 中国語CV - 命の星座 + 命ノ星座 コスチューム @@ -3282,6 +3340,12 @@ 旅行ツール + + アカウント ログイン + + + サードパーティ ログイン + ウェブ上でログイン @@ -3364,7 +3428,7 @@ 実行 - デバッグ スクリプトを実行します。 + デバッグスクリプトを実行 {0} 日後に開始 @@ -3384,6 +3448,21 @@ クリップボードにコピーしました。 + + 共有画像を保存 + + + 画像の保存に失敗しました + + + 画像を保存しました。 + + + クリップボードにコピー + + + ファイルとして保存 + すべての魔神任務が完了しました @@ -3541,10 +3620,10 @@ 無効なUIDです - 中国サーバー: 公式 + 中国サーバー: 天空島 - 中国サーバー: ビリビリ(bilibili) + 中国サーバー: 世界樹 国内サーバー: アジア diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ko.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ko.resx index bd8186fc9..3ae3fb8ab 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ko.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ko.resx @@ -1376,6 +1376,30 @@ 수동 기원 기록 입력 Url + + 游戏服务器 + + + 当前选择目录为HDD,建议使用SSD + + + 设置游戏安装目录 + + + 安装游戏 + + + 汉语 + + + 英语 + + + 日语 + + + 韩语 + 请输入请求接口的 Url 复合模板 @@ -1505,6 +1529,15 @@ 更新 + + 请输入账号 + + + 비밀번호를 입력하세요 + + + 账号密码登录 + 지금 이동 @@ -1676,6 +1709,9 @@ 캐릭터 상세정보 보기가 꺼져있습니다. 게임에서 설정 후 다시 시도하십시오. + + 共 {0} 位角色 + 复制角色详情失败 @@ -1880,9 +1916,15 @@ 가져오기 실패 + + 当前选中用户和游戏服务器不匹配,请重新选择 + 当前选中的游戏目录 {0} 已损坏,请手动删除文件夹后重新安装游戏 + + 使用 米游社 / HoYoLAB 用户登录失败,请重新登录 + 서버 변경 실패 @@ -2702,6 +2744,12 @@ 활성화 + + 使用当前选中的 米游社 / HoYoLAB 用户登录,不支持渠道服 + + + 使用 米游社 / HoYoLAB 用户登录 + 充分利用支持高动态范围的显示器获得更亮、更生动、更精细的画面 @@ -3011,6 +3059,12 @@ 게임 경로를 설정할 때 런쳐(launcher.exe) 대신 게임(YuanShen.exe 또는 GenshinImpact.exe)를 선택하세요 + + 选择点击分享按钮后保存图片的模式 + + + 分享保存模式 + Shell 体验 @@ -3071,6 +3125,9 @@ Webview2 런타임 + + WebView + 下半 @@ -3281,6 +3338,12 @@ 旅行工具 + + 账密登录 + + + 三方登录 + 웹 로그인 @@ -3383,6 +3446,21 @@ 已复制到剪贴板 + + 保存分享图片 + + + 图片保存失败 + + + 图片保存成功 + + + 复制到剪贴板 + + + 保存为文件 + 所有魔神任务已完成 diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.pt.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.pt.resx index 9feb1720f..774e1a3ad 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.pt.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.pt.resx @@ -1376,6 +1376,30 @@ Insira manualmente o URL do histórico de orações + + 游戏服务器 + + + 当前选择目录为HDD,建议使用SSD + + + 设置游戏安装目录 + + + 安装游戏 + + + 汉语 + + + 英语 + + + 日语 + + + 韩语 + Url da solicitação de entrada com modelo composto @@ -1505,6 +1529,15 @@ 更新 + + 请输入账号 + + + Digite sua senha + + + 账号密码登录 + Leve-me até lá @@ -1676,6 +1709,9 @@ A exibição de personagens está desativada. Por favor, ative-a no jogo. + + 共 {0} 位角色 + 复制角色详情失败 @@ -1880,9 +1916,15 @@ Falha na importação + + 当前选中用户和游戏服务器不匹配,请重新选择 + 当前选中的游戏目录 {0} 已损坏,请手动删除文件夹后重新安装游戏 + + 使用 米游社 / HoYoLAB 用户登录失败,请重新登录 + Falha ao converter o servidor @@ -2702,6 +2744,12 @@ Ativado + + 使用当前选中的 米游社 / HoYoLAB 用户登录,不支持渠道服 + + + 使用 米游社 / HoYoLAB 用户登录 + Aproveite as vantagens das telas que suportam HDR para obter imagens mais brilhantes, mais vívidas e mais detalhadas @@ -3011,6 +3059,12 @@ Ao definir o caminho do jogo, selecione o programa do jogo (Yuanshen.exe ou GenshinImpact.exe) em vez do iniciador do jogo (launcher.exe) + + 选择点击分享按钮后保存图片的模式 + + + 分享保存模式 + Experiência Shell @@ -3071,6 +3125,9 @@ Webview2 Runtime + + WebView + 下半 @@ -3281,6 +3338,12 @@ Ferramentas oficiais + + 账密登录 + + + 三方登录 + Login na web @@ -3383,6 +3446,21 @@ Copiado para a área de transferência + + 保存分享图片 + + + 图片保存失败 + + + 图片保存成功 + + + 复制到剪贴板 + + + 保存为文件 + Todas as missões de arconte concluídas diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ru.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ru.resx index 7de85367f..a4353c806 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ru.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ru.resx @@ -1376,6 +1376,30 @@ 手动输入祈愿记录 Url + + 游戏服务器 + + + 当前选择目录为HDD,建议使用SSD + + + 设置游戏安装目录 + + + 安装游戏 + + + 汉语 + + + 英语 + + + 日语 + + + 韩语 + 请输入请求接口的 Url 复合模板 @@ -1505,6 +1529,15 @@ 更新 + + 请输入账号 + + + Введите пароль + + + 账号密码登录 + 立即前往 @@ -1676,6 +1709,9 @@ 角色展柜尚未开启,请前往游戏操作后重试 + + 共 {0} 位角色 + 复制角色详情失败 @@ -1880,9 +1916,15 @@ Ошибка загрузки + + 当前选中用户和游戏服务器不匹配,请重新选择 + 当前选中的游戏目录 {0} 已损坏,请手动删除文件夹后重新安装游戏 + + 使用 米游社 / HoYoLAB 用户登录失败,请重新登录 + 切换服务器失败 @@ -2702,6 +2744,12 @@ Включено + + 使用当前选中的 米游社 / HoYoLAB 用户登录,不支持渠道服 + + + 使用 米游社 / HoYoLAB 用户登录 + Используйте преимущества мониторов с поддержкой HDR для получения более ярких, живых и детализированных изображений @@ -3011,6 +3059,12 @@ 设置游戏路径时,请选择游戏本体(YuanShen.exe 或 GenshinImpact.exe)而不是启动器(launcher.exe) + + 选择点击分享按钮后保存图片的模式 + + + 分享保存模式 + Shell 体验 @@ -3071,6 +3125,9 @@ Webview2 Runtime + + WebView + 下半 @@ -3281,6 +3338,12 @@ Официальные инструменты + + 账密登录 + + + 三方登录 + Вход через браузер @@ -3383,6 +3446,21 @@ Скопировано в буфер обмена + + 保存分享图片 + + + 图片保存失败 + + + 图片保存成功 + + + 复制到剪贴板 + + + 保存为文件 + 所有魔神任务已完成 diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.vi.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.vi.resx index bd6fbe7f2..e288ad2e6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.vi.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.vi.resx @@ -1376,6 +1376,30 @@ 手动输入祈愿记录 Url + + 游戏服务器 + + + 当前选择目录为HDD,建议使用SSD + + + 设置游戏安装目录 + + + 安装游戏 + + + 汉语 + + + 英语 + + + 日语 + + + 韩语 + 请输入请求接口的 Url 复合模板 @@ -1505,6 +1529,15 @@ 更新 + + 请输入账号 + + + 请输入密码 + + + 账号密码登录 + 立即前往 @@ -1676,6 +1709,9 @@ 角色展柜尚未开启,请前往游戏操作后重试 + + 共 {0} 位角色 + 复制角色详情失败 @@ -1880,9 +1916,15 @@ 导入失败 + + 当前选中用户和游戏服务器不匹配,请重新选择 + 当前选中的游戏目录 {0} 已损坏,请手动删除文件夹后重新安装游戏 + + 使用 米游社 / HoYoLAB 用户登录失败,请重新登录 + 切换服务器失败 @@ -2702,6 +2744,12 @@ 启用 + + 使用当前选中的 米游社 / HoYoLAB 用户登录,不支持渠道服 + + + 使用 米游社 / HoYoLAB 用户登录 + 充分利用支持高动态范围的显示器获得更亮、更生动、更精细的画面 @@ -3011,6 +3059,12 @@ 设置游戏路径时,请选择游戏本体(YuanShen.exe 或 GenshinImpact.exe)而不是启动器(launcher.exe) + + 选择点击分享按钮后保存图片的模式 + + + 分享保存模式 + Shell 体验 @@ -3071,6 +3125,9 @@ Webview2 运行时 + + WebView + 下半 @@ -3281,6 +3338,12 @@ 旅行工具 + + 账密登录 + + + 三方登录 + 网页登录 @@ -3383,6 +3446,21 @@ 已复制到剪贴板 + + 保存分享图片 + + + 图片保存失败 + + + 图片保存成功 + + + 复制到剪贴板 + + + 保存为文件 + 所有魔神任务已完成 diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.zh-Hant.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.zh-Hant.resx index 738acaead..33aa4d726 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.zh-Hant.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.zh-Hant.resx @@ -1376,6 +1376,30 @@ 手動輸入祈願紀錄 URL + + 遊戲伺服器 + + + 目前選擇目錄為HDD,建議使用SSD + + + 設定遊戲安裝目錄 + + + 安裝遊戲 + + + 漢語 + + + 英語 + + + 日語 + + + 韓語 + 請輸入請求介面的 URL 複合模板 @@ -1505,6 +1529,15 @@ 更新 + + 請輸入帳號 + + + 請輸入密碼 + + + 帳號密碼登入 + 立即前往 @@ -1676,6 +1709,9 @@ 角色展櫃尚未開啟,請前往遊戲操作後重試 + + 共 {0} 位角色 + 複製角色詳情失敗 @@ -1880,9 +1916,15 @@ 匯入失敗 + + 目前選中使用者與遊戲伺服器不匹配,請重新選擇 + 目前選中的遊戲目錄 {0} 已損壞,請手動刪除資料夾後重新安裝遊戲 + + 使用 米遊社 / HoYoLAB 使用者登入失敗,請重新登入 + 切換伺服器失敗 @@ -2702,6 +2744,12 @@ 啟用 + + 使用目前選中的 米遊社 / HoYoLAB 使用者登入,不支援渠道服 + + + 使用 米遊社 / HoYoLAB 使用者登入 + 充分利用支援 HDR 的顯示器以獲得更亮、更生動、更精細的畫面 @@ -3011,6 +3059,12 @@ 設定遊戲路徑時,請選擇遊戲本體(YuanShen.exe 或 GenshinImpact.exe) 而不是啟動器(launcher.exe) + + 選擇點擊分享按鈕後儲存圖片的模式 + + + 分享儲存模式 + Shell 體驗 @@ -3071,6 +3125,9 @@ WebView2 執行階段 + + WebView + 下半 @@ -3281,6 +3338,12 @@ 旅行工具 + + 帳密登入 + + + 第三方登入 + 網頁登入 @@ -3383,6 +3446,21 @@ 已複製到剪貼簿 + + 儲存分享圖片 + + + 圖片儲存失敗 + + + 圖片儲存成功 + + + 複製到剪貼簿 + + + 儲存為檔案 + 所有魔神任務已完成 From 10170724da1d7f85cb08fcc38dd8bf4a32ecd842 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Sun, 20 Oct 2024 19:08:21 +0800 Subject: [PATCH 05/99] bump version --- src/Snap.Hutao/Snap.Hutao/Package.appxmanifest | 2 +- src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest index 2df305c24..4f694e35a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest +++ b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest @@ -13,7 +13,7 @@ + Version="1.11.5.0" /> Snap Hutao diff --git a/src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest b/src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest index d02c82aad..6e8c08db6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest +++ b/src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest @@ -13,7 +13,7 @@ + Version="1.11.5.0" /> Snap Hutao Dev From a3a3488623ad589d6226457f9b1ff90bb0f33deb Mon Sep 17 00:00:00 2001 From: Masterain Date: Sun, 20 Oct 2024 16:45:56 -0700 Subject: [PATCH 06/99] Update CI/CD --- .github/workflows/alpha.yml | 18 ++++++++++++++++++ appveyor.yml | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/.github/workflows/alpha.yml b/.github/workflows/alpha.yml index e7a98c85a..5d6ba8da4 100644 --- a/.github/workflows/alpha.yml +++ b/.github/workflows/alpha.yml @@ -99,3 +99,21 @@ jobs: " echo $summary >> $Env:GITHUB_STEP_SUMMARY + + - name: Clean up + run: | + Write-Host "Cleaning up NuGet cache..." + Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages" + Write-Host "NuGet cache cleaned." + + Write-Host "Cleaning up .NET install folder..." + Remove-Item -Recurse -Force "C:\Users\Public\Documents\dotnet_install" + Write-Host ".NET install folder cleaned." + + Write-Host "Cleaning up AppVeyor user's local cache..." + Remove-Item -Recurse -Force "C:\Users\appveyor\AppData\Local" + Write-Host "AppVeyor user's local cache cleaned." + + Write-Host "Cleaning up Administrator user's local cache..." + Remove-Item -Recurse -Force "C:\Users\Administrator\AppData\Local" + Write-Host "Administrator user's local cache cleaned." diff --git a/appveyor.yml b/appveyor.yml index afe74bc29..7ca80e45b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,6 +4,8 @@ branches: - "release" build_cloud: HUTAO-ACTIONS image: Visual Studio 2022 +cache: + - 'C:\Users\Public\Documents\dotnet_install\.nuget\packages' clone_depth: 3 clone_folder: C:\Users\Public\appveyor\Snap.Hutao install: @@ -18,3 +20,20 @@ deploy: url: https://app.signpath.io/API/v1/7a941fa3-64d8-4c45-bd03-92a02bcd4964/Integrations/AppVeyor?ProjectSlug=Snap.Hutao&SigningPolicySlug=release-signing&ArtifactConfigurationSlug=msix authorization: secure: j8srQ5/UYWhI+jlm3Vo3D3QfXoRyQ9hOn3ynJGtwusKui4+uDi4gykdUFYCITZxK+C/fOCAZNJ+YaKSm/OaiXw== +on_finish: +- pwsh: | + Write-Host "Cleaning up NuGet cache..." + Remove-Item -Recurse -Force "$env:LOCALAPPDATA\NuGet\v3-cache" + Write-Host "NuGet cache cleaned." + + Write-Host "Cleaning up .NET install folder..." + Remove-Item -Recurse -Force "C:\Users\Public\Documents\dotnet_install" + Write-Host ".NET install folder cleaned." + + Write-Host "Cleaning up AppVeyor user's local cache..." + Remove-Item -Recurse -Force "C:\Users\appveyor\AppData\Local" + Write-Host "AppVeyor user's local cache cleaned." + + Write-Host "Cleaning up Administrator user's local cache..." + Remove-Item -Recurse -Force "C:\Users\Administrator\AppData\Local" + Write-Host "Administrator user's local cache cleaned." \ No newline at end of file From dbeaf0e059aa7fa715c8260d3be24d791b86ee65 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Mon, 21 Oct 2024 10:15:57 +0800 Subject: [PATCH 07/99] hack fix #2074 --- .../Core/IO/Http/Sharding/HttpShardCopyWorker.cs | 10 +++++----- .../LaunchExecutionEnsureGameResourceHandler.cs | 2 +- .../Service/Game/Package/IPackageConverter.cs | 16 ++++++++++++++++ ...rter.cs => ScatteredFilesPackageConverter.cs} | 7 ++++--- .../Builder/HttpRequestMessageExtension.cs | 6 ++++++ .../Request/Builder/JsonHttpContentSerializer.cs | 2 +- 6 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/Game/Package/IPackageConverter.cs rename src/Snap.Hutao/Snap.Hutao/Service/Game/Package/{PackageConverter.cs => ScatteredFilesPackageConverter.cs} (98%) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Sharding/HttpShardCopyWorker.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Sharding/HttpShardCopyWorker.cs index 98961be66..87335b64e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Sharding/HttpShardCopyWorker.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Sharding/HttpShardCopyWorker.cs @@ -60,18 +60,18 @@ private async ValueTask CopyShardAsync(IHttpShard shard, IProgress memoryOwner = MemoryPool.Shared.Rent(options.BufferSize)) { Memory buffer = memoryOwner.Memory; - using (Stream stream = await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false)) + using (Stream stream = await response.Content.ReadAsStreamAsync(token).ConfigureAwait(true)) { int bytesReadSinceLastReport = 0; do { - using (await shard.ReaderWriterLock.ReaderLockAsync().ConfigureAwait(false)) + using (await shard.ReaderWriterLock.ReaderLockAsync().ConfigureAwait(true)) { if (shard.BytesRead >= shard.End - shard.Start) { @@ -81,13 +81,13 @@ private async ValueTask CopyShardAsync(IHttpShard shard, IProgress EnsureGameResourceAsync(LaunchExecutionCont return false; } - PackageConverter packageConverter = context.ServiceProvider.GetRequiredService(); + IPackageConverter packageConverter = context.ServiceProvider.GetRequiredService(); if (!context.Scheme.ExecutableMatches(gameFileName)) { diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/IPackageConverter.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/IPackageConverter.cs new file mode 100644 index 000000000..041a30505 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/IPackageConverter.cs @@ -0,0 +1,16 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Service.Game.Scheme; +using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.ChannelSDK; +using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.DeprecatedFile; +using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Package; + +namespace Snap.Hutao.Service.Game.Package; + +internal interface IPackageConverter +{ + ValueTask EnsureDeprecatedFilesAndSdkAsync(GameChannelSDK? channelSDK, DeprecatedFilesWrapper? deprecatedFiles, string gameFolder); + + ValueTask EnsureGameResourceAsync(LaunchScheme targetScheme, GamePackage gamePackage, string gameFolder, IProgress progress); +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverter.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/ScatteredFilesPackageConverter.cs similarity index 98% rename from src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverter.cs rename to src/Snap.Hutao/Snap.Hutao/Service/Game/Package/ScatteredFilesPackageConverter.cs index 74b63242e..7733c2289 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/ScatteredFilesPackageConverter.cs @@ -21,14 +21,15 @@ namespace Snap.Hutao.Service.Game.Package; -[ConstructorGenerated(ResolveHttpClient = true)] [HttpClient(HttpClientConfiguration.Default)] [PrimaryHttpMessageHandler(MaxConnectionsPerServer = 8)] -internal sealed partial class PackageConverter +[ConstructorGenerated(ResolveHttpClient = true)] +[Injection(InjectAs.Transient, typeof(IPackageConverter))] +internal sealed partial class ScatteredFilesPackageConverter : IPackageConverter { private const string PackageVersion = "pkg_version"; - private readonly ILogger logger; + private readonly ILogger logger; private readonly JsonSerializerOptions options; private readonly HttpClient httpClient; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Request/Builder/HttpRequestMessageExtension.cs b/src/Snap.Hutao/Snap.Hutao/Web/Request/Builder/HttpRequestMessageExtension.cs index 3c4f8fca6..931338f8e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Request/Builder/HttpRequestMessageExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Request/Builder/HttpRequestMessageExtension.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using System.IO; using System.Net.Http; using System.Runtime.CompilerServices; @@ -16,6 +17,7 @@ public static void Resurrect(this HttpRequestMessage httpRequestMessage) if (httpRequestMessage.Content is { } content) { + Volatile.Write(ref GetPrivatedBufferedContent(content), default); Volatile.Write(ref GetPrivatedDisposed(content), false); } } @@ -27,4 +29,8 @@ public static void Resurrect(this HttpRequestMessage httpRequestMessage) // private bool _disposed [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_disposed")] private static extern ref bool GetPrivatedDisposed(HttpContent content); + + // private MemoryStream? _bufferedContent + [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_bufferedContent")] + private static extern ref MemoryStream? GetPrivatedBufferedContent(HttpContent content); } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Request/Builder/JsonHttpContentSerializer.cs b/src/Snap.Hutao/Snap.Hutao/Web/Request/Builder/JsonHttpContentSerializer.cs index f2d5c31fd..8486cdadf 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Request/Builder/JsonHttpContentSerializer.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Request/Builder/JsonHttpContentSerializer.cs @@ -8,7 +8,7 @@ namespace Snap.Hutao.Web.Request.Builder; [Injection(InjectAs.Singleton)] -internal class JsonHttpContentSerializer : HttpContentSerializer +internal sealed class JsonHttpContentSerializer : HttpContentSerializer { public JsonHttpContentSerializer(JsonSerializerOptions jsonSerializerOptions) { From 434516245f8a426563a9f6390782b4dc08868677 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Mon, 21 Oct 2024 10:50:04 +0800 Subject: [PATCH 08/99] ConfigureAwait(true) in Parallel.ForEachAsync --- .../Game/Package/Advanced/GameAssetOperationSSD.cs | 8 ++++---- .../Snap.Hutao/Service/Metadata/MetadataService.cs | 4 ++-- .../Snap.Hutao/ViewModel/Guide/GuideViewModel.cs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/Advanced/GameAssetOperationSSD.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/Advanced/GameAssetOperationSSD.cs index 15d3d6d4f..ddbc23fd5 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/Advanced/GameAssetOperationSSD.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/Advanced/GameAssetOperationSSD.cs @@ -19,7 +19,7 @@ public override async ValueTask InstallAssetsAsync(GamePackageServiceContext con await Parallel.ForEachAsync(remoteBuild.Manifests, context.ParallelOptions, async (manifest, token) => { IEnumerable assets = manifest.ManifestProto.Assets.Select(asset => SophonAssetOperation.AddOrRepair(manifest.UrlPrefix, asset)); - await Parallel.ForEachAsync(assets, context.ParallelOptions, (asset, token) => EnsureAssetAsync(context, asset)).ConfigureAwait(false); + await Parallel.ForEachAsync(assets, context.ParallelOptions, (asset, token) => EnsureAssetAsync(context, asset)).ConfigureAwait(true); }).ConfigureAwait(false); } @@ -91,7 +91,7 @@ private static async ValueTask MergeChunkIntoAssetAsync(GamePackageServiceContex return; } - using (await context.ExclusiveProcessChunkAsync(chunk.ChunkName, token).ConfigureAwait(false)) + using (await context.ExclusiveProcessChunkAsync(chunk.ChunkName, token).ConfigureAwait(true)) { using (FileStream chunkFile = File.OpenRead(chunkPath)) { @@ -100,13 +100,13 @@ private static async ValueTask MergeChunkIntoAssetAsync(GamePackageServiceContex long offset = chunk.ChunkOnFileOffset; do { - int bytesRead = await decompressionStream.ReadAsync(buffer, token).ConfigureAwait(false); + int bytesRead = await decompressionStream.ReadAsync(buffer, token).ConfigureAwait(true); if (bytesRead <= 0) { break; } - await RandomAccess.WriteAsync(fileHandle, buffer[..bytesRead], offset, token).ConfigureAwait(false); + await RandomAccess.WriteAsync(fileHandle, buffer[..bytesRead], offset, token).ConfigureAwait(true); context.Progress.Report(new GamePackageOperationReport.Install(bytesRead, 0, chunk.ChunkName)); offset += bytesRead; } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs index 3485c3fa3..121466f42 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Metadata/MetadataService.cs @@ -202,13 +202,13 @@ private Task CheckMetadataSourceFilesAsync(ImmutableDictionary m bool skip = false; if (File.Exists(fileFullPath)) { - skip = hash == await XXH64.HashFileAsync(fileFullPath, token).ConfigureAwait(false); + skip = hash == await XXH64.HashFileAsync(fileFullPath, token).ConfigureAwait(true); } if (!skip) { logger.LogInformation("{Hash} of {File} not matched, begin downloading", nameof(XXH64), fileFullName); - await DownloadMetadataSourceFilesAsync(fileFullName, token).ConfigureAwait(false); + await DownloadMetadataSourceFilesAsync(fileFullName, token).ConfigureAwait(true); } }); } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Guide/GuideViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Guide/GuideViewModel.cs index 1bc2b08b5..b6c547398 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Guide/GuideViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Guide/GuideViewModel.cs @@ -202,7 +202,7 @@ private async Task DownloadStaticResourceAsync() await Parallel.ForEachAsync([.. DownloadSummaries], async (summary, token) => { - if (await summary.DownloadAndExtractAsync().ConfigureAwait(false)) + if (await summary.DownloadAndExtractAsync().ConfigureAwait(true)) { taskContext.BeginInvokeOnMainThread(() => DownloadSummaries.Remove(summary)); } From 7e0436f69e7bf2b87b04cf84fb9f94863f3960fe Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Mon, 21 Oct 2024 11:13:29 +0800 Subject: [PATCH 09/99] bump version --- src/Snap.Hutao/Snap.Hutao/Package.appxmanifest | 2 +- src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest index 4f694e35a..ab9609d2a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest +++ b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest @@ -13,7 +13,7 @@ + Version="1.11.6.0" /> Snap Hutao diff --git a/src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest b/src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest index 6e8c08db6..0d79cb4c5 100644 --- a/src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest +++ b/src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest @@ -13,7 +13,7 @@ + Version="1.11.6.0" /> Snap Hutao Dev From eba9280195a57297731bf02fdd4eb8a54b269d25 Mon Sep 17 00:00:00 2001 From: Masterain Date: Sun, 20 Oct 2024 20:36:34 -0700 Subject: [PATCH 10/99] Update CI/CD --- .github/workflows/alpha.yml | 8 -------- appveyor.yml | 8 -------- 2 files changed, 16 deletions(-) diff --git a/.github/workflows/alpha.yml b/.github/workflows/alpha.yml index 5d6ba8da4..f2b7fc3bf 100644 --- a/.github/workflows/alpha.yml +++ b/.github/workflows/alpha.yml @@ -109,11 +109,3 @@ jobs: Write-Host "Cleaning up .NET install folder..." Remove-Item -Recurse -Force "C:\Users\Public\Documents\dotnet_install" Write-Host ".NET install folder cleaned." - - Write-Host "Cleaning up AppVeyor user's local cache..." - Remove-Item -Recurse -Force "C:\Users\appveyor\AppData\Local" - Write-Host "AppVeyor user's local cache cleaned." - - Write-Host "Cleaning up Administrator user's local cache..." - Remove-Item -Recurse -Force "C:\Users\Administrator\AppData\Local" - Write-Host "Administrator user's local cache cleaned." diff --git a/appveyor.yml b/appveyor.yml index 7ca80e45b..4bb093f9e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -29,11 +29,3 @@ on_finish: Write-Host "Cleaning up .NET install folder..." Remove-Item -Recurse -Force "C:\Users\Public\Documents\dotnet_install" Write-Host ".NET install folder cleaned." - - Write-Host "Cleaning up AppVeyor user's local cache..." - Remove-Item -Recurse -Force "C:\Users\appveyor\AppData\Local" - Write-Host "AppVeyor user's local cache cleaned." - - Write-Host "Cleaning up Administrator user's local cache..." - Remove-Item -Recurse -Force "C:\Users\Administrator\AppData\Local" - Write-Host "Administrator user's local cache cleaned." \ No newline at end of file From 4e64857aed8971c6062789329b770dac53ffaec3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 07:56:08 +0000 Subject: [PATCH 11/99] Bump Snap.Hutao.SourceGeneration Bumps the packages group in /src/Snap.Hutao with 1 update: [Snap.Hutao.SourceGeneration](https://github.com/DGP-Studio/Snap.Hutao.SourceGeneration). Updates `Snap.Hutao.SourceGeneration` from 1.1.24 to 1.1.25 - [Commits](https://github.com/DGP-Studio/Snap.Hutao.SourceGeneration/commits) --- updated-dependencies: - dependency-name: Snap.Hutao.SourceGeneration dependency-type: direct:production update-type: version-update:semver-patch dependency-group: packages ... Signed-off-by: dependabot[bot] --- src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index 1194b211d..5c48a7cfc 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -352,7 +352,7 @@ all runtime; build; native; contentfiles; analyzers - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 6cf7f39d3a3abc3137594169cbd37993d13a277a Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Mon, 21 Oct 2024 20:00:05 +0800 Subject: [PATCH 12/99] extract converter context --- ...aunchExecutionEnsureGameResourceHandler.cs | 5 +- .../Service/Game/Package/IPackageConverter.cs | 9 +--- .../Game/Package/PackageConverterContext.cs | 42 ++++++++++++++++ .../Package/ScatteredFilesPackageConverter.cs | 49 +++++++++---------- 4 files changed, 71 insertions(+), 34 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverterContext.cs diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionEnsureGameResourceHandler.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionEnsureGameResourceHandler.cs index 774df649c..b990e84b7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionEnsureGameResourceHandler.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionEnsureGameResourceHandler.cs @@ -126,10 +126,11 @@ private static async ValueTask EnsureGameResourceAsync(LaunchExecutionCont } IPackageConverter packageConverter = context.ServiceProvider.GetRequiredService(); + PackageConverterContext packageConverterContext = new(context.Scheme, gameFolder, gamePackages.GamePackages.Single(), channelSDKs.GameChannelSDKs.SingleOrDefault(), deprecatedFileConfigs.DeprecatedFileConfigurations.SingleOrDefault(), progress); if (!context.Scheme.ExecutableMatches(gameFileName)) { - if (!await packageConverter.EnsureGameResourceAsync(context.Scheme, gamePackages.GamePackages.Single(), gameFolder, progress).ConfigureAwait(false)) + if (!await packageConverter.EnsureGameResourceAsync(packageConverterContext).ConfigureAwait(false)) { context.Result.Kind = LaunchExecutionResultKind.GameResourcePackageConvertInternalError; context.Result.ErrorMessage = SH.ViewModelLaunchGameEnsureGameResourceFail; @@ -143,7 +144,7 @@ private static async ValueTask EnsureGameResourceAsync(LaunchExecutionCont context.Options.UpdateGamePathAndRefreshEntries(Path.Combine(gameFolder, executableName)); } - await packageConverter.EnsureDeprecatedFilesAndSdkAsync(channelSDKs.GameChannelSDKs.SingleOrDefault(), deprecatedFileConfigs.DeprecatedFileConfigurations.SingleOrDefault(), gameFolder).ConfigureAwait(false); + await packageConverter.EnsureDeprecatedFilesAndSdkAsync(packageConverterContext).ConfigureAwait(false); return true; } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/IPackageConverter.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/IPackageConverter.cs index 041a30505..ab39e5eda 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/IPackageConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/IPackageConverter.cs @@ -1,16 +1,11 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using Snap.Hutao.Service.Game.Scheme; -using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.ChannelSDK; -using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.DeprecatedFile; -using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Package; - namespace Snap.Hutao.Service.Game.Package; internal interface IPackageConverter { - ValueTask EnsureDeprecatedFilesAndSdkAsync(GameChannelSDK? channelSDK, DeprecatedFilesWrapper? deprecatedFiles, string gameFolder); + ValueTask EnsureDeprecatedFilesAndSdkAsync(PackageConverterContext context); - ValueTask EnsureGameResourceAsync(LaunchScheme targetScheme, GamePackage gamePackage, string gameFolder, IProgress progress); + ValueTask EnsureGameResourceAsync(PackageConverterContext context); } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverterContext.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverterContext.cs new file mode 100644 index 000000000..8f9e6d430 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverterContext.cs @@ -0,0 +1,42 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Service.Game.Scheme; +using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Branch; +using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.ChannelSDK; +using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.DeprecatedFile; +using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Package; + +namespace Snap.Hutao.Service.Game.Package; + +internal readonly struct PackageConverterContext +{ + public readonly LaunchScheme Scheme; + public readonly string GameDirectory; + public readonly BranchWrapper? CurrentBranch; + public readonly BranchWrapper? TargetBranch; + public readonly GamePackage? TargetPackage; + public readonly GameChannelSDK? GameChannelSDK; + public readonly DeprecatedFilesWrapper? DeprecatedFiles; + public readonly IProgress Progress; + + public PackageConverterContext(LaunchScheme scheme, string gameDirectory, BranchWrapper currentBranch, BranchWrapper targetBranch, GameChannelSDK? gameChannelSDK, IProgress progress) + { + Scheme = scheme; + GameDirectory = gameDirectory; + CurrentBranch = currentBranch; + TargetBranch = targetBranch; + GameChannelSDK = gameChannelSDK; + Progress = progress; + } + + public PackageConverterContext(LaunchScheme scheme, string gameDirectory, GamePackage gamePackage, GameChannelSDK? gameChannelSDK, DeprecatedFilesWrapper? deprecatedFiles, IProgress progress) + { + Scheme = scheme; + GameDirectory = gameDirectory; + TargetPackage = gamePackage; + GameChannelSDK = gameChannelSDK; + DeprecatedFiles = deprecatedFiles; + Progress = progress; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/ScatteredFilesPackageConverter.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/ScatteredFilesPackageConverter.cs index 7733c2289..5c231b843 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/ScatteredFilesPackageConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/ScatteredFilesPackageConverter.cs @@ -7,10 +7,7 @@ using Snap.Hutao.Core.IO; using Snap.Hutao.Core.IO.Hashing; using Snap.Hutao.Core.IO.Http.Sharding; -using Snap.Hutao.Service.Game.Scheme; -using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.ChannelSDK; using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.DeprecatedFile; -using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Package; using System.Globalization; using System.IO; using System.IO.Compression; @@ -33,7 +30,7 @@ internal sealed partial class ScatteredFilesPackageConverter : IPackageConverter private readonly JsonSerializerOptions options; private readonly HttpClient httpClient; - public async ValueTask EnsureGameResourceAsync(LaunchScheme targetScheme, GamePackage gamePackage, string gameFolder, IProgress progress) + public async ValueTask EnsureGameResourceAsync(PackageConverterContext context) { // 以 国服 -> 国际服 为例 // 1. 下载国际服的 pkg_version 文件,转换为索引字典 @@ -55,51 +52,53 @@ public async ValueTask EnsureGameResourceAsync(LaunchScheme targetScheme, // 替换操作等于 先备份国服文件,随后新增国际服文件 // 准备下载链接 - string scatteredFilesUrl = gamePackage.Main.Major.ResourceListUrl; + ArgumentNullException.ThrowIfNull(context.TargetPackage); + + string scatteredFilesUrl = context.TargetPackage.Main.Major.ResourceListUrl; string pkgVersionUrl = $"{scatteredFilesUrl}/{PackageVersion}"; - PackageConverterFileSystemContext context = new(targetScheme.IsOversea, HutaoRuntime.GetDataFolderServerCacheFolder(), gameFolder, scatteredFilesUrl); + PackageConverterFileSystemContext fileSystemContext = new(context.Scheme.IsOversea, HutaoRuntime.GetDataFolderServerCacheFolder(), context.GameDirectory, scatteredFilesUrl); // Step 1 - progress.Report(new(SH.ServiceGamePackageRequestPackageVerion)); + context.Progress.Report(new(SH.ServiceGamePackageRequestPackageVerion)); RelativePathVersionItemDictionary remoteItems = await GetRemoteItemsAsync(pkgVersionUrl).ConfigureAwait(false); - RelativePathVersionItemDictionary localItems = await GetLocalItemsAsync(gameFolder).ConfigureAwait(false); + RelativePathVersionItemDictionary localItems = await GetLocalItemsAsync(context.GameDirectory).ConfigureAwait(false); // Step 2 List diffOperations = GetItemOperationInfos(remoteItems, localItems).ToList(); diffOperations.SortBy(i => i.Kind); // Step 3 - await PrepareCacheFilesAsync(diffOperations, context, progress).ConfigureAwait(false); + await PrepareCacheFilesAsync(diffOperations, fileSystemContext, context.Progress).ConfigureAwait(false); // Step 4 - return await ReplaceGameResourceAsync(diffOperations, context, progress).ConfigureAwait(false); + return await ReplaceGameResourceAsync(diffOperations, fileSystemContext, context.Progress).ConfigureAwait(false); } - public async ValueTask EnsureDeprecatedFilesAndSdkAsync(GameChannelSDK? channelSDK, DeprecatedFilesWrapper? deprecatedFiles, string gameFolder) + public async ValueTask EnsureDeprecatedFilesAndSdkAsync(PackageConverterContext context) { // Just try to delete these files, always download from server when needed - FileOperation.Delete(Path.Combine(gameFolder, YuanShenData, "Plugins\\PCGameSDK.dll")); - FileOperation.Delete(Path.Combine(gameFolder, GenshinImpactData, "Plugins\\PCGameSDK.dll")); - FileOperation.Delete(Path.Combine(gameFolder, YuanShenData, "Plugins\\EOSSDK-Win64-Shipping.dll")); - FileOperation.Delete(Path.Combine(gameFolder, GenshinImpactData, "Plugins\\EOSSDK-Win64-Shipping.dll")); - FileOperation.Delete(Path.Combine(gameFolder, YuanShenData, "Plugins\\PluginEOSSDK.dll")); - FileOperation.Delete(Path.Combine(gameFolder, GenshinImpactData, "Plugins\\PluginEOSSDK.dll")); - FileOperation.Delete(Path.Combine(gameFolder, "sdk_pkg_version")); - - if (channelSDK is not null) + FileOperation.Delete(Path.Combine(context.GameDirectory, YuanShenData, "Plugins\\PCGameSDK.dll")); + FileOperation.Delete(Path.Combine(context.GameDirectory, GenshinImpactData, "Plugins\\PCGameSDK.dll")); + FileOperation.Delete(Path.Combine(context.GameDirectory, YuanShenData, "Plugins\\EOSSDK-Win64-Shipping.dll")); + FileOperation.Delete(Path.Combine(context.GameDirectory, GenshinImpactData, "Plugins\\EOSSDK-Win64-Shipping.dll")); + FileOperation.Delete(Path.Combine(context.GameDirectory, YuanShenData, "Plugins\\PluginEOSSDK.dll")); + FileOperation.Delete(Path.Combine(context.GameDirectory, GenshinImpactData, "Plugins\\PluginEOSSDK.dll")); + FileOperation.Delete(Path.Combine(context.GameDirectory, "sdk_pkg_version")); + + if (context.GameChannelSDK is not null) { - using (Stream sdkWebStream = await httpClient.GetStreamAsync(channelSDK.ChannelSdkPackage.Url).ConfigureAwait(false)) + using (Stream sdkWebStream = await httpClient.GetStreamAsync(context.GameChannelSDK.ChannelSdkPackage.Url).ConfigureAwait(false)) { - ZipFile.ExtractToDirectory(sdkWebStream, gameFolder, true); + ZipFile.ExtractToDirectory(sdkWebStream, context.GameDirectory, true); } } - if (deprecatedFiles is not null) + if (context.DeprecatedFiles is not null) { - foreach (DeprecatedFile file in deprecatedFiles.DeprecatedFiles) + foreach (DeprecatedFile file in context.DeprecatedFiles.DeprecatedFiles) { - string filePath = Path.Combine(gameFolder, file.Name); + string filePath = Path.Combine(context.GameDirectory, file.Name); FileOperation.Move(filePath, $"{filePath}.backup", true); } } From 0962f44e9c4b0797133d7a697e369cfe58b92377 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Tue, 22 Oct 2024 09:03:44 +0800 Subject: [PATCH 13/99] check if game is running when refresh gachalog with web cache --- src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx | 3 +++ .../GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx index 88dd962e8..eaba9ae89 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx @@ -929,6 +929,9 @@ 未找到可用的 Url + + 游戏正在运行中,关闭游戏后重试 + 提供的 Url 无效 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs index 0b7b1192d..1f3eae5e6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs @@ -45,7 +45,6 @@ public static string GetCacheFile(string path) return string.Empty; } - /// public async ValueTask> GetQueryAsync() { (bool isOk, string path) = await gameService.GetGamePathAsync().ConfigureAwait(false); @@ -55,6 +54,11 @@ public async ValueTask> GetQueryAsync() return new(false, GachaLogQuery.Invalid(SH.ServiceGachaLogUrlProviderCachePathInvalid)); } + if (gameService.IsGameRunning()) + { + return new(false, GachaLogQuery.Invalid(SH.ServiceGachaLogUrlProviderGameIsRunning)); + } + string cacheFile = GetCacheFile(path); if (!File.Exists(cacheFile)) { From b79b4d9b66c359a77e2c6056b86345f2d3ecb26a Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Tue, 22 Oct 2024 09:12:10 +0800 Subject: [PATCH 14/99] fix qa#38 --- src/Snap.Hutao/Snap.Hutao/ViewModel/TitleViewModel.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/TitleViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/TitleViewModel.cs index 54b7e4b85..adb759829 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/TitleViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/TitleViewModel.cs @@ -117,6 +117,11 @@ private async ValueTask DoCheckUpdateAsync() } } + if (currentXamlWindowReference.Window is null) + { + return; + } + if (checkUpdateResult.Kind is CheckUpdateResultKind.NeedInstall) { ContentDialogResult installUpdateUserConsentResult = await contentDialogFactory From b291a2ac03e27bf9ee38cd8d2f167e5b53574bca Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Tue, 22 Oct 2024 16:40:09 +0800 Subject: [PATCH 15/99] update issue template --- .github/ISSUE_TEMPLATE/CHS-bug-report.yml | 3 ++- .github/ISSUE_TEMPLATE/CHS-feature-request.yml | 3 ++- .github/ISSUE_TEMPLATE/CHS-network-issue.yml | 1 + .github/ISSUE_TEMPLATE/ENG-bug-report.yml | 3 ++- .github/ISSUE_TEMPLATE/ENG-feature-request.yml | 3 ++- .github/ISSUE_TEMPLATE/ENG-network-issue.yml | 1 + 6 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/CHS-bug-report.yml b/.github/ISSUE_TEMPLATE/CHS-bug-report.yml index 0123844f4..b2165ac40 100644 --- a/.github/ISSUE_TEMPLATE/CHS-bug-report.yml +++ b/.github/ISSUE_TEMPLATE/CHS-bug-report.yml @@ -1,7 +1,8 @@ name: 问题反馈 description: 通过这个议题向开发团队反馈你发现的程序中的问题 title: "[Bug]: 在这里填写一个合适的标题" -labels: ["BUG", "priority:none"] +type: "Bug" +labels: ["priority:none"] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/CHS-feature-request.yml b/.github/ISSUE_TEMPLATE/CHS-feature-request.yml index 6c443b0a2..06ba93500 100644 --- a/.github/ISSUE_TEMPLATE/CHS-feature-request.yml +++ b/.github/ISSUE_TEMPLATE/CHS-feature-request.yml @@ -1,7 +1,8 @@ name: 功能请求 description: 通过这个议题来向开发团队分享你的想法 title: "[Feat]: 在这里填写一个合适的标题" -labels: ["feature request", "needs-triage", "priority:none"] +type: "Feature" +labels: ["needs-triage", "priority:none"] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/CHS-network-issue.yml b/.github/ISSUE_TEMPLATE/CHS-network-issue.yml index 8576da0f3..cbb96bf03 100644 --- a/.github/ISSUE_TEMPLATE/CHS-network-issue.yml +++ b/.github/ISSUE_TEMPLATE/CHS-network-issue.yml @@ -1,6 +1,7 @@ name: 网络问题 description: 通过这个议题来反馈网络问题 title: "[Network]: 在这里填写一个合适的标题" +type: "Bug" labels: ["area-Network"] assignees: - Lightczx diff --git a/.github/ISSUE_TEMPLATE/ENG-bug-report.yml b/.github/ISSUE_TEMPLATE/ENG-bug-report.yml index 3576e416b..68ad9d120 100644 --- a/.github/ISSUE_TEMPLATE/ENG-bug-report.yml +++ b/.github/ISSUE_TEMPLATE/ENG-bug-report.yml @@ -1,7 +1,8 @@ name: BUG Report [English Form] description: Tell us what issue you get title: "[ENG][Bug]: Place your Issue Title Here" -labels: ["BUG", "priority:none"] +type: "Bug" +labels: ["priority:none"] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/ENG-feature-request.yml b/.github/ISSUE_TEMPLATE/ENG-feature-request.yml index 591e9cc7b..e7ebcae60 100644 --- a/.github/ISSUE_TEMPLATE/ENG-feature-request.yml +++ b/.github/ISSUE_TEMPLATE/ENG-feature-request.yml @@ -1,7 +1,8 @@ name: Feature Request [English Form] description: Tell us about your thought title: "[Feat]: Place your title here" -labels: ["feature request", "needs-triage", "priority:none"] +type: "Feature" +labels: ["needs-triage", "priority:none"] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/ENG-network-issue.yml b/.github/ISSUE_TEMPLATE/ENG-network-issue.yml index 5d46323aa..13d491f05 100644 --- a/.github/ISSUE_TEMPLATE/ENG-network-issue.yml +++ b/.github/ISSUE_TEMPLATE/ENG-network-issue.yml @@ -1,6 +1,7 @@ name: Network Issue [English Form] description: Submit this issue form when network issue affect your client experience title: "[Network]: Place your title here" +type: "Bug" labels: ["area-Network"] assignees: - Lightczx From 1648640091fce44c9594fdb04fb496b9e1004989 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Mon, 21 Oct 2024 20:00:05 +0800 Subject: [PATCH 16/99] extract converter context --- ...aunchExecutionEnsureGameResourceHandler.cs | 5 +- .../Service/Game/Package/IPackageConverter.cs | 9 +--- .../Game/Package/PackageConverterContext.cs | 42 ++++++++++++++++ .../Package/ScatteredFilesPackageConverter.cs | 49 +++++++++---------- 4 files changed, 71 insertions(+), 34 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverterContext.cs diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionEnsureGameResourceHandler.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionEnsureGameResourceHandler.cs index 774df649c..b990e84b7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionEnsureGameResourceHandler.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionEnsureGameResourceHandler.cs @@ -126,10 +126,11 @@ private static async ValueTask EnsureGameResourceAsync(LaunchExecutionCont } IPackageConverter packageConverter = context.ServiceProvider.GetRequiredService(); + PackageConverterContext packageConverterContext = new(context.Scheme, gameFolder, gamePackages.GamePackages.Single(), channelSDKs.GameChannelSDKs.SingleOrDefault(), deprecatedFileConfigs.DeprecatedFileConfigurations.SingleOrDefault(), progress); if (!context.Scheme.ExecutableMatches(gameFileName)) { - if (!await packageConverter.EnsureGameResourceAsync(context.Scheme, gamePackages.GamePackages.Single(), gameFolder, progress).ConfigureAwait(false)) + if (!await packageConverter.EnsureGameResourceAsync(packageConverterContext).ConfigureAwait(false)) { context.Result.Kind = LaunchExecutionResultKind.GameResourcePackageConvertInternalError; context.Result.ErrorMessage = SH.ViewModelLaunchGameEnsureGameResourceFail; @@ -143,7 +144,7 @@ private static async ValueTask EnsureGameResourceAsync(LaunchExecutionCont context.Options.UpdateGamePathAndRefreshEntries(Path.Combine(gameFolder, executableName)); } - await packageConverter.EnsureDeprecatedFilesAndSdkAsync(channelSDKs.GameChannelSDKs.SingleOrDefault(), deprecatedFileConfigs.DeprecatedFileConfigurations.SingleOrDefault(), gameFolder).ConfigureAwait(false); + await packageConverter.EnsureDeprecatedFilesAndSdkAsync(packageConverterContext).ConfigureAwait(false); return true; } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/IPackageConverter.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/IPackageConverter.cs index 041a30505..ab39e5eda 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/IPackageConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/IPackageConverter.cs @@ -1,16 +1,11 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using Snap.Hutao.Service.Game.Scheme; -using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.ChannelSDK; -using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.DeprecatedFile; -using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Package; - namespace Snap.Hutao.Service.Game.Package; internal interface IPackageConverter { - ValueTask EnsureDeprecatedFilesAndSdkAsync(GameChannelSDK? channelSDK, DeprecatedFilesWrapper? deprecatedFiles, string gameFolder); + ValueTask EnsureDeprecatedFilesAndSdkAsync(PackageConverterContext context); - ValueTask EnsureGameResourceAsync(LaunchScheme targetScheme, GamePackage gamePackage, string gameFolder, IProgress progress); + ValueTask EnsureGameResourceAsync(PackageConverterContext context); } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverterContext.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverterContext.cs new file mode 100644 index 000000000..8f9e6d430 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/PackageConverterContext.cs @@ -0,0 +1,42 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Service.Game.Scheme; +using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Branch; +using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.ChannelSDK; +using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.DeprecatedFile; +using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Package; + +namespace Snap.Hutao.Service.Game.Package; + +internal readonly struct PackageConverterContext +{ + public readonly LaunchScheme Scheme; + public readonly string GameDirectory; + public readonly BranchWrapper? CurrentBranch; + public readonly BranchWrapper? TargetBranch; + public readonly GamePackage? TargetPackage; + public readonly GameChannelSDK? GameChannelSDK; + public readonly DeprecatedFilesWrapper? DeprecatedFiles; + public readonly IProgress Progress; + + public PackageConverterContext(LaunchScheme scheme, string gameDirectory, BranchWrapper currentBranch, BranchWrapper targetBranch, GameChannelSDK? gameChannelSDK, IProgress progress) + { + Scheme = scheme; + GameDirectory = gameDirectory; + CurrentBranch = currentBranch; + TargetBranch = targetBranch; + GameChannelSDK = gameChannelSDK; + Progress = progress; + } + + public PackageConverterContext(LaunchScheme scheme, string gameDirectory, GamePackage gamePackage, GameChannelSDK? gameChannelSDK, DeprecatedFilesWrapper? deprecatedFiles, IProgress progress) + { + Scheme = scheme; + GameDirectory = gameDirectory; + TargetPackage = gamePackage; + GameChannelSDK = gameChannelSDK; + DeprecatedFiles = deprecatedFiles; + Progress = progress; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/ScatteredFilesPackageConverter.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/ScatteredFilesPackageConverter.cs index 7733c2289..5c231b843 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/ScatteredFilesPackageConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Package/ScatteredFilesPackageConverter.cs @@ -7,10 +7,7 @@ using Snap.Hutao.Core.IO; using Snap.Hutao.Core.IO.Hashing; using Snap.Hutao.Core.IO.Http.Sharding; -using Snap.Hutao.Service.Game.Scheme; -using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.ChannelSDK; using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.DeprecatedFile; -using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Package; using System.Globalization; using System.IO; using System.IO.Compression; @@ -33,7 +30,7 @@ internal sealed partial class ScatteredFilesPackageConverter : IPackageConverter private readonly JsonSerializerOptions options; private readonly HttpClient httpClient; - public async ValueTask EnsureGameResourceAsync(LaunchScheme targetScheme, GamePackage gamePackage, string gameFolder, IProgress progress) + public async ValueTask EnsureGameResourceAsync(PackageConverterContext context) { // 以 国服 -> 国际服 为例 // 1. 下载国际服的 pkg_version 文件,转换为索引字典 @@ -55,51 +52,53 @@ public async ValueTask EnsureGameResourceAsync(LaunchScheme targetScheme, // 替换操作等于 先备份国服文件,随后新增国际服文件 // 准备下载链接 - string scatteredFilesUrl = gamePackage.Main.Major.ResourceListUrl; + ArgumentNullException.ThrowIfNull(context.TargetPackage); + + string scatteredFilesUrl = context.TargetPackage.Main.Major.ResourceListUrl; string pkgVersionUrl = $"{scatteredFilesUrl}/{PackageVersion}"; - PackageConverterFileSystemContext context = new(targetScheme.IsOversea, HutaoRuntime.GetDataFolderServerCacheFolder(), gameFolder, scatteredFilesUrl); + PackageConverterFileSystemContext fileSystemContext = new(context.Scheme.IsOversea, HutaoRuntime.GetDataFolderServerCacheFolder(), context.GameDirectory, scatteredFilesUrl); // Step 1 - progress.Report(new(SH.ServiceGamePackageRequestPackageVerion)); + context.Progress.Report(new(SH.ServiceGamePackageRequestPackageVerion)); RelativePathVersionItemDictionary remoteItems = await GetRemoteItemsAsync(pkgVersionUrl).ConfigureAwait(false); - RelativePathVersionItemDictionary localItems = await GetLocalItemsAsync(gameFolder).ConfigureAwait(false); + RelativePathVersionItemDictionary localItems = await GetLocalItemsAsync(context.GameDirectory).ConfigureAwait(false); // Step 2 List diffOperations = GetItemOperationInfos(remoteItems, localItems).ToList(); diffOperations.SortBy(i => i.Kind); // Step 3 - await PrepareCacheFilesAsync(diffOperations, context, progress).ConfigureAwait(false); + await PrepareCacheFilesAsync(diffOperations, fileSystemContext, context.Progress).ConfigureAwait(false); // Step 4 - return await ReplaceGameResourceAsync(diffOperations, context, progress).ConfigureAwait(false); + return await ReplaceGameResourceAsync(diffOperations, fileSystemContext, context.Progress).ConfigureAwait(false); } - public async ValueTask EnsureDeprecatedFilesAndSdkAsync(GameChannelSDK? channelSDK, DeprecatedFilesWrapper? deprecatedFiles, string gameFolder) + public async ValueTask EnsureDeprecatedFilesAndSdkAsync(PackageConverterContext context) { // Just try to delete these files, always download from server when needed - FileOperation.Delete(Path.Combine(gameFolder, YuanShenData, "Plugins\\PCGameSDK.dll")); - FileOperation.Delete(Path.Combine(gameFolder, GenshinImpactData, "Plugins\\PCGameSDK.dll")); - FileOperation.Delete(Path.Combine(gameFolder, YuanShenData, "Plugins\\EOSSDK-Win64-Shipping.dll")); - FileOperation.Delete(Path.Combine(gameFolder, GenshinImpactData, "Plugins\\EOSSDK-Win64-Shipping.dll")); - FileOperation.Delete(Path.Combine(gameFolder, YuanShenData, "Plugins\\PluginEOSSDK.dll")); - FileOperation.Delete(Path.Combine(gameFolder, GenshinImpactData, "Plugins\\PluginEOSSDK.dll")); - FileOperation.Delete(Path.Combine(gameFolder, "sdk_pkg_version")); - - if (channelSDK is not null) + FileOperation.Delete(Path.Combine(context.GameDirectory, YuanShenData, "Plugins\\PCGameSDK.dll")); + FileOperation.Delete(Path.Combine(context.GameDirectory, GenshinImpactData, "Plugins\\PCGameSDK.dll")); + FileOperation.Delete(Path.Combine(context.GameDirectory, YuanShenData, "Plugins\\EOSSDK-Win64-Shipping.dll")); + FileOperation.Delete(Path.Combine(context.GameDirectory, GenshinImpactData, "Plugins\\EOSSDK-Win64-Shipping.dll")); + FileOperation.Delete(Path.Combine(context.GameDirectory, YuanShenData, "Plugins\\PluginEOSSDK.dll")); + FileOperation.Delete(Path.Combine(context.GameDirectory, GenshinImpactData, "Plugins\\PluginEOSSDK.dll")); + FileOperation.Delete(Path.Combine(context.GameDirectory, "sdk_pkg_version")); + + if (context.GameChannelSDK is not null) { - using (Stream sdkWebStream = await httpClient.GetStreamAsync(channelSDK.ChannelSdkPackage.Url).ConfigureAwait(false)) + using (Stream sdkWebStream = await httpClient.GetStreamAsync(context.GameChannelSDK.ChannelSdkPackage.Url).ConfigureAwait(false)) { - ZipFile.ExtractToDirectory(sdkWebStream, gameFolder, true); + ZipFile.ExtractToDirectory(sdkWebStream, context.GameDirectory, true); } } - if (deprecatedFiles is not null) + if (context.DeprecatedFiles is not null) { - foreach (DeprecatedFile file in deprecatedFiles.DeprecatedFiles) + foreach (DeprecatedFile file in context.DeprecatedFiles.DeprecatedFiles) { - string filePath = Path.Combine(gameFolder, file.Name); + string filePath = Path.Combine(context.GameDirectory, file.Name); FileOperation.Move(filePath, $"{filePath}.backup", true); } } From f053859492e254446840cd8631bea34fda94ba34 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Tue, 22 Oct 2024 09:03:44 +0800 Subject: [PATCH 17/99] check if game is running when refresh gachalog with web cache --- src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx | 3 +++ .../GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx index 88dd962e8..eaba9ae89 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx @@ -929,6 +929,9 @@ 未找到可用的 Url + + 游戏正在运行中,关闭游戏后重试 + 提供的 Url 无效 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs index 0b7b1192d..1f3eae5e6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs @@ -45,7 +45,6 @@ public static string GetCacheFile(string path) return string.Empty; } - /// public async ValueTask> GetQueryAsync() { (bool isOk, string path) = await gameService.GetGamePathAsync().ConfigureAwait(false); @@ -55,6 +54,11 @@ public async ValueTask> GetQueryAsync() return new(false, GachaLogQuery.Invalid(SH.ServiceGachaLogUrlProviderCachePathInvalid)); } + if (gameService.IsGameRunning()) + { + return new(false, GachaLogQuery.Invalid(SH.ServiceGachaLogUrlProviderGameIsRunning)); + } + string cacheFile = GetCacheFile(path); if (!File.Exists(cacheFile)) { From 0f457fa380b01ca23fa57eb8d08a1cc7fa9da447 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Tue, 22 Oct 2024 09:12:10 +0800 Subject: [PATCH 18/99] fix qa#38 --- src/Snap.Hutao/Snap.Hutao/ViewModel/TitleViewModel.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/TitleViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/TitleViewModel.cs index 54b7e4b85..adb759829 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/TitleViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/TitleViewModel.cs @@ -117,6 +117,11 @@ private async ValueTask DoCheckUpdateAsync() } } + if (currentXamlWindowReference.Window is null) + { + return; + } + if (checkUpdateResult.Kind is CheckUpdateResultKind.NeedInstall) { ContentDialogResult installUpdateUserConsentResult = await contentDialogFactory From fadec07689c06c5374d37c340b815f5ca739651c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 07:56:08 +0000 Subject: [PATCH 19/99] Bump Snap.Hutao.SourceGeneration Bumps the packages group in /src/Snap.Hutao with 1 update: [Snap.Hutao.SourceGeneration](https://github.com/DGP-Studio/Snap.Hutao.SourceGeneration). Updates `Snap.Hutao.SourceGeneration` from 1.1.24 to 1.1.25 - [Commits](https://github.com/DGP-Studio/Snap.Hutao.SourceGeneration/commits) --- updated-dependencies: - dependency-name: Snap.Hutao.SourceGeneration dependency-type: direct:production update-type: version-update:semver-patch dependency-group: packages ... Signed-off-by: dependabot[bot] --- src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index 1194b211d..5c48a7cfc 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -352,7 +352,7 @@ all runtime; build; native; contentfiles; analyzers - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 03b09e4e85abb299c3c81d4f05f7a7e39cb2a781 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Tue, 22 Oct 2024 16:40:09 +0800 Subject: [PATCH 20/99] update issue template --- .github/ISSUE_TEMPLATE/CHS-bug-report.yml | 3 ++- .github/ISSUE_TEMPLATE/CHS-feature-request.yml | 3 ++- .github/ISSUE_TEMPLATE/CHS-network-issue.yml | 1 + .github/ISSUE_TEMPLATE/ENG-bug-report.yml | 3 ++- .github/ISSUE_TEMPLATE/ENG-feature-request.yml | 3 ++- .github/ISSUE_TEMPLATE/ENG-network-issue.yml | 1 + 6 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/CHS-bug-report.yml b/.github/ISSUE_TEMPLATE/CHS-bug-report.yml index 0123844f4..b2165ac40 100644 --- a/.github/ISSUE_TEMPLATE/CHS-bug-report.yml +++ b/.github/ISSUE_TEMPLATE/CHS-bug-report.yml @@ -1,7 +1,8 @@ name: 问题反馈 description: 通过这个议题向开发团队反馈你发现的程序中的问题 title: "[Bug]: 在这里填写一个合适的标题" -labels: ["BUG", "priority:none"] +type: "Bug" +labels: ["priority:none"] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/CHS-feature-request.yml b/.github/ISSUE_TEMPLATE/CHS-feature-request.yml index 6c443b0a2..06ba93500 100644 --- a/.github/ISSUE_TEMPLATE/CHS-feature-request.yml +++ b/.github/ISSUE_TEMPLATE/CHS-feature-request.yml @@ -1,7 +1,8 @@ name: 功能请求 description: 通过这个议题来向开发团队分享你的想法 title: "[Feat]: 在这里填写一个合适的标题" -labels: ["feature request", "needs-triage", "priority:none"] +type: "Feature" +labels: ["needs-triage", "priority:none"] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/CHS-network-issue.yml b/.github/ISSUE_TEMPLATE/CHS-network-issue.yml index 8576da0f3..cbb96bf03 100644 --- a/.github/ISSUE_TEMPLATE/CHS-network-issue.yml +++ b/.github/ISSUE_TEMPLATE/CHS-network-issue.yml @@ -1,6 +1,7 @@ name: 网络问题 description: 通过这个议题来反馈网络问题 title: "[Network]: 在这里填写一个合适的标题" +type: "Bug" labels: ["area-Network"] assignees: - Lightczx diff --git a/.github/ISSUE_TEMPLATE/ENG-bug-report.yml b/.github/ISSUE_TEMPLATE/ENG-bug-report.yml index 3576e416b..68ad9d120 100644 --- a/.github/ISSUE_TEMPLATE/ENG-bug-report.yml +++ b/.github/ISSUE_TEMPLATE/ENG-bug-report.yml @@ -1,7 +1,8 @@ name: BUG Report [English Form] description: Tell us what issue you get title: "[ENG][Bug]: Place your Issue Title Here" -labels: ["BUG", "priority:none"] +type: "Bug" +labels: ["priority:none"] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/ENG-feature-request.yml b/.github/ISSUE_TEMPLATE/ENG-feature-request.yml index 591e9cc7b..e7ebcae60 100644 --- a/.github/ISSUE_TEMPLATE/ENG-feature-request.yml +++ b/.github/ISSUE_TEMPLATE/ENG-feature-request.yml @@ -1,7 +1,8 @@ name: Feature Request [English Form] description: Tell us about your thought title: "[Feat]: Place your title here" -labels: ["feature request", "needs-triage", "priority:none"] +type: "Feature" +labels: ["needs-triage", "priority:none"] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/ENG-network-issue.yml b/.github/ISSUE_TEMPLATE/ENG-network-issue.yml index 5d46323aa..13d491f05 100644 --- a/.github/ISSUE_TEMPLATE/ENG-network-issue.yml +++ b/.github/ISSUE_TEMPLATE/ENG-network-issue.yml @@ -1,6 +1,7 @@ name: Network Issue [English Form] description: Submit this issue form when network issue affect your client experience title: "[Network]: Place your title here" +type: "Bug" labels: ["area-Network"] assignees: - Lightczx From 7f89e7e3651a74961639b757a57448ed019890db Mon Sep 17 00:00:00 2001 From: Masterain Date: Sun, 20 Oct 2024 16:45:56 -0700 Subject: [PATCH 21/99] Update CI/CD --- .github/workflows/alpha.yml | 18 ++++++++++++++++++ appveyor.yml | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/.github/workflows/alpha.yml b/.github/workflows/alpha.yml index e7a98c85a..5d6ba8da4 100644 --- a/.github/workflows/alpha.yml +++ b/.github/workflows/alpha.yml @@ -99,3 +99,21 @@ jobs: " echo $summary >> $Env:GITHUB_STEP_SUMMARY + + - name: Clean up + run: | + Write-Host "Cleaning up NuGet cache..." + Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages" + Write-Host "NuGet cache cleaned." + + Write-Host "Cleaning up .NET install folder..." + Remove-Item -Recurse -Force "C:\Users\Public\Documents\dotnet_install" + Write-Host ".NET install folder cleaned." + + Write-Host "Cleaning up AppVeyor user's local cache..." + Remove-Item -Recurse -Force "C:\Users\appveyor\AppData\Local" + Write-Host "AppVeyor user's local cache cleaned." + + Write-Host "Cleaning up Administrator user's local cache..." + Remove-Item -Recurse -Force "C:\Users\Administrator\AppData\Local" + Write-Host "Administrator user's local cache cleaned." diff --git a/appveyor.yml b/appveyor.yml index afe74bc29..7ca80e45b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,6 +4,8 @@ branches: - "release" build_cloud: HUTAO-ACTIONS image: Visual Studio 2022 +cache: + - 'C:\Users\Public\Documents\dotnet_install\.nuget\packages' clone_depth: 3 clone_folder: C:\Users\Public\appveyor\Snap.Hutao install: @@ -18,3 +20,20 @@ deploy: url: https://app.signpath.io/API/v1/7a941fa3-64d8-4c45-bd03-92a02bcd4964/Integrations/AppVeyor?ProjectSlug=Snap.Hutao&SigningPolicySlug=release-signing&ArtifactConfigurationSlug=msix authorization: secure: j8srQ5/UYWhI+jlm3Vo3D3QfXoRyQ9hOn3ynJGtwusKui4+uDi4gykdUFYCITZxK+C/fOCAZNJ+YaKSm/OaiXw== +on_finish: +- pwsh: | + Write-Host "Cleaning up NuGet cache..." + Remove-Item -Recurse -Force "$env:LOCALAPPDATA\NuGet\v3-cache" + Write-Host "NuGet cache cleaned." + + Write-Host "Cleaning up .NET install folder..." + Remove-Item -Recurse -Force "C:\Users\Public\Documents\dotnet_install" + Write-Host ".NET install folder cleaned." + + Write-Host "Cleaning up AppVeyor user's local cache..." + Remove-Item -Recurse -Force "C:\Users\appveyor\AppData\Local" + Write-Host "AppVeyor user's local cache cleaned." + + Write-Host "Cleaning up Administrator user's local cache..." + Remove-Item -Recurse -Force "C:\Users\Administrator\AppData\Local" + Write-Host "Administrator user's local cache cleaned." \ No newline at end of file From 56aecb1ad0d2a1453f6923df2d6bedb1ed344ba9 Mon Sep 17 00:00:00 2001 From: Masterain Date: Sun, 20 Oct 2024 20:36:34 -0700 Subject: [PATCH 22/99] Update CI/CD --- .github/workflows/alpha.yml | 8 -------- appveyor.yml | 8 -------- 2 files changed, 16 deletions(-) diff --git a/.github/workflows/alpha.yml b/.github/workflows/alpha.yml index 5d6ba8da4..f2b7fc3bf 100644 --- a/.github/workflows/alpha.yml +++ b/.github/workflows/alpha.yml @@ -109,11 +109,3 @@ jobs: Write-Host "Cleaning up .NET install folder..." Remove-Item -Recurse -Force "C:\Users\Public\Documents\dotnet_install" Write-Host ".NET install folder cleaned." - - Write-Host "Cleaning up AppVeyor user's local cache..." - Remove-Item -Recurse -Force "C:\Users\appveyor\AppData\Local" - Write-Host "AppVeyor user's local cache cleaned." - - Write-Host "Cleaning up Administrator user's local cache..." - Remove-Item -Recurse -Force "C:\Users\Administrator\AppData\Local" - Write-Host "Administrator user's local cache cleaned." diff --git a/appveyor.yml b/appveyor.yml index 7ca80e45b..4bb093f9e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -29,11 +29,3 @@ on_finish: Write-Host "Cleaning up .NET install folder..." Remove-Item -Recurse -Force "C:\Users\Public\Documents\dotnet_install" Write-Host ".NET install folder cleaned." - - Write-Host "Cleaning up AppVeyor user's local cache..." - Remove-Item -Recurse -Force "C:\Users\appveyor\AppData\Local" - Write-Host "AppVeyor user's local cache cleaned." - - Write-Host "Cleaning up Administrator user's local cache..." - Remove-Item -Recurse -Force "C:\Users\Administrator\AppData\Local" - Write-Host "Administrator user's local cache cleaned." \ No newline at end of file From 0fca02bb69e6325704e25f59a56dc0d98cb06f12 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Wed, 23 Oct 2024 13:55:42 +0800 Subject: [PATCH 23/99] Test Remove Open Team Progress --- .../UnlockerIslandFunctionOffsetTest.cs | 16 ++++++-- .../Snap.Hutao/Core/Caching/ImageCache.cs | 8 ++-- .../Model/Entity/SettingEntry.Constant.cs | 2 + .../BackgroundImage/BackgroundImageService.cs | 41 ++++++++++++------- .../Snap.Hutao/Service/Game/LaunchOptions.cs | 14 +++++++ .../Service/Game/Unlocker/GameFpsUnlocker.cs | 8 +++- .../Game/Unlocker/Island/IslandEnvironment.cs | 4 ++ .../Unlocker/Island/IslandEnvironmentView.cs | 4 ++ .../Unlocker/Island/IslandFunctionOffsets.cs | 4 ++ src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj | 4 +- 10 files changed, 80 insertions(+), 25 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao.Test/IncomingFeature/UnlockerIslandFunctionOffsetTest.cs b/src/Snap.Hutao/Snap.Hutao.Test/IncomingFeature/UnlockerIslandFunctionOffsetTest.cs index 1f7c08a6b..09b232e9e 100644 --- a/src/Snap.Hutao/Snap.Hutao.Test/IncomingFeature/UnlockerIslandFunctionOffsetTest.cs +++ b/src/Snap.Hutao/Snap.Hutao.Test/IncomingFeature/UnlockerIslandFunctionOffsetTest.cs @@ -14,9 +14,11 @@ public class UnlockerIslandFunctionOffsetTest [TestMethod] public void GenerateJson() { - // public void set_fieldOfView(float value) -> jmp xxxxxxxx - // public static void set_targetFrameRate(int value) -> jmp xxxxxxxxx (to the end) - // public static void set_enableFogRendering(bool value) -> jmp xxxxxxxxx (to the end) + // FunctionOffsetSetFieldOfView: public void set_fieldOfView(float value) -> jmp xxxxxxxx + // FunctionOffsetSetTargetFrameRate: public static void set_targetFrameRate(int value) -> jmp xxxxxxxxx (to the end) + // FunctionOffsetSetEnableFogRendering: public static void set_enableFogRendering(bool value) -> jmp xxxxxxxxx (to the end) + // FunctionOffsetOpenTeam: public static void AJODMEAHOGI() + // FunctionOffsetOpenTeamPageAccordingly: public static void OEEFGJDOCJJ(bool KCBOKOCOGEI = true) UnlockerIslandConfigurationWrapper wrapper = new() { @@ -25,12 +27,16 @@ public void GenerateJson() FunctionOffsetSetFieldOfView = 0x01136D30, FunctionOffsetSetTargetFrameRate = 0x0131E600, FunctionOffsetSetEnableFogRendering = 0x015DC790, + FunctionOffsetOpenTeam = 0x07806530, + FunctionOffsetOpenTeamPageAccordingly = 0x0781D3F0, }, Oversea = new() { FunctionOffsetSetFieldOfView = 0x01136F30, FunctionOffsetSetTargetFrameRate = 0x0131E800, FunctionOffsetSetEnableFogRendering = 0x015DC990, + FunctionOffsetOpenTeam = 0x0777E4F0, + FunctionOffsetOpenTeamPageAccordingly = 0x07779870, }, }; @@ -51,5 +57,9 @@ private sealed class UnlockerIslandConfiguration public required uint FunctionOffsetSetTargetFrameRate { get; set; } public required uint FunctionOffsetSetEnableFogRendering { get; set; } + + public required uint FunctionOffsetOpenTeam { get; set; } + + public required uint FunctionOffsetOpenTeamPageAccordingly { get; set; } } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs index db9b5b647..9ee82397f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs @@ -77,7 +77,7 @@ public async ValueTask GetFileFromCacheAsync(Uri uri, ElementTheme th // If the file already exists, we don't need to download it again if (!IsFileInvalid(defaultFilePath)) { - await ConvertToMonoChromeAndSaveFileAsync(defaultFilePath, themeOrDefaultFilePath, theme).ConfigureAwait(false); + await TryConvertToMonoChromeAndSaveFileAsync(defaultFilePath, themeOrDefaultFilePath, theme).ConfigureAwait(false); return themeOrDefaultFilePath; } @@ -86,7 +86,7 @@ public async ValueTask GetFileFromCacheAsync(Uri uri, ElementTheme th // File may be downloaded by another thread if (!IsFileInvalid(defaultFilePath)) { - await ConvertToMonoChromeAndSaveFileAsync(defaultFilePath, themeOrDefaultFilePath, theme).ConfigureAwait(false); + await TryConvertToMonoChromeAndSaveFileAsync(defaultFilePath, themeOrDefaultFilePath, theme).ConfigureAwait(false); return themeOrDefaultFilePath; } @@ -122,9 +122,9 @@ private static bool IsFileInvalid(string file, bool treatNullFileAsInvalid = tru return new FileInfo(file).Length == 0; } - private static async ValueTask ConvertToMonoChromeAndSaveFileAsync(string sourceFile, string themeFile, ElementTheme theme) + private static async ValueTask TryConvertToMonoChromeAndSaveFileAsync(string sourceFile, string themeFile, ElementTheme theme) { - if (string.Equals(sourceFile, themeFile, StringComparison.OrdinalIgnoreCase)) + if (theme is ElementTheme.Default || string.Equals(sourceFile, themeFile, StringComparison.OrdinalIgnoreCase)) { return; } diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/SettingEntry.Constant.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/SettingEntry.Constant.cs index 14ea795b7..50c9d11d5 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/SettingEntry.Constant.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/SettingEntry.Constant.cs @@ -48,7 +48,9 @@ internal sealed partial class SettingEntry public const string LaunchUnlockFps = "Launch.UnlockFps"; public const string LaunchTargetFps = "Launch.TargetFps"; public const string LaunchTargetFov = "Launch.TargetFov"; + public const string LaunchFixLowFovScene = "Launch.FixLowFovScene"; public const string LaunchDisableFog = "Launch.DisableFog"; + public const string LaunchRemoveOpenTeamProgress = "Launch.RemoveOpenTeamProgress"; public const string LaunchLoopAdjustFpsOnly = "Launch.LoopAdjustFpsOnly"; public const string LaunchMonitor = "Launch.Monitor"; public const string LaunchIsMonitorEnabled = "Launch.IsMonitorEnabled"; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/BackgroundImage/BackgroundImageService.cs b/src/Snap.Hutao/Snap.Hutao/Service/BackgroundImage/BackgroundImageService.cs index 2ef3c4074..7ba7d21f4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/BackgroundImage/BackgroundImageService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/BackgroundImage/BackgroundImageService.cs @@ -10,6 +10,7 @@ using Snap.Hutao.Web.Response; using Snap.Hutao.Win32.Foundation; using System.Collections.Frozen; +using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using Windows.Graphics.Imaging; @@ -27,25 +28,32 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService private readonly ITaskContext taskContext; private readonly AppOptions appOptions; - private HashSet? currentBackgroundPathSet; + private HashSet? availableBackgroundPathSet; public async ValueTask> GetNextBackgroundImageAsync(BackgroundImage? previous, CancellationToken token = default) { - HashSet backgroundSet = await SkipOrInitBackgroundAsync(token).ConfigureAwait(false); + // The availableBackgroundSet will be empty if BackgroundImageType is None + // backgroundImageOptions.Wallpaper will also be set in this method if web wallpaper type is selected + HashSet availableBackgroundSet = await SkipOrInitAvailableBackgroundAsync(token).ConfigureAwait(false); - if (backgroundSet.Count <= 0) + if (availableBackgroundSet.Count <= 0) { return new(true, default!); } - string path = System.Random.Shared.GetItems([.. backgroundSet], 1)[0]; - backgroundSet.Remove(path); + string path = System.Random.Shared.GetItems([.. availableBackgroundSet], 1)[0]; + availableBackgroundSet.Remove(path); if (string.Equals(path, previous?.Path, StringComparison.OrdinalIgnoreCase)) { return new(false, default!); } + if (!File.Exists(path)) + { + Debugger.Break(); + } + using (FileStream fileStream = File.OpenRead(path)) { BitmapDecoder decoder; @@ -80,17 +88,17 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService } } - private async ValueTask> SkipOrInitBackgroundAsync(CancellationToken token = default) + private async ValueTask> SkipOrInitAvailableBackgroundAsync(CancellationToken token = default) { switch (appOptions.BackgroundImageType) { case BackgroundImageType.LocalFolder: { - if (currentBackgroundPathSet is not { Count: > 0 }) + if (availableBackgroundPathSet is not { Count: > 0 }) { string backgroundFolder = HutaoRuntime.GetDataFolderBackgroundFolder(); - currentBackgroundPathSet = Directory + availableBackgroundPathSet = Directory .EnumerateFiles(backgroundFolder, "*", SearchOption.AllDirectories) .Where(path => AllowedFormats.Contains(Path.GetExtension(path))) .ToHashSet(); @@ -101,20 +109,20 @@ private async ValueTask> SkipOrInitBackgroundAsync(CancellationT } case BackgroundImageType.HutaoBing: - await SetCurrentBackgroundPathSetAsync((client, token) => client.GetBingWallpaperAsync(token), token).ConfigureAwait(false); + await SetCurrentBackgroundPathSetAsync(static (client, token) => client.GetBingWallpaperAsync(token), token).ConfigureAwait(false); break; case BackgroundImageType.HutaoDaily: - await SetCurrentBackgroundPathSetAsync((client, token) => client.GetTodayWallpaperAsync(token), token).ConfigureAwait(false); + await SetCurrentBackgroundPathSetAsync(static (client, token) => client.GetTodayWallpaperAsync(token), token).ConfigureAwait(false); break; case BackgroundImageType.HutaoOfficialLauncher: - await SetCurrentBackgroundPathSetAsync((client, token) => client.GetLauncherWallpaperAsync(token), token).ConfigureAwait(false); + await SetCurrentBackgroundPathSetAsync(static (client, token) => client.GetLauncherWallpaperAsync(token), token).ConfigureAwait(false); break; default: - currentBackgroundPathSet = []; + availableBackgroundPathSet = []; break; } - return currentBackgroundPathSet ??= []; + return availableBackgroundPathSet ??= []; async Task SetCurrentBackgroundPathSetAsync(Func>> responseFactory, CancellationToken token = default) { @@ -125,7 +133,12 @@ async Task SetCurrentBackgroundPathSetAsync(Func().GetFileFromCacheAsync(url).ConfigureAwait(false); - currentBackgroundPathSet = [file]; + if (!File.Exists(file)) + { + Debugger.Break(); + } + + availableBackgroundPathSet = [file]; } await taskContext.SwitchToMainThreadAsync(); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs index 6cd2396f3..3e60d1822 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs @@ -38,7 +38,9 @@ internal sealed partial class LaunchOptions : DbStoreOptions private bool? unlockFps; private int? targetFps; private float? targetFov; + private bool? fixLowFovScene; private bool? disableFog; + private bool? removeOpenTeamProgress; private bool? loopAdjustFpsOnly; private NameValue? monitor; private bool? isMonitorEnabled; @@ -246,6 +248,12 @@ public float TargetFov set => SetOption(ref targetFov, SettingEntry.LaunchTargetFov, value); } + public bool FixLowFovScene + { + get => GetOption(ref fixLowFovScene, SettingEntry.LaunchFixLowFovScene, true); + set => SetOption(ref fixLowFovScene, SettingEntry.LaunchFixLowFovScene, value); + } + public bool DisableFog { get => GetOption(ref disableFog, SettingEntry.LaunchDisableFog, false); @@ -258,6 +266,12 @@ public bool LoopAdjustFpsOnly set => SetOption(ref loopAdjustFpsOnly, SettingEntry.LaunchLoopAdjustFpsOnly, value); } + public bool RemoveOpenTeamProgress + { + get => GetOption(ref removeOpenTeamProgress, SettingEntry.LaunchRemoveOpenTeamProgress, false); + set => SetOption(ref removeOpenTeamProgress, SettingEntry.LaunchRemoveOpenTeamProgress, value); + } + [NotNull] public NameValue? Monitor { diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs index 7932c633b..42942fde6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs @@ -97,7 +97,7 @@ public async ValueTask PostUnlockAsync(CancellationToken token = default) if (view.State is IslandState.None or IslandState.Stopped) { - if (Interlocked.Increment(ref accumulatedBadStateCount) >= 5) + if (Interlocked.Increment(ref accumulatedBadStateCount) >= 10) { HutaoException.Throw($"UnlockerIsland in bad state for too long, last state: {view.State}"); } @@ -121,8 +121,10 @@ private static unsafe void InitializeIslandEnvironment(nint handle, IslandFuncti { IslandEnvironment* pIslandEnvironment = (IslandEnvironment*)handle; pIslandEnvironment->FunctionOffsetSetFieldOfView = offsets.FunctionOffsetSetFieldOfView; - pIslandEnvironment->FunctionOffsetSetTargetFrameRate = offsets.FunctionOffsetSetTargetFrameRate; pIslandEnvironment->FunctionOffsetSetEnableFogRendering = offsets.FunctionOffsetSetEnableFogRendering; + pIslandEnvironment->FunctionOffsetSetTargetFrameRate = offsets.FunctionOffsetSetTargetFrameRate; + pIslandEnvironment->FunctionOffsetOpenTeam = offsets.FunctionOffsetOpenTeam; + pIslandEnvironment->FunctionOffsetOpenTeamPageAccordingly = offsets.FunctionOffsetOpenTeamPageAccordingly; pIslandEnvironment->LoopAdjustFpsOnly = options.LoopAdjustFpsOnly; @@ -133,8 +135,10 @@ private static unsafe IslandEnvironmentView UpdateIslandEnvironment(nint handle, { IslandEnvironment* pIslandEnvironment = (IslandEnvironment*)handle; pIslandEnvironment->FieldOfView = options.TargetFov; + pIslandEnvironment->FixLowFovScene = options.FixLowFovScene; pIslandEnvironment->TargetFrameRate = options.TargetFps; pIslandEnvironment->DisableFog = options.DisableFog; + pIslandEnvironment->RemoveOpenTeamProgress = true || options.RemoveOpenTeamProgress; return *(IslandEnvironmentView*)pIslandEnvironment; } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironment.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironment.cs index d52917a59..5f4006ca1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironment.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironment.cs @@ -13,11 +13,15 @@ internal struct IslandEnvironment public float FieldOfView; public int TargetFrameRate; public bool DisableFog; + public bool FixLowFovScene; + public bool RemoveOpenTeamProgress; public bool LoopAdjustFpsOnly; public uint FunctionOffsetSetFieldOfView; public uint FunctionOffsetSetEnableFogRendering; public uint FunctionOffsetSetTargetFrameRate; + public uint FunctionOffsetOpenTeam; + public uint FunctionOffsetOpenTeamPageAccordingly; public float DebugOriginalFieldOfView; } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironmentView.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironmentView.cs index 8f39600db..c78256542 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironmentView.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironmentView.cs @@ -13,11 +13,15 @@ internal struct IslandEnvironmentView public float FieldOfView; public int TargetFrameRate; public bool DisableFog; + public bool FixLowFovScene; + public bool RemoveOpenTeamProgress; public bool LoopAdjustFpsOnly; public uint FunctionOffsetSetFieldOfView; public uint FunctionOffsetSetEnableFogRendering; public uint FunctionOffsetSetTargetFrameRate; + public uint FunctionOffsetOpenTeam; + public uint FunctionOffsetOpenTeamPageAccordingly; public float DebugOriginalFieldOfView; } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandFunctionOffsets.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandFunctionOffsets.cs index eee03fc2b..509962bbf 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandFunctionOffsets.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandFunctionOffsets.cs @@ -10,4 +10,8 @@ internal sealed class IslandFunctionOffsets public required uint FunctionOffsetSetEnableFogRendering { get; set; } public required uint FunctionOffsetSetTargetFrameRate { get; set; } + + public required uint FunctionOffsetOpenTeam { get; set; } + + public required uint FunctionOffsetOpenTeamPageAccordingly { get; set; } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index 5c48a7cfc..7d1886f91 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -318,7 +318,7 @@ - + @@ -356,7 +356,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 8c09ba489b8461bde4a8128e55890d1a14069295 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Wed, 23 Oct 2024 14:29:39 +0800 Subject: [PATCH 24/99] debug write back open team count --- .../Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs | 2 +- .../Service/Game/Unlocker/Island/IslandEnvironment.cs | 1 + .../Service/Game/Unlocker/Island/IslandEnvironmentView.cs | 1 + src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs index 42942fde6..8a6666149 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/GameFpsUnlocker.cs @@ -93,7 +93,7 @@ public async ValueTask PostUnlockAsync(CancellationToken token = default) } IslandEnvironmentView view = UpdateIslandEnvironment(handle, launchOptions); - context.Logger.LogDebug("Island Environment|{State}|{Error}|{Value}", view.State, view.LastError, view.DebugOriginalFieldOfView); + context.Logger.LogDebug("Island Environment|{State}|{Error}|Fov:{Value1}|Team: {Value2}", view.State, view.LastError, view.DebugOriginalFieldOfView, view.DebugOpenTeamCount); if (view.State is IslandState.None or IslandState.Stopped) { diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironment.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironment.cs index 5f4006ca1..389d24827 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironment.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironment.cs @@ -24,4 +24,5 @@ internal struct IslandEnvironment public uint FunctionOffsetOpenTeamPageAccordingly; public float DebugOriginalFieldOfView; + public int DebugOpenTeamCount; } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironmentView.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironmentView.cs index c78256542..afba684f6 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironmentView.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Unlocker/Island/IslandEnvironmentView.cs @@ -24,4 +24,5 @@ internal struct IslandEnvironmentView public uint FunctionOffsetOpenTeamPageAccordingly; public float DebugOriginalFieldOfView; + public int DebugOpenTeamCount; } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index 7d1886f91..d36524891 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -356,7 +356,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 2e841473b8550fe921591f69af1efa06dc2f3a6e Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Wed, 23 Oct 2024 15:05:15 +0800 Subject: [PATCH 25/99] fix Remove Open Team Progress --- src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index d36524891..6d0b1efb8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -356,7 +356,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 4d681efbc9126acd790f402ec2b2f4090f758e35 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Wed, 23 Oct 2024 16:50:39 +0800 Subject: [PATCH 26/99] fix #2083 --- .../Snap.Hutao/Core/IO/TempFileStream.cs | 14 +++++++++++++- .../Snap.Hutao/Service/Feature/FeatureService.cs | 11 ++--------- .../QueryProvider/GachaLogQueryWebCacheProvider.cs | 4 +++- .../Handler/LaunchExecutionUnlockFpsHandler.cs | 3 ++- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/TempFileStream.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/TempFileStream.cs index bb03d752a..e786b3ddf 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/IO/TempFileStream.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/TempFileStream.cs @@ -11,8 +11,13 @@ internal sealed partial class TempFileStream : Stream private readonly FileStream stream; public TempFileStream(FileMode mode, FileAccess access) + : this(Path.GetTempFileName(), mode, access) { - path = Path.GetTempFileName(); + } + + private TempFileStream(string path, FileMode mode, FileAccess access) + { + this.path = path; stream = File.Open(path, mode, access); } @@ -26,6 +31,13 @@ public TempFileStream(FileMode mode, FileAccess access) public override long Position { get => stream.Position; set => stream.Position = value; } + public static TempFileStream CopyFrom(string file, FileMode mode, FileAccess access) + { + string path = Path.GetTempFileName(); + File.Copy(file, path, true); + return new TempFileStream(path, mode, access); + } + public override void Flush() { stream.Flush(); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Feature/FeatureService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Feature/FeatureService.cs index aad9318a0..934761874 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Feature/FeatureService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Feature/FeatureService.cs @@ -24,15 +24,8 @@ internal sealed partial class FeatureService : IFeatureService IHttpClientFactory httpClientFactory = scope.ServiceProvider.GetRequiredService(); using (HttpClient httpClient = httpClientFactory.CreateClient(nameof(FeatureService))) { - try - { - string url = hutaoEndpointsFactory.Create().Feature($"UnlockerIsland_{tag}"); - return await httpClient.GetFromJsonAsync(url).ConfigureAwait(false); - } - catch - { - return default; - } + string url = hutaoEndpointsFactory.Create().Feature($"UnlockerIsland_{tag}"); + return await httpClient.GetFromJsonAsync(url).ConfigureAwait(false); } } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs index 1f3eae5e6..9e6480595 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs @@ -65,7 +65,9 @@ public async ValueTask> GetQueryAsync() return new(false, GachaLogQuery.Invalid(SH.FormatServiceGachaLogUrlProviderCachePathNotFound(cacheFile))); } - using (FileStream fileStream = File.OpenRead(GetCacheFile(path))) + // Must copy the file to avoid the following exception: + // System.IO.IOException: The process cannot access the file + using (TempFileStream fileStream = TempFileStream.CopyFrom(path, FileMode.Open, FileAccess.Read)) { using (MemoryStream memoryStream = await memoryStreamFactory.GetStreamAsync(fileStream).ConfigureAwait(false)) { diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionUnlockFpsHandler.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionUnlockFpsHandler.cs index 0a8456ce1..a8fba69ee 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionUnlockFpsHandler.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionUnlockFpsHandler.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Snap.Hutao.Core; +using Snap.Hutao.Core.ExceptionService; using Snap.Hutao.Service.Game.Unlocker; namespace Snap.Hutao.Service.Game.Launching.Handler; @@ -35,7 +36,7 @@ public async ValueTask OnExecutionAsync(LaunchExecutionContext context, LaunchEx } else { - context.Logger.LogError("Unlocking FPS failed"); + HutaoException.Throw("下载解锁帧率配置文件失败"); } } catch (Exception ex) From 8221da6999b2bf2e054a3d9ec28275b18795fa7a Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Wed, 23 Oct 2024 17:31:47 +0800 Subject: [PATCH 27/99] disk extents --- .../Snap.Hutao/Core/IO/PhysicalDriver.cs | 16 +++++++++++++++- src/Snap.Hutao/Snap.Hutao/Win32/ConstValues.cs | 1 + .../Snap.Hutao/Win32/Foundation/FlexibleArray.cs | 8 ++++++++ .../Snap.Hutao/Win32/System/Ioctl/DISK_EXTENT.cs | 11 +++++++++++ .../Win32/System/Ioctl/VOLUME_DISK_EXTENTS.cs | 12 ++++++++++++ 5 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Win32/System/Ioctl/DISK_EXTENT.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Win32/System/Ioctl/VOLUME_DISK_EXTENTS.cs diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs index ab1fd5096..bf00e063d 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs @@ -43,7 +43,21 @@ private static unsafe void GetDeviceNumber(string fileName, out uint deviceNumbe STORAGE_DEVICE_NUMBER number = default; if (!DeviceIoControl(hLogicalDriver, IOCTL_STORAGE_GET_DEVICE_NUMBER, default, default, &number, (uint)sizeof(STORAGE_DEVICE_NUMBER), default, default)) { - Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(GetLastError())); + WIN32_ERROR error = GetLastError(); + if (error is not WIN32_ERROR.ERROR_INVALID_FUNCTION) + { + Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error)); + } + + // This logical driver belongs to a partitionable device. + VOLUME_DISK_EXTENTS extents = default; + if (!DeviceIoControl(hLogicalDriver, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, default, default, &extents, (uint)sizeof(VOLUME_DISK_EXTENTS), default, default)) + { + Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(GetLastError())); + } + + ref DISK_EXTENT extent = ref extents.Extents[0]; + deviceNumber = extent.DiskNumber; } deviceNumber = number.DeviceNumber; diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/ConstValues.cs b/src/Snap.Hutao/Snap.Hutao/Win32/ConstValues.cs index 4544330df..a69309ae8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/ConstValues.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/ConstValues.cs @@ -30,5 +30,6 @@ internal static class ConstValues public const uint NIN_POPUPCLOSE = 0x00000407U; public const uint IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x002D1080U; public const uint IOCTL_STORAGE_QUERY_PROPERTY = 0x002D1400U; + public const uint IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = 0x00560000U; public const uint INFINITE = 0xFFFFFFFFU; } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/FlexibleArray.cs b/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/FlexibleArray.cs index 97e163ec0..43b09e6a8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/FlexibleArray.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/FlexibleArray.cs @@ -1,10 +1,18 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using System.Runtime.CompilerServices; + namespace Snap.Hutao.Win32.Foundation; internal unsafe struct FlexibleArray where TElement : unmanaged { public TElement* Reference; + + public ref TElement this[int index] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => ref Reference[index]; + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/System/Ioctl/DISK_EXTENT.cs b/src/Snap.Hutao/Snap.Hutao/Win32/System/Ioctl/DISK_EXTENT.cs new file mode 100644 index 000000000..81e871ef4 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Win32/System/Ioctl/DISK_EXTENT.cs @@ -0,0 +1,11 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Win32.System.Ioctl; + +internal struct DISK_EXTENT +{ + public uint DiskNumber; + public long StartingOffset; + public long ExtentLength; +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/System/Ioctl/VOLUME_DISK_EXTENTS.cs b/src/Snap.Hutao/Snap.Hutao/Win32/System/Ioctl/VOLUME_DISK_EXTENTS.cs new file mode 100644 index 000000000..71d310fa2 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Win32/System/Ioctl/VOLUME_DISK_EXTENTS.cs @@ -0,0 +1,12 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Win32.Foundation; + +namespace Snap.Hutao.Win32.System.Ioctl; + +internal struct VOLUME_DISK_EXTENTS +{ + public uint NumberOfDiskExtents; + public FlexibleArray Extents; +} \ No newline at end of file From 6b519dc284a5c2e201689d882ab133611b227dce Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Wed, 23 Oct 2024 18:24:52 +0800 Subject: [PATCH 28/99] fix disk extents call --- .../Snap.Hutao/Core/IO/PhysicalDriver.cs | 32 ++++++++++++++----- .../GachaLogQueryWebCacheProvider.cs | 5 --- .../Win32/Foundation/FlexibleArray.cs | 7 ++++ 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs index bf00e063d..b06439706 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Core.ExceptionService; using Snap.Hutao.Core.Setting; using Snap.Hutao.Win32.Foundation; using Snap.Hutao.Win32.Storage.FileSystem; @@ -41,26 +42,41 @@ private static unsafe void GetDeviceNumber(string fileName, out uint deviceNumbe { hLogicalDriver = CreateDirectAccessStorageDeviceHandle(fileName); STORAGE_DEVICE_NUMBER number = default; - if (!DeviceIoControl(hLogicalDriver, IOCTL_STORAGE_GET_DEVICE_NUMBER, default, default, &number, (uint)sizeof(STORAGE_DEVICE_NUMBER), default, default)) + if (DeviceIoControl(hLogicalDriver, IOCTL_STORAGE_GET_DEVICE_NUMBER, default, default, &number, (uint)sizeof(STORAGE_DEVICE_NUMBER), default, default)) { - WIN32_ERROR error = GetLastError(); - if (error is not WIN32_ERROR.ERROR_INVALID_FUNCTION) + deviceNumber = number.DeviceNumber; + return; + } + + WIN32_ERROR error = GetLastError(); + if (error is not WIN32_ERROR.ERROR_INVALID_FUNCTION) + { + Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error)); + } + + // This logical driver belongs to a partitionable device. + VOLUME_DISK_EXTENTS extents = default; + extents.Extents = stackalloc DISK_EXTENT[1]; + if (!DeviceIoControl(hLogicalDriver, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, default, default, &extents, (uint)sizeof(VOLUME_DISK_EXTENTS), default, default)) + { + WIN32_ERROR error2 = GetLastError(); + if (error2 is not WIN32_ERROR.ERROR_MORE_DATA) { - Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error)); + Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error2)); } - // This logical driver belongs to a partitionable device. - VOLUME_DISK_EXTENTS extents = default; - if (!DeviceIoControl(hLogicalDriver, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, default, default, &extents, (uint)sizeof(VOLUME_DISK_EXTENTS), default, default)) + extents.Extents = stackalloc DISK_EXTENT[(int)extents.NumberOfDiskExtents]; + if (!DeviceIoControl(hLogicalDriver, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, default, default, &extents, (uint)sizeof(VOLUME_DISK_EXTENTS) + (uint)sizeof(DISK_EXTENT) * extents.NumberOfDiskExtents, default, default)) { Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(GetLastError())); } ref DISK_EXTENT extent = ref extents.Extents[0]; deviceNumber = extent.DiskNumber; + return; } - deviceNumber = number.DeviceNumber; + throw HutaoException.Throw("Failed to get the device number."); } finally { diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs index 9e6480595..dd52f82ae 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/QueryProvider/GachaLogQueryWebCacheProvider.cs @@ -54,11 +54,6 @@ public async ValueTask> GetQueryAsync() return new(false, GachaLogQuery.Invalid(SH.ServiceGachaLogUrlProviderCachePathInvalid)); } - if (gameService.IsGameRunning()) - { - return new(false, GachaLogQuery.Invalid(SH.ServiceGachaLogUrlProviderGameIsRunning)); - } - string cacheFile = GetCacheFile(path); if (!File.Exists(cacheFile)) { diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/FlexibleArray.cs b/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/FlexibleArray.cs index 43b09e6a8..4212b4c1f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/FlexibleArray.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/FlexibleArray.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace Snap.Hutao.Win32.Foundation; @@ -15,4 +16,10 @@ public ref TElement this[int index] [MethodImpl(MethodImplOptions.AggressiveInlining)] get => ref Reference[index]; } + + public static implicit operator FlexibleArray(Span span) + { + void* ptr = Unsafe.AsPointer(ref MemoryMarshal.GetReference(span)); + return *(FlexibleArray*)&ptr; + } } \ No newline at end of file From f42f5423f1b91314135d6eb1cc324fbd7e5272d5 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Wed, 23 Oct 2024 19:36:14 +0800 Subject: [PATCH 29/99] fix disk extents call 2 --- .../Snap.Hutao/Core/IO/PhysicalDriver.cs | 15 +++++++++------ .../Snap.Hutao/Win32/Foundation/FlexibleArray.cs | 10 +++++----- src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs | 8 ++++++++ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs index b06439706..e9f49aa10 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs @@ -55,9 +55,9 @@ private static unsafe void GetDeviceNumber(string fileName, out uint deviceNumbe } // This logical driver belongs to a partitionable device. - VOLUME_DISK_EXTENTS extents = default; - extents.Extents = stackalloc DISK_EXTENT[1]; - if (!DeviceIoControl(hLogicalDriver, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, default, default, &extents, (uint)sizeof(VOLUME_DISK_EXTENTS), default, default)) + int length = sizeof(VOLUME_DISK_EXTENTS) + (sizeof(DISK_EXTENT) * 1); + Span buffer = stackalloc byte[length]; + if (!DeviceIoControl(hLogicalDriver, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, default, default, buffer, default, default)) { WIN32_ERROR error2 = GetLastError(); if (error2 is not WIN32_ERROR.ERROR_MORE_DATA) @@ -65,13 +65,16 @@ private static unsafe void GetDeviceNumber(string fileName, out uint deviceNumbe Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error2)); } - extents.Extents = stackalloc DISK_EXTENT[(int)extents.NumberOfDiskExtents]; - if (!DeviceIoControl(hLogicalDriver, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, default, default, &extents, (uint)sizeof(VOLUME_DISK_EXTENTS) + (uint)sizeof(DISK_EXTENT) * extents.NumberOfDiskExtents, default, default)) + ref VOLUME_DISK_EXTENTS diskExtents = ref MemoryMarshal.AsRef(buffer); + length = sizeof(VOLUME_DISK_EXTENTS) + (sizeof(DISK_EXTENT) * (int)diskExtents.NumberOfDiskExtents); + buffer = stackalloc byte[length]; + if (!DeviceIoControl(hLogicalDriver, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, default, default, buffer, default, default)) { Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(GetLastError())); } - ref DISK_EXTENT extent = ref extents.Extents[0]; + ref VOLUME_DISK_EXTENTS diskExtents2 = ref MemoryMarshal.AsRef(buffer); + ref DISK_EXTENT extent = ref diskExtents2.Extents[0]; deviceNumber = extent.DiskNumber; return; } diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/FlexibleArray.cs b/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/FlexibleArray.cs index 4212b4c1f..3ba7db0b7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/FlexibleArray.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/Foundation/FlexibleArray.cs @@ -9,17 +9,17 @@ namespace Snap.Hutao.Win32.Foundation; internal unsafe struct FlexibleArray where TElement : unmanaged { - public TElement* Reference; + public TElement Data; + [UnscopedRef] public ref TElement this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref Reference[index]; + get => ref Unsafe.Add(ref Data, index); } - public static implicit operator FlexibleArray(Span span) + public Span AsSpan(int length) { - void* ptr = Unsafe.AsPointer(ref MemoryMarshal.GetReference(span)); - return *(FlexibleArray*)&ptr; + return MemoryMarshal.CreateSpan(ref Data, length); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs b/src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs index c231cd469..3fbfae5bd 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/Kernel32.cs @@ -50,6 +50,14 @@ public static unsafe HANDLE CreateEventW(ref readonly SECURITY_ATTRIBUTES eventA [SupportedOSPlatform("windows5.1.2600")] public static extern unsafe BOOL DeviceIoControl(HANDLE hDevice, uint dwIoControlCode, [Optional] void* lpInBuffer, uint nInBufferSize, [MaybeNull] void* lpOutBuffer, uint nOutBufferSize, [MaybeNull] uint* lpBytesReturned, [AllowNull][MaybeNull] OVERLAPPED* lpOverlapped); + public static unsafe BOOL DeviceIoControl(HANDLE hDevice, uint dwIoControlCode, [Optional] void* lpInBuffer, uint nInBufferSize, [MaybeNull] Span outBuffer, [MaybeNull] uint* lpBytesReturned, [AllowNull][MaybeNull] OVERLAPPED* lpOverlapped) + { + fixed (byte* lpOutBuffer = outBuffer) + { + return DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, (uint)outBuffer.Length, lpBytesReturned, lpOverlapped); + } + } + [DllImport("KERNEL32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] public static extern BOOL FreeConsole(); From 6709f74ecd3b1e0f8e510e180ff86b8bf42269f4 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Wed, 23 Oct 2024 20:02:41 +0800 Subject: [PATCH 30/99] fix disk extents call 3 --- .../Snap.Hutao/Core/IO/PhysicalDriver.cs | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs index e9f49aa10..d165e84a2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/PhysicalDriver.cs @@ -55,30 +55,28 @@ private static unsafe void GetDeviceNumber(string fileName, out uint deviceNumbe } // This logical driver belongs to a partitionable device. - int length = sizeof(VOLUME_DISK_EXTENTS) + (sizeof(DISK_EXTENT) * 1); - Span buffer = stackalloc byte[length]; - if (!DeviceIoControl(hLogicalDriver, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, default, default, buffer, default, default)) + Span buffer = stackalloc byte[sizeof(VOLUME_DISK_EXTENTS) + (sizeof(DISK_EXTENT) * 1)]; + if (DeviceIoControl(hLogicalDriver, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, default, default, buffer, default, default)) { - WIN32_ERROR error2 = GetLastError(); - if (error2 is not WIN32_ERROR.ERROR_MORE_DATA) - { - Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error2)); - } - - ref VOLUME_DISK_EXTENTS diskExtents = ref MemoryMarshal.AsRef(buffer); - length = sizeof(VOLUME_DISK_EXTENTS) + (sizeof(DISK_EXTENT) * (int)diskExtents.NumberOfDiskExtents); - buffer = stackalloc byte[length]; - if (!DeviceIoControl(hLogicalDriver, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, default, default, buffer, default, default)) - { - Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(GetLastError())); - } - - ref VOLUME_DISK_EXTENTS diskExtents2 = ref MemoryMarshal.AsRef(buffer); - ref DISK_EXTENT extent = ref diskExtents2.Extents[0]; - deviceNumber = extent.DiskNumber; + deviceNumber = MemoryMarshal.AsRef(buffer).Extents[0].DiskNumber; return; } + WIN32_ERROR error2 = GetLastError(); + if (error2 is not WIN32_ERROR.ERROR_MORE_DATA) + { + Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error2)); + } + + // The volume has multiple extents. + buffer = stackalloc byte[sizeof(VOLUME_DISK_EXTENTS) + (sizeof(DISK_EXTENT) * (int)MemoryMarshal.AsRef(buffer).NumberOfDiskExtents)]; + if (DeviceIoControl(hLogicalDriver, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, default, default, buffer, default, default)) + { + deviceNumber = MemoryMarshal.AsRef(buffer).Extents[0].DiskNumber; + return; + } + + Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(GetLastError())); throw HutaoException.Throw("Failed to get the device number."); } finally From bab287f9c0cf666f4897772c10d6aaa7614afa56 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Thu, 24 Oct 2024 13:51:20 +0800 Subject: [PATCH 31/99] refactor --- .../Core/LifeCycle/AppActivation.cs | 6 +- .../Snap.Hutao/Model/Entity/GameAccount.cs | 32 ---- .../Game/Account/GameAccountService.cs | 9 - .../Game/Account/IGameAccountService.cs | 2 - .../Service/Game/GameServiceFacade.cs | 5 - .../Service/Game/IGameServiceFacade.cs | 2 - .../Snap.Hutao/Service/Game/LaunchOptions.cs | 21 ++- .../Service/Game/LaunchOptionsExtension.cs | 34 ++-- ...aunchExecutionEnsureGameResourceHandler.cs | 2 +- .../Game/Launching/LaunchExecutionContext.cs | 2 +- .../Game/PathAbstraction/GamePathService.cs | 2 +- .../Service/User/UserServiceExtension.cs | 13 +- src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj | 2 +- .../UI/Xaml/View/Page/LaunchGamePage.xaml | 9 - .../ViewModel/Abstraction/ViewModel.cs | 6 +- .../Achievement/AchievementViewModel.cs | 2 +- .../AvatarProperty/AvatarPropertyViewModel.cs | 2 +- .../Complex/HutaoDatabaseViewModel.cs | 2 +- .../Cultivation/CultivationViewModel.cs | 2 +- .../ViewModel/DailyNote/DailyNoteViewModel.cs | 2 +- .../ViewModel/Feedback/FeedbackViewModel.cs | 2 +- .../ViewModel/GachaLog/GachaLogViewModel.cs | 2 +- .../ViewModel/GachaLog/HutaoCloudViewModel.cs | 2 +- .../Game/GamePackageInstallViewModel.cs | 2 +- .../ViewModel/Game/GamePackageViewModel.cs | 7 +- .../Game/IViewModelSupportLaunchExecution.cs | 2 +- .../ViewModel/Game/LaunchGameViewModel.cs | 157 +++++++----------- .../ViewModel/Game/LaunchGameViewModelSlim.cs | 7 - .../ViewModel/Guide/GuideViewModel.cs | 2 +- .../ViewModel/Home/AnnouncementViewModel.cs | 2 +- .../Snap.Hutao/ViewModel/MainViewModel.cs | 2 +- .../ViewModel/Setting/SettingViewModel.cs | 2 +- .../SpiralAbyss/SpiralAbyssRecordViewModel.cs | 2 +- .../Snap.Hutao/ViewModel/TitleViewModel.cs | 2 +- .../ViewModel/Wiki/WikiAvatarViewModel.cs | 2 +- .../ViewModel/Wiki/WikiMonsterViewModel.cs | 2 +- .../ViewModel/Wiki/WikiWeaponViewModel.cs | 2 +- 37 files changed, 122 insertions(+), 234 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs index cfe1cb157..2159a8b20 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs @@ -100,10 +100,8 @@ async ValueTask ActivateAndInitializeAsync() public async ValueTask HandleLaunchGameActionAsync(string? uid = null) { - serviceProvider - .GetRequiredService() - .Set(ViewModel.Game.LaunchGameViewModel.DesiredUid, uid); - + // TODO: Handle uid selection, notify user service to switch to the corresponding user + await taskContext.SwitchToMainThreadAsync(); switch (currentWindowReference.Window) diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/GameAccount.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/GameAccount.cs index ff12a5db2..75248f674 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/GameAccount.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/GameAccount.cs @@ -11,36 +11,18 @@ namespace Snap.Hutao.Model.Entity; -/// -/// 游戏内账号 -/// -[HighQuality] [Table("game_accounts")] internal sealed partial class GameAccount : ObservableObject, IAppDbEntity, IReorderable, IAdvancedCollectionViewItem { - /// - /// 内部Id - /// [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid InnerId { get; set; } - /// - /// 对应的Uid - /// - public string? AttachUid { get; set; } - - /// - /// 服务器类型 - /// public SchemeType Type { get; set; } - /// - /// 名称 - /// public string Name { get; set; } = default!; /// @@ -61,20 +43,6 @@ public static GameAccount From(string name, string sdk, SchemeType type) }; } - /// - /// 更新绑定的Uid - /// - /// uid - public void UpdateAttachUid(string? uid) - { - AttachUid = uid; - OnPropertyChanged(nameof(AttachUid)); - } - - /// - /// 更新名称 - /// - /// 新名称 public void UpdateName(string name) { Name = name; diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/GameAccountService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/GameAccountService.cs index 366b7fd06..8acebc7e1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/GameAccountService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/GameAccountService.cs @@ -89,15 +89,6 @@ public bool SetGameAccount(GameAccount account) return RegistryInterop.Set(account); } - public async ValueTask AttachGameAccountToUidAsync(GameAccount gameAccount, string uid) - { - await taskContext.SwitchToMainThreadAsync(); - gameAccount.UpdateAttachUid(uid); - - await taskContext.SwitchToBackgroundAsync(); - gameRepository.UpdateGameAccount(gameAccount); - } - public async ValueTask ModifyGameAccountAsync(GameAccount gameAccount) { LaunchGameAccountNameDialog dialog = await contentDialogFactory.CreateInstanceAsync().ConfigureAwait(false); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/IGameAccountService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/IGameAccountService.cs index 6a7c3d99c..9c8e462eb 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/IGameAccountService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Account/IGameAccountService.cs @@ -9,8 +9,6 @@ namespace Snap.Hutao.Service.Game.Account; internal interface IGameAccountService { - ValueTask AttachGameAccountToUidAsync(GameAccount gameAccount, string uid); - GameAccount? DetectCurrentGameAccount(SchemeType schemeType); ValueTask DetectGameAccountAsync(SchemeType schemeType); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameServiceFacade.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameServiceFacade.cs index d604aeeb4..69416c8cb 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameServiceFacade.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameServiceFacade.cs @@ -44,11 +44,6 @@ public ChannelOptions GetChannelOptions() return gameAccountService.DetectCurrentGameAccount(scheme); } - public ValueTask AttachGameAccountToUidAsync(GameAccount gameAccount, string uid) - { - return gameAccountService.AttachGameAccountToUidAsync(gameAccount, uid); - } - public ValueTask ModifyGameAccountAsync(GameAccount gameAccount) { return gameAccountService.ModifyGameAccountAsync(gameAccount); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameServiceFacade.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameServiceFacade.cs index 707a6c987..354d637c7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameServiceFacade.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameServiceFacade.cs @@ -10,8 +10,6 @@ namespace Snap.Hutao.Service.Game; internal interface IGameServiceFacade { - ValueTask AttachGameAccountToUidAsync(GameAccount gameAccount, string uid); - ValueTask DetectGameAccountAsync(SchemeType scheme); ValueTask> GetGamePathAsync(); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs index 3e60d1822..68d01ad8c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs @@ -24,7 +24,7 @@ internal sealed partial class LaunchOptions : DbStoreOptions private readonly int primaryScreenFps; private string? gamePath; - private ImmutableList? gamePathEntries; + private ImmutableArray? gamePathEntries; private bool? usingHoyolabAccount; private bool? isEnabled; private bool? isAdvancedLaunchOptionsEnabled; @@ -58,7 +58,7 @@ public LaunchOptions(IServiceProvider serviceProvider) primaryScreenWidth = primaryRect.Width; primaryScreenHeight = primaryRect.Height; - InitializeMonitors(Monitors); + Monitors = InitializeMonitors(); InitializeScreenFps(out primaryScreenFps); // Batch initialization, boost up performance @@ -120,8 +120,9 @@ static Void InitializeFloatValue(ref float? storage, string? value) return default; } - static void InitializeMonitors(List> monitors) + static ImmutableArray> InitializeMonitors() { + ImmutableArray>.Builder monitors = ImmutableArray.CreateBuilder>(); try { // This list can't use foreach @@ -138,6 +139,8 @@ static void InitializeMonitors(List> monitors) { monitors.Clear(); } + + return monitors.ToImmutable(); } static void InitializeScreenFps(out int fps) @@ -161,11 +164,11 @@ public string GamePath set => SetOption(ref gamePath, SettingEntry.GamePath, value); } - public ImmutableList GamePathEntries + public ImmutableArray GamePathEntries { // Because DbStoreOptions can't detect collection change, We use // ImmutableList to imply that the whole list needs to be replaced - get => GetOption(ref gamePathEntries, SettingEntry.GamePathEntries, raw => JsonSerializer.Deserialize>(raw), []); + get => GetOption(ref gamePathEntries, SettingEntry.GamePathEntries, raw => JsonSerializer.Deserialize>(raw), []).Value; set => SetOption(ref gamePathEntries, SettingEntry.GamePathEntries, value, v => JsonSerializer.Serialize(v)); } @@ -279,9 +282,9 @@ public NameValue? Monitor { return GetOption(ref monitor, SettingEntry.LaunchMonitor, index => Monitors[RestrictIndex(Monitors, index)], Monitors[0]); - static int RestrictIndex(List> monitors, string index) + static int RestrictIndex(ImmutableArray> monitors, string index) { - return Math.Clamp(int.Parse(index, CultureInfo.InvariantCulture) - 1, 0, monitors.Count - 1); + return Math.Clamp(int.Parse(index, CultureInfo.InvariantCulture) - 1, 0, monitors.Length - 1); } } @@ -331,9 +334,9 @@ public bool SetDiscordActivityWhenPlaying } #endregion - public List> Monitors { get; } = []; + public ImmutableArray> Monitors { get; } - public List AspectRatios { get; } = + public ImmutableArray AspectRatios { get; } = [ new(3840, 2160), new(2560, 1600), diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptionsExtension.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptionsExtension.cs index dff47349e..ee1b5d81e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptionsExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptionsExtension.cs @@ -3,6 +3,7 @@ using Snap.Hutao.Service.Game.PathAbstraction; using System.Collections.Immutable; +using System.Runtime.InteropServices; namespace Snap.Hutao.Service.Game; @@ -18,50 +19,49 @@ public static bool TryGetGameFileSystem(this LaunchOptions options, [NotNullWhen return false; } - fileSystem = new GameFileSystem(gamePath); + fileSystem = new(gamePath); return true; } - public static ImmutableList GetGamePathEntries(this LaunchOptions options, out GamePathEntry? entry) + public static ImmutableArray GetGamePathEntries(this LaunchOptions options, out GamePathEntry? selected) { string gamePath = options.GamePath; if (string.IsNullOrEmpty(gamePath)) { - entry = default; + selected = default; return options.GamePathEntries; } if (options.GamePathEntries.SingleOrDefault(entry => string.Equals(entry.Path, options.GamePath, StringComparison.OrdinalIgnoreCase)) is { } existed) { - entry = existed; + selected = existed; return options.GamePathEntries; } - entry = GamePathEntry.Create(options.GamePath); - return [.. options.GamePathEntries, entry]; + selected = GamePathEntry.Create(options.GamePath); + return options.GamePathEntries = options.GamePathEntries.Add(selected); } - public static ImmutableList RemoveGamePathEntry(this LaunchOptions options, GamePathEntry? entry, out GamePathEntry? selected) + public static ImmutableArray RemoveGamePathEntry(this LaunchOptions options, GamePathEntry? entry, out GamePathEntry? selected) { - if (entry is not null) + if (entry is null) { - if (string.Equals(options.GamePath, entry.Path, StringComparison.OrdinalIgnoreCase)) - { - options.GamePath = string.Empty; - } + return options.GetGamePathEntries(out selected); + } - options.GamePathEntries = options.GamePathEntries.Remove(entry); + if (string.Equals(options.GamePath, entry.Path, StringComparison.OrdinalIgnoreCase)) + { + options.GamePath = string.Empty; } + options.GamePathEntries = options.GamePathEntries.Remove(entry); return options.GetGamePathEntries(out selected); } - public static ImmutableList UpdateGamePathAndRefreshEntries(this LaunchOptions options, string gamePath) + public static ImmutableArray UpdateGamePath(this LaunchOptions options, string gamePath) { options.GamePath = gamePath; - ImmutableList entries = options.GetGamePathEntries(out _); - options.GamePathEntries = entries; - return entries; + return options.GetGamePathEntries(out _); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionEnsureGameResourceHandler.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionEnsureGameResourceHandler.cs index b990e84b7..7a63e336b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionEnsureGameResourceHandler.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/Handler/LaunchExecutionEnsureGameResourceHandler.cs @@ -141,7 +141,7 @@ private static async ValueTask EnsureGameResourceAsync(LaunchExecutionCont string executableName = context.Scheme.IsOversea ? GameConstants.GenshinImpactFileName : GameConstants.YuanShenFileName; await context.TaskContext.SwitchToMainThreadAsync(); - context.Options.UpdateGamePathAndRefreshEntries(Path.Combine(gameFolder, executableName)); + context.Options.UpdateGamePath(Path.Combine(gameFolder, executableName)); } await packageConverter.EnsureDeprecatedFilesAndSdkAsync(packageConverterContext).ConfigureAwait(false); diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionContext.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionContext.cs index 5d6de5896..046b1349c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionContext.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Launching/LaunchExecutionContext.cs @@ -79,7 +79,7 @@ public bool TryGetGameFileSystem([NotNullWhen(true)] out GameFileSystem? gameFil public void UpdateGamePathEntry() { - ImmutableList gamePathEntries = Options.GetGamePathEntries(out GamePathEntry? selectedEntry); + ImmutableArray gamePathEntries = Options.GetGamePathEntries(out GamePathEntry? selectedEntry); ViewModel.SetGamePathEntriesAndSelectedGamePathEntry(gamePathEntries, selectedEntry); // invalidate game file system diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/PathAbstraction/GamePathService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/PathAbstraction/GamePathService.cs index e35eab333..04af2c9d8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/PathAbstraction/GamePathService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/PathAbstraction/GamePathService.cs @@ -29,7 +29,7 @@ public async ValueTask> SilentGetGamePathAsync() if (isOk) { // Save result. - launchOptions.UpdateGamePathAndRefreshEntries(path); + launchOptions.UpdateGamePath(path); } else { diff --git a/src/Snap.Hutao/Snap.Hutao/Service/User/UserServiceExtension.cs b/src/Snap.Hutao/Snap.Hutao/Service/User/UserServiceExtension.cs index 2f4e25be9..bc9778621 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/User/UserServiceExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/User/UserServiceExtension.cs @@ -19,18 +19,7 @@ public static ValueTask RefreshCookieTokenAsync(this IUserService userServ public static async ValueTask GetUserGameRoleByUidAsync(this IUserService userService, string uid) { AdvancedDbCollectionView users = await userService.GetUsersAsync().ConfigureAwait(false); - foreach (BindingUser user in users.SourceCollection) - { - foreach (UserGameRole role in user.UserGameRoles) - { - if (role.GameUid == uid) - { - return role; - } - } - } - - return null; + return users.SourceCollection.SelectMany(user => user.UserGameRoles.SourceCollection).FirstOrDefault(role => role.GameUid == uid); } public static async ValueTask GetCurrentUidAsync(this IUserService userService) diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index 6d0b1efb8..0087b7447 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -344,7 +344,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/LaunchGamePage.xaml b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/LaunchGamePage.xaml index cba2fd716..1d769bfe6 100644 --- a/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/LaunchGamePage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/UI/Xaml/View/Page/LaunchGamePage.xaml @@ -58,15 +58,6 @@ Grid.Column="1" HorizontalAlignment="Right" Orientation="Horizontal"> -