From f34b4bbeea9e4af7afb8386c31045dc89d11b572 Mon Sep 17 00:00:00 2001 From: IcePixelx <41352111+PixieCore@users.noreply.github.com> Date: Fri, 5 Nov 2021 21:25:25 +0100 Subject: [PATCH] Rebuild CHostState::FrameUpdate fully works now. --- r5dev/src/hooks/hoststate.cpp | 67 ++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/r5dev/src/hooks/hoststate.cpp b/r5dev/src/hooks/hoststate.cpp index 43d5598b..513debe6 100644 --- a/r5dev/src/hooks/hoststate.cpp +++ b/r5dev/src/hooks/hoststate.cpp @@ -26,7 +26,11 @@ void Hooks::FrameUpdate(void* rcx, void* rdx, float time) static auto g_CEngineVGui = MemoryAddress(0x141741310).RCast(); static auto g_ServerDLL = MemoryAddress(0x141732048).RCast(); static auto Host_ChangelevelFn = MemoryAddress(0x1402387B0).RCast(); + static auto CL_EndMovieFn = MemoryAddress(0x1402C03D0).RCast(); + static auto SendOfflineRequestToStryderFn = MemoryAddress(0x14033D380).RCast(); + static auto CEngine = MemoryAddress(0X141741BA0).RCast(); + HostStates_t oldState; void* placeHolder = nullptr; if (setjmpFn(*host_abortserver, placeHolder)) { @@ -37,14 +41,15 @@ void Hooks::FrameUpdate(void* rcx, void* rdx, float time) { *g_ServerAbortServer = true; - while (true) + do { Cbuf_ExecuteFn(); - HostStates_t oldState = GameGlobals::HostState->m_iCurrentState; + oldState = GameGlobals::HostState->m_iCurrentState; switch (GameGlobals::HostState->m_iCurrentState) { case HostStates_t::HS_NEW_GAME: { + spdlog::debug("[+CHostState::FrameUpdate+] Starting new game now with level: {}\n", GameGlobals::HostState->m_levelName); // Inlined CHostState::State_NewGame GameGlobals::HostState->m_bSplitScreenConnect = false; if (!g_ServerGameClients) // Init Game if it ain't valid. @@ -52,15 +57,10 @@ void Hooks::FrameUpdate(void* rcx, void* rdx, float time) SV_InitGameDLLFn(); } - if (!g_ServerGameClients) // SV_InitGameDLL failed its still null. - { - std::cout << "Fatal CHostState::FrameUpdate Error. SV_InitGameDLL() failed." << std::endl; - abort(); // Placeholder. - } - if ( !CModelLoader_Map_IsValidFn(g_CModelLoader, GameGlobals::HostState->m_levelName) // Check if map is valid and if we can start a new game. - || !Host_NewGameFn(GameGlobals::HostState->m_levelName, nullptr, GameGlobals::HostState->m_bBackgroundLevel, GameGlobals::HostState->m_bSplitScreenConnect, nullptr) ) + || !Host_NewGameFn(GameGlobals::HostState->m_levelName, nullptr, GameGlobals::HostState->m_bBackgroundLevel, GameGlobals::HostState->m_bSplitScreenConnect, nullptr) || !g_ServerGameClients) { + spdlog::info("[+CHostState::FrameUpdate+] Fatal map error 1.\n"); // Inlined SCR_EndLoadingPlaque if (*src_drawloading) { @@ -101,19 +101,24 @@ void Hooks::FrameUpdate(void* rcx, void* rdx, float time) case HostStates_t::HS_CHANGE_LEVEL_SP: { GameGlobals::HostState->m_flShortFrameTime = 1.5; // Set frame time. + + spdlog::debug("[+CHostState::FrameUpdate+] Changing singleplayer level to: {}.\n", GameGlobals::HostState->m_levelName); + if (CModelLoader_Map_IsValidFn(g_CModelLoader, GameGlobals::HostState->m_levelName)) // Check if map is valid and if we can start a new game. { Host_ChangelevelFn(true, GameGlobals::HostState->m_levelName, GameGlobals::HostState->m_mapGroupName); // Call change level as singleplayer level. } else { - std::cout << "Fatal CHostState::FrameUpdate Error. Map is not valid."; + spdlog::info("[+CHostState::FrameUpdate+] Server unable to change level, because unable to find map {}.\n", GameGlobals::HostState->m_levelName); } // Seems useless so nope. // if (g_CHLClient) // (*(void(__fastcall**)(__int64, _QWORD))(*(_QWORD*)g_CHLClient + 1000i64))(g_CHLClient, 0i64); + GameGlobals::HostState->m_iCurrentState = HostStates_t::HS_RUN; // Set current state to run. + // If our next state isn't a shutdown or its a forced shutdown then set next state to run. if (GameGlobals::HostState->m_iNextState != HostStates_t::HS_SHUTDOWN || !GameGlobals::Cvar->FindVar("host_hasIrreversibleShutdown")->m_iValue) GameGlobals::HostState->m_iNextState = HostStates_t::HS_RUN; @@ -122,21 +127,29 @@ void Hooks::FrameUpdate(void* rcx, void* rdx, float time) } case HostStates_t::HS_CHANGE_LEVEL_MP: { - GameGlobals::HostState->m_flShortFrameTime = 1.5; // Set frame time. + GameGlobals::HostState->m_flShortFrameTime = 0.5; // Set frame time. using LevelShutdownFn = void(__thiscall*)(void*); (*reinterpret_cast(*g_ServerDLL))[8](g_ServerDLL); // (*(void (__fastcall **)(void *))(*(_QWORD *)server_dll_var + 64i64))(server_dll_var);// LevelShutdown + spdlog::debug("[+CHostState::FrameUpdate+] Changing multiplayer level to: {}.\n", GameGlobals::HostState->m_levelName); + if (CModelLoader_Map_IsValidFn(g_CModelLoader, GameGlobals::HostState->m_levelName)) // Check if map is valid and if we can start a new game. { - using ShowErrorMessageFn = void(*)(void*); - (*reinterpret_cast(g_CEngineVGui))[31](g_CEngineVGui); // (*((void(__fastcall**)(void**))g_CEngineVGUI + 31))(&g_CEngineVGUI);// EnabledProgressBarForNextLoad - Host_ChangelevelFn(false, GameGlobals::HostState->m_levelName, GameGlobals::HostState->m_mapGroupName); // Call change level as singleplayer level. + using EnabledProgressBarForNextLoadFn = void(*)(void*); + (*reinterpret_cast(g_CEngineVGui))[31](g_CEngineVGui); // (*((void(__fastcall**)(void**))g_CEngineVGUI + 31))(&g_CEngineVGUI);// EnabledProgressBarForNextLoad + Host_ChangelevelFn(false, GameGlobals::HostState->m_levelName, GameGlobals::HostState->m_mapGroupName); // Call change level as multiplayer level. + } + else + { + spdlog::info("[+CHostState::FrameUpdate+] Server unable to change level, because unable to find map {}.\n", GameGlobals::HostState->m_levelName); } // Seems useless so nope. // // if (g_CHLClient) // (*(void(__fastcall**)(__int64, _QWORD))(*(_QWORD*)g_CHLClient + 1000i64))(g_CHLClient, 0i64); + GameGlobals::HostState->m_iCurrentState = HostStates_t::HS_RUN; // Set current state to run. + // If our next state isn't a shutdown or its a forced shutdown then set next state to run. if (GameGlobals::HostState->m_iNextState != HostStates_t::HS_SHUTDOWN || !GameGlobals::Cvar->FindVar("host_hasIrreversibleShutdown")->m_iValue) GameGlobals::HostState->m_iNextState = HostStates_t::HS_RUN; @@ -150,12 +163,24 @@ void Hooks::FrameUpdate(void* rcx, void* rdx, float time) } case HostStates_t::HS_GAME_SHUTDOWN: { + spdlog::debug("[+CHostState::FrameUpdate+] Shutting game down now.\n"); Host_Game_ShutdownFn(GameGlobals::HostState); break; } case HostStates_t::HS_RESTART: { - + spdlog::debug("[+CHostState::FrameUpdate+] Restarting client.\n"); + CL_EndMovieFn(); + SendOfflineRequestToStryderFn(); // We have hostnames nulled anyway. + *(std::int32_t*)((std::uintptr_t)CEngine + 0xC) = 3; //g_CEngine.vtable->SetNextState(&g_CEngine, DLL_RESTART); + break; + } + case HostStates_t::HS_SHUTDOWN: + { + spdlog::debug("[+CHostState::FrameUpdate+] Shutting client down.\n"); + CL_EndMovieFn(); + SendOfflineRequestToStryderFn(); // We have hostnames nulled anyway. + *(std::int32_t*)((std::uintptr_t)CEngine + 0xC) = 2; //g_CEngine.vtable->SetNextState(&g_CEngine, DLL_CLOSE); break; } default: @@ -164,15 +189,9 @@ void Hooks::FrameUpdate(void* rcx, void* rdx, float time) } } - if (oldState == HostStates_t::HS_RUN) - break; - - if (oldState == HostStates_t::HS_SHUTDOWN || oldState == HostStates_t::HS_RESTART) - break; - - if (oldState == HostStates_t::HS_GAME_SHUTDOWN) - break; - } + } while ((oldState != HostStates_t::HS_RUN || GameGlobals::HostState->m_iNextState == HostStates_t::HS_LOAD_GAME && GameGlobals::Cvar->FindVar("g_single_frame_shutdown_for_reload_cvar")->m_pParent->m_iValue) + && oldState != HostStates_t::HS_SHUTDOWN + && oldState != HostStates_t::HS_RESTART); } // originalFrameUpdate(rcx, rdx, time);