1515using System . Net ;
1616using System . Net . Http . Json ;
1717using System . Runtime . CompilerServices ;
18+ using System . Linq ;
19+ using System . Collections . Generic ;
1820// ReSharper disable PartialTypeWithSinglePart
1921// ReSharper disable IdentifierTypo
2022// ReSharper disable StringLiteralTypo
2123// ReSharper disable VirtualMemberCallInConstructor
24+ // ReSharper disable CommentTypo
2225
2326#nullable enable
2427namespace CollapseLauncher . Helper . LauncherApiLoader
@@ -33,23 +36,25 @@ internal partial class LauncherApiBase : ILauncherApi
3336 public const int ExecutionTimeoutAttempt = 5 ;
3437 protected PresetConfig ? PresetConfig { get ; }
3538
36- public bool IsLoadingCompleted { get ; private set ; }
37- public string ? GameBackgroundImg { get => LauncherGameNews ? . Content ? . Background ? . BackgroundImg ; }
38- public string ? GameBackgroundImgLocal { get ; set ; }
39- public string ? GameName { get ; init ; }
40- 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 ; }
4145
4246 public string ? GameNameTranslation =>
4347 InnerLauncherConfig . GetGameTitleRegionTranslationString ( GameName , Locale . Lang . _GameClientTitles ) ;
4448
4549 public string ? GameRegionTranslation =>
4650 InnerLauncherConfig . GetGameTitleRegionTranslationString ( GameRegion , Locale . Lang . _GameClientRegions ) ;
4751
48- public virtual RegionResourceProp ? LauncherGameResource { get ; protected set ; }
49- public virtual LauncherGameNews ? LauncherGameNews { get ; protected set ; }
50- public virtual HoYoPlayGameInfoField ? LauncherGameInfoField { get ; protected set ; }
51- public virtual HttpClient ApiGeneralHttpClient { get ; protected set ; }
52- public virtual HttpClient ApiResourceHttpClient { get ; protected set ; }
52+ public virtual RegionResourceProp ? LauncherGameResource { get ; protected set ; }
53+ public virtual HoYoPlayLauncherGameInfo ? LauncherGameResourceSophon { get ; protected set ; }
54+ public virtual LauncherGameNews ? LauncherGameNews { get ; protected set ; }
55+ public virtual HoYoPlayGameInfoField ? LauncherGameInfoField { get ; protected set ; }
56+ public virtual HttpClient ApiGeneralHttpClient { get ; protected set ; }
57+ public virtual HttpClient ApiResourceHttpClient { get ; protected set ; }
5358
5459 public void Dispose ( )
5560 {
@@ -114,9 +119,11 @@ protected LauncherApiBase(PresetConfig presetConfig, string gameName, string gam
114119 ApiResourceHttpClient = apiResourceHttpBuilder . Create ( ) ;
115120 }
116121
117- public async Task < bool > LoadAsync ( OnLoadTaskAction ? beforeLoadRoutine , OnLoadTaskAction ? afterLoadRoutine ,
118- ActionOnTimeOutRetry ? onTimeoutRoutine , ErrorLoadRoutineDelegate ? errorLoadRoutine ,
119- CancellationToken token )
122+ public async Task < bool > LoadAsync ( OnLoadTaskAction ? beforeLoadRoutine ,
123+ OnLoadTaskAction ? afterLoadRoutine ,
124+ ActionOnTimeOutRetry ? onTimeoutRoutine ,
125+ ErrorLoadRoutineDelegate ? errorLoadRoutine ,
126+ CancellationToken token )
120127 {
121128 _ = beforeLoadRoutine ? . Invoke ( token ) ?? Task . CompletedTask ;
122129
@@ -140,12 +147,109 @@ public async Task<bool> LoadAsync(OnLoadTaskAction? beforeLoadRoutine, OnLoa
140147 }
141148 }
142149
143- protected virtual Task LoadAsyncInner ( ActionOnTimeOutRetry ? onTimeoutRoutine ,
144- CancellationToken token )
150+ protected virtual async Task LoadAsyncInner ( ActionOnTimeOutRetry ? onTimeoutRoutine ,
151+ CancellationToken token )
145152 {
146- return Task . WhenAll ( LoadLauncherGameResource ( onTimeoutRoutine , token ) ,
147- LoadLauncherNews ( onTimeoutRoutine , token ) ,
148- LoadLauncherGameInfo ( onTimeoutRoutine , token ) ) ;
153+ // 2025-05-05: As per now, the Sophon resource information requires to be fetched first.
154+ // This is mandatory due to latest Genshin Impact changes which removes zip
155+ // packages and also version infos.
156+ await LoadLauncherGameResourceSophon ( onTimeoutRoutine , token ) ;
157+ await Task . WhenAll ( LoadLauncherGameResource ( onTimeoutRoutine , token ) ,
158+ LoadLauncherNews ( onTimeoutRoutine , token ) ,
159+ LoadLauncherGameInfo ( onTimeoutRoutine , token ) ) ;
160+
161+ InitializeFakeVersionInfo ( ) ;
162+ PerformDebugRoutines ( ) ;
163+ }
164+
165+ protected virtual void InitializeFakeVersionInfo ( )
166+ {
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 )
190+ {
191+ return ;
192+ }
193+
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+ }
214+ }
215+
216+ protected virtual async Task LoadLauncherGameResourceSophon ( ActionOnTimeOutRetry ? onTimeoutRoutine ,
217+ CancellationToken token )
218+ {
219+ EnsurePresetConfigNotNull ( ) ;
220+
221+ SophonChunkUrls ? sophonUrls = PresetConfig ? . LauncherResourceChunksURL ;
222+ if ( sophonUrls == null )
223+ {
224+ return ;
225+ }
226+
227+ string ? sophonBranchUrl = sophonUrls . BranchUrl ;
228+ if ( string . IsNullOrEmpty ( PresetConfig ! . LauncherBizName ) || string . IsNullOrEmpty ( sophonBranchUrl ) )
229+ {
230+ Logger . LogWriteLine ( "This game/region doesn't have Sophon->BranchUrl or PresetConfig->LauncherBizName property defined! This might cause the launcher inaccurately check the version if Zip download is unavailable" , LogType . Warning , true ) ;
231+ }
232+
233+ await sophonUrls . EnsureReassociated ( ApiGeneralHttpClient ,
234+ sophonBranchUrl ,
235+ PresetConfig . LauncherBizName ! ,
236+ false ,
237+ token ) ;
238+ sophonUrls . ResetAssociation ( ) ; // Reset association so it won't conflict with preload/update/install activity
239+
240+ ActionTimeoutTaskAwaitableCallback < HoYoPlayLauncherGameInfo ? > launcherSophonBranchCallback =
241+ innerToken =>
242+ ApiGeneralHttpClient . GetFromJsonAsync ( PresetConfig . LauncherResourceChunksURL ? . BranchUrl ,
243+ HoYoPlayLauncherGameInfoJsonContext . Default . HoYoPlayLauncherGameInfo ,
244+ innerToken )
245+ . ConfigureAwait ( false ) ;
246+
247+ LauncherGameResourceSophon = await launcherSophonBranchCallback
248+ . WaitForRetryAsync ( ExecutionTimeout ,
249+ ExecutionTimeoutStep ,
250+ ExecutionTimeoutAttempt ,
251+ onTimeoutRoutine ,
252+ token ) ;
149253 }
150254
151255 protected virtual Task LoadLauncherGameResource ( ActionOnTimeOutRetry ? onTimeoutRoutine ,
@@ -213,8 +317,6 @@ void AfterExecute(Task action)
213317 LogType . Debug , true ) ;
214318#endif
215319 }
216-
217- PerformDebugRoutines ( ) ;
218320 }
219321 }
220322
0 commit comments