diff --git a/src/engine/client/cdll_engine_int.cpp b/src/engine/client/cdll_engine_int.cpp index 14c6c5b9..8000e6b9 100644 --- a/src/engine/client/cdll_engine_int.cpp +++ b/src/engine/client/cdll_engine_int.cpp @@ -20,6 +20,17 @@ #endif // !DEDICATED /*****************************************************************************/ +static CGlobalVarsBase dummyvars(true); +// So stuff that might reference gpGlobals during DLL initialization won't have a NULL pointer. +// Once the engine calls Init on this DLL, this pointer gets assigned to the shared data in the engine +CGlobalVarsBase* gpGlobals = &dummyvars; + +int CHLClient::Init(CHLClient* thisptr, CreateInterfaceFn appSystemFactory, CGlobalVarsBase* pGlobals) +{ + gpGlobals = pGlobals; + return CHLClient__Init(thisptr, appSystemFactory, pGlobals); +} + #ifndef DEDICATED //----------------------------------------------------------------------------- // Purpose: pre frame stage notify hook @@ -99,6 +110,7 @@ ClientClass* CHLClient::GetAllClasses() void VDll_Engine_Int::Detour(const bool bAttach) const { #ifndef DEDICATED + DetourSetup(&CHLClient__Init, &CHLClient::Init, bAttach); DetourSetup(&CHLClient__FrameStageNotify, &CHLClient::FrameStageNotify, bAttach); #endif // !DEDICATED } diff --git a/src/engine/client/cdll_engine_int.h b/src/engine/client/cdll_engine_int.h index ce2972e0..9dbe971c 100644 --- a/src/engine/client/cdll_engine_int.h +++ b/src/engine/client/cdll_engine_int.h @@ -1,5 +1,6 @@ #pragma once #ifndef DEDICATED // We should think about not including this file at all in dedicated tbh. +#include "public/globalvars_base.h" #include "public/client_class.h" #include "public/icliententitylist.h" #endif // !DEDICATED @@ -30,6 +31,7 @@ enum class ClientFrameStage_t : int class CHLClient { public: + static int Init(CHLClient* thisptr, CreateInterfaceFn appSystemFactory, CGlobalVarsBase* pGlobals); static void FrameStageNotify(CHLClient* pHLClient, ClientFrameStage_t curStage); #ifndef DEDICATED @@ -57,6 +59,7 @@ public: /* ==== CHLCLIENT ======================================================================================================================================================= */ #ifndef DEDICATED +inline int(*CHLClient__Init)(CHLClient* thisptr, CreateInterfaceFn appSystemFactory, CGlobalVarsBase* pGlobals); inline void*(*CHLClient__PostInit)(void); inline void*(*CHLClient__LevelShutdown)(CHLClient* thisptr); inline void(*CHLClient__HudProcessInput)(CHLClient* thisptr, bool bActive); @@ -73,6 +76,7 @@ class VDll_Engine_Int : public IDetour virtual void GetAdr(void) const { #ifndef DEDICATED + LogFunAdr("CHLClient::Init", CHLClient__Init); LogFunAdr("CHLClient::PostInit", CHLClient__PostInit); LogFunAdr("CHLClient::LevelShutdown", CHLClient__LevelShutdown); LogFunAdr("CHLClient::HudProcessInput", CHLClient__HudProcessInput); @@ -85,8 +89,9 @@ class VDll_Engine_Int : public IDetour virtual void GetFun(void) const { #ifndef DEDICATED - g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F9 48 8D 0D ?? ?? ?? ??").GetPtr(CHLClient__LevelShutdown); + g_GameDll.FindPatternSIMD("40 53 48 83 EC ?? 80 3D ?? ?? ?? ?? ?? 49 8B D8 75").GetPtr(CHLClient__Init); g_GameDll.FindPatternSIMD("48 83 EC 28 48 83 3D ?? ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ??").GetPtr(CHLClient__PostInit); + g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B F9 48 8D 0D ?? ?? ?? ??").GetPtr(CHLClient__LevelShutdown); g_GameDll.FindPatternSIMD("48 83 EC 28 89 15 ?? ?? ?? ??").GetPtr(CHLClient__FrameStageNotify); g_GameDll.FindPatternSIMD("48 8B 05 ?? ?? ?? ?? C3 CC CC CC CC CC CC CC CC 48 8B 05 ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ??").GetPtr(CHLClient__GetAllClasses); #endif // !DEDICATED diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 4c380ce6..158e11a5 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -19,6 +19,7 @@ #include "jwt/include/decode.h" #include "mbedtls/include/mbedtls/sha256.h" #endif +#include "game/server/gameinterface.h" // Absolute max string cmd length, any character past this will be NULLED. #define STRINGCMD_MAX_LEN 512 @@ -371,7 +372,7 @@ void CClient::WriteDataBlock(CClient* pClient, bf_write& buf) buf.WriteUBitLong(net_NOP, 8 - remainingBits); } - const bool isMultiplayer = g_ServerGlobalVariables->m_nGameMode < GameMode_t::PVE_MODE; + const bool isMultiplayer = gpGlobals->gameMode < GameMode_t::PVE_MODE; pClient->m_DataBlock.sender.WriteDataBlock(buf.GetData(), buf.GetNumBytesWritten(), isMultiplayer, buf.GetDebugName()); } else diff --git a/src/engine/host_state.cpp b/src/engine/host_state.cpp index 9871e075..a3042ffe 100644 --- a/src/engine/host_state.cpp +++ b/src/engine/host_state.cpp @@ -89,7 +89,7 @@ static void HostState_KeepAlive() *g_nServerRemoteChecksum, SDK_VERSION, g_pServer->GetNumClients(), - g_ServerGlobalVariables->m_nMaxClients, + gpGlobals->maxClients, std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch() ).count() @@ -141,7 +141,7 @@ void HostState_HandleAutoReload() { if (host_autoReloadRate.GetBool()) { - if (g_ServerGlobalVariables->m_flCurTime > host_autoReloadRate.GetFloat()) + if (gpGlobals->curTime > host_autoReloadRate.GetFloat()) { // We should respect the game state, and the game isn't finished yet so // don't reload the server now. @@ -368,7 +368,7 @@ void CHostState::Think(void) const { SetConsoleTitleA(Format("%s - %d/%d Players (%s on %s) - %d%% Server CPU (%.3f msec on frame %d)", hostname->GetString(), g_pServer->GetNumClients(), - g_ServerGlobalVariables->m_nMaxClients, v_Playlists_GetCurrent(), m_levelName, + gpGlobals->maxClients, v_Playlists_GetCurrent(), m_levelName, static_cast(g_pServer->GetCPUUsage() * 100.0f), (g_pEngine->GetFrameTime() * 1000.0f), g_pServer->GetTick()).c_str()); diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 8e5676ab..aa32aab0 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -21,6 +21,7 @@ #include "public/edict.h" #include "pluginsystem/pluginsystem.h" #include "rtech/liveapi/liveapi.h" +#include "game/server/gameinterface.h" //--------------------------------------------------------------------------------- // Console variables @@ -44,7 +45,7 @@ static ConVar sv_maxPersonaNameLength("sv_maxPersonaNameLength", "16", FCVAR_REL int CServer::GetNumHumanPlayers(void) const { int nHumans = 0; - for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++) + for (int i = 0; i < gpGlobals->maxClients; i++) { CClient* pClient = g_pServer->GetClient(i); if (!pClient) @@ -64,7 +65,7 @@ int CServer::GetNumHumanPlayers(void) const int CServer::GetNumFakeClients(void) const { int nBots = 0; - for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++) + for (int i = 0; i < gpGlobals->maxClients; i++) { CClient* pClient = g_pServer->GetClient(i); if (!pClient) @@ -84,7 +85,7 @@ int CServer::GetNumFakeClients(void) const int CServer::GetNumClients(void) const { int nClients = 0; - for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++) + for (int i = 0; i < gpGlobals->maxClients; i++) { CClient* pClient = g_pServer->GetClient(i); if (!pClient) diff --git a/src/engine/server/sv_main.cpp b/src/engine/server/sv_main.cpp index 144448a9..48927162 100644 --- a/src/engine/server/sv_main.cpp +++ b/src/engine/server/sv_main.cpp @@ -13,6 +13,7 @@ #include "networksystem/bansystem.h" #include "engine/client/client.h" #include "server.h" +#include "game/server/gameinterface.h" //----------------------------------------------------------------------------- // Purpose: checks if particular client is banned on the comp server @@ -73,7 +74,7 @@ void SV_CheckClientsForBan(const CBanSystem::BannedList_t* const pBannedVec /*= ? new CBanSystem::BannedList_t : nullptr; - for (int c = 0; c < g_ServerGlobalVariables->m_nMaxClients; c++) // Loop through all possible client instances. + for (int c = 0; c < gpGlobals->maxClients; c++) // Loop through all possible client instances. { CClient* const pClient = g_pServer->GetClient(c); @@ -176,7 +177,7 @@ bool SV_CanBroadcastVoice() if (!sv_voiceenable->GetBool()) return false; - if (g_ServerGlobalVariables->m_nMaxClients <= 0) + if (gpGlobals->maxClients <= 0) return false; return true; @@ -192,7 +193,7 @@ void SV_BroadcastVoiceData(CClient* const cl, const int nBytes, char* const data SVC_VoiceData voiceData(cl->GetUserID(), nBytes, data); - for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++) + for (int i = 0; i < gpGlobals->maxClients; i++) { CClient* const pClient = g_pServer->GetClient(i); @@ -239,7 +240,7 @@ void SV_BroadcastDurangoVoiceData(CClient* const cl, const int nBytes, char* con SVC_DurangoVoiceData voiceData(cl->GetUserID(), nBytes, data, unknown, useVoiceStream); - for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++) + for (int i = 0; i < gpGlobals->maxClients; i++) { CClient* const pClient = g_pServer->GetClient(i); diff --git a/src/game/server/ai_interest.cpp b/src/game/server/ai_interest.cpp index 60c9364c..31d94929 100644 --- a/src/game/server/ai_interest.cpp +++ b/src/game/server/ai_interest.cpp @@ -24,14 +24,14 @@ bool CAI_InterestTarget_t::IsThis(CBaseEntity* pThis) bool CAI_InterestTarget_t::IsActive(void) { - if (m_flEndTime < (*g_pGlobals)->m_flCurTime) return false; + if (m_flEndTime < gpGlobals->curTime) return false; if (m_eType == LOOKAT_ENTITY && m_hTarget == NULL) return false; return true; }; float CAI_InterestTarget_t::Interest(void) { - float t = ((*g_pGlobals)->m_flCurTime - m_flStartTime) / (m_flEndTime - m_flStartTime); + float t = (gpGlobals->curTime - m_flStartTime) / (m_flEndTime - m_flStartTime); if (t < 0.0f || t > 1.0f) return 0.0f; @@ -67,7 +67,7 @@ void CAI_InterestTarget::Add(CBaseEntity* pTarget, float flImportance, float flD if (target.m_hTarget == pTarget && target.m_rampDuration == 0) { - if (target.m_flStartTime == (*g_pGlobals)->m_flCurTime) + if (target.m_flStartTime == gpGlobals->curTime) { flImportance = MAX(flImportance, target.m_flInterest); } @@ -107,7 +107,7 @@ void CAI_InterestTarget::Add(CBaseEntity* pTarget, const Vector3D& vecPosition, if (target.m_hTarget == pTarget) { - if (target.m_flStartTime == (*g_pGlobals)->m_flCurTime) + if (target.m_flStartTime == gpGlobals->curTime) { flImportance = MAX(flImportance, target.m_flInterest); } @@ -128,7 +128,7 @@ void CAI_InterestTarget::Add(CAI_InterestTarget_t::CAI_InterestTarget_e type, CB target.m_hTarget = pTarget; target.m_vecPosition = vecPosition; target.m_flInterest = flImportance; - target.m_flStartTime = (*g_pGlobals)->m_flCurTime; - target.m_flEndTime = (*g_pGlobals)->m_flCurTime + flDuration; + target.m_flStartTime = gpGlobals->curTime; + target.m_flEndTime = gpGlobals->curTime + flDuration; target.m_rampDuration = flRamp / flDuration; } \ No newline at end of file diff --git a/src/game/server/ai_networkmanager.cpp b/src/game/server/ai_networkmanager.cpp index 2b736ab6..81f32bb5 100644 --- a/src/game/server/ai_networkmanager.cpp +++ b/src/game/server/ai_networkmanager.cpp @@ -40,8 +40,8 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork) char szMeshPath[MAX_PATH]; char szGraphPath[MAX_PATH]; - V_snprintf(szMeshPath, sizeof(szMeshPath), "%s%s_%s%s", NAVMESH_PATH, g_ServerGlobalVariables->m_pszMapName, NavMesh_GetNameForType(NAVMESH_LARGE), NAVMESH_EXT); - V_snprintf(szGraphPath, sizeof(szGraphPath), "%s%s%s", AINETWORK_PATH, g_ServerGlobalVariables->m_pszMapName, AINETWORK_EXT); + V_snprintf(szMeshPath, sizeof(szMeshPath), "%s%s_%s%s", NAVMESH_PATH, gpGlobals->mapName.ToCStr(), NavMesh_GetNameForType(NAVMESH_LARGE), NAVMESH_EXT); + V_snprintf(szGraphPath, sizeof(szGraphPath), "%s%s%s", AINETWORK_PATH, gpGlobals->mapName.ToCStr(), AINETWORK_EXT); CFastTimer masterTimer; CFastTimer timer; @@ -69,7 +69,7 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork) // Large NavMesh CRC. DevMsg(eDLL_T::SERVER, " |-- AINet version: '%d'\n", AINET_VERSION_NUMBER); - DevMsg(eDLL_T::SERVER, " |-- Map version: '%d'\n", g_ServerGlobalVariables->m_nMapVersion); + DevMsg(eDLL_T::SERVER, " |-- Map version: '%d'\n", gpGlobals->mapVersion); DevMsg(eDLL_T::SERVER, " |-- Runtime CRC: '0x%lX'\n", (*g_ppAINetworkManager)->GetRuntimeCRC()); CUtlBuffer buf; @@ -78,7 +78,7 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork) // Save the version numbers // --------------------------- buf.PutInt(AINET_VERSION_NUMBER); - buf.PutInt(g_ServerGlobalVariables->m_nMapVersion); + buf.PutInt(gpGlobals->mapVersion); buf.PutInt((*g_ppAINetworkManager)->GetRuntimeCRC()); timer.End(); @@ -419,8 +419,8 @@ void CAI_NetworkManager::LoadNetworkGraph(CAI_NetworkManager* pManager, CUtlBuff char szMeshPath[MAX_PATH]; char szGraphPath[MAX_PATH]; - V_snprintf(szMeshPath, sizeof(szMeshPath), "%s%s_%s%s", NAVMESH_PATH, g_ServerGlobalVariables->m_pszMapName, NavMesh_GetNameForType(NAVMESH_LARGE), NAVMESH_EXT); - V_snprintf(szGraphPath, sizeof(szGraphPath), "%s%s%s", AINETWORK_PATH, g_ServerGlobalVariables->m_pszMapName, AINETWORK_EXT); + V_snprintf(szMeshPath, sizeof(szMeshPath), "%s%s_%s%s", NAVMESH_PATH, gpGlobals->mapName.ToCStr(), NavMesh_GetNameForType(NAVMESH_LARGE), NAVMESH_EXT); + V_snprintf(szGraphPath, sizeof(szGraphPath), "%s%s%s", AINETWORK_PATH, gpGlobals->mapName.ToCStr(), AINETWORK_EXT); int nAiNetVersion = NULL; int nAiMapVersion = NULL; @@ -474,10 +474,10 @@ void CAI_NetworkManager::LoadNetworkGraph(CAI_NetworkManager* pManager, CUtlBuff } // AIN file was build with a different version of the map, therefore, // the path node positions might be invalid. - else if (nAiMapVersion != g_ServerGlobalVariables->m_nMapVersion) + else if (nAiMapVersion != gpGlobals->mapVersion) { Warning(eDLL_T::SERVER, "AI node graph '%s' is out of date (map version: '%d' expected: '%d')\n", - szGraphPath, nAiMapVersion, g_ServerGlobalVariables->m_nMapVersion); + szGraphPath, nAiMapVersion, gpGlobals->mapVersion); } // Data checksum is now what the runtime expects. else if (nAiGraphCRC != nAiRuntimeCRC) diff --git a/src/game/server/ai_utility.cpp b/src/game/server/ai_utility.cpp index f6eee3a5..e2e99e5e 100644 --- a/src/game/server/ai_utility.cpp +++ b/src/game/server/ai_utility.cpp @@ -107,7 +107,7 @@ bool Detour_IsLoaded() if (!nav) // Failed to load... { Warning(eDLL_T::SERVER, "NavMesh '%s%s_%s%s' not loaded\n", - NAVMESH_PATH, g_ServerGlobalVariables->m_pszMapName, + NAVMESH_PATH, gpGlobals->mapName.ToCStr(), NavMesh_GetNameForType(NavMeshType_e(i)), NAVMESH_EXT); ret++; @@ -167,7 +167,7 @@ static void Detour_HotSwap_f() return; // Only execute if server is initialized and active. Msg(eDLL_T::SERVER, "Executing NavMesh hot swap for level '%s'\n", - g_ServerGlobalVariables->m_pszMapName); + gpGlobals->mapName.ToCStr()); CFastTimer timer; diff --git a/src/game/server/gameinterface.cpp b/src/game/server/gameinterface.cpp index d138885b..14d31b79 100644 --- a/src/game/server/gameinterface.cpp +++ b/src/game/server/gameinterface.cpp @@ -20,6 +20,13 @@ #include "game/server/util_server.h" #include "pluginsystem/pluginsystem.h" +bool CServerGameDLL::DLLInit(CServerGameDLL* thisptr, CreateInterfaceFn appSystemFactory, CreateInterfaceFn physicsFactory, + CreateInterfaceFn fileSystemFactory, CGlobalVars* pGlobals) +{ + gpGlobals = pGlobals; + return CServerGameDLL__DLLInit(thisptr, appSystemFactory, physicsFactory, fileSystemFactory, pGlobals); +} + //----------------------------------------------------------------------------- // This is called when a new game is started. (restart, map) //----------------------------------------------------------------------------- @@ -80,14 +87,13 @@ ServerClass* CServerGameDLL::GetAllServerClasses(void) static ConVar chat_debug("chat_debug", "0", FCVAR_RELEASE, "Enables chat-related debug printing."); -void __fastcall CServerGameDLL::OnReceivedSayTextMessage(void* thisptr, int senderId, const char* text, bool isTeamChat) +void CServerGameDLL::OnReceivedSayTextMessage(CServerGameDLL* thisptr, int senderId, const char* text, bool isTeamChat) { - const CGlobalVars* globals = *g_pGlobals; if (senderId > 0) { - if (senderId <= globals->m_nMaxPlayers && senderId != 0xFFFF) + if (senderId <= gpGlobals->maxPlayers && senderId != 0xFFFF) { - CPlayer* player = reinterpret_cast(globals->m_pEdicts[senderId + 30728]); + CPlayer* player = reinterpret_cast(gpGlobals->m_pEdicts[senderId + 30728]); if (player && player->IsConnected()) { @@ -201,6 +207,7 @@ void RunFrameServer(double flFrameTime, bool bRunOverlays, bool bUniformUpdate) void VServerGameDLL::Detour(const bool bAttach) const { + DetourSetup(&CServerGameDLL__DLLInit, &CServerGameDLL::DLLInit, bAttach); DetourSetup(&CServerGameDLL__OnReceivedSayTextMessage, &CServerGameDLL::OnReceivedSayTextMessage, bAttach); DetourSetup(&CServerGameClients__ProcessUserCmds, CServerGameClients::ProcessUserCmds, bAttach); DetourSetup(&v_RunFrameServer, &RunFrameServer, bAttach); @@ -211,4 +218,4 @@ CServerGameClients* g_pServerGameClients = nullptr; CServerGameEnts* g_pServerGameEntities = nullptr; // Holds global variables shared between engine and game. -CGlobalVars** g_pGlobals = nullptr; +CGlobalVars* gpGlobals = nullptr; diff --git a/src/game/server/gameinterface.h b/src/game/server/gameinterface.h index e89084bd..791eeed5 100644 --- a/src/game/server/gameinterface.h +++ b/src/game/server/gameinterface.h @@ -26,7 +26,10 @@ public: float GetTickInterval(void); ServerClass* GetAllServerClasses(void); - static void __fastcall OnReceivedSayTextMessage(void* thisptr, int senderId, const char* text, bool isTeamChat); +public: // Hook statics + static bool DLLInit(CServerGameDLL* thisptr, CreateInterfaceFn appSystemFactory, CreateInterfaceFn physicsFactory, + CreateInterfaceFn fileSystemFactory, CGlobalVars* pGlobals); + static void OnReceivedSayTextMessage(CServerGameDLL* thisptr, int senderId, const char* text, bool isTeamChat); }; //----------------------------------------------------------------------------- @@ -47,8 +50,9 @@ class CServerGameEnts : public IServerGameEnts { }; -inline void(*CServerGameDLL__OnReceivedSayTextMessage)(void* thisptr, int senderId, const char* text, bool isTeamChat); +inline bool(*CServerGameDLL__DLLInit)(CServerGameDLL* thisptr, CreateInterfaceFn appSystemFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn fileSystemFactory, CGlobalVars* pGlobals); inline bool(*CServerGameDLL__GameInit)(void); +inline void(*CServerGameDLL__OnReceivedSayTextMessage)(CServerGameDLL* thisptr, int senderId, const char* text, bool isTeamChat); inline void(*CServerGameClients__ProcessUserCmds)(CServerGameClients* thisp, edict_t edict, bf_read* buf, int numCmds, int totalCmds, int droppedPackets, bool ignore, bool paused); @@ -61,33 +65,33 @@ extern CServerGameDLL* g_pServerGameDLL; extern CServerGameClients* g_pServerGameClients; extern CServerGameEnts* g_pServerGameEntities; -extern CGlobalVars** g_pGlobals; +extern CGlobalVars* gpGlobals; /////////////////////////////////////////////////////////////////////////////// class VServerGameDLL : public IDetour { virtual void GetAdr(void) const { - LogFunAdr("CServerGameDLL::OnReceivedSayTextMessage", CServerGameDLL__OnReceivedSayTextMessage); + LogFunAdr("CServerGameDLL::DLLInit", CServerGameDLL__DLLInit); LogFunAdr("CServerGameDLL::GameInit", CServerGameDLL__GameInit); + LogFunAdr("CServerGameDLL::OnReceivedSayTextMessage", CServerGameDLL__OnReceivedSayTextMessage); LogFunAdr("CServerGameClients::ProcessUserCmds", CServerGameClients__ProcessUserCmds); LogFunAdr("RunFrameServer", v_RunFrameServer); LogVarAdr("g_flServerFrameTimeBase", g_pflServerFrameTimeBase); LogVarAdr("g_pServerGameDLL", g_pServerGameDLL); LogVarAdr("g_pServerGameClients", g_pServerGameClients); LogVarAdr("g_pServerGameEntities", g_pServerGameEntities); - LogVarAdr("g_pGlobals", g_pGlobals); } virtual void GetFun(void) const { - g_GameDll.FindPatternSIMD("85 D2 0F 8E ?? ?? ?? ?? 4C 8B DC").GetPtr(CServerGameDLL__OnReceivedSayTextMessage); + g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC ?? 48 8B 05 ?? ?? ?? ?? 4C 8D 15").GetPtr(CServerGameDLL__DLLInit); g_GameDll.FindPatternSIMD("48 83 EC 28 48 8B 0D ?? ?? ?? ?? 48 8D 15 ?? ?? ?? ?? 48 8B 01 FF 90 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B 01").GetPtr(CServerGameDLL__GameInit); + g_GameDll.FindPatternSIMD("85 D2 0F 8E ?? ?? ?? ?? 4C 8B DC").GetPtr(CServerGameDLL__OnReceivedSayTextMessage); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 55 41 55 41 57").GetPtr(CServerGameClients__ProcessUserCmds); g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 30 0F 29 74 24 ?? 48 8D 0D ?? ?? ?? ??").GetPtr(v_RunFrameServer); } virtual void GetVar(void) const { - g_pGlobals = g_GameDll.FindPatternSIMD("4C 8B 0D ?? ?? ?? ?? 48 8B D1").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); g_pflServerFrameTimeBase = CMemory(CServerGameDLL__GameInit).FindPatternSelf("F3 0F 11 0D").ResolveRelativeAddressSelf(0x4, 0x8).RCast(); } virtual void GetCon(void) const { } diff --git a/src/game/server/physics_main.cpp b/src/game/server/physics_main.cpp index 761da69f..2f95a31d 100644 --- a/src/game/server/physics_main.cpp +++ b/src/game/server/physics_main.cpp @@ -22,7 +22,7 @@ void Physics_RunBotSimulation(bool bSimulating) if (!sv_simulateBots.GetBool()) return; - for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++) + for (int i = 0; i < g_ServerGlobalVariables->maxClients; i++) { CClient* pClient = g_pServer->GetClient(i); if (!pClient) diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index 6ebf10f6..c9a3c24d 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -23,8 +23,8 @@ void CPlayer::RunNullCommand(void) { CUserCmd cmd; - float flOldFrameTime = (*g_pGlobals)->m_flFrameTime; - float flOldCurTime = (*g_pGlobals)->m_flCurTime; + float flOldFrameTime = gpGlobals->frameTime; + float flOldCurTime = gpGlobals->curTime; cmd.frametime = flOldFrameTime; cmd.command_time = flOldCurTime; @@ -32,14 +32,14 @@ void CPlayer::RunNullCommand(void) pl.fixangle = FIXANGLE_NONE; EyeAngles(&cmd.viewangles); - SetTimeBase((*g_pGlobals)->m_flCurTime); + SetTimeBase(gpGlobals->curTime); MoveHelperServer()->SetHost(this); PlayerRunCommand(&cmd, MoveHelperServer()); SetLastUserCommand(&cmd); - (*g_pGlobals)->m_flFrameTime = flOldFrameTime; - (*g_pGlobals)->m_flCurTime = flOldCurTime; + gpGlobals->frameTime = flOldFrameTime; + gpGlobals->curTime = flOldCurTime; MoveHelperServer()->SetHost(NULL); } @@ -79,7 +79,7 @@ void CPlayer::SetLastUCmdSimulationRemainderTime(int nRemainderTime) if (nEdict != FL_EDICT_INVALID) { - _InterlockedOr16((SHORT*)(*g_pGlobals)->m_pEdicts + nEdict + 32, 0x200u); + _InterlockedOr16((SHORT*)gpGlobals->m_pEdicts + nEdict + 32, 0x200u); } m_lastUCmdSimulationRemainderTime = nRemainderTime; @@ -98,7 +98,7 @@ void CPlayer::SetTotalExtraClientCmdTimeAttempted(float flAttemptedTime) if (nEdict != FL_EDICT_INVALID) { - _InterlockedOr16((SHORT*)(*g_pGlobals)->m_pEdicts + nEdict + 32, 0x200u); + _InterlockedOr16((SHORT*)gpGlobals->m_pEdicts + nEdict + 32, 0x200u); } m_totalExtraClientCmdTimeAttempted = flAttemptedTime; @@ -127,7 +127,7 @@ void CPlayer::ProcessUserCmds(CUserCmd* cmds, int numCmds, int totalCmds, CUserCmd* lastCmd = &m_Commands[MAX_QUEUED_COMMANDS_PROCESS]; const float maxUnlag = sv_maxunlag->GetFloat(); - const float currTime = (*g_pGlobals)->m_flCurTime; + const float currTime = gpGlobals->curTime; for (int i = totalCmds - 1; i >= 0; i--) { @@ -206,7 +206,7 @@ bool Player_PhysicsSimulate(CPlayer* player, int numPerIteration, bool adjustTim CClientExtended* const cle = g_pServer->GetClientExtended(player->GetEdict() - 1); const int numUserCmdProcessTicksMax = sv_maxUserCmdProcessTicks.GetInt(); - if (numUserCmdProcessTicksMax && (*g_pGlobals)->m_nGameMode != GameMode_t::SP_MODE) // don't apply this filter in SP games + if (numUserCmdProcessTicksMax && gpGlobals->gameMode != GameMode_t::SP_MODE) // don't apply this filter in SP games cle->InitializeMovementTimeForUserCmdProcessing(numUserCmdProcessTicksMax, TICK_INTERVAL); else // Otherwise we don't care to track time cle->SetRemainingMovementTimeForUserCmdProcessing(FLT_MAX); @@ -236,7 +236,7 @@ static void CC_CreateFakePlayer_f(const CCommand& args) const int numPlayers = g_pServer->GetNumClients(); // Already at max, don't create. - if (numPlayers >= g_ServerGlobalVariables->m_nMaxClients) + if (numPlayers >= g_ServerGlobalVariables->maxClients) return; const char* playerName = args.Arg(1); diff --git a/src/game/server/util_server.cpp b/src/game/server/util_server.cpp index e89e67d5..3efedd52 100644 --- a/src/game/server/util_server.cpp +++ b/src/game/server/util_server.cpp @@ -13,13 +13,13 @@ //----------------------------------------------------------------------------- CPlayer* UTIL_PlayerByIndex(int nIndex) { - if (nIndex < 1 || nIndex >(*g_pGlobals)->m_nMaxClients || nIndex == FL_EDICT_INVALID) + if (nIndex < 1 || nIndex >gpGlobals->maxClients || nIndex == FL_EDICT_INVALID) { assert(0); return nullptr; } // !TODO: Improve this!!! - CPlayer* pPlayer = reinterpret_cast((*g_pGlobals)->m_pEdicts[nIndex + 0x7808]); + CPlayer* pPlayer = reinterpret_cast(gpGlobals->m_pEdicts[nIndex + 0x7808]); return pPlayer; } diff --git a/src/game/shared/shareddefs.h b/src/game/shared/shareddefs.h index b6385db8..5b47340b 100644 --- a/src/game/shared/shareddefs.h +++ b/src/game/shared/shareddefs.h @@ -14,7 +14,7 @@ #ifndef CLIENT_DLL #include "game/server/gameinterface.h" -#define TICK_INTERVAL ((*g_pGlobals)->m_flTickInterval) +#define TICK_INTERVAL (gpGlobals->tickInterval) #define TIME_TO_TICKS( dt ) ( (int)( 0.5f + (float)(dt) / TICK_INTERVAL ) ) #define TICKS_TO_TIME( t ) ( TICK_INTERVAL *( t ) ) diff --git a/src/game/shared/simtimer.h b/src/game/shared/simtimer.h index e9649eb3..74f072eb 100644 --- a/src/game/shared/simtimer.h +++ b/src/game/shared/simtimer.h @@ -34,7 +34,7 @@ public: bool Expired() const { - return ( (*g_pGlobals)->m_flCurTime - m_next > -ST_EPS ); + return ( gpGlobals->curTime - m_next > -ST_EPS ); } float Delay( float delayTime ) @@ -49,21 +49,21 @@ public: void Set( float interval ) { - m_next = (*g_pGlobals)->m_flCurTime + interval; + m_next = gpGlobals->curTime + interval; } // TODO: get CUniformRandomStream global, see 141809528 for global!!! //void Set( float minInterval, float maxInterval ) //{ // if ( maxInterval > 0.0 ) - // m_next = (*g_pGlobals)->m_flCurTime + random->RandomFloat( minInterval, maxInterval ); + // m_next = gpGlobals->m_flCurTime + random->RandomFloat( minInterval, maxInterval ); // else - // m_next = (*g_pGlobals)->m_flCurTime + minInterval; + // m_next = gpGlobals->m_flCurTime + minInterval; //} float GetRemaining() const { - float result = m_next - (*g_pGlobals)->m_flCurTime; + float result = m_next - gpGlobals->curTime; if (result < 0 ) return 0; return result; @@ -88,18 +88,18 @@ public: void Set( float interval, bool startExpired = true ) { m_interval = interval; - m_next = (startExpired) ? -1.0f : (*g_pGlobals)->m_flCurTime + m_interval; + m_next = (startExpired) ? -1.0f : gpGlobals->curTime + m_interval; } void Reset( float interval = -1.0f ) { if ( interval == -1.0f ) { - m_next = (*g_pGlobals)->m_flCurTime + m_interval; + m_next = gpGlobals->curTime + m_interval; } else { - m_next = (*g_pGlobals)->m_flCurTime + interval; + m_next = gpGlobals->curTime + interval; } } @@ -139,18 +139,18 @@ public: // else // { // if ( m_maxInterval == 0 ) - // m_next = (*g_pGlobals)->m_flCurTime + m_minInterval; + // m_next = gpGlobals->m_flCurTime + m_minInterval; // else - // m_next = (*g_pGlobals)->m_flCurTime + random->RandomFloat( m_minInterval, m_maxInterval ); + // m_next = gpGlobals->m_flCurTime + random->RandomFloat( m_minInterval, m_maxInterval ); // } //} //void Reset() //{ // if ( m_maxInterval == 0 ) - // m_next = (*g_pGlobals)->m_flCurTime + m_minInterval; + // m_next = gpGlobals->m_flCurTime + m_minInterval; // else - // m_next = (*g_pGlobals)->m_flCurTime + random->RandomFloat( m_minInterval, m_maxInterval ); + // m_next = gpGlobals->m_flCurTime + random->RandomFloat( m_minInterval, m_maxInterval ); //} float GetMinInterval() const @@ -241,7 +241,7 @@ public: void Start( float intervalOverride ) { m_fIsRunning = true; - m_next = (*g_pGlobals)->m_flCurTime + intervalOverride; + m_next = gpGlobals->curTime + intervalOverride; } void Start() @@ -281,9 +281,9 @@ public: //{ // m_fIsRunning = true; // if ( maxOverride == 0 ) - // m_next = (*g_pGlobals)->m_flCurTime + minOverride; + // m_next = gpGlobals->m_flCurTime + minOverride; // else - // m_next = (*g_pGlobals)->m_flCurTime + random->RandomFloat( minOverride, maxOverride ); + // m_next = gpGlobals->m_flCurTime + random->RandomFloat( minOverride, maxOverride ); //} //void Start() @@ -325,21 +325,21 @@ public: bool EnterThink() { - if ( m_lastTime == (*g_pGlobals)->m_flCurTime) + if ( m_lastTime == gpGlobals->curTime) return false; - m_lastTime = (*g_pGlobals)->m_flCurTime; + m_lastTime = gpGlobals->curTime; return true; } bool DidThink() const { - return ( (*g_pGlobals)->m_flCurTime == m_lastTime ); + return ( gpGlobals->curTime == m_lastTime ); } void SetDidThink() { - m_lastTime = (*g_pGlobals)->m_flCurTime; + m_lastTime = gpGlobals->curTime; } private: diff --git a/src/gameui/IBrowser.cpp b/src/gameui/IBrowser.cpp index 38dd7164..57b0d35d 100644 --- a/src/gameui/IBrowser.cpp +++ b/src/gameui/IBrowser.cpp @@ -37,6 +37,7 @@ History: #include "gameui/IBrowser.h" #include "public/edict.h" #include "game/shared/vscript_shared.h" +#include "game/server/gameinterface.h" static ConCommand togglebrowser("togglebrowser", CBrowser::ToggleBrowser_f, "Show/hide the server browser", FCVAR_CLIENTDLL | FCVAR_RELEASE); @@ -818,7 +819,7 @@ void CBrowser::UpdateHostingStatus(void) *g_nServerRemoteChecksum, SDK_VERSION, g_pServer->GetNumClients(), - g_ServerGlobalVariables->m_nMaxClients, + gpGlobals->maxClients, std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch() ).count() diff --git a/src/networksystem/bansystem.cpp b/src/networksystem/bansystem.cpp index 6311760c..4e01c0b6 100644 --- a/src/networksystem/bansystem.cpp +++ b/src/networksystem/bansystem.cpp @@ -13,6 +13,7 @@ #include "engine/client/client.h" #include "filesystem/filesystem.h" #include "networksystem/bansystem.h" +#include "game/server/gameinterface.h" //----------------------------------------------------------------------------- // Purpose: loads and parses the banned list @@ -311,7 +312,7 @@ void CBanSystem::AuthorPlayerByName(const char* playerName, const bool shouldBan if (!reason) reason = shouldBan ? "Banned from server" : "Kicked from server"; - for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++) + for (int i = 0; i < gpGlobals->maxClients; i++) { CClient* pClient = g_pServer->GetClient(i); if (!pClient) @@ -362,7 +363,7 @@ void CBanSystem::AuthorPlayerById(const char* playerHandle, const bool shouldBan if (!reason) reason = shouldBan ? "Banned from server" : "Kicked from server"; - for (int i = 0; i < g_ServerGlobalVariables->m_nMaxClients; i++) + for (int i = 0; i < gpGlobals->maxClients; i++) { CClient* pClient = g_pServer->GetClient(i); if (!pClient) diff --git a/src/public/edict.h b/src/public/edict.h index bc7211a9..ed61b0d6 100644 --- a/src/public/edict.h +++ b/src/public/edict.h @@ -1,4 +1,5 @@ #pragma once +#include "tier1/string_t.h" #include "public/globalvars_base.h" #ifndef CLIENT_DLL #include "engine/server/sv_main.h" @@ -24,11 +25,11 @@ class CGlobalVars : public CGlobalVarsBase { public: // Current map - const char* m_pszMapName; - int m_nMapVersion; - const char* m_pszStartSpot; // Seems empty at all times. - MapLoadType_t m_eLoadType; // How the current map was loaded. - bool m_bMapLoadFailed; // Map has failed to load, we need to kick back to the main menu (unused?). + string_t mapName; + int mapVersion; + string_t startSpot; // Seems empty at all times. + MapLoadType_t eLoadType; // How the current map was loaded. + bool bMapLoadFailed; // Map has failed to load, we need to kick back to the main menu (unused?). int64_t* m_pEdicts; // r5apex_ds.exe 'CBaseServer::Clear() + 0x7E' void* m_pUnk1; // r5apex_ds.exe 'CBaseServer::Clear() + 0x93' diff --git a/src/public/globalvars_base.h b/src/public/globalvars_base.h index 5bfc5e17..b5a1f58c 100644 --- a/src/public/globalvars_base.h +++ b/src/public/globalvars_base.h @@ -15,35 +15,81 @@ enum class GameMode_t //----------------------------------------------------------------------------- class CGlobalVarsBase { +public: + CGlobalVarsBase(const bool bIsClient); + + // This can be used to filter debug output or to catch the client or server in the act. + bool IsClient() const; + + // for encoding m_flSimulationTime, m_flAnimTime + int GetNetworkBase(const int nTick, const int nEntity); + public: float m_nUnkTime; - float m_rRealTime; // Absolute time (per frame still - Use Plat_FloatTime() for a high precision real time. - int m_nFrameCount; // Absolute frame counter - continues to increase even if game is paused - never resets. - float m_flAbsoluteFrameTime; // Non-paused frametime. - float m_flCurTime; + float realTime; // Absolute time (per frame still - Use Plat_FloatTime() for a high precision real time. + int frameCount; // Absolute frame counter - continues to increase even if game is paused - never resets. + float absoluteFrameTime; // Non-paused frametime. + + // Current time + // + // On the client, this (along with tickcount) takes a different meaning based on what + // piece of code you're in: + // + // - While receiving network packets (like in PreDataUpdate/PostDataUpdate and proxies), + // this is set to the SERVER TICKCOUNT for that packet. There is no interval between + // the server ticks. + // [server_current_Tick * tick_interval] + // + // - While rendering, this is the exact client clock + // [client_current_tick * tick_interval + interpolation_amount] + // + // - During prediction, this is based on the client's current tick: + // [client_current_tick * tick_interval] + float curTime; // These seem to be mainly used in c:\depot\r5launch\src\engine\client\clientstate.cpp. float m_flCurTimeUnknown0; // Empty on server. float m_flCurTimeUnknown1; // Empty on server. float m_flCurTimeUnknown2; // Empty on server. - float m_flLastFrameTimeSincePause; // Last frame time since pause, empty on server. + float lastFrameTimeSincePause; // Last frame time since pause, empty on server. float m_flCurTimeUnknown3; // Empty on server. - float m_flLastCurTimeSincePause; // Last current time since pause, empty on server. + float lastCurTimeSincePause; // Last current time since pause, empty on server. float m_flUnknown4; - float m_flFrameTime; // Time spent on last server or client frame (has nothing to do with think intervals) - int m_nMaxPlayers; // Max internal player entities. - int m_nMaxClients; // Max players as specified in the playlists file. - GameMode_t m_nGameMode; // 1 (MP) 2 (PVE) 3 (SP) - int m_nTickCount; // Simulation ticks - resets on restart. - float m_flTickInterval; + float frameTime; // Time spent on last server or client frame (has nothing to do with think intervals) + int maxPlayers; // Max internal player entities. + int maxClients; // Max players as specified in the playlists file. + GameMode_t gameMode; // 1 (MP) 2 (PVE) 3 (SP) + int tickCount; // Simulation ticks - resets on restart. + float tickInterval; int m_nUnk1; - int m_nUnk2; +private: + // Set to true in client code. + bool m_bClient; // 100 (i.e., tickcount is rounded down to this base and then the "delta" from this base is networked int m_nTimestampNetworkingBase; // 32 (entindex() % nTimestampRandomizeWindow ) is subtracted from gpGlobals->tickcount to set the networking basis, prevents // all of the entities from forcing a new PackedEntity on the same tick (i.e., prevents them from getting lockstepped on this) int m_nTimestampRandomizeWindow; }; + +inline int CGlobalVarsBase::GetNetworkBase(const int nTick, const int nEntity) +{ + const int nEntityMod = nEntity % m_nTimestampRandomizeWindow; + const int nBaseTick = m_nTimestampNetworkingBase * (int)((nTick - nEntityMod) / m_nTimestampNetworkingBase); + return nBaseTick; +} + +inline CGlobalVarsBase::CGlobalVarsBase(const bool bIsClient) : + m_bClient(bIsClient), + m_nTimestampNetworkingBase(100), + m_nTimestampRandomizeWindow(32) +{ +} + +inline bool CGlobalVarsBase::IsClient() const +{ + return m_bClient; +}