From 1600e7fe34ac40c16702cc13091be8a387b95c22 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Thu, 5 Oct 2023 00:13:00 +0200 Subject: [PATCH 01/48] progress report --- public/tier1/convar.h | 191 ++++++++++++++++++++---------------------- tier1/convar.cpp | 111 ++++++++++++++++++++++-- 2 files changed, 195 insertions(+), 107 deletions(-) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 45cd85523..947e7c446 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // @@ -19,6 +19,7 @@ #include "tier0/dbg.h" #include "tier1/utlvector.h" #include "tier1/utlstring.h" +#include "tier1/characterset.h" #include "Color.h" #include "mathlib/vector4d.h" #include "playerslot.h" @@ -49,21 +50,39 @@ class ConCommand; class ConCommandBase; class ConVarRefAbstract; class ConCommandRefAbstract; -struct characterset_t; class ALIGN8 ConVarHandle { public: - bool IsValid() { return value != kInvalidConVarHandle; } - uint32 Get() { return value; } - void Set( uint32 _value ) { value = _value; } + ConVarHandle() { m_value = 0xFFFFFFFF; }; -private: - uint32 value = kInvalidConVarHandle; + bool IsValid() const; + void Invalidate(); private: - static const uint32 kInvalidConVarHandle = 0xFFFFFFFF; + friend bool operator!=(const ConVarHandle& lhs, const ConVarHandle& rhs); + friend bool operator==(const ConVarHandle& lhs, const ConVarHandle& rhs); + + uint32 GetValue() const { return m_value; }; + + uint32 m_value; } ALIGN8_POST; + +inline bool operator!=(const ConVarHandle& lhs, const ConVarHandle& rhs) { return lhs.m_value != rhs.m_value; } +inline bool operator==(const ConVarHandle& lhs, const ConVarHandle& rhs) { return lhs.m_value == rhs.m_value; } + +static const ConVarHandle INVALID_CONVAR_HANDLE = ConVarHandle(); + +inline bool ConVarHandle::IsValid() const +{ + return *this != INVALID_CONVAR_HANDLE; +} + +inline void ConVarHandle::Invalidate() +{ + m_value = INVALID_CONVAR_HANDLE.GetValue(); +} + enum CommandTarget_t { CT_NO_TARGET = -1, @@ -97,6 +116,8 @@ class CCommandContext class ALIGN8 ConCommandHandle { public: + ConCommandHandle() { value = kInvalidConCommandHandle; }; + bool IsValid() { return value != kInvalidConCommandHandle; } uint16 Get() { return value; } void Set( uint16 _value ) { value = _value; } @@ -198,7 +219,8 @@ enum EConVarType : short EConVarType_Vector2, EConVarType_Vector3, EConVarType_Vector4, - EConVarType_Qangle + EConVarType_Qangle, + EConVarType_MAX }; union CVValue_t @@ -224,7 +246,6 @@ union CVValue_t // Called when a ConVar changes value //----------------------------------------------------------------------------- typedef void(*FnChangeCallbackGlobal_t)(ConVarRefAbstract *cvar, CSplitScreenSlot nSlot, const char *pNewValue, const char *pOldValue); -typedef void(*FnChangeCallback_t)(ConVarRefAbstract *cvar, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue); //----------------------------------------------------------------------------- // ConVar & ConCommand creation listener callbacks @@ -478,6 +499,7 @@ friend class ConCommandHandle; //----------------------------------------------------------------------------- // Purpose: A console variable //----------------------------------------------------------------------------- +#if false class ConVar { friend class CCvar; @@ -485,7 +507,6 @@ friend class ConVarRef; friend class SplitScreenConVarRef; public: -#ifdef CONVAR_WORK_FINISHED ConVar( const char *pName, const char *pDefaultValue, int64 flags = 0); ConVar( const char *pName, const char *pDefaultValue, int64 flags, @@ -584,51 +605,70 @@ friend class SplitScreenConVarRef; protected: -#if 0 - // Next ConVar in chain - // Prior to register, it points to the next convar in the DLL. - // Once registered, though, m_pNext is reset to point to the next - // convar in the global list - ConCommandBase* m_pNext; - - // Has the cvar been added to the global list? - bool m_bRegistered; - - // Static data const char* m_pszName; + CVValue_t* m_cvvDefaultValue; + CVValue_t* m_cvvMinValue; + CVValue_t* m_cvvMaxValue; const char* m_pszHelpString; + EConVarType m_eVarType; - // ConVar flags - int64 m_nFlags; + // This gets copied from the ConVarDesc_t on creation + short unk1; -protected: - // ConVars add themselves to this list for the executable. - // Then ConVar_Register runs through all the console variables - // and registers them into a global list stored in vstdlib.dll - static ConCommandBase* s_pConCommandBases; - - // ConVars in this executable use this 'global' to access values. - static IConCommandBaseAccessor* s_pAccessor; - // This either points to "this" or it points to the original declaration of a ConVar. - // This allows ConVars to exist in separate modules, and they all use the first one to be declared. - // m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar). - ConVar *m_pParent; + unsigned int timesChanged; + int64 flags; + unsigned int callback_index; - // Static data - const char *m_pszDefaultValue; - - CVValue_t m_Value; + // Used when setting default, max, min values from the ConVarDesc_t + // although that's not the only place of usage + // flags seems to be: + // (1 << 0) Skip setting value to split screen slots and also something keyvalues related + // (1 << 1) Skip setting default value + // (1 << 2) Skip setting min/max values + int allocation_flag_of_some_sort; - // Min/Max values - bool m_bHasMin; - float m_fMinVal; - bool m_bHasMax; - float m_fMaxVal; - - // Call this function when ConVar changes - CUtlVector< FnChangeCallback_t > m_fnChangeCallbacks; + CVValue_t** values; +}; #endif -#endif // CONVAR_WORK_FINISHED + +//----------------------------------------------------------------- +// Used to read/write/create? convars (replaces the FindVar method) +//----------------------------------------------------------------- +class ConVarRefAbstract +{ +public: + // sub_6A66B0 + ConVarRefAbstract(const char* name, int32 flags, const char* description, int64 obj, float value) + { + this->Init(INVALID_CONVAR_HANDLE, EConVarType_Float32); + + *(char *)(obj + 4) = 1; + *(float *)(obj + 7) = value; + this->sub_10B7C70(name, flags & 0xFB, description, obj); + } + +private: + // sub_10B7BC0 + void Init(ConVarHandle defaultHandle, EConVarType type); + + // sub_10B7C70 + void sub_10B7C70(const char* name, int32 flags, const char* description, int64 obj); + + // High-speed method to read convar data + ConVarHandle m_Handle; + ConVar* m_ConVar; +}; + +// sub_10B7760 +ConVar* ConVar_Invalid(EConVarType type); + +class ConVar +{ +friend class ConVarRegList; +friend class ConVarRefAbstract; +public: + ConVar(EConVarType type); +protected: const char* m_pszName; CVValue_t* m_cvvDefaultValue; CVValue_t* m_cvvMinValue; @@ -640,7 +680,7 @@ friend class SplitScreenConVarRef; short unk1; unsigned int timesChanged; - int64 flags; + int64 m_flags; unsigned int callback_index; // Used when setting default, max, min values from the ConVarDesc_t @@ -651,10 +691,9 @@ friend class SplitScreenConVarRef; // (1 << 2) Skip setting min/max values int allocation_flag_of_some_sort; - CVValue_t** values; + CVValue_t* m_value[4]; }; - #ifdef CONVAR_WORK_FINISHED //----------------------------------------------------------------------------- // Purpose: Return ConVar value as a float @@ -773,54 +812,6 @@ FORCEINLINE_CVAR int CSplitScreenAddedConVar::GetSplitScreenPlayerSlot() const return m_nSplitScreenSlot; } -#endif // CONVAR_WORK_FINISHED - -//----------------------------------------------------------------------------- -// Used to read/write convars that already exist (replaces the FindVar method) -//----------------------------------------------------------------------------- -class ConVarRefAbstract -{ -public: -#ifdef CONVAR_WORK_FINISHED - ConVarRefAbstract( const char *pName ); - ConVarRefAbstract( const char *pName, bool bIgnoreMissing ); - ConVarRefAbstract( IConVar *pConVar ); - - void Init( const char *pName, bool bIgnoreMissing ); - bool IsValid() const; - bool IsFlagSet( int64 nFlags ) const; - IConVar *GetLinkedConVar(); - - // Get/Set value - float GetFloat( void ) const; - int GetInt( void ) const; - Color GetColor( void ) const; - bool GetBool() const { return !!GetInt(); } - const char *GetString( void ) const; - - void SetValue( const char *pValue ); - void SetValue( float flValue ); - void SetValue( int nValue ); - void SetValue( Color value ); - void SetValue( bool bValue ); - - const char *GetName() const; - - const char *GetDefault() const; - - const char *GetBaseName() const; - - int GetSplitScreenPlayerSlot() const; - -private: -#endif // CONVAR_WORK_FINISHED - // High-speed method to read convar data - ConVarHandle m_Handle; - ConVar *m_pConVarState; -}; - - -#ifdef CONVAR_WORK_FINISHED //----------------------------------------------------------------------------- // Did we find an existing convar of that name? //----------------------------------------------------------------------------- diff --git a/tier1/convar.cpp b/tier1/convar.cpp index da72ad532..9144a6a88 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -1,5 +1,5 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // @@ -95,7 +95,6 @@ class ConCommandRegList bool ConCommandRegList::s_bConCommandsRegistered = false; -#ifdef CONVAR_WORK_FINISHED template void check_size() { static_assert(ExpectedSize == RealSize, "Size mismatch"); @@ -110,7 +109,7 @@ class ConVarRegList ConVarRegList() { check_size(); - check_size(); + //check_size(); } static bool AreConVarsRegistered() @@ -136,7 +135,7 @@ class ConVarRegList if (!hndl.IsValid()) { - Plat_FatalErrorFunc("RegisterConCommand: Unknown error registering convar \"%s\"!\n", pConVar->GetName()); + Plat_FatalErrorFunc("RegisterConCommand: Unknown error registering convar \"%s\"!\n", pConVar->m_pszName); DebuggerBreakIfDebugging(); } } @@ -157,7 +156,6 @@ class ConVarRegList }; bool ConVarRegList::s_bConVarsRegistered = false; -#endif // CONVAR_WORK_FINISHED //----------------------------------------------------------------------------- // Called by the framework to register ConCommandBases with the ICVar @@ -651,14 +649,113 @@ bool ConCommand::CanAutoComplete( void ) return m_bHasCompletionCallback; } - -#ifdef CONVAR_WORK_FINISHED //----------------------------------------------------------------------------- // // Console Variables // //----------------------------------------------------------------------------- +ConVar invalid_convar[EConVarType_MAX + 1] = { + EConVarType_Bool, + EConVarType_Int16, + EConVarType_UInt16, + EConVarType_Int32, + EConVarType_UInt32, + EConVarType_Int64, + EConVarType_UInt64, + EConVarType_Float32, + EConVarType_Float64, + EConVarType_String, + EConVarType_Color, + EConVarType_Vector2, + EConVarType_Vector3, + EConVarType_Vector4, + EConVarType_Qangle, + EConVarType_Invalid // EConVarType_MAX +}; + +// Strictly for invalid convar creation +ConVar::ConVar(EConVarType type) : + m_pszName(""), + m_cvvDefaultValue(nullptr), + m_cvvMinValue(nullptr), + m_cvvMaxValue(nullptr), + m_pszHelpString("This convar is being accessed prior to ConVar_Register being called"), + m_eVarType(type) +{ +} + +ConVar* ConVar_Invalid(EConVarType type) +{ + if (type == EConVarType_Invalid) + { + return &invalid_convar[EConVarType_MAX]; + } + return &invalid_convar[type]; +} + +void ConVarRefAbstract::Init(ConVarHandle defaultHandle, EConVarType type) +{ + this->m_Handle.Invalidate(); + this->m_ConVar = nullptr; + + // qword_191A3D8 + if (g_pCVar && (this->m_ConVar = g_pCVar->GetConVar(defaultHandle)) == nullptr) + { + this->m_ConVar = ConVar_Invalid(type); + // technically this + //result = *(char ***)(sub_10B7760((unsigned int)a3) + 80); + } + this->m_Handle = defaultHandle; +} + +void ConVarRefAbstract::sub_10B7C70(const char* name, int32 flags, const char* description, int64 obj) +{ + char **v5; // rax + __m128i v9; // xmm0 + __int16 v10; // ax + __m128i v11; // xmm1 + __m128i v12; // xmm2 + __m128i v13; // xmm3 + __int64 v15; // rax + __int64 v16[3]; // [rsp+0h] [rbp-A0h] BYREF + __m128i v17; // [rsp+18h] [rbp-88h] + __m128i v18; // [rsp+28h] [rbp-78h] + __m128i v19; // [rsp+38h] [rbp-68h] + __m128i v20; // [rsp+48h] [rbp-58h] + __int16 v21; // [rsp+58h] [rbp-48h] + int v22; // [rsp+5Ah] [rbp-46h] + __int16 v23; // [rsp+5Eh] [rbp-42h] + _QWORD *v24; // [rsp+60h] [rbp-40h] + _QWORD *v25; // [rsp+68h] [rbp-38h] + + this->m_ConVar = ConVar_Invalid(a5[4].m128i_i16[0]); + this->m_Handle.Invalidate(); + if ( !CommandLine()->HasParam("-tools") && (flags & (0x13084282)) == 0 ) + flags |= FCVAR_DEVELOPMENTONLY; + + v9 = _mm_loadu_si128(a5); + v24 = a1; + v23 = 0; + v10 = a5[4].m128i_i16[0]; + v11 = _mm_loadu_si128(a5 + 1); + v16[0] = a2; + v12 = _mm_loadu_si128(a5 + 2); + v16[1] = a4; + v13 = _mm_loadu_si128(a5 + 3); + v16[2] = flags; + v21 = v10; + v22 = 0; + v17 = v9; + v18 = v11; + v19 = v12; + v20 = v13; + v25 = a1 + 1; + return sub_10B79F0(v16); +} + +#ifdef CONVAR_WORK_FINISHED + //----------------------------------------------------------------------------- // Various constructors //----------------------------------------------------------------------------- From 03369afd4af07dea557c84ecdf1e0e34989f0c94 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Thu, 5 Oct 2023 09:06:59 +0200 Subject: [PATCH 02/48] clean up flags --- public/tier1/convar.h | 2 +- tier1/convar.cpp | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 947e7c446..c5e91eed9 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -644,7 +644,7 @@ class ConVarRefAbstract *(char *)(obj + 4) = 1; *(float *)(obj + 7) = value; - this->sub_10B7C70(name, flags & 0xFB, description, obj); + this->sub_10B7C70(name, flags &~ FCVAR_DEVELOPMENTONLY, description, obj); } private: diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 9144a6a88..dd94ae2ac 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -731,8 +731,18 @@ void ConVarRefAbstract::sub_10B7C70(const char* name, int32 flags, const char* d this->m_ConVar = ConVar_Invalid(a5[4].m128i_i16[0]); this->m_Handle.Invalidate(); - if ( !CommandLine()->HasParam("-tools") && (flags & (0x13084282)) == 0 ) + if (!CommandLine()->HasParam("-tools") + && (flags & (FCVAR_DEVELOPMENTONLY + |FCVAR_ARCHIVE + |FCVAR_USERINFO + |FCVAR_CHEAT + |FCVAR_RELEASE + |FCVAR_SERVER_CAN_EXECUTE + |FCVAR_CLIENT_CAN_EXECUTE + |FCVAR_CLIENTCMD_CAN_EXECUTE)) == 0) + { flags |= FCVAR_DEVELOPMENTONLY; + } v9 = _mm_loadu_si128(a5); v24 = a1; From 6ac7e3239e8fdd6e4c21d603b27dd76b7f231e24 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Fri, 6 Oct 2023 00:15:35 +0200 Subject: [PATCH 03/48] progress report --- public/icvar.h | 2 +- public/tier1/convar.h | 75 +++++++++++++++++-- tier1/convar.cpp | 166 +++++++++++++++++++++++++----------------- 3 files changed, 170 insertions(+), 73 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index b7c88d3f9..5f6381f57 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -72,7 +72,7 @@ abstract_class ICvar : public IAppSystem virtual void unk2() = 0; // Register, unregister vars - virtual void RegisterConVar( ConVar *pConVar, int64 nAdditionalFlags, ConVarHandle &pCvarRef, ConVar &pCvar ) = 0; + virtual void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, ConVar** pCvar ) = 0; virtual void UnregisterConVar( ConVarHandle handle ) = 0; virtual ConVar* GetConVar( ConVarHandle handle ) = 0; diff --git a/public/tier1/convar.h b/public/tier1/convar.h index c5e91eed9..8d0622bd4 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -225,6 +225,10 @@ enum EConVarType : short union CVValue_t { + CVValue_t() { memset(this, 0, sizeof(*this)); } + CVValue_t(CVValue_t const& cp) { memcpy(this, &cp, sizeof(*this)); }; + CVValue_t& operator=(CVValue_t other) { memcpy(this, &other, sizeof(*this)); return *this; } + bool m_bValue; short m_i16Value; uint16 m_u16Value; @@ -246,6 +250,8 @@ union CVValue_t // Called when a ConVar changes value //----------------------------------------------------------------------------- typedef void(*FnChangeCallbackGlobal_t)(ConVarRefAbstract *cvar, CSplitScreenSlot nSlot, const char *pNewValue, const char *pOldValue); +using FnChangeCallback_t = void(*)(ConVarRefAbstract *cvar, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue); +static_assert(sizeof(FnChangeCallback_t) == 0x8, "Wrong size for FnChangeCallback_t"); //----------------------------------------------------------------------------- // ConVar & ConCommand creation listener callbacks @@ -631,6 +637,61 @@ friend class SplitScreenConVarRef; }; #endif +#pragma pack(push,1) +struct ConVarSetup_t +{ + int32 unknown0; // 0x0 + + bool has_default; // 0x4 + bool has_min; // 0x5 + bool has_max; // 0x6 + + CVValue_t default_value; // 0x7 + + char pad3; // 0x17 + + FnChangeCallback_t callback; // 0x18 + EConVarType type; // 0x20 + + int32_t unk1; // 0x22 + int16_t unk2; // 0x26 +}; +#pragma pack(pop) + +static_assert(sizeof(ConVarSetup_t) == 0x28, "ConVarSetup_t is of the wrong size!"); +static_assert(sizeof(ConVarSetup_t) % 8 == 0x0, "ConVarSetup_t isn't 8 bytes aligned!"); + +#pragma pack(push,1) +struct ConVarCreation_t { + const char* name; // 0x0 + const char* description; // 0x8 + int64_t flags; // 0x10 + + int32_t unk1; // 0x18 + + bool has_default; // 0x1C + bool has_min; // 0x1D + bool has_max; // 0x1E + CVValue_t default_value; // 0x1F + + int8_t unk4[33]; // 0x2F + + FnChangeCallback_t callback; // 0x50 + + EConVarType type; // 0x58 + + int32_t unk9; // 0x5A + int16_t unk10; // 0x5E + + ConVarHandle* refHandle; // 0x60 + ConVar** refConVar; // 0x68 +}; +#pragma pack(pop) + +static_assert(sizeof(ConVarCreation_t) == 0x70, "ConVarCreation_t wrong size!"); +static_assert(sizeof(ConVarCreation_t) % 8 == 0x0, "ConVarCreation_t isn't 8 bytes aligned!"); +static_assert(sizeof(CVValue_t) == 0x10, "CVValue_t wrong size!"); + //----------------------------------------------------------------- // Used to read/write/create? convars (replaces the FindVar method) //----------------------------------------------------------------- @@ -638,12 +699,13 @@ class ConVarRefAbstract { public: // sub_6A66B0 - ConVarRefAbstract(const char* name, int32 flags, const char* description, int64 obj, float value) + ConVarRefAbstract(const char* name, int32 flags, const char* description, ConVarSetup_t obj, float value) : m_ConVar(nullptr) { this->Init(INVALID_CONVAR_HANDLE, EConVarType_Float32); - *(char *)(obj + 4) = 1; - *(float *)(obj + 7) = value; + obj.has_default = true; + obj.default_value.m_flValue = value; + this->sub_10B7C70(name, flags &~ FCVAR_DEVELOPMENTONLY, description, obj); } @@ -652,8 +714,8 @@ class ConVarRefAbstract void Init(ConVarHandle defaultHandle, EConVarType type); // sub_10B7C70 - void sub_10B7C70(const char* name, int32 flags, const char* description, int64 obj); - + void sub_10B7C70(const char* name, int32 flags, const char* description, ConVarSetup_t& obj); +public: // High-speed method to read convar data ConVarHandle m_Handle; ConVar* m_ConVar; @@ -662,6 +724,9 @@ class ConVarRefAbstract // sub_10B7760 ConVar* ConVar_Invalid(EConVarType type); +// sub_10B79F0 +void ConVar_Add(const ConVarCreation_t& setup); + class ConVar { friend class ConVarRegList; diff --git a/tier1/convar.cpp b/tier1/convar.cpp index dd94ae2ac..f320fcd3d 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -26,6 +26,20 @@ #endif #include "tier0/memdbgon.h" +template M get_member_type(M T::*); +template T get_class_type(M T::*); + +template +constexpr int32_t* offset_of() +{ + return (&(((T*)0)->*M)); +} + +#define OFFSET_OF(m) offset_of() // Comment this out when we release. //#define ALLOW_DEVELOPMENT_CVARS @@ -93,12 +107,20 @@ class ConCommandRegList static bool s_bConCommandsRegistered; }; -bool ConCommandRegList::s_bConCommandsRegistered = false; +#include +PLUGIN_GLOBALVARS(); +void RegisterConVar(ConVarCreation_t& setup) +{ + META_CONPRINTF( "Registering convar: %s!\n", setup.name); + g_pCVar->RegisterConVar(setup, s_nCVarFlag, setup.refHandle, setup.refConVar); + if (!setup.refHandle->IsValid()) + { + Plat_FatalErrorFunc("RegisterConCommand: Unknown error registering convar \"%s\"!\n", setup.name); + DebuggerBreakIfDebugging(); + } +} -template -void check_size() { - static_assert(ExpectedSize == RealSize, "Size mismatch"); -}; +bool ConCommandRegList::s_bConCommandsRegistered = false; class ConVarRegList; static ConVarRegList* s_pConVarRegList = nullptr; @@ -106,11 +128,7 @@ static ConVarRegList* s_pConVarRegList = nullptr; class ConVarRegList { public: - ConVarRegList() - { - check_size(); - //check_size(); - } + ConVarRegList() {} static bool AreConVarsRegistered() { @@ -128,16 +146,7 @@ class ConVarRegList { FOR_EACH_VEC(s_pConVarRegList->m_Vec, i) { - ConVar* pConVar = &pList->m_Vec[i]; - ConVarHandle hndl; - //g_pCVar->RegisterConVar(pConVar, s_nCVarFlag, hndl); - //pConVar->SetHandle(hndl); - - if (!hndl.IsValid()) - { - Plat_FatalErrorFunc("RegisterConCommand: Unknown error registering convar \"%s\"!\n", pConVar->m_pszName); - DebuggerBreakIfDebugging(); - } + RegisterConVar(pList->m_Vec[i]); } ConVarRegList *pNext = pList->m_pNext; @@ -148,19 +157,54 @@ class ConVarRegList s_pConVarRegList = nullptr; } } + + int Count() const + { + return m_Vec.Count(); + } + private: - CUtlVectorFixed m_Vec; + friend void ConVar_Add(const ConVarCreation_t& setup); + + void SetNextList(ConVarRegList* list) + { + m_pNext = list; + } + + void Add(const ConVarCreation_t& setup) + { + m_Vec.AddToTail(setup); + } + + CUtlVectorFixed m_Vec; ConVarRegList* m_pNext = nullptr; static bool s_bConVarsRegistered; }; - bool ConVarRegList::s_bConVarsRegistered = false; +static_assert(sizeof(ConVarRegList) == 0x2BD0, "Size mismatch"); + +void ConVar_Add(const ConVarCreation_t& setup) +{ + //if ( byte_1919861 ) + //return sub_10B7990(); + + if (!s_pConVarRegList || s_pConVarRegList->Count() == 100) + { + ConVarRegList* newList = new ConVarRegList; + newList->SetNextList(s_pConVarRegList); + + s_pConVarRegList = newList; + } + + s_pConVarRegList->Add(setup); +} + //----------------------------------------------------------------------------- // Called by the framework to register ConCommandBases with the ICVar //----------------------------------------------------------------------------- -void ConVar_Register( int64 nCVarFlag) +void ConVar_Register( int64 nCVarFlag ) { if ( !g_pCVar || s_bRegistered ) return; @@ -169,9 +213,7 @@ void ConVar_Register( int64 nCVarFlag) s_nCVarFlag = nCVarFlag; ConCommandRegList::RegisterAll(); -#ifdef CONVAR_WORK_FINISHED ConVarRegList::RegisterAll(); -#endif // CONVAR_WORK_FINISHED } void ConVar_Unregister( ) @@ -182,7 +224,6 @@ void ConVar_Unregister( ) s_bRegistered = false; } - //----------------------------------------------------------------------------- // Purpose: Default constructor //----------------------------------------------------------------------------- @@ -700,7 +741,7 @@ void ConVarRefAbstract::Init(ConVarHandle defaultHandle, EConVarType type) this->m_ConVar = nullptr; // qword_191A3D8 - if (g_pCVar && (this->m_ConVar = g_pCVar->GetConVar(defaultHandle)) == nullptr) + if (g_pCVar && g_pCVar->GetConVar(defaultHandle) == nullptr) { this->m_ConVar = ConVar_Invalid(type); // technically this @@ -709,29 +750,14 @@ void ConVarRefAbstract::Init(ConVarHandle defaultHandle, EConVarType type) this->m_Handle = defaultHandle; } -void ConVarRefAbstract::sub_10B7C70(const char* name, int32 flags, const char* description, int64 obj) -{ - char **v5; // rax - __m128i v9; // xmm0 - __int16 v10; // ax - __m128i v11; // xmm1 - __m128i v12; // xmm2 - __m128i v13; // xmm3 - __int64 v15; // rax - __int64 v16[3]; // [rsp+0h] [rbp-A0h] BYREF - __m128i v17; // [rsp+18h] [rbp-88h] - __m128i v18; // [rsp+28h] [rbp-78h] - __m128i v19; // [rsp+38h] [rbp-68h] - __m128i v20; // [rsp+48h] [rbp-58h] - __int16 v21; // [rsp+58h] [rbp-48h] - int v22; // [rsp+5Ah] [rbp-46h] - __int16 v23; // [rsp+5Eh] [rbp-42h] - _QWORD *v24; // [rsp+60h] [rbp-40h] - _QWORD *v25; // [rsp+68h] [rbp-38h] - - this->m_ConVar = ConVar_Invalid(a5[4].m128i_i16[0]); +//std::exit((int64_t)(&((ConVarSetup_t*)nullptr)->type)); + +void ConVarRefAbstract::sub_10B7C70(const char* name, int32 flags, const char* description, ConVarSetup_t& obj) +{ + this->m_ConVar = ConVar_Invalid(obj.type); this->m_Handle.Invalidate(); - if (!CommandLine()->HasParam("-tools") + + if (!CommandLine()->HasParm("-tools") && (flags & (FCVAR_DEVELOPMENTONLY |FCVAR_ARCHIVE |FCVAR_USERINFO @@ -743,25 +769,31 @@ void ConVarRefAbstract::sub_10B7C70(const char* name, int32 flags, const char* d { flags |= FCVAR_DEVELOPMENTONLY; } + + ConVarCreation_t cvar; - v9 = _mm_loadu_si128(a5); - v24 = a1; - v23 = 0; - v10 = a5[4].m128i_i16[0]; - v11 = _mm_loadu_si128(a5 + 1); - v16[0] = a2; - v12 = _mm_loadu_si128(a5 + 2); - v16[1] = a4; - v13 = _mm_loadu_si128(a5 + 3); - v16[2] = flags; - v21 = v10; - v22 = 0; - v17 = v9; - v18 = v11; - v19 = v12; - v20 = v13; - v25 = a1 + 1; - return sub_10B79F0(v16); + cvar.name = name; + cvar.description = description; + cvar.flags = flags; + + // 0x0 through 0x28 + /* 0x18 */ cvar.unk1 = obj.unknown0; // 0x0 + /* 0x1C */ cvar.has_default = obj.has_default; // 0x4 + /* 0x1D */ cvar.has_min = obj.has_min; // 0x5 + /* 0x1E */ cvar.has_max = obj.has_min; // 0x6 + /* 0x1F */ cvar.default_value = obj.default_value; // 0x7 + + /* 0x2F */ // 0x17 ???????????? + + /* 0x50 */ cvar.callback = obj.callback; // 0x18 + /* 0x58 */ cvar.type = obj.type; // 0x20 + /* 0x5A */ cvar.unk9 = obj.unk1; // 0x22 + /* 0x5E */ cvar.unk10 = obj.unk2; // 0x28 + + cvar.refHandle = &this->m_Handle; + cvar.refConVar = &this->m_ConVar; + + ConVar_Add(cvar); } #ifdef CONVAR_WORK_FINISHED From 37a765512295bd4468d2b25be6ca0b597d99ab0d Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Fri, 6 Oct 2023 00:24:05 +0200 Subject: [PATCH 04/48] remove some debug --- tier1/convar.cpp | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/tier1/convar.cpp b/tier1/convar.cpp index f320fcd3d..e182b7ac3 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -26,25 +26,6 @@ #endif #include "tier0/memdbgon.h" -template M get_member_type(M T::*); -template T get_class_type(M T::*); - -template -constexpr int32_t* offset_of() -{ - return (&(((T*)0)->*M)); -} - -#define OFFSET_OF(m) offset_of() - -// Comment this out when we release. -//#define ALLOW_DEVELOPMENT_CVARS - - //----------------------------------------------------------------------------- // Statically constructed list of ConCommandBases, // used for registering them with the ICVar interface @@ -107,11 +88,8 @@ class ConCommandRegList static bool s_bConCommandsRegistered; }; -#include -PLUGIN_GLOBALVARS(); void RegisterConVar(ConVarCreation_t& setup) { - META_CONPRINTF( "Registering convar: %s!\n", setup.name); g_pCVar->RegisterConVar(setup, s_nCVarFlag, setup.refHandle, setup.refConVar); if (!setup.refHandle->IsValid()) { From c671207b3f24768d918e3e15e1ebf531cd32b657 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sat, 7 Oct 2023 00:58:54 +0200 Subject: [PATCH 05/48] Template the convar class --- public/icvar.h | 11 ++-- public/tier1/convar.h | 146 +++++++++++++++++++++++++++--------------- tier1/convar.cpp | 124 +++++++++++------------------------ 3 files changed, 137 insertions(+), 144 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index 5f6381f57..10f421c59 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -17,14 +17,13 @@ class ConCommandBase; class ConCommand; -class ConVar; class Color; class IConVarListener; +class IConVar; class CConVarDetail; struct ConVarSnapshot_t; union CVValue_t; class KeyValues; -class ConVarRefAbstract; //----------------------------------------------------------------------------- @@ -47,7 +46,7 @@ abstract_class ICvar : public IAppSystem // Install a global change callback (to be called when any convar changes) virtual void InstallGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; virtual void RemoveGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; - virtual void CallGlobalChangeCallbacks( ConVarRefAbstract *var, CSplitScreenSlot nSlot, const char *pOldString, float flOldValue ) = 0; + virtual void CallGlobalChangeCallbacks( ConVar* var, CSplitScreenSlot nSlot, const char *pOldString, float flOldValue ) = 0; // Reverts cvars which contain a specific flag virtual void RevertFlaggedConVars( int nFlag ) = 0; @@ -72,16 +71,16 @@ abstract_class ICvar : public IAppSystem virtual void unk2() = 0; // Register, unregister vars - virtual void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, ConVar** pCvar ) = 0; + virtual void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, IConVar** pCvar ) = 0; virtual void UnregisterConVar( ConVarHandle handle ) = 0; - virtual ConVar* GetConVar( ConVarHandle handle ) = 0; + virtual IConVar* GetConVar( ConVarHandle handle ) = 0; // Register, unregister commands virtual ConCommandHandle RegisterConCommand( ConCommand *pCmd, int64 nAdditionalFlags = 0 ) = 0; virtual void UnregisterConCommand( ConCommandHandle handle ) = 0; virtual ConCommand* GetCommand( ConCommandHandle handle ) = 0; - virtual void QueueThreadSetValue( ConVarRefAbstract *ref, CSplitScreenSlot nSlot, CVValue_t *value ) = 0; + virtual void QueueThreadSetValue( ConVar* ref, CSplitScreenSlot nSlot, CVValue_t* value ) = 0; }; //----------------------------------------------------------------------------- diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 8d0622bd4..6bf4348ab 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -24,6 +24,8 @@ #include "mathlib/vector4d.h" #include "playerslot.h" +#include + #ifdef _WIN32 #define FORCEINLINE_CVAR FORCEINLINE #elif POSIX @@ -44,11 +46,11 @@ //----------------------------------------------------------------------------- // Forward declarations //----------------------------------------------------------------------------- -class ConVar; +class IConVar; class CCommand; class ConCommand; class ConCommandBase; -class ConVarRefAbstract; +class ConVar; class ConCommandRefAbstract; class ALIGN8 ConVarHandle @@ -229,28 +231,49 @@ union CVValue_t CVValue_t(CVValue_t const& cp) { memcpy(this, &cp, sizeof(*this)); }; CVValue_t& operator=(CVValue_t other) { memcpy(this, &other, sizeof(*this)); return *this; } + template + FORCEINLINE_CVAR CVValue_t& operator=(T other); + bool m_bValue; - short m_i16Value; - uint16 m_u16Value; - int m_i32Value; - uint m_u32Value; - int64 m_i64Value; - uint64 m_u64Value; + int16_t m_i16Value; + uint16_t m_u16Value; + int32_t m_i32Value; + uint32_t m_u32Value; + int64_t m_i64Value; + uint64_t m_u64Value; float m_flValue; double m_dbValue; - const char *m_szValue; + const char* m_szValue; Color m_clrValue; Vector2D m_vec2Value; Vector m_vec3Value; Vector4D m_vec4Value; QAngle m_angValue; }; +static_assert(sizeof(float) == sizeof(int32_t), "Wrong float type size for ConVar!"); +static_assert(sizeof(double) == sizeof(int64_t), "Wrong double type size for ConVar!"); + +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( bool other ) { m_bValue = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( int16_t other ) { m_i16Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( uint16_t other ) { m_u16Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( int32_t other ) { m_i32Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( uint32_t other ) { m_u32Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( int64_t other ) { m_i64Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( uint64_t other ) { m_u64Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( float other ) { m_flValue = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( double other ) { m_dbValue = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const char* other ) { m_szValue = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const Color& other ) { m_clrValue = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const Vector2D& other ) { m_vec2Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const Vector& other ) { m_vec3Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const Vector4D& other ) { m_vec4Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const QAngle& other ) { m_angValue = other; return *this; } //----------------------------------------------------------------------------- // Called when a ConVar changes value //----------------------------------------------------------------------------- -typedef void(*FnChangeCallbackGlobal_t)(ConVarRefAbstract *cvar, CSplitScreenSlot nSlot, const char *pNewValue, const char *pOldValue); -using FnChangeCallback_t = void(*)(ConVarRefAbstract *cvar, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue); +typedef void(*FnChangeCallbackGlobal_t)(ConVar* cvar, CSplitScreenSlot nSlot, const char *pNewValue, const char *pOldValue); +using FnChangeCallback_t = void(*)(ConVar* cvar, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue); static_assert(sizeof(FnChangeCallback_t) == 0x8, "Wrong size for FnChangeCallback_t"); //----------------------------------------------------------------------------- @@ -259,7 +282,7 @@ static_assert(sizeof(FnChangeCallback_t) == 0x8, "Wrong size for FnChangeCallbac class ICVarListenerCallbacks { public: - virtual void OnConVarCreated( ConVarRefAbstract *pNewCvar ) = 0; + virtual void OnConVarCreated( ConVar* pNewCvar ) = 0; virtual void OnConCommandCreated( ConCommandRefAbstract *pNewCommand ) = 0; }; @@ -509,7 +532,6 @@ friend class ConCommandHandle; class ConVar { friend class CCvar; -friend class ConVarRef; friend class SplitScreenConVarRef; public: @@ -640,6 +662,20 @@ friend class SplitScreenConVarRef; #pragma pack(push,1) struct ConVarSetup_t { + ConVarSetup_t() : + unknown0(0), + has_default(false), + has_min(false), + has_max(false), + default_value(), + min_value(), + max_value(), + callback(nullptr), + type(EConVarType_Invalid), + unk1(0), + unk2(0) + {} + int32 unknown0; // 0x0 bool has_default; // 0x4 @@ -647,44 +683,33 @@ struct ConVarSetup_t bool has_max; // 0x6 CVValue_t default_value; // 0x7 + CVValue_t min_value; // 0x17 + CVValue_t max_value; // 0x27 - char pad3; // 0x17 + char pad; // 0x37 - FnChangeCallback_t callback; // 0x18 - EConVarType type; // 0x20 + FnChangeCallback_t callback; // 0x38 + EConVarType type; // 0x40 - int32_t unk1; // 0x22 - int16_t unk2; // 0x26 + int32_t unk1; // 0x42 + int16_t unk2; // 0x46 }; #pragma pack(pop) - -static_assert(sizeof(ConVarSetup_t) == 0x28, "ConVarSetup_t is of the wrong size!"); +static_assert(sizeof(ConVarSetup_t) == 0x48, "ConVarSetup_t is of the wrong size!"); static_assert(sizeof(ConVarSetup_t) % 8 == 0x0, "ConVarSetup_t isn't 8 bytes aligned!"); #pragma pack(push,1) struct ConVarCreation_t { + ConVarCreation_t() { memset(this, 0, sizeof(*this)); } + const char* name; // 0x0 const char* description; // 0x8 int64_t flags; // 0x10 - int32_t unk1; // 0x18 - - bool has_default; // 0x1C - bool has_min; // 0x1D - bool has_max; // 0x1E - CVValue_t default_value; // 0x1F - - int8_t unk4[33]; // 0x2F - - FnChangeCallback_t callback; // 0x50 - - EConVarType type; // 0x58 - - int32_t unk9; // 0x5A - int16_t unk10; // 0x5E + ConVarSetup_t setup; // 0x18 ConVarHandle* refHandle; // 0x60 - ConVar** refConVar; // 0x68 + IConVar** refConVar; // 0x68 }; #pragma pack(pop) @@ -695,44 +720,63 @@ static_assert(sizeof(CVValue_t) == 0x10, "CVValue_t wrong size!"); //----------------------------------------------------------------- // Used to read/write/create? convars (replaces the FindVar method) //----------------------------------------------------------------- -class ConVarRefAbstract +class ConVar { public: // sub_6A66B0 - ConVarRefAbstract(const char* name, int32 flags, const char* description, ConVarSetup_t obj, float value) : m_ConVar(nullptr) + template + ConVar(const char* name, int32 flags, const char* description, T value) { - this->Init(INVALID_CONVAR_HANDLE, EConVarType_Float32); + this->Init(INVALID_CONVAR_HANDLE, TranslateType()); - obj.has_default = true; - obj.default_value.m_flValue = value; + ConVarSetup_t setup; + setup.has_default = true; + setup.default_value = value; + setup.type = TranslateType(); - this->sub_10B7C70(name, flags &~ FCVAR_DEVELOPMENTONLY, description, obj); + this->sub_10B7C70(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); } private: + template + static constexpr EConVarType TranslateType(); + // sub_10B7BC0 void Init(ConVarHandle defaultHandle, EConVarType type); // sub_10B7C70 - void sub_10B7C70(const char* name, int32 flags, const char* description, ConVarSetup_t& obj); + void sub_10B7C70(const char* name, int32 flags, const char* description, const ConVarSetup_t& obj); public: // High-speed method to read convar data ConVarHandle m_Handle; - ConVar* m_ConVar; + IConVar* m_ConVar; }; -// sub_10B7760 -ConVar* ConVar_Invalid(EConVarType type); +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Bool; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Int16; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_UInt16; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Int32; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_UInt32; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Int64; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_UInt64; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Float32; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Float64; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_String; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Color; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Vector2; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Vector3; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Vector4; } +template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Qangle; } -// sub_10B79F0 -void ConVar_Add(const ConVarCreation_t& setup); +// sub_10B7760 +IConVar* ConVar_Invalid(EConVarType type); -class ConVar +class IConVar { friend class ConVarRegList; -friend class ConVarRefAbstract; +friend class ConVar; public: - ConVar(EConVarType type); + IConVar(EConVarType type); protected: const char* m_pszName; CVValue_t* m_cvvDefaultValue; diff --git a/tier1/convar.cpp b/tier1/convar.cpp index e182b7ac3..6fdc097a3 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -88,12 +88,12 @@ class ConCommandRegList static bool s_bConCommandsRegistered; }; -void RegisterConVar(ConVarCreation_t& setup) +void RegisterConVar( ConVarCreation_t& setup ) { - g_pCVar->RegisterConVar(setup, s_nCVarFlag, setup.refHandle, setup.refConVar); + g_pCVar->RegisterConVar( setup, s_nCVarFlag, setup.refHandle, setup.refConVar ); if (!setup.refHandle->IsValid()) { - Plat_FatalErrorFunc("RegisterConCommand: Unknown error registering convar \"%s\"!\n", setup.name); + Plat_FatalErrorFunc( "RegisterConCommand: Unknown error registering convar \"%s\"!\n", setup.name ); DebuggerBreakIfDebugging(); } } @@ -115,21 +115,21 @@ class ConVarRegList static void RegisterAll() { - if (!s_bConVarsRegistered && g_pCVar) + if ( !s_bConVarsRegistered && g_pCVar ) { s_bConVarsRegistered = true; - ConVarRegList* pList = s_pConVarRegList; - while (pList != nullptr) + ConVarRegList* list = s_pConVarRegList; + while ( list != nullptr ) { - FOR_EACH_VEC(s_pConVarRegList->m_Vec, i) + FOR_EACH_VEC( s_pConVarRegList->m_Vec, i ) { - RegisterConVar(pList->m_Vec[i]); + RegisterConVar( list->m_Vec[i] ); } - ConVarRegList *pNext = pList->m_pNext; - delete pList; - pList = pNext; + ConVarRegList *pNext = list->m_pNext; + delete list; + list = pNext; } s_pConVarRegList = nullptr; @@ -142,16 +142,16 @@ class ConVarRegList } private: - friend void ConVar_Add(const ConVarCreation_t& setup); + friend void SetupConVar( ConVarCreation_t& setup ); - void SetNextList(ConVarRegList* list) + void SetNextList( ConVarRegList* list ) { m_pNext = list; } - void Add(const ConVarCreation_t& setup) + void Add( const ConVarCreation_t& setup ) { - m_Vec.AddToTail(setup); + m_Vec.AddToTail( setup ); } CUtlVectorFixed m_Vec; @@ -159,24 +159,28 @@ class ConVarRegList static bool s_bConVarsRegistered; }; -bool ConVarRegList::s_bConVarsRegistered = false; - static_assert(sizeof(ConVarRegList) == 0x2BD0, "Size mismatch"); -void ConVar_Add(const ConVarCreation_t& setup) +bool ConVarRegList::s_bConVarsRegistered = false; + +// sub_10B79F0 +void SetupConVar( ConVarCreation_t& setup ) { - //if ( byte_1919861 ) - //return sub_10B7990(); + if ( s_bRegistered ) + { + RegisterConVar(setup); + return; + } - if (!s_pConVarRegList || s_pConVarRegList->Count() == 100) + if ( !s_pConVarRegList || s_pConVarRegList->Count() == 100 ) { ConVarRegList* newList = new ConVarRegList; - newList->SetNextList(s_pConVarRegList); + newList->SetNextList( s_pConVarRegList ); s_pConVarRegList = newList; } - s_pConVarRegList->Add(setup); + s_pConVarRegList->Add( setup ); } //----------------------------------------------------------------------------- @@ -185,7 +189,9 @@ void ConVar_Add(const ConVarCreation_t& setup) void ConVar_Register( int64 nCVarFlag ) { if ( !g_pCVar || s_bRegistered ) + { return; + } s_bRegistered = true; s_nCVarFlag = nCVarFlag; @@ -674,7 +680,7 @@ bool ConCommand::CanAutoComplete( void ) // //----------------------------------------------------------------------------- -ConVar invalid_convar[EConVarType_MAX + 1] = { +IConVar invalid_convar[EConVarType_MAX + 1] = { EConVarType_Bool, EConVarType_Int16, EConVarType_UInt16, @@ -694,7 +700,7 @@ ConVar invalid_convar[EConVarType_MAX + 1] = { }; // Strictly for invalid convar creation -ConVar::ConVar(EConVarType type) : +IConVar::IConVar(EConVarType type) : m_pszName(""), m_cvvDefaultValue(nullptr), m_cvvMinValue(nullptr), @@ -704,7 +710,7 @@ ConVar::ConVar(EConVarType type) : { } -ConVar* ConVar_Invalid(EConVarType type) +IConVar* ConVar_Invalid(EConVarType type) { if (type == EConVarType_Invalid) { @@ -713,7 +719,7 @@ ConVar* ConVar_Invalid(EConVarType type) return &invalid_convar[type]; } -void ConVarRefAbstract::Init(ConVarHandle defaultHandle, EConVarType type) +void ConVar::Init(ConVarHandle defaultHandle, EConVarType type) { this->m_Handle.Invalidate(); this->m_ConVar = nullptr; @@ -730,9 +736,9 @@ void ConVarRefAbstract::Init(ConVarHandle defaultHandle, EConVarType type) //std::exit((int64_t)(&((ConVarSetup_t*)nullptr)->type)); -void ConVarRefAbstract::sub_10B7C70(const char* name, int32 flags, const char* description, ConVarSetup_t& obj) +void ConVar::sub_10B7C70(const char* name, int32 flags, const char* description, const ConVarSetup_t& setup) { - this->m_ConVar = ConVar_Invalid(obj.type); + this->m_ConVar = ConVar_Invalid(setup.type); this->m_Handle.Invalidate(); if (!CommandLine()->HasParm("-tools") @@ -754,24 +760,12 @@ void ConVarRefAbstract::sub_10B7C70(const char* name, int32 flags, const char* d cvar.description = description; cvar.flags = flags; - // 0x0 through 0x28 - /* 0x18 */ cvar.unk1 = obj.unknown0; // 0x0 - /* 0x1C */ cvar.has_default = obj.has_default; // 0x4 - /* 0x1D */ cvar.has_min = obj.has_min; // 0x5 - /* 0x1E */ cvar.has_max = obj.has_min; // 0x6 - /* 0x1F */ cvar.default_value = obj.default_value; // 0x7 - - /* 0x2F */ // 0x17 ???????????? - - /* 0x50 */ cvar.callback = obj.callback; // 0x18 - /* 0x58 */ cvar.type = obj.type; // 0x20 - /* 0x5A */ cvar.unk9 = obj.unk1; // 0x22 - /* 0x5E */ cvar.unk10 = obj.unk2; // 0x28 + cvar.setup = setup; cvar.refHandle = &this->m_Handle; cvar.refConVar = &this->m_ConVar; - ConVar_Add(cvar); + SetupConVar(cvar); } #ifdef CONVAR_WORK_FINISHED @@ -1202,50 +1196,6 @@ class CEmptyConVar : public ConVar static CEmptyConVar s_EmptyConVar; -ConVarRef::ConVarRef( const char *pName ) -{ - Init( pName, false ); -} - -ConVarRef::ConVarRef( const char *pName, bool bIgnoreMissing ) -{ - Init( pName, bIgnoreMissing ); -} - -void ConVarRef::Init( const char *pName, bool bIgnoreMissing ) -{ - m_pConVar = g_pCVar ? g_pCVar->FindVar( pName ) : &s_EmptyConVar; - if ( !m_pConVar ) - { - m_pConVar = &s_EmptyConVar; - } - m_pConVarState = static_cast< ConVar * >( m_pConVar ); - if( !IsValid() ) - { - static bool bFirst = true; - if ( g_pCVar || bFirst ) - { - if ( !bIgnoreMissing ) - { - Warning( "ConVarRef %s doesn't point to an existing ConVar\n", pName ); - } - bFirst = false; - } - } -} - -ConVarRef::ConVarRef( IConVar *pConVar ) -{ - m_pConVar = pConVar ? pConVar : &s_EmptyConVar; - m_pConVarState = static_cast< ConVar * >( m_pConVar ); -} - -bool ConVarRef::IsValid() const -{ - return m_pConVar != &s_EmptyConVar; -} - - //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- From 2558e41123ca6c45d21e379f100b05855a7a30f7 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sat, 7 Oct 2023 22:49:43 +0200 Subject: [PATCH 06/48] progress report --- public/icvar.h | 21 +- public/tier1/convar.h | 396 ++++++++++++-------------------------- tier1/convar.cpp | 437 ++++++++++++++---------------------------- 3 files changed, 280 insertions(+), 574 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index 10f421c59..62902501c 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -1,4 +1,4 @@ -//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // @@ -15,7 +15,6 @@ #include "tier1/utlvector.h" #include "tier0/memalloc.h" -class ConCommandBase; class ConCommand; class Color; class IConVarListener; @@ -38,10 +37,10 @@ abstract_class ICvar : public IAppSystem virtual ConVarHandle FindNextConVar( ConVarHandle prev ) = 0; virtual void SetConVarValue( ConVarHandle cvarid, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue ) = 0; - virtual ConCommandHandle FindCommand( const char *name ) = 0; - virtual ConCommandHandle FindFirstCommand() = 0; - virtual ConCommandHandle FindNextCommand( ConCommandHandle prev ) = 0; - virtual void DispatchConCommand( ConCommandHandle cmd, const CCommandContext &ctx, const CCommand &args ) = 0; + virtual ConVarHandle FindCommand( const char *name ) = 0; + virtual ConVarHandle FindFirstCommand() = 0; + virtual ConVarHandle FindNextCommand( ConVarHandle prev ) = 0; + virtual void DispatchConCommand( ConVarHandle cmd, const CCommandContext &ctx, const CCommand &args ) = 0; // Install a global change callback (to be called when any convar changes) virtual void InstallGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; @@ -71,14 +70,14 @@ abstract_class ICvar : public IAppSystem virtual void unk2() = 0; // Register, unregister vars - virtual void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, IConVar** pCvar ) = 0; - virtual void UnregisterConVar( ConVarHandle handle ) = 0; + virtual void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, IConVar** pCvar ) = 0; + virtual void UnregisterConVar( ConVarHandle handle ) = 0; virtual IConVar* GetConVar( ConVarHandle handle ) = 0; // Register, unregister commands - virtual ConCommandHandle RegisterConCommand( ConCommand *pCmd, int64 nAdditionalFlags = 0 ) = 0; - virtual void UnregisterConCommand( ConCommandHandle handle ) = 0; - virtual ConCommand* GetCommand( ConCommandHandle handle ) = 0; + virtual ConVarHandle RegisterConCommand( const ConCommandCreation_t& setup, int64 nAdditionalFlags = 0 ) = 0; + virtual void UnregisterConCommand( ConVarHandle handle ) = 0; + virtual ConCommand* GetCommand( ConVarHandle handle ) = 0; virtual void QueueThreadSetValue( ConVar* ref, CSplitScreenSlot nSlot, CVValue_t* value ) = 0; }; diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 6bf4348ab..a75e51735 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -1,4 +1,4 @@ -//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // @@ -49,40 +49,85 @@ class IConVar; class CCommand; class ConCommand; -class ConCommandBase; class ConVar; class ConCommandRefAbstract; -class ALIGN8 ConVarHandle +struct CVarCreationBase_t { -public: - ConVarHandle() { m_value = 0xFFFFFFFF; }; + CVarCreationBase_t( ) : + name( nullptr ), + description( nullptr ), + flags( 0 ) + {} - bool IsValid() const; - void Invalidate(); + bool IsFlagSet( int64_t flag ) const; + void AddFlags( int64_t flags ); + void RemoveFlags( int64_t flags ); + int64_t GetFlags() const; -private: - friend bool operator!=(const ConVarHandle& lhs, const ConVarHandle& rhs); - friend bool operator==(const ConVarHandle& lhs, const ConVarHandle& rhs); + const char* name; + const char* description; + int64_t flags; +}; + +inline bool CVarCreationBase_t::IsFlagSet( int64_t flag ) const +{ + return ( flag & this->flags ) ? true : false; +} + +inline void CVarCreationBase_t::AddFlags( int64_t flags ) +{ + this->flags |= flags; + +#ifdef ALLOW_DEVELOPMENT_CVARS + this->flags &= ~FCVAR_DEVELOPMENTONLY; +#endif +} + +inline void CVarCreationBase_t::RemoveFlags( int64_t flags ) +{ + this->flags &= ~flags; +} + +inline int64_t CVarCreationBase_t::GetFlags( void ) const +{ + return this->flags; +} - uint32 GetValue() const { return m_value; }; +class ConVarHandle +{ +public: + ConVarHandle( uint16_t convarIndex = -1, uint16_t unk = -1, uint32_t handle = -1) : + m_convarIndex(convarIndex), + m_unknown1(unk), + m_handleIndex(handle) + {} - uint32 m_value; -} ALIGN8_POST; + bool IsValid( ) const; + void Invalidate( ); -inline bool operator!=(const ConVarHandle& lhs, const ConVarHandle& rhs) { return lhs.m_value != rhs.m_value; } -inline bool operator==(const ConVarHandle& lhs, const ConVarHandle& rhs) { return lhs.m_value == rhs.m_value; } + uint16_t GetConVarIndex() const { return m_convarIndex; } + uint32_t GetIndex() const { return m_handleIndex; } + +private: + uint16_t m_convarIndex; + uint16_t m_unknown1; + uint32_t m_handleIndex; +}; +static_assert(sizeof(ConVarHandle) == 0x8, "ConVarHandle is of the wrong size!"); static const ConVarHandle INVALID_CONVAR_HANDLE = ConVarHandle(); inline bool ConVarHandle::IsValid() const { - return *this != INVALID_CONVAR_HANDLE; + return m_convarIndex != 0xFFFF; } inline void ConVarHandle::Invalidate() { - m_value = INVALID_CONVAR_HANDLE.GetValue(); + m_convarIndex = 0xFFFF; + m_unknown1 = 0xFFFF; + m_handleIndex = 0x0; } enum CommandTarget_t @@ -115,28 +160,6 @@ class CCommandContext CPlayerSlot m_nPlayerSlot; }; -class ALIGN8 ConCommandHandle -{ -public: - ConCommandHandle() { value = kInvalidConCommandHandle; }; - - bool IsValid() { return value != kInvalidConCommandHandle; } - uint16 Get() { return value; } - void Set( uint16 _value ) { value = _value; } - void Reset() { value = kInvalidConCommandHandle; } - - bool HasCallback() const; - void Dispatch( const CCommandContext& context, const CCommand& command ); - - void Unregister(); - -private: - uint16 value = kInvalidConCommandHandle; - -private: - static const uint16 kInvalidConCommandHandle = 0xFFFF; -} ALIGN8_POST; - struct CSplitScreenSlot { CSplitScreenSlot( int index ) @@ -286,8 +309,6 @@ class ICVarListenerCallbacks virtual void OnConCommandCreated( ConCommandRefAbstract *pNewCommand ) = 0; }; - - //----------------------------------------------------------------------------- // Called when a ConCommand needs to execute //----------------------------------------------------------------------------- @@ -319,47 +340,9 @@ class ICommandCompletionCallback class ConCommandRefAbstract { public: - ConCommandHandle handle; -}; - -//----------------------------------------------------------------------------- -// Purpose: The base console invoked command/cvar interface -//----------------------------------------------------------------------------- -class ConCommandBase -{ - friend class CCvar; - friend class ConCommand; - -protected: - ConCommandBase( void ); -public: - - ~ConCommandBase( void ); - // Check flag - bool IsFlagSet( int64 flag ) const; - // Set flag - void AddFlags( int64 flags ); - // Clear flag - void RemoveFlags( int64 flags ); - - int64 GetFlags() const; - - // Return name of cvar - const char *GetName( void ) const; - - // Return help text for cvar - const char *GetHelpText( void ) const; - -private: - // Static data - const char *m_pszName; - const char *m_pszHelpString; - - // ConVar flags - int64 m_nFlags; + ConVarHandle handle; }; - //----------------------------------------------------------------------------- // Command tokenizer //----------------------------------------------------------------------------- @@ -445,64 +428,37 @@ inline const char *CCommand::operator[]( int nIndex ) const //----------------------------------------------------------------------------- // Purpose: The console invoked command //----------------------------------------------------------------------------- -class ConCommand : public ConCommandBase +struct ConCommandCreation_t : CVarCreationBase_t { -friend class CCvar; -friend class ConCommandHandle; - -public: - typedef ConCommandBase BaseClass; - - ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallback_t callback, - const char *pHelpString = 0, int64 flags = 0, FnCommandCompletionCallback completionFunc = 0 ); - ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallbackVoid_t callback, - const char *pHelpString = 0, int64 flags = 0, FnCommandCompletionCallback completionFunc = 0 ); - ConCommand( ConCommandRefAbstract* pReferenceOut, const char* pName, FnCommandCallbackNoContext_t callback, - const char* pHelpString = 0, int64 flags = 0, FnCommandCompletionCallback completionFunc = 0 ); - ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, ICommandCallback *pCallback, - const char *pHelpString = 0, int64 flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 ); - - ~ConCommand( void ); - - // Used internally by OneTimeInit to initialize/shutdown - void Init(); - void Shutdown(); - - void Create( const char *pName, const char *pHelpString = 0, - int64 flags = 0 ); - - int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands ); - - bool CanAutoComplete( void ); - - inline ConCommandRefAbstract *GetRef( void ) const - { - return m_pReference; - } - - inline void SetHandle( ConCommandHandle hndl ) - { - m_pReference->handle = hndl; - } + ConCommandCreation_t() : + has_complitioncallback(false), + is_interface(false), + refHandle(nullptr) + {} -private: // Call this function when executing the command - class CallbackInfo_t + struct CallbackInfo_t { - public: + CallbackInfo_t() : + fnCommandCallback(nullptr), + is_interface(false), + is_voidcallback(false), + is_contextless(false) + {} + union { - FnCommandCallback_t m_fnCommandCallback; - FnCommandCallbackVoid_t m_fnVoidCommandCallback; - FnCommandCallbackNoContext_t m_fnContextlessCommandCallback; - ICommandCallback* m_pCommandCallback; + FnCommandCallback_t fnCommandCallback; + FnCommandCallbackVoid_t fnVoidCommandCallback; + FnCommandCallbackNoContext_t fnContextlessCommandCallback; + ICommandCallback* pCommandCallback; }; - bool m_bUsingCommandCallbackInterface : 1; - bool m_bHasVoidCommandCallback : 1; - bool m_bHasContextlessCommandCallback : 1; + bool is_interface; + bool is_voidcallback; + bool is_contextless; }; - CallbackInfo_t m_Callback; + CallbackInfo_t callback; // NOTE: To maintain backward compat, we have to be very careful: // All public virtual methods must appear in the same order always @@ -514,150 +470,41 @@ friend class ConCommandHandle; union { - FnCommandCompletionCallback m_fnCompletionCallback; - ICommandCompletionCallback* m_pCommandCompletionCallback; + FnCommandCompletionCallback fnCompletionCallback; + ICommandCompletionCallback* pCommandCompletionCallback; }; - bool m_bHasCompletionCallback : 1; - bool m_bUsingCommandCompletionInterface : 1; - - ConCommandRefAbstract *m_pReference; -}; + bool has_complitioncallback; + bool is_interface; + ConVarHandle* refHandle; +}; +static_assert(sizeof(ConCommandCreation_t) == 0x40, "ConCommandCreation_t is of the wrong size!"); -//----------------------------------------------------------------------------- -// Purpose: A console variable -//----------------------------------------------------------------------------- -#if false -class ConVar +class ConCommandBase {}; // For metamod compatibility only!!!! +class ConCommand : public ConCommandBase { -friend class CCvar; -friend class SplitScreenConVarRef; - public: - ConVar( const char *pName, const char *pDefaultValue, int64 flags = 0); - - ConVar( const char *pName, const char *pDefaultValue, int64 flags, - const char *pHelpString ); - ConVar( const char *pName, const char *pDefaultValue, int64 flags, - const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax ); - ConVar( const char *pName, const char *pDefaultValue, int64 flags, - const char *pHelpString, FnChangeCallback_t callback ); - ConVar( const char *pName, const char *pDefaultValue, int64 flags, - const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax, - FnChangeCallback_t callback ); - - ~ConVar( void ); - - bool IsFlagSet( int64 flag ) const; - const char* GetHelpText( void ) const; - const char *GetName( void ) const; - // Return name of command (usually == GetName(), except in case of FCVAR_SS_ADDED vars - const char *GetBaseName( void ) const; - int GetSplitScreenPlayerSlot() const; - - void AddFlags( int64 flags ); - int64 GetFlags() const; - - // Install a change callback (there shouldn't already be one....) - void InstallChangeCallback( FnChangeCallback_t callback, bool bInvoke = true ); - void RemoveChangeCallback( FnChangeCallback_t callbackToRemove ); - - int GetChangeCallbackCount() const { return m_pParent->m_fnChangeCallbacks.Count(); } - FnChangeCallback_t GetChangeCallback( int slot ) const { return m_pParent->m_fnChangeCallbacks[ slot ]; } - - // Retrieve value - FORCEINLINE_CVAR float GetFloat( void ) const; - FORCEINLINE_CVAR int GetInt( void ) const; - FORCEINLINE_CVAR Color GetColor( void ) const; - FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); } - FORCEINLINE_CVAR char const *GetString( void ) const; - - // Compiler driven selection for template use - template T Get( void ) const; - template T Get( T * ) const; - - // Any function that allocates/frees memory needs to be virtual or else you'll have crashes - // from alloc/free across dll/exe boundaries. - - // These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue). - void SetValue( const char *value ); - void SetValue( float value ); - void SetValue( int value ); - void SetValue( Color value ); - - // Reset to default value - void Revert( void ); - - // True if it has a min/max setting - bool HasMin() const; - bool HasMax() const; - - bool GetMin( float& minVal ) const; - bool GetMax( float& maxVal ) const; - - float GetMinValue() const; - float GetMaxValue() const; - - const char *GetDefault( void ) const; - + ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallback_t callback, + const char *pHelpString = 0, int64 flags = 0, FnCommandCompletionCallback completionFunc = 0 ); + ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallbackVoid_t callback, + const char *pHelpString = 0, int64 flags = 0, FnCommandCompletionCallback completionFunc = 0 ); + ConCommand( ConCommandRefAbstract* pReferenceOut, const char* pName, FnCommandCallbackNoContext_t callback, + const char* pHelpString = 0, int64 flags = 0, FnCommandCompletionCallback completionFunc = 0 ); + ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, ICommandCallback *pCallback, + const char *pHelpString = 0, int64 flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 ); - FORCEINLINE_CVAR CVValue_t &GetRawValue() - { - return m_Value; - } - FORCEINLINE_CVAR const CVValue_t &GetRawValue() const + ~ConCommand() { - return m_Value; + this->Destroy(); } private: - bool InternalSetColorFromString( const char *value ); - // Called by CCvar when the value of a var is changing. - void InternalSetValue(const char *value); - // For CVARs marked FCVAR_NEVER_AS_STRING - void InternalSetFloatValue( float fNewValue ); - void InternalSetIntValue( int nValue ); - void InternalSetColorValue( Color value ); - - bool ClampValue( float& value ); - void ChangeStringValue( const char *tempVal, float flOldValue ); - - void Create( const char *pName, const char *pDefaultValue, int64 flags = 0, - const char *pHelpString = 0, bool bMin = false, float fMin = 0.0, - bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 ); - - // Used internally by OneTimeInit to initialize. - void Init(); + void Create( const char *pName, const char *pHelpString, int64_t flags, ConCommandCreation_t& setup ); + void Destroy( ); - - -protected: - const char* m_pszName; - CVValue_t* m_cvvDefaultValue; - CVValue_t* m_cvvMinValue; - CVValue_t* m_cvvMaxValue; - const char* m_pszHelpString; - EConVarType m_eVarType; - - // This gets copied from the ConVarDesc_t on creation - short unk1; - - unsigned int timesChanged; - int64 flags; - unsigned int callback_index; - - // Used when setting default, max, min values from the ConVarDesc_t - // although that's not the only place of usage - // flags seems to be: - // (1 << 0) Skip setting value to split screen slots and also something keyvalues related - // (1 << 1) Skip setting default value - // (1 << 2) Skip setting min/max values - int allocation_flag_of_some_sort; - - CVValue_t** values; + ConVarHandle m_Handle; }; -#endif #pragma pack(push,1) struct ConVarSetup_t @@ -695,23 +542,20 @@ struct ConVarSetup_t int16_t unk2; // 0x46 }; #pragma pack(pop) + static_assert(sizeof(ConVarSetup_t) == 0x48, "ConVarSetup_t is of the wrong size!"); static_assert(sizeof(ConVarSetup_t) % 8 == 0x0, "ConVarSetup_t isn't 8 bytes aligned!"); -#pragma pack(push,1) -struct ConVarCreation_t { - ConVarCreation_t() { memset(this, 0, sizeof(*this)); } - - const char* name; // 0x0 - const char* description; // 0x8 - int64_t flags; // 0x10 - +struct ConVarCreation_t : CVarCreationBase_t { + ConVarCreation_t() : + refHandle(nullptr), + refConVar(nullptr) + {} ConVarSetup_t setup; // 0x18 ConVarHandle* refHandle; // 0x60 IConVar** refConVar; // 0x68 }; -#pragma pack(pop) static_assert(sizeof(ConVarCreation_t) == 0x70, "ConVarCreation_t wrong size!"); static_assert(sizeof(ConVarCreation_t) % 8 == 0x0, "ConVarCreation_t isn't 8 bytes aligned!"); @@ -725,7 +569,7 @@ class ConVar public: // sub_6A66B0 template - ConVar(const char* name, int32 flags, const char* description, T value) + ConVar(const char* name, int32_t flags, const char* description, T value) { this->Init(INVALID_CONVAR_HANDLE, TranslateType()); @@ -734,18 +578,20 @@ class ConVar setup.default_value = value; setup.type = TranslateType(); - this->sub_10B7C70(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); + this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); } + ~ConVar(); + private: template static constexpr EConVarType TranslateType(); - + // sub_10B7BC0 void Init(ConVarHandle defaultHandle, EConVarType type); // sub_10B7C70 - void sub_10B7C70(const char* name, int32 flags, const char* description, const ConVarSetup_t& obj); + void Register(const char* name, int32_t flags, const char* description, const ConVarSetup_t& obj); public: // High-speed method to read convar data ConVarHandle m_Handle; @@ -1151,7 +997,7 @@ void ConVar_Unregister( ); //----------------------------------------------------------------------------- // Utility methods //----------------------------------------------------------------------------- -void ConVar_PrintDescription( const ConCommandBase *pVar ); +void ConVar_PrintDescription( const CVarCreationBase_t* pVar ); //----------------------------------------------------------------------------- @@ -1180,7 +1026,7 @@ class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, pu ~CConCommandMemberAccessor() { - Shutdown(); + this->Destroy(); } void SetOwner( T* pOwner ) diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 6fdc097a3..9d79ee885 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -33,72 +33,117 @@ static int64 s_nCVarFlag = 0; static bool s_bRegistered = false; -class ConCommandRegList; -class ConCommandRegList +void RegisterCommand( ConCommandCreation_t& cmd ) { -public: - static void RegisterCommand(ConCommand* pCmd) + *cmd.refHandle = g_pCVar->RegisterConCommand( cmd, s_nCVarFlag ); + if ( !cmd.refHandle->IsValid() ) { - if (s_bConCommandsRegistered) - { - ConCommandHandle hndl = g_pCVar->RegisterConCommand(pCmd, s_nCVarFlag); - if (!hndl.IsValid()) - { - Plat_FatalErrorFunc("RegisterConCommand: Unknown error registering con command \"%s\"!\n", pCmd->GetName()); - DebuggerBreakIfDebugging(); - } + Plat_FatalErrorFunc( "RegisterConCommand: Unknown error registering con command \"%s\"!\n", cmd.name ); + DebuggerBreakIfDebugging( ); + } +} - pCmd->SetHandle(hndl); - } - else - { - GetCommandRegList()->AddToTail(pCmd); - } +void UnRegisterCommand( ConVarHandle& cmd ) +{ + if ( cmd.IsValid() ) + { + g_pCVar->UnregisterConCommand( cmd ); + + cmd.Invalidate(); } +} + +class ConCommandRegList; +static ConCommandRegList* s_pCommandRegList = nullptr; +class ConCommandRegList +{ +public: static void RegisterAll() { if (!s_bConCommandsRegistered && g_pCVar) { s_bConCommandsRegistered = true; - for(int i = 0; i < GetCommandRegList()->Count(); i++) + ConCommandRegList* list = s_pCommandRegList; + while ( list != nullptr ) { - ConCommand *pCmd = GetCommandRegList()->Element(i); - ConCommandHandle hndl = g_pCVar->RegisterConCommand(pCmd, s_nCVarFlag); - pCmd->SetHandle(hndl); - - if (!hndl.IsValid()) + FOR_EACH_VEC( list->m_Vec, i ) { - Plat_FatalErrorFunc("RegisterConCommand: Unknown error registering con command \"%s\"!\n", pCmd->GetName()); - DebuggerBreakIfDebugging(); + RegisterCommand( list->m_Vec[i] ); } + + ConCommandRegList *pNext = list->m_pNext; + delete list; + list = pNext; } } } private: + friend void AddCommand( ConCommandCreation_t& cmd ); + + void SetNextList( ConCommandRegList* list ) + { + m_pNext = list; + } - // GAMMACASE: Required to prevent static initialization order problem https://isocpp.org/wiki/faq/ctors#static-init-order - static CUtlVector *GetCommandRegList() + int Count() const + { + return m_Vec.Count(); + } + + void Add( const ConCommandCreation_t& cmd ) { - static CUtlVector s_ConCommandRegList; - return &s_ConCommandRegList; + m_Vec.AddToTail( cmd ); } + CUtlVectorFixed m_Vec; + ConCommandRegList* m_pNext = nullptr; +public: static bool s_bConCommandsRegistered; }; +bool ConCommandRegList::s_bConCommandsRegistered = false; + +void AddCommand( ConCommandCreation_t& cmd ) +{ + if (ConCommandRegList::s_bConCommandsRegistered && s_bRegistered) + { + RegisterCommand( cmd ); + return; + } + + if ( !s_pCommandRegList || s_pCommandRegList->Count() == 100 ) + { + ConCommandRegList* newList = new ConCommandRegList; + newList->SetNextList( s_pCommandRegList ); + + s_pCommandRegList = newList; + } + + s_pCommandRegList->Add( cmd ); +} -void RegisterConVar( ConVarCreation_t& setup ) +void RegisterConVar( ConVarCreation_t& cvar ) { - g_pCVar->RegisterConVar( setup, s_nCVarFlag, setup.refHandle, setup.refConVar ); - if (!setup.refHandle->IsValid()) + ConMsg( "Registering cvar %s\n", cvar.name ); + + g_pCVar->RegisterConVar( cvar, s_nCVarFlag, cvar.refHandle, cvar.refConVar ); + if (!cvar.refHandle->IsValid()) { - Plat_FatalErrorFunc( "RegisterConCommand: Unknown error registering convar \"%s\"!\n", setup.name ); + Plat_FatalErrorFunc( "RegisterConVar: Unknown error registering convar \"%s\"!\n", cvar.name ); DebuggerBreakIfDebugging(); } } -bool ConCommandRegList::s_bConCommandsRegistered = false; +void UnRegisterConVar( ConVarHandle& cvar ) +{ + if (cvar.IsValid()) + { + g_pCVar->UnregisterConVar( cvar ); + + cvar.Invalidate(); + } +} class ConVarRegList; static ConVarRegList* s_pConVarRegList = nullptr; @@ -108,11 +153,6 @@ class ConVarRegList public: ConVarRegList() {} - static bool AreConVarsRegistered() - { - return s_bConVarsRegistered; - } - static void RegisterAll() { if ( !s_bConVarsRegistered && g_pCVar ) @@ -120,9 +160,9 @@ class ConVarRegList s_bConVarsRegistered = true; ConVarRegList* list = s_pConVarRegList; - while ( list != nullptr ) + while ( list ) { - FOR_EACH_VEC( s_pConVarRegList->m_Vec, i ) + FOR_EACH_VEC( list->m_Vec, i ) { RegisterConVar( list->m_Vec[i] ); } @@ -131,32 +171,30 @@ class ConVarRegList delete list; list = pNext; } - - s_pConVarRegList = nullptr; } } - int Count() const - { - return m_Vec.Count(); - } - private: - friend void SetupConVar( ConVarCreation_t& setup ); + friend void SetupConVar( ConVarCreation_t& cvar ); void SetNextList( ConVarRegList* list ) { m_pNext = list; } - void Add( const ConVarCreation_t& setup ) + int Count() const + { + return m_Vec.Count(); + } + + void Add( const ConVarCreation_t& cvar ) { - m_Vec.AddToTail( setup ); + m_Vec.AddToTail( cvar ); } CUtlVectorFixed m_Vec; ConVarRegList* m_pNext = nullptr; - +public: static bool s_bConVarsRegistered; }; static_assert(sizeof(ConVarRegList) == 0x2BD0, "Size mismatch"); @@ -164,11 +202,11 @@ static_assert(sizeof(ConVarRegList) == 0x2BD0, "Size mismatch"); bool ConVarRegList::s_bConVarsRegistered = false; // sub_10B79F0 -void SetupConVar( ConVarCreation_t& setup ) +void SetupConVar( ConVarCreation_t& cvar ) { - if ( s_bRegistered ) + if ( ConVarRegList::s_bConVarsRegistered ) { - RegisterConVar(setup); + RegisterConVar(cvar); return; } @@ -180,7 +218,9 @@ void SetupConVar( ConVarCreation_t& setup ) s_pConVarRegList = newList; } - s_pConVarRegList->Add( setup ); + s_pConVarRegList->Add( cvar ); + + ConMsg( "Setting up cvar %s\n", cvar.name ); } //----------------------------------------------------------------------------- @@ -208,83 +248,6 @@ void ConVar_Unregister( ) s_bRegistered = false; } -//----------------------------------------------------------------------------- -// Purpose: Default constructor -//----------------------------------------------------------------------------- -ConCommandBase::ConCommandBase( void ) -{ - m_pszName = NULL; - m_pszHelpString = NULL; - - m_nFlags = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -ConCommandBase::~ConCommandBase( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Return name of the command/var -// Output : const char -//----------------------------------------------------------------------------- -const char *ConCommandBase::GetName( void ) const -{ - return m_pszName; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flag - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool ConCommandBase::IsFlagSet( int64 flag ) const -{ - return ( flag & m_nFlags ) ? true : false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flags - -//----------------------------------------------------------------------------- -void ConCommandBase::AddFlags( int64 flags ) -{ - m_nFlags |= flags; - -#ifdef ALLOW_DEVELOPMENT_CVARS - m_nFlags &= ~FCVAR_DEVELOPMENTONLY; -#endif -} - -void ConCommandBase::RemoveFlags( int64 flags ) -{ - m_nFlags &= ~flags; -} - -int64 ConCommandBase::GetFlags( void ) const -{ - return m_nFlags; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *ConCommandBase::GetHelpText( void ) const -{ - return m_pszHelpString; -} - -//----------------------------------------------------------------------------- -// -// Con Commands start here -// -//----------------------------------------------------------------------------- - - //----------------------------------------------------------------------------- // Global methods //----------------------------------------------------------------------------- @@ -474,98 +437,68 @@ int DefaultCompletionFunc( const char *partial, CUtlVector< CUtlString > &comman return 0; } - ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallback_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) { - m_Callback.m_fnCommandCallback = callback; - m_Callback.m_bUsingCommandCallbackInterface = false; - m_Callback.m_bHasVoidCommandCallback = false; - m_Callback.m_bHasContextlessCommandCallback = false; - - m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; - m_bHasCompletionCallback = completionFunc != 0 ? true : false; - m_bUsingCommandCompletionInterface = false; + ConCommandCreation_t creation; + creation.callback.fnCommandCallback = callback; + creation.callback.is_interface = false; + creation.callback.is_voidcallback = false; + creation.callback.is_contextless = false; - m_pReference = pReferenceOut; - m_pReference->handle.Reset(); + creation.fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; + creation.has_complitioncallback = completionFunc != 0 ? true : false; + creation.is_interface = false; // Setup the rest - Create( pName, pHelpString, flags ); + Create( pName, pHelpString, flags, creation ); } ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallbackVoid_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) { - m_Callback.m_fnVoidCommandCallback = callback; - m_Callback.m_bUsingCommandCallbackInterface = false; - m_Callback.m_bHasVoidCommandCallback = true; - m_Callback.m_bHasContextlessCommandCallback = false; - - m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; - m_bHasCompletionCallback = completionFunc != 0 ? true : false; - m_bUsingCommandCompletionInterface = false; + ConCommandCreation_t creation; + creation.callback.fnVoidCommandCallback = callback; + creation.callback.is_interface = false; + creation.callback.is_voidcallback = true; + creation.callback.is_contextless = false; - m_pReference = pReferenceOut; - m_pReference->handle.Reset(); + creation.fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; + creation.has_complitioncallback = completionFunc != nullptr ? true : false; + creation.is_interface = false; // Setup the rest - Create( pName, pHelpString, flags ); + Create( pName, pHelpString, flags, creation ); } ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallbackNoContext_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) { - m_Callback.m_fnContextlessCommandCallback = callback; - m_Callback.m_bUsingCommandCallbackInterface = false; - m_Callback.m_bHasVoidCommandCallback = false; - m_Callback.m_bHasContextlessCommandCallback = true; + ConCommandCreation_t creation; + creation.callback.fnContextlessCommandCallback = callback; + creation.callback.is_interface = false; + creation.callback.is_voidcallback = false; + creation.callback.is_contextless = true; - m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; - m_bHasCompletionCallback = completionFunc != 0 ? true : false; - m_bUsingCommandCompletionInterface = false; - - m_pReference = pReferenceOut; - m_pReference->handle.Reset(); + creation.fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; + creation.has_complitioncallback = completionFunc != nullptr ? true : false; + creation.is_interface = false; // Setup the rest - Create(pName, pHelpString, flags); + Create( pName, pHelpString, flags, creation ); } ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, ICommandCallback *pCallback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, ICommandCompletionCallback *pCompletionCallback /*= 0*/ ) { - m_Callback.m_pCommandCallback = pCallback; - m_Callback.m_bUsingCommandCallbackInterface = true; - m_Callback.m_bHasVoidCommandCallback = false; - m_Callback.m_bHasContextlessCommandCallback = false; - - m_pCommandCompletionCallback = pCompletionCallback; - m_bHasCompletionCallback = true; - m_bUsingCommandCompletionInterface = true; + ConCommandCreation_t creation; + creation.callback.pCommandCallback = pCallback; + creation.callback.is_interface = true; + creation.callback.is_voidcallback = false; + creation.callback.is_contextless = false; - m_pReference = pReferenceOut; - m_pReference->handle.Reset(); + creation.pCommandCompletionCallback = pCompletionCallback; + creation.has_complitioncallback = pCompletionCallback != nullptr ? true : false; + creation.is_interface = true; // Setup the rest - Create( pName, pHelpString, flags ); -} - -//----------------------------------------------------------------------------- -// Destructor -//----------------------------------------------------------------------------- -ConCommand::~ConCommand( void ) -{ - ConCommandRefAbstract *pRef = GetRef(); - if ( pRef ) - { - pRef->handle.Unregister(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Used internally by OneTimeInit to initialize. -//----------------------------------------------------------------------------- -void ConCommand::Init() -{ - ConCommandRegList::RegisterCommand( this ); + Create( pName, pHelpString, flags, creation ); } //----------------------------------------------------------------------------- @@ -575,103 +508,28 @@ void ConCommand::Init() // *pHelpString - // flags - //----------------------------------------------------------------------------- -void ConCommand::Create( const char* pName, const char* pHelpString /*= 0*/, int64 flags /*= 0*/ ) +void ConCommand::Create( const char* pName, const char* pHelpString, int64_t flags, ConCommandCreation_t& setup ) { static const char* empty_string = ""; // Name should be static data Assert(pName); - m_pszName = pName; - m_pszHelpString = pHelpString ? pHelpString : empty_string; + setup.name = pName; + setup.description = pHelpString ? pHelpString : empty_string; - m_nFlags = flags; + setup.flags = flags; #ifdef ALLOW_DEVELOPMENT_CVARS - m_nFlags &= ~FCVAR_DEVELOPMENTONLY; + setup.flags &= ~FCVAR_DEVELOPMENTONLY; #endif + setup.refHandle = &this->m_Handle; - Init(); + AddCommand( setup ); } -void ConCommand::Shutdown() +void ConCommand::Destroy() { - GetRef()->handle.Unregister(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Invoke the function if there is one -//----------------------------------------------------------------------------- -void ConCommandHandle::Dispatch( const CCommandContext &context, const CCommand &command ) -{ - ConCommand *pCommand = g_pCVar->GetCommand( *this ); - if ( pCommand->m_Callback.m_fnCommandCallback ) - { - if ( pCommand->m_Callback.m_bUsingCommandCallbackInterface ) - { - pCommand->m_Callback.m_pCommandCallback->CommandCallback( context, command ); - } - else if ( pCommand->m_Callback.m_bHasVoidCommandCallback ) - { - pCommand->m_Callback.m_fnVoidCommandCallback(); - } - else if ( pCommand->m_Callback.m_bHasContextlessCommandCallback ) - { - pCommand->m_Callback.m_fnContextlessCommandCallback( command ); - } - else - { - pCommand->m_Callback.m_fnCommandCallback( context, command ); - } - } - - // Command without callback!!! - AssertMsg(0, ("Encountered ConCommand without a callback!\n")); -} - -bool ConCommandHandle::HasCallback() const -{ - ConCommand *pCommand = g_pCVar->GetCommand( *this ); - return pCommand->m_Callback.m_fnCommandCallback != nullptr; -} - -void ConCommandHandle::Unregister() -{ - if (IsValid()) - { - if ( g_pCVar ) - g_pCVar->UnregisterConCommand( *this ); - - Reset(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Calls the autocompletion method to get autocompletion suggestions -//----------------------------------------------------------------------------- -int ConCommand::AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands ) -{ - if (m_bUsingCommandCompletionInterface) - { - if ( !m_pCommandCompletionCallback ) - return 0; - return m_pCommandCompletionCallback->CommandCompletionCallback( partial, commands ); - } - - Assert( m_fnCompletionCallback ); - if ( !m_fnCompletionCallback ) - return 0; - - return m_fnCompletionCallback( partial, commands ); -} - - -//----------------------------------------------------------------------------- -// Returns true if the console command can autocomplete -//----------------------------------------------------------------------------- -bool ConCommand::CanAutoComplete( void ) -{ - return m_bHasCompletionCallback; + UnRegisterCommand(this->m_Handle); } //----------------------------------------------------------------------------- @@ -719,13 +577,18 @@ IConVar* ConVar_Invalid(EConVarType type) return &invalid_convar[type]; } +ConVar::~ConVar() +{ + UnRegisterConVar(this->m_Handle); +} + void ConVar::Init(ConVarHandle defaultHandle, EConVarType type) { this->m_Handle.Invalidate(); this->m_ConVar = nullptr; // qword_191A3D8 - if (g_pCVar && g_pCVar->GetConVar(defaultHandle) == nullptr) + if (g_pCVar && (this->m_ConVar = g_pCVar->GetConVar(defaultHandle) == nullptr)) { this->m_ConVar = ConVar_Invalid(type); // technically this @@ -734,9 +597,7 @@ void ConVar::Init(ConVarHandle defaultHandle, EConVarType type) this->m_Handle = defaultHandle; } -//std::exit((int64_t)(&((ConVarSetup_t*)nullptr)->type)); - -void ConVar::sub_10B7C70(const char* name, int32 flags, const char* description, const ConVarSetup_t& setup) +void ConVar::Register(const char* name, int32_t flags, const char* description, const ConVarSetup_t& setup) { this->m_ConVar = ConVar_Invalid(setup.type); this->m_Handle.Invalidate(); From ed18156df64d230d78e106fdeba0301060ed346f Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sat, 7 Oct 2023 22:53:36 +0200 Subject: [PATCH 07/48] undo automatic symbol change --- public/tier0/icommandline.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/tier0/icommandline.h b/public/tier0/icommandline.h index 9ca3bb798..561bb2324 100644 --- a/public/tier0/icommandline.h +++ b/public/tier0/icommandline.h @@ -1,4 +1,4 @@ -//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // From 8429213cef9f4977a60e4f1203c7af6a6f870923 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sat, 7 Oct 2023 22:59:47 +0200 Subject: [PATCH 08/48] Get rid of ConCommandRefAbstract --- public/tier1/convar.h | 51 ++++++++++++++----------------------------- tier1/convar.cpp | 10 ++++----- 2 files changed, 21 insertions(+), 40 deletions(-) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index a75e51735..c8844ea74 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -50,7 +50,6 @@ class IConVar; class CCommand; class ConCommand; class ConVar; -class ConCommandRefAbstract; struct CVarCreationBase_t { @@ -266,7 +265,7 @@ union CVValue_t uint64_t m_u64Value; float m_flValue; double m_dbValue; - const char* m_szValue; + const char* m_szValue; Color m_clrValue; Vector2D m_vec2Value; Vector m_vec3Value; @@ -306,7 +305,7 @@ class ICVarListenerCallbacks { public: virtual void OnConVarCreated( ConVar* pNewCvar ) = 0; - virtual void OnConCommandCreated( ConCommandRefAbstract *pNewCommand ) = 0; + virtual void OnConCommandCreated( ConCommand* pNewCommand ) = 0; }; //----------------------------------------------------------------------------- @@ -337,12 +336,6 @@ class ICommandCompletionCallback virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0; }; -class ConCommandRefAbstract -{ -public: - ConVarHandle handle; -}; - //----------------------------------------------------------------------------- // Command tokenizer //----------------------------------------------------------------------------- @@ -485,13 +478,13 @@ class ConCommandBase {}; // For metamod compatibility only!!!! class ConCommand : public ConCommandBase { public: - ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallback_t callback, + ConCommand( const char *pName, FnCommandCallback_t callback, const char *pHelpString = 0, int64 flags = 0, FnCommandCompletionCallback completionFunc = 0 ); - ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallbackVoid_t callback, + ConCommand( const char *pName, FnCommandCallbackVoid_t callback, const char *pHelpString = 0, int64 flags = 0, FnCommandCompletionCallback completionFunc = 0 ); - ConCommand( ConCommandRefAbstract* pReferenceOut, const char* pName, FnCommandCallbackNoContext_t callback, + ConCommand( const char* pName, FnCommandCallbackNoContext_t callback, const char* pHelpString = 0, int64 flags = 0, FnCommandCompletionCallback completionFunc = 0 ); - ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, ICommandCallback *pCallback, + ConCommand( const char *pName, ICommandCallback *pCallback, const char *pHelpString = 0, int64 flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 ); ~ConCommand() @@ -1017,7 +1010,7 @@ class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, pu public: CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0, int64 flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) : - BaseClass( &m_ConCommandRef, pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL ) + BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL ) { m_pOwner = pOwner; m_Func = callback; @@ -1050,7 +1043,6 @@ class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, pu T* m_pOwner; FnMemberCommandCallback_t m_Func; FnMemberCommandCompletionCallback_t m_CompletionFunc; - ConCommandRefAbstract m_ConCommandRef; }; #ifdef _MSC_VER @@ -1061,61 +1053,52 @@ class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, pu // Purpose: Utility macros to quicky generate a simple console command //----------------------------------------------------------------------------- #define CON_COMMAND( name, description ) \ - static ConCommandRefAbstract name##_ref; \ static void name##_callback( const CCommand &args ); \ - static ConCommand name##_command( &name##_ref, #name, name##_callback, description ); \ + static ConCommand name##_command( #name, name##_callback, description ); \ static void name##_callback( const CCommand &args ) #ifdef CLIENT_DLL #define CON_COMMAND_SHARED( name, description ) \ - static ConCommandRefAbstract name##_ref; \ static void name##_callback( const CCommandContext &context, const CCommand &args ); \ - static ConCommand name##_command_client( &name##_ref, #name "_client", name##_callback, description ); \ + static ConCommand name##_command_client( #name "_client", name##_callback, description ); \ static void name##_callback( const CCommandContext &context, const CCommand &args ) #else #define CON_COMMAND_SHARED( name, description ) \ - static ConCommandRefAbstract name##_ref; \ static void name##_callback( const CCommandContext &context, const CCommand &args ); \ - static ConCommand name##_command( &name##_ref, #name, name##_callback, description ); \ + static ConCommand name##_command( #name, name##_callback, description ); \ static void name##_callback( const CCommandContext &context, const CCommand &args ) #endif #define CON_COMMAND_F( name, description, flags ) \ - static ConCommandRefAbstract name##_ref; \ static void name##_callback( const CCommandContext &context, const CCommand &args ); \ - static ConCommand name##_command( &name##_ref, #name, name##_callback, description, flags ); \ + static ConCommand name##_command( #name, name##_callback, description, flags ); \ static void name##_callback( const CCommandContext &context, const CCommand &args ) #ifdef CLIENT_DLL #define CON_COMMAND_F_SHARED( name, description, flags ) \ - static ConCommandRefAbstract name##_ref; \ static void name##_callback( const CCommandContext &context, const CCommand &args ); \ - static ConCommand name##_command_client( &name##_ref, #name "_client", name##_callback, description, flags ); \ + static ConCommand name##_command_client( #name "_client", name##_callback, description, flags ); \ static void name##_callback( const CCommandContext &context, const CCommand &args ) #else #define CON_COMMAND_F_SHARED( name, description, flags ) \ - static ConCommandRefAbstract name##_ref; \ static void name##_callback( const CCommandContext &context, const CCommand &args ); \ - static ConCommand name##_command( &name##_ref, #name, name##_callback, description, flags ); \ + static ConCommand name##_command( #name, name##_callback, description, flags ); \ static void name##_callback( const CCommandContext &context, const CCommand &args ) #endif #define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \ - static ConCommandRefAbstract name##_ref; \ static void name##_callback( const CCommandContext &context, const CCommand &args ); \ - static ConCommand name##_command( &name##_ref, #name, name##_callback, description, flags, completion ); \ + static ConCommand name##_command( #name, name##_callback, description, flags, completion ); \ static void name##_callback( const CCommandContext &context, const CCommand &args ) #ifdef CLIENT_DLL #define CON_COMMAND_F_COMPLETION_SHARED( name, description, flags, completion ) \ - static ConCommandRefAbstract name##_ref; \ static void name##_callback( const CCommandContext &context, const CCommand &args ); \ static ConCommand name##_command_client( name##_command, #name "_client", name##_callback, description, flags, completion ); \ static void name##_callback( const CCommandContext &context, const CCommand &args ) #else #define CON_COMMAND_F_COMPLETION_SHARED( name, description, flags, completion ) \ - static ConCommandRefAbstract name##_ref; \ static void name##_callback( const CCommandContext &context, const CCommand &args ); \ static ConCommand name##_command( name##_command, #name, name##_callback, description, flags, completion ); \ static void name##_callback( const CCommandContext &context, const CCommand &args ) @@ -1123,15 +1106,13 @@ class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, pu #define CON_COMMAND_EXTERN( name, _funcname, description ) \ - static ConCommandRefAbstract name##_ref; \ void _funcname( const CCommandContext &context, const CCommand &args ); \ - static ConCommand name##_command( &name##_ref, #name, _funcname, description ); \ + static ConCommand name##_command( #name, _funcname, description ); \ void _funcname( const CCommandContext &context, const CCommand &args ) #define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \ - static ConCommandRefAbstract name##_ref; \ void _funcname( const CCommandContext &context, const CCommand &args ); \ - static ConCommand name##_command( &name##_ref, #name, _funcname, description, flags ); \ + static ConCommand name##_command( #name, _funcname, description, flags ); \ void _funcname( const CCommandContext &context, const CCommand &args ) #define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \ diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 9d79ee885..672366b8d 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -437,7 +437,7 @@ int DefaultCompletionFunc( const char *partial, CUtlVector< CUtlString > &comman return 0; } -ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallback_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) +ConCommand::ConCommand( const char *pName, FnCommandCallback_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) { ConCommandCreation_t creation; creation.callback.fnCommandCallback = callback; @@ -453,7 +453,7 @@ ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, Create( pName, pHelpString, flags, creation ); } -ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallbackVoid_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) +ConCommand::ConCommand( const char *pName, FnCommandCallbackVoid_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) { ConCommandCreation_t creation; creation.callback.fnVoidCommandCallback = callback; @@ -469,7 +469,7 @@ ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, Create( pName, pHelpString, flags, creation ); } -ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallbackNoContext_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) +ConCommand::ConCommand( const char *pName, FnCommandCallbackNoContext_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) { ConCommandCreation_t creation; creation.callback.fnContextlessCommandCallback = callback; @@ -485,7 +485,7 @@ ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, Create( pName, pHelpString, flags, creation ); } -ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, ICommandCallback *pCallback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, ICommandCompletionCallback *pCompletionCallback /*= 0*/ ) +ConCommand::ConCommand( const char *pName, ICommandCallback *pCallback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, ICommandCompletionCallback *pCompletionCallback /*= 0*/ ) { ConCommandCreation_t creation; creation.callback.pCommandCallback = pCallback; @@ -588,7 +588,7 @@ void ConVar::Init(ConVarHandle defaultHandle, EConVarType type) this->m_ConVar = nullptr; // qword_191A3D8 - if (g_pCVar && (this->m_ConVar = g_pCVar->GetConVar(defaultHandle) == nullptr)) + if (g_pCVar && (this->m_ConVar = g_pCVar->GetConVar(defaultHandle)) == nullptr) { this->m_ConVar = ConVar_Invalid(type); // technically this From 8774df664dd8cc40455c76272fd892ef761cec79 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sat, 7 Oct 2023 23:01:06 +0200 Subject: [PATCH 09/48] remove debug --- tier1/convar.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 672366b8d..73bd198e3 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -125,8 +125,6 @@ void AddCommand( ConCommandCreation_t& cmd ) void RegisterConVar( ConVarCreation_t& cvar ) { - ConMsg( "Registering cvar %s\n", cvar.name ); - g_pCVar->RegisterConVar( cvar, s_nCVarFlag, cvar.refHandle, cvar.refConVar ); if (!cvar.refHandle->IsValid()) { @@ -219,8 +217,6 @@ void SetupConVar( ConVarCreation_t& cvar ) } s_pConVarRegList->Add( cvar ); - - ConMsg( "Setting up cvar %s\n", cvar.name ); } //----------------------------------------------------------------------------- From 79e18af8384f18358aa023615fc13f5ec4edcd64 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 00:02:06 +0200 Subject: [PATCH 10/48] reorganise the headers, and add templated getter/setters --- public/icvar.h | 124 ++++++++++++++++++++++- public/tier1/convar.h | 225 ++++++++++++------------------------------ tier1/convar.cpp | 27 ++--- 3 files changed, 199 insertions(+), 177 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index 62902501c..6fb1dad21 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -11,19 +11,135 @@ #endif #include "appframework/IAppSystem.h" -#include "tier1/convar.h" #include "tier1/utlvector.h" #include "tier0/memalloc.h" +#include class ConCommand; -class Color; +class CCommand; +class CCommandContext; +class ICVarListenerCallbacks; class IConVarListener; -class IConVar; -class CConVarDetail; +class ConVar; +struct ConVarCreation_t; +struct ConCommandCreation_t; struct ConVarSnapshot_t; union CVValue_t; class KeyValues; +struct CSplitScreenSlot +{ + CSplitScreenSlot( int index ) + { + m_Data = index; + } + + int Get() const + { + return m_Data; + } + + int m_Data; +}; + +//----------------------------------------------------------------------------- +// Called when a ConVar changes value +//----------------------------------------------------------------------------- +typedef void(*FnChangeCallbackGlobal_t)(ConVar* cvar, CSplitScreenSlot nSlot, const char *pNewValue, const char *pOldValue); +using FnChangeCallback_t = void(*)(ConVar* cvar, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue); +static_assert(sizeof(FnChangeCallback_t) == 0x8, "Wrong size for FnChangeCallback_t"); + +//----------------------------------------------------------------------------- +// Purpose: Replaces the ConVar* +//----------------------------------------------------------------------------- +class ConVarHandle +{ +public: + ConVarHandle( uint16_t convarIndex = -1, uint16_t unk = -1, uint32_t handle = -1) : + m_convarIndex(convarIndex), + m_unknown1(unk), + m_handleIndex(handle) + {} + + bool IsValid( ) const; + void Invalidate( ); + + uint16_t GetConVarIndex() const { return m_convarIndex; } + uint32_t GetIndex() const { return m_handleIndex; } + +private: + uint16_t m_convarIndex; + uint16_t m_unknown1; + uint32_t m_handleIndex; +}; +static_assert(sizeof(ConVarHandle) == 0x8, "ConVarHandle is of the wrong size!"); + +static const ConVarHandle INVALID_CONVAR_HANDLE = ConVarHandle(); + +inline bool ConVarHandle::IsValid() const +{ + return m_convarIndex != 0xFFFF; +} + +inline void ConVarHandle::Invalidate() +{ + m_convarIndex = 0xFFFF; + m_unknown1 = 0xFFFF; + m_handleIndex = 0x0; +} + +//----------------------------------------------------------------------------- +// Purpose: Internal structure of ConVar objects +//----------------------------------------------------------------------------- +enum EConVarType : short +{ + EConVarType_Invalid = -1, + EConVarType_Bool, + EConVarType_Int16, + EConVarType_UInt16, + EConVarType_Int32, + EConVarType_UInt32, + EConVarType_Int64, + EConVarType_UInt64, + EConVarType_Float32, + EConVarType_Float64, + EConVarType_String, + EConVarType_Color, + EConVarType_Vector2, + EConVarType_Vector3, + EConVarType_Vector4, + EConVarType_Qangle, + EConVarType_MAX +}; + +abstract_class IConVar +{ +friend class ConVar; +protected: + const char* m_pszName; + CVValue_t* m_cvvDefaultValue; + CVValue_t* m_cvvMinValue; + CVValue_t* m_cvvMaxValue; + const char* m_pszHelpString; + EConVarType m_eVarType; + + // This gets copied from the ConVarDesc_t on creation + short unk1; + + unsigned int timesChanged; + int64 m_flags; + unsigned int callback_index; + + // Used when setting default, max, min values from the ConVarDesc_t + // although that's not the only place of usage + // flags seems to be: + // (1 << 0) Skip setting value to split screen slots and also something keyvalues related + // (1 << 1) Skip setting default value + // (1 << 2) Skip setting min/max values + int allocation_flag_of_some_sort; + + CVValue_t* m_value[4]; +}; //----------------------------------------------------------------------------- // Purpose: DLL interface to ConVars/ConCommands diff --git a/public/tier1/convar.h b/public/tier1/convar.h index c8844ea74..7b25d33d4 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -21,6 +21,7 @@ #include "tier1/utlstring.h" #include "tier1/characterset.h" #include "Color.h" +#include "cvar.h" #include "mathlib/vector4d.h" #include "playerslot.h" @@ -93,42 +94,6 @@ inline int64_t CVarCreationBase_t::GetFlags( void ) const return this->flags; } -class ConVarHandle -{ -public: - ConVarHandle( uint16_t convarIndex = -1, uint16_t unk = -1, uint32_t handle = -1) : - m_convarIndex(convarIndex), - m_unknown1(unk), - m_handleIndex(handle) - {} - - bool IsValid( ) const; - void Invalidate( ); - - uint16_t GetConVarIndex() const { return m_convarIndex; } - uint32_t GetIndex() const { return m_handleIndex; } - -private: - uint16_t m_convarIndex; - uint16_t m_unknown1; - uint32_t m_handleIndex; -}; -static_assert(sizeof(ConVarHandle) == 0x8, "ConVarHandle is of the wrong size!"); - -static const ConVarHandle INVALID_CONVAR_HANDLE = ConVarHandle(); - -inline bool ConVarHandle::IsValid() const -{ - return m_convarIndex != 0xFFFF; -} - -inline void ConVarHandle::Invalidate() -{ - m_convarIndex = 0xFFFF; - m_unknown1 = 0xFFFF; - m_handleIndex = 0x0; -} - enum CommandTarget_t { CT_NO_TARGET = -1, @@ -159,21 +124,6 @@ class CCommandContext CPlayerSlot m_nPlayerSlot; }; -struct CSplitScreenSlot -{ - CSplitScreenSlot( int index ) - { - m_Data = index; - } - - int Get() const - { - return m_Data; - } - - int m_Data; -}; - //----------------------------------------------------------------------------- // ConVar flags //----------------------------------------------------------------------------- @@ -226,27 +176,6 @@ struct CSplitScreenSlot #define FCVAR_EXECUTE_PER_TICK (1<<29) -enum EConVarType : short -{ - EConVarType_Invalid = -1, - EConVarType_Bool, - EConVarType_Int16, - EConVarType_UInt16, - EConVarType_Int32, - EConVarType_UInt32, - EConVarType_Int64, - EConVarType_UInt64, - EConVarType_Float32, - EConVarType_Float64, - EConVarType_String, - EConVarType_Color, - EConVarType_Vector2, - EConVarType_Vector3, - EConVarType_Vector4, - EConVarType_Qangle, - EConVarType_MAX -}; - union CVValue_t { CVValue_t() { memset(this, 0, sizeof(*this)); } @@ -256,6 +185,22 @@ union CVValue_t template FORCEINLINE_CVAR CVValue_t& operator=(T other); + FORCEINLINE_CVAR operator bool() { return m_bValue; } + FORCEINLINE_CVAR operator int16_t() { return m_i16Value; } + FORCEINLINE_CVAR operator uint16_t() { return m_u16Value; } + FORCEINLINE_CVAR operator int32_t() { return m_i32Value; } + FORCEINLINE_CVAR operator uint32_t() { return m_u32Value; } + FORCEINLINE_CVAR operator int64_t() { return m_i64Value; } + FORCEINLINE_CVAR operator uint64_t() { return m_u64Value; } + FORCEINLINE_CVAR operator float() { return m_flValue; } + FORCEINLINE_CVAR operator double() { return m_dbValue; } + FORCEINLINE_CVAR operator const char*() { return m_szValue; } + FORCEINLINE_CVAR operator const Color&() { return m_clrValue; } + FORCEINLINE_CVAR operator const Vector2D&() { return m_vec2Value; } + FORCEINLINE_CVAR operator const Vector&() { return m_vec3Value; } + FORCEINLINE_CVAR operator const Vector4D&() { return m_vec4Value; } + FORCEINLINE_CVAR operator const QAngle&() { return m_angValue; } + bool m_bValue; int16_t m_i16Value; uint16_t m_u16Value; @@ -275,15 +220,15 @@ union CVValue_t static_assert(sizeof(float) == sizeof(int32_t), "Wrong float type size for ConVar!"); static_assert(sizeof(double) == sizeof(int64_t), "Wrong double type size for ConVar!"); -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( bool other ) { m_bValue = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( int16_t other ) { m_i16Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( uint16_t other ) { m_u16Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( int32_t other ) { m_i32Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( uint32_t other ) { m_u32Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( int64_t other ) { m_i64Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( uint64_t other ) { m_u64Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( float other ) { m_flValue = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( double other ) { m_dbValue = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const bool other ) { m_bValue = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const int16_t other ) { m_i16Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const uint16_t other ) { m_u16Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const int32_t other ) { m_i32Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const uint32_t other ) { m_u32Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const int64_t other ) { m_i64Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const uint64_t other ) { m_u64Value = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const float other ) { m_flValue = other; return *this; } +template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const double other ) { m_dbValue = other; return *this; } template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const char* other ) { m_szValue = other; return *this; } template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const Color& other ) { m_clrValue = other; return *this; } template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const Vector2D& other ) { m_vec2Value = other; return *this; } @@ -291,13 +236,6 @@ template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( cons template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const Vector4D& other ) { m_vec4Value = other; return *this; } template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const QAngle& other ) { m_angValue = other; return *this; } -//----------------------------------------------------------------------------- -// Called when a ConVar changes value -//----------------------------------------------------------------------------- -typedef void(*FnChangeCallbackGlobal_t)(ConVar* cvar, CSplitScreenSlot nSlot, const char *pNewValue, const char *pOldValue); -using FnChangeCallback_t = void(*)(ConVar* cvar, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue); -static_assert(sizeof(FnChangeCallback_t) == 0x8, "Wrong size for FnChangeCallback_t"); - //----------------------------------------------------------------------------- // ConVar & ConCommand creation listener callbacks //----------------------------------------------------------------------------- @@ -562,13 +500,35 @@ class ConVar public: // sub_6A66B0 template - ConVar(const char* name, int32_t flags, const char* description, T value) + ConVar(const char* name, int32_t flags, const char* description, T value, FnChangeCallback_t cb = nullptr) + { + this->Init(INVALID_CONVAR_HANDLE, TranslateType()); + + ConVarSetup_t setup; + setup.has_default = true; + setup.default_value = value; + setup.type = TranslateType(); + setup.callback = cb; + + this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); + } + + template + ConVar(const char* name, int32_t flags, const char* description, T value, bool min, T minValue, bool max, T maxValue, FnChangeCallback_t cb = nullptr) { this->Init(INVALID_CONVAR_HANDLE, TranslateType()); ConVarSetup_t setup; setup.has_default = true; setup.default_value = value; + + setup.has_min = min; + setup.min_value = minValue; + + setup.has_max = max; + setup.max_value = maxValue; + + setup.callback = cb; setup.type = TranslateType(); this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); @@ -576,6 +536,19 @@ class ConVar ~ConVar(); + template + void Set(const T value) + { + *m_ConVar->m_cvvDefaultValue = value; + } + + template + T Get() + { + CVValue_t& val = *m_ConVar->m_cvvDefaultValue; + return val; + } + private: template static constexpr EConVarType TranslateType(); @@ -607,82 +580,12 @@ template<> constexpr EConVarType ConVar::TranslateType( void ) { return template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Vector4; } template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Qangle; } +//----------------------------------------------------------------------------- + // sub_10B7760 IConVar* ConVar_Invalid(EConVarType type); -class IConVar -{ -friend class ConVarRegList; -friend class ConVar; -public: - IConVar(EConVarType type); -protected: - const char* m_pszName; - CVValue_t* m_cvvDefaultValue; - CVValue_t* m_cvvMinValue; - CVValue_t* m_cvvMaxValue; - const char* m_pszHelpString; - EConVarType m_eVarType; - - // This gets copied from the ConVarDesc_t on creation - short unk1; - - unsigned int timesChanged; - int64 m_flags; - unsigned int callback_index; - - // Used when setting default, max, min values from the ConVarDesc_t - // although that's not the only place of usage - // flags seems to be: - // (1 << 0) Skip setting value to split screen slots and also something keyvalues related - // (1 << 1) Skip setting default value - // (1 << 2) Skip setting min/max values - int allocation_flag_of_some_sort; - - CVValue_t* m_value[4]; -}; - #ifdef CONVAR_WORK_FINISHED -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a float -// Output : float -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR float ConVar::GetFloat( void ) const -{ - return m_pParent->m_Value.m_fValue; -} - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as an int -// Output : int -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR int ConVar::GetInt( void ) const -{ - return m_pParent->m_Value.m_nValue; -} - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a color -// Output : Color -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR Color ConVar::GetColor( void ) const -{ - unsigned char *pColorElement = ((unsigned char *)&m_pParent->m_Value.m_nValue); - return Color( pColorElement[0], pColorElement[1], pColorElement[2], pColorElement[3] ); -} - - -//----------------------------------------------------------------------------- - -template <> FORCEINLINE_CVAR float ConVar::Get( void ) const { return GetFloat(); } -template <> FORCEINLINE_CVAR int ConVar::Get( void ) const { return GetInt(); } -template <> FORCEINLINE_CVAR bool ConVar::Get( void ) const { return GetBool(); } -template <> FORCEINLINE_CVAR const char * ConVar::Get( void ) const { return GetString(); } -template <> FORCEINLINE_CVAR float ConVar::Get( float *p ) const { return ( *p = GetFloat() ); } -template <> FORCEINLINE_CVAR int ConVar::Get( int *p ) const { return ( *p = GetInt() ); } -template <> FORCEINLINE_CVAR bool ConVar::Get( bool *p ) const { return ( *p = GetBool() ); } -template <> FORCEINLINE_CVAR const char * ConVar::Get( char const **p ) const { return ( *p = GetString() ); } - //----------------------------------------------------------------------------- // Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc. // Output : const char * diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 73bd198e3..66ecaf14d 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -534,7 +534,21 @@ void ConCommand::Destroy() // //----------------------------------------------------------------------------- -IConVar invalid_convar[EConVarType_MAX + 1] = { +class CInvalidConvar : public IConVar +{ +public: + CInvalidConvar(EConVarType type) + { + m_pszName = ""; + m_cvvDefaultValue = nullptr; + m_cvvMinValue = nullptr; + m_cvvMaxValue = nullptr; + m_pszHelpString = "This convar is being accessed prior to ConVar_Register being called"; + m_eVarType = type; + } +}; + +CInvalidConvar invalid_convar[EConVarType_MAX + 1] = { EConVarType_Bool, EConVarType_Int16, EConVarType_UInt16, @@ -553,17 +567,6 @@ IConVar invalid_convar[EConVarType_MAX + 1] = { EConVarType_Invalid // EConVarType_MAX }; -// Strictly for invalid convar creation -IConVar::IConVar(EConVarType type) : - m_pszName(""), - m_cvvDefaultValue(nullptr), - m_cvvMinValue(nullptr), - m_cvvMaxValue(nullptr), - m_pszHelpString("This convar is being accessed prior to ConVar_Register being called"), - m_eVarType(type) -{ -} - IConVar* ConVar_Invalid(EConVarType type) { if (type == EConVarType_Invalid) From 780666ca56f802136714caf7e01803fe7b5c10be Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 00:38:26 +0200 Subject: [PATCH 11/48] finish templating job --- public/icvar.h | 90 ++++++++- public/tier1/convar.h | 201 +++----------------- tier1/convar.cpp | 426 ------------------------------------------ 3 files changed, 112 insertions(+), 605 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index 6fb1dad21..bf2b43d24 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -13,6 +13,7 @@ #include "appframework/IAppSystem.h" #include "tier1/utlvector.h" #include "tier0/memalloc.h" +#include "mathlib/vector4d.h" #include class ConCommand; @@ -24,9 +25,68 @@ class ConVar; struct ConVarCreation_t; struct ConCommandCreation_t; struct ConVarSnapshot_t; -union CVValue_t; class KeyValues; +union CVValue_t +{ + CVValue_t() { memset(this, 0, sizeof(*this)); } + CVValue_t(CVValue_t const& cp) { memcpy(this, &cp, sizeof(*this)); }; + CVValue_t& operator=(CVValue_t other) { memcpy(this, &other, sizeof(*this)); return *this; } + + template + inline CVValue_t& operator=(T other); + + inline operator bool() const { return m_bValue; } + inline operator int16_t() const { return m_i16Value; } + inline operator uint16_t() const { return m_u16Value; } + inline operator int32_t() const { return m_i32Value; } + inline operator uint32_t() const { return m_u32Value; } + inline operator int64_t() const { return m_i64Value; } + inline operator uint64_t() const { return m_u64Value; } + inline operator float() const { return m_flValue; } + inline operator double() const { return m_dbValue; } + inline operator const char*() const { return m_szValue; } + inline operator const Color&() const { return m_clrValue; } + inline operator const Vector2D&() const { return m_vec2Value; } + inline operator const Vector&() const { return m_vec3Value; } + inline operator const Vector4D&() const { return m_vec4Value; } + inline operator const QAngle&() const { return m_angValue; } + + bool m_bValue; + int16_t m_i16Value; + uint16_t m_u16Value; + int32_t m_i32Value; + uint32_t m_u32Value; + int64_t m_i64Value; + uint64_t m_u64Value; + float m_flValue; + double m_dbValue; + const char* m_szValue; + Color m_clrValue; + Vector2D m_vec2Value; + Vector m_vec3Value; + Vector4D m_vec4Value; + QAngle m_angValue; +}; +static_assert(sizeof(float) == sizeof(int32_t), "Wrong float type size for ConVar!"); +static_assert(sizeof(double) == sizeof(int64_t), "Wrong double type size for ConVar!"); + +template<> inline CVValue_t& CVValue_t::operator=( const bool other ) { m_bValue = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const int16_t other ) { m_i16Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const uint16_t other ) { m_u16Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const int32_t other ) { m_i32Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const uint32_t other ) { m_u32Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const int64_t other ) { m_i64Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const uint64_t other ) { m_u64Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const float other ) { m_flValue = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const double other ) { m_dbValue = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const char* other ) { m_szValue = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const Color& other ) { m_clrValue = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const Vector2D& other ) { m_vec2Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const Vector& other ) { m_vec3Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const Vector4D& other ) { m_vec4Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const QAngle& other ) { m_angValue = other; return *this; } + struct CSplitScreenSlot { CSplitScreenSlot( int index ) @@ -115,6 +175,32 @@ enum EConVarType : short abstract_class IConVar { friend class ConVar; + inline const char* GetName( ) const { return m_pszName; } + inline const char* GetDescription( ) const { return m_pszHelpString; } + inline EConVarType GetType( ) const { return m_eVarType; } + + inline CVValue_t* GetDefaultValue( ) const { return m_cvvDefaultValue; } + inline CVValue_t* GetMinValue( ) const { return m_cvvMinValue; } + inline CVValue_t* GetMaxValue( ) const { return m_cvvMaxValue; } + + template + inline void SetDefaultValue(const T& value) { m_cvvDefaultValue = value; } + template + inline void SetMinValue(const T& value) { m_cvvMinValue = value; } + template + inline void SetMaxValue(const T& value) { m_cvvMaxValue = value; } + + template + inline const T GetValue( int index = 0 ) const { return m_value[index]; } + inline const CVValue_t& GetValue( int index = 0 ) const { return m_value[index]; } + template + inline void SetValue(const T& value, int index = 0) { m_value[index] = value; } + + inline bool IsFlagSet( int64_t flag ) const { return ( flag & m_flags ) ? true : false; } + inline void AddFlags( int64_t flags ) { m_flags |= flags; } + inline void RemoveFlags( int64_t flags ) { m_flags &= ~flags; } + inline int64_t GetFlags( void ) const { return m_flags; } + protected: const char* m_pszName; CVValue_t* m_cvvDefaultValue; @@ -138,7 +224,7 @@ friend class ConVar; // (1 << 2) Skip setting min/max values int allocation_flag_of_some_sort; - CVValue_t* m_value[4]; + CVValue_t m_value[4]; }; //----------------------------------------------------------------------------- diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 7b25d33d4..cae56db03 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -22,7 +22,6 @@ #include "tier1/characterset.h" #include "Color.h" #include "cvar.h" -#include "mathlib/vector4d.h" #include "playerslot.h" #include @@ -176,66 +175,6 @@ class CCommandContext #define FCVAR_EXECUTE_PER_TICK (1<<29) -union CVValue_t -{ - CVValue_t() { memset(this, 0, sizeof(*this)); } - CVValue_t(CVValue_t const& cp) { memcpy(this, &cp, sizeof(*this)); }; - CVValue_t& operator=(CVValue_t other) { memcpy(this, &other, sizeof(*this)); return *this; } - - template - FORCEINLINE_CVAR CVValue_t& operator=(T other); - - FORCEINLINE_CVAR operator bool() { return m_bValue; } - FORCEINLINE_CVAR operator int16_t() { return m_i16Value; } - FORCEINLINE_CVAR operator uint16_t() { return m_u16Value; } - FORCEINLINE_CVAR operator int32_t() { return m_i32Value; } - FORCEINLINE_CVAR operator uint32_t() { return m_u32Value; } - FORCEINLINE_CVAR operator int64_t() { return m_i64Value; } - FORCEINLINE_CVAR operator uint64_t() { return m_u64Value; } - FORCEINLINE_CVAR operator float() { return m_flValue; } - FORCEINLINE_CVAR operator double() { return m_dbValue; } - FORCEINLINE_CVAR operator const char*() { return m_szValue; } - FORCEINLINE_CVAR operator const Color&() { return m_clrValue; } - FORCEINLINE_CVAR operator const Vector2D&() { return m_vec2Value; } - FORCEINLINE_CVAR operator const Vector&() { return m_vec3Value; } - FORCEINLINE_CVAR operator const Vector4D&() { return m_vec4Value; } - FORCEINLINE_CVAR operator const QAngle&() { return m_angValue; } - - bool m_bValue; - int16_t m_i16Value; - uint16_t m_u16Value; - int32_t m_i32Value; - uint32_t m_u32Value; - int64_t m_i64Value; - uint64_t m_u64Value; - float m_flValue; - double m_dbValue; - const char* m_szValue; - Color m_clrValue; - Vector2D m_vec2Value; - Vector m_vec3Value; - Vector4D m_vec4Value; - QAngle m_angValue; -}; -static_assert(sizeof(float) == sizeof(int32_t), "Wrong float type size for ConVar!"); -static_assert(sizeof(double) == sizeof(int64_t), "Wrong double type size for ConVar!"); - -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const bool other ) { m_bValue = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const int16_t other ) { m_i16Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const uint16_t other ) { m_u16Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const int32_t other ) { m_i32Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const uint32_t other ) { m_u32Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const int64_t other ) { m_i64Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const uint64_t other ) { m_u64Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const float other ) { m_flValue = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const double other ) { m_dbValue = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const char* other ) { m_szValue = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const Color& other ) { m_clrValue = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const Vector2D& other ) { m_vec2Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const Vector& other ) { m_vec3Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const Vector4D& other ) { m_vec4Value = other; return *this; } -template<> FORCEINLINE_CVAR CVValue_t& CVValue_t::operator=( const QAngle& other ) { m_angValue = other; return *this; } - //----------------------------------------------------------------------------- // ConVar & ConCommand creation listener callbacks //----------------------------------------------------------------------------- @@ -536,18 +475,31 @@ class ConVar ~ConVar(); - template - void Set(const T value) - { - *m_ConVar->m_cvvDefaultValue = value; - } + inline const char* GetName( ) const { return m_ConVar->GetName( ); } + inline const char* GetDescription( ) const { return m_ConVar->GetDescription( ); } + inline EConVarType GetType( ) const { return m_ConVar->GetType( ); } + + inline CVValue_t* GetDefaultValue( ) const { return m_ConVar->GetDefaultValue( ); } + inline CVValue_t* GetMinValue( ) const { return m_ConVar->GetMinValue( ); } + inline CVValue_t* GetMaxValue( ) const { return m_ConVar->GetMaxValue( ); } template - T Get() - { - CVValue_t& val = *m_ConVar->m_cvvDefaultValue; - return val; - } + inline void SetDefaultValue(const T& value) { m_ConVar->SetDefaultValue( value ); } + template + inline void SetMinValue(const T& value) { m_ConVar->SetMinValue( value ); } + template + inline void SetMaxValue(const T& value) { m_ConVar->SetMaxValue( value ); } + + template + inline const T GetValue( int index = 0 ) const { return m_ConVar->GetValue( index ); } + inline const CVValue_t& GetValue( int index = 0 ) const { return m_ConVar->GetValue( index ); } + template + inline void SetValue(const T& value, int index = 0) { m_ConVar->SetValue( value, index ); } + + inline bool IsFlagSet( int64_t flag ) const { return m_ConVar->IsFlagSet( flag ); } + inline void AddFlags( int64_t flags ) { m_ConVar->AddFlags( flags ); } + inline void RemoveFlags( int64_t flags ) { return m_ConVar->RemoveFlags( flags ); } + inline int64_t GetFlags( void ) const { return m_ConVar->GetFlags( ); } private: template @@ -558,7 +510,7 @@ class ConVar // sub_10B7C70 void Register(const char* name, int32_t flags, const char* description, const ConVarSetup_t& obj); -public: + // High-speed method to read convar data ConVarHandle m_Handle; IConVar* m_ConVar; @@ -586,19 +538,6 @@ template<> constexpr EConVarType ConVar::TranslateType( void ) { return IConVar* ConVar_Invalid(EConVarType type); #ifdef CONVAR_WORK_FINISHED -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc. -// Output : const char * -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR const char *ConVar::GetString( void ) const -{ - if ( m_nFlags & FCVAR_NEVER_AS_STRING ) - return "FCVAR_NEVER_AS_STRING"; - - char const *str = m_pParent->m_Value.m_pszString; - return str ? str : ""; -} - class CSplitScreenAddedConVar : public ConVar { typedef ConVar BaseClass; @@ -663,98 +602,6 @@ FORCEINLINE_CVAR int CSplitScreenAddedConVar::GetSplitScreenPlayerSlot() const return m_nSplitScreenSlot; } -//----------------------------------------------------------------------------- -// Did we find an existing convar of that name? -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR bool ConVarRefAbstract::IsFlagSet( int64 nFlags ) const -{ - return ( m_pConVar->IsFlagSet( nFlags ) != 0 ); -} - -FORCEINLINE_CVAR IConVar *ConVarRefAbstract::GetLinkedConVar() -{ - return m_pConVar; -} - -FORCEINLINE_CVAR const char *ConVarRefAbstract::GetName() const -{ - return m_pConVar->GetName(); -} - -FORCEINLINE_CVAR const char *ConVarRefAbstract::GetBaseName() const -{ - return m_pConVar->GetBaseName(); -} - -FORCEINLINE_CVAR int ConVarRefAbstract::GetSplitScreenPlayerSlot() const -{ - return m_pConVar->GetSplitScreenPlayerSlot(); -} - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a float -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR float ConVarRefAbstract::GetFloat( void ) const -{ - return m_pConVarState->m_Value.m_fValue; -} - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as an int -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR int ConVarRefAbstract::GetInt( void ) const -{ - return m_pConVarState->m_Value.m_nValue; -} - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a color -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR Color ConVarRefAbstract::GetColor( void ) const -{ - return m_pConVarState->GetColor(); -} - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc. -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR const char *ConVarRefAbstract::GetString( void ) const -{ - Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) ); - return m_pConVarState->m_Value.m_pszString; -} - - -FORCEINLINE_CVAR void ConVarRefAbstract::SetValue( const char *pValue ) -{ - m_pConVar->SetValue( pValue ); -} - -FORCEINLINE_CVAR void ConVarRefAbstract::SetValue( float flValue ) -{ - m_pConVar->SetValue( flValue ); -} - -FORCEINLINE_CVAR void ConVarRefAbstract::SetValue( int nValue ) -{ - m_pConVar->SetValue( nValue ); -} - -FORCEINLINE_CVAR void ConVarRefAbstract::SetValue( Color value ) -{ - m_pConVar->SetValue( value ); -} - -FORCEINLINE_CVAR void ConVarRefAbstract::SetValue( bool bValue ) -{ - m_pConVar->SetValue( bValue ? 1 : 0 ); -} - -FORCEINLINE_CVAR const char *ConVarRefAbstract::GetDefault() const -{ - return m_pConVarState->m_pszDefaultValue; -} - #if 0 //----------------------------------------------------------------------------- // Helper for referencing splitscreen convars (i.e., "name" and "name2") diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 66ecaf14d..a1d2d0f3d 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -630,432 +630,6 @@ void ConVar::Register(const char* name, int32_t flags, const char* description, #ifdef CONVAR_WORK_FINISHED -//----------------------------------------------------------------------------- -// Various constructors -//----------------------------------------------------------------------------- -ConVar::ConVar( const char *pName, const char *pDefaultValue, int64 flags /* = 0 */ ) -{ - Create( pName, pDefaultValue, flags ); -} - -ConVar::ConVar( const char *pName, const char *pDefaultValue, int64 flags, const char *pHelpString ) -{ - Create( pName, pDefaultValue, flags, pHelpString ); -} - -ConVar::ConVar( const char *pName, const char *pDefaultValue, int64 flags, const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) -{ - Create( pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax ); -} - -ConVar::ConVar( const char *pName, const char *pDefaultValue, int64 flags, const char *pHelpString, FnChangeCallback_t callback ) -{ - Create( pName, pDefaultValue, flags, pHelpString, false, 0.0, false, 0.0, callback ); -} - -ConVar::ConVar( const char *pName, const char *pDefaultValue, int64 flags, const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t callback ) -{ - Create( pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax, callback ); -} - - -//----------------------------------------------------------------------------- -// Destructor -//----------------------------------------------------------------------------- -ConVar::~ConVar( void ) -{ - if ( m_Value.m_pszString ) - { - delete[] m_Value.m_pszString; - m_Value.m_pszString = NULL; - } -} - - -//----------------------------------------------------------------------------- -// Install a change callback (there shouldn't already be one....) -//----------------------------------------------------------------------------- -void ConVar::InstallChangeCallback( FnChangeCallback_t callback, bool bInvoke ) -{ - if (callback) - { - if (m_fnChangeCallbacks.Find(callback) != -1) - { - m_fnChangeCallbacks.AddToTail(callback); - if (bInvoke) - callback(this, m_Value.m_pszString, m_Value.m_fValue); - } - else - { - Warning("InstallChangeCallback ignoring duplicate change callback!!!\n"); - } - } - else - { - Warning("InstallChangeCallback called with NULL callback, ignoring!!!\n"); - } -} - -bool ConVar::IsFlagSet( int64 flag ) const -{ - return ( flag & m_pParent->m_nFlags ) ? true : false; -} - -const char *ConVar::GetHelpText( void ) const -{ - return m_pParent->m_pszHelpString; -} - -void ConVar::AddFlags( int64 flags ) -{ - m_pParent->m_nFlags |= flags; - -#ifdef ALLOW_DEVELOPMENT_CVARS - m_pParent->m_nFlags &= ~FCVAR_DEVELOPMENTONLY; -#endif -} - -int64 ConVar::GetFlags( void ) const -{ - return m_pParent->m_nFlags; -} - -const char *ConVar::GetName( void ) const -{ - return m_pParent->m_pszName; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -//----------------------------------------------------------------------------- -void ConVar::Init() -{ - BaseClass::Init(); -} - -const char *ConVar::GetBaseName( void ) const -{ - return m_pParent->m_pszName; -} - -int ConVar::GetSplitScreenPlayerSlot( void ) const -{ - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *value - -//----------------------------------------------------------------------------- -void ConVar::InternalSetValue( const char *value ) -{ - float fNewValue; - char tempVal[ 32 ]; - char *val; - - Assert(m_pParent == this); // Only valid for root convars. - - float flOldValue = m_Value.m_fValue; - - val = (char *)value; - fNewValue = ( float )atof( value ); - - if ( ClampValue( fNewValue ) ) - { - Q_snprintf( tempVal,sizeof(tempVal), "%f", fNewValue ); - val = tempVal; - } - - // Redetermine value - m_Value.m_fValue = fNewValue; - m_Value.m_nValue = ( int )( fNewValue ); - - if ( !( m_nFlags & FCVAR_NEVER_AS_STRING ) ) - { - ChangeStringValue( val, flOldValue ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tempVal - -//----------------------------------------------------------------------------- -void ConVar::ChangeStringValue( const char *tempVal, float flOldValue ) -{ - Assert( !( m_nFlags & FCVAR_NEVER_AS_STRING ) ); - - char* pszOldValue = (char*)stackalloc( m_Value.m_StringLength ); - memcpy( pszOldValue, m_Value.m_pszString, m_Value.m_StringLength ); - - int len = Q_strlen(tempVal) + 1; - - if ( len > m_Value.m_StringLength) - { - if (m_Value.m_pszString) - { - delete[] m_Value.m_pszString; - } - - m_Value.m_pszString = new char[len]; - m_Value.m_StringLength = len; - } - - memcpy( m_Value.m_pszString, tempVal, len ); - - // Invoke any necessary callback function - for (int i = 0; i < m_fnChangeCallbacks.Count(); i++) - { - m_fnChangeCallbacks[i]( this, pszOldValue, flOldValue ); - } - - if (g_pCVar) - g_pCVar->CallGlobalChangeCallbacks( this, pszOldValue, flOldValue ); -} - -//----------------------------------------------------------------------------- -// Purpose: Check whether to clamp and then perform clamp -// Input : value - -// Output : Returns true if value changed -//----------------------------------------------------------------------------- -bool ConVar::ClampValue( float& value ) -{ - if ( m_bHasMin && ( value < m_fMinVal ) ) - { - value = m_fMinVal; - return true; - } - - if ( m_bHasMax && ( value > m_fMaxVal ) ) - { - value = m_fMaxVal; - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *value - -//----------------------------------------------------------------------------- -void ConVar::InternalSetFloatValue( float fNewValue ) -{ - if ( fNewValue == m_Value.m_fValue ) - return; - - Assert( m_pParent == this ); // Only valid for root convars. - - // Check bounds - ClampValue( fNewValue ); - - // Redetermine value - float flOldValue = m_Value.m_fValue; - m_Value.m_fValue = fNewValue; - m_Value.m_nValue = ( int )fNewValue; - - if ( !( m_nFlags & FCVAR_NEVER_AS_STRING ) ) - { - char tempVal[ 32 ]; - Q_snprintf( tempVal, sizeof( tempVal), "%f", m_Value.m_fValue ); - ChangeStringValue( tempVal, flOldValue ); - } - else - { - Assert( m_fnChangeCallbacks.Count() == 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *value - -//----------------------------------------------------------------------------- -void ConVar::InternalSetIntValue( int nValue ) -{ - if ( nValue == m_Value.m_nValue ) - return; - - Assert( m_pParent == this ); // Only valid for root convars. - - float fValue = (float)nValue; - if ( ClampValue( fValue ) ) - { - nValue = ( int )( fValue ); - } - - // Redetermine value - float flOldValue = m_Value.m_fValue; - m_Value.m_fValue = fValue; - m_Value.m_nValue = nValue; - - if ( !( m_nFlags & FCVAR_NEVER_AS_STRING ) ) - { - char tempVal[ 32 ]; - Q_snprintf( tempVal, sizeof( tempVal ), "%d", m_Value.m_nValue ); - ChangeStringValue( tempVal, flOldValue ); - } - else - { - Assert( m_fnChangeCallbacks.Count() == 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *value - -//----------------------------------------------------------------------------- -void ConVar::InternalSetColorValue( Color cValue ) -{ - int color = cValue.GetRawColor(); - InternalSetIntValue( color ); -} - -//----------------------------------------------------------------------------- -// Purpose: Private creation -//----------------------------------------------------------------------------- -void ConVar::Create( const char *pName, const char *pDefaultValue, int64 flags /*= 0*/, - const char *pHelpString /*= NULL*/, bool bMin /*= false*/, float fMin /*= 0.0*/, - bool bMax /*= false*/, float fMax /*= false*/, FnChangeCallback_t callback /*= NULL*/ ) -{ - static const char *empty_string = ""; - - m_pParent = this; - - // Name should be static data - m_pszDefaultValue = pDefaultValue ? pDefaultValue : empty_string; - Assert( m_pszDefaultValue ); - - m_Value.m_StringLength = strlen( m_pszDefaultValue ) + 1; - m_Value.m_pszString = new char[m_Value.m_StringLength]; - memcpy( m_Value.m_pszString, m_pszDefaultValue, m_Value.m_StringLength ); - - m_bHasMin = bMin; - m_fMinVal = fMin; - m_bHasMax = bMax; - m_fMaxVal = fMax; - - if (callback) - m_fnChangeCallbacks.AddToTail(callback); - - m_Value.m_fValue = ( float )atof( m_Value.m_pszString ); - - // Bounds Check, should never happen, if it does, no big deal - if ( m_bHasMin && ( m_Value.m_fValue < m_fMinVal ) ) - { - Assert( 0 ); - } - - if ( m_bHasMax && ( m_Value.m_fValue > m_fMaxVal ) ) - { - Assert( 0 ); - } - - m_Value.m_nValue = ( int )m_Value.m_fValue; - - BaseClass::Create( pName, pHelpString, flags ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *value - -//----------------------------------------------------------------------------- -void ConVar::SetValue(const char *value) -{ - ConVar *var = ( ConVar * )m_pParent; - var->InternalSetValue( value ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : value - -//----------------------------------------------------------------------------- -void ConVar::SetValue( float value ) -{ - ConVar *var = ( ConVar * )m_pParent; - var->InternalSetFloatValue( value ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : value - -//----------------------------------------------------------------------------- -void ConVar::SetValue( int value ) -{ - ConVar *var = ( ConVar * )m_pParent; - var->InternalSetIntValue( value ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : value - -//----------------------------------------------------------------------------- -void ConVar::SetValue( Color value ) -{ - ConVar *var = ( ConVar * )m_pParent; - var->InternalSetColorValue( value ); -} - -//----------------------------------------------------------------------------- -// Purpose: Reset to default value -//----------------------------------------------------------------------------- -void ConVar::Revert( void ) -{ - // Force default value again - ConVar *var = ( ConVar * )m_pParent; - var->SetValue( var->m_pszDefaultValue ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : minVal - -// Output : true if there is a min set -//----------------------------------------------------------------------------- -bool ConVar::GetMin( float& minVal ) const -{ - minVal = m_pParent->m_fMinVal; - return m_pParent->m_bHasMin; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : maxVal - -//----------------------------------------------------------------------------- -bool ConVar::GetMax( float& maxVal ) const -{ - maxVal = m_pParent->m_fMaxVal; - return m_pParent->m_bHasMax; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *ConVar::GetDefault( void ) const -{ - return m_pParent->m_pszDefaultValue; -} - - -//----------------------------------------------------------------------------- -// This version is simply used to make reading convars simpler. -// Writing convars isn't allowed in this mode -//----------------------------------------------------------------------------- -class CEmptyConVar : public ConVar -{ -public: - CEmptyConVar() : ConVar( "", "0" ) {} - // Used for optimal read access - virtual void SetValue( const char *pValue ) {} - virtual void SetValue( float flValue ) {} - virtual void SetValue( int nValue ) {} - virtual void SetValue( Color cValue ) {} - virtual const char *GetName( void ) const { return ""; } - virtual bool IsFlagSet( int nFlags ) const { return false; } -}; - -static CEmptyConVar s_EmptyConVar; - //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- From c3ac08278a313a87de9d2b322c5448c1d1b769df Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 00:40:12 +0200 Subject: [PATCH 12/48] fix copyright symbol --- tier1/convar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tier1/convar.cpp b/tier1/convar.cpp index a1d2d0f3d..1709cfd67 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -1,5 +1,5 @@ -//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // From 0e8b1a5559f021e0f4f8a92e83f0f9955ed4ca97 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 00:43:53 +0200 Subject: [PATCH 13/48] dont break metamod compilation --- public/tier1/convar.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index cae56db03..fc5c8b6ac 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -351,8 +351,14 @@ struct ConCommandCreation_t : CVarCreationBase_t }; static_assert(sizeof(ConCommandCreation_t) == 0x40, "ConCommandCreation_t is of the wrong size!"); -class ConCommandBase {}; // For metamod compatibility only!!!! -class ConCommand : public ConCommandBase +// TO-DO: Remove this... +class ConCommandBase +{ +public: + inline const char* GetName() { return "Please remove the ConCommandBase class..."; } +}; // For metamod compatibility only!!!! + +class ConCommand { public: ConCommand( const char *pName, FnCommandCallback_t callback, From fc063e1642b9e996712fb7e2df4172efc4370fdb Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 02:13:41 +0200 Subject: [PATCH 14/48] template the entire ConVar class --- public/icvar.h | 107 ++++++++++++++++++++++++++---------- public/tier1/convar.h | 122 ++++++++++++++++++++++++++---------------- tier1/convar.cpp | 109 ++++++------------------------------- 3 files changed, 171 insertions(+), 167 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index bf2b43d24..daa4ca1cd 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -16,17 +16,20 @@ #include "mathlib/vector4d.h" #include +class BaseConVar {}; class ConCommand; class CCommand; class CCommandContext; class ICVarListenerCallbacks; class IConVarListener; -class ConVar; struct ConVarCreation_t; struct ConCommandCreation_t; struct ConVarSnapshot_t; class KeyValues; +template +class ConVar; + union CVValue_t { CVValue_t() { memset(this, 0, sizeof(*this)); } @@ -105,8 +108,8 @@ struct CSplitScreenSlot //----------------------------------------------------------------------------- // Called when a ConVar changes value //----------------------------------------------------------------------------- -typedef void(*FnChangeCallbackGlobal_t)(ConVar* cvar, CSplitScreenSlot nSlot, const char *pNewValue, const char *pOldValue); -using FnChangeCallback_t = void(*)(ConVar* cvar, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue); +typedef void(*FnChangeCallbackGlobal_t)(BaseConVar* ref, CSplitScreenSlot nSlot, const char *pNewValue, const char *pOldValue); +using FnChangeCallback_t = void(*)(BaseConVar* ref, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue); static_assert(sizeof(FnChangeCallback_t) == 0x8, "Wrong size for FnChangeCallback_t"); //----------------------------------------------------------------------------- @@ -172,40 +175,70 @@ enum EConVarType : short EConVarType_MAX }; -abstract_class IConVar +template +constexpr EConVarType TranslateConVarType(); + +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Bool; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Int16; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_UInt16; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Int32; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_UInt32; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Int64; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_UInt64; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Float32; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Float64; } +template<> constexpr EConVarType TranslateConVarType( void ){ return EConVarType_String; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Color; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Vector2; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Vector3; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Vector4; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Qangle; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Invalid; } + +template +class IConVar { -friend class ConVar; +public: +friend class ConVar; + IConVar() : + m_pszName(""), + m_Default(nullptr), + m_Min(nullptr), + m_Max(nullptr), + m_pszHelpString("This convar is being accessed prior to ConVar_Register being called"), + m_eVarType(TranslateConVarType()) + { + } + inline const char* GetName( ) const { return m_pszName; } inline const char* GetDescription( ) const { return m_pszHelpString; } inline EConVarType GetType( ) const { return m_eVarType; } - inline CVValue_t* GetDefaultValue( ) const { return m_cvvDefaultValue; } - inline CVValue_t* GetMinValue( ) const { return m_cvvMinValue; } - inline CVValue_t* GetMaxValue( ) const { return m_cvvMaxValue; } + inline const T& GetDefaultValue( ) const { return m_Default->value; } + inline const T& GetMinValue( ) const { return m_Min->value; } + inline const T& GetMaxValue( ) const { return m_Max->value; } - template - inline void SetDefaultValue(const T& value) { m_cvvDefaultValue = value; } - template - inline void SetMinValue(const T& value) { m_cvvMinValue = value; } - template - inline void SetMaxValue(const T& value) { m_cvvMaxValue = value; } + inline void SetDefaultValue(const T& value) { m_Default->value = value; } + inline void SetMinValue(const T& value) { m_Min->value = value; } + inline void SetMaxValue(const T& value) { m_Max->value = value; } - template - inline const T GetValue( int index = 0 ) const { return m_value[index]; } - inline const CVValue_t& GetValue( int index = 0 ) const { return m_value[index]; } - template - inline void SetValue(const T& value, int index = 0) { m_value[index] = value; } + inline const T& GetValue( int index = 0 ) const { return m_value[index].value; } + inline void SetValue(const T& value, int index = 0) { m_value[index].value = value; } inline bool IsFlagSet( int64_t flag ) const { return ( flag & m_flags ) ? true : false; } inline void AddFlags( int64_t flags ) { m_flags |= flags; } inline void RemoveFlags( int64_t flags ) { m_flags &= ~flags; } inline int64_t GetFlags( void ) const { return m_flags; } -protected: const char* m_pszName; - CVValue_t* m_cvvDefaultValue; - CVValue_t* m_cvvMinValue; - CVValue_t* m_cvvMaxValue; + + union TemplatedValue { + int8_t pad[sizeof(CVValue_t)]; + T value = T(); + }; + TemplatedValue* m_Default; + TemplatedValue* m_Min; + TemplatedValue* m_Max; const char* m_pszHelpString; EConVarType m_eVarType; @@ -224,8 +257,10 @@ friend class ConVar; // (1 << 2) Skip setting min/max values int allocation_flag_of_some_sort; - CVValue_t m_value[4]; + TemplatedValue m_value[4]; }; +static_assert(sizeof(IConVar) == 0x80, "IConVar has wrong size!"); +static_assert(sizeof(IConVar) == sizeof(IConVar), "IConVar templated size changes!"); //----------------------------------------------------------------------------- // Purpose: DLL interface to ConVars/ConCommands @@ -247,7 +282,9 @@ abstract_class ICvar : public IAppSystem // Install a global change callback (to be called when any convar changes) virtual void InstallGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; virtual void RemoveGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; - virtual void CallGlobalChangeCallbacks( ConVar* var, CSplitScreenSlot nSlot, const char *pOldString, float flOldValue ) = 0; + virtual void CallGlobalChangeCallbacks( BaseConVar* ref, CSplitScreenSlot nSlot, const char *pOldString, float flOldValue ) = 0; + template + inline void CallGlobalChangeCallbacks( ConVar* var, CSplitScreenSlot nSlot, const char *pOldString, float flOldValue ) { this->CallGlobalChangeCallbacks(var, nSlot, pOldString, flOldValue); } // Reverts cvars which contain a specific flag virtual void RevertFlaggedConVars( int nFlag ) = 0; @@ -272,16 +309,30 @@ abstract_class ICvar : public IAppSystem virtual void unk2() = 0; // Register, unregister vars - virtual void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, IConVar** pCvar ) = 0; + virtual void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, void** pCvar ) = 0; + template + inline void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, IConVar** pCvar ) { this->RegisterConVar(setup, nAdditionalFlags, pCvarRef, (void**)pCvar); } + virtual void UnregisterConVar( ConVarHandle handle ) = 0; - virtual IConVar* GetConVar( ConVarHandle handle ) = 0; + + virtual void* GetConVarNoType( ConVarHandle handle ) = 0; + template + inline IConVar* GetConVar( ConVarHandle handle ) + { + auto convar = (IConVar*)this->GetConVarNoType( handle ); + if (convar && convar->GetType() != TranslateConVarType()) + { + return nullptr; + } + return convar; + } // Register, unregister commands virtual ConVarHandle RegisterConCommand( const ConCommandCreation_t& setup, int64 nAdditionalFlags = 0 ) = 0; virtual void UnregisterConCommand( ConVarHandle handle ) = 0; virtual ConCommand* GetCommand( ConVarHandle handle ) = 0; - virtual void QueueThreadSetValue( ConVar* ref, CSplitScreenSlot nSlot, CVValue_t* value ) = 0; + virtual void QueueThreadSetValue( BaseConVar* ref, CSplitScreenSlot nSlot, CVValue_t* value ) = 0; }; //----------------------------------------------------------------------------- diff --git a/public/tier1/convar.h b/public/tier1/convar.h index fc5c8b6ac..4c80c491e 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -46,10 +46,8 @@ //----------------------------------------------------------------------------- // Forward declarations //----------------------------------------------------------------------------- -class IConVar; class CCommand; class ConCommand; -class ConVar; struct CVarCreationBase_t { @@ -174,14 +172,13 @@ class CCommandContext // Note: IVEngineClient::ClientCmd_Unrestricted can run any client command. #define FCVAR_EXECUTE_PER_TICK (1<<29) - //----------------------------------------------------------------------------- // ConVar & ConCommand creation listener callbacks //----------------------------------------------------------------------------- class ICVarListenerCallbacks { public: - virtual void OnConVarCreated( ConVar* pNewCvar ) = 0; + virtual void OnConVarCreated( BaseConVar* pNewCvar ) = 0; virtual void OnConCommandCreated( ConCommand* pNewCommand ) = 0; }; @@ -430,38 +427,50 @@ struct ConVarCreation_t : CVarCreationBase_t { ConVarSetup_t setup; // 0x18 ConVarHandle* refHandle; // 0x60 - IConVar** refConVar; // 0x68 + void** refConVar; // 0x68 }; static_assert(sizeof(ConVarCreation_t) == 0x70, "ConVarCreation_t wrong size!"); static_assert(sizeof(ConVarCreation_t) % 8 == 0x0, "ConVarCreation_t isn't 8 bytes aligned!"); static_assert(sizeof(CVValue_t) == 0x10, "CVValue_t wrong size!"); +// sub_10B7760 +extern void* invalid_convar[EConVarType_MAX + 1]; + +template +IConVar* ConVar_Invalid() +{ + return (IConVar*)&invalid_convar[TranslateConVarType()]; +} + +void SetupConVar( ConVarCreation_t& cvar ); +void UnRegisterConVar( ConVarHandle& cvar ); +void RegisterConVar( ConVarCreation_t& cvar ); + //----------------------------------------------------------------- // Used to read/write/create? convars (replaces the FindVar method) //----------------------------------------------------------------- -class ConVar +template +class ConVar : public BaseConVar { public: // sub_6A66B0 - template ConVar(const char* name, int32_t flags, const char* description, T value, FnChangeCallback_t cb = nullptr) { - this->Init(INVALID_CONVAR_HANDLE, TranslateType()); + this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); ConVarSetup_t setup; setup.has_default = true; setup.default_value = value; - setup.type = TranslateType(); + setup.type = TranslateConVarType(); setup.callback = cb; this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); } - template ConVar(const char* name, int32_t flags, const char* description, T value, bool min, T minValue, bool max, T maxValue, FnChangeCallback_t cb = nullptr) { - this->Init(INVALID_CONVAR_HANDLE, TranslateType()); + this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); ConVarSetup_t setup; setup.has_default = true; @@ -474,12 +483,15 @@ class ConVar setup.max_value = maxValue; setup.callback = cb; - setup.type = TranslateType(); + setup.type = TranslateConVarType(); this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); } - ~ConVar(); + ~ConVar() + { + UnRegisterConVar(this->m_Handle); + } inline const char* GetName( ) const { return m_ConVar->GetName( ); } inline const char* GetDescription( ) const { return m_ConVar->GetDescription( ); } @@ -489,18 +501,12 @@ class ConVar inline CVValue_t* GetMinValue( ) const { return m_ConVar->GetMinValue( ); } inline CVValue_t* GetMaxValue( ) const { return m_ConVar->GetMaxValue( ); } - template inline void SetDefaultValue(const T& value) { m_ConVar->SetDefaultValue( value ); } - template inline void SetMinValue(const T& value) { m_ConVar->SetMinValue( value ); } - template inline void SetMaxValue(const T& value) { m_ConVar->SetMaxValue( value ); } - template - inline const T GetValue( int index = 0 ) const { return m_ConVar->GetValue( index ); } - inline const CVValue_t& GetValue( int index = 0 ) const { return m_ConVar->GetValue( index ); } - template - inline void SetValue(const T& value, int index = 0) { m_ConVar->SetValue( value, index ); } + inline const T& GetValue( int index = 0 ) const { return m_ConVar->GetValue( index ); } + inline void SetValue(const T& value, int index = 0) { m_ConVar->SetValue( value, index ); } inline bool IsFlagSet( int64_t flag ) const { return m_ConVar->IsFlagSet( flag ); } inline void AddFlags( int64_t flags ) { m_ConVar->AddFlags( flags ); } @@ -508,41 +514,64 @@ class ConVar inline int64_t GetFlags( void ) const { return m_ConVar->GetFlags( ); } private: - template - static constexpr EConVarType TranslateType(); - // sub_10B7BC0 - void Init(ConVarHandle defaultHandle, EConVarType type); + void Init(ConVarHandle defaultHandle, EConVarType type) + { + this->m_Handle.Invalidate(); + this->m_ConVar = nullptr; + + // qword_191A3D8 + if (g_pCVar && (this->m_ConVar = g_pCVar->GetConVar(defaultHandle)) == nullptr) + { + this->m_ConVar = ConVar_Invalid(); + // technically this + //result = *(char ***)(sub_10B7760((unsigned int)a3) + 80); + } + this->m_Handle = defaultHandle; + } // sub_10B7C70 - void Register(const char* name, int32_t flags, const char* description, const ConVarSetup_t& obj); + void Register(const char* name, int32_t flags, const char* description, const ConVarSetup_t& setup) + { + this->m_ConVar = ConVar_Invalid(); + this->m_Handle.Invalidate(); + + if (!CommandLine()->HasParm("-tools") + && (flags & (FCVAR_DEVELOPMENTONLY + |FCVAR_ARCHIVE + |FCVAR_USERINFO + |FCVAR_CHEAT + |FCVAR_RELEASE + |FCVAR_SERVER_CAN_EXECUTE + |FCVAR_CLIENT_CAN_EXECUTE + |FCVAR_CLIENTCMD_CAN_EXECUTE)) == 0) + { + flags |= FCVAR_DEVELOPMENTONLY; + } + + ConVarCreation_t cvar; + + cvar.name = name; + cvar.description = description; + cvar.flags = flags; + + cvar.setup = setup; + + cvar.refHandle = &this->m_Handle; + cvar.refConVar = (void**)&this->m_ConVar; + + SetupConVar(cvar); + } // High-speed method to read convar data ConVarHandle m_Handle; - IConVar* m_ConVar; + IConVar* m_ConVar; }; - -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Bool; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Int16; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_UInt16; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Int32; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_UInt32; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Int64; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_UInt64; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Float32; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Float64; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_String; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Color; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Vector2; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Vector3; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Vector4; } -template<> constexpr EConVarType ConVar::TranslateType( void ) { return EConVarType_Qangle; } +static_assert(sizeof(ConVar) == 0x10, "ConVar is of the wrong size!"); +static_assert(sizeof(ConVar) == sizeof(ConVar), "Templated ConVar size varies!"); //----------------------------------------------------------------------------- -// sub_10B7760 -IConVar* ConVar_Invalid(EConVarType type); - #ifdef CONVAR_WORK_FINISHED class CSplitScreenAddedConVar : public ConVar { @@ -887,5 +916,4 @@ class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, pu \ CCommandMemberInitializer_##_funcname m_##_funcname##_register; \ - #endif // CONVAR_H diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 1709cfd67..188a323e7 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -534,100 +534,25 @@ void ConCommand::Destroy() // //----------------------------------------------------------------------------- -class CInvalidConvar : public IConVar -{ -public: - CInvalidConvar(EConVarType type) - { - m_pszName = ""; - m_cvvDefaultValue = nullptr; - m_cvvMinValue = nullptr; - m_cvvMaxValue = nullptr; - m_pszHelpString = "This convar is being accessed prior to ConVar_Register being called"; - m_eVarType = type; - } +void* invalid_convar[EConVarType_MAX + 1] = { + new IConVar(), + new IConVar(), + new IConVar(), + new IConVar(), + new IConVar(), + new IConVar(), + new IConVar(), + new IConVar(), + new IConVar(), + new IConVar(), + new IConVar(), + new IConVar(), + new IConVar(), + new IConVar(), + new IConVar(), + new IConVar() // EConVarType_MAX }; -CInvalidConvar invalid_convar[EConVarType_MAX + 1] = { - EConVarType_Bool, - EConVarType_Int16, - EConVarType_UInt16, - EConVarType_Int32, - EConVarType_UInt32, - EConVarType_Int64, - EConVarType_UInt64, - EConVarType_Float32, - EConVarType_Float64, - EConVarType_String, - EConVarType_Color, - EConVarType_Vector2, - EConVarType_Vector3, - EConVarType_Vector4, - EConVarType_Qangle, - EConVarType_Invalid // EConVarType_MAX -}; - -IConVar* ConVar_Invalid(EConVarType type) -{ - if (type == EConVarType_Invalid) - { - return &invalid_convar[EConVarType_MAX]; - } - return &invalid_convar[type]; -} - -ConVar::~ConVar() -{ - UnRegisterConVar(this->m_Handle); -} - -void ConVar::Init(ConVarHandle defaultHandle, EConVarType type) -{ - this->m_Handle.Invalidate(); - this->m_ConVar = nullptr; - - // qword_191A3D8 - if (g_pCVar && (this->m_ConVar = g_pCVar->GetConVar(defaultHandle)) == nullptr) - { - this->m_ConVar = ConVar_Invalid(type); - // technically this - //result = *(char ***)(sub_10B7760((unsigned int)a3) + 80); - } - this->m_Handle = defaultHandle; -} - -void ConVar::Register(const char* name, int32_t flags, const char* description, const ConVarSetup_t& setup) -{ - this->m_ConVar = ConVar_Invalid(setup.type); - this->m_Handle.Invalidate(); - - if (!CommandLine()->HasParm("-tools") - && (flags & (FCVAR_DEVELOPMENTONLY - |FCVAR_ARCHIVE - |FCVAR_USERINFO - |FCVAR_CHEAT - |FCVAR_RELEASE - |FCVAR_SERVER_CAN_EXECUTE - |FCVAR_CLIENT_CAN_EXECUTE - |FCVAR_CLIENTCMD_CAN_EXECUTE)) == 0) - { - flags |= FCVAR_DEVELOPMENTONLY; - } - - ConVarCreation_t cvar; - - cvar.name = name; - cvar.description = description; - cvar.flags = flags; - - cvar.setup = setup; - - cvar.refHandle = &this->m_Handle; - cvar.refConVar = &this->m_ConVar; - - SetupConVar(cvar); -} - #ifdef CONVAR_WORK_FINISHED //----------------------------------------------------------------------------- From 61323ebf0271ff617eba4a4acaf1fdcaa14e7e8d Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 02:30:34 +0200 Subject: [PATCH 15/48] template change callback --- public/icvar.h | 2 -- public/tier1/convar.h | 8 +++++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index daa4ca1cd..a40d4d0e5 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -109,8 +109,6 @@ struct CSplitScreenSlot // Called when a ConVar changes value //----------------------------------------------------------------------------- typedef void(*FnChangeCallbackGlobal_t)(BaseConVar* ref, CSplitScreenSlot nSlot, const char *pNewValue, const char *pOldValue); -using FnChangeCallback_t = void(*)(BaseConVar* ref, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue); -static_assert(sizeof(FnChangeCallback_t) == 0x8, "Wrong size for FnChangeCallback_t"); //----------------------------------------------------------------------------- // Purpose: Replaces the ConVar* diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 4c80c491e..e9d6fcb83 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -408,7 +408,8 @@ struct ConVarSetup_t char pad; // 0x37 - FnChangeCallback_t callback; // 0x38 + using FnGenericChangeCallback_t = void(*)(BaseConVar* ref, CSplitScreenSlot nSlot, CVValue_t* pNewValue, CVValue_t* pOldValue); + FnGenericChangeCallback_t callback; // 0x38 EConVarType type; // 0x40 int32_t unk1; // 0x42 @@ -454,6 +455,7 @@ template class ConVar : public BaseConVar { public: + using FnChangeCallback_t = void(*)(ConVar* ref, CSplitScreenSlot nSlot, T* pNewValue, T* pOldValue); // sub_6A66B0 ConVar(const char* name, int32_t flags, const char* description, T value, FnChangeCallback_t cb = nullptr) { @@ -463,7 +465,7 @@ class ConVar : public BaseConVar setup.has_default = true; setup.default_value = value; setup.type = TranslateConVarType(); - setup.callback = cb; + setup.callback = reinterpret_cast(cb); this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); } @@ -482,7 +484,7 @@ class ConVar : public BaseConVar setup.has_max = max; setup.max_value = maxValue; - setup.callback = cb; + setup.callback = reinterpret_cast(cb); setup.type = TranslateConVarType(); this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); From 4ebc6ac557e1d5d4a7c8d32fcda971ef90203f20 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 11:04:51 +0200 Subject: [PATCH 16/48] Use MAX_SPLITSCREEN_CLIENTS for IConVar definition --- public/icvar.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index a40d4d0e5..43a8efcc5 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -255,9 +255,9 @@ friend class ConVar; // (1 << 2) Skip setting min/max values int allocation_flag_of_some_sort; - TemplatedValue m_value[4]; + TemplatedValue m_value[MAX_SPLITSCREEN_CLIENTS]; }; -static_assert(sizeof(IConVar) == 0x80, "IConVar has wrong size!"); +static_assert(sizeof(IConVar) == 0x50, "IConVar has wrong size!"); static_assert(sizeof(IConVar) == sizeof(IConVar), "IConVar templated size changes!"); //----------------------------------------------------------------------------- From 19775584644fa2f8f12475a1ad7c6fbab00ff0d9 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 13:34:47 +0200 Subject: [PATCH 17/48] split convarhandle once more + template iconvar --- public/icvar.h | 114 ++++++++++++++++++++++-------------------- public/tier1/convar.h | 4 +- tier1/convar.cpp | 2 +- 3 files changed, 64 insertions(+), 56 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index 43a8efcc5..9277ce3af 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -111,43 +111,57 @@ struct CSplitScreenSlot typedef void(*FnChangeCallbackGlobal_t)(BaseConVar* ref, CSplitScreenSlot nSlot, const char *pNewValue, const char *pOldValue); //----------------------------------------------------------------------------- -// Purpose: Replaces the ConVar* +// Purpose: Replaces the ConVar* and ConCommand* //----------------------------------------------------------------------------- class ConVarHandle { public: - ConVarHandle( uint16_t convarIndex = -1, uint16_t unk = -1, uint32_t handle = -1) : - m_convarIndex(convarIndex), - m_unknown1(unk), + ConVarHandle( uint16_t index = -1, uint32_t handle = -1) : + m_convarIndex(index), m_handleIndex(handle) {} - bool IsValid( ) const; - void Invalidate( ); + bool IsValid( ) const { return m_convarIndex != 0xFFFF; } + void Invalidate( ) + { + m_convarIndex = 0xFFFF; + m_handleIndex = 0x0; + } uint16_t GetConVarIndex() const { return m_convarIndex; } uint32_t GetIndex() const { return m_handleIndex; } private: uint16_t m_convarIndex; - uint16_t m_unknown1; uint32_t m_handleIndex; }; -static_assert(sizeof(ConVarHandle) == 0x8, "ConVarHandle is of the wrong size!"); static const ConVarHandle INVALID_CONVAR_HANDLE = ConVarHandle(); -inline bool ConVarHandle::IsValid() const +class ConCommandHandle { - return m_convarIndex != 0xFFFF; -} +public: + ConCommandHandle( uint16_t index = -1, uint32_t handle = -1) : + m_concommandIndex(index), + m_handleIndex(handle) + {} -inline void ConVarHandle::Invalidate() -{ - m_convarIndex = 0xFFFF; - m_unknown1 = 0xFFFF; - m_handleIndex = 0x0; -} + bool IsValid( ) const { return m_concommandIndex != 0xFFFF; } + void Invalidate( ) + { + m_concommandIndex = 0xFFFF; + m_handleIndex = 0x0; + } + + uint16_t GetConVarIndex() const { return m_concommandIndex; } + uint32_t GetIndex() const { return m_handleIndex; } + +private: + uint32_t m_concommandIndex; + uint32_t m_handleIndex; +}; + +static const ConCommandHandle INVALID_CONCOMMAND_HANDLE = ConCommandHandle(); //----------------------------------------------------------------------------- // Purpose: Internal structure of ConVar objects @@ -200,9 +214,9 @@ class IConVar friend class ConVar; IConVar() : m_pszName(""), - m_Default(nullptr), - m_Min(nullptr), - m_Max(nullptr), + m_defaultValue(new T()), + m_minValue(new T()), + m_maxValue(new T()), m_pszHelpString("This convar is being accessed prior to ConVar_Register being called"), m_eVarType(TranslateConVarType()) { @@ -212,40 +226,36 @@ friend class ConVar; inline const char* GetDescription( ) const { return m_pszHelpString; } inline EConVarType GetType( ) const { return m_eVarType; } - inline const T& GetDefaultValue( ) const { return m_Default->value; } - inline const T& GetMinValue( ) const { return m_Min->value; } - inline const T& GetMaxValue( ) const { return m_Max->value; } + inline const T& GetDefaultValue( ) const { return *m_defaultValue; } + inline const T& GetMinValue( ) const { return *m_minValue; } + inline const T& GetMaxValue( ) const { return *m_maxValue; } - inline void SetDefaultValue(const T& value) { m_Default->value = value; } - inline void SetMinValue(const T& value) { m_Min->value = value; } - inline void SetMaxValue(const T& value) { m_Max->value = value; } + inline void SetDefaultValue(const T& value) { *m_defaultValue = value; } + inline void SetMinValue(const T& value) { *m_minValue = value; } + inline void SetMaxValue(const T& value) { *m_maxValue = value; } - inline const T& GetValue( int index = 0 ) const { return m_value[index].value; } - inline void SetValue(const T& value, int index = 0) { m_value[index].value = value; } + inline const T& GetValue( int index = 0 ) const { return m_value[index]; } + inline void SetValue(const T& value, int index = 0) { m_value[index] = value; } - inline bool IsFlagSet( int64_t flag ) const { return ( flag & m_flags ) ? true : false; } - inline void AddFlags( int64_t flags ) { m_flags |= flags; } - inline void RemoveFlags( int64_t flags ) { m_flags &= ~flags; } - inline int64_t GetFlags( void ) const { return m_flags; } + inline bool IsFlagSet( int64_t flag ) const { return ( flag & m_nFlags ) ? true : false; } + inline void AddFlags( int64_t flags ) { m_nFlags |= flags; } + inline void RemoveFlags( int64_t flags ) { m_nFlags &= ~flags; } + inline int64_t GetFlags( void ) const { return m_nFlags; } const char* m_pszName; - union TemplatedValue { - int8_t pad[sizeof(CVValue_t)]; - T value = T(); - }; - TemplatedValue* m_Default; - TemplatedValue* m_Min; - TemplatedValue* m_Max; + T* m_defaultValue; + T* m_minValue; + T* m_maxValue; const char* m_pszHelpString; EConVarType m_eVarType; // This gets copied from the ConVarDesc_t on creation short unk1; - unsigned int timesChanged; - int64 m_flags; - unsigned int callback_index; + unsigned int m_iTimesChanged; + int64 m_nFlags; + unsigned int m_iCallbackIndex; // Used when setting default, max, min values from the ConVarDesc_t // although that's not the only place of usage @@ -253,12 +263,10 @@ friend class ConVar; // (1 << 0) Skip setting value to split screen slots and also something keyvalues related // (1 << 1) Skip setting default value // (1 << 2) Skip setting min/max values - int allocation_flag_of_some_sort; + int m_nUnknownAllocFlags; - TemplatedValue m_value[MAX_SPLITSCREEN_CLIENTS]; + T m_value[MAX_SPLITSCREEN_CLIENTS]; }; -static_assert(sizeof(IConVar) == 0x50, "IConVar has wrong size!"); -static_assert(sizeof(IConVar) == sizeof(IConVar), "IConVar templated size changes!"); //----------------------------------------------------------------------------- // Purpose: DLL interface to ConVars/ConCommands @@ -272,10 +280,10 @@ abstract_class ICvar : public IAppSystem virtual ConVarHandle FindNextConVar( ConVarHandle prev ) = 0; virtual void SetConVarValue( ConVarHandle cvarid, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue ) = 0; - virtual ConVarHandle FindCommand( const char *name ) = 0; - virtual ConVarHandle FindFirstCommand() = 0; - virtual ConVarHandle FindNextCommand( ConVarHandle prev ) = 0; - virtual void DispatchConCommand( ConVarHandle cmd, const CCommandContext &ctx, const CCommand &args ) = 0; + virtual ConCommandHandle FindCommand( const char *name ) = 0; + virtual ConCommandHandle FindFirstCommand() = 0; + virtual ConCommandHandle FindNextCommand( ConCommandHandle prev ) = 0; + virtual void DispatchConCommand( ConCommandHandle cmd, const CCommandContext &ctx, const CCommand &args ) = 0; // Install a global change callback (to be called when any convar changes) virtual void InstallGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; @@ -326,9 +334,9 @@ abstract_class ICvar : public IAppSystem } // Register, unregister commands - virtual ConVarHandle RegisterConCommand( const ConCommandCreation_t& setup, int64 nAdditionalFlags = 0 ) = 0; - virtual void UnregisterConCommand( ConVarHandle handle ) = 0; - virtual ConCommand* GetCommand( ConVarHandle handle ) = 0; + virtual ConCommandHandle RegisterConCommand( const ConCommandCreation_t& setup, int64 nAdditionalFlags = 0 ) = 0; + virtual void UnregisterConCommand( ConCommandHandle handle ) = 0; + virtual ConCommand* GetCommand( ConCommandHandle handle ) = 0; virtual void QueueThreadSetValue( BaseConVar* ref, CSplitScreenSlot nSlot, CVValue_t* value ) = 0; }; diff --git a/public/tier1/convar.h b/public/tier1/convar.h index e9d6fcb83..33ea5d3b1 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -344,7 +344,7 @@ struct ConCommandCreation_t : CVarCreationBase_t bool has_complitioncallback; bool is_interface; - ConVarHandle* refHandle; + ConCommandHandle* refHandle; }; static_assert(sizeof(ConCommandCreation_t) == 0x40, "ConCommandCreation_t is of the wrong size!"); @@ -376,7 +376,7 @@ class ConCommand void Create( const char *pName, const char *pHelpString, int64_t flags, ConCommandCreation_t& setup ); void Destroy( ); - ConVarHandle m_Handle; + ConCommandHandle m_Handle; }; #pragma pack(push,1) diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 188a323e7..cb8f47bc8 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -43,7 +43,7 @@ void RegisterCommand( ConCommandCreation_t& cmd ) } } -void UnRegisterCommand( ConVarHandle& cmd ) +void UnRegisterCommand( ConCommandHandle& cmd ) { if ( cmd.IsValid() ) { From 9b66bab950d917b127e994b53c9b2db9a524a1e2 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 13:55:43 +0200 Subject: [PATCH 18/48] Renaming IConVar and depollute ICVar --- public/icvar.h | 124 +++++++++++++++++++++++++----------------- public/tier1/convar.h | 18 +++--- tier1/convar.cpp | 32 +++++------ 3 files changed, 101 insertions(+), 73 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index 9277ce3af..c7f6908b9 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -208,45 +208,45 @@ template<> constexpr EConVarType TranslateConVarType( void ) { return EC template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Invalid; } template -class IConVar +struct ConVarData_t; + +struct ConVarBaseData_t { -public: -friend class ConVar; - IConVar() : - m_pszName(""), - m_defaultValue(new T()), - m_minValue(new T()), - m_maxValue(new T()), - m_pszHelpString("This convar is being accessed prior to ConVar_Register being called"), - m_eVarType(TranslateConVarType()) + template + inline const ConVarData_t* Cast() const { + if (this->m_eVarType == TranslateConVarType()) + { + return reinterpret_cast*>(this); + } + return nullptr; } - inline const char* GetName( ) const { return m_pszName; } - inline const char* GetDescription( ) const { return m_pszHelpString; } - inline EConVarType GetType( ) const { return m_eVarType; } - - inline const T& GetDefaultValue( ) const { return *m_defaultValue; } - inline const T& GetMinValue( ) const { return *m_minValue; } - inline const T& GetMaxValue( ) const { return *m_maxValue; } - - inline void SetDefaultValue(const T& value) { *m_defaultValue = value; } - inline void SetMinValue(const T& value) { *m_minValue = value; } - inline void SetMaxValue(const T& value) { *m_maxValue = value; } - - inline const T& GetValue( int index = 0 ) const { return m_value[index]; } - inline void SetValue(const T& value, int index = 0) { m_value[index] = value; } + template + inline ConVarData_t* Cast() + { + if (this->m_eVarType == TranslateConVarType()) + { + return reinterpret_cast*>(this); + } + return nullptr; + } - inline bool IsFlagSet( int64_t flag ) const { return ( flag & m_nFlags ) ? true : false; } - inline void AddFlags( int64_t flags ) { m_nFlags |= flags; } - inline void RemoveFlags( int64_t flags ) { m_nFlags &= ~flags; } - inline int64_t GetFlags( void ) const { return m_nFlags; } + ConVarBaseData_t() : + m_pszName(""), + m_defaultValue(nullptr), + m_minValue(nullptr), + m_maxValue(nullptr), + m_pszHelpString("This convar is being accessed prior to ConVar_Register being called"), + m_eVarType(EConVarType_Invalid) + { + } const char* m_pszName; - T* m_defaultValue; - T* m_minValue; - T* m_maxValue; + void* m_defaultValue; + void* m_minValue; + void* m_maxValue; const char* m_pszHelpString; EConVarType m_eVarType; @@ -264,6 +264,47 @@ friend class ConVar; // (1 << 1) Skip setting default value // (1 << 2) Skip setting min/max values int m_nUnknownAllocFlags; +}; + +template +struct ConVarData_t : ConVarBaseData_t +{ +public: +friend class ConVar; + ConVarData_t() + { + m_defaultValue = new T(); + m_minValue = new T(); + m_maxValue = new T(); + m_eVarType = TranslateConVarType(); + } + + ~ConVarData_t() + { + delete m_defaultValue; + delete m_minValue; + delete m_eVarType; + } + + inline const char* GetName( ) const { return m_pszName; } + inline const char* GetDescription( ) const { return m_pszHelpString; } + inline EConVarType GetType( ) const { return m_eVarType; } + + inline const T& GetDefaultValue( ) const { return *reinterpret_cast(m_defaultValue); } + inline const T& GetMinValue( ) const { return *reinterpret_cast(m_minValue); } + inline const T& GetMaxValue( ) const { return *reinterpret_cast(m_maxValue); } + + inline void SetDefaultValue(const T& value) { *reinterpret_cast(m_defaultValue) = value; } + inline void SetMinValue(const T& value) { *reinterpret_cast(m_minValue) = value; } + inline void SetMaxValue(const T& value) { *reinterpret_cast(m_maxValue) = value; } + + inline const T& GetValue( int index = 0 ) const { return m_value[index]; } + inline void SetValue(const T& value, int index = 0) { m_value[index] = value; } + + inline bool IsFlagSet( int64_t flag ) const { return ( flag & m_nFlags ) ? true : false; } + inline void AddFlags( int64_t flags ) { m_nFlags |= flags; } + inline void RemoveFlags( int64_t flags ) { m_nFlags &= ~flags; } + inline int64_t GetFlags( void ) const { return m_nFlags; } T m_value[MAX_SPLITSCREEN_CLIENTS]; }; @@ -289,9 +330,6 @@ abstract_class ICvar : public IAppSystem virtual void InstallGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; virtual void RemoveGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; virtual void CallGlobalChangeCallbacks( BaseConVar* ref, CSplitScreenSlot nSlot, const char *pOldString, float flOldValue ) = 0; - template - inline void CallGlobalChangeCallbacks( ConVar* var, CSplitScreenSlot nSlot, const char *pOldString, float flOldValue ) { this->CallGlobalChangeCallbacks(var, nSlot, pOldString, flOldValue); } - // Reverts cvars which contain a specific flag virtual void RevertFlaggedConVars( int nFlag ) = 0; @@ -315,23 +353,9 @@ abstract_class ICvar : public IAppSystem virtual void unk2() = 0; // Register, unregister vars - virtual void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, void** pCvar ) = 0; - template - inline void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, IConVar** pCvar ) { this->RegisterConVar(setup, nAdditionalFlags, pCvarRef, (void**)pCvar); } - + virtual void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, ConVarBaseData_t** pCvar ) = 0; virtual void UnregisterConVar( ConVarHandle handle ) = 0; - - virtual void* GetConVarNoType( ConVarHandle handle ) = 0; - template - inline IConVar* GetConVar( ConVarHandle handle ) - { - auto convar = (IConVar*)this->GetConVarNoType( handle ); - if (convar && convar->GetType() != TranslateConVarType()) - { - return nullptr; - } - return convar; - } + virtual ConVarBaseData_t* GetConVar( ConVarHandle handle ) = 0; // Register, unregister commands virtual ConCommandHandle RegisterConCommand( const ConCommandCreation_t& setup, int64 nAdditionalFlags = 0 ) = 0; diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 33ea5d3b1..f5282461c 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -428,7 +428,7 @@ struct ConVarCreation_t : CVarCreationBase_t { ConVarSetup_t setup; // 0x18 ConVarHandle* refHandle; // 0x60 - void** refConVar; // 0x68 + ConVarBaseData_t** refConVar; // 0x68 }; static_assert(sizeof(ConVarCreation_t) == 0x70, "ConVarCreation_t wrong size!"); @@ -439,9 +439,9 @@ static_assert(sizeof(CVValue_t) == 0x10, "CVValue_t wrong size!"); extern void* invalid_convar[EConVarType_MAX + 1]; template -IConVar* ConVar_Invalid() +ConVarData_t* ConVar_Invalid() { - return (IConVar*)&invalid_convar[TranslateConVarType()]; + return (ConVarData_t*)&invalid_convar[TranslateConVarType()]; } void SetupConVar( ConVarCreation_t& cvar ); @@ -523,9 +523,13 @@ class ConVar : public BaseConVar this->m_ConVar = nullptr; // qword_191A3D8 - if (g_pCVar && (this->m_ConVar = g_pCVar->GetConVar(defaultHandle)) == nullptr) + if (g_pCVar) { - this->m_ConVar = ConVar_Invalid(); + this->m_ConVar = g_pCVar->GetConVar(defaultHandle)->Cast(); + if (!this->m_ConVar) + { + this->m_ConVar = ConVar_Invalid(); + } // technically this //result = *(char ***)(sub_10B7760((unsigned int)a3) + 80); } @@ -560,14 +564,14 @@ class ConVar : public BaseConVar cvar.setup = setup; cvar.refHandle = &this->m_Handle; - cvar.refConVar = (void**)&this->m_ConVar; + cvar.refConVar = (ConVarBaseData_t**)&this->m_ConVar; SetupConVar(cvar); } // High-speed method to read convar data ConVarHandle m_Handle; - IConVar* m_ConVar; + ConVarData_t* m_ConVar; }; static_assert(sizeof(ConVar) == 0x10, "ConVar is of the wrong size!"); static_assert(sizeof(ConVar) == sizeof(ConVar), "Templated ConVar size varies!"); diff --git a/tier1/convar.cpp b/tier1/convar.cpp index cb8f47bc8..23836ce47 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -535,22 +535,22 @@ void ConCommand::Destroy() //----------------------------------------------------------------------------- void* invalid_convar[EConVarType_MAX + 1] = { - new IConVar(), - new IConVar(), - new IConVar(), - new IConVar(), - new IConVar(), - new IConVar(), - new IConVar(), - new IConVar(), - new IConVar(), - new IConVar(), - new IConVar(), - new IConVar(), - new IConVar(), - new IConVar(), - new IConVar(), - new IConVar() // EConVarType_MAX + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t(), + new ConVarData_t() // EConVarType_MAX }; #ifdef CONVAR_WORK_FINISHED From 7ededcc159e5675caa7d3f866caabb2e915ba753 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 14:01:16 +0200 Subject: [PATCH 19/48] remove static_assert + IDA comments --- public/tier1/convar.h | 6 +----- tier1/convar.cpp | 2 -- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index f5282461c..3cfd103e2 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -435,7 +435,6 @@ static_assert(sizeof(ConVarCreation_t) == 0x70, "ConVarCreation_t wrong size!"); static_assert(sizeof(ConVarCreation_t) % 8 == 0x0, "ConVarCreation_t isn't 8 bytes aligned!"); static_assert(sizeof(CVValue_t) == 0x10, "CVValue_t wrong size!"); -// sub_10B7760 extern void* invalid_convar[EConVarType_MAX + 1]; template @@ -456,7 +455,7 @@ class ConVar : public BaseConVar { public: using FnChangeCallback_t = void(*)(ConVar* ref, CSplitScreenSlot nSlot, T* pNewValue, T* pOldValue); - // sub_6A66B0 + ConVar(const char* name, int32_t flags, const char* description, T value, FnChangeCallback_t cb = nullptr) { this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); @@ -516,13 +515,11 @@ class ConVar : public BaseConVar inline int64_t GetFlags( void ) const { return m_ConVar->GetFlags( ); } private: - // sub_10B7BC0 void Init(ConVarHandle defaultHandle, EConVarType type) { this->m_Handle.Invalidate(); this->m_ConVar = nullptr; - // qword_191A3D8 if (g_pCVar) { this->m_ConVar = g_pCVar->GetConVar(defaultHandle)->Cast(); @@ -536,7 +533,6 @@ class ConVar : public BaseConVar this->m_Handle = defaultHandle; } - // sub_10B7C70 void Register(const char* name, int32_t flags, const char* description, const ConVarSetup_t& setup) { this->m_ConVar = ConVar_Invalid(); diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 23836ce47..8256505d7 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -195,11 +195,9 @@ class ConVarRegList public: static bool s_bConVarsRegistered; }; -static_assert(sizeof(ConVarRegList) == 0x2BD0, "Size mismatch"); bool ConVarRegList::s_bConVarsRegistered = false; -// sub_10B79F0 void SetupConVar( ConVarCreation_t& cvar ) { if ( ConVarRegList::s_bConVarsRegistered ) From cdd1aca530f796986054f3322d024b8bf9492e89 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 14:26:49 +0200 Subject: [PATCH 20/48] renaming struct properties --- public/tier1/convar.h | 212 ++++++++++++++++++------------------------ tier1/convar.cpp | 78 ++++++++-------- 2 files changed, 132 insertions(+), 158 deletions(-) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 3cfd103e2..abf433889 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -52,9 +52,9 @@ class ConCommand; struct CVarCreationBase_t { CVarCreationBase_t( ) : - name( nullptr ), - description( nullptr ), - flags( 0 ) + m_pszName( nullptr ), + m_pszHelpString( nullptr ), + m_nFlags( 0 ) {} bool IsFlagSet( int64_t flag ) const; @@ -62,35 +62,11 @@ struct CVarCreationBase_t void RemoveFlags( int64_t flags ); int64_t GetFlags() const; - const char* name; - const char* description; - int64_t flags; + const char* m_pszName; + const char* m_pszHelpString; + int64_t m_nFlags; }; -inline bool CVarCreationBase_t::IsFlagSet( int64_t flag ) const -{ - return ( flag & this->flags ) ? true : false; -} - -inline void CVarCreationBase_t::AddFlags( int64_t flags ) -{ - this->flags |= flags; - -#ifdef ALLOW_DEVELOPMENT_CVARS - this->flags &= ~FCVAR_DEVELOPMENTONLY; -#endif -} - -inline void CVarCreationBase_t::RemoveFlags( int64_t flags ) -{ - this->flags &= ~flags; -} - -inline int64_t CVarCreationBase_t::GetFlags( void ) const -{ - return this->flags; -} - enum CommandTarget_t { CT_NO_TARGET = -1, @@ -298,34 +274,34 @@ inline const char *CCommand::operator[]( int nIndex ) const struct ConCommandCreation_t : CVarCreationBase_t { ConCommandCreation_t() : - has_complitioncallback(false), - is_interface(false), - refHandle(nullptr) + m_bHasCompletionCallback(false), + m_bIsInterface(false), + m_pHandle(nullptr) {} // Call this function when executing the command struct CallbackInfo_t { CallbackInfo_t() : - fnCommandCallback(nullptr), - is_interface(false), - is_voidcallback(false), - is_contextless(false) + m_fnCommandCallback(nullptr), + m_bIsInterface(false), + m_bIsVoidCallback(false), + m_bIsContextLess(false) {} union { - FnCommandCallback_t fnCommandCallback; - FnCommandCallbackVoid_t fnVoidCommandCallback; - FnCommandCallbackNoContext_t fnContextlessCommandCallback; - ICommandCallback* pCommandCallback; + FnCommandCallback_t m_fnCommandCallback; + FnCommandCallbackVoid_t m_fnVoidCommandCallback; + FnCommandCallbackNoContext_t m_fnContextlessCommandCallback; + ICommandCallback* m_pCommandCallback; }; - bool is_interface; - bool is_voidcallback; - bool is_contextless; + bool m_bIsInterface; + bool m_bIsVoidCallback; + bool m_bIsContextLess; }; - CallbackInfo_t callback; + CallbackInfo_t m_fnCallback; // NOTE: To maintain backward compat, we have to be very careful: // All public virtual methods must appear in the same order always @@ -337,14 +313,14 @@ struct ConCommandCreation_t : CVarCreationBase_t union { - FnCommandCompletionCallback fnCompletionCallback; - ICommandCompletionCallback* pCommandCompletionCallback; + FnCommandCompletionCallback m_fnCompletionCallback; + ICommandCompletionCallback* m_pCommandCompletionCallback; }; - bool has_complitioncallback; - bool is_interface; + bool m_bHasCompletionCallback; + bool m_bIsInterface; - ConCommandHandle* refHandle; + ConCommandHandle* m_pHandle; }; static_assert(sizeof(ConCommandCreation_t) == 0x40, "ConCommandCreation_t is of the wrong size!"); @@ -379,56 +355,55 @@ class ConCommand ConCommandHandle m_Handle; }; +using FnGenericChangeCallback_t = void(*)(BaseConVar* ref, CSplitScreenSlot nSlot, CVValue_t* pNewValue, CVValue_t* pOldValue); #pragma pack(push,1) struct ConVarSetup_t { ConVarSetup_t() : - unknown0(0), - has_default(false), - has_min(false), - has_max(false), - default_value(), - min_value(), - max_value(), - callback(nullptr), - type(EConVarType_Invalid), - unk1(0), - unk2(0) + m_unknown1(0), + m_bHasDefault(false), + m_bHasMin(false), + m_bHasMax(false), + m_defaultValue(), + m_minValue(), + m_maxValue(), + m_fnCallBack(nullptr), + m_eVarType(EConVarType_Invalid), + m_unknown2(0), + m_unknown3(0) {} - int32 unknown0; // 0x0 + int32_t m_unknown1; // 0x0 - bool has_default; // 0x4 - bool has_min; // 0x5 - bool has_max; // 0x6 + bool m_bHasDefault; // 0x4 + bool m_bHasMin; // 0x5 + bool m_bHasMax; // 0x6 - CVValue_t default_value; // 0x7 - CVValue_t min_value; // 0x17 - CVValue_t max_value; // 0x27 + CVValue_t m_defaultValue; // 0x7 + CVValue_t m_minValue; // 0x17 + CVValue_t m_maxValue; // 0x27 char pad; // 0x37 - using FnGenericChangeCallback_t = void(*)(BaseConVar* ref, CSplitScreenSlot nSlot, CVValue_t* pNewValue, CVValue_t* pOldValue); - FnGenericChangeCallback_t callback; // 0x38 - EConVarType type; // 0x40 + FnGenericChangeCallback_t m_fnCallBack; // 0x38 + EConVarType m_eVarType; // 0x40 - int32_t unk1; // 0x42 - int16_t unk2; // 0x46 + int32_t m_unknown2; // 0x42 + int16_t m_unknown3; // 0x46 }; #pragma pack(pop) - static_assert(sizeof(ConVarSetup_t) == 0x48, "ConVarSetup_t is of the wrong size!"); static_assert(sizeof(ConVarSetup_t) % 8 == 0x0, "ConVarSetup_t isn't 8 bytes aligned!"); struct ConVarCreation_t : CVarCreationBase_t { ConVarCreation_t() : - refHandle(nullptr), - refConVar(nullptr) + m_pHandle(nullptr), + m_pConVarData(nullptr) {} - ConVarSetup_t setup; // 0x18 + ConVarSetup_t m_cvarSetup; // 0x18 - ConVarHandle* refHandle; // 0x60 - ConVarBaseData_t** refConVar; // 0x68 + ConVarHandle* m_pHandle; // 0x60 + ConVarBaseData_t** m_pConVarData; // 0x68 }; static_assert(sizeof(ConVarCreation_t) == 0x70, "ConVarCreation_t wrong size!"); @@ -461,10 +436,10 @@ class ConVar : public BaseConVar this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); ConVarSetup_t setup; - setup.has_default = true; - setup.default_value = value; - setup.type = TranslateConVarType(); - setup.callback = reinterpret_cast(cb); + setup.m_bHasDefault = true; + setup.m_defaultValue = value; + setup.m_eVarType = TranslateConVarType(); + setup.m_fnCallBack = reinterpret_cast(cb); this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); } @@ -474,17 +449,16 @@ class ConVar : public BaseConVar this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); ConVarSetup_t setup; - setup.has_default = true; - setup.default_value = value; - - setup.has_min = min; - setup.min_value = minValue; + setup.m_bHasDefault = true; + setup.m_defaultValue = value; - setup.has_max = max; - setup.max_value = maxValue; + setup.m_bHasMin = min; + setup.m_bHasMax = max; + setup.m_minValue = minValue; + setup.m_maxValue = maxValue; - setup.callback = reinterpret_cast(cb); - setup.type = TranslateConVarType(); + setup.m_eVarType = TranslateConVarType(); + setup.m_fnCallBack = reinterpret_cast(cb); this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); } @@ -494,38 +468,38 @@ class ConVar : public BaseConVar UnRegisterConVar(this->m_Handle); } - inline const char* GetName( ) const { return m_ConVar->GetName( ); } - inline const char* GetDescription( ) const { return m_ConVar->GetDescription( ); } - inline EConVarType GetType( ) const { return m_ConVar->GetType( ); } + inline const char* GetName( ) const { return m_ConVarData->GetName( ); } + inline const char* GetDescription( ) const { return m_ConVarData->GetDescription( ); } + inline EConVarType GetType( ) const { return m_ConVarData->GetType( ); } - inline CVValue_t* GetDefaultValue( ) const { return m_ConVar->GetDefaultValue( ); } - inline CVValue_t* GetMinValue( ) const { return m_ConVar->GetMinValue( ); } - inline CVValue_t* GetMaxValue( ) const { return m_ConVar->GetMaxValue( ); } + inline CVValue_t* GetDefaultValue( ) const { return m_ConVarData->GetDefaultValue( ); } + inline CVValue_t* GetMinValue( ) const { return m_ConVarData->GetMinValue( ); } + inline CVValue_t* GetMaxValue( ) const { return m_ConVarData->GetMaxValue( ); } - inline void SetDefaultValue(const T& value) { m_ConVar->SetDefaultValue( value ); } - inline void SetMinValue(const T& value) { m_ConVar->SetMinValue( value ); } - inline void SetMaxValue(const T& value) { m_ConVar->SetMaxValue( value ); } + inline void SetDefaultValue(const T& value) { m_ConVarData->SetDefaultValue( value ); } + inline void SetMinValue(const T& value) { m_ConVarData->SetMinValue( value ); } + inline void SetMaxValue(const T& value) { m_ConVarData->SetMaxValue( value ); } - inline const T& GetValue( int index = 0 ) const { return m_ConVar->GetValue( index ); } - inline void SetValue(const T& value, int index = 0) { m_ConVar->SetValue( value, index ); } + inline const T& GetValue( int index = 0 ) const { return m_ConVarData->GetValue( index ); } + inline void SetValue(const T& value, int index = 0) { m_ConVarData->SetValue( value, index ); } - inline bool IsFlagSet( int64_t flag ) const { return m_ConVar->IsFlagSet( flag ); } - inline void AddFlags( int64_t flags ) { m_ConVar->AddFlags( flags ); } - inline void RemoveFlags( int64_t flags ) { return m_ConVar->RemoveFlags( flags ); } - inline int64_t GetFlags( void ) const { return m_ConVar->GetFlags( ); } + inline bool IsFlagSet( int64_t flag ) const { return m_ConVarData->IsFlagSet( flag ); } + inline void AddFlags( int64_t flags ) { m_ConVarData->AddFlags( flags ); } + inline void RemoveFlags( int64_t flags ) { return m_ConVarData->RemoveFlags( flags ); } + inline int64_t GetFlags( void ) const { return m_ConVarData->GetFlags( ); } private: void Init(ConVarHandle defaultHandle, EConVarType type) { this->m_Handle.Invalidate(); - this->m_ConVar = nullptr; + this->m_ConVarData = nullptr; if (g_pCVar) { - this->m_ConVar = g_pCVar->GetConVar(defaultHandle)->Cast(); - if (!this->m_ConVar) + this->m_ConVarData = g_pCVar->GetConVar(defaultHandle)->Cast(); + if (!this->m_ConVarData) { - this->m_ConVar = ConVar_Invalid(); + this->m_ConVarData = ConVar_Invalid(); } // technically this //result = *(char ***)(sub_10B7760((unsigned int)a3) + 80); @@ -535,7 +509,7 @@ class ConVar : public BaseConVar void Register(const char* name, int32_t flags, const char* description, const ConVarSetup_t& setup) { - this->m_ConVar = ConVar_Invalid(); + this->m_ConVarData = ConVar_Invalid(); this->m_Handle.Invalidate(); if (!CommandLine()->HasParm("-tools") @@ -553,21 +527,21 @@ class ConVar : public BaseConVar ConVarCreation_t cvar; - cvar.name = name; - cvar.description = description; - cvar.flags = flags; + cvar.m_pszName = name; + cvar.m_pszHelpString = description; + cvar.m_nFlags = flags; - cvar.setup = setup; + cvar.m_cvarSetup = setup; - cvar.refHandle = &this->m_Handle; - cvar.refConVar = (ConVarBaseData_t**)&this->m_ConVar; + cvar.m_pHandle = &this->m_Handle; + cvar.m_pConVarData = (ConVarBaseData_t**)&this->m_ConVarData; SetupConVar(cvar); } // High-speed method to read convar data ConVarHandle m_Handle; - ConVarData_t* m_ConVar; + ConVarData_t* m_ConVarData; }; static_assert(sizeof(ConVar) == 0x10, "ConVar is of the wrong size!"); static_assert(sizeof(ConVar) == sizeof(ConVar), "Templated ConVar size varies!"); diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 8256505d7..741cb7d78 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -35,10 +35,10 @@ static bool s_bRegistered = false; void RegisterCommand( ConCommandCreation_t& cmd ) { - *cmd.refHandle = g_pCVar->RegisterConCommand( cmd, s_nCVarFlag ); - if ( !cmd.refHandle->IsValid() ) + *cmd.m_pHandle = g_pCVar->RegisterConCommand( cmd, s_nCVarFlag ); + if ( !cmd.m_pHandle->IsValid() ) { - Plat_FatalErrorFunc( "RegisterConCommand: Unknown error registering con command \"%s\"!\n", cmd.name ); + Plat_FatalErrorFunc( "RegisterConCommand: Unknown error registering con command \"%s\"!\n", cmd.m_pszName ); DebuggerBreakIfDebugging( ); } } @@ -125,10 +125,10 @@ void AddCommand( ConCommandCreation_t& cmd ) void RegisterConVar( ConVarCreation_t& cvar ) { - g_pCVar->RegisterConVar( cvar, s_nCVarFlag, cvar.refHandle, cvar.refConVar ); - if (!cvar.refHandle->IsValid()) + g_pCVar->RegisterConVar( cvar, s_nCVarFlag, cvar.m_pHandle, cvar.m_pConVarData ); + if (!cvar.m_pHandle->IsValid()) { - Plat_FatalErrorFunc( "RegisterConVar: Unknown error registering convar \"%s\"!\n", cvar.name ); + Plat_FatalErrorFunc( "RegisterConVar: Unknown error registering convar \"%s\"!\n", cvar.m_pszName ); DebuggerBreakIfDebugging(); } } @@ -434,14 +434,14 @@ int DefaultCompletionFunc( const char *partial, CUtlVector< CUtlString > &comman ConCommand::ConCommand( const char *pName, FnCommandCallback_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) { ConCommandCreation_t creation; - creation.callback.fnCommandCallback = callback; - creation.callback.is_interface = false; - creation.callback.is_voidcallback = false; - creation.callback.is_contextless = false; + creation.m_fnCallback.m_fnCommandCallback = callback; + creation.m_fnCallback.m_bIsInterface = false; + creation.m_fnCallback.m_bIsVoidCallback = false; + creation.m_fnCallback.m_bIsContextLess = false; - creation.fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; - creation.has_complitioncallback = completionFunc != 0 ? true : false; - creation.is_interface = false; + creation.m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; + creation.m_bHasCompletionCallback = completionFunc != 0 ? true : false; + creation.m_bIsInterface = false; // Setup the rest Create( pName, pHelpString, flags, creation ); @@ -450,14 +450,14 @@ ConCommand::ConCommand( const char *pName, FnCommandCallback_t callback, const c ConCommand::ConCommand( const char *pName, FnCommandCallbackVoid_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) { ConCommandCreation_t creation; - creation.callback.fnVoidCommandCallback = callback; - creation.callback.is_interface = false; - creation.callback.is_voidcallback = true; - creation.callback.is_contextless = false; + creation.m_fnCallback.m_fnVoidCommandCallback = callback; + creation.m_fnCallback.m_bIsInterface = false; + creation.m_fnCallback.m_bIsVoidCallback = true; + creation.m_fnCallback.m_bIsContextLess = false; - creation.fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; - creation.has_complitioncallback = completionFunc != nullptr ? true : false; - creation.is_interface = false; + creation.m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; + creation.m_bHasCompletionCallback = completionFunc != nullptr ? true : false; + creation.m_bIsInterface = false; // Setup the rest Create( pName, pHelpString, flags, creation ); @@ -466,14 +466,14 @@ ConCommand::ConCommand( const char *pName, FnCommandCallbackVoid_t callback, con ConCommand::ConCommand( const char *pName, FnCommandCallbackNoContext_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) { ConCommandCreation_t creation; - creation.callback.fnContextlessCommandCallback = callback; - creation.callback.is_interface = false; - creation.callback.is_voidcallback = false; - creation.callback.is_contextless = true; + creation.m_fnCallback.m_fnContextlessCommandCallback = callback; + creation.m_fnCallback.m_bIsInterface = false; + creation.m_fnCallback.m_bIsVoidCallback = false; + creation.m_fnCallback.m_bIsContextLess = true; - creation.fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; - creation.has_complitioncallback = completionFunc != nullptr ? true : false; - creation.is_interface = false; + creation.m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; + creation.m_bHasCompletionCallback = completionFunc != nullptr ? true : false; + creation.m_bIsInterface = false; // Setup the rest Create( pName, pHelpString, flags, creation ); @@ -482,14 +482,14 @@ ConCommand::ConCommand( const char *pName, FnCommandCallbackNoContext_t callback ConCommand::ConCommand( const char *pName, ICommandCallback *pCallback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, ICommandCompletionCallback *pCompletionCallback /*= 0*/ ) { ConCommandCreation_t creation; - creation.callback.pCommandCallback = pCallback; - creation.callback.is_interface = true; - creation.callback.is_voidcallback = false; - creation.callback.is_contextless = false; + creation.m_fnCallback.m_pCommandCallback = pCallback; + creation.m_fnCallback.m_bIsInterface = true; + creation.m_fnCallback.m_bIsVoidCallback = false; + creation.m_fnCallback.m_bIsContextLess = false; - creation.pCommandCompletionCallback = pCompletionCallback; - creation.has_complitioncallback = pCompletionCallback != nullptr ? true : false; - creation.is_interface = true; + creation.m_pCommandCompletionCallback = pCompletionCallback; + creation.m_bHasCompletionCallback = pCompletionCallback != nullptr ? true : false; + creation.m_bIsInterface = true; // Setup the rest Create( pName, pHelpString, flags, creation ); @@ -508,15 +508,15 @@ void ConCommand::Create( const char* pName, const char* pHelpString, int64_t fla // Name should be static data Assert(pName); - setup.name = pName; - setup.description = pHelpString ? pHelpString : empty_string; + setup.m_pszName = pName; + setup.m_pszHelpString = pHelpString ? pHelpString : empty_string; - setup.flags = flags; + setup.m_nFlags = flags; #ifdef ALLOW_DEVELOPMENT_CVARS - setup.flags &= ~FCVAR_DEVELOPMENTONLY; + setup.m_nFlags &= ~FCVAR_DEVELOPMENTONLY; #endif - setup.refHandle = &this->m_Handle; + setup.m_pHandle = &this->m_Handle; AddCommand( setup ); } From f17c0bd7e09c4c569b75ef4f7ac2a5a394750ddd Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 14:33:41 +0200 Subject: [PATCH 21/48] undo icommandline change --- public/tier0/icommandline.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/tier0/icommandline.h b/public/tier0/icommandline.h index 561bb2324..1e5faac8c 100644 --- a/public/tier0/icommandline.h +++ b/public/tier0/icommandline.h @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// +//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// // // Purpose: // From b682b73d12c30697afd8e4b87b6c8e44b5051b9b Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 14:45:52 +0200 Subject: [PATCH 22/48] make reglist simpler --- tier1/convar.cpp | 92 ++++++++++++------------------------------------ 1 file changed, 23 insertions(+), 69 deletions(-) diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 741cb7d78..ff2b7a0bc 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -53,52 +53,38 @@ void UnRegisterCommand( ConCommandHandle& cmd ) } } -class ConCommandRegList; -static ConCommandRegList* s_pCommandRegList = nullptr; - class ConCommandRegList { public: + static ConCommandRegList* GetRegList() + { + static ConCommandRegList* list = new ConCommandRegList(); + return list; + } + static void RegisterAll() { if (!s_bConCommandsRegistered && g_pCVar) { s_bConCommandsRegistered = true; - ConCommandRegList* list = s_pCommandRegList; - while ( list != nullptr ) + ConCommandRegList* list = GetRegList(); + FOR_EACH_VEC( list->m_Vec, i ) { - FOR_EACH_VEC( list->m_Vec, i ) - { - RegisterCommand( list->m_Vec[i] ); - } - - ConCommandRegList *pNext = list->m_pNext; - delete list; - list = pNext; + RegisterCommand( list->m_Vec[i] ); } + delete list; } } private: friend void AddCommand( ConCommandCreation_t& cmd ); - void SetNextList( ConCommandRegList* list ) - { - m_pNext = list; - } - - int Count() const - { - return m_Vec.Count(); - } - void Add( const ConCommandCreation_t& cmd ) { m_Vec.AddToTail( cmd ); } - CUtlVectorFixed m_Vec; - ConCommandRegList* m_pNext = nullptr; + CUtlVector m_Vec; public: static bool s_bConCommandsRegistered; }; @@ -112,15 +98,7 @@ void AddCommand( ConCommandCreation_t& cmd ) return; } - if ( !s_pCommandRegList || s_pCommandRegList->Count() == 100 ) - { - ConCommandRegList* newList = new ConCommandRegList; - newList->SetNextList( s_pCommandRegList ); - - s_pCommandRegList = newList; - } - - s_pCommandRegList->Add( cmd ); + ConCommandRegList::GetRegList()->Add( cmd ); } void RegisterConVar( ConVarCreation_t& cvar ) @@ -143,13 +121,14 @@ void UnRegisterConVar( ConVarHandle& cvar ) } } -class ConVarRegList; -static ConVarRegList* s_pConVarRegList = nullptr; - class ConVarRegList { public: - ConVarRegList() {} + static ConVarRegList* GetRegList() + { + static ConVarRegList* list = new ConVarRegList(); + return list; + } static void RegisterAll() { @@ -157,41 +136,24 @@ class ConVarRegList { s_bConVarsRegistered = true; - ConVarRegList* list = s_pConVarRegList; - while ( list ) + ConVarRegList* list = GetRegList(); + FOR_EACH_VEC( list->m_Vec, i ) { - FOR_EACH_VEC( list->m_Vec, i ) - { - RegisterConVar( list->m_Vec[i] ); - } - - ConVarRegList *pNext = list->m_pNext; - delete list; - list = pNext; + RegisterConVar( list->m_Vec[i] ); } + delete list; } } private: friend void SetupConVar( ConVarCreation_t& cvar ); - void SetNextList( ConVarRegList* list ) - { - m_pNext = list; - } - - int Count() const - { - return m_Vec.Count(); - } - void Add( const ConVarCreation_t& cvar ) { m_Vec.AddToTail( cvar ); } - CUtlVectorFixed m_Vec; - ConVarRegList* m_pNext = nullptr; + CUtlVector m_Vec; public: static bool s_bConVarsRegistered; }; @@ -206,15 +168,7 @@ void SetupConVar( ConVarCreation_t& cvar ) return; } - if ( !s_pConVarRegList || s_pConVarRegList->Count() == 100 ) - { - ConVarRegList* newList = new ConVarRegList; - newList->SetNextList( s_pConVarRegList ); - - s_pConVarRegList = newList; - } - - s_pConVarRegList->Add( cvar ); + ConVarRegList::GetRegList()->Add( cvar ); } //----------------------------------------------------------------------------- From 13e111d611d0676fcc12aa94063bf0458831b1f5 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 14:48:32 +0200 Subject: [PATCH 23/48] Destroy ConCommandBase --- public/tier1/convar.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index abf433889..c7008921a 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -324,13 +324,6 @@ struct ConCommandCreation_t : CVarCreationBase_t }; static_assert(sizeof(ConCommandCreation_t) == 0x40, "ConCommandCreation_t is of the wrong size!"); -// TO-DO: Remove this... -class ConCommandBase -{ -public: - inline const char* GetName() { return "Please remove the ConCommandBase class..."; } -}; // For metamod compatibility only!!!! - class ConCommand { public: From 2c442dfac926342d366e7a68aea0f98a722079b0 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 15:21:42 +0200 Subject: [PATCH 24/48] move some functions to baseconvardata --- public/icvar.h | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index c7f6908b9..a782eebfb 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -242,6 +242,19 @@ struct ConVarBaseData_t { } + inline const char* GetName( void ) const { return m_pszName; } + inline const char* GetDescription( void ) const { return m_pszHelpString; } + inline EConVarType GetType( void ) const { return m_eVarType; } + + inline int GetTimesChanges( void ) const { return m_iTimesChanged; } + + inline bool IsFlagSet( int64_t flag ) const { return ( flag & m_nFlags ) ? true : false; } + inline void AddFlags( int64_t flags ) { m_nFlags |= flags; } + inline void RemoveFlags( int64_t flags ) { m_nFlags &= ~flags; } + inline int64_t GetFlags( void ) const { return m_nFlags; } + + inline int GetCallbackIndex( void ) const { return m_iCallbackIndex; } +protected: const char* m_pszName; void* m_defaultValue; @@ -286,10 +299,6 @@ friend class ConVar; delete m_eVarType; } - inline const char* GetName( ) const { return m_pszName; } - inline const char* GetDescription( ) const { return m_pszHelpString; } - inline EConVarType GetType( ) const { return m_eVarType; } - inline const T& GetDefaultValue( ) const { return *reinterpret_cast(m_defaultValue); } inline const T& GetMinValue( ) const { return *reinterpret_cast(m_minValue); } inline const T& GetMaxValue( ) const { return *reinterpret_cast(m_maxValue); } @@ -301,11 +310,6 @@ friend class ConVar; inline const T& GetValue( int index = 0 ) const { return m_value[index]; } inline void SetValue(const T& value, int index = 0) { m_value[index] = value; } - inline bool IsFlagSet( int64_t flag ) const { return ( flag & m_nFlags ) ? true : false; } - inline void AddFlags( int64_t flags ) { m_nFlags |= flags; } - inline void RemoveFlags( int64_t flags ) { m_nFlags &= ~flags; } - inline int64_t GetFlags( void ) const { return m_nFlags; } - T m_value[MAX_SPLITSCREEN_CLIENTS]; }; From e8f353ed6419a95938890f175552ff2cc541013b Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 15:22:13 +0200 Subject: [PATCH 25/48] put cvar values into its own struct --- public/tier1/convar.h | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index c7008921a..6f6b38bb6 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -354,12 +354,6 @@ struct ConVarSetup_t { ConVarSetup_t() : m_unknown1(0), - m_bHasDefault(false), - m_bHasMin(false), - m_bHasMax(false), - m_defaultValue(), - m_minValue(), - m_maxValue(), m_fnCallBack(nullptr), m_eVarType(EConVarType_Invalid), m_unknown2(0), @@ -368,13 +362,22 @@ struct ConVarSetup_t int32_t m_unknown1; // 0x0 - bool m_bHasDefault; // 0x4 - bool m_bHasMin; // 0x5 - bool m_bHasMax; // 0x6 + struct ConVarValueInfo_t + { + ConVarValueInfo_t() : + m_bHasDefault(false), + m_bHasMin(false), + m_bHasMax(false) + {} + + bool m_bHasDefault; // 0x4 + bool m_bHasMin; // 0x5 + bool m_bHasMax; // 0x6 - CVValue_t m_defaultValue; // 0x7 - CVValue_t m_minValue; // 0x17 - CVValue_t m_maxValue; // 0x27 + CVValue_t m_defaultValue; // 0x7 + CVValue_t m_minValue; // 0x17 + CVValue_t m_maxValue; // 0x27 + } m_valueInfo; char pad; // 0x37 @@ -429,8 +432,8 @@ class ConVar : public BaseConVar this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); ConVarSetup_t setup; - setup.m_bHasDefault = true; - setup.m_defaultValue = value; + setup.m_valueInfo.m_bHasDefault = true; + setup.m_valueInfo.m_defaultValue = value; setup.m_eVarType = TranslateConVarType(); setup.m_fnCallBack = reinterpret_cast(cb); @@ -442,13 +445,13 @@ class ConVar : public BaseConVar this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); ConVarSetup_t setup; - setup.m_bHasDefault = true; - setup.m_defaultValue = value; + setup.m_valueInfo.m_bHasDefault = true; + setup.m_valueInfo.m_defaultValue = value; - setup.m_bHasMin = min; - setup.m_bHasMax = max; - setup.m_minValue = minValue; - setup.m_maxValue = maxValue; + setup.m_valueInfo.m_bHasMin = min; + setup.m_valueInfo.m_bHasMax = max; + setup.m_valueInfo.m_minValue = minValue; + setup.m_valueInfo.m_maxValue = maxValue; setup.m_eVarType = TranslateConVarType(); setup.m_fnCallBack = reinterpret_cast(cb); From 782a488cf01fab805a5e90a911422282b36230e3 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 16:17:41 +0200 Subject: [PATCH 26/48] revise struct --- public/tier1/convar.h | 63 ++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 43 deletions(-) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 6f6b38bb6..6933bda25 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -349,19 +349,16 @@ class ConCommand }; using FnGenericChangeCallback_t = void(*)(BaseConVar* ref, CSplitScreenSlot nSlot, CVValue_t* pNewValue, CVValue_t* pOldValue); -#pragma pack(push,1) -struct ConVarSetup_t -{ - ConVarSetup_t() : - m_unknown1(0), - m_fnCallBack(nullptr), - m_eVarType(EConVarType_Invalid), - m_unknown2(0), - m_unknown3(0) + +struct ConVarCreation_t : CVarCreationBase_t { + ConVarCreation_t() : + m_pHandle(nullptr), + m_pConVarData(nullptr) {} - int32_t m_unknown1; // 0x0 + int32_t m_unknown1; // 0x18 + #pragma pack(push,1) struct ConVarValueInfo_t { ConVarValueInfo_t() : @@ -370,38 +367,22 @@ struct ConVarSetup_t m_bHasMax(false) {} - bool m_bHasDefault; // 0x4 - bool m_bHasMin; // 0x5 - bool m_bHasMax; // 0x6 - - CVValue_t m_defaultValue; // 0x7 - CVValue_t m_minValue; // 0x17 - CVValue_t m_maxValue; // 0x27 - } m_valueInfo; - - char pad; // 0x37 - - FnGenericChangeCallback_t m_fnCallBack; // 0x38 - EConVarType m_eVarType; // 0x40 + bool m_bHasDefault; // 0x22 + bool m_bHasMin; // 0x23 + bool m_bHasMax; // 0x24 - int32_t m_unknown2; // 0x42 - int16_t m_unknown3; // 0x46 -}; -#pragma pack(pop) -static_assert(sizeof(ConVarSetup_t) == 0x48, "ConVarSetup_t is of the wrong size!"); -static_assert(sizeof(ConVarSetup_t) % 8 == 0x0, "ConVarSetup_t isn't 8 bytes aligned!"); + CVValue_t m_defaultValue; // 0x25 + CVValue_t m_minValue; // 0x35 + CVValue_t m_maxValue; // 0x45 + } m_valueInfo; // 0x22 + #pragma pack(pop) -struct ConVarCreation_t : CVarCreationBase_t { - ConVarCreation_t() : - m_pHandle(nullptr), - m_pConVarData(nullptr) - {} - ConVarSetup_t m_cvarSetup; // 0x18 + FnGenericChangeCallback_t m_fnCallBack; // 0x56 + EConVarType m_eVarType; // 0x58 ConVarHandle* m_pHandle; // 0x60 ConVarBaseData_t** m_pConVarData; // 0x68 }; - static_assert(sizeof(ConVarCreation_t) == 0x70, "ConVarCreation_t wrong size!"); static_assert(sizeof(ConVarCreation_t) % 8 == 0x0, "ConVarCreation_t isn't 8 bytes aligned!"); static_assert(sizeof(CVValue_t) == 0x10, "CVValue_t wrong size!"); @@ -431,7 +412,7 @@ class ConVar : public BaseConVar { this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); - ConVarSetup_t setup; + ConVarCreation_t setup; setup.m_valueInfo.m_bHasDefault = true; setup.m_valueInfo.m_defaultValue = value; setup.m_eVarType = TranslateConVarType(); @@ -444,7 +425,7 @@ class ConVar : public BaseConVar { this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); - ConVarSetup_t setup; + ConVarCreation_t setup; setup.m_valueInfo.m_bHasDefault = true; setup.m_valueInfo.m_defaultValue = value; @@ -503,7 +484,7 @@ class ConVar : public BaseConVar this->m_Handle = defaultHandle; } - void Register(const char* name, int32_t flags, const char* description, const ConVarSetup_t& setup) + void Register(const char* name, int32_t flags, const char* description, ConVarCreation_t& cvar) { this->m_ConVarData = ConVar_Invalid(); this->m_Handle.Invalidate(); @@ -521,14 +502,10 @@ class ConVar : public BaseConVar flags |= FCVAR_DEVELOPMENTONLY; } - ConVarCreation_t cvar; - cvar.m_pszName = name; cvar.m_pszHelpString = description; cvar.m_nFlags = flags; - cvar.m_cvarSetup = setup; - cvar.m_pHandle = &this->m_Handle; cvar.m_pConVarData = (ConVarBaseData_t**)&this->m_ConVarData; From 5d63cc8a0285b9fec81ae1184d45c7c29378a713 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 16:20:14 +0200 Subject: [PATCH 27/48] remove padding --- public/tier1/convar.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 6933bda25..833495443 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -355,9 +355,7 @@ struct ConVarCreation_t : CVarCreationBase_t { m_pHandle(nullptr), m_pConVarData(nullptr) {} - - int32_t m_unknown1; // 0x18 - + #pragma pack(push,1) struct ConVarValueInfo_t { From 960ccb09d1c02fe34c8d50c31544d58162df1392 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 16:31:23 +0200 Subject: [PATCH 28/48] add back unknown --- public/tier1/convar.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 833495443..f7c79b786 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -355,6 +355,8 @@ struct ConVarCreation_t : CVarCreationBase_t { m_pHandle(nullptr), m_pConVarData(nullptr) {} + + int32_t m_unknown1; #pragma pack(push,1) struct ConVarValueInfo_t From 47f939d0ce807b6003a81f8c90ae38fc96b34fba Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 23:07:32 +0200 Subject: [PATCH 29/48] finish templating --- public/icvar.h | 201 ++++++++++++++++++++++++++++++++++++------ public/tier1/convar.h | 81 +++++++++++++---- 2 files changed, 239 insertions(+), 43 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index a782eebfb..2e783e930 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -37,7 +37,7 @@ union CVValue_t CVValue_t& operator=(CVValue_t other) { memcpy(this, &other, sizeof(*this)); return *this; } template - inline CVValue_t& operator=(T other); + inline CVValue_t& operator=(const T& other); inline operator bool() const { return m_bValue; } inline operator int16_t() const { return m_i16Value; } @@ -74,24 +74,28 @@ union CVValue_t static_assert(sizeof(float) == sizeof(int32_t), "Wrong float type size for ConVar!"); static_assert(sizeof(double) == sizeof(int64_t), "Wrong double type size for ConVar!"); -template<> inline CVValue_t& CVValue_t::operator=( const bool other ) { m_bValue = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const int16_t other ) { m_i16Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const uint16_t other ) { m_u16Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const int32_t other ) { m_i32Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const uint32_t other ) { m_u32Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const int64_t other ) { m_i64Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const uint64_t other ) { m_u64Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const float other ) { m_flValue = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const double other ) { m_dbValue = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const char* other ) { m_szValue = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const Color& other ) { m_clrValue = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const Vector2D& other ) { m_vec2Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const Vector& other ) { m_vec3Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const Vector4D& other ) { m_vec4Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const QAngle& other ) { m_angValue = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const bool& other ) { m_bValue = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const int16_t& other ) { m_i16Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const uint16_t& other ) { m_u16Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const int32_t& other ) { m_i32Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const uint32_t& other ) { m_u32Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const int64_t& other ) { m_i64Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const uint64_t& other ) { m_u64Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const float& other ) { m_flValue = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const double& other ) { m_dbValue = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const char*const& other ) { m_szValue = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const Color& other ) { m_clrValue = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const Vector2D& other ) { m_vec2Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const Vector& other ) { m_vec3Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const Vector4D& other ) { m_vec4Value = other; return *this; } +template<> inline CVValue_t& CVValue_t::operator=( const QAngle& other ) { m_angValue = other; return *this; } struct CSplitScreenSlot { + CSplitScreenSlot() : + m_Data(0) + {} + CSplitScreenSlot( int index ) { m_Data = index; @@ -101,6 +105,11 @@ struct CSplitScreenSlot { return m_Data; } + + operator int() const + { + return m_Data; + } int m_Data; }; @@ -153,7 +162,7 @@ class ConCommandHandle m_handleIndex = 0x0; } - uint16_t GetConVarIndex() const { return m_concommandIndex; } + uint16_t GetConCommandIndex() const { return m_concommandIndex; } uint32_t GetIndex() const { return m_handleIndex; } private: @@ -166,7 +175,7 @@ static const ConCommandHandle INVALID_CONCOMMAND_HANDLE = ConCommandHandle(); //----------------------------------------------------------------------------- // Purpose: Internal structure of ConVar objects //----------------------------------------------------------------------------- -enum EConVarType : short +enum EConVarType : int16_t { EConVarType_Invalid = -1, EConVarType_Bool, @@ -246,6 +255,10 @@ struct ConVarBaseData_t inline const char* GetDescription( void ) const { return m_pszHelpString; } inline EConVarType GetType( void ) const { return m_eVarType; } + inline bool HasDefaultValue( ) const { return m_defaultValue != nullptr; } + inline bool HasMinValue( ) const { return m_minValue != nullptr; } + inline bool HasMaxValue( ) const { return m_maxValue != nullptr; } + inline int GetTimesChanges( void ) const { return m_iTimesChanged; } inline bool IsFlagSet( int64_t flag ) const { return ( flag & m_nFlags ) ? true : false; } @@ -255,6 +268,12 @@ struct ConVarBaseData_t inline int GetCallbackIndex( void ) const { return m_iCallbackIndex; } protected: + template + static inline void ValueToString( const T& val, char* dst, size_t length ); + + template + static T ValueFromString( const char* val ); + const char* m_pszName; void* m_defaultValue; @@ -279,12 +298,48 @@ struct ConVarBaseData_t int m_nUnknownAllocFlags; }; +template<> inline void ConVarBaseData_t::ValueToString( const bool& val, char* dst, size_t length ) +{ + const char* src = ( val ) ? "true" : "false"; + memcpy( dst, src, length ); +} +template<> inline void ConVarBaseData_t::ValueToString( const uint16_t& val, char* dst, size_t length ) { snprintf( dst, length, "%u", val ); } +template<> inline void ConVarBaseData_t::ValueToString( const int16_t& val, char* dst, size_t length ) { snprintf( dst, length, "%d", val ); } +template<> inline void ConVarBaseData_t::ValueToString( const uint32_t& val, char* dst, size_t length ) { snprintf( dst, length, "%u", val ); } +template<> inline void ConVarBaseData_t::ValueToString( const int32_t& val, char* dst, size_t length ) { snprintf( dst, length, "%d", val ); } +template<> inline void ConVarBaseData_t::ValueToString( const uint64_t& val, char* dst, size_t length ) { snprintf( dst, length, "%lu", val ); } +template<> inline void ConVarBaseData_t::ValueToString( const int64_t& val, char* dst, size_t length ) { snprintf( dst, length, "%ld", val ); } +template<> inline void ConVarBaseData_t::ValueToString( const float& val, char* dst, size_t length ) { snprintf( dst, length, "%f", val ); } +template<> inline void ConVarBaseData_t::ValueToString( const double& val, char* dst, size_t length ) { snprintf( dst, length, "%lf", val ); } +template<> inline void ConVarBaseData_t::ValueToString( const char*const& val, char* dst, size_t length ) { memcpy( dst, val, length ); } +template<> inline void ConVarBaseData_t::ValueToString( const Color& val, char* dst, size_t length ) { snprintf( dst, length, "%d %d %d %d", val.r(), val.g(), val.b(), val.a() ); } +template<> inline void ConVarBaseData_t::ValueToString( const Vector2D& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f", val.x, val.y ); } +template<> inline void ConVarBaseData_t::ValueToString( const Vector& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f %f", val.x, val.y, val.z ); } +template<> inline void ConVarBaseData_t::ValueToString( const Vector4D& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f %f %f", val.x, val.y, val.z, val.w ); } +template<> inline void ConVarBaseData_t::ValueToString( const QAngle& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f %f", val.x, val.y, val.z ); } + +template<> inline bool ConVarBaseData_t::ValueFromString( const char* val ) { if (strcmp(val, "true") == 0 || strcmp(val, "1") == 0) { return true; } return false; } +template<> inline uint16_t ConVarBaseData_t::ValueFromString( const char* val ) { unsigned int ret; sscanf(val, "%u", &ret); return ret; } +template<> inline int16_t ConVarBaseData_t::ValueFromString( const char* val ) { int ret; sscanf(val, "%d", &ret); return ret; } +template<> inline uint32_t ConVarBaseData_t::ValueFromString( const char* val ) { uint32_t ret; sscanf(val, "%u", &ret); return ret; } +template<> inline int32_t ConVarBaseData_t::ValueFromString( const char* val ) { int32_t ret; sscanf(val, "%d", &ret); return ret; } +template<> inline uint64_t ConVarBaseData_t::ValueFromString( const char* val ) { uint64_t ret; sscanf(val, "%lu", &ret); return ret; } +template<> inline int64_t ConVarBaseData_t::ValueFromString( const char* val ) { int64_t ret; sscanf(val, "%ld", &ret); return ret; } +template<> inline float ConVarBaseData_t::ValueFromString( const char* val ) { float ret; sscanf(val, "%f", &ret); return ret; } +template<> inline double ConVarBaseData_t::ValueFromString( const char* val ) { double ret; sscanf(val, "%lf", &ret); return ret; } +template<> inline const char* ConVarBaseData_t::ValueFromString( const char* val ) { return val; } +template<> inline Color ConVarBaseData_t::ValueFromString( const char* val ) { int r, g, b, a; sscanf(val, "%d %d %d %d", &r, &g, &b, &a); return Color(r, g, b, a); } +template<> inline Vector2D ConVarBaseData_t::ValueFromString( const char* val ) { float x, y; sscanf(val, "%f %f", &x, &y); return Vector2D(x, y); } +template<> inline Vector ConVarBaseData_t::ValueFromString( const char* val ) { float x, y, z; sscanf(val, "%f %f %f", &x, &y, &z); return Vector(x, y, z); } +template<> inline Vector4D ConVarBaseData_t::ValueFromString( const char* val ) { float x, y, z, w; sscanf(val, "%f %f %f %f", &x, &y, &z, &w); return Vector4D(x, y, z, w); } +template<> inline QAngle ConVarBaseData_t::ValueFromString( const char* val ) { float x, y, z; sscanf(val, "%f %f %f", &x, &y, &z); return QAngle(x, y, z); } + template struct ConVarData_t : ConVarBaseData_t { public: friend class ConVar; - ConVarData_t() + constexpr ConVarData_t() { m_defaultValue = new T(); m_minValue = new T(); @@ -303,16 +358,110 @@ friend class ConVar; inline const T& GetMinValue( ) const { return *reinterpret_cast(m_minValue); } inline const T& GetMaxValue( ) const { return *reinterpret_cast(m_maxValue); } - inline void SetDefaultValue(const T& value) { *reinterpret_cast(m_defaultValue) = value; } - inline void SetMinValue(const T& value) { *reinterpret_cast(m_minValue) = value; } - inline void SetMaxValue(const T& value) { *reinterpret_cast(m_maxValue) = value; } + inline void SetDefaultValue(const T& value) + { + if (!m_defaultValue) + { + m_defaultValue = new T(); + } + *reinterpret_cast(m_defaultValue) = value; + } + inline void SetMinValue(const T& value) + { + if (!m_minValue) + { + m_minValue = new T(); + } + *reinterpret_cast(m_minValue) = value; + } + inline void SetMaxValue(const T& value) + { + if (!m_maxValue) + { + m_maxValue = new T(); + } + *reinterpret_cast(m_maxValue) = value; + } + + inline void RemoveDefaultValue( ) + { + if (m_defaultValue) + { + delete reinterpret_cast(m_defaultValue); + } + m_defaultValue = nullptr; + } + inline void RemoveMinValue( ) + { + if (m_minValue) + { + delete reinterpret_cast(m_minValue); + } + m_minValue = nullptr; + } + inline void RemoveMaxValue( ) + { + if (m_maxValue) + { + delete reinterpret_cast(m_maxValue); + } + m_maxValue = nullptr; + } + + inline const T& Clamp(const T& value) const + { + if (HasMinValue() && value < GetMinValue()) + { + return GetMinValue(); + } + if (HasMaxValue() && value > GetMaxValue()) + { + return GetMaxValue(); + } + return value; + } + + inline const T& GetValue( const CSplitScreenSlot& index = 0 ) const { return m_value[index]; } + inline void SetValue(const T& value, const CSplitScreenSlot& index = 0) { m_value[index] = value; } + + inline void GetStringValue( char* dst, size_t len, const CSplitScreenSlot& index = 0 ) const { ValueToString( GetValue( index ), dst, len ); } + + inline void GetStringDefaultValue( char* dst, size_t len ) const { ValueToString( GetDefaultValue( ), dst, len ); } + inline void GetStringMinValue( char* dst, size_t len ) const { ValueToString( GetMaxValue( ), dst, len ); } + inline void GetStringMaxValue( char* dst, size_t len ) const { ValueToString( GetValue( index ), dst, len ); } + + inline void SetStringValue( const char* src, const CSplitScreenSlot& index = 0 ) const { SetValue( ValueFromString( src ), index ); } - inline const T& GetValue( int index = 0 ) const { return m_value[index]; } - inline void SetValue(const T& value, int index = 0) { m_value[index] = value; } + inline void SetStringDefaultValue( const char* src ) const { SetDefaultValue( ValueFromString( src ) ); } + inline void SetStringMinValue( const char* src ) const { SetMinValue( ValueFromString( src ) ); } + inline void SetStringMaxValue( const char* src ) const { SetMaxValue( ValueFromString( src ) ); } + +protected: + static inline void ValueToString( const T& value, char* dst, size_t length ) { ConVarBaseData_t::ValueToString( value, dst, length ); }; + + static T ValueFromString( const char* val ) { return ConVarBaseData_t::ValueFromString( val ); }; T m_value[MAX_SPLITSCREEN_CLIENTS]; }; +// Special case for string handling +template<> inline void ConVarData_t::SetValue(const char*const& value, const CSplitScreenSlot& index) +{ + char* data = new char[256]; + memcpy(data, value, 256); + + delete[] m_value[index]; + m_value[index] = data; +} + +// For some types it makes no sense to clamp +template<> inline const char*const& ConVarData_t::Clamp(const char*const& value) const { return value; } +template<> inline const Color& ConVarData_t::Clamp(const Color& value) const { return value; } +template<> inline const Vector2D& ConVarData_t::Clamp(const Vector2D& value) const { return value; } +template<> inline const Vector& ConVarData_t::Clamp(const Vector& value) const { return value; } +template<> inline const Vector4D& ConVarData_t::Clamp(const Vector4D& value) const { return value; } +template<> inline const QAngle& ConVarData_t::Clamp(const QAngle& value) const { return value; } + //----------------------------------------------------------------------------- // Purpose: DLL interface to ConVars/ConCommands //----------------------------------------------------------------------------- @@ -323,7 +472,7 @@ abstract_class ICvar : public IAppSystem virtual ConVarHandle FindConVar( const char *name, bool bAllowDeveloper = false ) = 0; virtual ConVarHandle FindFirstConVar() = 0; virtual ConVarHandle FindNextConVar( ConVarHandle prev ) = 0; - virtual void SetConVarValue( ConVarHandle cvarid, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue ) = 0; + virtual void CallChangeCallback( ConVarHandle cvarid, const CSplitScreenSlot nSlot, const CVValue_t* pNewValue, const CVValue_t* pOldValue ) = 0; virtual ConCommandHandle FindCommand( const char *name ) = 0; virtual ConCommandHandle FindFirstCommand() = 0; @@ -333,7 +482,7 @@ abstract_class ICvar : public IAppSystem // Install a global change callback (to be called when any convar changes) virtual void InstallGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; virtual void RemoveGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; - virtual void CallGlobalChangeCallbacks( BaseConVar* ref, CSplitScreenSlot nSlot, const char *pOldString, float flOldValue ) = 0; + virtual void CallGlobalChangeCallbacks( BaseConVar* ref, CSplitScreenSlot nSlot, const char* newValue, char* oldValue ) = 0; // Reverts cvars which contain a specific flag virtual void RevertFlaggedConVars( int nFlag ) = 0; diff --git a/public/tier1/convar.h b/public/tier1/convar.h index f7c79b786..c94ebbe38 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -25,6 +25,7 @@ #include "playerslot.h" #include +#include #ifdef _WIN32 #define FORCEINLINE_CVAR FORCEINLINE @@ -355,8 +356,6 @@ struct ConVarCreation_t : CVarCreationBase_t { m_pHandle(nullptr), m_pConVarData(nullptr) {} - - int32_t m_unknown1; #pragma pack(push,1) struct ConVarValueInfo_t @@ -367,6 +366,8 @@ struct ConVarCreation_t : CVarCreationBase_t { m_bHasMax(false) {} + int32_t m_unknown1; // 0x18 + bool m_bHasDefault; // 0x22 bool m_bHasMin; // 0x23 bool m_bHasMax; // 0x24 @@ -390,7 +391,7 @@ static_assert(sizeof(CVValue_t) == 0x10, "CVValue_t wrong size!"); extern void* invalid_convar[EConVarType_MAX + 1]; template -ConVarData_t* ConVar_Invalid() +ConVarData_t* GetInvalidConVar() { return (ConVarData_t*)&invalid_convar[TranslateConVarType()]; } @@ -406,9 +407,9 @@ template class ConVar : public BaseConVar { public: - using FnChangeCallback_t = void(*)(ConVar* ref, CSplitScreenSlot nSlot, T* pNewValue, T* pOldValue); + using FnChangeCallback_t = void(*)(ConVar* ref, const CSplitScreenSlot nSlot, const T* pNewValue, const T* pOldValue); - ConVar(const char* name, int32_t flags, const char* description, T value, FnChangeCallback_t cb = nullptr) + ConVar(const char* name, int32_t flags, const char* description, const T& value, FnChangeCallback_t cb = nullptr) { this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); @@ -421,7 +422,7 @@ class ConVar : public BaseConVar this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); } - ConVar(const char* name, int32_t flags, const char* description, T value, bool min, T minValue, bool max, T maxValue, FnChangeCallback_t cb = nullptr) + ConVar(const char* name, int32_t flags, const char* description, const T& value, bool min, const T& minValue, bool max, const T& maxValue, FnChangeCallback_t cb = nullptr) { this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); @@ -449,16 +450,46 @@ class ConVar : public BaseConVar inline const char* GetDescription( ) const { return m_ConVarData->GetDescription( ); } inline EConVarType GetType( ) const { return m_ConVarData->GetType( ); } - inline CVValue_t* GetDefaultValue( ) const { return m_ConVarData->GetDefaultValue( ); } - inline CVValue_t* GetMinValue( ) const { return m_ConVarData->GetMinValue( ); } - inline CVValue_t* GetMaxValue( ) const { return m_ConVarData->GetMaxValue( ); } + inline bool HasDefaultValue( ) const { return m_ConVarData->HasDefaultValue( ); } + inline bool HasMinValue( ) const { return m_ConVarData->HasMinValue( ); } + inline bool HasMaxValue( ) const { return m_ConVarData->HasMaxValue( ); } + + inline const T& GetDefaultValue( ) const { return m_ConVarData->GetDefaultValue( ); } + inline const T& GetMinValue( ) const { return m_ConVarData->GetMinValue( ); } + inline const T& GetMaxValue( ) const { return m_ConVarData->GetMaxValue( ); } + + inline void SetDefaultValue( const T& value ) { m_ConVarData->SetDefaultValue( value ); } + inline void SetMinValue( const T& value ) { m_ConVarData->SetMinValue( value ); } + inline void SetMaxValue( const T& value ) { m_ConVarData->SetMaxValue( value ); } + + inline void RemoveDefaultValue( ) { m_ConVarData->RemoveDefaultValue( ); } + inline void RemoveMinValue( ) { m_ConVarData->RemoveMinValue( ); } + inline void RemoveMaxValue( ) { m_ConVarData->RemoveMaxValue( ); } - inline void SetDefaultValue(const T& value) { m_ConVarData->SetDefaultValue( value ); } - inline void SetMinValue(const T& value) { m_ConVarData->SetMinValue( value ); } - inline void SetMaxValue(const T& value) { m_ConVarData->SetMaxValue( value ); } + inline const T& Clamp(const T& value) const { return m_ConVarData->Clamp( value ); } - inline const T& GetValue( int index = 0 ) const { return m_ConVarData->GetValue( index ); } - inline void SetValue(const T& value, int index = 0) { m_ConVarData->SetValue( value, index ); } + inline const T& GetValue( const CSplitScreenSlot& index = CSplitScreenSlot() ) const { return m_ConVarData->GetValue( index ); } + inline void SetValue( const T& val, const CSplitScreenSlot& index = CSplitScreenSlot() ) + { + auto newValue = this->Clamp( val ); + + char szNewValue[256], szOldValue[256]; + ConVarData_t::ValueToString( newValue, szNewValue, sizeof(szNewValue) ); + m_ConVarData->GetStringValue( szOldValue, sizeof(szOldValue), index ); + + // Deep copy + T oldValue = this->GetValue( ); + m_ConVarData->SetValue( newValue, index ); + + g_pCVar->CallChangeCallback( this->m_Handle, index, (const CVValue_t*)&newValue, (const CVValue_t*)&oldValue ); + g_pCVar->CallGlobalChangeCallbacks( this, index, szNewValue, szOldValue ); + } + + inline void GetStringValue( char* dst, size_t len, const CSplitScreenSlot& index = 0 ) const { m_ConVarData->GetStringValue( dst, len, index ); } + + inline void GetStringDefaultValue( char* dst, size_t len ) const { m_ConVarData->GetStringDefaultValue( dst, len ); } + inline void GetStringMinValue( char* dst, size_t len ) const { m_ConVarData->GetStringMinValue( dst, len ); } + inline void GetStringMaxValue( char* dst, size_t len ) const { m_ConVarData->GetStringMaxValue( dst, len ); } inline bool IsFlagSet( int64_t flag ) const { return m_ConVarData->IsFlagSet( flag ); } inline void AddFlags( int64_t flags ) { m_ConVarData->AddFlags( flags ); } @@ -473,10 +504,11 @@ class ConVar : public BaseConVar if (g_pCVar) { - this->m_ConVarData = g_pCVar->GetConVar(defaultHandle)->Cast(); + auto cvar = g_pCVar->GetConVar(defaultHandle); + this->m_ConVarData = (cvar) ? g_pCVar->GetConVar(defaultHandle)->Cast() : nullptr; if (!this->m_ConVarData) { - this->m_ConVarData = ConVar_Invalid(); + this->m_ConVarData = GetInvalidConVar(); } // technically this //result = *(char ***)(sub_10B7760((unsigned int)a3) + 80); @@ -486,7 +518,7 @@ class ConVar : public BaseConVar void Register(const char* name, int32_t flags, const char* description, ConVarCreation_t& cvar) { - this->m_ConVarData = ConVar_Invalid(); + this->m_ConVarData = GetInvalidConVar(); this->m_Handle.Invalidate(); if (!CommandLine()->HasParm("-tools") @@ -519,6 +551,21 @@ class ConVar : public BaseConVar static_assert(sizeof(ConVar) == 0x10, "ConVar is of the wrong size!"); static_assert(sizeof(ConVar) == sizeof(ConVar), "Templated ConVar size varies!"); +// Special case for string +template<> inline void ConVar::SetValue( const char*const& val, const CSplitScreenSlot& index ) +{ + auto newValue = this->Clamp( val ); + + char szNewValue[256], szOldValue[256]; + ConVarData_t::ValueToString( newValue, szNewValue, sizeof(szNewValue) ); + m_ConVarData->GetStringValue( szOldValue, sizeof(szOldValue), index ); + + m_ConVarData->SetValue( newValue, index ); + + g_pCVar->CallChangeCallback( this->m_Handle, index, (const CVValue_t*)&newValue, (const CVValue_t*)&szOldValue ); + g_pCVar->CallGlobalChangeCallbacks( this, index, szNewValue, szOldValue ); +} + //----------------------------------------------------------------------------- #ifdef CONVAR_WORK_FINISHED From 5c806c8fddba70dd868e947259343d1e298c71b2 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 8 Oct 2023 23:10:11 +0200 Subject: [PATCH 30/48] fix wrong ret value --- public/icvar.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/icvar.h b/public/icvar.h index 2e783e930..d78bb8de9 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -162,7 +162,7 @@ class ConCommandHandle m_handleIndex = 0x0; } - uint16_t GetConCommandIndex() const { return m_concommandIndex; } + uint32_t GetConCommandIndex() const { return m_concommandIndex; } uint32_t GetIndex() const { return m_handleIndex; } private: From adb77b91ad000f8af608d7f9065b6aeb181105a2 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Mon, 9 Oct 2023 19:12:08 +0200 Subject: [PATCH 31/48] review changes --- public/icvar.h | 127 +++++++++++++++------------------- public/tier1/convar.h | 156 +++++++++++++++++++++++++----------------- tier1/convar.cpp | 19 ----- 3 files changed, 149 insertions(+), 153 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index d78bb8de9..6ed53b7c3 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -16,7 +16,7 @@ #include "mathlib/vector4d.h" #include -class BaseConVar {}; +class BaseConVar; class ConCommand; class CCommand; class CCommandContext; @@ -32,10 +32,6 @@ class ConVar; union CVValue_t { - CVValue_t() { memset(this, 0, sizeof(*this)); } - CVValue_t(CVValue_t const& cp) { memcpy(this, &cp, sizeof(*this)); }; - CVValue_t& operator=(CVValue_t other) { memcpy(this, &other, sizeof(*this)); return *this; } - template inline CVValue_t& operator=(const T& other); @@ -74,22 +70,6 @@ union CVValue_t static_assert(sizeof(float) == sizeof(int32_t), "Wrong float type size for ConVar!"); static_assert(sizeof(double) == sizeof(int64_t), "Wrong double type size for ConVar!"); -template<> inline CVValue_t& CVValue_t::operator=( const bool& other ) { m_bValue = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const int16_t& other ) { m_i16Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const uint16_t& other ) { m_u16Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const int32_t& other ) { m_i32Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const uint32_t& other ) { m_u32Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const int64_t& other ) { m_i64Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const uint64_t& other ) { m_u64Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const float& other ) { m_flValue = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const double& other ) { m_dbValue = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const char*const& other ) { m_szValue = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const Color& other ) { m_clrValue = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const Vector2D& other ) { m_vec2Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const Vector& other ) { m_vec3Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const Vector4D& other ) { m_vec4Value = other; return *this; } -template<> inline CVValue_t& CVValue_t::operator=( const QAngle& other ) { m_angValue = other; return *this; } - struct CSplitScreenSlot { CSplitScreenSlot() : @@ -217,31 +197,32 @@ template<> constexpr EConVarType TranslateConVarType( void ) { return EC template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Invalid; } template -struct ConVarData_t; +class CConVarData; -struct ConVarBaseData_t +class CConVarBaseData { +public: template - inline const ConVarData_t* Cast() const + inline const CConVarData* Cast() const { if (this->m_eVarType == TranslateConVarType()) { - return reinterpret_cast*>(this); + return reinterpret_cast*>(this); } return nullptr; } template - inline ConVarData_t* Cast() + inline CConVarData* Cast() { if (this->m_eVarType == TranslateConVarType()) { - return reinterpret_cast*>(this); + return reinterpret_cast*>(this); } return nullptr; } - ConVarBaseData_t() : + CConVarBaseData() : m_pszName(""), m_defaultValue(nullptr), m_minValue(nullptr), @@ -298,48 +279,48 @@ struct ConVarBaseData_t int m_nUnknownAllocFlags; }; -template<> inline void ConVarBaseData_t::ValueToString( const bool& val, char* dst, size_t length ) +template<> inline void CConVarBaseData::ValueToString( const bool& val, char* dst, size_t length ) { const char* src = ( val ) ? "true" : "false"; memcpy( dst, src, length ); } -template<> inline void ConVarBaseData_t::ValueToString( const uint16_t& val, char* dst, size_t length ) { snprintf( dst, length, "%u", val ); } -template<> inline void ConVarBaseData_t::ValueToString( const int16_t& val, char* dst, size_t length ) { snprintf( dst, length, "%d", val ); } -template<> inline void ConVarBaseData_t::ValueToString( const uint32_t& val, char* dst, size_t length ) { snprintf( dst, length, "%u", val ); } -template<> inline void ConVarBaseData_t::ValueToString( const int32_t& val, char* dst, size_t length ) { snprintf( dst, length, "%d", val ); } -template<> inline void ConVarBaseData_t::ValueToString( const uint64_t& val, char* dst, size_t length ) { snprintf( dst, length, "%lu", val ); } -template<> inline void ConVarBaseData_t::ValueToString( const int64_t& val, char* dst, size_t length ) { snprintf( dst, length, "%ld", val ); } -template<> inline void ConVarBaseData_t::ValueToString( const float& val, char* dst, size_t length ) { snprintf( dst, length, "%f", val ); } -template<> inline void ConVarBaseData_t::ValueToString( const double& val, char* dst, size_t length ) { snprintf( dst, length, "%lf", val ); } -template<> inline void ConVarBaseData_t::ValueToString( const char*const& val, char* dst, size_t length ) { memcpy( dst, val, length ); } -template<> inline void ConVarBaseData_t::ValueToString( const Color& val, char* dst, size_t length ) { snprintf( dst, length, "%d %d %d %d", val.r(), val.g(), val.b(), val.a() ); } -template<> inline void ConVarBaseData_t::ValueToString( const Vector2D& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f", val.x, val.y ); } -template<> inline void ConVarBaseData_t::ValueToString( const Vector& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f %f", val.x, val.y, val.z ); } -template<> inline void ConVarBaseData_t::ValueToString( const Vector4D& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f %f %f", val.x, val.y, val.z, val.w ); } -template<> inline void ConVarBaseData_t::ValueToString( const QAngle& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f %f", val.x, val.y, val.z ); } - -template<> inline bool ConVarBaseData_t::ValueFromString( const char* val ) { if (strcmp(val, "true") == 0 || strcmp(val, "1") == 0) { return true; } return false; } -template<> inline uint16_t ConVarBaseData_t::ValueFromString( const char* val ) { unsigned int ret; sscanf(val, "%u", &ret); return ret; } -template<> inline int16_t ConVarBaseData_t::ValueFromString( const char* val ) { int ret; sscanf(val, "%d", &ret); return ret; } -template<> inline uint32_t ConVarBaseData_t::ValueFromString( const char* val ) { uint32_t ret; sscanf(val, "%u", &ret); return ret; } -template<> inline int32_t ConVarBaseData_t::ValueFromString( const char* val ) { int32_t ret; sscanf(val, "%d", &ret); return ret; } -template<> inline uint64_t ConVarBaseData_t::ValueFromString( const char* val ) { uint64_t ret; sscanf(val, "%lu", &ret); return ret; } -template<> inline int64_t ConVarBaseData_t::ValueFromString( const char* val ) { int64_t ret; sscanf(val, "%ld", &ret); return ret; } -template<> inline float ConVarBaseData_t::ValueFromString( const char* val ) { float ret; sscanf(val, "%f", &ret); return ret; } -template<> inline double ConVarBaseData_t::ValueFromString( const char* val ) { double ret; sscanf(val, "%lf", &ret); return ret; } -template<> inline const char* ConVarBaseData_t::ValueFromString( const char* val ) { return val; } -template<> inline Color ConVarBaseData_t::ValueFromString( const char* val ) { int r, g, b, a; sscanf(val, "%d %d %d %d", &r, &g, &b, &a); return Color(r, g, b, a); } -template<> inline Vector2D ConVarBaseData_t::ValueFromString( const char* val ) { float x, y; sscanf(val, "%f %f", &x, &y); return Vector2D(x, y); } -template<> inline Vector ConVarBaseData_t::ValueFromString( const char* val ) { float x, y, z; sscanf(val, "%f %f %f", &x, &y, &z); return Vector(x, y, z); } -template<> inline Vector4D ConVarBaseData_t::ValueFromString( const char* val ) { float x, y, z, w; sscanf(val, "%f %f %f %f", &x, &y, &z, &w); return Vector4D(x, y, z, w); } -template<> inline QAngle ConVarBaseData_t::ValueFromString( const char* val ) { float x, y, z; sscanf(val, "%f %f %f", &x, &y, &z); return QAngle(x, y, z); } +template<> inline void CConVarBaseData::ValueToString( const uint16_t& val, char* dst, size_t length ) { snprintf( dst, length, "%u", val ); } +template<> inline void CConVarBaseData::ValueToString( const int16_t& val, char* dst, size_t length ) { snprintf( dst, length, "%d", val ); } +template<> inline void CConVarBaseData::ValueToString( const uint32_t& val, char* dst, size_t length ) { snprintf( dst, length, "%u", val ); } +template<> inline void CConVarBaseData::ValueToString( const int32_t& val, char* dst, size_t length ) { snprintf( dst, length, "%d", val ); } +template<> inline void CConVarBaseData::ValueToString( const uint64_t& val, char* dst, size_t length ) { snprintf( dst, length, "%lu", val ); } +template<> inline void CConVarBaseData::ValueToString( const int64_t& val, char* dst, size_t length ) { snprintf( dst, length, "%ld", val ); } +template<> inline void CConVarBaseData::ValueToString( const float& val, char* dst, size_t length ) { snprintf( dst, length, "%f", val ); } +template<> inline void CConVarBaseData::ValueToString( const double& val, char* dst, size_t length ) { snprintf( dst, length, "%lf", val ); } +template<> inline void CConVarBaseData::ValueToString( const char*const& val, char* dst, size_t length ) { memcpy( dst, val, length ); } +template<> inline void CConVarBaseData::ValueToString( const Color& val, char* dst, size_t length ) { snprintf( dst, length, "%d %d %d %d", val.r(), val.g(), val.b(), val.a() ); } +template<> inline void CConVarBaseData::ValueToString( const Vector2D& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f", val.x, val.y ); } +template<> inline void CConVarBaseData::ValueToString( const Vector& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f %f", val.x, val.y, val.z ); } +template<> inline void CConVarBaseData::ValueToString( const Vector4D& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f %f %f", val.x, val.y, val.z, val.w ); } +template<> inline void CConVarBaseData::ValueToString( const QAngle& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f %f", val.x, val.y, val.z ); } + +template<> inline bool CConVarBaseData::ValueFromString( const char* val ) { if (strcmp(val, "true") == 0 || strcmp(val, "1") == 0) { return true; } return false; } +template<> inline uint16_t CConVarBaseData::ValueFromString( const char* val ) { unsigned int ret; sscanf(val, "%u", &ret); return ret; } +template<> inline int16_t CConVarBaseData::ValueFromString( const char* val ) { int ret; sscanf(val, "%d", &ret); return ret; } +template<> inline uint32_t CConVarBaseData::ValueFromString( const char* val ) { uint32_t ret; sscanf(val, "%u", &ret); return ret; } +template<> inline int32_t CConVarBaseData::ValueFromString( const char* val ) { int32_t ret; sscanf(val, "%d", &ret); return ret; } +template<> inline uint64_t CConVarBaseData::ValueFromString( const char* val ) { uint64_t ret; sscanf(val, "%lu", &ret); return ret; } +template<> inline int64_t CConVarBaseData::ValueFromString( const char* val ) { int64_t ret; sscanf(val, "%ld", &ret); return ret; } +template<> inline float CConVarBaseData::ValueFromString( const char* val ) { float ret; sscanf(val, "%f", &ret); return ret; } +template<> inline double CConVarBaseData::ValueFromString( const char* val ) { double ret; sscanf(val, "%lf", &ret); return ret; } +template<> inline const char* CConVarBaseData::ValueFromString( const char* val ) { return val; } +template<> inline Color CConVarBaseData::ValueFromString( const char* val ) { int r, g, b, a; sscanf(val, "%d %d %d %d", &r, &g, &b, &a); return Color(r, g, b, a); } +template<> inline Vector2D CConVarBaseData::ValueFromString( const char* val ) { float x, y; sscanf(val, "%f %f", &x, &y); return Vector2D(x, y); } +template<> inline Vector CConVarBaseData::ValueFromString( const char* val ) { float x, y, z; sscanf(val, "%f %f %f", &x, &y, &z); return Vector(x, y, z); } +template<> inline Vector4D CConVarBaseData::ValueFromString( const char* val ) { float x, y, z, w; sscanf(val, "%f %f %f %f", &x, &y, &z, &w); return Vector4D(x, y, z, w); } +template<> inline QAngle CConVarBaseData::ValueFromString( const char* val ) { float x, y, z; sscanf(val, "%f %f %f", &x, &y, &z); return QAngle(x, y, z); } template -struct ConVarData_t : ConVarBaseData_t +class CConVarData : public CConVarBaseData { public: friend class ConVar; - constexpr ConVarData_t() + constexpr CConVarData() { m_defaultValue = new T(); m_minValue = new T(); @@ -347,7 +328,7 @@ friend class ConVar; m_eVarType = TranslateConVarType(); } - ~ConVarData_t() + ~CConVarData() { delete m_defaultValue; delete m_minValue; @@ -437,15 +418,15 @@ friend class ConVar; inline void SetStringMaxValue( const char* src ) const { SetMaxValue( ValueFromString( src ) ); } protected: - static inline void ValueToString( const T& value, char* dst, size_t length ) { ConVarBaseData_t::ValueToString( value, dst, length ); }; + static inline void ValueToString( const T& value, char* dst, size_t length ) { CConVarBaseData::ValueToString( value, dst, length ); }; - static T ValueFromString( const char* val ) { return ConVarBaseData_t::ValueFromString( val ); }; + static T ValueFromString( const char* val ) { return CConVarBaseData::ValueFromString( val ); }; T m_value[MAX_SPLITSCREEN_CLIENTS]; }; // Special case for string handling -template<> inline void ConVarData_t::SetValue(const char*const& value, const CSplitScreenSlot& index) +template<> inline void CConVarData::SetValue(const char*const& value, const CSplitScreenSlot& index) { char* data = new char[256]; memcpy(data, value, 256); @@ -455,12 +436,12 @@ template<> inline void ConVarData_t::SetValue(const char*const& val } // For some types it makes no sense to clamp -template<> inline const char*const& ConVarData_t::Clamp(const char*const& value) const { return value; } -template<> inline const Color& ConVarData_t::Clamp(const Color& value) const { return value; } -template<> inline const Vector2D& ConVarData_t::Clamp(const Vector2D& value) const { return value; } -template<> inline const Vector& ConVarData_t::Clamp(const Vector& value) const { return value; } -template<> inline const Vector4D& ConVarData_t::Clamp(const Vector4D& value) const { return value; } -template<> inline const QAngle& ConVarData_t::Clamp(const QAngle& value) const { return value; } +template<> inline const char*const& CConVarData::Clamp(const char*const& value) const { return value; } +template<> inline const Color& CConVarData::Clamp(const Color& value) const { return value; } +template<> inline const Vector2D& CConVarData::Clamp(const Vector2D& value) const { return value; } +template<> inline const Vector& CConVarData::Clamp(const Vector& value) const { return value; } +template<> inline const Vector4D& CConVarData::Clamp(const Vector4D& value) const { return value; } +template<> inline const QAngle& CConVarData::Clamp(const QAngle& value) const { return value; } //----------------------------------------------------------------------------- // Purpose: DLL interface to ConVars/ConCommands @@ -506,9 +487,9 @@ abstract_class ICvar : public IAppSystem virtual void unk2() = 0; // Register, unregister vars - virtual void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, ConVarBaseData_t** pCvar ) = 0; + virtual void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, CConVarBaseData** pCvar ) = 0; virtual void UnregisterConVar( ConVarHandle handle ) = 0; - virtual ConVarBaseData_t* GetConVar( ConVarHandle handle ) = 0; + virtual CConVarBaseData* GetConVar( ConVarHandle handle ) = 0; // Register, unregister commands virtual ConCommandHandle RegisterConCommand( const ConCommandCreation_t& setup, int64 nAdditionalFlags = 0 ) = 0; diff --git a/public/tier1/convar.h b/public/tier1/convar.h index c94ebbe38..7129b7fc1 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -366,15 +366,23 @@ struct ConVarCreation_t : CVarCreationBase_t { m_bHasMax(false) {} + template + T& DefaultValue() { return *reinterpret_cast(m_defaultValue); } + template + T& MinValue() { return *reinterpret_cast(m_minValue); } + template + T& MaxValue() { return *reinterpret_cast(m_maxValue); } + int32_t m_unknown1; // 0x18 bool m_bHasDefault; // 0x22 bool m_bHasMin; // 0x23 bool m_bHasMax; // 0x24 - - CVValue_t m_defaultValue; // 0x25 - CVValue_t m_minValue; // 0x35 - CVValue_t m_maxValue; // 0x45 + private: + // Don't use CVValue_t directly, to avoid initialising memory + uint8_t m_defaultValue[sizeof(CVValue_t)]; // 0x25 + uint8_t m_minValue[sizeof(CVValue_t)]; // 0x35 + uint8_t m_maxValue[sizeof(CVValue_t)]; // 0x45 } m_valueInfo; // 0x22 #pragma pack(pop) @@ -382,18 +390,38 @@ struct ConVarCreation_t : CVarCreationBase_t { EConVarType m_eVarType; // 0x58 ConVarHandle* m_pHandle; // 0x60 - ConVarBaseData_t** m_pConVarData; // 0x68 + CConVarBaseData** m_pConVarData; // 0x68 }; static_assert(sizeof(ConVarCreation_t) == 0x70, "ConVarCreation_t wrong size!"); static_assert(sizeof(ConVarCreation_t) % 8 == 0x0, "ConVarCreation_t isn't 8 bytes aligned!"); static_assert(sizeof(CVValue_t) == 0x10, "CVValue_t wrong size!"); -extern void* invalid_convar[EConVarType_MAX + 1]; +static CConVarBaseData* GetInvalidConVar( EConVarType type ) +{ + static CConVarBaseData* invalid_convar[EConVarType_MAX + 1] = { + new CConVarData(), + new CConVarData(), + new CConVarData(), + new CConVarData(), + new CConVarData(), + new CConVarData(), + new CConVarData(), + new CConVarData(), + new CConVarData(), + new CConVarData(), + new CConVarData(), + new CConVarData(), + new CConVarData(), + new CConVarData(), + new CConVarData(), + new CConVarData() // EConVarType_MAX + }; -template -ConVarData_t* GetInvalidConVar() -{ - return (ConVarData_t*)&invalid_convar[TranslateConVarType()]; + if (type == EConVarType_Invalid) + { + return invalid_convar[ EConVarType_MAX ]; + } + return invalid_convar[ type ]; } void SetupConVar( ConVarCreation_t& cvar ); @@ -401,8 +429,29 @@ void UnRegisterConVar( ConVarHandle& cvar ); void RegisterConVar( ConVarCreation_t& cvar ); //----------------------------------------------------------------- -// Used to read/write/create? convars (replaces the FindVar method) +// Used to read/write/create convars (replaces the FindVar method) //----------------------------------------------------------------- +class BaseConVar +{ +public: + inline const char* GetName( ) const { return m_ConVarData->GetName( ); } + inline const char* GetDescription( ) const { return m_ConVarData->GetDescription( ); } + inline EConVarType GetType( ) const { return m_ConVarData->GetType( ); } + + inline bool HasDefaultValue( ) const { return m_ConVarData->HasDefaultValue( ); } + inline bool HasMinValue( ) const { return m_ConVarData->HasMinValue( ); } + inline bool HasMaxValue( ) const { return m_ConVarData->HasMaxValue( ); } + + inline bool IsFlagSet( int64_t flag ) const { return m_ConVarData->IsFlagSet( flag ); } + inline void AddFlags( int64_t flags ) { m_ConVarData->AddFlags( flags ); } + inline void RemoveFlags( int64_t flags ) { return m_ConVarData->RemoveFlags( flags ); } + inline int64_t GetFlags( void ) const { return m_ConVarData->GetFlags( ); } +protected: + // High-speed method to read convar data + ConVarHandle m_Handle; + CConVarBaseData* m_ConVarData; +}; + template class ConVar : public BaseConVar { @@ -415,7 +464,7 @@ class ConVar : public BaseConVar ConVarCreation_t setup; setup.m_valueInfo.m_bHasDefault = true; - setup.m_valueInfo.m_defaultValue = value; + setup.m_valueInfo.DefaultValue() = value; setup.m_eVarType = TranslateConVarType(); setup.m_fnCallBack = reinterpret_cast(cb); @@ -428,12 +477,12 @@ class ConVar : public BaseConVar ConVarCreation_t setup; setup.m_valueInfo.m_bHasDefault = true; - setup.m_valueInfo.m_defaultValue = value; + setup.m_valueInfo.DefaultValue() = value; setup.m_valueInfo.m_bHasMin = min; setup.m_valueInfo.m_bHasMax = max; - setup.m_valueInfo.m_minValue = minValue; - setup.m_valueInfo.m_maxValue = maxValue; + setup.m_valueInfo.MinValue() = minValue; + setup.m_valueInfo.MaxValue() = maxValue; setup.m_eVarType = TranslateConVarType(); setup.m_fnCallBack = reinterpret_cast(cb); @@ -446,69 +495,58 @@ class ConVar : public BaseConVar UnRegisterConVar(this->m_Handle); } - inline const char* GetName( ) const { return m_ConVarData->GetName( ); } - inline const char* GetDescription( ) const { return m_ConVarData->GetDescription( ); } - inline EConVarType GetType( ) const { return m_ConVarData->GetType( ); } - - inline bool HasDefaultValue( ) const { return m_ConVarData->HasDefaultValue( ); } - inline bool HasMinValue( ) const { return m_ConVarData->HasMinValue( ); } - inline bool HasMaxValue( ) const { return m_ConVarData->HasMaxValue( ); } + inline const CConVarData* GetConVarData() const { return reinterpret_cast*>(m_ConVarData); } + inline CConVarData* GetConVarData() { return reinterpret_cast*>(m_ConVarData); } - inline const T& GetDefaultValue( ) const { return m_ConVarData->GetDefaultValue( ); } - inline const T& GetMinValue( ) const { return m_ConVarData->GetMinValue( ); } - inline const T& GetMaxValue( ) const { return m_ConVarData->GetMaxValue( ); } + inline const T& GetDefaultValue( ) const { return GetConVarData()->GetDefaultValue( ); } + inline const T& GetMinValue( ) const { return GetConVarData()->GetMinValue( ); } + inline const T& GetMaxValue( ) const { return GetConVarData()->GetMaxValue( ); } - inline void SetDefaultValue( const T& value ) { m_ConVarData->SetDefaultValue( value ); } - inline void SetMinValue( const T& value ) { m_ConVarData->SetMinValue( value ); } - inline void SetMaxValue( const T& value ) { m_ConVarData->SetMaxValue( value ); } + inline void SetDefaultValue( const T& value ) { GetConVarData()->SetDefaultValue( value ); } + inline void SetMinValue( const T& value ) { GetConVarData()->SetMinValue( value ); } + inline void SetMaxValue( const T& value ) { GetConVarData()->SetMaxValue( value ); } - inline void RemoveDefaultValue( ) { m_ConVarData->RemoveDefaultValue( ); } - inline void RemoveMinValue( ) { m_ConVarData->RemoveMinValue( ); } - inline void RemoveMaxValue( ) { m_ConVarData->RemoveMaxValue( ); } + inline void RemoveDefaultValue( ) { GetConVarData()->RemoveDefaultValue( ); } + inline void RemoveMinValue( ) { GetConVarData()->RemoveMinValue( ); } + inline void RemoveMaxValue( ) { GetConVarData()->RemoveMaxValue( ); } - inline const T& Clamp(const T& value) const { return m_ConVarData->Clamp( value ); } + inline const T& Clamp(const T& value) const { return GetConVarData()->Clamp( value ); } - inline const T& GetValue( const CSplitScreenSlot& index = CSplitScreenSlot() ) const { return m_ConVarData->GetValue( index ); } + inline const T& GetValue( const CSplitScreenSlot& index = CSplitScreenSlot() ) const { return GetConVarData()->GetValue( index ); } inline void SetValue( const T& val, const CSplitScreenSlot& index = CSplitScreenSlot() ) { auto newValue = this->Clamp( val ); char szNewValue[256], szOldValue[256]; - ConVarData_t::ValueToString( newValue, szNewValue, sizeof(szNewValue) ); - m_ConVarData->GetStringValue( szOldValue, sizeof(szOldValue), index ); + CConVarData::ValueToString( newValue, szNewValue, sizeof(szNewValue) ); + GetConVarData()->GetStringValue( szOldValue, sizeof(szOldValue), index ); // Deep copy T oldValue = this->GetValue( ); - m_ConVarData->SetValue( newValue, index ); + GetConVarData()->SetValue( newValue, index ); g_pCVar->CallChangeCallback( this->m_Handle, index, (const CVValue_t*)&newValue, (const CVValue_t*)&oldValue ); g_pCVar->CallGlobalChangeCallbacks( this, index, szNewValue, szOldValue ); } - inline void GetStringValue( char* dst, size_t len, const CSplitScreenSlot& index = 0 ) const { m_ConVarData->GetStringValue( dst, len, index ); } - - inline void GetStringDefaultValue( char* dst, size_t len ) const { m_ConVarData->GetStringDefaultValue( dst, len ); } - inline void GetStringMinValue( char* dst, size_t len ) const { m_ConVarData->GetStringMinValue( dst, len ); } - inline void GetStringMaxValue( char* dst, size_t len ) const { m_ConVarData->GetStringMaxValue( dst, len ); } - - inline bool IsFlagSet( int64_t flag ) const { return m_ConVarData->IsFlagSet( flag ); } - inline void AddFlags( int64_t flags ) { m_ConVarData->AddFlags( flags ); } - inline void RemoveFlags( int64_t flags ) { return m_ConVarData->RemoveFlags( flags ); } - inline int64_t GetFlags( void ) const { return m_ConVarData->GetFlags( ); } + inline void GetStringValue( char* dst, size_t len, const CSplitScreenSlot& index = 0 ) const { GetConVarData()->GetStringValue( dst, len, index ); } + inline void GetStringDefaultValue( char* dst, size_t len ) const { GetConVarData()->GetStringDefaultValue( dst, len ); } + inline void GetStringMinValue( char* dst, size_t len ) const { GetConVarData()->GetStringMinValue( dst, len ); } + inline void GetStringMaxValue( char* dst, size_t len ) const { GetConVarData()->GetStringMaxValue( dst, len ); } private: void Init(ConVarHandle defaultHandle, EConVarType type) { - this->m_Handle.Invalidate(); + this->m_Handle.Invalidate( ); this->m_ConVarData = nullptr; - if (g_pCVar) + if ( g_pCVar ) { - auto cvar = g_pCVar->GetConVar(defaultHandle); - this->m_ConVarData = (cvar) ? g_pCVar->GetConVar(defaultHandle)->Cast() : nullptr; - if (!this->m_ConVarData) + auto cvar = g_pCVar->GetConVar( defaultHandle ); + this->m_ConVarData = ( cvar && cvar->Cast( ) ) ? cvar : nullptr; + if ( !this->m_ConVarData ) { - this->m_ConVarData = GetInvalidConVar(); + this->m_ConVarData = GetInvalidConVar( TranslateConVarType( ) ); } // technically this //result = *(char ***)(sub_10B7760((unsigned int)a3) + 80); @@ -518,7 +556,7 @@ class ConVar : public BaseConVar void Register(const char* name, int32_t flags, const char* description, ConVarCreation_t& cvar) { - this->m_ConVarData = GetInvalidConVar(); + this->m_ConVarData = GetInvalidConVar( cvar.m_eVarType ); this->m_Handle.Invalidate(); if (!CommandLine()->HasParm("-tools") @@ -539,14 +577,10 @@ class ConVar : public BaseConVar cvar.m_nFlags = flags; cvar.m_pHandle = &this->m_Handle; - cvar.m_pConVarData = (ConVarBaseData_t**)&this->m_ConVarData; + cvar.m_pConVarData = &this->m_ConVarData; SetupConVar(cvar); } - - // High-speed method to read convar data - ConVarHandle m_Handle; - ConVarData_t* m_ConVarData; }; static_assert(sizeof(ConVar) == 0x10, "ConVar is of the wrong size!"); static_assert(sizeof(ConVar) == sizeof(ConVar), "Templated ConVar size varies!"); @@ -557,10 +591,10 @@ template<> inline void ConVar::SetValue( const char*const& val, con auto newValue = this->Clamp( val ); char szNewValue[256], szOldValue[256]; - ConVarData_t::ValueToString( newValue, szNewValue, sizeof(szNewValue) ); - m_ConVarData->GetStringValue( szOldValue, sizeof(szOldValue), index ); + CConVarData::ValueToString( newValue, szNewValue, sizeof(szNewValue) ); + GetConVarData()->GetStringValue( szOldValue, sizeof(szOldValue), index ); - m_ConVarData->SetValue( newValue, index ); + GetConVarData()->SetValue( newValue, index ); g_pCVar->CallChangeCallback( this->m_Handle, index, (const CVValue_t*)&newValue, (const CVValue_t*)&szOldValue ); g_pCVar->CallGlobalChangeCallbacks( this, index, szNewValue, szOldValue ); diff --git a/tier1/convar.cpp b/tier1/convar.cpp index ff2b7a0bc..f81b5e551 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -486,25 +486,6 @@ void ConCommand::Destroy() // //----------------------------------------------------------------------------- -void* invalid_convar[EConVarType_MAX + 1] = { - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t(), - new ConVarData_t() // EConVarType_MAX -}; - #ifdef CONVAR_WORK_FINISHED //----------------------------------------------------------------------------- From 2382f23dc03da30682e0a9375f5d19cccc1f810c Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Mon, 9 Oct 2023 19:27:32 +0200 Subject: [PATCH 32/48] small mistake --- public/icvar.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index 6ed53b7c3..64daf0d52 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -408,8 +408,8 @@ friend class ConVar; inline void GetStringValue( char* dst, size_t len, const CSplitScreenSlot& index = 0 ) const { ValueToString( GetValue( index ), dst, len ); } inline void GetStringDefaultValue( char* dst, size_t len ) const { ValueToString( GetDefaultValue( ), dst, len ); } - inline void GetStringMinValue( char* dst, size_t len ) const { ValueToString( GetMaxValue( ), dst, len ); } - inline void GetStringMaxValue( char* dst, size_t len ) const { ValueToString( GetValue( index ), dst, len ); } + inline void GetStringMinValue( char* dst, size_t len ) const { ValueToString( GetMinValue( ), dst, len ); } + inline void GetStringMaxValue( char* dst, size_t len ) const { ValueToString( GetMaxValue( ), dst, len ); } inline void SetStringValue( const char* src, const CSplitScreenSlot& index = 0 ) const { SetValue( ValueFromString( src ), index ); } From 9def682ca8a2fde5990adbfaf26abfbbd667ea50 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Mon, 9 Oct 2023 19:36:17 +0200 Subject: [PATCH 33/48] setup times changed --- public/icvar.h | 5 +++-- public/tier1/convar.h | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index 64daf0d52..41b127cc4 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -240,7 +240,8 @@ class CConVarBaseData inline bool HasMinValue( ) const { return m_minValue != nullptr; } inline bool HasMaxValue( ) const { return m_maxValue != nullptr; } - inline int GetTimesChanges( void ) const { return m_iTimesChanged; } + inline int GetTimesChanged( void ) const { return m_iTimesChanged; } + inline void SetTimesChanged( int val ) { m_iTimesChanged = val; } inline bool IsFlagSet( int64_t flag ) const { return ( flag & m_nFlags ) ? true : false; } inline void AddFlags( int64_t flags ) { m_nFlags |= flags; } @@ -463,7 +464,7 @@ abstract_class ICvar : public IAppSystem // Install a global change callback (to be called when any convar changes) virtual void InstallGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; virtual void RemoveGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; - virtual void CallGlobalChangeCallbacks( BaseConVar* ref, CSplitScreenSlot nSlot, const char* newValue, char* oldValue ) = 0; + virtual void CallGlobalChangeCallbacks( BaseConVar* ref, CSplitScreenSlot nSlot, const char* newValue, const char* oldValue ) = 0; // Reverts cvars which contain a specific flag virtual void RevertFlaggedConVars( int nFlag ) = 0; diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 7129b7fc1..998a64db2 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -523,10 +523,7 @@ class ConVar : public BaseConVar // Deep copy T oldValue = this->GetValue( ); - GetConVarData()->SetValue( newValue, index ); - - g_pCVar->CallChangeCallback( this->m_Handle, index, (const CVValue_t*)&newValue, (const CVValue_t*)&oldValue ); - g_pCVar->CallGlobalChangeCallbacks( this, index, szNewValue, szOldValue ); + this->UpdateValue( newValue, index, (const CVValue_t*)&newValue, (const CVValue_t*)&oldValue, szNewValue, szOldValue ); } inline void GetStringValue( char* dst, size_t len, const CSplitScreenSlot& index = 0 ) const { GetConVarData()->GetStringValue( dst, len, index ); } @@ -581,6 +578,15 @@ class ConVar : public BaseConVar SetupConVar(cvar); } + + inline void UpdateValue( const T& value, const CSplitScreenSlot& index, const CVValue_t* newValue, const CVValue_t* oldValue, const char* szNewValue, const char* szOldValue ) + { + GetConVarData()->SetValue( value, index ); + + GetConVarData()->SetTimesChanged( GetConVarData()->GetTimesChanged( ) + 1 ); + g_pCVar->CallChangeCallback( this->m_Handle, index, newValue, oldValue ); + g_pCVar->CallGlobalChangeCallbacks( this, index, szNewValue, szOldValue ); + } }; static_assert(sizeof(ConVar) == 0x10, "ConVar is of the wrong size!"); static_assert(sizeof(ConVar) == sizeof(ConVar), "Templated ConVar size varies!"); @@ -594,10 +600,7 @@ template<> inline void ConVar::SetValue( const char*const& val, con CConVarData::ValueToString( newValue, szNewValue, sizeof(szNewValue) ); GetConVarData()->GetStringValue( szOldValue, sizeof(szOldValue), index ); - GetConVarData()->SetValue( newValue, index ); - - g_pCVar->CallChangeCallback( this->m_Handle, index, (const CVValue_t*)&newValue, (const CVValue_t*)&szOldValue ); - g_pCVar->CallGlobalChangeCallbacks( this, index, szNewValue, szOldValue ); + this->UpdateValue( newValue, index, (const CVValue_t*)&newValue, (const CVValue_t*)&szOldValue, szNewValue, szOldValue ); } //----------------------------------------------------------------------------- From 34fd0ef91312c7177ca9a44729ff74bbc8163685 Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Mon, 9 Oct 2023 22:31:31 +0200 Subject: [PATCH 34/48] expose handle --- public/tier1/convar.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 998a64db2..79b8fc906 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -342,6 +342,7 @@ class ConCommand this->Destroy(); } + inline ConCommandHandle GetHandle() const { return m_Handle; }; private: void Create( const char *pName, const char *pHelpString, int64_t flags, ConCommandCreation_t& setup ); void Destroy( ); @@ -446,6 +447,9 @@ class BaseConVar inline void AddFlags( int64_t flags ) { m_ConVarData->AddFlags( flags ); } inline void RemoveFlags( int64_t flags ) { return m_ConVarData->RemoveFlags( flags ); } inline int64_t GetFlags( void ) const { return m_ConVarData->GetFlags( ); } + + inline ConVarHandle GetHandle() const { return m_Handle; }; + inline CConVarBaseData* GetConVarData() const { return m_ConVarData; }; protected: // High-speed method to read convar data ConVarHandle m_Handle; From f8d22f9843c624db775036ee0b85bf1ce68b690a Mon Sep 17 00:00:00 2001 From: Kenzzer Date: Sun, 29 Oct 2023 22:35:48 +0100 Subject: [PATCH 35/48] add character_t include to icvar --- public/icvar.h | 1 + 1 file changed, 1 insertion(+) diff --git a/public/icvar.h b/public/icvar.h index 41b127cc4..7fd36e46d 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -12,6 +12,7 @@ #include "appframework/IAppSystem.h" #include "tier1/utlvector.h" +#include "tier1/characterset.h" #include "tier0/memalloc.h" #include "mathlib/vector4d.h" #include From 38edca2012767f2b7652250f86da9777c01d94a5 Mon Sep 17 00:00:00 2001 From: Benoist <14257866+Kenzzer@users.noreply.github.com> Date: Wed, 7 Feb 2024 14:31:06 +0100 Subject: [PATCH 36/48] Streamline build for others This commit will be reverted eventually --- public/icvar.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/public/icvar.h b/public/icvar.h index 7fd36e46d..ddaf19764 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -17,6 +17,9 @@ #include "mathlib/vector4d.h" #include +// TO-DO: Remove Metamod ConVar PR is finished +class ConCommandBase; + class BaseConVar; class ConCommand; class CCommand; From ae3cbcbff17a5351bca899c89d4710909d3fa408 Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Sun, 26 Jan 2025 16:45:42 +0300 Subject: [PATCH 37/48] Update command completion cb signatures --- public/tier1/convar.h | 14 +++++++------- tier1/convar.cpp | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 79b8fc906..bc9101a6f 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -169,7 +169,7 @@ typedef void ( *FnCommandCallbackVoid_t )(); //----------------------------------------------------------------------------- // Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings //----------------------------------------------------------------------------- -typedef int(*FnCommandCompletionCallback)( const char *partial, CUtlVector< CUtlString > &commands ); +typedef int(*FnCommandCompletionCallback)( const CCommand &command, CUtlVector< CUtlString > &completions ); //----------------------------------------------------------------------------- @@ -184,7 +184,7 @@ class ICommandCallback class ICommandCompletionCallback { public: - virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0; + virtual int CommandCompletionCallback( const CCommand &command, CUtlVector< CUtlString > &completions ) = 0; }; //----------------------------------------------------------------------------- @@ -823,11 +823,11 @@ void ConVar_PrintDescription( const CVarCreationBase_t* pVar ); #endif template< class T > -class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback +class CConCommandMemberAccessor : public ICommandCallback, public ICommandCompletionCallback, public ConCommand { typedef ConCommand BaseClass; typedef void ( T::*FnMemberCommandCallback_t )( const CCommandContext &context, const CCommand &command ); - typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands ); + typedef int ( T::*FnMemberCommandCompletionCallback_t )( const CCommand &command, CUtlVector< CUtlString > &completions ); public: CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0, @@ -849,16 +849,16 @@ class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, pu m_pOwner = pOwner; } - virtual void CommandCallback( const CCommandContext &context, const CCommand &command ) + virtual void CommandCallback( const CCommandContext &context, const CCommand &command ) override { Assert( m_pOwner && m_Func ); (m_pOwner->*m_Func)( context, command ); } - virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) + virtual int CommandCompletionCallback( const CCommand &command, CUtlVector< CUtlString > &completions ) override { Assert( m_pOwner && m_CompletionFunc ); - return (m_pOwner->*m_CompletionFunc)( pPartial, commands ); + return (m_pOwner->*m_CompletionFunc)( command, completions ); } private: diff --git a/tier1/convar.cpp b/tier1/convar.cpp index f81b5e551..79ed3b97f 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -380,7 +380,7 @@ int CCommand::FindArgInt( const char *pName, int nDefaultVal ) const //----------------------------------------------------------------------------- // Default console command autocompletion function //----------------------------------------------------------------------------- -int DefaultCompletionFunc( const char *partial, CUtlVector< CUtlString > &commands ) +int DefaultCompletionFunc( const CCommand &command, CUtlVector< CUtlString > &completions ) { return 0; } From b29c4b251a3a387809638a0dc4eb4f7c513688ff Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Sun, 26 Jan 2025 17:21:16 +0300 Subject: [PATCH 38/48] Update ConVarValueInfo_t & CConVarBaseData --- public/icvar.h | 37 +++++++++++++++++++++++++------------ public/tier1/convar.h | 11 ++++++----- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index ddaf19764..fc55983f4 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -232,7 +232,12 @@ class CConVarBaseData m_minValue(nullptr), m_maxValue(nullptr), m_pszHelpString("This convar is being accessed prior to ConVar_Register being called"), - m_eVarType(EConVarType_Invalid) + m_eVarType(EConVarType_Invalid), + m_Version(0), + m_iTimesChanged(0), + m_nFlags(0), + m_iCallbackIndex(0), + m_GameInfoFlags(0) { } @@ -268,20 +273,28 @@ class CConVarBaseData const char* m_pszHelpString; EConVarType m_eVarType; - // This gets copied from the ConVarDesc_t on creation - short unk1; + // Might be set by a gameinfo config via "version" key + short m_Version; unsigned int m_iTimesChanged; int64 m_nFlags; unsigned int m_iCallbackIndex; - // Used when setting default, max, min values from the ConVarDesc_t - // although that's not the only place of usage - // flags seems to be: - // (1 << 0) Skip setting value to split screen slots and also something keyvalues related - // (1 << 1) Skip setting default value - // (1 << 2) Skip setting min/max values - int m_nUnknownAllocFlags; + enum + { + // GameInfo was used to initialize this cvar + CVARGI_INITIALIZED = (1 << 0), + // GameInfo has set default value, and it cannot be overriden + CVARGI_HAS_DEFAULT_VALUE = (1 << 1), + // GameInfo has set min value, and it cannot be overriden + CVARGI_HAS_MIN_VALUE = (1 << 2), + // GameInfo has set max value, and it cannot be overriden + CVARGI_HAS_MAX_VALUE = (1 << 3), + // GameInfo has set cvar version + CVARGI_HAS_VERSION = (1 << 4) + }; + + int m_GameInfoFlags; }; template<> inline void CConVarBaseData::ValueToString( const bool& val, char* dst, size_t length ) @@ -460,7 +473,7 @@ abstract_class ICvar : public IAppSystem virtual ConVarHandle FindNextConVar( ConVarHandle prev ) = 0; virtual void CallChangeCallback( ConVarHandle cvarid, const CSplitScreenSlot nSlot, const CVValue_t* pNewValue, const CVValue_t* pOldValue ) = 0; - virtual ConCommandHandle FindCommand( const char *name ) = 0; + virtual ConCommandHandle FindCommand( const char *name, bool bAllowDeveloper = false ) = 0; virtual ConCommandHandle FindFirstCommand() = 0; virtual ConCommandHandle FindNextCommand( ConCommandHandle prev ) = 0; virtual void DispatchConCommand( ConCommandHandle cmd, const CCommandContext &ctx, const CCommand &args ) = 0; @@ -470,7 +483,7 @@ abstract_class ICvar : public IAppSystem virtual void RemoveGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; virtual void CallGlobalChangeCallbacks( BaseConVar* ref, CSplitScreenSlot nSlot, const char* newValue, const char* oldValue ) = 0; // Reverts cvars which contain a specific flag - virtual void RevertFlaggedConVars( int nFlag ) = 0; + virtual void RevertFlaggedConVars( uint64 nFlag ) = 0; virtual void SetMaxSplitScreenSlots( int nSlots ) = 0; virtual int GetMaxSplitScreenSlots() const = 0; diff --git a/public/tier1/convar.h b/public/tier1/convar.h index bc9101a6f..ef5df8387 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -21,7 +21,7 @@ #include "tier1/utlstring.h" #include "tier1/characterset.h" #include "Color.h" -#include "cvar.h" +#include "icvar.h" #include "playerslot.h" #include @@ -362,9 +362,10 @@ struct ConVarCreation_t : CVarCreationBase_t { struct ConVarValueInfo_t { ConVarValueInfo_t() : - m_bHasDefault(false), - m_bHasMin(false), - m_bHasMax(false) + m_Version(0), + m_bHasDefault(false), + m_bHasMin(false), + m_bHasMax(false) {} template @@ -374,7 +375,7 @@ struct ConVarCreation_t : CVarCreationBase_t { template T& MaxValue() { return *reinterpret_cast(m_maxValue); } - int32_t m_unknown1; // 0x18 + int32_t m_Version; // 0x18 bool m_bHasDefault; // 0x22 bool m_bHasMin; // 0x23 From 72408e810e5ee0b90b329fefbc71f006be62ea1a Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Thu, 30 Jan 2025 23:16:21 +0300 Subject: [PATCH 39/48] Update CCommand --- public/icvar.h | 2 +- public/tier1/convar.h | 4 ++- tier1/convar.cpp | 63 +++++++++++++++++-------------------------- 3 files changed, 29 insertions(+), 40 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index fc55983f4..29253d2e1 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -499,7 +499,7 @@ abstract_class ICvar : public IAppSystem virtual void ResetConVarsToSnapshot( ConVarSnapshot_t *pSnapshot ) = 0; virtual void DestroyConVarSnapshot( ConVarSnapshot_t *pSnaoshot ) = 0; - virtual characterset_t GetCharacterSet( void ) = 0; + virtual characterset_t *GetCharacterSet( void ) = 0; virtual void SetConVarsFromGameInfo( KeyValues *pKV ) = 0; virtual void unk2() = 0; diff --git a/public/tier1/convar.h b/public/tier1/convar.h index ef5df8387..68e3d0584 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -195,7 +195,7 @@ class CCommand public: CCommand(); CCommand( int nArgC, const char **ppArgV ); - bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL ); + bool Tokenize( CUtlString pCommand, characterset_t *pBreakSet = nullptr ); void Reset(); int ArgC() const; @@ -216,6 +216,8 @@ class CCommand static characterset_t* DefaultBreakSet(); private: + void EnsureBuffers(); + enum { COMMAND_MAX_ARGC = 64, diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 79ed3b97f..778cbd453 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -196,39 +196,20 @@ void ConVar_Unregister( ) s_bRegistered = false; } -//----------------------------------------------------------------------------- -// Global methods -//----------------------------------------------------------------------------- -static characterset_t s_BreakSet; -static bool s_bBuiltBreakSet = false; - //----------------------------------------------------------------------------- // Tokenizer class //----------------------------------------------------------------------------- CCommand::CCommand() { - if ( !s_bBuiltBreakSet ) - { - s_bBuiltBreakSet = true; - CharacterSetBuild( &s_BreakSet, "{}()':" ); - } - + EnsureBuffers(); Reset(); } -CCommand::CCommand( int nArgC, const char **ppArgV ) +CCommand::CCommand( int nArgC, const char **ppArgV ) : CCommand() { Assert( nArgC > 0 ); - if ( !s_bBuiltBreakSet ) - { - s_bBuiltBreakSet = true; - CharacterSetBuild( &s_BreakSet, "{}()':" ); - } - - Reset(); - char *pBuf = m_ArgvBuffer.Base(); char *pSBuf = m_ArgSBuffer.Base(); for ( int i = 0; i < nArgC; ++i ) @@ -261,50 +242,59 @@ CCommand::CCommand( int nArgC, const char **ppArgV ) } } +void CCommand::EnsureBuffers() +{ + m_ArgSBuffer.SetSize( MaxCommandLength() ); + m_ArgvBuffer.SetSize( MaxCommandLength() ); +} + void CCommand::Reset() { m_nArgv0Size = 0; - m_ArgSBuffer.RemoveAll(); - m_ArgvBuffer.RemoveAll(); + m_ArgSBuffer.Base()[0] = '\0'; m_Args.RemoveAll(); } characterset_t* CCommand::DefaultBreakSet() { - return &s_BreakSet; + return g_pCVar->GetCharacterSet(); } -bool CCommand::Tokenize( const char *pCommand, characterset_t *pBreakSet ) +bool CCommand::Tokenize( CUtlString pCommand, characterset_t *pBreakSet ) { + if(m_ArgSBuffer.Count() == 0) + EnsureBuffers(); + Reset(); - if ( !pCommand ) + + if ( pCommand.IsEmpty() ) return false; // Use default break set if ( !pBreakSet ) { - pBreakSet = &s_BreakSet; + pBreakSet = DefaultBreakSet(); } // Copy the current command into a temp buffer // NOTE: This is here to avoid the pointers returned by DequeueNextCommand // to become invalid by calling AddText. Is there a way we can avoid the memcpy? - int nLen = V_strlen( pCommand ); - if ( nLen >= COMMAND_MAX_LENGTH - 1 ) + int nLen = pCommand.Length(); + if ( nLen >= m_ArgSBuffer.Count() - 1 ) { Warning( "CCommand::Tokenize: Encountered command which overflows the tokenizer buffer.. Skipping!\n" ); return false; } - memcpy( m_ArgSBuffer.Base(), pCommand, nLen + 1 ); + memmove( m_ArgSBuffer.Base(), pCommand, nLen + 1 ); // Parse the current command into the current command buffer CUtlBuffer bufParse( m_ArgSBuffer.Base(), nLen, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY); int nArgvBufferSize = 0; - while ( bufParse.IsValid() && ( m_Args.Count() < COMMAND_MAX_ARGC ) ) + while ( bufParse.IsValid() ) { char *pArgvBuf = &m_ArgvBuffer[nArgvBufferSize]; - int nMaxLen = COMMAND_MAX_LENGTH - nArgvBufferSize; + int nMaxLen = m_ArgvBuffer.Count() - nArgvBufferSize; int nStartGet = bufParse.TellGet(); int nSize = bufParse.ParseToken( pBreakSet, pArgvBuf, nMaxLen ); if ( nSize < 0 ) @@ -340,13 +330,10 @@ bool CCommand::Tokenize( const char *pCommand, characterset_t *pBreakSet ) } m_Args.AddToTail( pArgvBuf ); - if( m_Args.Count() >= COMMAND_MAX_ARGC ) - { - Warning( "CCommand::Tokenize: Encountered command which overflows the argument buffer.. Clamped!\n" ); - } - nArgvBufferSize += nSize + 1; - Assert( nArgvBufferSize <= COMMAND_MAX_LENGTH ); + + if(nArgvBufferSize >= m_ArgvBuffer.Count()) + break; } return true; From 29edecba9223e710e74348ea1a71bfa056e7609d Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Thu, 30 Jan 2025 23:17:21 +0300 Subject: [PATCH 40/48] Update ICvar --- public/icvar.h | 6 ++++-- public/tier1/convar.h | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index 29253d2e1..fa8dc631e 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -233,7 +233,7 @@ class CConVarBaseData m_maxValue(nullptr), m_pszHelpString("This convar is being accessed prior to ConVar_Register being called"), m_eVarType(EConVarType_Invalid), - m_Version(0), + m_Version(-1), m_iTimesChanged(0), m_nFlags(0), m_iCallbackIndex(0), @@ -502,7 +502,9 @@ abstract_class ICvar : public IAppSystem virtual characterset_t *GetCharacterSet( void ) = 0; virtual void SetConVarsFromGameInfo( KeyValues *pKV ) = 0; - virtual void unk2() = 0; + // Removes FCVAR_DEVELOPMENTONLY | FCVAR_DEFENSIVE from all cvars and concommands + // that have FCVAR_DEFENSIVE set + virtual void StripDevelopmentFlags() = 0; // Register, unregister vars virtual void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, CConVarBaseData** pCvar ) = 0; diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 68e3d0584..446b44923 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -133,7 +133,7 @@ class CCommandContext #define FCVAR_PER_USER (1<<15) // causes varnameN where N == 2 through max splitscreen slots for mod to be autogenerated #define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file #define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles -#define FCVAR_MISSING2 (1<<18) +#define FCVAR_PERFORMING_SETVALUE (1<<18) // Cvar is in a SetValue state #define FCVAR_RELEASE (1<<19) // Cvars tagged with this are the only cvars avaliable to customers #define FCVAR_MENUBAR_ITEM (1<<20) #define FCVAR_MISSING3 (1<<21) @@ -149,6 +149,8 @@ class CCommandContext // Note: IVEngineClient::ClientCmd_Unrestricted can run any client command. #define FCVAR_EXECUTE_PER_TICK (1<<29) + +#define FCVAR_DEFENSIVE (1<<32) //----------------------------------------------------------------------------- // ConVar & ConCommand creation listener callbacks //----------------------------------------------------------------------------- From df333bca32221c7675d3c0d63df4f2beb958520f Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Sat, 1 Feb 2025 02:45:25 +0300 Subject: [PATCH 41/48] Update ConCommand & cb structs --- public/icvar.h | 42 ++------ public/tier1/convar.h | 240 ++++++++++++++++++++++++++++++++---------- tier1/convar.cpp | 214 +++++++++++++++++-------------------- 3 files changed, 293 insertions(+), 203 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index fa8dc631e..180c0fa29 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -131,31 +131,6 @@ class ConVarHandle static const ConVarHandle INVALID_CONVAR_HANDLE = ConVarHandle(); -class ConCommandHandle -{ -public: - ConCommandHandle( uint16_t index = -1, uint32_t handle = -1) : - m_concommandIndex(index), - m_handleIndex(handle) - {} - - bool IsValid( ) const { return m_concommandIndex != 0xFFFF; } - void Invalidate( ) - { - m_concommandIndex = 0xFFFF; - m_handleIndex = 0x0; - } - - uint32_t GetConCommandIndex() const { return m_concommandIndex; } - uint32_t GetIndex() const { return m_handleIndex; } - -private: - uint32_t m_concommandIndex; - uint32_t m_handleIndex; -}; - -static const ConCommandHandle INVALID_CONCOMMAND_HANDLE = ConCommandHandle(); - //----------------------------------------------------------------------------- // Purpose: Internal structure of ConVar objects //----------------------------------------------------------------------------- @@ -473,10 +448,10 @@ abstract_class ICvar : public IAppSystem virtual ConVarHandle FindNextConVar( ConVarHandle prev ) = 0; virtual void CallChangeCallback( ConVarHandle cvarid, const CSplitScreenSlot nSlot, const CVValue_t* pNewValue, const CVValue_t* pOldValue ) = 0; - virtual ConCommandHandle FindCommand( const char *name, bool bAllowDeveloper = false ) = 0; - virtual ConCommandHandle FindFirstCommand() = 0; - virtual ConCommandHandle FindNextCommand( ConCommandHandle prev ) = 0; - virtual void DispatchConCommand( ConCommandHandle cmd, const CCommandContext &ctx, const CCommand &args ) = 0; + virtual ConCommandRef FindCommand( const char *name, bool bAllowDeveloper = false ) = 0; + virtual ConCommandRef FindFirstCommand() = 0; + virtual ConCommandRef FindNextCommand( ConCommandRef prev ) = 0; + virtual void DispatchConCommand( ConCommandRef cmd, const CCommandContext &ctx, const CCommand &args ) = 0; // Install a global change callback (to be called when any convar changes) virtual void InstallGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; @@ -512,9 +487,12 @@ abstract_class ICvar : public IAppSystem virtual CConVarBaseData* GetConVar( ConVarHandle handle ) = 0; // Register, unregister commands - virtual ConCommandHandle RegisterConCommand( const ConCommandCreation_t& setup, int64 nAdditionalFlags = 0 ) = 0; - virtual void UnregisterConCommand( ConCommandHandle handle ) = 0; - virtual ConCommand* GetCommand( ConCommandHandle handle ) = 0; + virtual ConCommand RegisterConCommand( const ConCommandCreation_t& setup, int64 nAdditionalFlags = 0 ) = 0; + // Unregisters concommand callbacks, but leaves the command in the lists, + // so all ConCommandRefs would still be valid as well as searching for it + virtual void UnregisterConCommand( ConCommand cmd ) = 0; + // Returns command info or empty command struct if not found, never nullptr + virtual ConCommandData* GetCommand( ConCommandRef cmd ) = 0; virtual void QueueThreadSetValue( BaseConVar* ref, CSplitScreenSlot nSlot, CVValue_t* value ) = 0; }; diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 446b44923..16549d831 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -106,7 +106,7 @@ class CCommandContext // Command to ConVars and ConCommands // ConVar Systems -#define FCVAR_LINKED_CONCOMMAND (1<<0) +#define FCVAR_LINKED_CONCOMMAND (1<<0) // Allows concommand callback chaining. When command is dispatched all chained callbacks would fire. #define FCVAR_DEVELOPMENTONLY (1<<1) // Hidden in released products. Flag is removed automatically if ALLOW_DEVELOPMENT_CVARS is defined. #define FCVAR_GAMEDLL (1<<2) // defined by the game DLL #define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL @@ -133,7 +133,7 @@ class CCommandContext #define FCVAR_PER_USER (1<<15) // causes varnameN where N == 2 through max splitscreen slots for mod to be autogenerated #define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file #define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles -#define FCVAR_PERFORMING_SETVALUE (1<<18) // Cvar is in a SetValue state +#define FCVAR_PERFORMING_SETVALUE (1<<18) // Cvar is in a SetValue state #define FCVAR_RELEASE (1<<19) // Cvars tagged with this are the only cvars avaliable to customers #define FCVAR_MENUBAR_ITEM (1<<20) #define FCVAR_MISSING3 (1<<21) @@ -160,6 +160,8 @@ class ICVarListenerCallbacks virtual void OnConVarCreated( BaseConVar* pNewCvar ) = 0; virtual void OnConCommandCreated( ConCommand* pNewCommand ) = 0; }; +#define FCVAR_MISSING4 (1<<33) + //----------------------------------------------------------------------------- // Called when a ConCommand needs to execute @@ -171,7 +173,7 @@ typedef void ( *FnCommandCallbackVoid_t )(); //----------------------------------------------------------------------------- // Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings //----------------------------------------------------------------------------- -typedef int(*FnCommandCompletionCallback)( const CCommand &command, CUtlVector< CUtlString > &completions ); +typedef void (*FnCommandCompletionCallback)( const CCommand &command, CUtlVector< CUtlString > &completions ); //----------------------------------------------------------------------------- @@ -272,86 +274,214 @@ inline const char *CCommand::operator[]( int nIndex ) const return Arg( nIndex ); } - -//----------------------------------------------------------------------------- -// Purpose: The console invoked command -//----------------------------------------------------------------------------- -struct ConCommandCreation_t : CVarCreationBase_t +struct ConCommandCallbackInfo_t { - ConCommandCreation_t() : - m_bHasCompletionCallback(false), - m_bIsInterface(false), - m_pHandle(nullptr) + ConCommandCallbackInfo_t() : + m_fnCommandCallback( nullptr ), + m_bIsInterface( false ), + m_bIsVoidCallback( false ), + m_bIsContextLess( false ) {} - // Call this function when executing the command - struct CallbackInfo_t - { - CallbackInfo_t() : - m_fnCommandCallback(nullptr), - m_bIsInterface(false), - m_bIsVoidCallback(false), - m_bIsContextLess(false) - {} + ConCommandCallbackInfo_t( FnCommandCallback_t cb ) : + m_fnCommandCallback( cb ), + m_bIsInterface( false ), + m_bIsVoidCallback( false ), + m_bIsContextLess( false ) + {} + + ConCommandCallbackInfo_t( FnCommandCallbackVoid_t cb ) : + m_fnVoidCommandCallback( cb ), + m_bIsInterface( false ), + m_bIsVoidCallback( cb ? true : false ), + m_bIsContextLess( false ) + {} + + ConCommandCallbackInfo_t( FnCommandCallbackNoContext_t cb ) : + m_fnContextlessCommandCallback( cb ), + m_bIsInterface( false ), + m_bIsVoidCallback( false ), + m_bIsContextLess( cb ? true : false ) + {} + + ConCommandCallbackInfo_t( ICommandCallback *cb ) : + m_pCommandCallback( cb ), + m_bIsInterface( cb ? true : false ), + m_bIsVoidCallback( false ), + m_bIsContextLess( false ) + {} - union { - FnCommandCallback_t m_fnCommandCallback; - FnCommandCallbackVoid_t m_fnVoidCommandCallback; - FnCommandCallbackNoContext_t m_fnContextlessCommandCallback; - ICommandCallback* m_pCommandCallback; - }; + bool IsValid() const { return m_fnCommandCallback != nullptr; } - bool m_bIsInterface; - bool m_bIsVoidCallback; - bool m_bIsContextLess; + void Dispatch( const CCommandContext &context, const CCommand &command ) const + { + if(!IsValid()) + return; + + if(m_bIsInterface) + m_pCommandCallback->CommandCallback( context, command ); + else if(m_bIsVoidCallback) + m_fnVoidCommandCallback(); + else if(m_bIsContextLess) + m_fnContextlessCommandCallback( command ); + else + m_fnCommandCallback( context, command ); + } + + union + { + FnCommandCallback_t m_fnCommandCallback; + FnCommandCallbackVoid_t m_fnVoidCommandCallback; + FnCommandCallbackNoContext_t m_fnContextlessCommandCallback; + ICommandCallback *m_pCommandCallback; }; - CallbackInfo_t m_fnCallback; + bool m_bIsInterface : 1; + bool m_bIsVoidCallback : 1; + bool m_bIsContextLess : 1; +}; + +struct ConCommandCompletionCallbackInfo_t +{ + ConCommandCompletionCallbackInfo_t() : + m_fnCompletionCallback( nullptr ), + m_bIsFunction( false ), + m_bIsInterface( false ) + {} + + ConCommandCompletionCallbackInfo_t( FnCommandCompletionCallback cb ) : + m_fnCompletionCallback( cb ), + m_bIsFunction( cb ? true : false ), + m_bIsInterface( false ) + {} + + ConCommandCompletionCallbackInfo_t( ICommandCompletionCallback *cb ) : + m_pCommandCompletionCallback( cb ), + m_bIsFunction( false ), + m_bIsInterface( cb ? true : false ) + {} - // NOTE: To maintain backward compat, we have to be very careful: - // All public virtual methods must appear in the same order always - // since engine code will be calling into this code, which *does not match* - // in the mod code; it's using slightly different, but compatible versions - // of this class. Also: Be very careful about adding new fields to this class. - // Those fields will not exist in the version of this class that is instanced - // in mod code. + bool IsValid() const { return m_fnCompletionCallback != nullptr; } + + int Dispatch( const CCommand &command, CUtlVector< CUtlString > &completions ) const + { + if(!IsValid()) + return 0; + + if(m_bIsInterface) + return m_pCommandCompletionCallback->CommandCompletionCallback( command, completions ); + + m_fnCompletionCallback( command, completions ); + return completions.Count(); + } union { FnCommandCompletionCallback m_fnCompletionCallback; - ICommandCompletionCallback* m_pCommandCompletionCallback; + ICommandCompletionCallback *m_pCommandCompletionCallback; }; - bool m_bHasCompletionCallback; + bool m_bIsFunction; bool m_bIsInterface; +}; - ConCommandHandle* m_pHandle; +struct ConCommandCreation_t : CVarCreationBase_t +{ + ConCommandCallbackInfo_t m_CBInfo; + ConCommandCompletionCallbackInfo_t m_CompletionCBInfo; }; -static_assert(sizeof(ConCommandCreation_t) == 0x40, "ConCommandCreation_t is of the wrong size!"); -class ConCommand +//----------------------------------------------------------------------------- +// ConCommands internal data storage class +//----------------------------------------------------------------------------- +class ConCommandData : public CVarCreationBase_t { public: - ConCommand( const char *pName, FnCommandCallback_t callback, - const char *pHelpString = 0, int64 flags = 0, FnCommandCompletionCallback completionFunc = 0 ); - ConCommand( const char *pName, FnCommandCallbackVoid_t callback, - const char *pHelpString = 0, int64 flags = 0, FnCommandCompletionCallback completionFunc = 0 ); - ConCommand( const char* pName, FnCommandCallbackNoContext_t callback, - const char* pHelpString = 0, int64 flags = 0, FnCommandCompletionCallback completionFunc = 0 ); - ConCommand( const char *pName, ICommandCallback *pCallback, - const char *pHelpString = 0, int64 flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 ); + int GetAutoCompleteSuggestions( const CCommand &command, CUtlVector< CUtlString > &completions ) const + { + return m_CompletionCB.Dispatch( command, completions ); + } + + bool HasCompletionCallback() const { return m_CompletionCB.IsValid(); } + bool HasCallback() const { return m_CallbackInfoIndex > 0; } + + ConCommandCompletionCallbackInfo_t m_CompletionCB; + + // Register index of concommand which completion cb comes from + int m_ComplitionCBCmdIndex; + // Index in a linkedlist of callbackinfos + uint16 m_CallbackInfoIndex; +}; + +//----------------------------------------------------------------------------- +// Used to access registered concommands +//----------------------------------------------------------------------------- +class ConCommandRef +{ +public: + ConCommandRef() : m_CommandAccessIndex( -1 ) {} + ConCommandRef( uint16_t command_idx ) : m_CommandAccessIndex( command_idx ) {} + + ConCommandRef( const char *command, bool allow_developer = false ); + + ConCommandData *GetRawData(); + const ConCommandData *GetRawData() const { return const_cast(this)->GetRawData(); } + + const char *GetName() const { return GetRawData()->m_pszName; } + const char *GetHelpString() const { return GetRawData()->m_pszHelpString; } + + bool IsFlagSet( int64_t flag ) const { return GetRawData()->GetFlags(); } + void AddFlags( int64_t flags ) { GetRawData()->AddFlags( flags ); } + void RemoveFlags( int64_t flags ) { GetRawData()->RemoveFlags( flags ); } + int64_t GetFlags() const { return GetRawData()->GetFlags(); } + + bool HasCompletionCallback() const { return GetRawData()->HasCompletionCallback(); } + bool HasCallback() const { return GetRawData()->HasCallback(); } + + uint16_t GetCallbackIndex() const { return GetRawData()->m_CallbackInfoIndex; } + + int GetAutoCompleteSuggestions( const CCommand &command, CUtlVector< CUtlString > &completions ) const + { + return GetRawData()->GetAutoCompleteSuggestions( command, completions ); + } + + void Invalidate() { m_CommandAccessIndex = -1; } + bool IsValid() const { return m_CommandAccessIndex != -1; } + uint16_t GetCommandAccessIndex() const { return m_CommandAccessIndex; } + +private: + // Index into internal linked list of concommands + uint16_t m_CommandAccessIndex; +}; + +//----------------------------------------------------------------------------- +// Used to register concommands in the system as well as access its own data +//----------------------------------------------------------------------------- +class ConCommand : public ConCommandRef +{ +public: + ConCommand( uint16_t access_idx, int reg_idx ) : ConCommandRef( access_idx ), m_CommandRegisteredIndex( reg_idx ) {} + + ConCommand( const char *pName, ConCommandCallbackInfo_t callback, + const char *pHelpString = 0, int64 flags = 0, ConCommandCompletionCallbackInfo_t completionFunc = ConCommandCompletionCallbackInfo_t() ) + : ConCommandRef(), m_CommandRegisteredIndex( 0 ) + { + Create( pName, callback, pHelpString, flags, completionFunc ); + } ~ConCommand() { - this->Destroy(); + Destroy(); } - inline ConCommandHandle GetHandle() const { return m_Handle; }; + int GetRegisteredIndex() const { return m_CommandRegisteredIndex; } + private: - void Create( const char *pName, const char *pHelpString, int64_t flags, ConCommandCreation_t& setup ); + void Create( const char *pName, const ConCommandCallbackInfo_t &cb, const char *pHelpString, int64_t flags, const ConCommandCompletionCallbackInfo_t &completion_cb ); void Destroy( ); - ConCommandHandle m_Handle; + // Commands registered positional index + int m_CommandRegisteredIndex; }; using FnGenericChangeCallback_t = void(*)(BaseConVar* ref, CSplitScreenSlot nSlot, CVValue_t* pNewValue, CVValue_t* pOldValue); diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 778cbd453..9ead09f91 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -26,6 +26,9 @@ #endif #include "tier0/memdbgon.h" +// AMNOTE: Define this if you need cvars/concommands to respect flags sanitization rules +// #define SANITIZE_CVAR_FLAGS 1 + //----------------------------------------------------------------------------- // Statically constructed list of ConCommandBases, // used for registering them with the ICVar interface @@ -33,33 +36,23 @@ static int64 s_nCVarFlag = 0; static bool s_bRegistered = false; -void RegisterCommand( ConCommandCreation_t& cmd ) -{ - *cmd.m_pHandle = g_pCVar->RegisterConCommand( cmd, s_nCVarFlag ); - if ( !cmd.m_pHandle->IsValid() ) - { - Plat_FatalErrorFunc( "RegisterConCommand: Unknown error registering con command \"%s\"!\n", cmd.m_pszName ); - DebuggerBreakIfDebugging( ); - } -} - -void UnRegisterCommand( ConCommandHandle& cmd ) -{ - if ( cmd.IsValid() ) - { - g_pCVar->UnregisterConCommand( cmd ); - - cmd.Invalidate(); - } -} - class ConCommandRegList { public: - static ConCommandRegList* GetRegList() + struct ConCommandCreationEntry_t { - static ConCommandRegList* list = new ConCommandRegList(); - return list; + ConCommandCreation_t m_Info; + ConCommand *m_Command = nullptr; + }; + + static void RegisterCommand( ConCommandCreationEntry_t &cmd ) + { + *cmd.m_Command = g_pCVar->RegisterConCommand( cmd.m_Info, s_nCVarFlag ); + if(!cmd.m_Command->IsValid()) + { + Plat_FatalErrorFunc( "RegisterConCommand: Unknown error registering con command \"%s\"!\n", cmd.m_Info.m_pszName ); + DebuggerBreakIfDebugging(); + } } static void RegisterAll() @@ -68,37 +61,72 @@ class ConCommandRegList { s_bConCommandsRegistered = true; - ConCommandRegList* list = GetRegList(); - FOR_EACH_VEC( list->m_Vec, i ) + ConCommandRegList *prev = nullptr; + for(auto list = s_pRoot; list; list = prev) { - RegisterCommand( list->m_Vec[i] ); - } - delete list; + for(int i = 0; i < list->m_nSize; i++) + { + RegisterCommand( list->m_Entries[i] ); + } + + prev = list->m_pPrev; + delete list; + }; } } -private: - friend void AddCommand( ConCommandCreation_t& cmd ); - void Add( const ConCommandCreation_t& cmd ) + static void AddToList( const ConCommandCreationEntry_t &cmd ) { - m_Vec.AddToTail( cmd ); + auto list = s_pRoot; + + if(!list || list->m_nSize >= sizeof( m_Entries ) / sizeof( m_Entries[0] )) + { + list = new ConCommandRegList; + list->m_nSize = 0; + list->m_pPrev = s_pRoot; + + s_pRoot = list; + } + + list->m_Entries[list->m_nSize++] = cmd; } - CUtlVector m_Vec; +private: + int m_nSize; + ConCommandCreationEntry_t m_Entries[100]; + ConCommandRegList *m_pPrev; + public: static bool s_bConCommandsRegistered; + static ConCommandRegList *s_pRoot; }; + bool ConCommandRegList::s_bConCommandsRegistered = false; +ConCommandRegList *ConCommandRegList::s_pRoot = nullptr; -void AddCommand( ConCommandCreation_t& cmd ) +void SetupConCommand( ConCommand *cmd, const ConCommandCreation_t& info ) { + ConCommandRegList::ConCommandCreationEntry_t entry; + entry.m_Info = info; + entry.m_Command = cmd; + if (ConCommandRegList::s_bConCommandsRegistered && s_bRegistered) { - RegisterCommand( cmd ); + ConCommandRegList::RegisterCommand( entry ); return; } - ConCommandRegList::GetRegList()->Add( cmd ); + ConCommandRegList::AddToList( entry ); +} + +void UnRegisterCommand( ConCommand *cmd ) +{ + if(cmd->IsValid()) + { + g_pCVar->UnregisterConCommand( *cmd ); + + cmd->Invalidate(); + } } void RegisterConVar( ConVarCreation_t& cvar ) @@ -363,77 +391,14 @@ int CCommand::FindArgInt( const char *pName, int nDefaultVal ) const return nDefaultVal; } - -//----------------------------------------------------------------------------- -// Default console command autocompletion function -//----------------------------------------------------------------------------- -int DefaultCompletionFunc( const CCommand &command, CUtlVector< CUtlString > &completions ) -{ - return 0; -} - -ConCommand::ConCommand( const char *pName, FnCommandCallback_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) +ConCommandRef::ConCommandRef( const char *command, bool allow_developer ) { - ConCommandCreation_t creation; - creation.m_fnCallback.m_fnCommandCallback = callback; - creation.m_fnCallback.m_bIsInterface = false; - creation.m_fnCallback.m_bIsVoidCallback = false; - creation.m_fnCallback.m_bIsContextLess = false; - - creation.m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; - creation.m_bHasCompletionCallback = completionFunc != 0 ? true : false; - creation.m_bIsInterface = false; - - // Setup the rest - Create( pName, pHelpString, flags, creation ); + *this = g_pCVar->FindCommand( command, allow_developer ); } -ConCommand::ConCommand( const char *pName, FnCommandCallbackVoid_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) +ConCommandData *ConCommandRef::GetRawData() { - ConCommandCreation_t creation; - creation.m_fnCallback.m_fnVoidCommandCallback = callback; - creation.m_fnCallback.m_bIsInterface = false; - creation.m_fnCallback.m_bIsVoidCallback = true; - creation.m_fnCallback.m_bIsContextLess = false; - - creation.m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; - creation.m_bHasCompletionCallback = completionFunc != nullptr ? true : false; - creation.m_bIsInterface = false; - - // Setup the rest - Create( pName, pHelpString, flags, creation ); -} - -ConCommand::ConCommand( const char *pName, FnCommandCallbackNoContext_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) -{ - ConCommandCreation_t creation; - creation.m_fnCallback.m_fnContextlessCommandCallback = callback; - creation.m_fnCallback.m_bIsInterface = false; - creation.m_fnCallback.m_bIsVoidCallback = false; - creation.m_fnCallback.m_bIsContextLess = true; - - creation.m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; - creation.m_bHasCompletionCallback = completionFunc != nullptr ? true : false; - creation.m_bIsInterface = false; - - // Setup the rest - Create( pName, pHelpString, flags, creation ); -} - -ConCommand::ConCommand( const char *pName, ICommandCallback *pCallback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, ICommandCompletionCallback *pCompletionCallback /*= 0*/ ) -{ - ConCommandCreation_t creation; - creation.m_fnCallback.m_pCommandCallback = pCallback; - creation.m_fnCallback.m_bIsInterface = true; - creation.m_fnCallback.m_bIsVoidCallback = false; - creation.m_fnCallback.m_bIsContextLess = false; - - creation.m_pCommandCompletionCallback = pCompletionCallback; - creation.m_bHasCompletionCallback = pCompletionCallback != nullptr ? true : false; - creation.m_bIsInterface = true; - - // Setup the rest - Create( pName, pHelpString, flags, creation ); + return g_pCVar->GetCommand( *this ); } //----------------------------------------------------------------------------- @@ -443,28 +408,45 @@ ConCommand::ConCommand( const char *pName, ICommandCallback *pCallback, const ch // *pHelpString - // flags - //----------------------------------------------------------------------------- -void ConCommand::Create( const char* pName, const char* pHelpString, int64_t flags, ConCommandCreation_t& setup ) +void ConCommand::Create( const char* pName, const ConCommandCallbackInfo_t &cb, const char* pHelpString, int64_t flags, const ConCommandCompletionCallbackInfo_t &completion_cb ) { - static const char* empty_string = ""; - // Name should be static data Assert(pName); - setup.m_pszName = pName; - setup.m_pszHelpString = pHelpString ? pHelpString : empty_string; - - setup.m_nFlags = flags; - -#ifdef ALLOW_DEVELOPMENT_CVARS - setup.m_nFlags &= ~FCVAR_DEVELOPMENTONLY; + Assert(pHelpString); + + ConCommandCreation_t info; + info.m_pszName = pName; + info.m_pszHelpString = pHelpString; + +#ifdef SANITIZE_CVAR_FLAGS + if(!CommandLine()->HasParm( "-tools" ) + && (flags & (FCVAR_CLIENTDLL + | FCVAR_HIDDEN + | FCVAR_USERINFO + | FCVAR_MISSING0 + | FCVAR_PER_USER + | FCVAR_MENUBAR_ITEM + | FCVAR_MISSING3 + | FCVAR_SERVER_CAN_EXECUTE + | FCVAR_VCONSOLE_SET_FOCUS + | FCVAR_CLIENTCMD_CAN_EXECUTE + | FCVAR_DEFENSIVE + | FCVAR_MISSING4)) == 0) + { + flags |= FCVAR_DEFENSIVE | FCVAR_DEVELOPMENTONLY; + } #endif - setup.m_pHandle = &this->m_Handle; - AddCommand( setup ); + info.m_nFlags = flags; + info.m_CBInfo = cb; + info.m_CompletionCBInfo = completion_cb; + + SetupConCommand( this, info ); } void ConCommand::Destroy() { - UnRegisterCommand(this->m_Handle); + UnRegisterCommand( this ); } //----------------------------------------------------------------------------- From 1b7d8708a656631577f19ff05c396e9c8cade106 Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Sat, 1 Feb 2025 03:09:55 +0300 Subject: [PATCH 42/48] Fix few typos --- public/tier1/convar.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index 16549d831..df46c39f8 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -408,7 +408,7 @@ class ConCommandData : public CVarCreationBase_t ConCommandCompletionCallbackInfo_t m_CompletionCB; // Register index of concommand which completion cb comes from - int m_ComplitionCBCmdIndex; + int m_CompletionCBCmdIndex; // Index in a linkedlist of callbackinfos uint16 m_CallbackInfoIndex; }; @@ -438,6 +438,7 @@ class ConCommandRef bool HasCompletionCallback() const { return GetRawData()->HasCompletionCallback(); } bool HasCallback() const { return GetRawData()->HasCallback(); } + int GetCompletionCommandIndex() const { return GetRawData()->m_CompletionCBCmdIndex; } uint16_t GetCallbackIndex() const { return GetRawData()->m_CallbackInfoIndex; } int GetAutoCompleteSuggestions( const CCommand &command, CUtlVector< CUtlString > &completions ) const @@ -463,7 +464,8 @@ class ConCommand : public ConCommandRef ConCommand( uint16_t access_idx, int reg_idx ) : ConCommandRef( access_idx ), m_CommandRegisteredIndex( reg_idx ) {} ConCommand( const char *pName, ConCommandCallbackInfo_t callback, - const char *pHelpString = 0, int64 flags = 0, ConCommandCompletionCallbackInfo_t completionFunc = ConCommandCompletionCallbackInfo_t() ) + const char *pHelpString, int64 flags = 0, + ConCommandCompletionCallbackInfo_t completionFunc = ConCommandCompletionCallbackInfo_t() ) : ConCommandRef(), m_CommandRegisteredIndex( 0 ) { Create( pName, callback, pHelpString, flags, completionFunc ); From 6a377634142d9abf1b15ab421f3592e7be62c344 Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Fri, 7 Feb 2025 18:18:02 +0300 Subject: [PATCH 43/48] Add ConVarRefAbstract & update ConVar api Also a lot of small code reshufflings/cleanup --- public/icvar.h | 497 ++------------- public/tier1/convar.h | 1289 ++++++++++++++++++++++++++------------- public/tier1/strtools.h | 40 ++ tier1/convar.cpp | 521 +++++++++------- 4 files changed, 1261 insertions(+), 1086 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index 180c0fa29..5df74d2e0 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -14,487 +14,120 @@ #include "tier1/utlvector.h" #include "tier1/characterset.h" #include "tier0/memalloc.h" -#include "mathlib/vector4d.h" +#include "convar.h" #include // TO-DO: Remove Metamod ConVar PR is finished class ConCommandBase; -class BaseConVar; -class ConCommand; -class CCommand; -class CCommandContext; -class ICVarListenerCallbacks; -class IConVarListener; -struct ConVarCreation_t; -struct ConCommandCreation_t; -struct ConVarSnapshot_t; -class KeyValues; - -template -class ConVar; - -union CVValue_t -{ - template - inline CVValue_t& operator=(const T& other); +// Shorthand helper to iterate registered convars +// Example usage: +// FOR_EACH_CONVAR( iter ) +// { +// ConVarRefAbstract aref( iter ); +// Msg( "%s = %d\n", aref.GetName(), aref.GetInt() ); +// +// /* or use typed version, but make sure to check its validity after, +// since it would be invalid on type mismatch */ +// +// CConVarRef cref( iter ); +// if(cref.IsValidRef()) +// Msg( "%s = %d\n", cref.GetName(), cref.Get() ); +// } +#define FOR_EACH_CONVAR( iter ) for(ConVarRef iter = g_pCVar->FindFirstConVar(); iter.IsValidRef(); iter = g_pCVar->FindNextConVar( iter )) + +// Shorthand helper to iterate registered concommands +#define FOR_EACH_CONCOMMAND( iter ) for(ConCommandRef iter = icvar->FindFirstConCommand(); iter.IsValidRef(); iter = icvar->FindNextConCommand( iter )) - inline operator bool() const { return m_bValue; } - inline operator int16_t() const { return m_i16Value; } - inline operator uint16_t() const { return m_u16Value; } - inline operator int32_t() const { return m_i32Value; } - inline operator uint32_t() const { return m_u32Value; } - inline operator int64_t() const { return m_i64Value; } - inline operator uint64_t() const { return m_u64Value; } - inline operator float() const { return m_flValue; } - inline operator double() const { return m_dbValue; } - inline operator const char*() const { return m_szValue; } - inline operator const Color&() const { return m_clrValue; } - inline operator const Vector2D&() const { return m_vec2Value; } - inline operator const Vector&() const { return m_vec3Value; } - inline operator const Vector4D&() const { return m_vec4Value; } - inline operator const QAngle&() const { return m_angValue; } - - bool m_bValue; - int16_t m_i16Value; - uint16_t m_u16Value; - int32_t m_i32Value; - uint32_t m_u32Value; - int64_t m_i64Value; - uint64_t m_u64Value; - float m_flValue; - double m_dbValue; - const char* m_szValue; - Color m_clrValue; - Vector2D m_vec2Value; - Vector m_vec3Value; - Vector4D m_vec4Value; - QAngle m_angValue; -}; -static_assert(sizeof(float) == sizeof(int32_t), "Wrong float type size for ConVar!"); -static_assert(sizeof(double) == sizeof(int64_t), "Wrong double type size for ConVar!"); - -struct CSplitScreenSlot -{ - CSplitScreenSlot() : - m_Data(0) - {} - - CSplitScreenSlot( int index ) - { - m_Data = index; - } - - int Get() const - { - return m_Data; - } - operator int() const - { - return m_Data; - } - - int m_Data; -}; +struct ConVarSnapshot_t; +class KeyValues; //----------------------------------------------------------------------------- // Called when a ConVar changes value //----------------------------------------------------------------------------- -typedef void(*FnChangeCallbackGlobal_t)(BaseConVar* ref, CSplitScreenSlot nSlot, const char *pNewValue, const char *pOldValue); - -//----------------------------------------------------------------------------- -// Purpose: Replaces the ConVar* and ConCommand* -//----------------------------------------------------------------------------- -class ConVarHandle -{ -public: - ConVarHandle( uint16_t index = -1, uint32_t handle = -1) : - m_convarIndex(index), - m_handleIndex(handle) - {} - - bool IsValid( ) const { return m_convarIndex != 0xFFFF; } - void Invalidate( ) - { - m_convarIndex = 0xFFFF; - m_handleIndex = 0x0; - } - - uint16_t GetConVarIndex() const { return m_convarIndex; } - uint32_t GetIndex() const { return m_handleIndex; } - -private: - uint16_t m_convarIndex; - uint32_t m_handleIndex; -}; - -static const ConVarHandle INVALID_CONVAR_HANDLE = ConVarHandle(); +typedef void(*FnChangeCallbackGlobal_t)(ConVarRefAbstract* ref, CSplitScreenSlot nSlot, const char *pNewValue, const char *pOldValue); //----------------------------------------------------------------------------- -// Purpose: Internal structure of ConVar objects +// ConVar & ConCommand creation listener callbacks //----------------------------------------------------------------------------- -enum EConVarType : int16_t -{ - EConVarType_Invalid = -1, - EConVarType_Bool, - EConVarType_Int16, - EConVarType_UInt16, - EConVarType_Int32, - EConVarType_UInt32, - EConVarType_Int64, - EConVarType_UInt64, - EConVarType_Float32, - EConVarType_Float64, - EConVarType_String, - EConVarType_Color, - EConVarType_Vector2, - EConVarType_Vector3, - EConVarType_Vector4, - EConVarType_Qangle, - EConVarType_MAX -}; - -template -constexpr EConVarType TranslateConVarType(); - -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Bool; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Int16; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_UInt16; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Int32; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_UInt32; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Int64; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_UInt64; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Float32; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Float64; } -template<> constexpr EConVarType TranslateConVarType( void ){ return EConVarType_String; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Color; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Vector2; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Vector3; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Vector4; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Qangle; } -template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Invalid; } - -template -class CConVarData; - -class CConVarBaseData -{ -public: - template - inline const CConVarData* Cast() const - { - if (this->m_eVarType == TranslateConVarType()) - { - return reinterpret_cast*>(this); - } - return nullptr; - } - - template - inline CConVarData* Cast() - { - if (this->m_eVarType == TranslateConVarType()) - { - return reinterpret_cast*>(this); - } - return nullptr; - } - - CConVarBaseData() : - m_pszName(""), - m_defaultValue(nullptr), - m_minValue(nullptr), - m_maxValue(nullptr), - m_pszHelpString("This convar is being accessed prior to ConVar_Register being called"), - m_eVarType(EConVarType_Invalid), - m_Version(-1), - m_iTimesChanged(0), - m_nFlags(0), - m_iCallbackIndex(0), - m_GameInfoFlags(0) - { - } - - inline const char* GetName( void ) const { return m_pszName; } - inline const char* GetDescription( void ) const { return m_pszHelpString; } - inline EConVarType GetType( void ) const { return m_eVarType; } - - inline bool HasDefaultValue( ) const { return m_defaultValue != nullptr; } - inline bool HasMinValue( ) const { return m_minValue != nullptr; } - inline bool HasMaxValue( ) const { return m_maxValue != nullptr; } - - inline int GetTimesChanged( void ) const { return m_iTimesChanged; } - inline void SetTimesChanged( int val ) { m_iTimesChanged = val; } - - inline bool IsFlagSet( int64_t flag ) const { return ( flag & m_nFlags ) ? true : false; } - inline void AddFlags( int64_t flags ) { m_nFlags |= flags; } - inline void RemoveFlags( int64_t flags ) { m_nFlags &= ~flags; } - inline int64_t GetFlags( void ) const { return m_nFlags; } - - inline int GetCallbackIndex( void ) const { return m_iCallbackIndex; } -protected: - template - static inline void ValueToString( const T& val, char* dst, size_t length ); - - template - static T ValueFromString( const char* val ); - - const char* m_pszName; - - void* m_defaultValue; - void* m_minValue; - void* m_maxValue; - const char* m_pszHelpString; - EConVarType m_eVarType; - - // Might be set by a gameinfo config via "version" key - short m_Version; - - unsigned int m_iTimesChanged; - int64 m_nFlags; - unsigned int m_iCallbackIndex; - - enum - { - // GameInfo was used to initialize this cvar - CVARGI_INITIALIZED = (1 << 0), - // GameInfo has set default value, and it cannot be overriden - CVARGI_HAS_DEFAULT_VALUE = (1 << 1), - // GameInfo has set min value, and it cannot be overriden - CVARGI_HAS_MIN_VALUE = (1 << 2), - // GameInfo has set max value, and it cannot be overriden - CVARGI_HAS_MAX_VALUE = (1 << 3), - // GameInfo has set cvar version - CVARGI_HAS_VERSION = (1 << 4) - }; - - int m_GameInfoFlags; -}; - -template<> inline void CConVarBaseData::ValueToString( const bool& val, char* dst, size_t length ) -{ - const char* src = ( val ) ? "true" : "false"; - memcpy( dst, src, length ); -} -template<> inline void CConVarBaseData::ValueToString( const uint16_t& val, char* dst, size_t length ) { snprintf( dst, length, "%u", val ); } -template<> inline void CConVarBaseData::ValueToString( const int16_t& val, char* dst, size_t length ) { snprintf( dst, length, "%d", val ); } -template<> inline void CConVarBaseData::ValueToString( const uint32_t& val, char* dst, size_t length ) { snprintf( dst, length, "%u", val ); } -template<> inline void CConVarBaseData::ValueToString( const int32_t& val, char* dst, size_t length ) { snprintf( dst, length, "%d", val ); } -template<> inline void CConVarBaseData::ValueToString( const uint64_t& val, char* dst, size_t length ) { snprintf( dst, length, "%lu", val ); } -template<> inline void CConVarBaseData::ValueToString( const int64_t& val, char* dst, size_t length ) { snprintf( dst, length, "%ld", val ); } -template<> inline void CConVarBaseData::ValueToString( const float& val, char* dst, size_t length ) { snprintf( dst, length, "%f", val ); } -template<> inline void CConVarBaseData::ValueToString( const double& val, char* dst, size_t length ) { snprintf( dst, length, "%lf", val ); } -template<> inline void CConVarBaseData::ValueToString( const char*const& val, char* dst, size_t length ) { memcpy( dst, val, length ); } -template<> inline void CConVarBaseData::ValueToString( const Color& val, char* dst, size_t length ) { snprintf( dst, length, "%d %d %d %d", val.r(), val.g(), val.b(), val.a() ); } -template<> inline void CConVarBaseData::ValueToString( const Vector2D& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f", val.x, val.y ); } -template<> inline void CConVarBaseData::ValueToString( const Vector& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f %f", val.x, val.y, val.z ); } -template<> inline void CConVarBaseData::ValueToString( const Vector4D& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f %f %f", val.x, val.y, val.z, val.w ); } -template<> inline void CConVarBaseData::ValueToString( const QAngle& val, char* dst, size_t length ) { snprintf( dst, length, "%f %f %f", val.x, val.y, val.z ); } - -template<> inline bool CConVarBaseData::ValueFromString( const char* val ) { if (strcmp(val, "true") == 0 || strcmp(val, "1") == 0) { return true; } return false; } -template<> inline uint16_t CConVarBaseData::ValueFromString( const char* val ) { unsigned int ret; sscanf(val, "%u", &ret); return ret; } -template<> inline int16_t CConVarBaseData::ValueFromString( const char* val ) { int ret; sscanf(val, "%d", &ret); return ret; } -template<> inline uint32_t CConVarBaseData::ValueFromString( const char* val ) { uint32_t ret; sscanf(val, "%u", &ret); return ret; } -template<> inline int32_t CConVarBaseData::ValueFromString( const char* val ) { int32_t ret; sscanf(val, "%d", &ret); return ret; } -template<> inline uint64_t CConVarBaseData::ValueFromString( const char* val ) { uint64_t ret; sscanf(val, "%lu", &ret); return ret; } -template<> inline int64_t CConVarBaseData::ValueFromString( const char* val ) { int64_t ret; sscanf(val, "%ld", &ret); return ret; } -template<> inline float CConVarBaseData::ValueFromString( const char* val ) { float ret; sscanf(val, "%f", &ret); return ret; } -template<> inline double CConVarBaseData::ValueFromString( const char* val ) { double ret; sscanf(val, "%lf", &ret); return ret; } -template<> inline const char* CConVarBaseData::ValueFromString( const char* val ) { return val; } -template<> inline Color CConVarBaseData::ValueFromString( const char* val ) { int r, g, b, a; sscanf(val, "%d %d %d %d", &r, &g, &b, &a); return Color(r, g, b, a); } -template<> inline Vector2D CConVarBaseData::ValueFromString( const char* val ) { float x, y; sscanf(val, "%f %f", &x, &y); return Vector2D(x, y); } -template<> inline Vector CConVarBaseData::ValueFromString( const char* val ) { float x, y, z; sscanf(val, "%f %f %f", &x, &y, &z); return Vector(x, y, z); } -template<> inline Vector4D CConVarBaseData::ValueFromString( const char* val ) { float x, y, z, w; sscanf(val, "%f %f %f %f", &x, &y, &z, &w); return Vector4D(x, y, z, w); } -template<> inline QAngle CConVarBaseData::ValueFromString( const char* val ) { float x, y, z; sscanf(val, "%f %f %f", &x, &y, &z); return QAngle(x, y, z); } - -template -class CConVarData : public CConVarBaseData +class ICVarListenerCallbacks { public: -friend class ConVar; - constexpr CConVarData() - { - m_defaultValue = new T(); - m_minValue = new T(); - m_maxValue = new T(); - m_eVarType = TranslateConVarType(); - } - - ~CConVarData() - { - delete m_defaultValue; - delete m_minValue; - delete m_eVarType; - } - - inline const T& GetDefaultValue( ) const { return *reinterpret_cast(m_defaultValue); } - inline const T& GetMinValue( ) const { return *reinterpret_cast(m_minValue); } - inline const T& GetMaxValue( ) const { return *reinterpret_cast(m_maxValue); } - - inline void SetDefaultValue(const T& value) - { - if (!m_defaultValue) - { - m_defaultValue = new T(); - } - *reinterpret_cast(m_defaultValue) = value; - } - inline void SetMinValue(const T& value) - { - if (!m_minValue) - { - m_minValue = new T(); - } - *reinterpret_cast(m_minValue) = value; - } - inline void SetMaxValue(const T& value) - { - if (!m_maxValue) - { - m_maxValue = new T(); - } - *reinterpret_cast(m_maxValue) = value; - } - - inline void RemoveDefaultValue( ) - { - if (m_defaultValue) - { - delete reinterpret_cast(m_defaultValue); - } - m_defaultValue = nullptr; - } - inline void RemoveMinValue( ) - { - if (m_minValue) - { - delete reinterpret_cast(m_minValue); - } - m_minValue = nullptr; - } - inline void RemoveMaxValue( ) - { - if (m_maxValue) - { - delete reinterpret_cast(m_maxValue); - } - m_maxValue = nullptr; - } - - inline const T& Clamp(const T& value) const - { - if (HasMinValue() && value < GetMinValue()) - { - return GetMinValue(); - } - if (HasMaxValue() && value > GetMaxValue()) - { - return GetMaxValue(); - } - return value; - } - - inline const T& GetValue( const CSplitScreenSlot& index = 0 ) const { return m_value[index]; } - inline void SetValue(const T& value, const CSplitScreenSlot& index = 0) { m_value[index] = value; } - - inline void GetStringValue( char* dst, size_t len, const CSplitScreenSlot& index = 0 ) const { ValueToString( GetValue( index ), dst, len ); } - - inline void GetStringDefaultValue( char* dst, size_t len ) const { ValueToString( GetDefaultValue( ), dst, len ); } - inline void GetStringMinValue( char* dst, size_t len ) const { ValueToString( GetMinValue( ), dst, len ); } - inline void GetStringMaxValue( char* dst, size_t len ) const { ValueToString( GetMaxValue( ), dst, len ); } - - inline void SetStringValue( const char* src, const CSplitScreenSlot& index = 0 ) const { SetValue( ValueFromString( src ), index ); } - - inline void SetStringDefaultValue( const char* src ) const { SetDefaultValue( ValueFromString( src ) ); } - inline void SetStringMinValue( const char* src ) const { SetMinValue( ValueFromString( src ) ); } - inline void SetStringMaxValue( const char* src ) const { SetMaxValue( ValueFromString( src ) ); } - -protected: - static inline void ValueToString( const T& value, char* dst, size_t length ) { CConVarBaseData::ValueToString( value, dst, length ); }; - - static T ValueFromString( const char* val ) { return CConVarBaseData::ValueFromString( val ); }; - - T m_value[MAX_SPLITSCREEN_CLIENTS]; + virtual void OnConVarCreated( ConVarRefAbstract *pNewCvar ) {}; + virtual void OnConCommandCreated( ConCommand *pNewCommand ) {}; }; -// Special case for string handling -template<> inline void CConVarData::SetValue(const char*const& value, const CSplitScreenSlot& index) -{ - char* data = new char[256]; - memcpy(data, value, 256); - - delete[] m_value[index]; - m_value[index] = data; -} - -// For some types it makes no sense to clamp -template<> inline const char*const& CConVarData::Clamp(const char*const& value) const { return value; } -template<> inline const Color& CConVarData::Clamp(const Color& value) const { return value; } -template<> inline const Vector2D& CConVarData::Clamp(const Vector2D& value) const { return value; } -template<> inline const Vector& CConVarData::Clamp(const Vector& value) const { return value; } -template<> inline const Vector4D& CConVarData::Clamp(const Vector4D& value) const { return value; } -template<> inline const QAngle& CConVarData::Clamp(const QAngle& value) const { return value; } - //----------------------------------------------------------------------------- // Purpose: DLL interface to ConVars/ConCommands //----------------------------------------------------------------------------- abstract_class ICvar : public IAppSystem { public: - // bAllowDeveloper - Allows finding convars with FCVAR_DEVELOPMENTONLY flag - virtual ConVarHandle FindConVar( const char *name, bool bAllowDeveloper = false ) = 0; - virtual ConVarHandle FindFirstConVar() = 0; - virtual ConVarHandle FindNextConVar( ConVarHandle prev ) = 0; - virtual void CallChangeCallback( ConVarHandle cvarid, const CSplitScreenSlot nSlot, const CVValue_t* pNewValue, const CVValue_t* pOldValue ) = 0; - - virtual ConCommandRef FindCommand( const char *name, bool bAllowDeveloper = false ) = 0; - virtual ConCommandRef FindFirstCommand() = 0; - virtual ConCommandRef FindNextCommand( ConCommandRef prev ) = 0; + // allow_defensive - Allows finding convars with FCVAR_DEFENSIVE flag + virtual ConVarRef FindConVar( const char *name, bool allow_defensive = false ) = 0; + virtual ConVarRef FindFirstConVar() = 0; + virtual ConVarRef FindNextConVar( ConVarRef prev ) = 0; + virtual void CallChangeCallback( ConVarRef cvar, const CSplitScreenSlot nSlot, const CVValue_t* pNewValue, const CVValue_t* pOldValue ) = 0; + + // allow_defensive - Allows finding commands with FCVAR_DEFENSIVE flag + virtual ConCommandRef FindConCommand( const char *name, bool allow_defensive = false ) = 0; + virtual ConCommandRef FindFirstConCommand() = 0; + virtual ConCommandRef FindNextConCommand( ConCommandRef prev ) = 0; virtual void DispatchConCommand( ConCommandRef cmd, const CCommandContext &ctx, const CCommand &args ) = 0; // Install a global change callback (to be called when any convar changes) virtual void InstallGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; virtual void RemoveGlobalChangeCallback( FnChangeCallbackGlobal_t callback ) = 0; - virtual void CallGlobalChangeCallbacks( BaseConVar* ref, CSplitScreenSlot nSlot, const char* newValue, const char* oldValue ) = 0; - // Reverts cvars which contain a specific flag - virtual void RevertFlaggedConVars( uint64 nFlag ) = 0; + virtual void CallGlobalChangeCallbacks( ConVarRefAbstract* ref, CSplitScreenSlot nSlot, const char* newValue, const char* oldValue ) = 0; + + // Reverts cvars to default values which contain a specific flag, + // cvars with a flag FCVAR_COMMANDLINE_ENFORCED would be skipped + virtual void ResetConVarsToDefaultValuesByFlag( uint64 nFlag ) = 0; virtual void SetMaxSplitScreenSlots( int nSlots ) = 0; virtual int GetMaxSplitScreenSlots() const = 0; - virtual void RegisterCreationListeners( ICVarListenerCallbacks *callbacks ) = 0; - virtual void RemoveCreationListeners( ICVarListenerCallbacks *callbacks ) = 0; + virtual void RegisterCreationListeners( ICVarListenerCallbacks *callbacks ) = 0; + virtual void RemoveCreationListeners( ICVarListenerCallbacks *callbacks ) = 0; - virtual void unk1() = 0; + virtual void unk001() = 0; - virtual void ResetConVarsToDefaultValues( const char *pszPrefix ) = 0; + // Reverts cvars to default values which match pszPrefix string, + // ignores FCVAR_COMMANDLINE_ENFORCED + virtual void ResetConVarsToDefaultValuesByName( const char *pszPrefix ) = 0; virtual ConVarSnapshot_t *TakeConVarSnapshot( void ) = 0; virtual void ResetConVarsToSnapshot( ConVarSnapshot_t *pSnapshot ) = 0; - virtual void DestroyConVarSnapshot( ConVarSnapshot_t *pSnaoshot ) = 0; + virtual void DestroyConVarSnapshot( ConVarSnapshot_t *pSnapshot ) = 0; - virtual characterset_t *GetCharacterSet( void ) = 0; - virtual void SetConVarsFromGameInfo( KeyValues *pKV ) = 0; + virtual characterset_t *GetCharacterSet( void ) = 0; + virtual void SetConVarsFromGameInfo( KeyValues *pKV ) = 0; // Removes FCVAR_DEVELOPMENTONLY | FCVAR_DEFENSIVE from all cvars and concommands // that have FCVAR_DEFENSIVE set - virtual void StripDevelopmentFlags() = 0; + virtual void StripDevelopmentFlags() = 0; // Register, unregister vars - virtual void RegisterConVar( const ConVarCreation_t& setup, int64 nAdditionalFlags, ConVarHandle* pCvarRef, CConVarBaseData** pCvar ) = 0; - virtual void UnregisterConVar( ConVarHandle handle ) = 0; - virtual CConVarBaseData* GetConVar( ConVarHandle handle ) = 0; + virtual void RegisterConVar( const ConVarCreation_t& setup, uint64 nAdditionalFlags, ConVarRef* pCvarRef, ConVarData** pCvarData ) = 0; + // Unregisters convar change callback, but leaves the convar in the lists, + // so all ConVarRefs would still be valid as well as searching for it. + // Expects ref to have registered index to be set (is set on convar creation) + virtual void UnregisterConVarCallbacks( ConVarRef cvar ) = 0; + // Returns convar data or nullptr if not found + virtual ConVarData* GetConVarData( ConVarRef cvar ) = 0; // Register, unregister commands - virtual ConCommand RegisterConCommand( const ConCommandCreation_t& setup, int64 nAdditionalFlags = 0 ) = 0; + virtual ConCommand RegisterConCommand( const ConCommandCreation_t& setup, uint64 nAdditionalFlags = 0 ) = 0; // Unregisters concommand callbacks, but leaves the command in the lists, - // so all ConCommandRefs would still be valid as well as searching for it - virtual void UnregisterConCommand( ConCommand cmd ) = 0; + // so all ConCommandRefs would still be valid as well as searching for it. + // Expects ref to have registered index to be set (is set on command creation) + virtual void UnregisterConCommandCallbacks( ConCommandRef cmd ) = 0; // Returns command info or empty command struct if not found, never nullptr - virtual ConCommandData* GetCommand( ConCommandRef cmd ) = 0; + virtual ConCommandData* GetConCommandData( ConCommandRef cmd ) = 0; - virtual void QueueThreadSetValue( BaseConVar* ref, CSplitScreenSlot nSlot, CVValue_t* value ) = 0; + // Queues up value (creates a copy of it) to be set when convar is ready to be edited + virtual void QueueThreadSetValue( ConVarRefAbstract* ref, CSplitScreenSlot nSlot, CVValue_t* value ) = 0; }; //----------------------------------------------------------------------------- diff --git a/public/tier1/convar.h b/public/tier1/convar.h index df46c39f8..dff5c60ba 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -19,83 +19,163 @@ #include "tier0/dbg.h" #include "tier1/utlvector.h" #include "tier1/utlstring.h" +#include "mathlib/vector4d.h" +#include "bufferstring.h" #include "tier1/characterset.h" #include "Color.h" -#include "icvar.h" #include "playerslot.h" #include #include - -#ifdef _WIN32 -#define FORCEINLINE_CVAR FORCEINLINE -#elif POSIX -#define FORCEINLINE_CVAR inline -#else -#error "implement me" -#endif - - -//----------------------------------------------------------------------------- -// Uncomment me to test for threading issues for material system convars -// NOTE: You want to disable all threading when you do this -// +host_thread_mode 0 +r_threaded_particles 0 +sv_parallel_packentities 0 +sv_disable_querycache 0 -//----------------------------------------------------------------------------- -//#define CONVAR_TEST_MATERIAL_THREAD_CONVARS 1 - +#include //----------------------------------------------------------------------------- // Forward declarations //----------------------------------------------------------------------------- class CCommand; class ConCommand; +class CCommandContext; +class ConVarRefAbstract; -struct CVarCreationBase_t +struct CSplitScreenSlot { - CVarCreationBase_t( ) : - m_pszName( nullptr ), - m_pszHelpString( nullptr ), - m_nFlags( 0 ) + CSplitScreenSlot() : + m_Data(0) {} + + CSplitScreenSlot( int index ) + { + m_Data = index; + } + + int Get() const + { + return m_Data; + } - bool IsFlagSet( int64_t flag ) const; - void AddFlags( int64_t flags ); - void RemoveFlags( int64_t flags ); - int64_t GetFlags() const; - - const char* m_pszName; - const char* m_pszHelpString; - int64_t m_nFlags; + operator int() const + { + return m_Data; + } + + int m_Data; }; -enum CommandTarget_t +//----------------------------------------------------------------------------- +// Purpose: Internal structure of ConVar objects +//----------------------------------------------------------------------------- +enum EConVarType : int16_t { - CT_NO_TARGET = -1, - CT_FIRST_SPLITSCREEN_CLIENT = 0, - CT_LAST_SPLITSCREEN_CLIENT = 3, + EConVarType_Invalid = -1, + EConVarType_Bool, + EConVarType_Int16, + EConVarType_UInt16, + EConVarType_Int32, + EConVarType_UInt32, + EConVarType_Int64, + EConVarType_UInt64, + EConVarType_Float32, + EConVarType_Float64, + EConVarType_String, + EConVarType_Color, + EConVarType_Vector2, + EConVarType_Vector3, + EConVarType_Vector4, + EConVarType_Qangle, + EConVarType_MAX }; -class CCommandContext +template +constexpr EConVarType TranslateConVarType(); + +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Bool; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Int16; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_UInt16; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Int32; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_UInt32; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Int64; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_UInt64; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Float32; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Float64; } +template<> constexpr EConVarType TranslateConVarType( void ){ return EConVarType_String; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Color; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Vector2; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Vector3; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Vector4; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Qangle; } +template<> constexpr EConVarType TranslateConVarType( void ) { return EConVarType_Invalid; } + +union CVValue_t { -public: - CCommandContext(CommandTarget_t nTarget, CPlayerSlot nSlot) : - m_nTarget(nTarget), m_nPlayerSlot(nSlot) + static CVValue_t *InvalidValue() { + static uint8 s_Data[sizeof( CVValue_t )] = {}; + return (CVValue_t *)&s_Data; } - CommandTarget_t GetTarget() const - { - return m_nTarget; - } + CVValue_t() {} + CVValue_t( const bool value ) : m_bValue( value ) {} + CVValue_t( const int16 value ) : m_i16Value( value ) {} + CVValue_t( const uint16 value ) : m_u16Value( value ) {} + CVValue_t( const int32 value ) : m_i32Value( value ) {} + CVValue_t( const uint32 value ) : m_u32Value( value ) {} + CVValue_t( const int64 value ) : m_i64Value( value ) {} + CVValue_t( const uint64 value ) : m_u64Value( value ) {} + CVValue_t( const float32 value ) : m_fl32Value( value ) {} + CVValue_t( const float64 value ) : m_fl64Value( value ) {} + CVValue_t( const CUtlString &value ) : m_StringValue( value ) {} + CVValue_t( const Color &value ) : m_clrValue( value ) {} + CVValue_t( const Vector2D &value ) : m_vec2Value( value ) {} + CVValue_t( const Vector &value ) : m_vec3Value( value ) {} + CVValue_t( const Vector4D &value ) : m_vec4Value( value ) {} + CVValue_t( const QAngle &value ) : m_angValue( value ) {} + ~CVValue_t() {} + + operator bool() const { return m_bValue; } + operator int16() const { return m_i16Value; } + operator uint16() const { return m_u16Value; } + operator int32() const { return m_i32Value; } + operator uint32() const { return m_u32Value; } + operator int64() const { return m_i64Value; } + operator uint64() const { return m_u64Value; } + operator float32() const { return m_fl32Value; } + operator float64() const { return m_fl64Value; } + operator const char*() const { return m_StringValue.Get(); } + operator const CUtlString&() const { return m_StringValue; } + operator const Color&() const { return m_clrValue; } + operator const Vector2D&() const { return m_vec2Value; } + operator const Vector&() const { return m_vec3Value; } + operator const Vector4D&() const { return m_vec4Value; } + operator const QAngle&() const { return m_angValue; } + + bool m_bValue; + int16 m_i16Value; + uint16 m_u16Value; + int32 m_i32Value; + uint32 m_u32Value; + int64 m_i64Value; + uint64 m_u64Value; + float32 m_fl32Value; + float64 m_fl64Value; + CUtlString m_StringValue; + Color m_clrValue; + Vector2D m_vec2Value; + Vector m_vec3Value; + Vector4D m_vec4Value; + QAngle m_angValue; +}; - CPlayerSlot GetPlayerSlot() const - { - return m_nPlayerSlot; - } +struct CVarCreationBase_t +{ + CVarCreationBase_t() : + m_pszName( nullptr ), + m_pszHelpString( nullptr ), + m_nFlags( 0 ) + {} -private: - CommandTarget_t m_nTarget; - CPlayerSlot m_nPlayerSlot; + const char* m_pszName; + const char* m_pszHelpString; + uint64 m_nFlags; }; //----------------------------------------------------------------------------- @@ -119,9 +199,11 @@ class CCommandContext #define FCVAR_NOTIFY (1<<8) // notifies players when changed #define FCVAR_USERINFO (1<<9) // changes the client's info string -#define FCVAR_MISSING0 (1<<10) // Something that hides the cvar from the cvar lookups +#define FCVAR_REFERENCE (1<<10) // Means cvar is a reference, usually used to get a cvar reference of a cvar registered in other module, + // and is temporary until the actual cvar was registered #define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log -#define FCVAR_MISSING1 (1<<12) // Something that hides the cvar from the cvar lookups +#define FCVAR_INITIAL_SETVALUE (1<<12) // Is set for a first convar SetValue either with its default_value or with a value from a gameinfo. + // Mostly for callbacks to check for. // It's a ConVar that's shared between the client and the server. // At signon, the values of all such ConVars are sent from the server to the client (skipped for local @@ -133,10 +215,11 @@ class CCommandContext #define FCVAR_PER_USER (1<<15) // causes varnameN where N == 2 through max splitscreen slots for mod to be autogenerated #define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file #define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles -#define FCVAR_PERFORMING_SETVALUE (1<<18) // Cvar is in a SetValue state +#define FCVAR_PERFORMING_CALLBACKS (1<<18) // Is set when cvar is calling to its callbacks from CallChangeCallback or CallGlobalChangeCallbacks, + // usually means if you set the value during these callbacks, its value would be queued and set when all callbacks were fired #define FCVAR_RELEASE (1<<19) // Cvars tagged with this are the only cvars avaliable to customers #define FCVAR_MENUBAR_ITEM (1<<20) -#define FCVAR_MISSING3 (1<<21) +#define FCVAR_COMMANDLINE_ENFORCED (1<<21) // If cvar was set via launch options it would not be reset on calls to ResetConVarsToDefaultValuesByFlag #define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server #define FCVAR_VCONSOLE_FUZZY_MATCHING (1<<23) @@ -151,16 +234,6 @@ class CCommandContext #define FCVAR_EXECUTE_PER_TICK (1<<29) #define FCVAR_DEFENSIVE (1<<32) -//----------------------------------------------------------------------------- -// ConVar & ConCommand creation listener callbacks -//----------------------------------------------------------------------------- -class ICVarListenerCallbacks -{ -public: - virtual void OnConVarCreated( BaseConVar* pNewCvar ) = 0; - virtual void OnConCommandCreated( ConCommand* pNewCommand ) = 0; -}; -#define FCVAR_MISSING4 (1<<33) //----------------------------------------------------------------------------- @@ -194,6 +267,35 @@ class ICommandCompletionCallback //----------------------------------------------------------------------------- // Command tokenizer //----------------------------------------------------------------------------- +enum CommandTarget_t +{ + CT_NO_TARGET = -1, + CT_FIRST_SPLITSCREEN_CLIENT = 0, + CT_LAST_SPLITSCREEN_CLIENT = 3, +}; + +class CCommandContext +{ +public: + CCommandContext( CommandTarget_t nTarget, CPlayerSlot nSlot ) : + m_nTarget( nTarget ), m_nPlayerSlot( nSlot ) + {} + + CommandTarget_t GetTarget() const + { + return m_nTarget; + } + + CPlayerSlot GetPlayerSlot() const + { + return m_nPlayerSlot; + } + +private: + CommandTarget_t m_nTarget; + CPlayerSlot m_nPlayerSlot; +}; + class CCommand { public: @@ -394,9 +496,18 @@ struct ConCommandCreation_t : CVarCreationBase_t //----------------------------------------------------------------------------- // ConCommands internal data storage class //----------------------------------------------------------------------------- -class ConCommandData : public CVarCreationBase_t +class ConCommandData { public: + const char *GetName() const { return m_pszName; } + const char *GetHelpString() const { return m_pszHelpString; } + bool HasHelpString() const { return m_pszHelpString && m_pszHelpString[0]; } + + bool IsFlagSet( uint64 flag ) const { return (m_nFlags & flag) != 0; } + void AddFlags( uint64 flags ) { m_nFlags |= flags; } + void RemoveFlags( uint64 flags ) { m_nFlags &= ~flags; } + uint64 GetFlags( void ) const { return m_nFlags; } + int GetAutoCompleteSuggestions( const CCommand &command, CUtlVector< CUtlString > &completions ) const { return m_CompletionCB.Dispatch( command, completions ); @@ -405,6 +516,10 @@ class ConCommandData : public CVarCreationBase_t bool HasCompletionCallback() const { return m_CompletionCB.IsValid(); } bool HasCallback() const { return m_CallbackInfoIndex > 0; } + const char* m_pszName; + const char* m_pszHelpString; + uint64 m_nFlags; + ConCommandCompletionCallbackInfo_t m_CompletionCB; // Register index of concommand which completion cb comes from @@ -418,41 +533,52 @@ class ConCommandData : public CVarCreationBase_t //----------------------------------------------------------------------------- class ConCommandRef { +private: + static const uint16 kInvalidAccessIndex = 0xFFFF; + public: - ConCommandRef() : m_CommandAccessIndex( -1 ) {} - ConCommandRef( uint16_t command_idx ) : m_CommandAccessIndex( command_idx ) {} - ConCommandRef( const char *command, bool allow_developer = false ); + ConCommandRef() : m_CommandAccessIndex( kInvalidAccessIndex ), m_CommandRegisteredIndex( 0 ) {} + ConCommandRef( uint16 command_idx ) : m_CommandAccessIndex( command_idx ), m_CommandRegisteredIndex( 0 ) {} + ConCommandRef( uint16 access_idx, int reg_idx ) : m_CommandAccessIndex( access_idx ), m_CommandRegisteredIndex( reg_idx ) {} + + ConCommandRef( const char *name, bool allow_defensive = false ); ConCommandData *GetRawData(); const ConCommandData *GetRawData() const { return const_cast(this)->GetRawData(); } - const char *GetName() const { return GetRawData()->m_pszName; } - const char *GetHelpString() const { return GetRawData()->m_pszHelpString; } + const char *GetName() const { return GetRawData()->GetName(); } + const char *GetHelpString() const { return GetRawData()->GetHelpString(); } + bool HasHelpString() const { return GetRawData()->HasHelpString(); } - bool IsFlagSet( int64_t flag ) const { return GetRawData()->GetFlags(); } - void AddFlags( int64_t flags ) { GetRawData()->AddFlags( flags ); } - void RemoveFlags( int64_t flags ) { GetRawData()->RemoveFlags( flags ); } - int64_t GetFlags() const { return GetRawData()->GetFlags(); } + bool IsFlagSet( uint64 flag ) const { return GetRawData()->GetFlags(); } + void AddFlags( uint64 flags ) { GetRawData()->AddFlags( flags ); } + void RemoveFlags( uint64 flags ) { GetRawData()->RemoveFlags( flags ); } + uint64 GetFlags() const { return GetRawData()->GetFlags(); } bool HasCompletionCallback() const { return GetRawData()->HasCompletionCallback(); } bool HasCallback() const { return GetRawData()->HasCallback(); } + void Dispatch( const CCommandContext &context, const CCommand &command ); + int GetCompletionCommandIndex() const { return GetRawData()->m_CompletionCBCmdIndex; } - uint16_t GetCallbackIndex() const { return GetRawData()->m_CallbackInfoIndex; } + uint16 GetCallbackIndex() const { return GetRawData()->m_CallbackInfoIndex; } int GetAutoCompleteSuggestions( const CCommand &command, CUtlVector< CUtlString > &completions ) const { return GetRawData()->GetAutoCompleteSuggestions( command, completions ); } - void Invalidate() { m_CommandAccessIndex = -1; } - bool IsValid() const { return m_CommandAccessIndex != -1; } - uint16_t GetCommandAccessIndex() const { return m_CommandAccessIndex; } + void InvalidateRef() { m_CommandAccessIndex = kInvalidAccessIndex; m_CommandRegisteredIndex = 0; } + bool IsValidRef() const { return m_CommandAccessIndex != kInvalidAccessIndex; } + uint16 GetAccessIndex() const { return m_CommandAccessIndex; } + int GetRegisteredIndex() const { return m_CommandRegisteredIndex; } private: // Index into internal linked list of concommands - uint16_t m_CommandAccessIndex; + uint16 m_CommandAccessIndex; + // Commands registered positional index + int m_CommandRegisteredIndex; }; //----------------------------------------------------------------------------- @@ -461,12 +587,12 @@ class ConCommandRef class ConCommand : public ConCommandRef { public: - ConCommand( uint16_t access_idx, int reg_idx ) : ConCommandRef( access_idx ), m_CommandRegisteredIndex( reg_idx ) {} + typedef ConCommandRef BaseClass; ConCommand( const char *pName, ConCommandCallbackInfo_t callback, - const char *pHelpString, int64 flags = 0, + const char *pHelpString, uint64 flags = 0, ConCommandCompletionCallbackInfo_t completionFunc = ConCommandCompletionCallbackInfo_t() ) - : ConCommandRef(), m_CommandRegisteredIndex( 0 ) + : BaseClass() { Create( pName, callback, pHelpString, flags, completionFunc ); } @@ -476,480 +602,773 @@ class ConCommand : public ConCommandRef Destroy(); } - int GetRegisteredIndex() const { return m_CommandRegisteredIndex; } - private: - void Create( const char *pName, const ConCommandCallbackInfo_t &cb, const char *pHelpString, int64_t flags, const ConCommandCompletionCallbackInfo_t &completion_cb ); + void Create( const char *pName, const ConCommandCallbackInfo_t &cb, const char *pHelpString, uint64 flags, const ConCommandCompletionCallbackInfo_t &completion_cb ); void Destroy( ); - - // Commands registered positional index - int m_CommandRegisteredIndex; }; -using FnGenericChangeCallback_t = void(*)(BaseConVar* ref, CSplitScreenSlot nSlot, CVValue_t* pNewValue, CVValue_t* pOldValue); +using FnGenericChangeCallback_t = void(*)(ConVarRefAbstract* ref, CSplitScreenSlot nSlot, const CVValue_t* pNewValue, const CVValue_t* pOldValue); -struct ConVarCreation_t : CVarCreationBase_t { - ConVarCreation_t() : - m_pHandle(nullptr), - m_pConVarData(nullptr) +struct ConVarValueInfo_t +{ + ConVarValueInfo_t( EConVarType type = EConVarType_Invalid ) : + m_Version( 0 ), + m_bHasDefault( false ), + m_bHasMin( false ), + m_bHasMax( false ), + m_defaultValue {}, + m_minValue {}, + m_maxValue {}, + m_fnCallBack(), + m_eVarType( type ) {} - - #pragma pack(push,1) - struct ConVarValueInfo_t + + template + void SetDefaultValue( const T &value ) { - ConVarValueInfo_t() : - m_Version(0), - m_bHasDefault(false), - m_bHasMin(false), - m_bHasMax(false) - {} - - template - T& DefaultValue() { return *reinterpret_cast(m_defaultValue); } - template - T& MinValue() { return *reinterpret_cast(m_minValue); } - template - T& MaxValue() { return *reinterpret_cast(m_maxValue); } - - int32_t m_Version; // 0x18 - - bool m_bHasDefault; // 0x22 - bool m_bHasMin; // 0x23 - bool m_bHasMax; // 0x24 - private: - // Don't use CVValue_t directly, to avoid initialising memory - uint8_t m_defaultValue[sizeof(CVValue_t)]; // 0x25 - uint8_t m_minValue[sizeof(CVValue_t)]; // 0x35 - uint8_t m_maxValue[sizeof(CVValue_t)]; // 0x45 - } m_valueInfo; // 0x22 - #pragma pack(pop) - - FnGenericChangeCallback_t m_fnCallBack; // 0x56 - EConVarType m_eVarType; // 0x58 - - ConVarHandle* m_pHandle; // 0x60 - CConVarBaseData** m_pConVarData; // 0x68 -}; -static_assert(sizeof(ConVarCreation_t) == 0x70, "ConVarCreation_t wrong size!"); -static_assert(sizeof(ConVarCreation_t) % 8 == 0x0, "ConVarCreation_t isn't 8 bytes aligned!"); -static_assert(sizeof(CVValue_t) == 0x10, "CVValue_t wrong size!"); + m_bHasDefault = true; + *reinterpret_cast(m_defaultValue) = value; + } -static CConVarBaseData* GetInvalidConVar( EConVarType type ) -{ - static CConVarBaseData* invalid_convar[EConVarType_MAX + 1] = { - new CConVarData(), - new CConVarData(), - new CConVarData(), - new CConVarData(), - new CConVarData(), - new CConVarData(), - new CConVarData(), - new CConVarData(), - new CConVarData(), - new CConVarData(), - new CConVarData(), - new CConVarData(), - new CConVarData(), - new CConVarData(), - new CConVarData(), - new CConVarData() // EConVarType_MAX - }; + template + void SetMinValue( const T &min ) + { + m_bHasMin = true; + *reinterpret_cast(m_minValue) = min; + } - if (type == EConVarType_Invalid) + template + void SetMaxValue( const T &max ) { - return invalid_convar[ EConVarType_MAX ]; + m_bHasMax = true; + *reinterpret_cast(m_maxValue) = max; } - return invalid_convar[ type ]; + + int32 m_Version; + + bool m_bHasDefault; + bool m_bHasMin; + bool m_bHasMax; + +private: + // Don't use CVValue_t directly to prevent align issues and to avoid initialising memory + uint8 m_defaultValue[sizeof( CVValue_t )]; + uint8 m_minValue[sizeof( CVValue_t )]; + uint8 m_maxValue[sizeof( CVValue_t )]; + +public: + FnGenericChangeCallback_t m_fnCallBack; + EConVarType m_eVarType; +}; + +struct ConVarCreation_t : CVarCreationBase_t +{ + ConVarValueInfo_t m_valueInfo; +}; + +template static void CvarTypeTrait_ConstructFn( CVValue_t *obj ) { Construct( (T *)obj ); } +template static void CvarTypeTrait_CopyFn( CVValue_t *obj, const CVValue_t &other ) { *(T *)obj = *(T *)&other; } +template static void CvarTypeTrait_DestructFn( CVValue_t *obj ) { Destruct( (T *)obj ); } +template static bool CvarTypeTrait_StringToValueFn( const char *string, CVValue_t *obj ) { return V_StringToValue( string, *(T *)obj ); } +template static void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ); +template static bool CvarTypeTrait_EqualFn( const CVValue_t *obj, const CVValue_t *other ) { return *(T *)obj == *(T *)other; } +template static void CvarTypeTrait_ClampFn( CVValue_t *obj, const CVValue_t *min, const CVValue_t *max ) +{ + if(min) + *(T *)obj = Max( *(T *)obj, *(T *)min ); + + if(max) + *(T *)obj = Min( *(T *)obj, *(T *)max ); } -void SetupConVar( ConVarCreation_t& cvar ); -void UnRegisterConVar( ConVarHandle& cvar ); -void RegisterConVar( ConVarCreation_t& cvar ); +template<> bool CvarTypeTrait_StringToValueFn( const char *string, CVValue_t *obj ) { obj->m_StringValue = string; return true; } + +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Insert( 0, obj->m_bValue ? "true" : "false" ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Format( "%d", obj->m_i16Value ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Format( "%u", obj->m_u16Value ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Format( "%d", obj->m_i32Value ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Format( "%u", obj->m_u32Value ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Format( "%lld", obj->m_i64Value ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Format( "%llu", obj->m_u64Value ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Format( "%f", obj->m_fl32Value ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Format( "%lf", obj->m_fl64Value ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Insert( 0, obj->m_StringValue.Get() ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Format( "%f %f", obj->m_vec2Value[0], obj->m_vec2Value[1] ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Format( "%f %f %f", obj->m_vec3Value[0], obj->m_vec3Value[1], obj->m_vec3Value[2] ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Format( "%f %f %f %f", obj->m_vec4Value[0], obj->m_vec4Value[1], obj->m_vec4Value[2], obj->m_vec4Value[3] ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) { buf.Format( "%f %f %f", obj->m_angValue[0], obj->m_angValue[1], obj->m_angValue[2] ); } +template<> void CvarTypeTrait_ValueToStringFn( const CVValue_t *obj, CBufferString &buf ) +{ + if( obj->m_clrValue.a() == 255 ) + buf.Format( "%d %d %d", obj->m_clrValue[0], obj->m_clrValue[1], obj->m_clrValue[2] ); + else + buf.Format( "%d %d %d %d", obj->m_clrValue[0], obj->m_clrValue[1], obj->m_clrValue[2], obj->m_clrValue[3] ); +} -//----------------------------------------------------------------- -// Used to read/write/create convars (replaces the FindVar method) -//----------------------------------------------------------------- -class BaseConVar +template<> void CvarTypeTrait_ClampFn( CVValue_t *obj, const CVValue_t *min, const CVValue_t *max ) { } +template<> void CvarTypeTrait_ClampFn( CVValue_t *obj, const CVValue_t *min, const CVValue_t *max ) { -public: - inline const char* GetName( ) const { return m_ConVarData->GetName( ); } - inline const char* GetDescription( ) const { return m_ConVarData->GetDescription( ); } - inline EConVarType GetType( ) const { return m_ConVarData->GetType( ); } + if(min) for(int i = 0; i < 4; i++) obj->m_clrValue[i] = Max( obj->m_clrValue[i], min->m_clrValue[i] ); + if(max) for(int i = 0; i < 4; i++) obj->m_clrValue[i] = Min( obj->m_clrValue[i], max->m_clrValue[i] ); +} +template<> void CvarTypeTrait_ClampFn( CVValue_t *obj, const CVValue_t *min, const CVValue_t *max ) +{ + if(min) for(int i = 0; i < 2; i++) obj->m_vec2Value[i] = Max( obj->m_vec2Value[i], min->m_vec2Value[i] ); + if(max) for(int i = 0; i < 2; i++) obj->m_vec2Value[i] = Min( obj->m_vec2Value[i], max->m_vec2Value[i] ); +} +template<> void CvarTypeTrait_ClampFn( CVValue_t *obj, const CVValue_t *min, const CVValue_t *max ) +{ + if(min) for(int i = 0; i < 3; i++) obj->m_vec3Value[i] = Max( obj->m_vec3Value[i], min->m_vec3Value[i] ); + if(max) for(int i = 0; i < 3; i++) obj->m_vec3Value[i] = Min( obj->m_vec3Value[i], max->m_vec3Value[i] ); +} +template<> void CvarTypeTrait_ClampFn( CVValue_t *obj, const CVValue_t *min, const CVValue_t *max ) +{ + if(min) for(int i = 0; i < 4; i++) obj->m_vec4Value[i] = Max( obj->m_vec4Value[i], min->m_vec4Value[i] ); + if(max) for(int i = 0; i < 4; i++) obj->m_vec4Value[i] = Min( obj->m_vec4Value[i], max->m_vec4Value[i] ); +} +template<> void CvarTypeTrait_ClampFn( CVValue_t *obj, const CVValue_t *min, const CVValue_t *max ) +{ + if(min) for(int i = 0; i < 3; i++) obj->m_angValue[i] = Max( obj->m_angValue[i], min->m_angValue[i] ); + if(max) for(int i = 0; i < 3; i++) obj->m_angValue[i] = Min( obj->m_angValue[i], max->m_angValue[i] ); +} + +class ConVarData; +static ConVarData *GetInvalidConVarData( EConVarType type ); + +struct CVarTypeTraits +{ + template + CVarTypeTraits *InitAs( const char *name, const char *default_value ) + { + m_TypeName = name; + m_ByteSize = sizeof( T ); + m_IsPrimitive = std::is_literal_type_v; + + Construct = &CvarTypeTrait_ConstructFn; + Copy = &CvarTypeTrait_CopyFn; + Destruct = &CvarTypeTrait_DestructFn; + StringToValue = &CvarTypeTrait_StringToValueFn; + ValueToString = &CvarTypeTrait_ValueToStringFn; + Equal = &CvarTypeTrait_EqualFn; + Clamp = &CvarTypeTrait_ClampFn; + + m_DefaultValue = default_value; + m_InvalidCvarData = GetInvalidConVarData( TranslateConVarType() ); + + return this; + } - inline bool HasDefaultValue( ) const { return m_ConVarData->HasDefaultValue( ); } - inline bool HasMinValue( ) const { return m_ConVarData->HasMinValue( ); } - inline bool HasMaxValue( ) const { return m_ConVarData->HasMaxValue( ); } + const char *m_TypeName; + int m_ByteSize; + bool m_IsPrimitive; - inline bool IsFlagSet( int64_t flag ) const { return m_ConVarData->IsFlagSet( flag ); } - inline void AddFlags( int64_t flags ) { m_ConVarData->AddFlags( flags ); } - inline void RemoveFlags( int64_t flags ) { return m_ConVarData->RemoveFlags( flags ); } - inline int64_t GetFlags( void ) const { return m_ConVarData->GetFlags( ); } + void (*Construct)(CVValue_t *obj); + void (*Copy)(CVValue_t *obj, const CVValue_t &other); + void (*Destruct)(CVValue_t *obj); + bool (*StringToValue)(const char *string, CVValue_t *obj); + void (*ValueToString)(const CVValue_t *obj, CBufferString &buf); + bool (*Equal)(const CVValue_t *obj, const CVValue_t *other); + void (*Clamp)(CVValue_t *obj, const CVValue_t *min, const CVValue_t *max); - inline ConVarHandle GetHandle() const { return m_Handle; }; - inline CConVarBaseData* GetConVarData() const { return m_ConVarData; }; -protected: - // High-speed method to read convar data - ConVarHandle m_Handle; - CConVarBaseData* m_ConVarData; + const char *m_DefaultValue; + ConVarData *m_InvalidCvarData; }; -template -class ConVar : public BaseConVar +static CVarTypeTraits *GetCvarTypeTraits( EConVarType type ) { -public: - using FnChangeCallback_t = void(*)(ConVar* ref, const CSplitScreenSlot nSlot, const T* pNewValue, const T* pOldValue); + Assert( type >= 0 && type < EConVarType_MAX ); + + static CVarTypeTraits s_TypeTraits[EConVarType_MAX] = { + *CVarTypeTraits().InitAs( "bool", "false" ), + *CVarTypeTraits().InitAs( "int16", "0" ), + *CVarTypeTraits().InitAs( "uint16", "0" ), + *CVarTypeTraits().InitAs( "int32", "0" ), + *CVarTypeTraits().InitAs( "uint32", "0" ), + *CVarTypeTraits().InitAs( "int64", "0" ), + *CVarTypeTraits().InitAs( "uint64", "0" ), + *CVarTypeTraits().InitAs( "float32", "0" ), + *CVarTypeTraits().InitAs( "float64", "0" ), + *CVarTypeTraits().InitAs( "string", "" ), + *CVarTypeTraits().InitAs( "color", "0 0 0 255" ), + *CVarTypeTraits().InitAs( "vector2", "0 0" ), + *CVarTypeTraits().InitAs( "vector3", "0 0 0" ), + *CVarTypeTraits().InitAs( "vector4", "0 0 0 0" ), + *CVarTypeTraits().InitAs( "qangle", "0 0 0" ) + }; + + return &s_TypeTraits[type]; +} - ConVar(const char* name, int32_t flags, const char* description, const T& value, FnChangeCallback_t cb = nullptr) +class ConVarData +{ +public: + enum { - this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); + // GameInfo was used to initialize this cvar + CVARGI_INITIALIZED = (1 << 0), + // GameInfo has set default value, and it cannot be overriden + CVARGI_HAS_DEFAULT_VALUE = (1 << 1), + // GameInfo has set min value, and it cannot be overriden + CVARGI_HAS_MIN_VALUE = (1 << 2), + // GameInfo has set max value, and it cannot be overriden + CVARGI_HAS_MAX_VALUE = (1 << 3), + // GameInfo has set cvar version + CVARGI_HAS_VERSION = (1 << 4) + }; - ConVarCreation_t setup; - setup.m_valueInfo.m_bHasDefault = true; - setup.m_valueInfo.DefaultValue() = value; - setup.m_eVarType = TranslateConVarType(); - setup.m_fnCallBack = reinterpret_cast(cb); + ConVarData( EConVarType type = EConVarType_Invalid ) : + m_pszName( "" ), + m_defaultValue( CVValue_t::InvalidValue() ), + m_minValue( nullptr ), + m_maxValue( nullptr ), + m_pszHelpString( "This convar is being accessed prior to ConVar_Register being called" ), + m_eVarType( type ), + m_Version( 0 ), + m_iTimesChanged( 0 ), + m_nFlags( FCVAR_REFERENCE ), + m_iCallbackIndex( 0 ), + m_GameInfoFlags( 0 ), + m_Values {} + {} - this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); - } + const char *GetName( void ) const { return m_pszName; } + const char *GetHelpString( void ) const { return m_pszHelpString; } + bool HasHelpString() const { return m_pszHelpString && m_pszHelpString[0]; } - ConVar(const char* name, int32_t flags, const char* description, const T& value, bool min, const T& minValue, bool max, const T& maxValue, FnChangeCallback_t cb = nullptr) - { - this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); + EConVarType GetType( void ) const { return m_eVarType; } + + short GetVersion() const { return m_Version; } - ConVarCreation_t setup; - setup.m_valueInfo.m_bHasDefault = true; - setup.m_valueInfo.DefaultValue() = value; + int GetTimesChanged() const { return m_iTimesChanged; } + void SetTimesChanged( int val ) { m_iTimesChanged = val; } + void IncrementTimesChanged() { m_iTimesChanged++; } - setup.m_valueInfo.m_bHasMin = min; - setup.m_valueInfo.m_bHasMax = max; - setup.m_valueInfo.MinValue() = minValue; - setup.m_valueInfo.MaxValue() = maxValue; + bool IsFlagSet( uint64 flag ) const { return (m_nFlags & flag) != 0; } + void AddFlags( uint64 flags ) { m_nFlags |= flags; } + void RemoveFlags( uint64 flags ) { m_nFlags &= ~flags; } + uint64 GetFlags() const { return m_nFlags; } - setup.m_eVarType = TranslateConVarType(); - setup.m_fnCallBack = reinterpret_cast(cb); + int GetGameInfoFlags() const { return m_GameInfoFlags; } + int GetCallbackIndex() const { return m_iCallbackIndex; } - this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); - } + int GetMaxSplitScreenSlots() const; - ~ConVar() + CVarTypeTraits *TypeTraits() const { - UnRegisterConVar(this->m_Handle); + Assert( m_eVarType != EConVarType_Invalid ); + return GetCvarTypeTraits( m_eVarType ); } - inline const CConVarData* GetConVarData() const { return reinterpret_cast*>(m_ConVarData); } - inline CConVarData* GetConVarData() { return reinterpret_cast*>(m_ConVarData); } + int GetDataByteSize() const { return TypeTraits()->m_ByteSize; } + bool IsPrimitiveType() const { return TypeTraits()->m_IsPrimitive; } + const char *GetDataTypeName() const { return TypeTraits()->m_TypeName; } - inline const T& GetDefaultValue( ) const { return GetConVarData()->GetDefaultValue( ); } - inline const T& GetMinValue( ) const { return GetConVarData()->GetMinValue( ); } - inline const T& GetMaxValue( ) const { return GetConVarData()->GetMaxValue( ); } + bool HasDefaultValue() const { return m_defaultValue && m_defaultValue != CVValue_t::InvalidValue(); } + bool HasMinValue() const { return m_minValue != nullptr; } + bool HasMaxValue() const { return m_maxValue != nullptr; } - inline void SetDefaultValue( const T& value ) { GetConVarData()->SetDefaultValue( value ); } - inline void SetMinValue( const T& value ) { GetConVarData()->SetMinValue( value ); } - inline void SetMaxValue( const T& value ) { GetConVarData()->SetMaxValue( value ); } + CVValue_t *DefaultValue() const { return m_defaultValue; } + CVValue_t *MinValue() const { return m_minValue; } + CVValue_t *MaxValue() const { return m_maxValue; } - inline void RemoveDefaultValue( ) { GetConVarData()->RemoveDefaultValue( ); } - inline void RemoveMinValue( ) { GetConVarData()->RemoveMinValue( ); } - inline void RemoveMaxValue( ) { GetConVarData()->RemoveMaxValue( ); } + // Since cvars can't be without default value, this just resets it to a global default value if it had one set + void RemoveDefaultValue() { if(HasDefaultValue()) TypeTraits()->StringToValue( TypeTraits()->m_DefaultValue, m_defaultValue ); } - inline const T& Clamp(const T& value) const { return GetConVarData()->Clamp( value ); } - - inline const T& GetValue( const CSplitScreenSlot& index = CSplitScreenSlot() ) const { return GetConVarData()->GetValue( index ); } - inline void SetValue( const T& val, const CSplitScreenSlot& index = CSplitScreenSlot() ) - { - auto newValue = this->Clamp( val ); + // AMNOTE: Min/Max values are allocated by default by a CCvar allocator which doesn't cleanup memory, + // thus be careful when removing min/max values allocated by other sources and do cleanup yourself + void RemoveMinValue() { m_minValue = nullptr; } + void RemoveMaxValue() { m_maxValue = nullptr; } - char szNewValue[256], szOldValue[256]; - CConVarData::ValueToString( newValue, szNewValue, sizeof(szNewValue) ); - GetConVarData()->GetStringValue( szOldValue, sizeof(szOldValue), index ); + // Updates default/min/max values to other value if present + bool UpdateDefaultValueString( const char *value ) { return HasDefaultValue() && TypeTraits()->StringToValue( value, m_defaultValue ); } + bool UpdateMinValueString( const char *value ) { return HasMinValue() && TypeTraits()->StringToValue( value, m_minValue ); } + bool UpdateMaxValueString( const char *value ) { return HasMaxValue() && TypeTraits()->StringToValue( value, m_maxValue ); } - // Deep copy - T oldValue = this->GetValue( ); - this->UpdateValue( newValue, index, (const CVValue_t*)&newValue, (const CVValue_t*)&oldValue, szNewValue, szOldValue ); - } + // Sets default value by copying it, doesn't need to be allocated + void SetDefaultValue( CVValue_t *value ) { TypeTraits()->Copy( m_defaultValue, value ); } + + // AMNOTE: Expects you to manually allocate its value and for it to be alive while it's used by the cvar + // Also you should be responsible for clearing memory on cleanup, by default game uses CCvar memory allocator for this + void SetMinValue( CVValue_t *value ) { m_minValue = value; } + void SetMaxValue( CVValue_t *value ) { m_maxValue = value; } + + // Could be nullptr if slot is invalid for this cvar + CVValue_t *Value( CSplitScreenSlot slot ) const; + // Returns default_value if slot is invalid + CVValue_t *ValueOrDefault( CSplitScreenSlot slot ) const; + + bool IsSetToDefault( CSplitScreenSlot slot ) const { return TypeTraits()->Equal( ValueOrDefault( slot ), m_defaultValue ); } + bool IsAllSetToDefault() const; - inline void GetStringValue( char* dst, size_t len, const CSplitScreenSlot& index = 0 ) const { GetConVarData()->GetStringValue( dst, len, index ); } + void ValueToString( CSplitScreenSlot slot, CBufferString &buf ) const { TypeTraits()->ValueToString( ValueOrDefault( slot ), buf ); } + void DefaultValueToString( CBufferString &buf ) const { TypeTraits()->ValueToString( m_defaultValue, buf ); } + void MinValueToString( CBufferString &buf ) const; + void MaxValueToString( CBufferString &buf ) const; + + void Construct( CSplitScreenSlot slot ) const { if(IsSlotInRange( slot )) TypeTraits()->Construct( Value( slot ) ); } + void Destruct( CSplitScreenSlot slot ) const { if(IsSlotInRange( slot )) TypeTraits()->Destruct( Value( slot ) ); } + bool IsEqual( CSplitScreenSlot slot, CVValue_t *other ) const { return TypeTraits()->Equal( ValueOrDefault( slot ), other ); } + void Clamp( CSplitScreenSlot slot ) const { if(IsSlotInRange( slot )) TypeTraits()->Clamp( Value( slot ), m_minValue, m_maxValue ); } - inline void GetStringDefaultValue( char* dst, size_t len ) const { GetConVarData()->GetStringDefaultValue( dst, len ); } - inline void GetStringMinValue( char* dst, size_t len ) const { GetConVarData()->GetStringMinValue( dst, len ); } - inline void GetStringMaxValue( char* dst, size_t len ) const { GetConVarData()->GetStringMaxValue( dst, len ); } private: - void Init(ConVarHandle defaultHandle, EConVarType type) - { - this->m_Handle.Invalidate( ); - this->m_ConVarData = nullptr; + bool IsSlotInRange( CSplitScreenSlot slot ) const { return slot.Get() == -1 || (slot.Get() >= 0 && slot.Get() < GetMaxSplitScreenSlots()); } - if ( g_pCVar ) - { - auto cvar = g_pCVar->GetConVar( defaultHandle ); - this->m_ConVarData = ( cvar && cvar->Cast( ) ) ? cvar : nullptr; - if ( !this->m_ConVarData ) - { - this->m_ConVarData = GetInvalidConVar( TranslateConVarType( ) ); - } - // technically this - //result = *(char ***)(sub_10B7760((unsigned int)a3) + 80); - } - this->m_Handle = defaultHandle; - } + const char* m_pszName; - void Register(const char* name, int32_t flags, const char* description, ConVarCreation_t& cvar) - { - this->m_ConVarData = GetInvalidConVar( cvar.m_eVarType ); - this->m_Handle.Invalidate(); - - if (!CommandLine()->HasParm("-tools") - && (flags & (FCVAR_DEVELOPMENTONLY - |FCVAR_ARCHIVE - |FCVAR_USERINFO - |FCVAR_CHEAT - |FCVAR_RELEASE - |FCVAR_SERVER_CAN_EXECUTE - |FCVAR_CLIENT_CAN_EXECUTE - |FCVAR_CLIENTCMD_CAN_EXECUTE)) == 0) - { - flags |= FCVAR_DEVELOPMENTONLY; - } + // Default value is expected to always be present, + // even if convar wasn't created with default value + // it would use global per type default value in that case + CVValue_t* m_defaultValue; - cvar.m_pszName = name; - cvar.m_pszHelpString = description; - cvar.m_nFlags = flags; + // Min/Max Could be nullptr if not set + CVValue_t* m_minValue; + CVValue_t* m_maxValue; - cvar.m_pHandle = &this->m_Handle; - cvar.m_pConVarData = &this->m_ConVarData; + const char* m_pszHelpString; + EConVarType m_eVarType; - SetupConVar(cvar); - } + // Might be set by a gameinfo config via "version" key + short m_Version; - inline void UpdateValue( const T& value, const CSplitScreenSlot& index, const CVValue_t* newValue, const CVValue_t* oldValue, const char* szNewValue, const char* szOldValue ) - { - GetConVarData()->SetValue( value, index ); + unsigned int m_iTimesChanged; + uint64 m_nFlags; - GetConVarData()->SetTimesChanged( GetConVarData()->GetTimesChanged( ) + 1 ); - g_pCVar->CallChangeCallback( this->m_Handle, index, newValue, oldValue ); - g_pCVar->CallGlobalChangeCallbacks( this, index, szNewValue, szOldValue ); - } + // Index into a linked list of cvar callbacks + unsigned int m_iCallbackIndex; + + int m_GameInfoFlags; + + // At convar registration this is trimmed to better match convar type being used + // or if it was initialized as EConVarType_Invalid it would be of this size + uint8 m_Values[sizeof( CVValue_t ) * MAX_SPLITSCREEN_CLIENTS]; }; -static_assert(sizeof(ConVar) == 0x10, "ConVar is of the wrong size!"); -static_assert(sizeof(ConVar) == sizeof(ConVar), "Templated ConVar size varies!"); -// Special case for string -template<> inline void ConVar::SetValue( const char*const& val, const CSplitScreenSlot& index ) +static ConVarData *GetInvalidConVarData( EConVarType type ) { - auto newValue = this->Clamp( val ); - - char szNewValue[256], szOldValue[256]; - CConVarData::ValueToString( newValue, szNewValue, sizeof(szNewValue) ); - GetConVarData()->GetStringValue( szOldValue, sizeof(szOldValue), index ); + Assert( type >= EConVarType_Invalid && type < EConVarType_MAX ); + + static ConVarData s_InvalidConVar[EConVarType_MAX + 1] = { + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ), + ConVarData( TranslateConVarType() ) // EConVarType_MAX + }; - this->UpdateValue( newValue, index, (const CVValue_t*)&newValue, (const CVValue_t*)&szOldValue, szNewValue, szOldValue ); + if(type == EConVarType_Invalid) + { + return &s_InvalidConVar[EConVarType_MAX]; + } + return &s_InvalidConVar[type]; } -//----------------------------------------------------------------------------- +//----------------------------------------------------------------- +// Used to read/write/create convars (replaces the FindVar method) +//----------------------------------------------------------------- +class ConVarRef +{ +private: + static const uint16 kInvalidAccessIndex = 0xFFFF; + +public: + ConVarRef() : m_ConVarAccessIndex( kInvalidAccessIndex ), m_ConVarRegisteredIndex( 0 ) {} + ConVarRef( uint16 convar_idx ) : m_ConVarAccessIndex( convar_idx ), m_ConVarRegisteredIndex( 0 ) {} + ConVarRef( uint16 convar_idx, int registered_idx ) : m_ConVarAccessIndex( convar_idx ), m_ConVarRegisteredIndex( registered_idx ) {} + + ConVarRef( const char *name, bool allow_defensive = false ); + + void InvalidateRef() { m_ConVarAccessIndex = kInvalidAccessIndex; m_ConVarRegisteredIndex = 0; } + bool IsValidRef() const { return m_ConVarAccessIndex != kInvalidAccessIndex; } + uint16 GetAccessIndex() const { return m_ConVarAccessIndex; } + int GetRegisteredIndex() const { return m_ConVarRegisteredIndex; } + +protected: + // Index into internal linked list of concommands + uint16 m_ConVarAccessIndex; + // ConVar registered positional index + int m_ConVarRegisteredIndex; +}; -#ifdef CONVAR_WORK_FINISHED -class CSplitScreenAddedConVar : public ConVar +class ConVarRefAbstract : public ConVarRef { - typedef ConVar BaseClass; public: - CSplitScreenAddedConVar( int nSplitScreenSlot, const char *pName, const ConVar *pBaseVar ) : - BaseClass - ( - pName, - pBaseVar->GetDefault(), - // Keep basevar flags, except remove _SS and add _SS_ADDED instead - ( pBaseVar->GetFlags() & ~FCVAR_SS ) | FCVAR_SS_ADDED, - pBaseVar->GetHelpText(), - pBaseVar->HasMin(), - pBaseVar->GetMinValue(), - pBaseVar->HasMax(), - pBaseVar->GetMaxValue() - ), - m_pBaseVar( pBaseVar ), - m_nSplitScreenSlot( nSplitScreenSlot ) + typedef ConVarRef BaseClass; + + ConVarRefAbstract( const char *name, bool allow_defensive = false ) + : BaseClass( name, allow_defensive ), m_ConVarData( nullptr ) { - for ( int i = 0; i < pBaseVar->GetChangeCallbackCount(); ++i ) - { - InstallChangeCallback( pBaseVar->GetChangeCallback( i ), false ); - } - Assert( nSplitScreenSlot >= 1 ); - Assert( nSplitScreenSlot < MAX_SPLITSCREEN_CLIENTS ); - Assert( m_pBaseVar ); - Assert( IsFlagSet( FCVAR_SS_ADDED ) ); - Assert( !IsFlagSet( FCVAR_SS ) ); + Init( *this ); } - const ConVar *GetBaseVar() const; - virtual const char *GetBaseName() const; - void SetSplitScreenPlayerSlot( int nSlot ); - virtual int GetSplitScreenPlayerSlot() const; + ConVarRefAbstract( ConVarRef ref, EConVarType type = EConVarType_Invalid ) + : BaseClass( ref ), m_ConVarData( nullptr ) + { + Init( *this, type ); + } + + const char *GetName() const { return m_ConVarData->GetName(); } + const char *GetHelpString() const { return m_ConVarData->GetHelpString(); } + bool HasHelpString() const { return m_ConVarData->HasHelpString(); } + + EConVarType GetType() const { return m_ConVarData->GetType(); } + + bool HasDefault() const { return m_ConVarData->HasDefaultValue(); } + bool HasMin() const { return m_ConVarData->HasMinValue(); } + bool HasMax() const { return m_ConVarData->HasMaxValue(); } + + bool IsFlagSet( uint64 flag ) const { return m_ConVarData->IsFlagSet( flag ); } + void AddFlags( uint64 flags ) { m_ConVarData->AddFlags( flags ); } + void RemoveFlags( uint64 flags ) { return m_ConVarData->RemoveFlags( flags ); } + uint64 GetFlags( void ) const { return m_ConVarData->GetFlags(); } + + // Returns true if convar should be treated as hidden + bool ShouldBeHidden() const { return !m_ConVarData || IsFlagSet( FCVAR_REFERENCE | FCVAR_HIDDEN | FCVAR_DEVELOPMENTONLY ); } + + bool IsSetToDefault( CSplitScreenSlot slot = -1 ) const { return m_ConVarData->IsSetToDefault( slot ); } + bool IsAllSetToDefault() const { return m_ConVarData->IsAllSetToDefault(); } + + void GetValueAsString( CBufferString &buf, CSplitScreenSlot slot = -1 ) const { m_ConVarData->ValueToString( slot, buf ); } + void GetDefaultAsString( CBufferString &buf ) const { m_ConVarData->DefaultValueToString( buf ); } + void GetMinAsString( CBufferString &buf ) const { m_ConVarData->MinValueToString( buf ); } + void GetMaxAsString( CBufferString &buf ) const { m_ConVarData->MaxValueToString( buf ); } + + bool IsValuePrimitive() const { return m_ConVarData->GetType() != EConVarType_Invalid && m_ConVarData->IsPrimitiveType(); } + + // Attempts to get value as a type T, does type conversion if possible, + // if no such action is available for CvarType/T combo, global default value for type T would be returned + template + const T GetAs( CSplitScreenSlot slot = -1 ) const; + + // Attempts to get value as a bool, does type conversion if possible, + // if no such action is available for CvarType/bool combo, global default value for bool would be returned + bool GetBool( CSplitScreenSlot slot = -1 ) const { return GetAs( slot ); } + // Attempts to get value as a float, does type conversion if possible, + // if no such action is available for CvarType/float combo, global default value for float would be returned + float GetFloat( CSplitScreenSlot slot = -1 ) const { return GetAs( slot ); } + // Attempts to get value as a int, does type conversion if possible, + // if no such action is available for CvarType/int combo, global default value for int would be returned + int GetInt( CSplitScreenSlot slot = -1 ) const { return GetAs( slot ); } + // Parses the value to string, mostly the same to GetValueAsString + CUtlString GetString( CSplitScreenSlot slot = -1 ) const; + + // Attempts to set value as a type T, does type conversion if possible, + // if no such action is available for CvarType/T combo, no action would be done + // + // AMNOTE: Using this function (as well as SetBool, SetFloat and SetInt) in a + // change callbacks (either global or cvar one) will result in a crash since it + // does constructor casts to CConVarRef which would be invalid if setvalue is queued + // (which will happen in callbacks), so the solution is to do a static_cast to + // CConVarRef yourself on the cvar you receive in a callback and call .Set() on it + template + void SetAs( T value, CSplitScreenSlot slot = -1 ); + + // Attempts to set value as a bool, does type conversion if possible, + // if no such action is available for CvarType/bool combo, no action would be done + void SetBool( bool value, CSplitScreenSlot slot = -1 ) { SetAs( value, slot ); } + // Attempts to set value as a float, does type conversion if possible, + // if no such action is available for CvarType/float combo, no action would be done + void SetFloat( float value, CSplitScreenSlot slot = -1 ) { SetAs( value, slot ); } + // Attempts to set value as a int, does type conversion if possible, + // if no such action is available for CvarType/int combo, no action would be done + void SetInt( int value, CSplitScreenSlot slot = -1 ) { SetAs( value, slot ); } + // Parses the string to CvarType type, returns true on success, false otherwise + bool SetString( CUtlString string, CSplitScreenSlot slot = -1 ); + + // Reset to default value + void Revert( CSplitScreenSlot slot = -1 ); + // Clamps value to min/max bounds if set + void Clamp( CSplitScreenSlot slot = -1 ) { m_ConVarData->Clamp( slot ); } + + CVarTypeTraits *TypeTraits() const { return m_ConVarData->TypeTraits(); } + ConVarData* GetConVarData() const { return m_ConVarData; }; + + // Checks if stored ConVarData points to invalid convar data + bool IsConVarDataValid() const { return m_ConVarData && GetType() != EConVarType_Invalid && m_ConVarData != TypeTraits()->m_InvalidCvarData; } + + // Checks if ConVarData is available for usage (means cvar was registered), + // mostly useful for CConVarRef cvars which register themselves partially + bool IsConVarDataAvailable() const { return !m_ConVarData->IsFlagSet( FCVAR_REFERENCE ) && IsConVarDataValid(); } protected: + ConVarRefAbstract() : BaseClass(), m_ConVarData( nullptr ) {} - const ConVar *m_pBaseVar; - int m_nSplitScreenSlot; -}; + void CopyRef( const ConVarRefAbstract &ref ) + { + m_ConVarAccessIndex = ref.m_ConVarAccessIndex; + m_ConVarRegisteredIndex = ref.m_ConVarRegisteredIndex; + m_ConVarData = ref.m_ConVarData; + } -FORCEINLINE_CVAR const ConVar *CSplitScreenAddedConVar::GetBaseVar() const -{ - Assert( m_pBaseVar ); - return m_pBaseVar; -} + void CallChangeCallbacks( CSplitScreenSlot slot, CVValue_t *new_value, CVValue_t *prev_value, const char *new_str, const char *prev_str ); -FORCEINLINE_CVAR const char *CSplitScreenAddedConVar::GetBaseName() const -{ - Assert( m_pBaseVar ); - return m_pBaseVar->GetName(); -} + void SetOrQueueValueInternal( CSplitScreenSlot slot, CVValue_t *value ); + void QueueSetValueInternal( CSplitScreenSlot slot, CVValue_t *value ); + void SetValueInternal( CSplitScreenSlot slot, CVValue_t *value ); -FORCEINLINE_CVAR void CSplitScreenAddedConVar::SetSplitScreenPlayerSlot( int nSlot ) -{ - m_nSplitScreenSlot = nSlot; -} + // Does type conversion from CvarType to type T, only valid for primitive types + template + T ConvertFromPrimitiveTo( CSplitScreenSlot slot ) const; + // Does type conversion from type T to CvarType, only valid for primitive types + template + void ConvertToPrimitiveFrom( CSplitScreenSlot slot, T value ) const; -FORCEINLINE_CVAR int CSplitScreenAddedConVar::GetSplitScreenPlayerSlot() const -{ - return m_nSplitScreenSlot; -} + // Initialises this cvar, if ref is invalid, ConVarData would be initialised to invalid convar data of a set type + void Init( ConVarRef ref, EConVarType type = EConVarType_Invalid ); -#if 0 -//----------------------------------------------------------------------------- -// Helper for referencing splitscreen convars (i.e., "name" and "name2") -//----------------------------------------------------------------------------- -class SplitScreenConVarRef + void InvalidateConVarData( EConVarType type = EConVarType_Invalid ); + + ConVarData* m_ConVarData; +}; + +uint64 SanitiseConVarFlags( uint64 flags ); +void SetupConVar( ConVarRef *cvar, ConVarData **cvar_data, ConVarCreation_t &info ); +void UnRegisterConVar( ConVarRef *cvar ); + +template +class CConVarRef : public ConVarRefAbstract { public: - SplitScreenConVarRef( const char *pName ); - SplitScreenConVarRef( const char *pName, bool bIgnoreMissing ); - SplitScreenConVarRef( IConVar *pConVar ); + typedef ConVarRefAbstract BaseClass; - void Init( const char *pName, bool bIgnoreMissing ); - bool IsValid() const; - bool IsFlagSet( int64 nFlags ) const; + // Creates a convar ref that will pre-register convar in a system if it's not yet registered + // otherwise it just acts as a normal reference to a convar + // Mostly useful for cross module convar access, where you can't guarantee the order of creation + // and can't get direct access to convar CConVar + CConVarRef( const char *name ) : BaseClass() + { + ConVarValueInfo_t value_info( TranslateConVarType() ); + Register( name, FCVAR_REFERENCE, nullptr, value_info ); + } - // Get/Set value - float GetFloat( int nSlot ) const; - int GetInt( int nSlot ) const; - Color GetColor( int nSlot ) const; - bool GetBool( int nSlot ) const { return !!GetInt( nSlot ); } - const char *GetString( int nSlot ) const; + // Constructs typed cvar ref if the type matches, otherwise this would be initialised to invalid convar data! + CConVarRef( const ConVarRefAbstract &ref ) : BaseClass() + { + // If the ref type doesn't match ours, bad cast was attempted, + // fall back to invalid cvar data + if(ref.GetType() == TranslateConVarType()) + CopyRef( ref ); + else + Init( ConVarRef(), TranslateConVarType() ); + } - void SetValue( int nSlot, const char *pValue ); - void SetValue( int nSlot, float flValue ); - void SetValue( int nSlot, int nValue ); - void SetValue( int nSlot, Color value ); - void SetValue( int nSlot, bool bValue ); + // Constructs typed cvar ref if the type matches, otherwise this would be initialised to invalid convar data! + CConVarRef( const ConVarRef &ref ) : CConVarRef( ConVarRefAbstract( ref ) ) { } - const char *GetName( int nSlot ) const; + const T &Get( CSplitScreenSlot slot = -1 ) const { return *reinterpret_cast(m_ConVarData->ValueOrDefault( slot )); } + void Set( const T &value, CSplitScreenSlot slot = -1 ); - const char *GetDefault() const; + const T &GetDefault() const { *reinterpret_cast(m_ConVarData->DefaultValue()); } + const T &GetMin() const { *reinterpret_cast(m_ConVarData->MinValue()); } + const T &GetMax() const { *reinterpret_cast(m_ConVarData->MaxValue()); } - const char *GetBaseName() const; +protected: + CConVarRef() : BaseClass() {} -private: - struct cv_t + void Register( const char *name, uint64 flags, const char *help_string, const ConVarValueInfo_t &value_info ) { - IConVar *m_pConVar; - ConVar *m_pConVarState; - }; + Assert( name ); + + ConVarCreation_t info; + info.m_pszName = name; + info.m_pszHelpString = help_string; + info.m_nFlags = SanitiseConVarFlags( flags ); + info.m_valueInfo = value_info; - cv_t m_Info[ MAX_SPLITSCREEN_CLIENTS ]; + SetupConVar( this, &m_ConVarData, info ); + } }; -//----------------------------------------------------------------------------- -// Did we find an existing convar of that name? -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR bool SplitScreenConVarRef::IsFlagSet( int64 nFlags ) const +template +class CConVar : public CConVarRef { - return ( m_Info[ 0 ].m_pConVar->IsFlagSet( nFlags ) != 0 ); -} +public: + typedef CConVarRef BaseClass; -FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetName( int nSlot ) const -{ - return m_Info[ nSlot ].m_pConVar->GetName(); -} + using FnChangeCallback_t = void(*)(CConVar *ref, CSplitScreenSlot nSlot, const T *pNewValue, const T *pOldValue); -FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetBaseName() const -{ - return m_Info[ 0 ].m_pConVar->GetBaseName(); -} + CConVar( const char *name, uint64 flags, const char *help_string, const T &default_value, FnChangeCallback_t cb = nullptr ) + : BaseClass() + { + ConVarValueInfo_t value_info( TranslateConVarType() ); + value_info.SetDefaultValue( default_value ); + value_info.m_fnCallBack = reinterpret_cast(cb); -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a float -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR float SplitScreenConVarRef::GetFloat( int nSlot ) const + BaseClass::Register( name, flags, help_string, value_info ); + } + + CConVar( const char *name, uint64 flags, const char *help_string, const T &default_value, bool min, const T &minValue, bool max, const T &maxValue, FnChangeCallback_t cb = nullptr ) + : BaseClass() + { + ConVarValueInfo_t value_info( TranslateConVarType() ); + value_info.SetDefaultValue( default_value ); + + if(min) + value_info.SetMinValue( minValue ); + + if(max) + value_info.SetMaxValue( maxValue ); + + value_info.m_fnCallBack = reinterpret_cast(cb); + + BaseClass::Register( name, flags, help_string, value_info ); + } + + ~CConVar() + { + UnRegisterConVar( this ); + BaseClass::InvalidateConVarData(); + } +}; + +template +inline const T ConVarRefAbstract::GetAs( CSplitScreenSlot slot ) const { - return m_Info[ nSlot ].m_pConVarState->m_Value.m_fValue; + CVValue_t *value = m_ConVarData->ValueOrDefault( slot ); + + if(GetType() == TranslateConVarType()) + return *value; + else if(GetType() == EConVarType_String) + { + CVValue_t obj; + GetCvarTypeTraits( TranslateConVarType() )->Construct( &obj ); + + if(GetCvarTypeTraits( TranslateConVarType() )->StringToValue( value->m_StringValue.Get(), &obj )) + { + T ret = obj; + GetCvarTypeTraits( TranslateConVarType() )->Destruct( &obj ); + return ret; + } + + GetCvarTypeTraits( TranslateConVarType() )->Destruct( &obj ); + } + else if(IsValuePrimitive()) + return ConvertFromPrimitiveTo( slot ); + + return *GetInvalidConVarData( TranslateConVarType() )->DefaultValue(); } -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as an int -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR int SplitScreenConVarRef::GetInt( int nSlot ) const +template<> +inline const CUtlString ConVarRefAbstract::GetAs( CSplitScreenSlot slot ) const { - return m_Info[ nSlot ].m_pConVarState->m_Value.m_nValue; + CBufferString buf; + GetValueAsString( buf, slot ); + return buf.Get(); } -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as an int -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR Color SplitScreenConVarRef::GetColor( int nSlot ) const +inline CUtlString ConVarRefAbstract::GetString( CSplitScreenSlot slot ) const { - return m_Info[ nSlot ].m_pConVarState->GetColor(); + return GetAs( slot ); } -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc. -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetString( int nSlot ) const +template +inline T ConVarRefAbstract::ConvertFromPrimitiveTo( CSplitScreenSlot slot ) const { - Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) ); - return m_Info[ nSlot ].m_pConVarState->m_Value.m_pszString; -} + if constexpr(std::is_literal_type_v) + { + CVValue_t *value = m_ConVarData->ValueOrDefault( slot ); + switch(GetType()) + { + case EConVarType_Bool: return value->m_bValue; + case EConVarType_Int16: return value->m_i16Value; + case EConVarType_UInt16: return value->m_u16Value; + case EConVarType_Int32: return value->m_i32Value; + case EConVarType_UInt32: return value->m_u32Value; + case EConVarType_Int64: return value->m_i64Value; + case EConVarType_UInt64: return value->m_u64Value; + case EConVarType_Float32: return value->m_fl32Value; + case EConVarType_Float64: return value->m_fl64Value; + } + } -FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, const char *pValue ) -{ - m_Info[ nSlot ].m_pConVar->SetValue( pValue ); + return *GetInvalidConVarData( TranslateConVarType() )->DefaultValue(); } -FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, float flValue ) +template +inline void CConVarRef::Set( const T &value, CSplitScreenSlot slot ) { - m_Info[ nSlot ].m_pConVar->SetValue( flValue ); -} + CVValue_t *cvvalue = m_ConVarData->Value( slot ); -FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, int nValue ) -{ - m_Info[ nSlot ].m_pConVar->SetValue( nValue ); + if(cvvalue) + { + CVValue_t newval; + TypeTraits()->Construct( &newval ); + TypeTraits()->Copy( &newval, value ); + + SetOrQueueValueInternal( slot, &newval ); + + TypeTraits()->Destruct( &newval ); + } } -FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, Color value ) +template +inline void ConVarRefAbstract::SetAs( T value, CSplitScreenSlot slot ) { - m_Info[ nSlot ].m_pConVar->SetValue( value ); + if(GetType() == TranslateConVarType()) + { + CConVarRef( *this ).Set( value, slot ); + } + else if(GetType() == EConVarType_String) + { + CBufferString buf; + CVValue_t cvvalue( value ); + GetCvarTypeTraits( TranslateConVarType() )->ValueToString( &cvvalue, buf ); + + CConVarRef( *this ).Set( buf.Get(), slot ); + } + else if(IsValuePrimitive()) + { + ConvertToPrimitiveFrom( slot, value ); + } } -FORCEINLINE_CVAR void SplitScreenConVarRef::SetValue( int nSlot, bool bValue ) +template<> inline void ConVarRefAbstract::SetAs( CUtlString value, CSplitScreenSlot slot ) { - m_Info[ nSlot ].m_pConVar->SetValue( bValue ? 1 : 0 ); + SetString( value, slot ); } -FORCEINLINE_CVAR const char *SplitScreenConVarRef::GetDefault() const +template +inline void ConVarRefAbstract::ConvertToPrimitiveFrom( CSplitScreenSlot slot, T value ) const { - return m_Info[ 0 ].m_pConVarState->m_pszDefaultValue; + if constexpr(std::is_literal_type_v) + { + switch(GetType()) + { + case EConVarType_Bool: return CConVarRef( *this ).Set( value, slot ); + case EConVarType_Int16: return CConVarRef( *this ).Set( value, slot ); + case EConVarType_UInt16: return CConVarRef( *this ).Set( value, slot ); + case EConVarType_Int32: return CConVarRef( *this ).Set( value, slot ); + case EConVarType_UInt32: return CConVarRef( *this ).Set( value, slot ); + case EConVarType_Int64: return CConVarRef( *this ).Set( value, slot ); + case EConVarType_UInt64: return CConVarRef( *this ).Set( value, slot ); + case EConVarType_Float32: return CConVarRef( *this ).Set( value, slot ); + case EConVarType_Float64: return CConVarRef( *this ).Set( value, slot ); + } + } } -#endif -#endif // CONVAR_WORK_FINISHED //----------------------------------------------------------------------------- // Called by the framework to register ConVars and ConCommands with the ICVar //----------------------------------------------------------------------------- -void ConVar_Register( int64 nCVarFlag = 0 ); +void ConVar_Register( uint64 nCVarFlag = 0 ); void ConVar_Unregister( ); //----------------------------------------------------------------------------- // Utility methods //----------------------------------------------------------------------------- -void ConVar_PrintDescription( const CVarCreationBase_t* pVar ); +void ConVar_PrintDescription( const ConVarRefAbstract *ref ); //----------------------------------------------------------------------------- @@ -967,8 +1386,8 @@ class CConCommandMemberAccessor : public ICommandCallback, public ICommandComple typedef int ( T::*FnMemberCommandCompletionCallback_t )( const CCommand &command, CUtlVector< CUtlString > &completions ); public: - CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0, - int64 flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) : + CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString, + uint64 flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) : BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL ) { m_pOwner = pOwner; diff --git a/public/tier1/strtools.h b/public/tier1/strtools.h index 95ad8ddb2..b0cf7c425 100644 --- a/public/tier1/strtools.h +++ b/public/tier1/strtools.h @@ -310,6 +310,46 @@ PLATFORM_INTERFACE float64 V_StringToFloat64Raw(const char *buf, float64 default // Parses string as a float32 value, if the parsing fails, default_value is returned, doesn't perform error checking/reporting PLATFORM_INTERFACE float32 V_StringToFloat32Raw(const char *buf, float32 default_value, bool *successful = NULL, char **remainder = NULL); +// Templatised and shortened version of the generic V_StringTo* functions +// these are silent, so you won't get error console warnings if parsing fails by default +template +inline bool V_StringToValue( const char *string, T &value, uint flags = PARSING_FLAG_SKIP_ASSERT | PARSING_FLAG_SKIP_WARNING ); + +template <> inline bool V_StringToValue( const char *string, bool &value, uint flags ) +{ bool success = false; value = V_StringToBool( string, false, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, int8 &value, uint flags ) +{ bool success = false; value = V_StringToInt8( string, 0, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, uint8 &value, uint flags ) +{ bool success = false; value = V_StringToUint8( string, 0, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, int16 &value, uint flags ) +{ bool success = false; value = V_StringToInt16( string, 0, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, uint16 &value, uint flags ) +{ bool success = false; value = V_StringToUint16( string, 0, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, int32 &value, uint flags ) +{ bool success = false; value = V_StringToInt32( string, 0, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, uint32 &value, uint flags ) +{ bool success = false; value = V_StringToUint32( string, 0, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, int64 &value, uint flags ) +{ bool success = false; value = V_StringToInt64( string, 0, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, uint64 &value, uint flags ) +{ bool success = false; value = V_StringToUint64( string, 0, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, float32 &value, uint flags ) +{ bool success = false; value = V_StringToFloat32( string, 0.0f, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, float64 &value, uint flags ) +{ bool success = false; value = V_StringToFloat64( string, 0.0, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, Vector &value, uint flags ) +{ bool success = false; V_StringToVector( string, value, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, Vector2D &value, uint flags ) +{ bool success = false; V_StringToVector2D( string, value, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, Vector4D &value, uint flags ) +{ bool success = false; V_StringToVector4D( string, value, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, Color &value, uint flags ) +{ bool success = false; V_StringToColor( string, value, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, QAngle &value, uint flags ) +{ bool success = false; V_StringToQAngle( string, value, &success, nullptr, flags ); return success; } +template <> inline bool V_StringToValue( const char *string, Quaternion &value, uint flags ) +{ bool success = false; V_StringToQuaternion( string, value, &success, nullptr, flags ); return success; } + // returns string immediately following prefix, (ie str+strlen(prefix)) or NULL if prefix not found PLATFORM_INTERFACE const char *_V_StringAfterPrefix( const char *str, const char *prefix ); PLATFORM_INTERFACE const char *_V_StringAfterPrefixCaseSensitive( const char *str, const char *prefix ); diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 9ead09f91..0dcbf5b12 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -33,22 +33,22 @@ // Statically constructed list of ConCommandBases, // used for registering them with the ICVar interface //----------------------------------------------------------------------------- -static int64 s_nCVarFlag = 0; +static uint64 s_nCVarFlag = 0; static bool s_bRegistered = false; class ConCommandRegList { public: - struct ConCommandCreationEntry_t + struct Entry_t { ConCommandCreation_t m_Info; ConCommand *m_Command = nullptr; }; - static void RegisterCommand( ConCommandCreationEntry_t &cmd ) + static void RegisterConCommand( const Entry_t &cmd ) { *cmd.m_Command = g_pCVar->RegisterConCommand( cmd.m_Info, s_nCVarFlag ); - if(!cmd.m_Command->IsValid()) + if(!cmd.m_Command->IsValidRef()) { Plat_FatalErrorFunc( "RegisterConCommand: Unknown error registering con command \"%s\"!\n", cmd.m_Info.m_pszName ); DebuggerBreakIfDebugging(); @@ -66,7 +66,7 @@ class ConCommandRegList { for(int i = 0; i < list->m_nSize; i++) { - RegisterCommand( list->m_Entries[i] ); + RegisterConCommand( list->m_Entries[i] ); } prev = list->m_pPrev; @@ -75,8 +75,14 @@ class ConCommandRegList } } - static void AddToList( const ConCommandCreationEntry_t &cmd ) + static void AddToList( const Entry_t &cmd ) { + if(s_bConCommandsRegistered) + { + RegisterConCommand( cmd ); + return; + } + auto list = s_pRoot; if(!list || list->m_nSize >= sizeof( m_Entries ) / sizeof( m_Entries[0] )) @@ -93,7 +99,7 @@ class ConCommandRegList private: int m_nSize; - ConCommandCreationEntry_t m_Entries[100]; + Entry_t m_Entries[100]; ConCommandRegList *m_pPrev; public: @@ -106,103 +112,144 @@ ConCommandRegList *ConCommandRegList::s_pRoot = nullptr; void SetupConCommand( ConCommand *cmd, const ConCommandCreation_t& info ) { - ConCommandRegList::ConCommandCreationEntry_t entry; + ConCommandRegList::Entry_t entry; entry.m_Info = info; entry.m_Command = cmd; - if (ConCommandRegList::s_bConCommandsRegistered && s_bRegistered) - { - ConCommandRegList::RegisterCommand( entry ); - return; - } - ConCommandRegList::AddToList( entry ); } -void UnRegisterCommand( ConCommand *cmd ) +void UnRegisterConCommand( ConCommand *cmd ) { - if(cmd->IsValid()) + if(cmd->IsValidRef()) { - g_pCVar->UnregisterConCommand( *cmd ); + if(g_pCVar) + g_pCVar->UnregisterConCommandCallbacks( *cmd ); - cmd->Invalidate(); + cmd->InvalidateRef(); } } -void RegisterConVar( ConVarCreation_t& cvar ) -{ - g_pCVar->RegisterConVar( cvar, s_nCVarFlag, cvar.m_pHandle, cvar.m_pConVarData ); - if (!cvar.m_pHandle->IsValid()) - { - Plat_FatalErrorFunc( "RegisterConVar: Unknown error registering convar \"%s\"!\n", cvar.m_pszName ); - DebuggerBreakIfDebugging(); - } -} - -void UnRegisterConVar( ConVarHandle& cvar ) +class ConVarRegList { - if (cvar.IsValid()) +public: + struct Entry_t { - g_pCVar->UnregisterConVar( cvar ); + ConVarCreation_t m_Info; - cvar.Invalidate(); - } -} + ConVarRef *m_pConVar = nullptr; + ConVarData **m_pConVarData = nullptr; + }; -class ConVarRegList -{ -public: - static ConVarRegList* GetRegList() + static void RegisterConVar( const Entry_t &cvar ) { - static ConVarRegList* list = new ConVarRegList(); - return list; + g_pCVar->RegisterConVar( cvar.m_Info, s_nCVarFlag, cvar.m_pConVar, cvar.m_pConVarData ); + if(!cvar.m_pConVar->IsValidRef()) + { + Plat_FatalErrorFunc( "RegisterConVar: Unknown error registering convar \"%s\"!\n", cvar.m_Info.m_pszName ); + DebuggerBreakIfDebugging(); + } } static void RegisterAll() { - if ( !s_bConVarsRegistered && g_pCVar ) + if(!s_bConVarsRegistered && g_pCVar) { s_bConVarsRegistered = true; - ConVarRegList* list = GetRegList(); - FOR_EACH_VEC( list->m_Vec, i ) + ConVarRegList *prev = nullptr; + for(auto list = s_pRoot; list; list = prev) { - RegisterConVar( list->m_Vec[i] ); - } - delete list; + for(int i = 0; i < list->m_nSize; i++) + { + RegisterConVar( list->m_Entries[i] ); + } + + prev = list->m_pPrev; + delete list; + }; } } -private: - friend void SetupConVar( ConVarCreation_t& cvar ); - - void Add( const ConVarCreation_t& cvar ) + static void AddToList( const Entry_t &cvar ) { - m_Vec.AddToTail( cvar ); + if(s_bConVarsRegistered) + { + RegisterConVar( cvar ); + return; + } + + auto list = s_pRoot; + + if(!list || list->m_nSize >= sizeof( m_Entries ) / sizeof( m_Entries[0] )) + { + list = new ConVarRegList; + list->m_nSize = 0; + list->m_pPrev = s_pRoot; + + s_pRoot = list; + } + + list->m_Entries[list->m_nSize++] = cvar; } - CUtlVector m_Vec; +private: + int m_nSize; + Entry_t m_Entries[100]; + ConVarRegList *m_pPrev; + public: static bool s_bConVarsRegistered; + static ConVarRegList *s_pRoot; }; bool ConVarRegList::s_bConVarsRegistered = false; +ConVarRegList *ConVarRegList::s_pRoot = nullptr; + +void SetupConVar( ConVarRef *cvar, ConVarData **cvar_data, ConVarCreation_t &info ) +{ + ConVarRegList::Entry_t entry; + entry.m_Info = info; + entry.m_pConVar = cvar; + entry.m_pConVarData = cvar_data; + + ConVarRegList::AddToList( entry ); +} -void SetupConVar( ConVarCreation_t& cvar ) +void UnRegisterConVar( ConVarRef *cvar ) { - if ( ConVarRegList::s_bConVarsRegistered ) + if(cvar->IsValidRef()) { - RegisterConVar(cvar); - return; + if(g_pCVar) + g_pCVar->UnregisterConVarCallbacks( *cvar ); + + cvar->InvalidateRef(); } - - ConVarRegList::GetRegList()->Add( cvar ); +} + +uint64 SanitiseConVarFlags( uint64 flags ) +{ +#ifdef SANITIZE_CVAR_FLAGS + if(!CommandLine()->HasParm( "-tools" ) + && (flags & (FCVAR_DEVELOPMENTONLY + | FCVAR_ARCHIVE + | FCVAR_USERINFO + | FCVAR_CHEAT + | FCVAR_RELEASE + | FCVAR_SERVER_CAN_EXECUTE + | FCVAR_CLIENT_CAN_EXECUTE + | FCVAR_CLIENTCMD_CAN_EXECUTE)) == 0) + { + flags |= FCVAR_DEFENSIVE | FCVAR_DEVELOPMENTONLY; + } +#endif + return flags; } //----------------------------------------------------------------------------- // Called by the framework to register ConCommandBases with the ICVar //----------------------------------------------------------------------------- -void ConVar_Register( int64 nCVarFlag ) +void ConVar_Register( uint64 nCVarFlag ) { if ( !g_pCVar || s_bRegistered ) { @@ -391,53 +438,30 @@ int CCommand::FindArgInt( const char *pName, int nDefaultVal ) const return nDefaultVal; } -ConCommandRef::ConCommandRef( const char *command, bool allow_developer ) +ConCommandRef::ConCommandRef( const char *name, bool allow_developer ) { - *this = g_pCVar->FindCommand( command, allow_developer ); + *this = g_pCVar->FindConCommand( name, allow_developer ); } ConCommandData *ConCommandRef::GetRawData() { - return g_pCVar->GetCommand( *this ); + return g_pCVar->GetConCommandData( *this ); } -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pName - -// callback - -// *pHelpString - -// flags - -//----------------------------------------------------------------------------- -void ConCommand::Create( const char* pName, const ConCommandCallbackInfo_t &cb, const char* pHelpString, int64_t flags, const ConCommandCompletionCallbackInfo_t &completion_cb ) +void ConCommandRef::Dispatch( const CCommandContext &context, const CCommand &command ) +{ + g_pCVar->DispatchConCommand( *this, context, command ); +} + +void ConCommand::Create( const char* pName, const ConCommandCallbackInfo_t &cb, const char* pHelpString, uint64 flags, const ConCommandCompletionCallbackInfo_t &completion_cb ) { // Name should be static data Assert(pName); - Assert(pHelpString); ConCommandCreation_t info; info.m_pszName = pName; info.m_pszHelpString = pHelpString; - -#ifdef SANITIZE_CVAR_FLAGS - if(!CommandLine()->HasParm( "-tools" ) - && (flags & (FCVAR_CLIENTDLL - | FCVAR_HIDDEN - | FCVAR_USERINFO - | FCVAR_MISSING0 - | FCVAR_PER_USER - | FCVAR_MENUBAR_ITEM - | FCVAR_MISSING3 - | FCVAR_SERVER_CAN_EXECUTE - | FCVAR_VCONSOLE_SET_FOCUS - | FCVAR_CLIENTCMD_CAN_EXECUTE - | FCVAR_DEFENSIVE - | FCVAR_MISSING4)) == 0) - { - flags |= FCVAR_DEFENSIVE | FCVAR_DEVELOPMENTONLY; - } -#endif - - info.m_nFlags = flags; + info.m_nFlags = SanitiseConVarFlags( flags ); info.m_CBInfo = cb; info.m_CompletionCBInfo = completion_cb; @@ -446,7 +470,7 @@ void ConCommand::Create( const char* pName, const ConCommandCallbackInfo_t &cb, void ConCommand::Destroy() { - UnRegisterCommand( this ); + UnRegisterConCommand( this ); } //----------------------------------------------------------------------------- @@ -455,168 +479,227 @@ void ConCommand::Destroy() // //----------------------------------------------------------------------------- -#ifdef CONVAR_WORK_FINISHED +int ConVarData::GetMaxSplitScreenSlots() const +{ + if((m_nFlags & FCVAR_PER_USER) != 0) + return g_pCVar->GetMaxSplitScreenSlots(); -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void ConVar_PrintFlags( const ConCommandBase *var ) + return 1; +} + +CVValue_t *ConVarData::Value( CSplitScreenSlot slot ) const { - bool any = false; - if ( var->IsFlagSet( FCVAR_GAMEDLL ) ) - { - ConMsg( " game" ); - any = true; - } + if(slot.Get() == -1) + slot = CSplitScreenSlot( 0 ); - if ( var->IsFlagSet( FCVAR_CLIENTDLL ) ) - { - ConMsg( " client" ); - any = true; - } + if(!IsSlotInRange( slot )) + return nullptr; - if ( var->IsFlagSet( FCVAR_ARCHIVE ) ) - { - ConMsg( " archive" ); - any = true; - } + return (CVValue_t *)&m_Values[GetDataByteSize() * slot.Get()]; +} - if ( var->IsFlagSet( FCVAR_NOTIFY ) ) - { - ConMsg( " notify" ); - any = true; - } +CVValue_t *ConVarData::ValueOrDefault( CSplitScreenSlot slot ) const +{ + CVValue_t *value = Value( slot ); + return value ? value : m_defaultValue; +} - if ( var->IsFlagSet( FCVAR_SPONLY ) ) +bool ConVarData::IsAllSetToDefault() const +{ + for(int i = 0; i < GetMaxSplitScreenSlots(); i++) { - ConMsg( " singleplayer" ); - any = true; + if(!IsSetToDefault( i )) + return false; } - if ( var->IsFlagSet( FCVAR_NOT_CONNECTED ) ) - { - ConMsg( " notconnected" ); - any = true; - } + return true; +} - if ( var->IsFlagSet( FCVAR_CHEAT ) ) - { - ConMsg( " cheat" ); - any = true; - } +void ConVarData::MinValueToString( CBufferString &buf ) const +{ + if(HasMinValue()) + TypeTraits()->ValueToString( m_minValue, buf ); + else + buf.Insert( 0, "" ); +} - if ( var->IsFlagSet( FCVAR_REPLICATED ) ) - { - ConMsg( " replicated" ); - any = true; - } +void ConVarData::MaxValueToString( CBufferString &buf ) const +{ + if(HasMaxValue()) + TypeTraits()->ValueToString( m_maxValue, buf ); + else + buf.Insert( 0, "" ); +} - if ( var->IsFlagSet( FCVAR_SERVER_CAN_EXECUTE ) ) - { - ConMsg( " server_can_execute" ); - any = true; - } +ConVarRef::ConVarRef( const char *name, bool allow_developer ) +{ + *this = g_pCVar->FindConVar( name, allow_developer ); +} - if ( var->IsFlagSet( FCVAR_CLIENTCMD_CAN_EXECUTE ) ) - { - ConMsg( " clientcmd_can_execute" ); - any = true; - } +void ConVarRefAbstract::Init( ConVarRef ref, EConVarType type ) +{ + m_ConVarData = nullptr; - if ( any ) - { - ConMsg( "\n" ); - } + if(g_pCVar) + m_ConVarData = g_pCVar->GetConVarData( ref ); + + if(!m_ConVarData) + InvalidateConVarData( type ); } +void ConVarRefAbstract::InvalidateConVarData( EConVarType type ) +{ + if(type == EConVarType_Invalid) + m_ConVarData = GetInvalidConVarData( EConVarType_Invalid ); + else + m_ConVarData = GetCvarTypeTraits( type )->m_InvalidCvarData; +} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void ConVar_PrintDescription( const ConCommandBase *pVar ) +void ConVarRefAbstract::CallChangeCallbacks( CSplitScreenSlot slot, CVValue_t *new_value, CVValue_t *prev_value, const char *new_str, const char *prev_str ) { - bool bMin, bMax; - float fMin, fMax; - const char *pStr; + if(slot.Get() == -1) + slot = CSplitScreenSlot( 0 ); - Assert( pVar ); + g_pCVar->CallChangeCallback( *this, slot, new_value, prev_value ); + g_pCVar->CallGlobalChangeCallbacks( this, slot, new_str, prev_str ); +} - Color clr; - clr.SetColor( 255, 100, 100, 255 ); +void ConVarRefAbstract::SetOrQueueValueInternal( CSplitScreenSlot slot, CVValue_t *value ) +{ + if(m_ConVarData->IsFlagSet( FCVAR_PERFORMING_CALLBACKS )) + QueueSetValueInternal( slot, value ); + else + SetValueInternal( slot, value ); +} - if ( !pVar->IsCommand() ) - { - ConVar *var = ( ConVar * )pVar; - const ConVar_ServerBounded *pBounded = dynamic_cast( var ); +void ConVarRefAbstract::QueueSetValueInternal( CSplitScreenSlot slot, CVValue_t *value ) +{ + if(slot.Get() == -1) + slot = CSplitScreenSlot( 0 ); - bMin = var->GetMin( fMin ); - bMax = var->GetMax( fMax ); + TypeTraits()->Clamp( value, m_ConVarData->MinValue(), m_ConVarData->MaxValue() ); - const char *value = NULL; - char tempVal[ 32 ]; + if(!m_ConVarData->IsEqual( slot, value )) + g_pCVar->QueueThreadSetValue( this, slot, value ); +} - if ( pBounded || var->IsFlagSet( FCVAR_NEVER_AS_STRING ) ) - { - value = tempVal; - - int intVal = pBounded ? pBounded->GetInt() : var->GetInt(); - float floatVal = pBounded ? pBounded->GetFloat() : var->GetFloat(); +void ConVarRefAbstract::SetValueInternal( CSplitScreenSlot slot, CVValue_t *value ) +{ + CVValue_t *curr_value = m_ConVarData->ValueOrDefault( slot ); - if ( fabs( (float)intVal - floatVal ) < 0.000001 ) - { - Q_snprintf( tempVal, sizeof( tempVal ), "%d", intVal ); - } - else - { - Q_snprintf( tempVal, sizeof( tempVal ), "%f", floatVal ); - } - } - else - { - value = var->GetString(); - } + CVValue_t prev; + TypeTraits()->Construct( &prev ); - if ( value ) - { - ConColorMsg( clr, "\"%s\" = \"%s\"", var->GetName(), value ); + TypeTraits()->Copy( &prev, *curr_value ); + TypeTraits()->Destruct( curr_value ); - if ( stricmp( value, var->GetDefault() ) ) - { - ConMsg( " ( def. \"%s\" )", var->GetDefault() ); - } - } + TypeTraits()->Copy( curr_value, *value ); + m_ConVarData->Clamp( slot ); - if ( bMin ) - { - ConMsg( " min. %f", fMin ); - } - if ( bMax ) - { - ConMsg( " max. %f", fMax ); - } + if(!m_ConVarData->IsEqual( slot, &prev )) + { + CBufferString prev_str, new_str; - ConMsg( "\n" ); + TypeTraits()->ValueToString( &prev, prev_str ); + TypeTraits()->ValueToString( curr_value, new_str ); - // Handled virtualized cvars. - if ( pBounded && fabs( pBounded->GetFloat() - var->GetFloat() ) > 0.0001f ) - { - ConColorMsg( clr, "** NOTE: The real value is %.3f but the server has temporarily restricted it to %.3f **\n", - var->GetFloat(), pBounded->GetFloat() ); - } + m_ConVarData->IncrementTimesChanged(); + + CallChangeCallbacks( slot, curr_value, &prev, new_str.Get(), prev_str.Get() ); } - else + + TypeTraits()->Destruct( &prev ); +} + +bool ConVarRefAbstract::SetString( CUtlString string, CSplitScreenSlot slot ) +{ + CVValue_t *value = m_ConVarData->Value( slot ); + + if(!value) + return true; + + if(GetType() != EConVarType_String) + string.Trim( "\t\n\v\f\r " ); + + CVValue_t new_value; + TypeTraits()->Construct( &new_value ); + + bool success = false; + if(TypeTraits()->StringToValue( string.Get(), &new_value )) + { + SetOrQueueValueInternal( slot, &new_value ); + success = true; + } + + TypeTraits()->Destruct( &new_value ); + return success; +} + +void ConVarRefAbstract::Revert( CSplitScreenSlot slot ) +{ + CBufferString buf; + GetDefaultAsString( buf ); + SetString( buf.Get(), slot ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ConVar_PrintDescription( const ConVarRefAbstract *ref ) +{ + Assert( ref ); + + static struct + { + uint64 m_Flag; + const char *m_Name; + } s_FlagsMap[] = { + { FCVAR_GAMEDLL, "game" }, + { FCVAR_CLIENTDLL, "client" }, + { FCVAR_ARCHIVE, "archive" }, + { FCVAR_NOTIFY, "notify" }, + { FCVAR_SPONLY, "singleplayer" }, + { FCVAR_NOT_CONNECTED, "notconnected" }, + { FCVAR_CHEAT, "cheat" }, + { FCVAR_REPLICATED, "replicated" }, + { FCVAR_SERVER_CAN_EXECUTE, "server_can_execute" }, + { FCVAR_CLIENTCMD_CAN_EXECUTE, "clientcmd_can_execute" }, + { FCVAR_USERINFO, "userinfo" }, + { FCVAR_PER_USER, "per_user" } + }; + + CBufferStringN<4096> desc; + CBufferString buf; + + ref->GetValueAsString( buf ); + desc.AppendFormat( "\"%s\" = \"%s\"", ref->GetName(), buf.Get() ); + + if(!ref->IsSetToDefault()) { - ConCommand *var = ( ConCommand * )pVar; + ref->GetDefaultAsString( buf ); + desc.AppendFormat( " ( def. \"%s\" )", buf.Get() ); + } - ConColorMsg( clr, "\"%s\"\n", var->GetName() ); + if(ref->HasMin()) + { + ref->GetMinAsString( buf ); + desc.AppendFormat( " min. %s", buf.Get() ); } - ConVar_PrintFlags( pVar ); + if(ref->HasMax()) + { + ref->GetMaxAsString( buf ); + desc.AppendFormat( " max. %s", buf.Get() ); + } - pStr = pVar->GetHelpText(); - if ( pStr && pStr[0] ) + for(int i = 0; i < sizeof( s_FlagsMap ) / sizeof( s_FlagsMap[0] ); i++) { - ConMsg( " - %s\n", pStr ); + if(ref->IsFlagSet( s_FlagsMap[i].m_Flag )) + desc.AppendFormat( " %s", s_FlagsMap[i].m_Name ); } + + if(ref->HasHelpString()) + ConMsg( "%-120s - %s\n", desc.Get(), ref->GetHelpString() ); + else + ConMsg( "%-120s\n", desc.Get() ); } -#endif // CONVAR_WORK_FINISHED From 7324340c444d2f2c6c739182cc3ea37feac9d5f0 Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Fri, 7 Feb 2025 19:19:34 +0300 Subject: [PATCH 44/48] Add CCvar --- public/icvar.h | 123 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/public/icvar.h b/public/icvar.h index 5df74d2e0..512848627 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -13,6 +13,8 @@ #include "appframework/IAppSystem.h" #include "tier1/utlvector.h" #include "tier1/characterset.h" +#include "utllinkedlist.h" +#include "utlhashtable.h" #include "tier0/memalloc.h" #include "convar.h" #include @@ -130,6 +132,127 @@ abstract_class ICvar : public IAppSystem virtual void QueueThreadSetValue( ConVarRefAbstract* ref, CSplitScreenSlot nSlot, CVValue_t* value ) = 0; }; +#include "memdbgon.h" + +// AMNOTE: CCvar definition is mostly for reference and is reverse engineered +// You shouldn't be using this to directly register cvars/concommands, use its interface instead when possible +class CCvar : public ICvar +{ +public: + static const int kMemoryBufferChunkMaxSize = 8192; + static const int kStringBufferChunkMaxSize = 2048; + + // Allocates memory in its internal buffer, can't be freed + // (other than freeing internal buffers completely), so is leaky and thus use cautiously + // AMNOTE: Mostly used for allocating CVValue_t and ConVarData/ConCommandData objects + void *AllocateMemory( int size ) + { + int aligned_size = ALIGN_VALUE( size, 8 ); + + if(aligned_size + m_CurrentMemoryBufferSize > kMemoryBufferChunkMaxSize) + { + m_CurrentMemoryBufferSize = 0; + *m_MemoryBuffer.AddToTailGetPtr() = (uint8 *)malloc( kMemoryBufferChunkMaxSize ); + } + + int offs = m_CurrentMemoryBufferSize; + m_CurrentMemoryBufferSize += aligned_size; + + return &m_MemoryBuffer[m_MemoryBuffer.Count() - 1][offs]; + } + + // Allocates memory in its internal string buffer, can't be freed + // (other than freeing internal buffers completely), so is leaky and thus use cautiously + // AMNOTE: Mostly used for allocating cvar/concommand names + const char *AllocateString( const char *string ) + { + if(!string || !string[0]) + return ""; + + int strlen = V_strlen( string ) + 1; + + if(strlen + m_CurrentStringsBufferSize > kStringBufferChunkMaxSize) + { + m_CurrentStringsBufferSize = 0; + *m_StringsBuffer.AddToTailGetPtr() = (char *)malloc( kStringBufferChunkMaxSize ); + } + + int offs = m_CurrentStringsBufferSize; + m_CurrentStringsBufferSize += strlen; + + char *base = &m_StringsBuffer[m_StringsBuffer.Count() - 1][offs]; + V_memmove( base, string, strlen ); + + return base; + } + + struct CConVarChangeCallbackNode_t + { + FnGenericChangeCallback_t m_pCallback; + + // Register index of cvar which change cb comes from + int m_ConVarIndex; + }; + + struct ConCommandCallbackInfoNode_t + { + ConCommandCallbackInfo_t m_CB; + + // Register index of concommand which completion cb comes from + int m_ConCmdIndex; + // Index in a linkedlist of callbackinfos + uint16 m_CallbackInfoIndex; + }; + + struct QueuedConVarSet_t + { + ConVarRefAbstract *m_ConVar; + CSplitScreenSlot m_Slot; + CVValue_t *m_Value; + }; + + CUtlVector m_StringsBuffer; + CUtlVector m_MemoryBuffer; + int m_CurrentStringsBufferSize; + int m_CurrentMemoryBufferSize; + + CUtlLinkedList m_ConVarList; + CUtlHashtable m_ConVarHashes; + CUtlLinkedList m_ConVarChangeCBList; + int m_ConVarCount; + + CUtlVector m_CvarCreationListeners; + CUtlVector m_GlobalChangeCBList; + + CUtlLinkedList m_ConCommandList; + CUtlHashtable m_ConCommandHashes; + CUtlLinkedList m_CallbackInfoList; + int m_ConCommandCount; + + int m_SplitScreenSlots; + + CThreadMutex m_Mutex; + characterset_t m_CharacterSet; + KeyValues *m_GameInfoKV; + + uint8 m_CvarDefaultValues[EConVarType_MAX][128]; + + CUtlVector m_SetValueQueue; + + CConCommandMemberAccessor m_FindCmd; + CConCommandMemberAccessor m_DumpChannelsCmd; + CConCommandMemberAccessor m_LogLevelCmd; + CConCommandMemberAccessor m_LogVerbosityCmd; + CConCommandMemberAccessor m_LogColorCmd; + CConCommandMemberAccessor m_LogFlagsCmd; + CConCommandMemberAccessor m_DifferencesCmd; + CConCommandMemberAccessor m_CvarListCmd; + CConCommandMemberAccessor m_HelpCmd; + CConCommandMemberAccessor m_FindFlagsCmd; +}; + +#include "memdbgoff.h" + //----------------------------------------------------------------------------- // These global names are defined by tier1.h, duplicated here so you // don't have to include tier1.h From 8ba042bf98f21a0c7a59f86a7833fc5f3f216bc5 Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Fri, 7 Feb 2025 19:26:42 +0300 Subject: [PATCH 45/48] Cleanup CONVAR_WORK_FINISHED defines --- public/schemasystem/schemasystem.h | 8 ----- public/tier1/convar_serverbounded.h | 54 ----------------------------- tier1/convar.cpp | 1 - 3 files changed, 63 deletions(-) delete mode 100644 public/tier1/convar_serverbounded.h diff --git a/public/schemasystem/schemasystem.h b/public/schemasystem/schemasystem.h index 452d704e1..b9e1e0dba 100644 --- a/public/schemasystem/schemasystem.h +++ b/public/schemasystem/schemasystem.h @@ -180,20 +180,12 @@ class CSchemaSystem : public ISchemaSystem int m_nNumConnections; CThreadFastMutex m_Mutex; -#ifdef CONVAR_WORK_FINISHED CConCommandMemberAccessor m_SchemaListBindings; CConCommandMemberAccessor m_SchemaAllListBindings; CConCommandMemberAccessor m_SchemaDumpBinding; CConCommandMemberAccessor m_SchemaDetailedClassLayout; CConCommandMemberAccessor m_SchemaStats; CConCommandMemberAccessor m_SchemaMetaStats; -#else -#ifdef _WIN32 - uint8 pad[288]; -#else - uint8 pad[384]; -#endif // _WIN32 -#endif // CONVAR_WORK_FINISHED CUtlVector m_LoadedModules; CUtlVector m_DetectedSchemaMismatches; diff --git a/public/tier1/convar_serverbounded.h b/public/tier1/convar_serverbounded.h deleted file mode 100644 index 94b1ecb7e..000000000 --- a/public/tier1/convar_serverbounded.h +++ /dev/null @@ -1,54 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Helper class for cvars that have restrictions on their value. -// -//=============================================================================// - -#ifndef CONVAR_SERVERBOUNDED_H -#define CONVAR_SERVERBOUNDED_H -#ifdef _WIN32 -#pragma once -#endif - -#ifdef CONVAR_WORK_FINISHED -// This class is used to virtualize a ConVar's value, so the client can restrict its -// value while connected to a server. When using this across modules, it's important -// to dynamic_cast it to a ConVar_ServerBounded or you won't get the restricted value. -// -// NOTE: FCVAR_USERINFO vars are not virtualized before they are sent to the server -// (we have no way to detect if the virtualized value would change), so -// if you want to use a bounded cvar's value on the server, you must rebound it -// the same way the client does. -class ConVar_ServerBounded : public ConVar -{ -public: - ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) - : ConVar( pName, pDefaultValue, flags, pHelpString ) - { - } - - ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, FnChangeCallback_t callback ) - : ConVar( pName, pDefaultValue, flags, pHelpString, callback ) - { - } - - ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) - : ConVar( pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax ) {} - - // You must implement GetFloat. - virtual float GetFloat() const = 0; - - // You can optionally implement these. - virtual int GetInt() const { return (int)GetFloat(); } - virtual bool GetBool() const { return ( GetInt() != 0 ); } - - // Use this to get the underlying cvar's value. - float GetBaseFloatValue() const - { - return ConVar::GetFloat(); - } -}; -#endif // CONVAR_WORK_FINISHED - - -#endif // CONVAR_SERVERBOUNDED_H diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 0dcbf5b12..1e8fa3312 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -17,7 +17,6 @@ #include "tier1/utlvector.h" #include "tier1/utlbuffer.h" #include "tier1/tier1.h" -#include "tier1/convar_serverbounded.h" #include "icvar.h" #include "tier0/dbg.h" #include "Color.h" From 0b6378070cea7356863cbca74972dc0f32129be6 Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Mon, 10 Feb 2025 17:17:33 +0300 Subject: [PATCH 46/48] Few small corrections --- public/icvar.h | 2 +- public/tier1/convar.h | 14 ++++++++++++-- tier1/convar.cpp | 16 ++++++++-------- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index 512848627..f407ea21c 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -120,7 +120,7 @@ abstract_class ICvar : public IAppSystem virtual ConVarData* GetConVarData( ConVarRef cvar ) = 0; // Register, unregister commands - virtual ConCommand RegisterConCommand( const ConCommandCreation_t& setup, uint64 nAdditionalFlags = 0 ) = 0; + virtual ConCommandRef RegisterConCommand( const ConCommandCreation_t& setup, uint64 nAdditionalFlags = 0 ) = 0; // Unregisters concommand callbacks, but leaves the command in the lists, // so all ConCommandRefs would still be valid as well as searching for it. // Expects ref to have registered index to be set (is set on command creation) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index dff5c60ba..f9e4111b8 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -1056,7 +1056,7 @@ class ConVarRefAbstract : public ConVarRef // Attempts to get value as a float, does type conversion if possible, // if no such action is available for CvarType/float combo, global default value for float would be returned float GetFloat( CSplitScreenSlot slot = -1 ) const { return GetAs( slot ); } - // Attempts to get value as a int, does type conversion if possible, + // Attempts to get value as an int, does type conversion if possible, // if no such action is available for CvarType/int combo, global default value for int would be returned int GetInt( CSplitScreenSlot slot = -1 ) const { return GetAs( slot ); } // Parses the value to string, mostly the same to GetValueAsString @@ -1079,7 +1079,7 @@ class ConVarRefAbstract : public ConVarRef // Attempts to set value as a float, does type conversion if possible, // if no such action is available for CvarType/float combo, no action would be done void SetFloat( float value, CSplitScreenSlot slot = -1 ) { SetAs( value, slot ); } - // Attempts to set value as a int, does type conversion if possible, + // Attempts to set value as an int, does type conversion if possible, // if no such action is available for CvarType/int combo, no action would be done void SetInt( int value, CSplitScreenSlot slot = -1 ) { SetAs( value, slot ); } // Parses the string to CvarType type, returns true on success, false otherwise @@ -1179,6 +1179,8 @@ class CConVarRef : public ConVarRefAbstract { Assert( name ); + Init( ConVarRef(), TranslateConVarType() ); + ConVarCreation_t info; info.m_pszName = name; info.m_pszHelpString = help_string; @@ -1200,6 +1202,10 @@ class CConVar : public CConVarRef CConVar( const char *name, uint64 flags, const char *help_string, const T &default_value, FnChangeCallback_t cb = nullptr ) : BaseClass() { + Assert( name ); + + BaseClass::Init( ConVarRef(), TranslateConVarType() ); + ConVarValueInfo_t value_info( TranslateConVarType() ); value_info.SetDefaultValue( default_value ); value_info.m_fnCallBack = reinterpret_cast(cb); @@ -1210,6 +1216,10 @@ class CConVar : public CConVarRef CConVar( const char *name, uint64 flags, const char *help_string, const T &default_value, bool min, const T &minValue, bool max, const T &maxValue, FnChangeCallback_t cb = nullptr ) : BaseClass() { + Assert( name ); + + BaseClass::Init( ConVarRef(), TranslateConVarType() ); + ConVarValueInfo_t value_info( TranslateConVarType() ); value_info.SetDefaultValue( default_value ); diff --git a/tier1/convar.cpp b/tier1/convar.cpp index 1e8fa3312..e55d45bcf 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -41,7 +41,7 @@ class ConCommandRegList struct Entry_t { ConCommandCreation_t m_Info; - ConCommand *m_Command = nullptr; + ConCommandRef *m_Command = nullptr; }; static void RegisterConCommand( const Entry_t &cmd ) @@ -63,7 +63,7 @@ class ConCommandRegList ConCommandRegList *prev = nullptr; for(auto list = s_pRoot; list; list = prev) { - for(int i = 0; i < list->m_nSize; i++) + for(size_t i = 0; i < list->m_nSize; i++) { RegisterConCommand( list->m_Entries[i] ); } @@ -84,7 +84,7 @@ class ConCommandRegList auto list = s_pRoot; - if(!list || list->m_nSize >= sizeof( m_Entries ) / sizeof( m_Entries[0] )) + if(!list || list->m_nSize >= (sizeof( m_Entries ) / sizeof( m_Entries[0] ))) { list = new ConCommandRegList; list->m_nSize = 0; @@ -97,7 +97,7 @@ class ConCommandRegList } private: - int m_nSize; + uint32 m_nSize; Entry_t m_Entries[100]; ConCommandRegList *m_pPrev; @@ -159,7 +159,7 @@ class ConVarRegList ConVarRegList *prev = nullptr; for(auto list = s_pRoot; list; list = prev) { - for(int i = 0; i < list->m_nSize; i++) + for(size_t i = 0; i < list->m_nSize; i++) { RegisterConVar( list->m_Entries[i] ); } @@ -180,7 +180,7 @@ class ConVarRegList auto list = s_pRoot; - if(!list || list->m_nSize >= sizeof( m_Entries ) / sizeof( m_Entries[0] )) + if(!list || list->m_nSize >= (sizeof( m_Entries ) / sizeof( m_Entries[0] ))) { list = new ConVarRegList; list->m_nSize = 0; @@ -193,7 +193,7 @@ class ConVarRegList } private: - int m_nSize; + uint32 m_nSize; Entry_t m_Entries[100]; ConVarRegList *m_pPrev; @@ -691,7 +691,7 @@ void ConVar_PrintDescription( const ConVarRefAbstract *ref ) desc.AppendFormat( " max. %s", buf.Get() ); } - for(int i = 0; i < sizeof( s_FlagsMap ) / sizeof( s_FlagsMap[0] ); i++) + for(size_t i = 0; i < (sizeof( s_FlagsMap ) / sizeof( s_FlagsMap[0] )); i++) { if(ref->IsFlagSet( s_FlagsMap[i].m_Flag )) desc.AppendFormat( " %s", s_FlagsMap[i].m_Name ); From 8e5bebd253a44adfdf7d5e6e0b9a50a2fca701cb Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Tue, 11 Feb 2025 21:14:47 +0300 Subject: [PATCH 47/48] Remove ConCommandBase declaration --- public/icvar.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/public/icvar.h b/public/icvar.h index f407ea21c..c70c4f499 100644 --- a/public/icvar.h +++ b/public/icvar.h @@ -19,9 +19,6 @@ #include "convar.h" #include -// TO-DO: Remove Metamod ConVar PR is finished -class ConCommandBase; - // Shorthand helper to iterate registered convars // Example usage: // FOR_EACH_CONVAR( iter ) From ebb5d6b2bb18be623849bb98dbf18bcbe0892c24 Mon Sep 17 00:00:00 2001 From: GAMMACASE <31375974+GAMMACASE@users.noreply.github.com> Date: Tue, 11 Feb 2025 21:15:26 +0300 Subject: [PATCH 48/48] Add concommand/convar register callbacks --- public/tier1/convar.h | 65 +++++++++++++++++++++++++++---------------- tier1/convar.cpp | 21 ++++++++++---- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/public/tier1/convar.h b/public/tier1/convar.h index f9e4111b8..476cb1b5a 100644 --- a/public/tier1/convar.h +++ b/public/tier1/convar.h @@ -500,8 +500,8 @@ class ConCommandData { public: const char *GetName() const { return m_pszName; } - const char *GetHelpString() const { return m_pszHelpString; } - bool HasHelpString() const { return m_pszHelpString && m_pszHelpString[0]; } + const char *GetHelpText() const { return m_pszHelpString; } + bool HasHelpText() const { return m_pszHelpString && m_pszHelpString[0]; } bool IsFlagSet( uint64 flag ) const { return (m_nFlags & flag) != 0; } void AddFlags( uint64 flags ) { m_nFlags |= flags; } @@ -548,8 +548,8 @@ class ConCommandRef const ConCommandData *GetRawData() const { return const_cast(this)->GetRawData(); } const char *GetName() const { return GetRawData()->GetName(); } - const char *GetHelpString() const { return GetRawData()->GetHelpString(); } - bool HasHelpString() const { return GetRawData()->HasHelpString(); } + const char *GetHelpText() const { return GetRawData()->GetHelpText(); } + bool HasHelpText() const { return GetRawData()->HasHelpText(); } bool IsFlagSet( uint64 flag ) const { return GetRawData()->GetFlags(); } void AddFlags( uint64 flags ) { GetRawData()->AddFlags( flags ); } @@ -817,26 +817,34 @@ class ConVarData }; ConVarData( EConVarType type = EConVarType_Invalid ) : - m_pszName( "" ), - m_defaultValue( CVValue_t::InvalidValue() ), - m_minValue( nullptr ), - m_maxValue( nullptr ), - m_pszHelpString( "This convar is being accessed prior to ConVar_Register being called" ), - m_eVarType( type ), - m_Version( 0 ), - m_iTimesChanged( 0 ), - m_nFlags( FCVAR_REFERENCE ), - m_iCallbackIndex( 0 ), - m_GameInfoFlags( 0 ), m_Values {} - {} + { + Invalidate( type, true ); + } + + // Helper method to invalidate convar data to its default, pre-register state + void Invalidate( EConVarType type = EConVarType_Invalid, bool as_undefined = false ) + { + if(as_undefined) + m_pszName = ""; + m_defaultValue = CVValue_t::InvalidValue(); + m_minValue = nullptr; + m_maxValue = nullptr; + m_pszHelpString = as_undefined ? "This convar is being accessed prior to ConVar_Register being called" : nullptr; + m_eVarType = type; + m_Version = 0; + m_iTimesChanged = 0; + m_nFlags = FCVAR_REFERENCE; + m_iCallbackIndex = 0; + m_GameInfoFlags = 0; + } const char *GetName( void ) const { return m_pszName; } - const char *GetHelpString( void ) const { return m_pszHelpString; } - bool HasHelpString() const { return m_pszHelpString && m_pszHelpString[0]; } + const char *GetHelpText( void ) const { return m_pszHelpString; } + bool HasHelpText() const { return m_pszHelpString && m_pszHelpString[0]; } + + EConVarType GetType() const { return m_eVarType; } - EConVarType GetType( void ) const { return m_eVarType; } - short GetVersion() const { return m_Version; } int GetTimesChanged() const { return m_iTimesChanged; } @@ -1017,9 +1025,15 @@ class ConVarRefAbstract : public ConVarRef Init( *this, type ); } + ConVarRefAbstract( const ConVarRefAbstract &ref ) + : BaseClass(), m_ConVarData( nullptr ) + { + CopyRef( ref ); + } + const char *GetName() const { return m_ConVarData->GetName(); } - const char *GetHelpString() const { return m_ConVarData->GetHelpString(); } - bool HasHelpString() const { return m_ConVarData->HasHelpString(); } + const char *GetHelpText() const { return m_ConVarData->GetHelpText(); } + bool HasHelpText() const { return m_ConVarData->HasHelpText(); } EConVarType GetType() const { return m_ConVarData->GetType(); } @@ -1132,7 +1146,7 @@ class ConVarRefAbstract : public ConVarRef }; uint64 SanitiseConVarFlags( uint64 flags ); -void SetupConVar( ConVarRef *cvar, ConVarData **cvar_data, ConVarCreation_t &info ); +void SetupConVar( ConVarRefAbstract *cvar, ConVarData **cvar_data, ConVarCreation_t &info ); void UnRegisterConVar( ConVarRef *cvar ); template @@ -1371,7 +1385,10 @@ inline void ConVarRefAbstract::ConvertToPrimitiveFrom( CSplitScreenSlot slot, T //----------------------------------------------------------------------------- // Called by the framework to register ConVars and ConCommands with the ICVar //----------------------------------------------------------------------------- -void ConVar_Register( uint64 nCVarFlag = 0 ); +typedef void (*FnConVarRegisterCallback)(ConVarRefAbstract *ref); +typedef void (*FnConCommandRegisterCallback)(ConCommandRef *ref); + +void ConVar_Register( uint64 nCVarFlag = 0, FnConVarRegisterCallback cvar_reg_cb = nullptr, FnConCommandRegisterCallback cmd_reg_cb = nullptr ); void ConVar_Unregister( ); diff --git a/tier1/convar.cpp b/tier1/convar.cpp index e55d45bcf..98ccb0ae7 100644 --- a/tier1/convar.cpp +++ b/tier1/convar.cpp @@ -29,9 +29,11 @@ // #define SANITIZE_CVAR_FLAGS 1 //----------------------------------------------------------------------------- -// Statically constructed list of ConCommandBases, +// Statically constructed list of ConVars/ConCommands, // used for registering them with the ICVar interface //----------------------------------------------------------------------------- +static FnConVarRegisterCallback s_ConVarRegCB = nullptr; +static FnConCommandRegisterCallback s_ConCommandRegCB = nullptr; static uint64 s_nCVarFlag = 0; static bool s_bRegistered = false; @@ -52,6 +54,8 @@ class ConCommandRegList Plat_FatalErrorFunc( "RegisterConCommand: Unknown error registering con command \"%s\"!\n", cmd.m_Info.m_pszName ); DebuggerBreakIfDebugging(); } + else if(s_ConCommandRegCB) + s_ConCommandRegCB( cmd.m_Command ); } static void RegisterAll() @@ -136,7 +140,7 @@ class ConVarRegList { ConVarCreation_t m_Info; - ConVarRef *m_pConVar = nullptr; + ConVarRefAbstract *m_pConVar = nullptr; ConVarData **m_pConVarData = nullptr; }; @@ -148,6 +152,9 @@ class ConVarRegList Plat_FatalErrorFunc( "RegisterConVar: Unknown error registering convar \"%s\"!\n", cvar.m_Info.m_pszName ); DebuggerBreakIfDebugging(); } + // Don't let references pass as a newly registered cvar + else if(s_ConVarRegCB && (cvar.m_Info.m_nFlags & FCVAR_REFERENCE) == 0) + s_ConVarRegCB( cvar.m_pConVar ); } static void RegisterAll() @@ -205,7 +212,7 @@ class ConVarRegList bool ConVarRegList::s_bConVarsRegistered = false; ConVarRegList *ConVarRegList::s_pRoot = nullptr; -void SetupConVar( ConVarRef *cvar, ConVarData **cvar_data, ConVarCreation_t &info ) +void SetupConVar( ConVarRefAbstract *cvar, ConVarData **cvar_data, ConVarCreation_t &info ) { ConVarRegList::Entry_t entry; entry.m_Info = info; @@ -248,7 +255,7 @@ uint64 SanitiseConVarFlags( uint64 flags ) //----------------------------------------------------------------------------- // Called by the framework to register ConCommandBases with the ICVar //----------------------------------------------------------------------------- -void ConVar_Register( uint64 nCVarFlag ) +void ConVar_Register( uint64 nCVarFlag, FnConVarRegisterCallback cvar_reg_cb, FnConCommandRegisterCallback cmd_reg_cb ) { if ( !g_pCVar || s_bRegistered ) { @@ -257,6 +264,8 @@ void ConVar_Register( uint64 nCVarFlag ) s_bRegistered = true; s_nCVarFlag = nCVarFlag; + s_ConVarRegCB = cvar_reg_cb; + s_ConCommandRegCB = cmd_reg_cb; ConCommandRegList::RegisterAll(); ConVarRegList::RegisterAll(); @@ -697,8 +706,8 @@ void ConVar_PrintDescription( const ConVarRefAbstract *ref ) desc.AppendFormat( " %s", s_FlagsMap[i].m_Name ); } - if(ref->HasHelpString()) - ConMsg( "%-120s - %s\n", desc.Get(), ref->GetHelpString() ); + if(ref->HasHelpText()) + ConMsg( "%-120s - %s\n", desc.Get(), ref->GetHelpText() ); else ConMsg( "%-120s\n", desc.Get() ); }