diff --git a/hooks.asm b/hooks.asm index 9167619..6285114 100644 --- a/hooks.asm +++ b/hooks.asm @@ -230,6 +230,14 @@ Hooks_TickFlush PROC mov rbx, rcx ; NetDriver* movd DWORD PTR [rsp + 32], xmm1 ; spill DeltaSeconds + ; Auto-initialize server each tick until bListening is set. + ; Server_Initialize performs an Athena type check and returns + ; without setting bListening if still in lobby context. + movzx eax, BYTE PTR [bListening] + test al, al + jnz @@check_netdriver + call Server_Initialize +@@check_netdriver: ; NetDriver null check test rbx, rbx jz @@call_orig @@ -533,43 +541,18 @@ Hooks_ProcessEventHook PROC push r12 push r13 push r14 - sub rsp, 32 ; 7 pushes: RSP=0; sub32(=0) -> 0 + sub rsp, 32 ; 7 pushes: RSP=0; sub32(≡0) -> 0 mov rbx, rcx ; Object mov rsi, rdx ; Function mov rdi, r8 ; Params - ; PlayButton check (once-only) movzx eax, BYTE PTR [bPlayButton] test al, al jnz @@check_traveled - ; Resolve ReadyToStartMatch UFunction (cached after first call) - mov r12, QWORD PTR [pFn_PlayButton] - test r12, r12 - jnz @@have_playbtn - - lea rcx, szPlayButtonFn - call SDK_FindObject - mov QWORD PTR [pFn_PlayButton], rax - mov r12, rax - -@@have_playbtn: - test r12, r12 - jz @@check_traveled - - cmp rsi, r12 ; Function == ReadyToStartMatch? - jne @@check_traveled - - ; Match - server is ready to start: set flag, travel, hook network mov BYTE PTR [bPlayButton], 1 - - call SDK_GetWorld - test rax, rax - jz @@check_traveled - mov rcx, rax call Game_Start - call Hooks_InitNetworkHooks ; UFunctionHooks dispatch (once bTraveled is true) diff --git a/raider.asm b/raider.asm index 09d93e9..eb77928 100644 --- a/raider.asm +++ b/raider.asm @@ -20,8 +20,6 @@ szDbgAtchProcEvent DB "[DEBUG] Attached Hooks_ProcessEventHook", 0 szDbgAtchViewPt DB "[DEBUG] Attached Hooks_GetPlayerViewPoint", 0 szDbgDetourCommit DB "[DEBUG] Detours transaction committed", 0 szDbgConsoleCreated DB "[DEBUG] SDK console created", 0 -szDbgServerInit DB "[DEBUG] Server_Initialize starting", 0 -szDbgServerDone DB "[DEBUG] Server_Initialize complete", 0 ENDIF .data @@ -119,10 +117,6 @@ Main PROC call SDK_CreateConsole LOG_DBG szDbgConsoleCreated - LOG_DBG szDbgServerInit - call Server_Initialize - LOG_DBG szDbgServerDone - xor eax, eax ; return 0 (DWORD thread exit code) @@main_exit: diff --git a/ufunctionhooks.asm b/ufunctionhooks.asm index b0b36e6..b15bc37 100644 --- a/ufunctionhooks.asm +++ b/ufunctionhooks.asm @@ -44,8 +44,9 @@ pFn_OnRep_bAlreadySearched QWORD ? pFn_OnRep_PlayersLeft QWORD ? pFn_OnRep_DeathInfo QWORD ? -; Cached class pointers (used by ReadyToStartMatch) +; Cached class pointers pClass_FortOnlineBeaconHost QWORD ? +pClass_FortGameModeAthena QWORD ? .const @@ -87,6 +88,7 @@ szFn_OnRep_EditActor DB "Function FortniteGame.FortWeap_EditingTo szFn_K2_GetActorLocation DB "Function Engine.Actor.K2_GetActorLocation", 0 szClass_FortOnlineBeaconHost DB "Class FortniteGame.FortOnlineBeaconHost", 0 +szClass_FortGameModeAthena DB "Class FortniteGame.FortGameModeAthena", 0 szFn_RepairBuilding DB "Function FortniteGame.BuildingSMActor.RepairBuilding", 0 szFn_OnRep_bAlreadySearched DB "Function FortniteGame.BuildingContainer.OnRep_bAlreadySearched", 0 @@ -1172,8 +1174,10 @@ PEHOOK_ServerEditBuildingActor PROC PEHOOK_ServerEditBuildingActor ENDP ; Server_Initialize - set up full listen-server infrastructure -; Called directly from raider.asm Main after DetourTransactionCommit. +; Called from Hooks_TickFlush each tick until bListening is set. ; No arguments; no return value. +; Returns immediately (bListening=0, no state change) if the world is +; not yet in Athena context - Hooks_TickFlush will retry next tick. ; ; Sequence: ; 1. Guard bListening - skip if already listening @@ -1202,6 +1206,33 @@ Server_Initialize PROC test al, al jnz @@done + ; Type check: AuthorityGameMode must be AFortGameModeAthena. + ; If not (lobby context), return WITHOUT setting bListening=1 so + ; Hooks_TickFlush retries on the next tick. + call SDK_GetWorld + test rax, rax + jz @@done ; world not ready -> retry + + mov r12, QWORD PTR [rax + UWORLD_AuthorityGameMode] + test r12, r12 + jz @@done ; GameMode not ready -> retry + + ; Lazily cache AFortGameModeAthena class pointer + mov rax, QWORD PTR [pClass_FortGameModeAthena] + test rax, rax + jnz @@have_athena_class + lea rcx, szClass_FortGameModeAthena + call SDK_FindClass + mov QWORD PTR [pClass_FortGameModeAthena], rax +@@have_athena_class: + test rax, rax + jz @@done ; class not found -> retry + + ; GameMode->ClassPrivate (+0x10) must equal AFortGameModeAthena + cmp QWORD PTR [r12 + 010h], rax + jne @@done ; lobby type -> retry + + ; Verified Athena context - proceed ; Game setup call Game_OnReadyToStartMatch @@ -1295,7 +1326,7 @@ Server_Initialize ENDP ; ; Stack: push rbp,rbx,rsi,rdi,r12 = 5 pushes (RSP=8); sub 40(=8) -> 0 -; Helper macro-equivalent — inline for each registration: +; Helper macro-equivalent - inline for each registration: ; REGISTER rcx=szFnName, handler_label ; lea rcx, szFn_X ; call SDK_FindObject @@ -1558,7 +1589,7 @@ UFunctionHooks_Initialize PROC inc ebp @@r23: ; ---- 24 (renumbered). OnAircraftExitedDropZone ---- - ; NOTE: ReadyToStartMatch removed — server init now called directly + ; NOTE: ReadyToStartMatch removed - server init now called directly ; via Server_Initialize from raider.asm Main after Detours commit. lea rcx, szFn_OnAircraftExitedDropZone call SDK_FindObject