Implement ConVar change callbacks

CUtlVector containing callbacks (you can have several callbacks for each ConVar).

also, in 'ConVar::InternalSetValue' Valve and Respawn run V_atod (atof) on function param 'pszValue', but they also check if input param 'pszValue' is a nullptr (which in this case, 'pszNewValue' gets set to an empty string), but yet they deref 'pszValue' (nullptr or not) in 'SetColorFromString' and V_atod, is this correct behavior?

For now I swapped these out with 'pszNewValue' for the very rare event the string happens to be nullptr.
This commit is contained in:
Kawe Mazidjatari 2022-08-04 11:06:56 +02:00
parent babbcbe6d5
commit 238e145818
8 changed files with 138 additions and 100 deletions

View File

@ -486,7 +486,7 @@ void CRConServer::Execute(const cl_rcon::request& cl_request, bool bConVar) cons
if (bConVar) if (bConVar)
{ {
ConVar* pConVar = g_pCVar->FindVar(cl_request.requestbuf().c_str()); ConVar* pConVar = g_pCVar->FindVar(cl_request.requestbuf().c_str());
if (pConVar) // Set value without running the callback. if (pConVar) // Only run if this is a ConVar.
{ {
pConVar->SetValue(cl_request.requestval().c_str()); pConVar->SetValue(cl_request.requestval().c_str());
} }

View File

@ -410,6 +410,15 @@ inline int64 CastPtrToInt64(const void* p)
#endif #endif
#define stackalloc_aligned( _size, _align ) (void*)( ( ((uintp)alloca( ALIGN_VALUE( ( _size ) + (_align ), ( _align ) ) )) + ( _align ) ) & ~_align )
// We should probably always just align to 16 bytes, stackalloc just causes too many problems without this behavior. Source2 does it already.
// #define stackalloc( _size ) stackalloc_aligned( _size, 16 )
#define stackfree( _p ) 0
// two-argument ( type, #elements) stackalloc
#define StackAlloc( typ, nelements ) ( ( typ * ) stackalloc_aligned( ( nelements ) * sizeof(typ), 16 ) )
#define NO_MALLOC_OVERRIDE #define NO_MALLOC_OVERRIDE
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -221,7 +221,8 @@ void ConVar::InitShipped(void) const
#ifndef CLIENT_DLL #ifndef CLIENT_DLL
ai_script_nodes_draw->SetValue(-1); ai_script_nodes_draw->SetValue(-1);
#endif // !CLIENT_DLL #endif // !CLIENT_DLL
mp_gamemode->SetCallback(&MP_GameMode_Changed_f); mp_gamemode->RemoveChangeCallback(mp_gamemode->m_fnChangeCallbacks[0]);
mp_gamemode->InstallChangeCallback(MP_GameMode_Changed_f, false);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -292,6 +293,10 @@ void ConVar::PurgeHostNames(void) const
void ConVar::AddFlags(int nFlags) void ConVar::AddFlags(int nFlags)
{ {
m_pParent->m_nFlags |= nFlags; m_pParent->m_nFlags |= nFlags;
#ifdef ALLOW_DEVELOPMENT_CVARS
m_pParent->m_nFlags &= ~FCVAR_DEVELOPMENTONLY;
#endif
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -534,15 +539,15 @@ void ConVar::InternalSetValue(const char* pszValue)
pszNewValue = ""; pszNewValue = "";
} }
if (!SetColorFromString(pszValue)) if (!SetColorFromString(pszNewValue))
{ {
// Not a color, do the standard thing // Not a color, do the standard thing
double dblValue = atof(pszValue); // Use double to avoid 24-bit restriction on integers and allow storing timestamps or dates in convars double dblValue = atof(pszNewValue); // Use double to avoid 24-bit restriction on integers and allow storing timestamps or dates in convars
float flNewValue = static_cast<float>(dblValue); float flNewValue = static_cast<float>(dblValue);
if (!IsFinite(flNewValue)) if (!IsFinite(flNewValue))
{ {
Warning(eDLL_T::ENGINE, "Warning: ConVar '%s' = '%s' is infinite, clamping value.\n", GetBaseName(), pszValue); Warning(eDLL_T::ENGINE, "Warning: ConVar '%s' = '%s' is infinite, clamping value.\n", GetBaseName(), pszNewValue);
flNewValue = FLT_MAX; flNewValue = FLT_MAX;
} }
@ -705,15 +710,6 @@ void ConVar::SetDefault(const char* pszDefault)
assert(m_pszDefaultValue); assert(m_pszDefaultValue);
} }
//-----------------------------------------------------------------------------
// Purpose: sets the ConVar callback.
// Input : *pCallback -
//-----------------------------------------------------------------------------
void ConVar::SetCallback(void* pCallback)
{
*m_Callback.m_ppCallback = *&pCallback;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: sets the ConVar color value from string. // Purpose: sets the ConVar color value from string.
// Input : *pszValue - // Input : *pszValue -
@ -723,7 +719,7 @@ bool ConVar::SetColorFromString(const char* pszValue)
bool bColor = false; bool bColor = false;
// Try pulling RGBA color values out of the string. // Try pulling RGBA color values out of the string.
int nRGBA[4]{}; int nRGBA[4];
int nParamsRead = sscanf_s(pszValue, "%i %i %i %i", &(nRGBA[0]), &(nRGBA[1]), &(nRGBA[2]), &(nRGBA[3])); int nParamsRead = sscanf_s(pszValue, "%i %i %i %i", &(nRGBA[0]), &(nRGBA[1]), &(nRGBA[2]), &(nRGBA[3]));
if (nParamsRead >= 3) if (nParamsRead >= 3)
@ -766,52 +762,43 @@ bool ConVar::SetColorFromString(const char* pszValue)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ConVar::ChangeStringValue(const char* pszTempVal) void ConVar::ChangeStringValue(const char* pszTempVal)
{ {
assert(!(m_nFlags & FCVAR_NEVER_AS_STRING)); Assert(!(m_nFlags & FCVAR_NEVER_AS_STRING));
char* pszOldValue = reinterpret_cast<char*>(_malloca(m_Value.m_iStringLength)); char* pszOldValue = (char*)stackalloc(m_Value.m_iStringLength);
if (pszOldValue != nullptr) memcpy(pszOldValue, m_Value.m_pszString, m_Value.m_iStringLength);
{
memcpy(pszOldValue, m_Value.m_pszString, m_Value.m_iStringLength);
}
if (pszTempVal) int len = strlen(pszTempVal) + 1;
if (len > m_Value.m_iStringLength)
{ {
size_t len = strlen(pszTempVal) + 1; if (m_Value.m_pszString)
if (len > m_Value.m_iStringLength)
{ {
if (m_Value.m_pszString) MemAllocSingleton()->Free(m_Value.m_pszString);
{
MemAllocSingleton()->Free(m_Value.m_pszString);
}
m_Value.m_pszString = MemAllocSingleton()->Alloc<char>(len);
m_Value.m_iStringLength = len;
} }
else if (!m_Value.m_pszString)
{
m_Value.m_pszString = MemAllocSingleton()->Alloc<char>(len);
m_Value.m_iStringLength = len;
}
memmove(m_Value.m_pszString, pszTempVal, len);
/***** m_Value.m_pszString = MemAllocSingleton()->Alloc<char>(len);
!FIXME: m_Value.m_iStringLength = len;
Respawn put additional code here which
seems to itterate over a 64bit integer
to call the callback several times (as many times as m_iCallbackCount?).
******/
} }
else
memcpy(reinterpret_cast<void*>(m_Value.m_pszString), pszTempVal, len);
// Invoke any necessary callback function
for (int i = 0; i < m_fnChangeCallbacks.Count(); ++i)
{ {
m_Value.m_pszString = nullptr; m_fnChangeCallbacks[i](reinterpret_cast<IConVar*>(&m_pIConVarVFTable), pszOldValue, NULL);
} }
pszOldValue = nullptr; if (g_pCVar)
{
g_pCVar->CallGlobalChangeCallbacks(this, pszOldValue);
}
stackfree(pszOldValue);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: changes the ConVar string value (this is faster than ChangeStringValue, // Purpose: changes the ConVar string value without calling the callback
// only use if the new string is equal or lower than this->m_iStringLength). // (Size of new string must be equal or lower than m_iStringLength!!!)
// Input : *pszTempVal - flOldValue // Input : *pszTempVal - flOldValue
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ConVar::ChangeStringValueUnsafe(const char* pszNewValue) void ConVar::ChangeStringValueUnsafe(const char* pszNewValue)
@ -819,6 +806,46 @@ void ConVar::ChangeStringValueUnsafe(const char* pszNewValue)
m_Value.m_pszString = const_cast<char*>(pszNewValue); m_Value.m_pszString = const_cast<char*>(pszNewValue);
} }
//-----------------------------------------------------------------------------
// Purpose: Install a change callback (there shouldn't already be one....)
// Input : callback -
// bInvoke -
//-----------------------------------------------------------------------------
void ConVar::InstallChangeCallback(FnChangeCallback_t callback, bool bInvoke /*=true*/)
{
if (!callback)
{
Warning(eDLL_T::ENGINE, "%s: called with NULL callback, ignoring!!!\n", __FUNCTION__);
return;
}
if (m_pParent->m_fnChangeCallbacks.Find(callback) != m_pParent->m_fnChangeCallbacks.InvalidIndex())
{
// Same ptr added twice, sigh...
Warning(eDLL_T::ENGINE, "%s: ignoring duplicate change callback!!!\n", __FUNCTION__);
return;
}
m_pParent->m_fnChangeCallbacks.AddToTail(callback);
// Call it immediately to set the initial value...
if (bInvoke)
{
callback(reinterpret_cast<IConVar*>(&m_pIConVarVFTable), m_Value.m_pszString, m_Value.m_fValue);
}
sizeof(CUtlVector<int>);
}
//-----------------------------------------------------------------------------
// Purpose: Install a change callback (there shouldn't already be one....)
// Input : callback -
//-----------------------------------------------------------------------------
void ConVar::RemoveChangeCallback(FnChangeCallback_t callback)
{
m_pParent->m_fnChangeCallbacks.FindAndRemove(callback);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Checks if ConVar is registered. // Purpose: Checks if ConVar is registered.
// Output : bool // Output : bool

View File

@ -2,6 +2,7 @@
#include "tier1/cmd.h" #include "tier1/cmd.h"
#include "mathlib/color.h" #include "mathlib/color.h"
#include "public/include/iconvar.h" #include "public/include/iconvar.h"
#include "tier1/utlvector.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: A console variable // Purpose: A console variable
@ -58,12 +59,14 @@ public:
const char* GetDefault(void) const; const char* GetDefault(void) const;
void SetDefault(const char* pszDefault); void SetDefault(const char* pszDefault);
void SetCallback(void* pCallback);
bool SetColorFromString(const char* pszValue); bool SetColorFromString(const char* pszValue);
void ChangeStringValue(const char* pszTempValue); void ChangeStringValue(const char* pszTempValue);
void ChangeStringValueUnsafe(const char* pszNewValue); void ChangeStringValueUnsafe(const char* pszNewValue);
void InstallChangeCallback(FnChangeCallback_t callback, bool bInvoke);
void RemoveChangeCallback(FnChangeCallback_t callback);
bool IsRegistered(void) const; bool IsRegistered(void) const;
bool IsCommand(void) const; bool IsCommand(void) const;
static bool IsFlagSet(ConVar* pConVar, int nFlags); static bool IsFlagSet(ConVar* pConVar, int nFlags);
@ -75,13 +78,6 @@ public:
float m_fValue; float m_fValue;
int m_nValue; int m_nValue;
}; };
struct CVCallback_t
{
void** m_ppCallback;
int64_t m_iFlags;
char m_Pad[8];
int64_t m_iCallbackCount;
};
IConVar* m_pIConVarVFTable{}; //0x0040 IConVar* m_pIConVarVFTable{}; //0x0040
ConVar* m_pParent {}; //0x0048 ConVar* m_pParent {}; //0x0048
@ -91,8 +87,9 @@ public:
float m_fMinVal {}; //0x0074 float m_fMinVal {}; //0x0074
bool m_bHasMax {}; //0x0078 bool m_bHasMax {}; //0x0078
float m_fMaxVal {}; //0x007C float m_fMaxVal {}; //0x007C
CVCallback_t m_Callback {}; //0x0080 // <-- !FIXME: 'CUtlVector< FnChangeCallback_t > m_fnChangeCallbacks;' CUtlVector<FnChangeCallback_t> m_fnChangeCallbacks; //0x0080
}; //Size: 0x00A0 }; //Size: 0x00A0
static_assert(sizeof(ConVar) == 0xA0);
/* ==== ICONVAR ========================================================================================================================================================= */ /* ==== ICONVAR ========================================================================================================================================================= */
inline CMemory p_IConVar_IsFlagSet; inline CMemory p_IConVar_IsFlagSet;
@ -104,9 +101,6 @@ inline auto ConVar_SetInfo = p_ConVar_SetInfo.RCast<void* (*)(ConVar* thisptr, i
inline CMemory p_ConVar_Register; inline CMemory p_ConVar_Register;
inline auto ConVar_Register = p_ConVar_Register.RCast<void* (*)(ConVar* thisptr, const char* szName, const char* szDefaultValue, int nFlags, const char* szHelpString, bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t pCallback, const char* pszUsageString)>(); inline auto ConVar_Register = p_ConVar_Register.RCast<void* (*)(ConVar* thisptr, const char* szName, const char* szDefaultValue, int nFlags, const char* szHelpString, bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t pCallback, const char* pszUsageString)>();
inline CMemory p_ConVar_ChangeStringValue;
inline auto ConVar_ChangeStringValue = p_IConVar_IsFlagSet.RCast<bool (*)(ConVar* pConVar, const char* pszTempVal)>();
inline CMemory g_pConVarVFTable; inline CMemory g_pConVarVFTable;
inline CMemory g_pIConVarVFTable; inline CMemory g_pIConVarVFTable;
@ -121,10 +115,9 @@ class VConVar : public IDetour
{ {
virtual void GetAdr(void) const virtual void GetAdr(void) const
{ {
spdlog::debug("| FUN: IConVar::IsFlagSet : {:#18x} |\n", p_IConVar_IsFlagSet.GetPtr()); spdlog::debug("| FUN: ConVar::IsFlagSet : {:#18x} |\n", p_IConVar_IsFlagSet.GetPtr());
spdlog::debug("| FUN: IConVar::SetInfo : {:#18x} |\n", p_ConVar_SetInfo.GetPtr()); spdlog::debug("| FUN: ConVar::SetInfo : {:#18x} |\n", p_ConVar_SetInfo.GetPtr());
spdlog::debug("| FUN: IConVar::Register : {:#18x} |\n", p_ConVar_Register.GetPtr()); spdlog::debug("| FUN: ConVar::Register : {:#18x} |\n", p_ConVar_Register.GetPtr());
spdlog::debug("| FUN: ConVar::ChangeStringValue : {:#18x} |\n", p_ConVar_ChangeStringValue.GetPtr());
spdlog::debug("| VAR: g_pConVarVtable : {:#18x} |\n", g_pConVarVFTable.GetPtr()); spdlog::debug("| VAR: g_pConVarVtable : {:#18x} |\n", g_pConVarVFTable.GetPtr());
spdlog::debug("| VAR: g_pIConVarVtable : {:#18x} |\n", g_pIConVarVFTable.GetPtr()); spdlog::debug("| VAR: g_pIConVarVtable : {:#18x} |\n", g_pIConVarVFTable.GetPtr());
spdlog::debug("+----------------------------------------------------------------+\n"); spdlog::debug("+----------------------------------------------------------------+\n");
@ -138,12 +131,9 @@ class VConVar : public IDetour
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) #elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
p_ConVar_Register = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x40\xF3\x0F\x10\x84\x24\x00\x00\x00\x00"), "xxxx?xxxx?xxxx?xxxxxxxxxx????"); p_ConVar_Register = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x40\xF3\x0F\x10\x84\x24\x00\x00\x00\x00"), "xxxx?xxxx?xxxx?xxxxxxxxxx????");
#endif #endif
p_ConVar_ChangeStringValue = g_mGameDll.FindPatternSIMD(reinterpret_cast<rsig_t>("\x40\x55\x41\x56\x41\x57\x48\x83\xEC\x30\x48\x8D\x6C\x24\x00\x4C\x8B\x41\x60"), "xxxxxxxxxxxxxx?xxxx");
IConVar_IsFlagSet = p_IConVar_IsFlagSet.RCast<bool (*)(ConVar*, int)>(); /*48 8B 41 48 85 50 38*/ IConVar_IsFlagSet = p_IConVar_IsFlagSet.RCast<bool (*)(ConVar*, int)>(); /*48 8B 41 48 85 50 38*/
ConVar_SetInfo = p_ConVar_SetInfo.RCast<void* (*)(ConVar*, int, int, int, void*)>(); /*40 53 48 83 EC 60 48 8B D9 C6 41 10 00 33 C9 48 8D 05 ? ? ? ? 48 89 4C 24 ? 0F 57 C0 48 89 4C 24 ? 48 89 03 48 8D 05 ? ? ? ? 48 89 43 40*/ ConVar_SetInfo = p_ConVar_SetInfo.RCast<void* (*)(ConVar*, int, int, int, void*)>(); /*40 53 48 83 EC 60 48 8B D9 C6 41 10 00 33 C9 48 8D 05 ? ? ? ? 48 89 4C 24 ? 0F 57 C0 48 89 4C 24 ? 48 89 03 48 8D 05 ? ? ? ? 48 89 43 40*/
ConVar_Register = p_ConVar_Register.RCast<void* (*)(ConVar*, const char*, const char*, int, const char*, bool, float, bool, float, FnChangeCallback_t, const char*)>(); /*48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 40 F3 0F 10 84 24 ? ? ? ?*/ ConVar_Register = p_ConVar_Register.RCast<void* (*)(ConVar*, const char*, const char*, int, const char*, bool, float, bool, float, FnChangeCallback_t, const char*)>(); /*48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 40 F3 0F 10 84 24 ? ? ? ?*/
ConVar_ChangeStringValue = p_IConVar_IsFlagSet.RCast<bool (*)(ConVar*, const char*)>(); /*40 55 41 56 41 57 48 83 EC 30 48 8D 6C 24 ? 4C 8B 41 60*/
} }
virtual void GetVar(void) const virtual void GetVar(void) const
{ {

View File

@ -214,6 +214,39 @@ ConCommand* CCVar::FindCommand(const char* pszCommandName)
return CallVFunc<ConCommand*>(index, this, pszCommandName); return CallVFunc<ConCommand*>(index, this, pszCommandName);
} }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCVar::CallGlobalChangeCallbacks(ConVar* pConVar, const char* pOldString)
{
const int index = 23;
CallVFunc<void>(index, this, pConVar, pOldString);
}
//-----------------------------------------------------------------------------
// Purpose: deal with queued material system ConVars
//-----------------------------------------------------------------------------
bool CCVar::IsMaterialThreadSetAllowed(void)
{
const int index = 35;
return CallVFunc<bool>(index, this);
}
void CCVar::QueueMaterialThreadSetValue(ConVar* pConVar, float flValue)
{
const int index = 36;
CallVFunc<void>(index, this, pConVar, flValue);
}
void CCVar::QueueMaterialThreadSetValue(ConVar* pConVar, int nValue)
{
const int index = 37;
CallVFunc<void>(index, this, pConVar, nValue);
}
void CCVar::QueueMaterialThreadSetValue(ConVar* pConVar, const char* pValue)
{
const int index = 38;
CallVFunc<void>(index, this, pConVar, pValue);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: iterates over all ConVars // Purpose: iterates over all ConVars
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -243,29 +276,5 @@ unordered_map<string, ConCommandBase*> CCVar::DumpToMap(void)
return allConVars; return allConVars;
} }
//-----------------------------------------------------------------------------
// Purpose: deal with queued material system ConVars
//-----------------------------------------------------------------------------
bool CCVar::IsMaterialThreadSetAllowed(void)
{
const int index = 280;
return CallVFunc<bool>(index, this);
}
void CCVar::QueueMaterialThreadSetValue(ConVar* pConVar, float flValue)
{
const int index = 288;
CallVFunc<void>(index, this, pConVar, flValue);
}
void CCVar::QueueMaterialThreadSetValue(ConVar* pConVar, int nValue)
{
const int index = 296;
CallVFunc<void>(index, this, pConVar, nValue);
}
void CCVar::QueueMaterialThreadSetValue(ConVar* pConVar, const char* pValue)
{
const int index = 304;
CallVFunc<void>(index, this, pConVar, pValue);
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
CCVar* g_pCVar = nullptr; CCVar* g_pCVar = nullptr;

View File

@ -180,13 +180,15 @@ public:
ConCommandBase* FindCommandBase(const char* pszCommandName); // @0x1405983A0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM ConCommandBase* FindCommandBase(const char* pszCommandName); // @0x1405983A0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
ConVar* FindVar(const char* pszVarName); // @0x1405983B0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM ConVar* FindVar(const char* pszVarName); // @0x1405983B0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
ConCommand* FindCommand(const char* pszCommandName); ConCommand* FindCommand(const char* pszCommandName);
CCVarIteratorInternal* FactoryInternalIterator(void);
unordered_map<string, ConCommandBase*> DumpToMap(void);
void CallGlobalChangeCallbacks(ConVar* pConVar, const char* pOldString);
bool IsMaterialThreadSetAllowed(void); bool IsMaterialThreadSetAllowed(void);
void QueueMaterialThreadSetValue(ConVar* pConVar, float flValue); void QueueMaterialThreadSetValue(ConVar* pConVar, float flValue);
void QueueMaterialThreadSetValue(ConVar* pConVar, int nValue); void QueueMaterialThreadSetValue(ConVar* pConVar, int nValue);
void QueueMaterialThreadSetValue(ConVar* pConVar, const char* pValue); void QueueMaterialThreadSetValue(ConVar* pConVar, const char* pValue);
CCVarIteratorInternal* FactoryInternalIterator(void);
unordered_map<string, ConCommandBase*> DumpToMap(void);
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -52,9 +52,9 @@
MP_GameMode_Changed_f MP_GameMode_Changed_f
===================== =====================
*/ */
bool MP_GameMode_Changed_f(ConVar* pVTable) void MP_GameMode_Changed_f(IConVar* pConVar, const char* pOldString, float flOldValue)
{ {
return SetupGamemode(mp_gamemode->GetString()); SetupGamemode(mp_gamemode->GetString());
} }
#ifndef DEDICATED #ifndef DEDICATED
@ -780,7 +780,8 @@ void RCON_CmdQuery_f(const CCommand& args)
return; return;
} }
RCONClient()->Send(RCONClient()->Serialize(args.ArgS(), "", cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND)); string svCmdQuery = RCONClient()->Serialize(args.ArgS(), "", cl_rcon::request_t::SERVERDATA_REQUEST_EXECCOMMAND);
RCONClient()->Send(svCmdQuery);
return; return;
} }
else else
@ -1025,11 +1026,11 @@ BHit_f
*/ */
void BHit_f(const CCommand& args) void BHit_f(const CCommand& args)
{ {
#if !defined (DEDICATED) && !defined (CLIENT_DLL)
if (args.ArgC() != 9) if (args.ArgC() != 9)
return; return;
if (bhit_enable->GetBool() && sv_visualizetraces->GetBool()) #ifndef DEDICATED
if (sv_visualizetraces->GetBool())
{ {
Vector3D vecAbsStart; Vector3D vecAbsStart;
Vector3D vecAbsEnd; Vector3D vecAbsEnd;
@ -1065,5 +1066,5 @@ void BHit_f(const CCommand& args)
Cbuf_AddText(Cbuf_GetCurrentPlayer(), szBuf, cmd_source_t::kCommandSrcCode); Cbuf_AddText(Cbuf_GetCurrentPlayer(), szBuf, cmd_source_t::kCommandSrcCode);
Cbuf_Execute(); Cbuf_Execute();
} }
#endif // !DEDICATED && !CLIENT_DLL #endif // !DEDICATED
} }

View File

@ -12,7 +12,7 @@ inline CMemory p_DownloadPlaylists_f;
inline auto _DownloadPlaylists_f = p_DownloadPlaylists_f.RCast<void(*)(void)>(); inline auto _DownloadPlaylists_f = p_DownloadPlaylists_f.RCast<void(*)(void)>();
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
bool MP_GameMode_Changed_f(ConVar* pVTable); void MP_GameMode_Changed_f(IConVar* pConVar, const char* pOldString, float flOldValue);
#ifndef DEDICATED #ifndef DEDICATED
void GameConsole_Invoke_f(const CCommand& args); void GameConsole_Invoke_f(const CCommand& args);
void ServerBrowser_Invoke_f(const CCommand& args); void ServerBrowser_Invoke_f(const CCommand& args);