diff --git a/r5dev/client/client.cpp b/r5dev/client/client.cpp index 2a0bc684..4bf5817a 100644 --- a/r5dev/client/client.cpp +++ b/r5dev/client/client.cpp @@ -1,5 +1,6 @@ #include "core/stdafx.h" #include "client/client.h" +#include "engine/baseclient.h" /////////////////////////////////////////////////////////////////////////////// -CClient* g_pClient = reinterpret_cast(g_pClientBuffer.GetPtr()); +CBaseClient* g_pClient = reinterpret_cast(g_pClientBuffer.GetPtr()); diff --git a/r5dev/client/client.h b/r5dev/client/client.h index b022fb40..adc21983 100644 --- a/r5dev/client/client.h +++ b/r5dev/client/client.h @@ -4,57 +4,25 @@ //----------------------------------------------------------------------------- // Forward declarations //----------------------------------------------------------------------------- -class CClient; +class CBaseClient; /////////////////////////////////////////////////////////////////////////////// -extern CClient* g_pClient; +extern CBaseClient* g_pClient; namespace { #if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) - const std::uintptr_t g_dwCClientSize = 0x4A440; - const std::uintptr_t g_dwPersistenceVar = 0x5B4; - const std::uintptr_t g_dwCClientPadding = 303232; + const uintptr_t g_dwCClientSize = 0x4A440; + const uintptr_t g_dwPersistenceVar = 0x5B4; + const uintptr_t g_dwCClientPadding = 0x49E88; #elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) - const std::uintptr_t g_dwCClientSize = 0x4A4C0; - const std::uintptr_t g_dwPersistenceVar = 0x5BC; - const std::uintptr_t g_dwCClientPadding = 303360; + const uintptr_t g_dwCClientSize = 0x4A4C0; + const uintptr_t g_dwPersistenceVar = 0x5BC; + const uintptr_t g_dwCClientPadding = 0x49F00; #endif - static ADDRESS g_pClientBuffer = p_IVEngineServer_PersistenceAvailable.FindPatternSelf("48 8D 0D", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7); + static ADDRESS g_pClientBuffer = p_IVEngineServer__PersistenceAvailable.FindPatternSelf("48 8D 0D", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7); } -class CClient -{ -public: - inline CClient* GetClientInstance(int nIndex) - { - return (CClient*)(std::uintptr_t)(g_pClientBuffer.GetPtr() + (nIndex * g_dwCClientSize)); - } - - void*& GetNetChan() - { - return m_nNetChannel; - } -private: - char pad_0000[16]; //0x0000 -public: - int m_iUserID; //0x0010 -private: - char pad_0014[908]; //0x0014 -public: - void* m_nNetChannel; //0x03A0 -private: - char pad_03A8[8]; //0x03A8 -public: - int m_iSignonstate; //0x03B0 -private: - char pad_03B4[4]; //0x03B4 -public: - std::int64_t m_iOriginID; //0x03B8 -private: - char pad_03C0[g_dwCClientPadding]; //0x03C0 -}; - /////////////////////////////////////////////////////////////////////////////// class HClient : public IDetour { diff --git a/r5dev/common/protocol.h b/r5dev/common/protocol.h index 44c94d9d..6e7b83d9 100644 --- a/r5dev/common/protocol.h +++ b/r5dev/common/protocol.h @@ -17,3 +17,11 @@ enum class SIGNONSTATE : int SIGNONSTATE_FULL = 8, // we are fully connected; first non-delta packet received. SIGNONSTATE_CHANGELEVEL = 9, // server is changing level; please wait. }; + +enum class PERSISTENCE : int +{ + PERSISTENCE_NONE = 0, // no persistence data for this client yet. + PERSISTENCE_PENDING = 1, // pending or processing persistence data. + PERSISTENCE_AVAILABLE = 2, // persistence is available for this client. + PERSISTENCE_READY = 5 // persistence is ready for this client. +}; diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index 887c26d0..cef43893 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -49,6 +49,9 @@ #include "rtech/rui/rui.h" #endif // !DEDICATED #include "engine/baseclient.h" +#ifndef GAMECLIENTONLY +#include "engine/baseserver.h" +#endif // !GAMECLIENTONLY #include "engine/common.h" #include "engine/cmodel_bsp.h" #include "engine/host_cmd.h" diff --git a/r5dev/engine/baseclient.cpp b/r5dev/engine/baseclient.cpp index 2fe8abbb..3d7eed0a 100644 --- a/r5dev/engine/baseclient.cpp +++ b/r5dev/engine/baseclient.cpp @@ -1,20 +1,207 @@ +//===============================================================================// +// +// Purpose: +// +// $NoKeywords: $ +// +//===============================================================================// +// baseclient.cpp: implementation of the CBaseClient class. +// +/////////////////////////////////////////////////////////////////////////////////// #include "core/stdafx.h" #include "engine/baseclient.h" //--------------------------------------------------------------------------------- -// Purpose: throw away any residual garbage in the channel +// Purpose: gets the client from buffer by index //--------------------------------------------------------------------------------- -std::int64_t* HCBaseClient_Clear(std::int64_t client) +CBaseClient* CBaseClient::GetClient(int nIndex) const { - return CBaseClient_Clear(client); + return (CBaseClient*)(std::uintptr_t)(g_pClientBuffer.GetPtr() + (nIndex * g_dwCClientSize)); } -/////////////////////////////////////////////////////////////////////////////// +//--------------------------------------------------------------------------------- +// Purpose: gets the userID of this client +//--------------------------------------------------------------------------------- +int32_t CBaseClient::GetUserID(void) const +{ + return m_UserID; +} + +//--------------------------------------------------------------------------------- +// Purpose: gets the userID of this client +//--------------------------------------------------------------------------------- +int64_t CBaseClient::GetOriginID(void) const +{ + return m_OriginID; +} + +//--------------------------------------------------------------------------------- +// Purpose: gets the signon state of this client +//--------------------------------------------------------------------------------- +SIGNONSTATE CBaseClient::GetSignonState(void) const +{ + return m_nSignonState; +} + +//--------------------------------------------------------------------------------- +// Purpose: gets the persistence state of this client +//--------------------------------------------------------------------------------- +PERSISTENCE CBaseClient::GetPersistenceState(void) const +{ + return m_nPersistenceState; +} + +//--------------------------------------------------------------------------------- +// Purpose: gets the net channel of this client +//--------------------------------------------------------------------------------- +void* CBaseClient::GetNetChan(void) const +{ + return m_NetChannel; +} + +//--------------------------------------------------------------------------------- +// Purpose: sets the userID of this client +//--------------------------------------------------------------------------------- +void CBaseClient::SetUserID(int32_t nUserID) +{ + m_UserID = nUserID; +} + +//--------------------------------------------------------------------------------- +// Purpose: sets the originID of this client +//--------------------------------------------------------------------------------- +void CBaseClient::SetOriginID(int64_t nOriginID) +{ + m_OriginID = nOriginID; +} + +//--------------------------------------------------------------------------------- +// Purpose: sets the signon state of this client +//--------------------------------------------------------------------------------- +void CBaseClient::SetSignonState(SIGNONSTATE nSignonState) +{ + m_nSignonState = nSignonState; +} + +//--------------------------------------------------------------------------------- +// Purpose: sets the persistence state of this client +//--------------------------------------------------------------------------------- +void CBaseClient::SetPersistenceState(PERSISTENCE nPersistenceState) +{ + m_nPersistenceState = nPersistenceState; +} + +//--------------------------------------------------------------------------------- +// Purpose: sets the net channel of this client +// !TODO : Remove this and rebuild INetChannel +//--------------------------------------------------------------------------------- +void CBaseClient::SetNetChan(void* pNetChan) +{ + m_NetChannel = pNetChan; +} + +//--------------------------------------------------------------------------------- +// Purpose: checks if client is connected to server +// Output : true if connected, false otherwise +//--------------------------------------------------------------------------------- +bool CBaseClient::IsConnected(void) const +{ + return m_nSignonState >= SIGNONSTATE::SIGNONSTATE_CONNECTED; +} + +//--------------------------------------------------------------------------------- +// Purpose: checks if client is spawned to server +// Output : true if connected, false otherwise +//--------------------------------------------------------------------------------- +bool CBaseClient::IsSpawned(void) const +{ + return m_nSignonState >= SIGNONSTATE::SIGNONSTATE_NEW; +} + +//--------------------------------------------------------------------------------- +// Purpose: checks if client is active to server +// Output : true if connected, false otherwise +//--------------------------------------------------------------------------------- +bool CBaseClient::IsActive(void) const +{ + return m_nSignonState == SIGNONSTATE::SIGNONSTATE_FULL; +} + +//--------------------------------------------------------------------------------- +// Purpose: checks if client's persistence data is available +// Output : true if available, false otherwise +//--------------------------------------------------------------------------------- +bool CBaseClient::IsPersistenceAvailable(void) const +{ + return m_nPersistenceState >= PERSISTENCE::PERSISTENCE_AVAILABLE; +} + +//--------------------------------------------------------------------------------- +// Purpose: checks if client's persistence data is ready +// Output : true if ready, false otherwise +//--------------------------------------------------------------------------------- +bool CBaseClient::IsPersistenceReady(void) const +{ + return m_nPersistenceState == PERSISTENCE::PERSISTENCE_READY; +} + +//--------------------------------------------------------------------------------- +// Purpose: checks if client is a fake client +// Output : true if connected, false otherwise +//--------------------------------------------------------------------------------- +bool CBaseClient::IsFakeClient(void) const +{ + return m_bFakePlayer; +} + +//--------------------------------------------------------------------------------- +// Purpose: checks if this client is an actual human player +// Output : true if human, false otherwise +//--------------------------------------------------------------------------------- +bool CBaseClient::IsHumanPlayer(void) const +{ + if (!IsConnected()) + return false; + + if (IsFakeClient()) + return false; + + return true; +} + +//--------------------------------------------------------------------------------- +// Purpose: throw away any residual garbage in the channel +// Input : *pBaseClient - +//--------------------------------------------------------------------------------- +void* CBaseClient::Clear(CBaseClient* pBaseClient) +{ + return CBaseClient_Clear(pBaseClient); +} + +//--------------------------------------------------------------------------------- +// Purpose: connect new client +// Input : *pClient - +// *szName - +// *pNetChannel - +// bFakePlayer - +// *a5 - +// *szMessage - +// nMessageSize - +// Output : true if connection was succesfull, false otherwise +//--------------------------------------------------------------------------------- +bool CBaseClient::Connect(CBaseClient* pClient, const char* szName, void* pNetChannel, bool bFakePlayer, void* a5, char* szMessage, int nMessageSize) +{ + return CBaseClient_Connect(pClient, szName, pNetChannel, bFakePlayer, a5, szMessage, nMessageSize); +} + +/////////////////////////////////////////////////////////////////////////////////// void CBaseClient_Attach() { - DetourAttach((LPVOID*)&CBaseClient_Clear, &HCBaseClient_Clear); + DetourAttach((LPVOID*)&CBaseClient_Clear, &CBaseClient::Clear); + DetourAttach((LPVOID*)&CBaseClient_Connect, &CBaseClient::Connect); } void CBaseClient_Detach() { - DetourDetach((LPVOID*)&CBaseClient_Clear, &HCBaseClient_Clear); + DetourDetach((LPVOID*)&CBaseClient_Clear, &CBaseClient::Clear); + DetourDetach((LPVOID*)&CBaseClient_Connect, &CBaseClient::Connect); } diff --git a/r5dev/engine/baseclient.h b/r5dev/engine/baseclient.h index cb929954..8992ec96 100644 --- a/r5dev/engine/baseclient.h +++ b/r5dev/engine/baseclient.h @@ -1,15 +1,61 @@ #pragma once +#include "client/client.h" +#include "common/protocol.h" + +class CBaseClient +{ +public: + CBaseClient* GetClient(int nIndex) const; + int32_t GetUserID(void) const; + int64_t GetOriginID(void) const; + SIGNONSTATE GetSignonState(void) const; + PERSISTENCE GetPersistenceState(void) const; + void* GetNetChan(void) const; + void SetUserID(int32_t nUserID); + void SetOriginID(int64_t nOriginID); + void SetSignonState(SIGNONSTATE nSignonState); + void SetPersistenceState(PERSISTENCE nPersistenceState); + void SetNetChan(void* pNetChan); // !TODO: HACK! + bool IsConnected(void) const; + bool IsSpawned(void) const; + bool IsActive(void) const; + bool IsPersistenceAvailable(void) const; + bool IsPersistenceReady(void) const; + bool IsFakeClient(void) const; + bool IsHumanPlayer(void) const; + static bool Connect(CBaseClient* pClient, const char* szName, void* pNetChannel, bool bFakePlayer, void* a5, char* szMessage, int nMessageSize); + static void* Clear(CBaseClient* pBaseClient); + +private: + char pad_0000[0x10]; //0x0000 + int32_t m_UserID; //0x0010 + char pad_0014[0x38C]; //0x0014 + void* m_NetChannel; //0x03A0 + char pad_03A8[0x8]; //0x03A8 + SIGNONSTATE m_nSignonState; //0x03B0 + char pad_03B4[0x4]; //0x03B4 + int64_t m_OriginID; //0x03B8 + char pad_03C0[0x1D8]; //0x03C0 +#if defined (GAMEDLL_S2) || defined (GAMEDLL_S3) + int64_t pad_0598; //0x0598 +#endif + bool m_bFakePlayer; //0x05A0 + char pad_05A4[0x18]; //0x05A4 + PERSISTENCE m_nPersistenceState; //0x05BC + char pad_05C0[g_dwCClientPadding]; //0x05C0 +}; namespace { /* ==== CBASECLIENT ===================================================================================================================================================== */ + ADDRESS p_CBaseClient_Connect = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x41\x56\x41\x57\x48\x83\xEC\x20\x48\x8B\xD9\x48\x89\x74", "xxxxxxxxxxxxxxxx"); /*40 53 41 56 41 57 48 83 EC 20 48 8B D9 48 89 74*/ + bool (*CBaseClient_Connect)(CBaseClient* pClient, const char* szName, void* pNetChannel, bool bFakePlayer, void* a5, char* szMessage, int nMessageSize) = (bool (*)(CBaseClient*, const char*, void*, bool, void*, char*, int))p_CBaseClient_Connect.GetPtr(); + ADDRESS p_CBaseClient_Clear = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x41\x56\x41\x57\x48\x83\xEC\x20\x48\x8B\xD9\x48\x89\x74", "xxxxxxxxxxxxxxxx"); - std::int64_t* (*CBaseClient_Clear)(std::int64_t client) = (std::int64_t * (*)(std::int64_t))p_CBaseClient_Clear.GetPtr(); /*40 53 41 56 41 57 48 83 EC 20 48 8B D9 48 89 74*/ + void* (*CBaseClient_Clear)(CBaseClient* pClient) = (void* (*)(CBaseClient*))p_CBaseClient_Clear.GetPtr(); /*40 53 41 56 41 57 48 83 EC 20 48 8B D9 48 89 74*/ } /////////////////////////////////////////////////////////////////////////////// -std::int64_t* HCBaseClient_Clear(std::int64_t client); - void CBaseClient_Attach(); void CBaseClient_Detach(); @@ -18,7 +64,8 @@ class HBaseClient : public IDetour { virtual void debugp() { - std::cout << "| FUN: CBaseClient::Clear : 0x" << std::hex << std::uppercase << p_CBaseClient_Clear.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| FUN: CBaseClient::Connect : 0x" << std::hex << std::uppercase << p_CBaseClient_Connect.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| FUN: CBaseClient::Clear : 0x" << std::hex << std::uppercase << p_CBaseClient_Clear.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl; } }; diff --git a/r5dev/engine/baseserver.cpp b/r5dev/engine/baseserver.cpp new file mode 100644 index 00000000..a8a5c36f --- /dev/null +++ b/r5dev/engine/baseserver.cpp @@ -0,0 +1,57 @@ +//=============================================================================// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// +// baseserver.cpp: implementation of the CBaseServer class. +// +///////////////////////////////////////////////////////////////////////////////// +#include "core/stdafx.h" +#include "common/protocol.h" +#include "engine/baseserver.h" +#include "engine/baseclient.h" + +//--------------------------------------------------------------------------------- +// Purpose: Gets the number of human players on the server +// Output : +// !TODO : Rebuild properly.. +//--------------------------------------------------------------------------------- +int64_t CBaseServer::GetNumHumanPlayers(void) const +{ + uint32_t nHumans = 0; + if (SHIDWORD(*g_dwMaxClients) > 0) + { + bool v13 = false; + uint32_t v14 = 0; + int32_t* v11 = reinterpret_cast(&*m_Clients); // CUtlVector m_Clients. + int64_t nHumanCount = HIDWORD(*g_dwMaxClients); + do + { + if (*(v11 - 124) >= static_cast(SIGNONSTATE::SIGNONSTATE_CONNECTED)) // m_Client[i]->IsConnected(). + v13 = *v11 == 0; + else + v13 = 0; + v14 = nHumans + 1; + if (!v13) + v14 = nHumans; + v11 += 0x12930; + nHumans = v14; + --nHumanCount; + } while (nHumanCount); + } + return nHumans; +} + +//--------------------------------------------------------------------------------- +// Purpose: Gets the number of fake clients on the server +// Output : +//--------------------------------------------------------------------------------- +int64_t CBaseServer::GetNumFakeClients(void) const +{ + // !TODO: Needs partial CBaseClient class rebuild. + return NULL; +} + +CBaseServer* g_pServer = new CBaseServer(); // !TODO: Replace with engine global if found. diff --git a/r5dev/engine/baseserver.h b/r5dev/engine/baseserver.h new file mode 100644 index 00000000..96f3b2a4 --- /dev/null +++ b/r5dev/engine/baseserver.h @@ -0,0 +1,41 @@ +#pragma once +#include "engine/baseclient.h" + +namespace +{ +#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) + int64_t* g_dwMaxClients = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x8B\x05\x00\x00\x00\x00\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x48\x83\xEC\x28\x45\x33\xC0", + "xx????xxxxxxxxxxxxxxxxx").ResolveRelativeAddressSelf(0x2, 0x6).RCast(); /*8B 05 ? ? ? ? C3 CC CC CC CC CC CC CC CC CC 48 83 EC 28 45 33 C0*/ +#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) + int64_t* g_dwMaxClients = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x8B\x05\x00\x00\x00\x00\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x48\x83\xEC\x28\x48\x8B\x05\x00\x00\x00\x00", + "xx????xxxxxxxxxxxxxxxxx????").ResolveRelativeAddressSelf(0x2, 0x6).RCast(); /*8B 05 ? ? ? ? C3 CC CC CC CC CC CC CC CC CC 48 83 EC 28 48 8B 05 ? ? ? ?*/ +#endif + int64_t* g_dwMaxFakeClients = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x8B\x15\x00\x00\x00\x00\x33\xC0\x85\xD2\x7E\x37", + "xx????xxxxxx").ResolveRelativeAddressSelf(0x2, 0x6).RCast(); /*8B 15 ? ? ? ? 33 C0 85 D2 7E 37*/ + + // This is a CUtlVector + CBaseClient* m_Clients = p_IVEngineServer__GetNumHumanPlayers.Offset(0x0).FindPatternSelf("48 8D", ADDRESS::Direction::DOWN).ResolveRelativeAddress(0x3, 0x7).RCast(); +} + +class CBaseServer +{ +public: + int64_t GetNumHumanPlayers(void) const; + int64_t GetNumFakeClients(void) const; +}; +extern CBaseServer* g_pServer; + +/////////////////////////////////////////////////////////////////////////////// +class HBaseServer : public IDetour +{ + virtual void debugp() + { + std::cout << "| VAR: g_dwMaxClients : 0x" << std::hex << std::uppercase << g_dwMaxClients << std::setw(0) << " |" << std::endl; + std::cout << "| VAR: g_dwMaxFakeClients : 0x" << std::hex << std::uppercase << g_dwMaxFakeClients << std::setw(0) << " |" << std::endl; + std::cout << "| VAR: m_Clients : 0x" << std::hex << std::uppercase << m_Clients << std::setw(0) << " |" << std::endl; + std::cout << "+----------------------------------------------------------------+" << std::endl; + } +}; +/////////////////////////////////////////////////////////////////////////////// + +REGISTER(HBaseServer); diff --git a/r5dev/engine/host_state.cpp b/r5dev/engine/host_state.cpp index 7a20bd3a..960bf452 100644 --- a/r5dev/engine/host_state.cpp +++ b/r5dev/engine/host_state.cpp @@ -11,6 +11,7 @@ #include "tier0/fasttimer.h" #include "tier1/NetAdr2.h" #include "tier2/socketcreator.h" +#include "vpc/keyvalues.h" #ifdef DEDICATED #include "engine/sv_rcon.h" #else // @@ -22,6 +23,9 @@ #include "engine/sys_engine.h" #include "engine/sys_utils.h" #include "engine/cmodel_bsp.h" +#ifndef GAMECLIENTONLY +#include "engine/baseserver.h" +#endif // !GAMECLIENTONLY #include "rtech/rtech_game.h" #ifndef DEDICATED #include "vgui/vgui_baseui_interface.h" @@ -29,6 +33,7 @@ #include "client/IVEngineClient.h" #include "networksystem/pylon.h" #include "public/include/bansystem.h" +#include "public/include/edict.h" #ifndef GAMECLIENTONLY #include "game/server/gameinterface.h" #endif // !GAMECLIENTONLY @@ -147,16 +152,17 @@ FORCEINLINE void CHostState::Setup(void) const g_pRConClient->Init(); #endif // DEDICATED - *(bool*)m_bRestrictServerCommands = true; // Restrict commands. - ConCommandBase* disconnect = (ConCommandBase*)g_pCVar->FindCommand("disconnect"); + *reinterpret_cast(m_bRestrictServerCommands) = true; // Restrict commands. + ConCommandBase* disconnect = g_pCVar->FindCommandBase("disconnect"); disconnect->AddFlags(FCVAR_SERVER_CAN_EXECUTE); // Make sure server is not restricted to this. + g_pCVar->FindVar("net_usesocketsforloopback")->SetValue(1); if (net_userandomkey->GetBool()) { HNET_GenerateKey(); } - g_pCVar->FindVar("net_usesocketsforloopback")->SetValue(1); + snprintf(const_cast(m_levelName), sizeof(m_levelName), "no_map"); } //----------------------------------------------------------------------------- @@ -166,12 +172,14 @@ FORCEINLINE void CHostState::Think(void) const { static CFastTimer banListTimer; static CFastTimer pylonTimer; + static CFastTimer statsTimer; static bool bInitialized = false; if (!bInitialized) // Initialize clocks. { banListTimer.Start(); pylonTimer.Start(); + statsTimer.Start(); bInitialized = true; } @@ -186,6 +194,15 @@ FORCEINLINE void CHostState::Think(void) const KeepAliveToPylon(); pylonTimer.Start(); } + if (statsTimer.GetDurationInProgress().GetSeconds() > 1.0) + { + std::string svCurrentPlaylist = KeyValues_GetCurrentPlaylist(); + std::int64_t nPlayerCount = g_pServer->GetNumHumanPlayers(); + + SetConsoleTitleA(fmt::format("{} - {}/{} Players ({} on {})", + g_pCVar->FindVar("hostname")->GetString(), nPlayerCount, g_ServerGlobalVariables->m_nMaxClients, svCurrentPlaylist.c_str(), m_levelName).c_str()); + statsTimer.Start(); + } } //----------------------------------------------------------------------------- @@ -228,6 +245,7 @@ FORCEINLINE void CHostState::GameShutDown(void) g_pServerGameDLL->GameShutdown(); #endif // !GAMECLIENTONLY m_bActiveGame = 0; + snprintf(const_cast(m_levelName), sizeof(m_levelName), "no_map"); } } diff --git a/r5dev/engine/net_chan.cpp b/r5dev/engine/net_chan.cpp index 36f119e3..7f9630b8 100644 --- a/r5dev/engine/net_chan.cpp +++ b/r5dev/engine/net_chan.cpp @@ -132,7 +132,7 @@ void HNET_PrintFunc(const char* fmt, ...) //----------------------------------------------------------------------------- // Purpose: disconnect the client and shutdown netchannel //----------------------------------------------------------------------------- -void NET_DisconnectClient(CClient* pClient, int nIndex, const char* szReason, uint8_t unk1, char unk2) +void NET_DisconnectClient(CBaseClient* pClient, int nIndex, const char* szReason, uint8_t unk1, char unk2) { #ifndef GAMECLIENTONLY if (!pClient) // Client valid? @@ -151,8 +151,8 @@ void NET_DisconnectClient(CClient* pClient, int nIndex, const char* szReason, ui } NET_Shutdown(pClient->GetNetChan(), szReason, unk1, unk2); // Shutdown netchan. - pClient->GetNetChan() = nullptr; // Null netchan. - CBaseClient_Clear((std::int64_t)pClient); // Reset CClient instance for client. + pClient->SetNetChan(nullptr); // Null netchan. + CBaseClient_Clear(pClient); // Reset CClient instance for client. g_bIsPersistenceVarSet[nIndex] = false; // Reset Persistence var. #endif // !GAMECLIENTONLY } diff --git a/r5dev/engine/net_chan.h b/r5dev/engine/net_chan.h index b668d620..c02c3aa1 100644 --- a/r5dev/engine/net_chan.h +++ b/r5dev/engine/net_chan.h @@ -38,7 +38,7 @@ void* HNET_SendDatagram(SOCKET s, const char* szPayload, int iLenght, int nFlags void HNET_SetKey(std::string svNetKey); void HNET_GenerateKey(); void HNET_PrintFunc(const char* fmt, ...); -void NET_DisconnectClient(CClient* pClient, int nIndex, const char* szReason, std::uint8_t unk1, char unk2); +void NET_DisconnectClient(CBaseClient* pClient, int nIndex, const char* szReason, std::uint8_t unk1, char unk2); void CNetChan_Attach(); void CNetChan_Detach(); diff --git a/r5dev/public/bansystem.cpp b/r5dev/public/bansystem.cpp index dc17671b..971d1b76 100644 --- a/r5dev/public/bansystem.cpp +++ b/r5dev/public/bansystem.cpp @@ -6,9 +6,9 @@ //=====================================================================================// #include "core/stdafx.h" -#include "client/client.h" #include "engine/net_chan.h" #include "engine/sys_utils.h" +#include "engine/baseclient.h" #include "public/include/bansystem.h" //----------------------------------------------------------------------------- @@ -201,7 +201,7 @@ void CBanSystem::BanListCheck(void) { for (int c = 0; c < MAX_PLAYERS; c++) // Loop through all possible client instances. { - CClient* client = g_pClient->GetClientInstance(c); // Get client instance. + CBaseClient* client = g_pClient->GetClient(c); // Get client instance. if (!client) { continue; @@ -212,7 +212,7 @@ void CBanSystem::BanListCheck(void) continue; } - if (g_pClient->m_iOriginID != vsvrefuseList[i].second) // See if nucleus id matches entry. + if (g_pClient->GetOriginID() != vsvrefuseList[i].second) // See if nucleus id matches entry. { continue; } @@ -233,7 +233,7 @@ void CBanSystem::BanListCheck(void) DevMsg(eDLL_T::SERVER, "\n"); DevMsg(eDLL_T::SERVER, "______________________________________________________________\n"); DevMsg(eDLL_T::SERVER, "] PYLON_NOTICE -----------------------------------------------\n"); - DevMsg(eDLL_T::SERVER, "] OriginID : | '%lld' IS GETTING DISCONNECTED.\n", g_pClient->m_iOriginID); + DevMsg(eDLL_T::SERVER, "] OriginID : | '%lld' IS GETTING DISCONNECTED.\n", g_pClient->GetOriginID()); if (finalIpAddress.empty()) DevMsg(eDLL_T::SERVER, "] IP-ADDR : | CLIENT MODIFIED PACKET.\n"); else @@ -241,7 +241,7 @@ void CBanSystem::BanListCheck(void) DevMsg(eDLL_T::SERVER, "--------------------------------------------------------------\n"); DevMsg(eDLL_T::SERVER, "\n"); - AddEntry(finalIpAddress, g_pClient->m_iOriginID); // Add local entry to reserve a non needed request. + AddEntry(finalIpAddress, g_pClient->GetOriginID()); // Add local entry to reserve a non needed request. Save(); // Save list. NET_DisconnectClient(g_pClient, c, vsvrefuseList[i].first.c_str(), 0, 1); // Disconnect client. } diff --git a/r5dev/public/include/edict.h b/r5dev/public/include/edict.h index f612acfa..46f22595 100644 --- a/r5dev/public/include/edict.h +++ b/r5dev/public/include/edict.h @@ -3,7 +3,9 @@ #include "launcher/IApplication.h" #endif // !DEDICATED #include "public/include/globalvars_base.h" +#ifndef GAMECLIENTONLY #include "engine/sv_main.h" +#endif // !GAMECLIENTONLY //----------------------------------------------------------------------------- @@ -38,7 +40,9 @@ public: namespace { +#ifndef GAMECLIENTONLY CGlobalVars* g_ServerGlobalVariables = p_SV_InitGameDLL.Offset(0x0).FindPatternSelf("48 8D ?? ?? ?? ?? 01", ADDRESS::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); +#endif // !GAMECLIENTONLY #ifndef DEDICATED CGlobalVarsBase* g_ClientGlobalVariables = p_CModAppSystemGroup_Create.Offset(0x0).FindPatternSelf("4C 8D ?? ?? ?? ?? 01", ADDRESS::Direction::DOWN, 8000).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); #endif // !DEDICATED @@ -49,7 +53,9 @@ class HEdict : public IDetour { virtual void debugp() { +#ifndef GAMECLIENTONLY std::cout << "| VAR: g_ServerGlobalVariables : 0x" << std::hex << std::uppercase << g_ServerGlobalVariables << std::setw(0) << " |" << std::endl; +#endif // !GAMECLIENTONLY #ifndef DEDICATED std::cout << "| VAR: g_ClientGlobalVariables : 0x" << std::hex << std::uppercase << g_ClientGlobalVariables << std::setw(0) << " |" << std::endl; #endif // !DEDICATED diff --git a/r5dev/server/IVEngineServer.cpp b/r5dev/server/IVEngineServer.cpp index ef250cae..6a1ed691 100644 --- a/r5dev/server/IVEngineServer.cpp +++ b/r5dev/server/IVEngineServer.cpp @@ -6,24 +6,25 @@ #include "core/stdafx.h" #include "tier0/cvar.h" +#include "common/protocol.h" #include "engine/sys_utils.h" +#include "engine/baseclient.h" #include "server/IVEngineServer.h" -#include "client/client.h" //----------------------------------------------------------------------------- // Purpose: sets the persistence var in the CClient instance to 'ready' //----------------------------------------------------------------------------- -bool HIVEngineServer_PersistenceAvailable(void* entidx, int clientidx) +bool HIVEngineServer__PersistenceAvailable(void* entidx, int clientidx) { - CClient* pClient = g_pClient->GetClientInstance(clientidx); // Get client instance. - *(char*)((std::uintptr_t)pClient + g_dwPersistenceVar) = (char)0x5; // Set the client instance to 'ready'. + CBaseClient* pClient = g_pClient->GetClient(clientidx); // Get client instance. + pClient->SetPersistenceState(PERSISTENCE::PERSISTENCE_READY); // Set the client instance to 'ready'. if (!g_bIsPersistenceVarSet[clientidx] && sv_showconnecting->GetBool()) { void* clientNamePtr = (void**)(((std::uintptr_t)pClient->GetNetChan()) + 0x1A8D); // Get client name from netchan. - std::string clientName((char*)clientNamePtr, 32); // Get full name. - std::int64_t originID = pClient->m_iOriginID; - std::int64_t clientID = static_cast(pClient->m_iUserID + 1); + std::string clientName((char*)clientNamePtr, 32); // Get full name. + std::int64_t originID = pClient->GetOriginID(); + std::int64_t clientID = static_cast(pClient->GetUserID() + 1); std::string ipAddress = "null"; // If this stays null they modified the packet somehow. ADDRESS ipAddressField = ADDRESS(((std::uintptr_t)pClient->GetNetChan()) + 0x1AC0); // Get client ip from netchan. @@ -52,17 +53,17 @@ bool HIVEngineServer_PersistenceAvailable(void* entidx, int clientidx) g_bIsPersistenceVarSet[clientidx] = true; } /////////////////////////////////////////////////////////////////////////// - return IVEngineServer_PersistenceAvailable(entidx, clientidx); + return IVEngineServer__PersistenceAvailable(entidx, clientidx); } void IVEngineServer_Attach() { - DetourAttach((LPVOID*)&IVEngineServer_PersistenceAvailable, &HIVEngineServer_PersistenceAvailable); + DetourAttach((LPVOID*)&IVEngineServer__PersistenceAvailable, &HIVEngineServer__PersistenceAvailable); } void IVEngineServer_Detach() { - DetourDetach((LPVOID*)&IVEngineServer_PersistenceAvailable, &HIVEngineServer_PersistenceAvailable); + DetourDetach((LPVOID*)&IVEngineServer__PersistenceAvailable, &HIVEngineServer__PersistenceAvailable); } /////////////////////////////////////////////////////////////////////////////// diff --git a/r5dev/server/IVEngineServer.h b/r5dev/server/IVEngineServer.h index 101c4d73..f8fcbb6a 100644 --- a/r5dev/server/IVEngineServer.h +++ b/r5dev/server/IVEngineServer.h @@ -3,17 +3,23 @@ namespace { /* ==== CVENGINESERVER ================================================================================================================================================== */ - ADDRESS p_IVEngineServer_PersistenceAvailable = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x3B\x15\x00\x00\x00\x00\x7D\x33", "xx????xx"); - bool (*IVEngineServer_PersistenceAvailable)(void* entidx, int clientidx) = (bool (*)(void*, int))p_IVEngineServer_PersistenceAvailable.GetPtr(); /*3B 15 ?? ?? ?? ?? 7D 33*/ + ADDRESS p_IVEngineServer__PersistenceAvailable = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x3B\x15\x00\x00\x00\x00\x7D\x33", "xx????xx"); + bool (*IVEngineServer__PersistenceAvailable)(void* entidx, int clientidx) = (bool (*)(void*, int))p_IVEngineServer__PersistenceAvailable.GetPtr(); /*3B 15 ?? ?? ?? ?? 7D 33*/ - ADDRESS p_IVEngineServer_IsDedicatedServer = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x0F\xB6\x05\x00\x00\x00\x00\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x48\x8B\x05\x00\x00\x00\x00\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x40\x53", "xxx????xxxxxxxxxxxx????xxxxxxxxxxx"); - bool (*IVEngineServer_IsDedicatedServer)(void) = (bool (*)(void))p_IVEngineServer_IsDedicatedServer.GetPtr(); /*0F B6 05 ? ? ? ? C3 CC CC CC CC CC CC CC CC 48 8B 05 ? ? ? ? C3 CC CC CC CC CC CC CC CC 40 53*/ + ADDRESS p_IVEngineServer__IsDedicatedServer = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x0F\xB6\x05\x00\x00\x00\x00\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x48\x8B\x05\x00\x00\x00\x00\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x40\x53", "xxx????xxxxxxxxxxxx????xxxxxxxxxxx"); + bool (*IVEngineServer__IsDedicatedServer)(void) = (bool (*)(void))p_IVEngineServer__IsDedicatedServer.GetPtr(); /*0F B6 05 ? ? ? ? C3 CC CC CC CC CC CC CC CC 48 8B 05 ? ? ? ? C3 CC CC CC CC CC CC CC CC 40 53*/ - bool* g_bDedicated = p_IVEngineServer_IsDedicatedServer.Offset(0x0).ResolveRelativeAddress(0x3, 0x7).RCast(); + ADDRESS p_IVEngineServer__GetNumHumanPlayers = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x8B\x15\x00\x00\x00\x00\x33\xC0\x85\xD2\x7E\x24", "xx????xxxxxx"); + int64_t(*IVEngineServer__GetNumHumanPlayers)(void) = (int64_t(*)(void))p_IVEngineServer__GetNumHumanPlayers.GetPtr(); /*8B 15 ? ? ? ? 33 C0 85 D2 7E 24*/ + + ADDRESS p_IVEngineServer__GetNumFakeClients = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x8B\x05\x00\x00\x00\x00\x33\xC9\x85\xC0\x7E\x2D", "xx????xxxxxx"); + int64_t(*IVEngineServer__GetNumFakeClients)(void) = (int64_t(*)(void))p_IVEngineServer__GetNumFakeClients.GetPtr(); /*8B 05 ? ? ? ? 33 C9 85 C0 7E 2D*/ + + bool* g_bDedicated = p_IVEngineServer__IsDedicatedServer.Offset(0x0).ResolveRelativeAddress(0x3, 0x7).RCast(); } /////////////////////////////////////////////////////////////////////////////// -bool HIVEngineServer_PersistenceAvailable(void* entidx, int clientidx); +bool HIVEngineServer__PersistenceAvailable(void* entidx, int clientidx); void IVEngineServer_Attach(); void IVEngineServer_Detach(); @@ -26,9 +32,11 @@ class HVEngineServer : public IDetour { virtual void debugp() { - std::cout << "| FUN: IVEngineServer::PersistenceAvailable : 0x" << std::hex << std::uppercase << p_IVEngineServer_PersistenceAvailable.GetPtr() << std::setw(npad) << " |" << std::endl; - std::cout << "| FUN: IVEngineServer::IsDedicatedServer : 0x" << std::hex << std::uppercase << p_IVEngineServer_IsDedicatedServer.GetPtr() << std::setw(npad) << " |" << std::endl; - std::cout << "| VAR: g_bDedicated : 0x" << std::hex << std::uppercase << g_bDedicated << std::setw(0) << " |" << std::endl; + std::cout << "| FUN: IVEngineServer::PersistenceAvailable : 0x" << std::hex << std::uppercase << p_IVEngineServer__PersistenceAvailable.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| FUN: IVEngineServer::IsDedicatedServer : 0x" << std::hex << std::uppercase << p_IVEngineServer__IsDedicatedServer.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| FUN: IVEngineServer::GetNumHumanPlayers : 0x" << std::hex << std::uppercase << p_IVEngineServer__GetNumHumanPlayers.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| FUN: IVEngineServer::GetNumFakeClients : 0x" << std::hex << std::uppercase << p_IVEngineServer__GetNumFakeClients.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| VAR: g_bDedicated : 0x" << std::hex << std::uppercase << g_bDedicated << std::setw(0) << " |" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl; } }; diff --git a/r5dev/tier0/completion.cpp b/r5dev/tier0/completion.cpp index d7c4a72e..4bb3115d 100644 --- a/r5dev/tier0/completion.cpp +++ b/r5dev/tier0/completion.cpp @@ -14,6 +14,7 @@ #endif // !DEDICATED #include "engine/net_chan.h" #include "engine/sys_utils.h" +#include "engine/baseclient.h" #include "rtech/rtech_game.h" #include "rtech/rtech_utils.h" #include "vpklib/packedstore.h" @@ -64,7 +65,7 @@ void _Kick_f_CompletionFunc(const CCommand& args) for (int i = 0; i < MAX_PLAYERS; i++) { - CClient* client = g_pClient->GetClientInstance(i); + CBaseClient* client = g_pClient->GetClient(i); if (!client) { continue; @@ -121,7 +122,7 @@ void _KickID_f_CompletionFunc(const CCommand& args) bool onlyDigits = HasOnlyDigits(args.Arg(1)); for (int i = 0; i < MAX_PLAYERS; i++) { - CClient* client = g_pClient->GetClientInstance(i); + CBaseClient* client = g_pClient->GetClient(i); if (!client) { continue; @@ -150,7 +151,7 @@ void _KickID_f_CompletionFunc(const CCommand& args) std::int64_t ID = static_cast(std::stoll(args.Arg(1))); if (ID > MAX_PLAYERS) // Is it a possible originID? { - std::int64_t originID = client->m_iOriginID; + std::int64_t originID = client->GetOriginID(); if (originID != ID) { continue; @@ -158,7 +159,7 @@ void _KickID_f_CompletionFunc(const CCommand& args) } else // If its not try by userID. { - std::int64_t clientID = static_cast(client->m_iUserID + 1); // Get UserID + 1. + std::int64_t clientID = static_cast(client->GetOriginID() + 1); // Get UserID + 1. if (clientID != ID) { continue; @@ -199,7 +200,7 @@ void _Ban_f_CompletionFunc(const CCommand& args) for (int i = 0; i < MAX_PLAYERS; i++) { - CClient* client = g_pClient->GetClientInstance(i); + CBaseClient* client = g_pClient->GetClient(i); if (!client) { continue; @@ -236,7 +237,7 @@ void _Ban_f_CompletionFunc(const CCommand& args) finalIpAddress = ss.str(); } - g_pBanSystem->AddEntry(finalIpAddress, client->m_iOriginID); + g_pBanSystem->AddEntry(finalIpAddress, client->GetOriginID()); g_pBanSystem->Save(); NET_DisconnectClient(client, i, "Banned from Server", 0, 1); } @@ -271,7 +272,7 @@ void _BanID_f_CompletionFunc(const CCommand& args) bool onlyDigits = HasOnlyDigits(args.Arg(1)); for (int i = 0; i < MAX_PLAYERS; i++) { - CClient* client = g_pClient->GetClientInstance(i); + CBaseClient* client = g_pClient->GetClient(i); if (!client) { continue; @@ -300,7 +301,7 @@ void _BanID_f_CompletionFunc(const CCommand& args) std::int64_t ID = static_cast(std::stoll(args.Arg(1))); if (ID > MAX_PLAYERS) // Is it a possible originID? { - std::int64_t originID = client->m_iOriginID; + std::int64_t originID = client->GetOriginID(); if (originID != ID) { continue; @@ -308,14 +309,14 @@ void _BanID_f_CompletionFunc(const CCommand& args) } else // If its not try by userID. { - std::int64_t clientID = static_cast(client->m_iUserID + 1); // Get UserID + 1. + std::int64_t clientID = static_cast(client->GetUserID() + 1); // Get UserID + 1. if (clientID != ID) { continue; } } - g_pBanSystem->AddEntry(finalIpAddress, client->m_iOriginID); + g_pBanSystem->AddEntry(finalIpAddress, client->GetOriginID()); g_pBanSystem->Save(); NET_DisconnectClient(client, i, "Banned from Server", 0, 1); } @@ -326,7 +327,7 @@ void _BanID_f_CompletionFunc(const CCommand& args) continue; } - g_pBanSystem->AddEntry(finalIpAddress, client->m_iOriginID); + g_pBanSystem->AddEntry(finalIpAddress, client->GetOriginID()); g_pBanSystem->Save(); NET_DisconnectClient(client, i, "Banned from Server", 0, 1); } diff --git a/r5dev/vpc/keyvalues.h b/r5dev/vpc/keyvalues.h index 44db26db..174632a7 100644 --- a/r5dev/vpc/keyvalues.h +++ b/r5dev/vpc/keyvalues.h @@ -29,19 +29,25 @@ namespace ADDRESS p_KeyValues_FindKey = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x10\x48\x89\x6C\x24\x18\x48\x89\x74\x24\x20\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x81\xEC\x20\x01\x00\x00\x45", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); void* (*KeyValues_FindKey)(void* a1, const char* a2, bool a3) = (void* (*)(void*, const char*, bool))p_KeyValues_FindKey.GetPtr(); /*48 89 5C 24 10 48 89 6C 24 18 48 89 74 24 20 57 41 54 41 55 41 56 41 57 48 81 EC 20 01 00 00 45*/ + + ADDRESS p_KeyValues_GetCurrentPlaylist = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x8B\x0D\x00\x00\x00\x00\x48\x85\xC9\x75\x08\x48\x8D\x05\x00\x00\x00\x00", "xxx????xxxxxxxx????"); + const char* (*KeyValues_GetCurrentPlaylist)() = (const char* (*)())p_KeyValues_GetCurrentPlaylist.GetPtr(); /*48 8B 0D ? ? ? ? 48 85 C9 75 08 48 8D 05 ? ? ? ?*/ #elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) ADDRESS p_KeyValues_Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x48\x8B\x05\x00\x00\x00\x01\x48\x8B\xD9\x4C\x8B\xC2", "xxxxxxxxx???xxxxxxx"); /*40 53 48 83 EC 20 48 8B 05 ?? ?? ?? 01 48 8B D9 4C 8B C2*/ void* (*KeyValues_Init)(std::int64_t a1, std::int64_t a2, std::int64_t a3, std::int64_t a4) = (void* (*)(std::int64_t, std::int64_t, std::int64_t, std::int64_t))p_KeyValues_Init.GetPtr(); ADDRESS p_KeyValues_FindKey = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x56\x57\x41\x57\x48\x81\xEC\x00\x00\x00\x00\x45", "xxxxxxxx????x"); void* (*KeyValues_FindKey)(void* a1, const char* a2, bool a3) = (void* (*)(void*, const char*, bool))p_KeyValues_FindKey.GetPtr(); /*40 56 57 41 57 48 81 EC 30 01 00 00 45 0F B6 F8*/ -#endif - ADDRESS p_KeyValues_LoadPlaylist = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\xE8\x00\x00\x00\x00\x80\x3D\x00\x00\x00\x00\x00\x74\x0C", "x????xx?????xx").FollowNearCallSelf().GetPtr(); - bool (*KeyValues_LoadPlaylist)(const char* source) = (bool (*)(const char*))p_KeyValues_LoadPlaylist.GetPtr(); /*E8 ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 74 0C*/ + ADDRESS p_KeyValues_GetCurrentPlaylist = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x8B\x05\x00\x00\x00\x00\x48\x85\xC0\x75\x08\x48\x8D\x05\x00\x00\x00\x00\xC3\x0F\xB7\x50\x2A", "xxx????xxxxxxxx????xxxxx"); + const char* (*KeyValues_GetCurrentPlaylist)() = (const char* (*)())p_KeyValues_GetCurrentPlaylist.GetPtr(); /*48 8B 05 ? ? ? ? 48 85 C0 75 08 48 8D 05 ? ? ? ? C3 0F B7 50 2A*/ +#endif ADDRESS p_KeyValues_GetMemPool = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x8B\x05\x00\x00\x00\x00\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x48\x85\xD2", "xxx????xxxxxxxxxxxx"); void* (*KeyValues_GetMemPool)() = (void* (*)())p_KeyValues_GetMemPool.GetPtr(); /*48 8B 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 48 85 D2*/ + ADDRESS p_KeyValues_LoadPlaylist = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\xE8\x00\x00\x00\x00\x80\x3D\x00\x00\x00\x00\x00\x74\x0C", "x????xx?????xx").FollowNearCallSelf().GetPtr(); + bool (*KeyValues_LoadPlaylist)(const char* source) = (bool (*)(const char*))p_KeyValues_LoadPlaylist.GetPtr(); /*E8 ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 74 0C*/ + std::uintptr_t g_pKeyValuesMemPool = p_KeyValues_GetMemPool.ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(); } @@ -238,13 +244,14 @@ class HKeyValues : public IDetour { virtual void debugp() { - std::cout << "| FUN: KeyValues::Init : 0x" << std::hex << std::uppercase << p_KeyValues_Init.GetPtr() << std::setw(npad) << " |" << std::endl; - std::cout << "| FUN: KeyValues::FindKey : 0x" << std::hex << std::uppercase << p_KeyValues_FindKey.GetPtr() << std::setw(npad) << " |" << std::endl; - std::cout << "| FUN: KeyValues::LoadPlaylist : 0x" << std::hex << std::uppercase << p_KeyValues_LoadPlaylist.GetPtr() << std::setw(npad) << " |" << std::endl; - std::cout << "| FUN: KeyValues::GetMemPool : 0x" << std::hex << std::uppercase << p_KeyValues_GetMemPool.GetPtr() << std::setw(npad) << " |" << std::endl; - std::cout << "| VAR: g_pKeyValuesMemPool : 0x" << std::hex << std::uppercase << g_pKeyValuesMemPool << std::setw(npad) << " |" << std::endl; - std::cout << "| VAR: g_pKeyValuesSystem : 0x" << std::hex << std::uppercase << g_pKeyValuesSystem << std::setw(0) << " |" << std::endl; - std::cout << "| VAR: g_pPlaylistKeyValues : 0x" << std::hex << std::uppercase << g_pPlaylistKeyValues << std::setw(0) << " |" << std::endl; + std::cout << "| FUN: KeyValues::Init : 0x" << std::hex << std::uppercase << p_KeyValues_Init.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| FUN: KeyValues::FindKey : 0x" << std::hex << std::uppercase << p_KeyValues_FindKey.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| FUN: KeyValues::GetMemPool : 0x" << std::hex << std::uppercase << p_KeyValues_GetMemPool.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| FUN: KeyValues::LoadPlaylist : 0x" << std::hex << std::uppercase << p_KeyValues_LoadPlaylist.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| FUN: KeyValues::GetCurrentPlaylist : 0x" << std::hex << std::uppercase << p_KeyValues_GetCurrentPlaylist.GetPtr() << std::setw(npad) << " |" << std::endl; + std::cout << "| VAR: g_pKeyValuesMemPool : 0x" << std::hex << std::uppercase << g_pKeyValuesMemPool << std::setw(npad) << " |" << std::endl; + std::cout << "| VAR: g_pKeyValuesSystem : 0x" << std::hex << std::uppercase << g_pKeyValuesSystem << std::setw(0) << " |" << std::endl; + std::cout << "| VAR: g_pPlaylistKeyValues : 0x" << std::hex << std::uppercase << g_pPlaylistKeyValues << std::setw(0) << " |" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl; } };