From dc7aecd4f2da49dd1c415a1baadab63978a89c1a Mon Sep 17 00:00:00 2001 From: LWSS Date: Fri, 3 Nov 2023 15:16:46 -0700 Subject: [PATCH] fix(gta-net-five): Construct CPlayerInfo for g_player31. This was null before, the PlayerInfo isn't set in the constructor for the player. It's expected to be non-null in some events. --- .../gta-net-five/src/CloneExperiments.cpp | 56 +++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/code/components/gta-net-five/src/CloneExperiments.cpp b/code/components/gta-net-five/src/CloneExperiments.cpp index 74369710c8..5a8ea92950 100644 --- a/code/components/gta-net-five/src/CloneExperiments.cpp +++ b/code/components/gta-net-five/src/CloneExperiments.cpp @@ -734,7 +734,22 @@ static hook::cdecl_stub _netPlayerCtor([]() #elif IS_RDR3 return hook::get_pattern("E8 ? ? ? ? 33 F6 48 8D 05 ? ? ? ? 48 8D 8B", -0x17); #endif +}); + +#ifdef GTA_FIVE +// Offset is usually 0xA0, but can differ on ancient builds +static int g_CNetPlayerOffset_PlayerInfo = 0; +struct CPlayerInfo_Five; +static hook::cdecl_stub _playerInfoCtor([]() +{ + return hook::get_pattern("48 83 EC 30 65 4C 8B 0C 25 ? 00 00 00 0F 29 70 C8 45 33 ED", -0x18); +}); +// this appears to be a substruct that makes up a good chunk of the beginning of the CPlayerInfo +static hook::cdecl_stub _getLocalGamerInfo([]() +{ + return hook::get_address(hook::get_pattern("E8 ? ? ? ? 33 D2 48 8B CB 4C 8B C0 E8 ? ? ? ? 4D 8B CE"), 1, 5); }); +#endif static CNetGamePlayer*(*g_origAllocateNetPlayer)(void*); @@ -756,9 +771,30 @@ static CNetGamePlayer* AllocateNetPlayer(void* mgr) // RDR3 wants CNetworkPlayerMgr pointer in CNetGamePlayer #ifdef IS_RDR3 *(rage::netPlayerMgrBase**)((uint64_t)player + 288) = g_playerMgr; -#endif - +#endif + return player; +} + +// fix: some Events expect the CPlayerInfo to be non-null in the CNetGamePlayer (It is not set in the constructor) +static void Player31_ApplyPlayerInfo(CNetGamePlayer* player) +{ + static void* infoMem = nullptr; + if (!infoMem) + { + infoMem = malloc(0x2000); + CPlayerInfo_Five* info = _playerInfoCtor(infoMem, 0, _getLocalGamerInfo()); + *(CPlayerInfo_Five**)((uint64_t)player + g_CNetPlayerOffset_PlayerInfo) = info; + } + else + { + *(CPlayerInfo_Five**)((uint64_t)player + g_CNetPlayerOffset_PlayerInfo) = (CPlayerInfo_Five*)infoMem; + } +} +// Clear the playerInfo after events +static void Player31_ClearPlayerInfo(CNetGamePlayer* player) +{ + *(CPlayerInfo_Five**)((uint64_t)player + g_CNetPlayerOffset_PlayerInfo) = nullptr; } #include @@ -3019,6 +3055,8 @@ static void HandleNetGameEvent(const char* idata, size_t len) if (ev) { + Player31_ApplyPlayerInfo(g_player31); + ev->HandleReply(&rlBuffer, player); #ifdef GTA_FIVE @@ -3033,7 +3071,9 @@ static void HandleNetGameEvent(const char* idata, size_t len) #endif delete ev; - g_events.erase({ eventType, eventHeader }); + g_events.erase({ eventType, eventHeader }); + + Player31_ClearPlayerInfo(g_player31); } } } @@ -3074,7 +3114,7 @@ static void HandleNetGameEvent(const char* idata, size_t len) } } } - + static void DecideNetGameEvent(rage::netGameEvent* ev, CNetGamePlayer* player, CNetGamePlayer* unkConn, rage::datBitBuffer* buffer, uint16_t evH) { g_lastEventGotRejected = false; @@ -4208,7 +4248,13 @@ static HookFunction hookFunctionTime([]() MH_CreateHook((xbr::IsGameBuildOrGreater<1436>()) ? hook::get_pattern("83 C8 FF 4C 89 77 08 83 FD", -87) : hook::get_pattern("48 89 51 08 41 83 F8 02 44 0F 45 C8", -49), func, (void**)&g_origInitializeTime); #endif - MH_EnableHook(MH_ALL_HOOKS); + MH_EnableHook(MH_ALL_HOOKS); + +#ifdef GTA_FIVE + char* loc = hook::get_pattern("48 8B 81 ? 00 00 00 48 83 C0 20 C3"); + loc += 3; + g_CNetPlayerOffset_PlayerInfo = *(int*)loc; +#endif #ifdef GTA_FIVE if (xbr::IsGameBuildOrGreater<2372>())