Game: properly load shared global vars for game dll's

Properly load it from CServerGameDLL::DLLInit (and new in this commit, the client's shared globals from CHLClient::Init), this way we can also avoid the double dereference which improves performance. Also performed an architectural change where anything outside Game DLL code uses the shared interface pointer instead of the objects directly.
This commit is contained in:
Kawe Mazidjatari 2024-07-31 22:18:33 +02:00
parent 084f94aefd
commit 044528b9b1
20 changed files with 174 additions and 94 deletions

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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::milliseconds>(
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<int>(g_pServer->GetCPUUsage() * 100.0f), (g_pEngine->GetFrameTime() * 1000.0f),
g_pServer->GetTick()).c_str());

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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;

View File

@ -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<CPlayer*>(globals->m_pEdicts[senderId + 30728]);
CPlayer* player = reinterpret_cast<CPlayer*>(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;

View File

@ -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<CGlobalVars**>();
g_pflServerFrameTimeBase = CMemory(CServerGameDLL__GameInit).FindPatternSelf("F3 0F 11 0D").ResolveRelativeAddressSelf(0x4, 0x8).RCast<float*>();
}
virtual void GetCon(void) const { }

View File

@ -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)

View File

@ -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);

View File

@ -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<CPlayer*>((*g_pGlobals)->m_pEdicts[nIndex + 0x7808]);
CPlayer* pPlayer = reinterpret_cast<CPlayer*>(gpGlobals->m_pEdicts[nIndex + 0x7808]);
return pPlayer;
}

View File

@ -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 ) )

View File

@ -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:

View File

@ -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::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count()

View File

@ -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)

View File

@ -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'

View File

@ -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;
}