diff --git a/public/icvar.h b/public/icvar.h index b7c88d3f9..ddaf19764 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: // @@ -11,21 +11,442 @@ #endif #include "appframework/IAppSystem.h" -#include "tier1/convar.h" #include "tier1/utlvector.h" +#include "tier1/characterset.h" #include "tier0/memalloc.h" +#include "mathlib/vector4d.h" +#include +// TO-DO: Remove Metamod ConVar PR is finished class ConCommandBase; + +class BaseConVar; class ConCommand; -class ConVar; -class Color; +class CCommand; +class CCommandContext; +class ICVarListenerCallbacks; class IConVarListener; -class CConVarDetail; +struct ConVarCreation_t; +struct ConCommandCreation_t; struct ConVarSnapshot_t; -union CVValue_t; class KeyValues; -class ConVarRefAbstract; +template +class ConVar; + +union CVValue_t +{ + template + inline CVValue_t& operator=(const 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!"); + +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; +}; + +//----------------------------------------------------------------------------- +// 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(); + +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 +//----------------------------------------------------------------------------- +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) + { + } + + 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; + + // This gets copied from the ConVarDesc_t on creation + short unk1; + + 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; +}; + +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 +{ +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]; +}; + +// 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 @@ -37,7 +458,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; @@ -47,8 +468,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( BaseConVar* ref, CSplitScreenSlot nSlot, const char* newValue, const char* oldValue ) = 0; // Reverts cvars which contain a specific flag virtual void RevertFlaggedConVars( int nFlag ) = 0; @@ -72,16 +492,16 @@ 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 UnregisterConVar( ConVarHandle handle ) = 0; - virtual ConVar* GetConVar( ConVarHandle handle ) = 0; + 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; // Register, unregister commands - virtual ConCommandHandle RegisterConCommand( ConCommand *pCmd, int64 nAdditionalFlags = 0 ) = 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( ConVarRefAbstract *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 45cd85523..79b8fc906 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,10 +19,14 @@ #include "tier0/dbg.h" #include "tier1/utlvector.h" #include "tier1/utlstring.h" +#include "tier1/characterset.h" #include "Color.h" -#include "mathlib/vector4d.h" +#include "cvar.h" #include "playerslot.h" +#include +#include + #ifdef _WIN32 #define FORCEINLINE_CVAR FORCEINLINE #elif POSIX @@ -43,27 +47,27 @@ //----------------------------------------------------------------------------- // Forward declarations //----------------------------------------------------------------------------- -class ConVar; class CCommand; class ConCommand; -class ConCommandBase; -class ConVarRefAbstract; -class ConCommandRefAbstract; -struct characterset_t; -class ALIGN8 ConVarHandle +struct CVarCreationBase_t { -public: - bool IsValid() { return value != kInvalidConVarHandle; } - uint32 Get() { return value; } - void Set( uint32 _value ) { value = _value; } + CVarCreationBase_t( ) : + m_pszName( nullptr ), + m_pszHelpString( nullptr ), + m_nFlags( 0 ) + {} -private: - uint32 value = kInvalidConVarHandle; + 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; +}; -private: - static const uint32 kInvalidConVarHandle = 0xFFFFFFFF; -} ALIGN8_POST; enum CommandTarget_t { CT_NO_TARGET = -1, @@ -94,41 +98,6 @@ class CCommandContext CPlayerSlot m_nPlayerSlot; }; -class ALIGN8 ConCommandHandle -{ -public: - 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 ) - { - m_Data = index; - } - - int Get() const - { - return m_Data; - } - - int m_Data; -}; - //----------------------------------------------------------------------------- // ConVar flags //----------------------------------------------------------------------------- @@ -180,64 +149,16 @@ struct CSplitScreenSlot // Note: IVEngineClient::ClientCmd_Unrestricted can run any client command. #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 -}; - -union CVValue_t -{ - bool m_bValue; - short m_i16Value; - uint16 m_u16Value; - int m_i32Value; - uint m_u32Value; - int64 m_i64Value; - uint64 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; -}; - -//----------------------------------------------------------------------------- -// 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 //----------------------------------------------------------------------------- class ICVarListenerCallbacks { public: - virtual void OnConVarCreated( ConVarRefAbstract *pNewCvar ) = 0; - virtual void OnConCommandCreated( ConCommandRefAbstract *pNewCommand ) = 0; + virtual void OnConVarCreated( BaseConVar* pNewCvar ) = 0; + virtual void OnConCommandCreated( ConCommand* pNewCommand ) = 0; }; - - //----------------------------------------------------------------------------- // Called when a ConCommand needs to execute //----------------------------------------------------------------------------- @@ -266,50 +187,6 @@ class ICommandCompletionCallback virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0; }; -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; -}; - - //----------------------------------------------------------------------------- // Command tokenizer //----------------------------------------------------------------------------- @@ -395,51 +272,24 @@ 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 ); + ConCommandCreation_t() : + m_bHasCompletionCallback(false), + m_bIsInterface(false), + m_pHandle(nullptr) + {} - 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; - } - -private: // Call this function when executing the command - class CallbackInfo_t + struct CallbackInfo_t { - public: + CallbackInfo_t() : + m_fnCommandCallback(nullptr), + m_bIsInterface(false), + m_bIsVoidCallback(false), + m_bIsContextLess(false) + {} + union { FnCommandCallback_t m_fnCommandCallback; FnCommandCallbackVoid_t m_fnVoidCommandCallback; @@ -447,12 +297,12 @@ friend class ConCommandHandle; ICommandCallback* m_pCommandCallback; }; - bool m_bUsingCommandCallbackInterface : 1; - bool m_bHasVoidCommandCallback : 1; - bool m_bHasContextlessCommandCallback : 1; + bool m_bIsInterface; + bool m_bIsVoidCallback; + bool m_bIsContextLess; }; - CallbackInfo_t m_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 @@ -468,247 +318,298 @@ friend class ConCommandHandle; ICommandCompletionCallback* m_pCommandCompletionCallback; }; - bool m_bHasCompletionCallback : 1; - bool m_bUsingCommandCompletionInterface : 1; - - ConCommandRefAbstract *m_pReference; -}; + bool m_bHasCompletionCallback; + bool m_bIsInterface; + ConCommandHandle* m_pHandle; +}; +static_assert(sizeof(ConCommandCreation_t) == 0x40, "ConCommandCreation_t is of the wrong size!"); -//----------------------------------------------------------------------------- -// Purpose: A console variable -//----------------------------------------------------------------------------- -class ConVar +class ConCommand { -friend class CCvar; -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, - 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 ); + 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 ); - // True if it has a min/max setting - bool HasMin() const; - bool HasMax() const; + ~ConCommand() + { + this->Destroy(); + } - bool GetMin( float& minVal ) const; - bool GetMax( float& maxVal ) const; + inline ConCommandHandle GetHandle() const { return m_Handle; }; +private: + void Create( const char *pName, const char *pHelpString, int64_t flags, ConCommandCreation_t& setup ); + void Destroy( ); - float GetMinValue() const; - float GetMaxValue() const; + ConCommandHandle m_Handle; +}; - const char *GetDefault( void ) const; +using FnGenericChangeCallback_t = void(*)(BaseConVar* ref, CSplitScreenSlot nSlot, CVValue_t* pNewValue, CVValue_t* pOldValue); +struct ConVarCreation_t : CVarCreationBase_t { + ConVarCreation_t() : + m_pHandle(nullptr), + m_pConVarData(nullptr) + {} + + #pragma pack(push,1) + struct ConVarValueInfo_t + { + ConVarValueInfo_t() : + 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_unknown1; // 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!"); + +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 + }; - FORCEINLINE_CVAR CVValue_t &GetRawValue() + if (type == EConVarType_Invalid) { - return m_Value; + return invalid_convar[ EConVarType_MAX ]; } - FORCEINLINE_CVAR const CVValue_t &GetRawValue() const + return invalid_convar[ type ]; +} + +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 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( ); } + + 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; +}; + +template +class ConVar : public BaseConVar +{ +public: + 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, const T& value, FnChangeCallback_t cb = nullptr) { - return m_Value; + this->Init(INVALID_CONVAR_HANDLE, TranslateConVarType()); + + ConVarCreation_t setup; + setup.m_valueInfo.m_bHasDefault = true; + setup.m_valueInfo.DefaultValue() = value; + setup.m_eVarType = TranslateConVarType(); + setup.m_fnCallBack = reinterpret_cast(cb); + + this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); } -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 ); + 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()); - bool ClampValue( float& value ); - void ChangeStringValue( const char *tempVal, float flOldValue ); + ConVarCreation_t setup; + setup.m_valueInfo.m_bHasDefault = true; + setup.m_valueInfo.DefaultValue() = value; - 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 ); + setup.m_valueInfo.m_bHasMin = min; + setup.m_valueInfo.m_bHasMax = max; + setup.m_valueInfo.MinValue() = minValue; + setup.m_valueInfo.MaxValue() = maxValue; - // Used internally by OneTimeInit to initialize. - void Init(); + setup.m_eVarType = TranslateConVarType(); + setup.m_fnCallBack = reinterpret_cast(cb); + this->Register(name, flags &~ FCVAR_DEVELOPMENTONLY, description, setup); + } + ~ConVar() + { + UnRegisterConVar(this->m_Handle); + } -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; + inline const CConVarData* GetConVarData() const { return reinterpret_cast*>(m_ConVarData); } + inline CConVarData* GetConVarData() { return reinterpret_cast*>(m_ConVarData); } - // Has the cvar been added to the global list? - bool m_bRegistered; + inline const T& GetDefaultValue( ) const { return GetConVarData()->GetDefaultValue( ); } + inline const T& GetMinValue( ) const { return GetConVarData()->GetMinValue( ); } + inline const T& GetMaxValue( ) const { return GetConVarData()->GetMaxValue( ); } - // Static data - const char* m_pszName; - const char* m_pszHelpString; + 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 ); } - // ConVar flags - int64 m_nFlags; + inline void RemoveDefaultValue( ) { GetConVarData()->RemoveDefaultValue( ); } + inline void RemoveMinValue( ) { GetConVarData()->RemoveMinValue( ); } + inline void RemoveMaxValue( ) { GetConVarData()->RemoveMaxValue( ); } -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; - - // Static data - const char *m_pszDefaultValue; + inline const T& Clamp(const T& value) const { return GetConVarData()->Clamp( value ); } - CVValue_t m_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 ); - // 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; -#endif -#endif // CONVAR_WORK_FINISHED - 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; -}; + char szNewValue[256], szOldValue[256]; + CConVarData::ValueToString( newValue, szNewValue, sizeof(szNewValue) ); + GetConVarData()->GetStringValue( szOldValue, sizeof(szOldValue), index ); + // Deep copy + T oldValue = this->GetValue( ); + this->UpdateValue( newValue, index, (const CVValue_t*)&newValue, (const CVValue_t*)&oldValue, szNewValue, szOldValue ); + } -#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; -} + inline void GetStringValue( char* dst, size_t len, const CSplitScreenSlot& index = 0 ) const { GetConVarData()->GetStringValue( dst, len, index ); } -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as an int -// Output : int -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR int ConVar::GetInt( void ) const -{ - return m_pParent->m_Value.m_nValue; -} + 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; -//----------------------------------------------------------------------------- -// 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] ); -} + 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; + } + 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; + } -//----------------------------------------------------------------------------- + cvar.m_pszName = name; + cvar.m_pszHelpString = description; + cvar.m_nFlags = flags; -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() ); } + cvar.m_pHandle = &this->m_Handle; + cvar.m_pConVarData = &this->m_ConVarData; -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc. -// Output : const char * -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR const char *ConVar::GetString( void ) const + 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!"); + +// Special case for string +template<> inline void ConVar::SetValue( const char*const& val, const CSplitScreenSlot& index ) { - if ( m_nFlags & FCVAR_NEVER_AS_STRING ) - return "FCVAR_NEVER_AS_STRING"; - - char const *str = m_pParent->m_Value.m_pszString; - return str ? str : ""; + auto newValue = this->Clamp( val ); + + char szNewValue[256], szOldValue[256]; + CConVarData::ValueToString( newValue, szNewValue, sizeof(szNewValue) ); + GetConVarData()->GetStringValue( szOldValue, sizeof(szOldValue), index ); + + this->UpdateValue( newValue, index, (const CVValue_t*)&newValue, (const CVValue_t*)&szOldValue, szNewValue, szOldValue ); } +//----------------------------------------------------------------------------- + +#ifdef CONVAR_WORK_FINISHED class CSplitScreenAddedConVar : public ConVar { typedef ConVar BaseClass; @@ -773,146 +674,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? -//----------------------------------------------------------------------------- -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") @@ -1051,7 +812,7 @@ void ConVar_Unregister( ); //----------------------------------------------------------------------------- // Utility methods //----------------------------------------------------------------------------- -void ConVar_PrintDescription( const ConCommandBase *pVar ); +void ConVar_PrintDescription( const CVarCreationBase_t* pVar ); //----------------------------------------------------------------------------- @@ -1071,7 +832,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; @@ -1080,7 +841,7 @@ class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, pu ~CConCommandMemberAccessor() { - Shutdown(); + this->Destroy(); } void SetOwner( T* pOwner ) @@ -1104,7 +865,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 @@ -1115,61 +875,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 ) @@ -1177,15 +928,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 ) \ @@ -1204,5 +953,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 da72ad532..f81b5e551 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: // @@ -26,11 +26,6 @@ #endif #include "tier0/memdbgon.h" - -// Comment this out when we release. -//#define ALLOW_DEVELOPMENT_CVARS - - //----------------------------------------------------------------------------- // Statically constructed list of ConCommandBases, // used for registering them with the ICVar interface @@ -38,27 +33,33 @@ static int64 s_nCVarFlag = 0; static bool s_bRegistered = false; -class ConCommandRegList; +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 void RegisterCommand(ConCommand* pCmd) + static ConCommandRegList* GetRegList() { - 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(); - } - - pCmd->SetHandle(hndl); - } - else - { - GetCommandRegList()->AddToTail(pCmd); - } + static ConCommandRegList* list = new ConCommandRegList(); + return list; } static void RegisterAll() @@ -67,113 +68,124 @@ class ConCommandRegList { s_bConCommandsRegistered = true; - for(int i = 0; i < GetCommandRegList()->Count(); i++) + ConCommandRegList* list = GetRegList(); + FOR_EACH_VEC( list->m_Vec, i ) { - ConCommand *pCmd = GetCommandRegList()->Element(i); - ConCommandHandle hndl = g_pCVar->RegisterConCommand(pCmd, s_nCVarFlag); - pCmd->SetHandle(hndl); - - if (!hndl.IsValid()) - { - Plat_FatalErrorFunc("RegisterConCommand: Unknown error registering con command \"%s\"!\n", pCmd->GetName()); - DebuggerBreakIfDebugging(); - } + RegisterCommand( list->m_Vec[i] ); } + delete list; } } private: + friend void AddCommand( ConCommandCreation_t& cmd ); - // GAMMACASE: Required to prevent static initialization order problem https://isocpp.org/wiki/faq/ctors#static-init-order - static CUtlVector *GetCommandRegList() + void Add( const ConCommandCreation_t& cmd ) { - static CUtlVector s_ConCommandRegList; - return &s_ConCommandRegList; + m_Vec.AddToTail( cmd ); } + CUtlVector m_Vec; +public: static bool s_bConCommandsRegistered; }; - bool ConCommandRegList::s_bConCommandsRegistered = false; -#ifdef CONVAR_WORK_FINISHED -template -void check_size() { - static_assert(ExpectedSize == RealSize, "Size mismatch"); -}; +void AddCommand( ConCommandCreation_t& cmd ) +{ + if (ConCommandRegList::s_bConCommandsRegistered && s_bRegistered) + { + RegisterCommand( cmd ); + return; + } -class ConVarRegList; -static ConVarRegList* s_pConVarRegList = nullptr; + ConCommandRegList::GetRegList()->Add( cmd ); +} -class ConVarRegList +void RegisterConVar( ConVarCreation_t& cvar ) { -public: - ConVarRegList() + g_pCVar->RegisterConVar( cvar, s_nCVarFlag, cvar.m_pHandle, cvar.m_pConVarData ); + if (!cvar.m_pHandle->IsValid()) { - check_size(); - check_size(); + Plat_FatalErrorFunc( "RegisterConVar: Unknown error registering convar \"%s\"!\n", cvar.m_pszName ); + DebuggerBreakIfDebugging(); } +} - static bool AreConVarsRegistered() +void UnRegisterConVar( ConVarHandle& cvar ) +{ + if (cvar.IsValid()) { - return s_bConVarsRegistered; + g_pCVar->UnregisterConVar( cvar ); + + cvar.Invalidate(); + } +} + +class ConVarRegList +{ +public: + static ConVarRegList* GetRegList() + { + static ConVarRegList* list = new ConVarRegList(); + return list; } 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 = GetRegList(); + FOR_EACH_VEC( list->m_Vec, i ) { - 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->GetName()); - DebuggerBreakIfDebugging(); - } - } - - ConVarRegList *pNext = pList->m_pNext; - delete pList; - pList = pNext; + RegisterConVar( list->m_Vec[i] ); } - - s_pConVarRegList = nullptr; + delete list; } } + private: - CUtlVectorFixed m_Vec; - ConVarRegList* m_pNext = nullptr; + friend void SetupConVar( ConVarCreation_t& cvar ); + void Add( const ConVarCreation_t& cvar ) + { + m_Vec.AddToTail( cvar ); + } + + CUtlVector m_Vec; +public: static bool s_bConVarsRegistered; }; bool ConVarRegList::s_bConVarsRegistered = false; -#endif // CONVAR_WORK_FINISHED + +void SetupConVar( ConVarCreation_t& cvar ) +{ + if ( ConVarRegList::s_bConVarsRegistered ) + { + RegisterConVar(cvar); + return; + } + + ConVarRegList::GetRegList()->Add( cvar ); +} //----------------------------------------------------------------------------- // 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; + } s_bRegistered = true; s_nCVarFlag = nCVarFlag; ConCommandRegList::RegisterAll(); -#ifdef CONVAR_WORK_FINISHED ConVarRegList::RegisterAll(); -#endif // CONVAR_WORK_FINISHED } void ConVar_Unregister( ) @@ -184,84 +196,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 //----------------------------------------------------------------------------- @@ -451,98 +385,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*/ ) +ConCommand::ConCommand( 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.m_fnCallback.m_fnCommandCallback = callback; + creation.m_fnCallback.m_bIsInterface = false; + creation.m_fnCallback.m_bIsVoidCallback = false; + creation.m_fnCallback.m_bIsContextLess = false; - m_pReference = pReferenceOut; - m_pReference->handle.Reset(); + creation.m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; + creation.m_bHasCompletionCallback = completionFunc != 0 ? true : false; + creation.m_bIsInterface = 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*/ ) +ConCommand::ConCommand( 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.m_fnCallback.m_fnVoidCommandCallback = callback; + creation.m_fnCallback.m_bIsInterface = false; + creation.m_fnCallback.m_bIsVoidCallback = true; + creation.m_fnCallback.m_bIsContextLess = false; - m_pReference = pReferenceOut; - m_pReference->handle.Reset(); + creation.m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; + creation.m_bHasCompletionCallback = completionFunc != nullptr ? true : false; + creation.m_bIsInterface = 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*/ ) +ConCommand::ConCommand( 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.m_fnCallback.m_fnContextlessCommandCallback = callback; + creation.m_fnCallback.m_bIsInterface = false; + creation.m_fnCallback.m_bIsVoidCallback = false; + creation.m_fnCallback.m_bIsContextLess = true; - m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; - m_bHasCompletionCallback = completionFunc != 0 ? true : false; - m_bUsingCommandCompletionInterface = false; - - m_pReference = pReferenceOut; - m_pReference->handle.Reset(); + creation.m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; + creation.m_bHasCompletionCallback = completionFunc != nullptr ? true : false; + creation.m_bIsInterface = 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*/ ) +ConCommand::ConCommand( 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.m_fnCallback.m_pCommandCallback = pCallback; + creation.m_fnCallback.m_bIsInterface = true; + creation.m_fnCallback.m_bIsVoidCallback = false; + creation.m_fnCallback.m_bIsContextLess = false; - m_pReference = pReferenceOut; - m_pReference->handle.Reset(); + creation.m_pCommandCompletionCallback = pCompletionCallback; + creation.m_bHasCompletionCallback = pCompletionCallback != nullptr ? true : false; + creation.m_bIsInterface = 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 ); } //----------------------------------------------------------------------------- @@ -552,582 +456,37 @@ 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.m_pszName = pName; + setup.m_pszHelpString = pHelpString ? pHelpString : empty_string; - m_nFlags = flags; + setup.m_nFlags = flags; #ifdef ALLOW_DEVELOPMENT_CVARS - m_nFlags &= ~FCVAR_DEVELOPMENTONLY; + setup.m_nFlags &= ~FCVAR_DEVELOPMENTONLY; #endif + setup.m_pHandle = &this->m_Handle; - Init(); + AddCommand( setup ); } -void ConCommand::Shutdown() +void ConCommand::Destroy() { - GetRef()->handle.Unregister(); + UnRegisterCommand(this->m_Handle); } - -//----------------------------------------------------------------------------- -// 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; -} - - -#ifdef CONVAR_WORK_FINISHED //----------------------------------------------------------------------------- // // Console Variables // //----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// 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; - -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; -} - +#ifdef CONVAR_WORK_FINISHED //----------------------------------------------------------------------------- // Purpose: