1111using System . Threading ;
1212using System . Threading . Tasks ;
1313using Hi3Helper . SentryHelper ;
14- using Hi3Helper . Sophon . Structs ;
1514using System . Net . Http ;
1615using System . Net ;
1716using System . Net . Http . Json ;
1817using System . Runtime . CompilerServices ;
1918using System . Linq ;
19+ using System . Collections . Generic ;
2020// ReSharper disable PartialTypeWithSinglePart
2121// ReSharper disable IdentifierTypo
2222// ReSharper disable StringLiteralTypo
@@ -36,11 +36,12 @@ internal partial class LauncherApiBase : ILauncherApi
3636 public const int ExecutionTimeoutAttempt = 5 ;
3737 protected PresetConfig ? PresetConfig { get ; }
3838
39- public bool IsLoadingCompleted { get ; private set ; }
40- public string ? GameBackgroundImg { get => LauncherGameNews ? . Content ? . Background ? . BackgroundImg ; }
41- public string ? GameBackgroundImgLocal { get ; set ; }
42- public string ? GameName { get ; init ; }
43- public string ? GameRegion { get ; init ; }
39+ public bool IsLoadingCompleted { get ; private set ; }
40+ public bool IsForceRedirectToSophon { get ; private set ; }
41+ public string ? GameBackgroundImg { get => LauncherGameNews ? . Content ? . Background ? . BackgroundImg ; }
42+ public string ? GameBackgroundImgLocal { get ; set ; }
43+ public string ? GameName { get ; init ; }
44+ public string ? GameRegion { get ; init ; }
4445
4546 public string ? GameNameTranslation =>
4647 InnerLauncherConfig . GetGameTitleRegionTranslationString ( GameName , Locale . Lang . _GameClientTitles ) ;
@@ -118,9 +119,11 @@ protected LauncherApiBase(PresetConfig presetConfig, string gameName, string gam
118119 ApiResourceHttpClient = apiResourceHttpBuilder . Create ( ) ;
119120 }
120121
121- public async Task < bool > LoadAsync ( OnLoadTaskAction ? beforeLoadRoutine , OnLoadTaskAction ? afterLoadRoutine ,
122- ActionOnTimeOutRetry ? onTimeoutRoutine , ErrorLoadRoutineDelegate ? errorLoadRoutine ,
123- CancellationToken token )
122+ public async Task < bool > LoadAsync ( OnLoadTaskAction ? beforeLoadRoutine ,
123+ OnLoadTaskAction ? afterLoadRoutine ,
124+ ActionOnTimeOutRetry ? onTimeoutRoutine ,
125+ ErrorLoadRoutineDelegate ? errorLoadRoutine ,
126+ CancellationToken token )
124127 {
125128 _ = beforeLoadRoutine ? . Invoke ( token ) ?? Task . CompletedTask ;
126129
@@ -145,7 +148,7 @@ public async Task<bool> LoadAsync(OnLoadTaskAction? beforeLoadRoutine, OnLoa
145148 }
146149
147150 protected virtual async Task LoadAsyncInner ( ActionOnTimeOutRetry ? onTimeoutRoutine ,
148- CancellationToken token )
151+ CancellationToken token )
149152 {
150153 // 2025-05-05: As per now, the Sophon resource information requires to be fetched first.
151154 // This is mandatory due to latest Genshin Impact changes which removes zip
@@ -161,17 +164,57 @@ await Task.WhenAll(LoadLauncherGameResource(onTimeoutRoutine, token),
161164
162165 protected virtual void InitializeFakeVersionInfo ( )
163166 {
164- if ( LauncherGameResourceSophon == null )
167+ if ( LauncherGameResource ? . data == null )
168+ {
169+ return ;
170+ }
171+
172+ HoYoPlayGameInfoBranch ? gameBranch = LauncherGameResourceSophon ? . GameInfoData ? . GameBranchesInfo ?
173+ . FirstOrDefault ( x => x . GameInfo ? . BizName ? . Equals ( PresetConfig ? . LauncherBizName ) ?? false ) ;
174+
175+ if ( gameBranch == null )
176+ {
177+ return ;
178+ }
179+
180+ var branchPreloadField = gameBranch . GamePreloadField ;
181+ var branchBaseField = gameBranch . GameMainField ;
182+
183+ if ( branchPreloadField != null )
184+ {
185+ LauncherGameResource . data . pre_download_game ??= new RegionResourceLatest ( ) ;
186+ AddFakeVersionInfo ( branchPreloadField , LauncherGameResource . data . pre_download_game ) ;
187+ }
188+
189+ if ( branchBaseField == null )
165190 {
166191 return ;
167192 }
168193
169- HoYoPlayGameInfoBranch ? gameBranch = LauncherGameResourceSophon . GameInfoData ? . GameBranchesInfo ?
170- . FirstOrDefault ( x => x . GameInfo ? . BizName ? . Equals ( PresetConfig ? . LauncherBizName ) ?? false ) ;
194+ LauncherGameResource . data . game ??= new RegionResourceLatest ( ) ;
195+ AddFakeVersionInfo ( branchBaseField , LauncherGameResource . data . game ) ;
196+ IsForceRedirectToSophon = true ;
197+ }
198+
199+ protected virtual void AddFakeVersionInfo ( HoYoPlayGameInfoBranchField branchField , RegionResourceLatest region )
200+ {
201+ region . latest ??= new RegionResourceVersion ( ) ;
202+ region . latest . version = branchField . Tag ;
203+
204+ region . diffs ??= [ ] ;
205+
206+ HashSet < string > existingDiffsVer = new ( region . diffs . Select ( x => x . version ) ! ) ;
207+ foreach ( var versionTags in ( branchField . DiffTags ?? [ ] ) . Where ( x => ! existingDiffsVer . Contains ( x ) ) )
208+ {
209+ region . diffs . Add ( new RegionResourceVersion
210+ {
211+ version = versionTags
212+ } ) ;
213+ }
171214 }
172215
173216 protected virtual async Task LoadLauncherGameResourceSophon ( ActionOnTimeOutRetry ? onTimeoutRoutine ,
174- CancellationToken token )
217+ CancellationToken token )
175218 {
176219 EnsurePresetConfigNotNull ( ) ;
177220
@@ -188,6 +231,7 @@ protected virtual async Task LoadLauncherGameResourceSophon(ActionOnTimeOutRetry
188231 PresetConfig . LauncherBizName ! ,
189232 false ,
190233 token ) ?? Task . CompletedTask ) ;
234+ sophonUrls ? . ResetAssociation ( ) ; // Reset association so it won't conflict with preload/update/install activity
191235
192236 ActionTimeoutTaskAwaitableCallback < HoYoPlayLauncherGameInfo ? > launcherSophonBranchCallback =
193237 innerToken =>
0 commit comments