@@ -240,6 +240,11 @@ class Client {
240240 token : string ;
241241 createdAt : number ;
242242 } > | null = null ;
243+ private serverConfigPrefetch : Promise <
244+ Awaited < ReturnType < typeof getServerConfigFromClient > >
245+ > | null = null ;
246+ private cosmeticsPromise : Promise < Awaited < ReturnType < typeof fetchCosmetics > > > | null =
247+ null ;
243248
244249 constructor ( ) { }
245250
@@ -248,6 +253,16 @@ class Client {
248253 // Prefetch turnstile token so it is available when
249254 // the user joins a lobby.
250255 this . turnstileTokenPromise = getTurnstileToken ( ) ;
256+ // Warm critical join dependencies to avoid blocking on first join.
257+ const configPrefetch = getServerConfigFromClient ( ) ;
258+ configPrefetch . catch ( ( error ) => {
259+ console . warn ( "Server config prefetch failed" , error ) ;
260+ if ( this . serverConfigPrefetch === configPrefetch ) {
261+ this . serverConfigPrefetch = null ;
262+ }
263+ } ) ;
264+ this . serverConfigPrefetch = configPrefetch ;
265+ this . cosmeticsPromise = fetchCosmetics ( ) ;
251266
252267 // Wait for components to render before setting version
253268 await customElements . whenDefined ( "mobile-nav-bar" ) ;
@@ -796,23 +811,29 @@ class Client {
796811 if ( lobby . source === "public" ) {
797812 this . joinPublicModal ?. open ( lobby . gameID , lobby . publicLobbyInfo ) ;
798813 }
799- const config = await getServerConfigFromClient ( ) ;
800- if ( joinAttemptId !== this . joinAttemptId ) {
801- return ;
802- }
803- this . updateJoinUrlForShare ( lobby . gameID , config ) ;
804-
805- const pattern = this . userSettings . getSelectedPatternName (
806- await fetchCosmetics ( ) ,
814+ const configPromise =
815+ this . serverConfigPrefetch ?? getServerConfigFromClient ( ) ;
816+ const cosmeticsPromise = this . cosmeticsPromise ?? fetchCosmetics ( ) ;
817+ const turnstilePromise = configPromise . then ( ( config ) =>
818+ this . getTurnstileToken ( lobby , config ) ,
807819 ) ;
820+ const [ config , cosmetics , turnstileToken ] = await Promise . all ( [
821+ configPromise ,
822+ cosmeticsPromise ,
823+ turnstilePromise ,
824+ ] ) ;
808825 if ( joinAttemptId !== this . joinAttemptId ) {
809826 return ;
810827 }
811-
812- const turnstileToken = await this . getTurnstileToken ( lobby ) ;
813- if ( joinAttemptId !== this . joinAttemptId ) {
814- return ;
828+ if ( this . serverConfigPrefetch === configPromise ) {
829+ this . serverConfigPrefetch = null ;
815830 }
831+ if ( this . cosmeticsPromise === cosmeticsPromise && cosmetics === null ) {
832+ this . cosmeticsPromise = null ;
833+ }
834+ this . updateJoinUrlForShare ( lobby . gameID , config ) ;
835+
836+ const pattern = this . userSettings . getSelectedPatternName ( cosmetics ) ;
816837
817838 this . gameStop = joinLobby (
818839 this . eventBus ,
@@ -1004,10 +1025,11 @@ class Client {
10041025
10051026 private async getTurnstileToken (
10061027 lobby : JoinLobbyEvent ,
1028+ config ?: Awaited < ReturnType < typeof getServerConfigFromClient > > ,
10071029 ) : Promise < string | null > {
1008- const config = await getServerConfigFromClient ( ) ;
1030+ const resolvedConfig = config ?? ( await getServerConfigFromClient ( ) ) ;
10091031 if (
1010- config . env ( ) === GameEnv . Dev ||
1032+ resolvedConfig . env ( ) === GameEnv . Dev ||
10111033 lobby . gameStartInfo ?. config . gameType === GameType . Singleplayer
10121034 ) {
10131035 return null ;
0 commit comments