mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Restructure concommandbase classes
Move all classes deriving from ConCommandBase to a single file, and split out CCommand, CCvar, CCvarUtilities etc to their own files. This makes it possible to use CCommand and stuff in external tools without linker errors/warnings.
This commit is contained in:
parent
dbe75c0709
commit
26c10dfd11
@ -448,7 +448,7 @@ void DetourRegister() // Register detour classes to be searched and hooked.
|
||||
|
||||
// Tier1
|
||||
REGISTER(VCommandLine);
|
||||
REGISTER(VConCommand);
|
||||
REGISTER(VConVar);
|
||||
REGISTER(VCVar);
|
||||
|
||||
// VPC
|
||||
|
@ -2,6 +2,24 @@
|
||||
#define ICONCOMMAND_H
|
||||
#include "icvar.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Forward declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConCommandBase;
|
||||
class CCommand;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Any executable that wants to use ConVars need to implement one of
|
||||
// these to hook up access to console variables.
|
||||
//-----------------------------------------------------------------------------
|
||||
abstract_class IConCommandBaseAccessor
|
||||
{
|
||||
public:
|
||||
// Flags is a combination of FCVAR flags in cvar.h.
|
||||
// hOut is filled in with a handle to the variable.
|
||||
virtual bool RegisterConCommandBase(ConCommandBase* pVar) = 0;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Abstract interface for ConVars
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef ICVAR_H
|
||||
#define ICVAR_H
|
||||
#include "tier0/annotations.h"
|
||||
#include "iconvar.h"
|
||||
#include "appframework/IAppSystem.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -12,29 +12,7 @@
|
||||
#ifndef TIER1_CMD_H
|
||||
#define TIER1_CMD_H
|
||||
|
||||
#include "tier1/utlvector.h"
|
||||
#include "tier1/utlstring.h"
|
||||
#include "tier1/characterset.h"
|
||||
#include "public/iconvar.h"
|
||||
#include "public/iconcommand.h"
|
||||
#include "mathlib/color.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Forward declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConCommandBase;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Any executable that wants to use ConVars need to implement one of
|
||||
// these to hook up access to console variables.
|
||||
//-----------------------------------------------------------------------------
|
||||
class IConCommandBaseAccessor
|
||||
{
|
||||
public:
|
||||
// Flags is a combination of FCVAR flags in cvar.h.
|
||||
// hOut is filled in with a handle to the variable.
|
||||
virtual bool RegisterConCommandBase(ConCommandBase* pVar) = 0;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Command buffer context
|
||||
@ -77,7 +55,7 @@ private:
|
||||
public:
|
||||
CCommand();
|
||||
CCommand(int nArgC, const char** ppArgV, cmd_source_t source);
|
||||
bool Tokenize(const char* pCommand, cmd_source_t source, characterset_t* pBreakSet = nullptr);
|
||||
bool Tokenize(const char* pCommand, cmd_source_t source = cmd_source_t::kCommandSrcCode, characterset_t* pBreakSet = nullptr);
|
||||
|
||||
int64_t ArgC(void) const;
|
||||
const char** ArgV(void) const;
|
||||
@ -99,135 +77,4 @@ private:
|
||||
const char* m_ppArgv[COMMAND_MAX_ARGC];
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: The base console invoked command/cvar interface
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConCommandBase
|
||||
{
|
||||
public:
|
||||
virtual ~ConCommandBase(void) { };
|
||||
|
||||
virtual bool IsCommand(void) const = 0;
|
||||
virtual bool IsFlagSet(int nFlags) const = 0;
|
||||
|
||||
virtual void AddFlags(int nFlags) = 0;
|
||||
virtual void RemoveFlags(int nFlags) = 0;
|
||||
|
||||
virtual int GetFlags(void) const = 0;
|
||||
virtual const char* GetName(void) const = 0;
|
||||
virtual const char* GetHelpText(void) const = 0;
|
||||
virtual const char* GetUsageText(void) const = 0;
|
||||
|
||||
virtual void SetAccessor(IConCommandBaseAccessor* pAccessor) = 0;
|
||||
virtual bool IsRegistered(void) const = 0;
|
||||
|
||||
virtual int GetDLLIdentifier() const = 0;
|
||||
virtual ConCommandBase* Create (const char* szName, const char* szHelpString,
|
||||
int nFlags, const char* pszUsageString) = 0;
|
||||
|
||||
virtual void Init() = 0;
|
||||
|
||||
bool HasFlags(int nFlags) const;
|
||||
|
||||
ConCommandBase* GetNext(void) const;
|
||||
char* CopyString(const char* szFrom) const;
|
||||
|
||||
ConCommandBase* m_pNext; //0x0008
|
||||
bool m_bRegistered; //0x0010
|
||||
const char* m_pszName; //0x0018
|
||||
const char* m_pszHelpString; //0x0020
|
||||
const char* m_pszUsageString; //0x0028
|
||||
IConCommandBaseAccessor* s_pAccessor; //0x0030 <-- unused since executable is monolithic.
|
||||
int m_nFlags; //0x0038
|
||||
}; //Size: 0x0040
|
||||
static_assert(sizeof(ConCommandBase) == 0x40);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: The console invoked command
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConCommand : public ConCommandBase
|
||||
{
|
||||
friend class CCvar;
|
||||
public:
|
||||
ConCommand(void);
|
||||
|
||||
static ConCommand* StaticCreate(const char* szName, const char* szHelpString, const char* pszUsageString,
|
||||
int nFlags, FnCommandCallback_t pCallback, FnCommandCompletionCallback pCommandCompletionCallback);
|
||||
|
||||
virtual int AutoCompleteSuggest(const char* partial, CUtlVector< CUtlString >& commands) = 0;
|
||||
virtual bool CanAutoComplete(void) const = 0;
|
||||
|
||||
void* m_nNullCallBack; //0x0040
|
||||
void* m_pSubCallback; //0x0048
|
||||
// Call this function when executing the command
|
||||
union
|
||||
{
|
||||
FnCommandCallbackV1_t m_fnCommandCallbackV1;
|
||||
FnCommandCallback_t m_fnCommandCallback;
|
||||
ICommandCallback* m_pCommandCallback;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
FnCommandCompletionCallback m_fnCompletionCallback;
|
||||
ICommandCompletionCallback* m_pCommandCompletionCallback;
|
||||
};
|
||||
|
||||
bool m_bHasCompletionCallback : 1;
|
||||
bool m_bUsingNewCommandCallback : 1;
|
||||
bool m_bUsingCommandCallbackInterface : 1;
|
||||
};
|
||||
|
||||
/* ==== CONCOMMAND ====================================================================================================================================================== */
|
||||
inline CMemory p_ConCommand_AutoCompleteSuggest;
|
||||
inline bool(*ConCommand_AutoCompleteSuggest)(ConCommand* pCommand, const char* partial, CUtlVector< CUtlString >& commands);
|
||||
|
||||
inline CMemory p_ConCommandBase_IsFlagSet;
|
||||
inline bool(*ConCommandBase_IsFlagSet)(ConCommandBase* pCommand, int nFlag);
|
||||
|
||||
inline CMemory p_NullSub;
|
||||
inline void(*NullSub)(void);
|
||||
|
||||
inline CMemory p_CallbackStub;
|
||||
inline FnCommandCompletionCallback CallbackStub;
|
||||
|
||||
inline ConCommandBase* g_pConCommandVFTable;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
ECommandTarget_t Cbuf_GetCurrentPlayer(void);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class VConCommand : public IDetour
|
||||
{
|
||||
virtual void GetAdr(void) const
|
||||
{
|
||||
LogFunAdr("ConCommandBase::IsFlagSet", p_ConCommandBase_IsFlagSet.GetPtr());
|
||||
LogFunAdr("ConCommand::AutoCompleteSuggest", p_ConCommand_AutoCompleteSuggest.GetPtr());
|
||||
LogFunAdr("CallbackStub", p_CallbackStub.GetPtr());
|
||||
LogFunAdr("NullSub", p_NullSub.GetPtr());
|
||||
}
|
||||
virtual void GetFun(void) const
|
||||
{
|
||||
p_ConCommand_AutoCompleteSuggest = g_GameDll.FindPatternSIMD("40 ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 F6 41 60 04");
|
||||
p_ConCommandBase_IsFlagSet = g_GameDll.FindPatternSIMD("85 51 38 0F 95 C0 C3");
|
||||
|
||||
p_NullSub = g_GameDll.FindPatternSIMD("C2 ?? ?? CC CC CC CC CC CC CC CC CC CC CC CC CC 40 53 48 83 EC 20 48 8D 05 ?? ?? ?? ??");
|
||||
p_CallbackStub = g_GameDll.FindPatternSIMD("33 C0 C3 CC CC CC CC CC CC CC CC CC CC CC CC CC 80 49 68 08");
|
||||
|
||||
ConCommandBase_IsFlagSet = p_ConCommandBase_IsFlagSet.RCast<bool (*)(ConCommandBase*, int)>(); /*85 51 38 0F 95 C0 C3*/
|
||||
ConCommand_AutoCompleteSuggest = p_ConCommand_AutoCompleteSuggest.RCast<bool (*)(ConCommand*, const char*, CUtlVector< CUtlString >&)>();
|
||||
|
||||
NullSub = p_NullSub.RCast<void(*)(void)>(); /*C2 00 00 CC CC CC CC CC CC CC CC CC CC CC CC CC 40 53 48 83 EC 20 48 8D 05 ?? ?? ?? ??*/
|
||||
CallbackStub = p_CallbackStub.RCast<FnCommandCompletionCallback>(); /*33 C0 C3 CC CC CC CC CC CC CC CC CC CC CC CC CC 80 49 68 08*/ /*UserMathErrorFunction*/
|
||||
}
|
||||
virtual void GetVar(void) const { }
|
||||
virtual void GetCon(void) const
|
||||
{
|
||||
g_pConCommandVFTable = g_GameDll.GetVirtualMethodTable(".?AVConCommand@@").RCast<ConCommandBase*>();
|
||||
}
|
||||
virtual void Attach(void) const { };
|
||||
virtual void Detach(void) const { };
|
||||
};
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // TIER1_CMD_H
|
||||
|
302
r5dev/public/tier1/convar.h
Normal file
302
r5dev/public/tier1/convar.h
Normal file
@ -0,0 +1,302 @@
|
||||
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef CONVAR_H
|
||||
#define CONVAR_H
|
||||
|
||||
#include "mathlib/color.h"
|
||||
#include "public/iconvar.h"
|
||||
#include "public/iconcommand.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "tier1/utlstring.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: The base console invoked command/cvar interface
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConCommandBase
|
||||
{
|
||||
public:
|
||||
virtual ~ConCommandBase(void) { };
|
||||
|
||||
virtual bool IsCommand(void) const = 0;
|
||||
virtual bool IsFlagSet(int nFlags) const = 0;
|
||||
|
||||
virtual void AddFlags(int nFlags) = 0;
|
||||
virtual void RemoveFlags(int nFlags) = 0;
|
||||
|
||||
virtual int GetFlags(void) const = 0;
|
||||
virtual const char* GetName(void) const = 0;
|
||||
virtual const char* GetHelpText(void) const = 0;
|
||||
virtual const char* GetUsageText(void) const = 0;
|
||||
|
||||
virtual void SetAccessor(IConCommandBaseAccessor* pAccessor) = 0;
|
||||
virtual bool IsRegistered(void) const = 0;
|
||||
|
||||
virtual int GetDLLIdentifier() const = 0;
|
||||
virtual ConCommandBase* Create(const char* szName, const char* szHelpString,
|
||||
int nFlags, const char* pszUsageString) = 0;
|
||||
|
||||
virtual void Init() = 0;
|
||||
|
||||
bool HasFlags(int nFlags) const;
|
||||
|
||||
ConCommandBase* GetNext(void) const;
|
||||
char* CopyString(const char* szFrom) const;
|
||||
|
||||
ConCommandBase* m_pNext; //0x0008
|
||||
bool m_bRegistered; //0x0010
|
||||
const char* m_pszName; //0x0018
|
||||
const char* m_pszHelpString; //0x0020
|
||||
const char* m_pszUsageString; //0x0028
|
||||
IConCommandBaseAccessor* s_pAccessor; //0x0030 <-- unused since executable is monolithic.
|
||||
int m_nFlags; //0x0038
|
||||
};
|
||||
static_assert(sizeof(ConCommandBase) == 0x40);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: The console invoked command
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConCommand : public ConCommandBase
|
||||
{
|
||||
friend class CCvar;
|
||||
public:
|
||||
ConCommand(void);
|
||||
|
||||
static ConCommand* StaticCreate(const char* szName, const char* szHelpString, const char* pszUsageString,
|
||||
int nFlags, FnCommandCallback_t pCallback, FnCommandCompletionCallback pCommandCompletionCallback);
|
||||
|
||||
virtual int AutoCompleteSuggest(const char* partial, CUtlVector< CUtlString >& commands) = 0;
|
||||
virtual bool CanAutoComplete(void) const = 0;
|
||||
|
||||
void* m_nNullCallBack; //0x0040
|
||||
void* m_pSubCallback; //0x0048
|
||||
// Call this function when executing the command
|
||||
union
|
||||
{
|
||||
FnCommandCallbackV1_t m_fnCommandCallbackV1;
|
||||
FnCommandCallback_t m_fnCommandCallback;
|
||||
ICommandCallback* m_pCommandCallback;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
FnCommandCompletionCallback m_fnCompletionCallback;
|
||||
ICommandCompletionCallback* m_pCommandCompletionCallback;
|
||||
};
|
||||
|
||||
bool m_bHasCompletionCallback : 1;
|
||||
bool m_bUsingNewCommandCallback : 1;
|
||||
bool m_bUsingCommandCallbackInterface : 1;
|
||||
};
|
||||
static_assert(sizeof(ConCommand) == 0x68);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: A console variable
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConVar : public ConCommandBase, public IConVar
|
||||
{
|
||||
friend class CCvar;
|
||||
friend class ConVarRef;
|
||||
|
||||
public:
|
||||
static ConVar* StaticCreate(const char* pszName, const char* pszDefaultValue, int nFlags, const char* pszHelpString,
|
||||
bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t pCallback, const char* pszUsageString);
|
||||
void Destroy(void);
|
||||
|
||||
ConVar(void);
|
||||
virtual ~ConVar(void) { };
|
||||
|
||||
FORCEINLINE bool GetBool(void) const;
|
||||
FORCEINLINE float GetFloat(void) const;
|
||||
FORCEINLINE double GetDouble(void) const;
|
||||
FORCEINLINE int GetInt(void) const;
|
||||
FORCEINLINE Color GetColor(void) const;
|
||||
FORCEINLINE const char* GetString(void) const;
|
||||
|
||||
void SetMax(float flMaxValue);
|
||||
void SetMin(float flMinValue);
|
||||
bool GetMin(float& flMinValue) const;
|
||||
bool GetMax(float& flMaxValue) const;
|
||||
float GetMinValue(void) const;
|
||||
float GetMaxValue(void) const;
|
||||
bool HasMin(void) const;
|
||||
bool HasMax(void) const;
|
||||
|
||||
void SetValue(int nValue);
|
||||
void SetValue(float flValue);
|
||||
void SetValue(const char* pszValue);
|
||||
void SetValue(Color clValue);
|
||||
|
||||
virtual void InternalSetValue(const char* pszValue) = 0;
|
||||
virtual void InternalSetFloatValue(float flValue) = 0;
|
||||
virtual void InternalSetIntValue(int nValue) = 0;
|
||||
void InternalSetColorValue(Color value);
|
||||
|
||||
virtual __int64 Unknown0(unsigned int a2) = 0;
|
||||
virtual __int64 Unknown1(const char* a2) = 0;
|
||||
|
||||
void Revert(void);
|
||||
virtual bool ClampValue(float& flValue) = 0;
|
||||
|
||||
const char* GetDefault(void) const;
|
||||
void SetDefault(const char* pszDefault);
|
||||
bool SetColorFromString(const char* pszValue);
|
||||
|
||||
virtual void ChangeStringValue(const char* pszTempValue) = 0;
|
||||
virtual void CreateInternal(const char* pszName, const char* pszDefaultValue, int nFlags, const char* pszHelpString,
|
||||
bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t pCallback, const char* pszUsageString) = 0;
|
||||
|
||||
void InstallChangeCallback(FnChangeCallback_t callback, bool bInvoke);
|
||||
void RemoveChangeCallback(FnChangeCallback_t callback);
|
||||
|
||||
struct CVValue_t
|
||||
{
|
||||
char* m_pszString;
|
||||
size_t m_iStringLength;
|
||||
float m_fValue;
|
||||
int m_nValue;
|
||||
};
|
||||
|
||||
ConVar* m_pParent; //0x0048
|
||||
const char* m_pszDefaultValue; //0x0050
|
||||
CVValue_t m_Value; //0c0058
|
||||
bool m_bHasMin; //0x0070
|
||||
float m_fMinVal; //0x0074
|
||||
bool m_bHasMax; //0x0078
|
||||
float m_fMaxVal; //0x007C
|
||||
CUtlVector<FnChangeCallback_t> m_fnChangeCallbacks; //0x0080
|
||||
};
|
||||
static_assert(sizeof(ConVar) == 0xA0);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a boolean.
|
||||
// Output : bool
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE bool ConVar::GetBool(void) const
|
||||
{
|
||||
return !!GetInt();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a float.
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE float ConVar::GetFloat(void) const
|
||||
{
|
||||
return m_pParent->m_Value.m_fValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a double.
|
||||
// Output : double
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE double ConVar::GetDouble(void) const
|
||||
{
|
||||
return static_cast<double>(m_pParent->m_Value.m_fValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as an integer.
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE int ConVar::GetInt(void) const
|
||||
{
|
||||
return m_pParent->m_Value.m_nValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a color.
|
||||
// Output : Color
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE Color ConVar::GetColor(void) const
|
||||
{
|
||||
unsigned char* pColorElement = (reinterpret_cast<unsigned char*>(&m_pParent->m_Value.m_nValue));
|
||||
return Color(pColorElement[0], pColorElement[1], pColorElement[2], pColorElement[3]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a string.
|
||||
// Output : const char *
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE 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 : "";
|
||||
}
|
||||
|
||||
/* ==== CONVAR ========================================================================================================================================================== */
|
||||
inline CMemory p_ConVar_Register;
|
||||
inline void*(*v_ConVar_Register)(ConVar* thisptr, const char* szName, const char* szDefaultValue, int nFlags, const char* szHelpString, bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t pCallback, const char* pszUsageString);
|
||||
|
||||
inline CMemory p_ConVar_Unregister;
|
||||
inline void(*v_ConVar_Unregister)(ConVar* thisptr);
|
||||
|
||||
inline CMemory p_ConVar_IsFlagSet;
|
||||
inline bool(*v_ConVar_IsFlagSet)(ConVar* pConVar, int nFlag);
|
||||
|
||||
inline ConCommandBase* g_pConCommandBaseVFTable;
|
||||
inline ConCommand* g_pConCommandVFTable;
|
||||
inline ConVar* g_pConVarVBTable;
|
||||
inline IConVar* g_pConVarVFTable;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class VConVar : public IDetour
|
||||
{
|
||||
virtual void GetAdr(void) const
|
||||
{
|
||||
LogConAdr("ConCommandBase::`vftable'", reinterpret_cast<uintptr_t>(g_pConCommandBaseVFTable));
|
||||
LogConAdr("ConCommand::`vftable'", reinterpret_cast<uintptr_t>(g_pConCommandVFTable));
|
||||
LogConAdr("ConVar::`vbtable'", reinterpret_cast<uintptr_t>(g_pConVarVBTable));
|
||||
LogConAdr("ConVar::`vftable'", reinterpret_cast<uintptr_t>(g_pConVarVFTable));
|
||||
LogFunAdr("ConVar::Register", p_ConVar_Register.GetPtr());
|
||||
LogFunAdr("ConVar::Unregister", p_ConVar_Unregister.GetPtr());
|
||||
LogFunAdr("ConVar::IsFlagSet", p_ConVar_IsFlagSet.GetPtr());
|
||||
}
|
||||
virtual void GetFun(void) const
|
||||
{
|
||||
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
|
||||
p_ConVar_Register = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 30 F3 0F 10 44 24 ??");
|
||||
p_ConVar_Unregister = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 48 8B 59 58 48 8D 05 ?? ?? ?? ??");
|
||||
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
|
||||
p_ConVar_Register = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 40 F3 0F 10 84 24 ?? ?? ?? ??");
|
||||
p_ConVar_Unregister = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B 79 58");
|
||||
#endif
|
||||
p_ConVar_IsFlagSet = g_GameDll.FindPatternSIMD("48 8B 41 48 85 50 38");
|
||||
|
||||
v_ConVar_IsFlagSet = p_ConVar_IsFlagSet.RCast<bool (*)(ConVar*, int)>();
|
||||
v_ConVar_Register = p_ConVar_Register.RCast<void* (*)(ConVar*, const char*, const char*, int, const char*, bool, float, bool, float, FnChangeCallback_t, const char*)>();
|
||||
v_ConVar_Unregister = p_ConVar_Unregister.RCast<void (*)(ConVar*)>();
|
||||
}
|
||||
virtual void GetVar(void) const { }
|
||||
virtual void GetCon(void) const
|
||||
{
|
||||
g_pConCommandBaseVFTable = g_GameDll.GetVirtualMethodTable(".?AVConCommandBase@@").RCast<ConCommandBase*>();
|
||||
g_pConCommandVFTable = g_GameDll.GetVirtualMethodTable(".?AVConCommand@@").RCast<ConCommand*>();
|
||||
g_pConVarVBTable = g_GameDll.GetVirtualMethodTable(".?AVConVar@@", 0).RCast<ConVar*>();
|
||||
g_pConVarVFTable = g_GameDll.GetVirtualMethodTable(".?AVConVar@@", 1).RCast<IConVar*>();
|
||||
}
|
||||
virtual void Attach(void) const { }
|
||||
virtual void Detach(void) const { }
|
||||
};
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif // CONVAR_H
|
@ -13,11 +13,80 @@
|
||||
#define CVAR_H
|
||||
|
||||
#include "vstdlib/concommandhash.h"
|
||||
#include "public/icvar.h"
|
||||
#include "public/iconvar.h"
|
||||
#include "tier1/utlmap.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "tier1/utlstring.h"
|
||||
|
||||
/* ==== CCVAR =========================================================================================================================================================== */
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Forward declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConCommandBase;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Interface to ConVars/ConCommands
|
||||
//-----------------------------------------------------------------------------
|
||||
class CCvar : public CBaseAppSystem< ICvar >
|
||||
{ // Implementation in engine.
|
||||
protected:
|
||||
enum ConVarSetType_t
|
||||
{
|
||||
CONVAR_SET_STRING = 0,
|
||||
CONVAR_SET_INT,
|
||||
CONVAR_SET_FLOAT,
|
||||
};
|
||||
|
||||
struct QueuedConVarSet_t
|
||||
{
|
||||
ConVar* m_pConVar;
|
||||
ConVarSetType_t m_nType;
|
||||
int m_nInt;
|
||||
float m_flFloat;
|
||||
CUtlString m_String;
|
||||
};
|
||||
|
||||
class CCVarIteratorInternal : public ICVarIteratorInternal
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void SetFirst(void) = 0;
|
||||
virtual void Next(void) = 0;
|
||||
virtual bool IsValid(void) = 0;
|
||||
virtual ConCommandBase* Get(void) = 0;
|
||||
|
||||
virtual ~CCVarIteratorInternal() { }
|
||||
|
||||
CCvar* const m_pOuter = nullptr;
|
||||
CConCommandHash* const m_pHash = nullptr;
|
||||
CConCommandHash::CCommandHashIterator_t m_hashIter;
|
||||
};
|
||||
|
||||
virtual CCVarIteratorInternal* FactoryInternalIterator(void) = 0;
|
||||
|
||||
friend class CCVarIteratorInternal;
|
||||
friend class CCvarUtilities;
|
||||
|
||||
private:
|
||||
CUtlVector< FnChangeCallback_t > m_GlobalChangeCallbacks;
|
||||
char pad0[30]; //!TODO:
|
||||
int m_nNextDLLIdentifier;
|
||||
ConCommandBase* m_pConCommandList;
|
||||
CConCommandHash m_CommandHash;
|
||||
CUtlVector<void*> m_Unknown;
|
||||
char pad2[32];
|
||||
void* m_pCallbackStub;
|
||||
void* m_pAllocFunc;
|
||||
char pad3[16];
|
||||
CUtlVector< QueuedConVarSet_t > m_QueuedConVarSets;
|
||||
bool m_bMaterialSystemThreadSetAllowed;
|
||||
};
|
||||
|
||||
extern CCvar* g_pCVar;
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: ConVar tools
|
||||
//-----------------------------------------------------------------------------
|
||||
class CCvarUtilities
|
||||
{
|
||||
@ -63,204 +132,7 @@ private:
|
||||
};
|
||||
|
||||
extern CCvarUtilities* cv;
|
||||
|
||||
class CCvar : public CBaseAppSystem< ICvar >
|
||||
{ // Implementation in engine.
|
||||
protected:
|
||||
enum ConVarSetType_t
|
||||
{
|
||||
CONVAR_SET_STRING = 0,
|
||||
CONVAR_SET_INT,
|
||||
CONVAR_SET_FLOAT,
|
||||
};
|
||||
|
||||
struct QueuedConVarSet_t
|
||||
{
|
||||
ConVar* m_pConVar;
|
||||
ConVarSetType_t m_nType;
|
||||
int m_nInt;
|
||||
float m_flFloat;
|
||||
CUtlString m_String;
|
||||
};
|
||||
|
||||
class CCVarIteratorInternal : public ICVarIteratorInternal
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void SetFirst(void) = 0;
|
||||
virtual void Next(void) = 0;
|
||||
virtual bool IsValid(void) = 0;
|
||||
virtual ConCommandBase* Get(void) = 0;
|
||||
|
||||
virtual ~CCVarIteratorInternal() { }
|
||||
|
||||
CCvar* const m_pOuter = nullptr;
|
||||
CConCommandHash* const m_pHash = nullptr;
|
||||
CConCommandHash::CCommandHashIterator_t m_hashIter;
|
||||
};
|
||||
|
||||
virtual CCVarIteratorInternal* FactoryInternalIterator(void) = 0;
|
||||
|
||||
friend class CCVarIteratorInternal;
|
||||
friend class CCvarUtilities;
|
||||
|
||||
private:
|
||||
CUtlVector< FnChangeCallback_t > m_GlobalChangeCallbacks;
|
||||
char pad0[30]; //!TODO:
|
||||
int m_nNextDLLIdentifier;
|
||||
ConCommandBase* m_pConCommandList;
|
||||
CConCommandHash m_CommandHash;
|
||||
CUtlVector<void*> m_Unknown;
|
||||
char pad2[32];
|
||||
void* m_pCallbackStub;
|
||||
void* m_pAllocFunc;
|
||||
char pad3[16];
|
||||
CUtlVector< QueuedConVarSet_t > m_QueuedConVarSets;
|
||||
bool m_bMaterialSystemThreadSetAllowed;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
extern CCvar* g_pCVar;
|
||||
|
||||
/* ==== CONVAR ========================================================================================================================================================== */
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: A console variable
|
||||
//-----------------------------------------------------------------------------
|
||||
class ConVar : public ConCommandBase, public IConVar
|
||||
{
|
||||
friend class CCvar;
|
||||
friend class ConVarRef;
|
||||
|
||||
public:
|
||||
static ConVar* StaticCreate(const char* pszName, const char* pszDefaultValue, int nFlags, const char* pszHelpString,
|
||||
bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t pCallback, const char* pszUsageString);
|
||||
void Destroy(void);
|
||||
|
||||
ConVar(void);
|
||||
virtual ~ConVar(void) { };
|
||||
|
||||
FORCEINLINE bool GetBool(void) const;
|
||||
FORCEINLINE float GetFloat(void) const;
|
||||
FORCEINLINE double GetDouble(void) const;
|
||||
FORCEINLINE int GetInt(void) const;
|
||||
FORCEINLINE Color GetColor(void) const;
|
||||
FORCEINLINE const char* GetString(void) const;
|
||||
|
||||
void SetMax(float flMaxValue);
|
||||
void SetMin(float flMinValue);
|
||||
bool GetMin(float& flMinValue) const;
|
||||
bool GetMax(float& flMaxValue) const;
|
||||
float GetMinValue(void) const;
|
||||
float GetMaxValue(void) const;
|
||||
bool HasMin(void) const;
|
||||
bool HasMax(void) const;
|
||||
|
||||
void SetValue(int nValue);
|
||||
void SetValue(float flValue);
|
||||
void SetValue(const char* pszValue);
|
||||
void SetValue(Color clValue);
|
||||
|
||||
virtual void InternalSetValue(const char* pszValue) = 0;
|
||||
virtual void InternalSetFloatValue(float flValue) = 0;
|
||||
virtual void InternalSetIntValue(int nValue) = 0;
|
||||
void InternalSetColorValue(Color value);
|
||||
|
||||
virtual __int64 Unknown0(unsigned int a2) = 0;
|
||||
virtual __int64 Unknown1(const char* a2) = 0;
|
||||
|
||||
void Revert(void);
|
||||
virtual bool ClampValue(float& flValue) = 0;
|
||||
|
||||
const char* GetDefault(void) const;
|
||||
void SetDefault(const char* pszDefault);
|
||||
bool SetColorFromString(const char* pszValue);
|
||||
|
||||
virtual void ChangeStringValue(const char* pszTempValue) = 0;
|
||||
virtual void CreateInternal(const char* pszName, const char* pszDefaultValue, int nFlags, const char* pszHelpString,
|
||||
bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t pCallback, const char* pszUsageString) = 0;
|
||||
|
||||
void InstallChangeCallback(FnChangeCallback_t callback, bool bInvoke);
|
||||
void RemoveChangeCallback(FnChangeCallback_t callback);
|
||||
|
||||
struct CVValue_t
|
||||
{
|
||||
char* m_pszString;
|
||||
size_t m_iStringLength;
|
||||
float m_fValue;
|
||||
int m_nValue;
|
||||
};
|
||||
|
||||
ConVar* m_pParent; //0x0048
|
||||
const char* m_pszDefaultValue; //0x0050
|
||||
CVValue_t m_Value; //0c0058
|
||||
bool m_bHasMin; //0x0070
|
||||
float m_fMinVal; //0x0074
|
||||
bool m_bHasMax; //0x0078
|
||||
float m_fMaxVal; //0x007C
|
||||
CUtlVector<FnChangeCallback_t> m_fnChangeCallbacks; //0x0080
|
||||
}; //Size: 0x00A0
|
||||
static_assert(sizeof(ConVar) == 0xA0);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a boolean.
|
||||
// Output : bool
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE bool ConVar::GetBool(void) const
|
||||
{
|
||||
return !!GetInt();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a float.
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE float ConVar::GetFloat(void) const
|
||||
{
|
||||
return m_pParent->m_Value.m_fValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a double.
|
||||
// Output : double
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE double ConVar::GetDouble(void) const
|
||||
{
|
||||
return static_cast<double>(m_pParent->m_Value.m_fValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as an integer.
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE int ConVar::GetInt(void) const
|
||||
{
|
||||
return m_pParent->m_Value.m_nValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a color.
|
||||
// Output : Color
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE Color ConVar::GetColor(void) const
|
||||
{
|
||||
unsigned char* pColorElement = (reinterpret_cast<unsigned char*>(&m_pParent->m_Value.m_nValue));
|
||||
return Color(pColorElement[0], pColorElement[1], pColorElement[2], pColorElement[3]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return ConVar value as a string.
|
||||
// Output : const char *
|
||||
//-----------------------------------------------------------------------------
|
||||
FORCEINLINE 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 : "";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Console variable flags container for tools
|
||||
@ -289,52 +161,21 @@ extern ConVarFlags g_ConVarFlags;
|
||||
bool ConVar_ParseFlagString(const char* pszFlags, int& nFlags, const char* pszConVarName = "<<unspecified>>");
|
||||
void ConVar_PrintDescription(ConCommandBase* pVar);
|
||||
|
||||
/* ==== CONVAR ========================================================================================================================================================== */
|
||||
inline CMemory p_ConVar_Register;
|
||||
inline void*(*v_ConVar_Register)(ConVar* thisptr, const char* szName, const char* szDefaultValue, int nFlags, const char* szHelpString, bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t pCallback, const char* pszUsageString);
|
||||
|
||||
inline CMemory p_ConVar_Unregister;
|
||||
inline void(*v_ConVar_Unregister)(ConVar* thisptr);
|
||||
|
||||
inline CMemory p_ConVar_IsFlagSet;
|
||||
inline bool(*v_ConVar_IsFlagSet)(ConVar* pConVar, int nFlag);
|
||||
|
||||
inline CMemory p_ConVar_PrintDescription;
|
||||
inline void*(*v_ConVar_PrintDescription)(ConCommandBase* pVar);
|
||||
|
||||
inline ConVar* g_pConVarVBTable;
|
||||
inline IConVar* g_pConVarVFTable;
|
||||
inline void* (*v_ConVar_PrintDescription)(ConCommandBase* pVar);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class VCVar : public IDetour
|
||||
{
|
||||
virtual void GetAdr(void) const
|
||||
{
|
||||
LogConAdr("ConCommand::`vftable'", reinterpret_cast<uintptr_t>(g_pConCommandVFTable));
|
||||
LogConAdr("ConVar::`vbtable'", reinterpret_cast<uintptr_t>(g_pConVarVBTable));
|
||||
LogConAdr("ConVar::`vftable'", reinterpret_cast<uintptr_t>(g_pConVarVFTable));
|
||||
LogFunAdr("ConVar::Register", p_ConVar_Register.GetPtr());
|
||||
LogFunAdr("ConVar::Unregister", p_ConVar_Unregister.GetPtr());
|
||||
LogFunAdr("ConVar::IsFlagSet", p_ConVar_IsFlagSet.GetPtr());
|
||||
LogFunAdr("ConVar_PrintDescription", p_ConVar_PrintDescription.GetPtr());
|
||||
LogVarAdr("g_pCVar", reinterpret_cast<uintptr_t>(g_pCVar));
|
||||
}
|
||||
virtual void GetFun(void) const
|
||||
virtual void GetFun(void) const
|
||||
{
|
||||
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
|
||||
p_ConVar_Register = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 30 F3 0F 10 44 24 ??");
|
||||
p_ConVar_Unregister = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC 20 48 8B 59 58 48 8D 05 ?? ?? ?? ??");
|
||||
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
|
||||
p_ConVar_Register = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 40 F3 0F 10 84 24 ?? ?? ?? ??");
|
||||
p_ConVar_Unregister = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B 79 58");
|
||||
#endif
|
||||
p_ConVar_IsFlagSet = g_GameDll.FindPatternSIMD("48 8B 41 48 85 50 38");
|
||||
p_ConVar_PrintDescription = g_GameDll.FindPatternSIMD("B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 01 48 89 9C 24 ?? ?? ?? ??");
|
||||
|
||||
v_ConVar_IsFlagSet = p_ConVar_IsFlagSet.RCast<bool (*)(ConVar*, int)>();
|
||||
v_ConVar_Register = p_ConVar_Register.RCast<void* (*)(ConVar*, const char*, const char*, int, const char*, bool, float, bool, float, FnChangeCallback_t, const char*)>();
|
||||
v_ConVar_Unregister = p_ConVar_Unregister.RCast<void (*)(ConVar*)>();
|
||||
v_ConVar_PrintDescription = p_ConVar_PrintDescription.RCast<void* (*)(ConCommandBase*)>();
|
||||
p_ConVar_PrintDescription = g_GameDll.FindPatternSIMD("B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B 01 48 89 9C 24 ?? ?? ?? ??");
|
||||
v_ConVar_PrintDescription = p_ConVar_PrintDescription.RCast<void* (*)(ConCommandBase*)>();
|
||||
}
|
||||
virtual void GetVar(void) const
|
||||
{
|
||||
@ -344,11 +185,7 @@ class VCVar : public IDetour
|
||||
//g_pCVar = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 83 3D ?? ?? ?? ?? ?? 48 8B D9 74 09") // Actual CCvar, above is the vtable ptr.
|
||||
//.FindPatternSelf("48 83 3D", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x8).RCast<CCvar*>();
|
||||
}
|
||||
virtual void GetCon(void) const
|
||||
{
|
||||
g_pConVarVBTable = g_GameDll.GetVirtualMethodTable(".?AVConVar@@", 0).RCast<ConVar*>();
|
||||
g_pConVarVFTable = g_GameDll.GetVirtualMethodTable(".?AVConVar@@", 1).RCast<IConVar*>();
|
||||
}
|
||||
virtual void GetCon(void) const { }
|
||||
virtual void Attach(void) const;
|
||||
virtual void Detach(void) const;
|
||||
};
|
||||
|
@ -22,6 +22,7 @@ add_sources( SOURCE_GROUP "Utility"
|
||||
|
||||
add_sources( SOURCE_GROUP "Private"
|
||||
"cmd.cpp"
|
||||
"convar.cpp"
|
||||
"cvar.cpp"
|
||||
)
|
||||
|
||||
|
@ -274,90 +274,3 @@ void CCommand::Reset()
|
||||
m_pArgSBuffer[0] = 0;
|
||||
m_nQueuedVal = cmd_source_t::kCommandSrcInvalid;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: create
|
||||
//-----------------------------------------------------------------------------
|
||||
ConCommand* ConCommand::StaticCreate(const char* pszName, const char* pszHelpString, const char* pszUsageString,
|
||||
int nFlags, FnCommandCallback_t pCallback, FnCommandCompletionCallback pCompletionFunc)
|
||||
{
|
||||
ConCommand* pCommand = (ConCommand*)malloc(sizeof(ConCommand));
|
||||
*(ConCommandBase**)pCommand = g_pConCommandVFTable;
|
||||
|
||||
pCommand->m_pNext = nullptr;
|
||||
pCommand->m_bRegistered = false;
|
||||
|
||||
pCommand->m_pszName = pszName;
|
||||
pCommand->m_pszHelpString = pszHelpString;
|
||||
pCommand->m_pszUsageString = pszUsageString;
|
||||
pCommand->s_pAccessor = nullptr;
|
||||
pCommand->m_nFlags = nFlags;
|
||||
|
||||
pCommand->m_nNullCallBack = NullSub;
|
||||
pCommand->m_pSubCallback = nullptr;
|
||||
pCommand->m_fnCommandCallback = pCallback;
|
||||
pCommand->m_bHasCompletionCallback = pCompletionFunc != nullptr ? true : false;
|
||||
pCommand->m_bUsingNewCommandCallback = true;
|
||||
pCommand->m_bUsingCommandCallbackInterface = false;
|
||||
pCommand->m_fnCompletionCallback = pCompletionFunc ? pCompletionFunc : CallbackStub;
|
||||
|
||||
g_pCVar->RegisterConCommand(pCommand);
|
||||
return pCommand;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: construct/allocate
|
||||
//-----------------------------------------------------------------------------
|
||||
ConCommand::ConCommand()
|
||||
: m_nNullCallBack(nullptr)
|
||||
, m_pSubCallback(nullptr)
|
||||
, m_fnCommandCallbackV1(nullptr)
|
||||
, m_fnCompletionCallback(nullptr)
|
||||
, m_bHasCompletionCallback(false)
|
||||
, m_bUsingNewCommandCallback(false)
|
||||
, m_bUsingCommandCallbackInterface(false)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Checks if ConCommand has requested flags.
|
||||
// Input : nFlags -
|
||||
// Output : True if ConCommand has nFlags.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConCommandBase::HasFlags(int nFlags) const
|
||||
{
|
||||
return m_nFlags & nFlags;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : const ConCommandBase
|
||||
//-----------------------------------------------------------------------------
|
||||
ConCommandBase* ConCommandBase::GetNext(void) const
|
||||
{
|
||||
return m_pNext;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Copies string using local new/delete operators
|
||||
// Input : *szFrom -
|
||||
// Output : char
|
||||
//-----------------------------------------------------------------------------
|
||||
char* ConCommandBase::CopyString(const char* szFrom) const
|
||||
{
|
||||
size_t nLen;
|
||||
char* szTo;
|
||||
|
||||
nLen = strlen(szFrom);
|
||||
if (nLen <= 0)
|
||||
{
|
||||
szTo = new char[1];
|
||||
szTo[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
szTo = new char[nLen + 1];
|
||||
memmove(szTo, szFrom, nLen + 1);
|
||||
}
|
||||
return szTo;
|
||||
}
|
||||
|
497
r5dev/tier1/convar.cpp
Normal file
497
r5dev/tier1/convar.cpp
Normal file
@ -0,0 +1,497 @@
|
||||
//=============================================================================//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
#include "tier0/tslist.h"
|
||||
#include "tier1/convar.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Checks if ConCommand has requested flags.
|
||||
// Input : nFlags -
|
||||
// Output : True if ConCommand has nFlags.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConCommandBase::HasFlags(int nFlags) const
|
||||
{
|
||||
return m_nFlags & nFlags;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : const ConCommandBase
|
||||
//-----------------------------------------------------------------------------
|
||||
ConCommandBase* ConCommandBase::GetNext(void) const
|
||||
{
|
||||
return m_pNext;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Copies string using local new/delete operators
|
||||
// Input : *szFrom -
|
||||
// Output : char
|
||||
//-----------------------------------------------------------------------------
|
||||
char* ConCommandBase::CopyString(const char* szFrom) const
|
||||
{
|
||||
size_t nLen;
|
||||
char* szTo;
|
||||
|
||||
nLen = strlen(szFrom);
|
||||
if (nLen <= 0)
|
||||
{
|
||||
szTo = new char[1];
|
||||
szTo[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
szTo = new char[nLen + 1];
|
||||
memmove(szTo, szFrom, nLen + 1);
|
||||
}
|
||||
return szTo;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Default do nothing function
|
||||
//-----------------------------------------------------------------------------
|
||||
void DefaultNullSub()
|
||||
{
|
||||
; /*DO NOTHING*/
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Default console command autocompletion function
|
||||
//-----------------------------------------------------------------------------
|
||||
int DefaultCompletionFunc(const char* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: create
|
||||
//-----------------------------------------------------------------------------
|
||||
ConCommand* ConCommand::StaticCreate(const char* pszName, const char* pszHelpString, const char* pszUsageString,
|
||||
int nFlags, FnCommandCallback_t pCallback, FnCommandCompletionCallback pCompletionFunc)
|
||||
{
|
||||
ConCommand* pCommand = (ConCommand*)malloc(sizeof(ConCommand));
|
||||
*(ConCommand**)pCommand = g_pConCommandVFTable;
|
||||
|
||||
pCommand->m_pNext = nullptr;
|
||||
pCommand->m_bRegistered = false;
|
||||
|
||||
pCommand->m_pszName = pszName;
|
||||
pCommand->m_pszHelpString = pszHelpString;
|
||||
pCommand->m_pszUsageString = pszUsageString;
|
||||
pCommand->s_pAccessor = nullptr;
|
||||
pCommand->m_nFlags = nFlags;
|
||||
|
||||
pCommand->m_nNullCallBack = DefaultNullSub;
|
||||
pCommand->m_pSubCallback = nullptr;
|
||||
pCommand->m_fnCommandCallback = pCallback;
|
||||
pCommand->m_bHasCompletionCallback = pCompletionFunc != nullptr ? true : false;
|
||||
pCommand->m_bUsingNewCommandCallback = true;
|
||||
pCommand->m_bUsingCommandCallbackInterface = false;
|
||||
pCommand->m_fnCompletionCallback = pCompletionFunc ? pCompletionFunc : DefaultCompletionFunc;
|
||||
|
||||
g_pCVar->RegisterConCommand(pCommand);
|
||||
return pCommand;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: construct/allocate
|
||||
//-----------------------------------------------------------------------------
|
||||
ConCommand::ConCommand()
|
||||
: m_nNullCallBack(nullptr)
|
||||
, m_pSubCallback(nullptr)
|
||||
, m_fnCommandCallbackV1(nullptr)
|
||||
, m_fnCompletionCallback(nullptr)
|
||||
, m_bHasCompletionCallback(false)
|
||||
, m_bUsingNewCommandCallback(false)
|
||||
, m_bUsingCommandCallbackInterface(false)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: create
|
||||
//-----------------------------------------------------------------------------
|
||||
ConVar* ConVar::StaticCreate(const char* pszName, const char* pszDefaultValue,
|
||||
int nFlags, const char* pszHelpString, bool bMin, float fMin, bool bMax,
|
||||
float fMax, FnChangeCallback_t pCallback, const char* pszUsageString)
|
||||
{
|
||||
ConVar* pNewConVar = (ConVar*)malloc(sizeof(ConVar));
|
||||
|
||||
pNewConVar->m_bRegistered = false;
|
||||
*(ConVar**)pNewConVar = g_pConVarVBTable;
|
||||
char* pConVarVFTable = (char*)pNewConVar + sizeof(ConCommandBase);
|
||||
*(IConVar**)pConVarVFTable = g_pConVarVFTable;
|
||||
|
||||
pNewConVar->m_pszName = nullptr;
|
||||
pNewConVar->m_pszHelpString = nullptr;
|
||||
pNewConVar->m_pszUsageString = nullptr;
|
||||
pNewConVar->s_pAccessor = nullptr;
|
||||
pNewConVar->m_nFlags = FCVAR_NONE;
|
||||
pNewConVar->m_pNext = nullptr;
|
||||
|
||||
pNewConVar->m_fnChangeCallbacks.Init();
|
||||
|
||||
v_ConVar_Register(pNewConVar, pszName, pszDefaultValue, nFlags,
|
||||
pszHelpString, bMin, fMin, bMax, fMax, pCallback, pszUsageString);
|
||||
return pNewConVar;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: destroy
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::Destroy(void)
|
||||
{
|
||||
v_ConVar_Unregister(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: construct/allocate
|
||||
//-----------------------------------------------------------------------------
|
||||
ConVar::ConVar(void)
|
||||
: m_pParent(nullptr)
|
||||
, m_pszDefaultValue(nullptr)
|
||||
, m_bHasMin(false)
|
||||
, m_fMinVal(0.f)
|
||||
, m_bHasMax(false)
|
||||
, m_fMaxVal(0.f)
|
||||
{
|
||||
m_Value.m_pszString = nullptr;
|
||||
m_Value.m_iStringLength = 0;
|
||||
m_Value.m_fValue = 0.0f;
|
||||
m_Value.m_nValue = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
//ConVar::~ConVar(void)
|
||||
//{
|
||||
// if (m_Value.m_pszString)
|
||||
// {
|
||||
// delete[] m_Value.m_pszString);
|
||||
// m_Value.m_pszString = NULL;
|
||||
// }
|
||||
//}
|
||||
|
||||
////-----------------------------------------------------------------------------
|
||||
//// Purpose: Returns the base ConVar name.
|
||||
//// Output : const char*
|
||||
////-----------------------------------------------------------------------------
|
||||
//const char* ConVar::GetBaseName(void) const
|
||||
//{
|
||||
// return m_pParent->m_pszName;
|
||||
//}
|
||||
//
|
||||
////-----------------------------------------------------------------------------
|
||||
//// Purpose: Returns the ConVar help text.
|
||||
//// Output : const char*
|
||||
////-----------------------------------------------------------------------------
|
||||
//const char* ConVar::GetHelpText(void) const
|
||||
//{
|
||||
// return m_pParent->m_pszHelpString;
|
||||
//}
|
||||
//
|
||||
////-----------------------------------------------------------------------------
|
||||
//// Purpose: Returns the ConVar usage text.
|
||||
//// Output : const char*
|
||||
////-----------------------------------------------------------------------------
|
||||
//const char* ConVar::GetUsageText(void) const
|
||||
//{
|
||||
// return m_pParent->m_pszUsageString;
|
||||
//}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flMaxVal -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetMax(float flMaxVal)
|
||||
{
|
||||
m_pParent->m_fMaxVal = flMaxVal;
|
||||
m_pParent->m_bHasMax = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flMinVal -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetMin(float flMinVal)
|
||||
{
|
||||
m_pParent->m_fMinVal = flMinVal;
|
||||
m_pParent->m_bHasMin = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flMinVal -
|
||||
// Output : true if there is a min set.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::GetMin(float& flMinVal) const
|
||||
{
|
||||
flMinVal = m_pParent->m_fMinVal;
|
||||
return m_pParent->m_bHasMin;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flMaxVal -
|
||||
// Output : true if there is a max set.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::GetMax(float& flMaxVal) const
|
||||
{
|
||||
flMaxVal = m_pParent->m_fMaxVal;
|
||||
return m_pParent->m_bHasMax;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the min value.
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
float ConVar::GetMinValue(void) const
|
||||
{
|
||||
return m_pParent->m_fMinVal;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the max value.
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
float ConVar::GetMaxValue(void) const
|
||||
{
|
||||
return m_pParent->m_fMaxVal;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if ConVar has min value.
|
||||
// Output : bool
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::HasMin(void) const
|
||||
{
|
||||
return m_pParent->m_bHasMin;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if ConVar has max value.
|
||||
// Output : bool
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::HasMax(void) const
|
||||
{
|
||||
return m_pParent->m_bHasMax;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the ConVar int value.
|
||||
// Input : nValue -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetValue(int nValue)
|
||||
{
|
||||
ConVar* pCVar = reinterpret_cast<ConVar*>(m_pParent);
|
||||
pCVar->InternalSetIntValue(nValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the ConVar float value.
|
||||
// Input : flValue -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetValue(float flValue)
|
||||
{
|
||||
ConVar* pCVar = reinterpret_cast<ConVar*>(m_pParent);
|
||||
pCVar->InternalSetFloatValue(flValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the ConVar string value.
|
||||
// Input : *szValue -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetValue(const char* pszValue)
|
||||
{
|
||||
ConVar* pCVar = reinterpret_cast<ConVar*>(m_pParent);
|
||||
pCVar->InternalSetValue(pszValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the ConVar color value.
|
||||
// Input : value -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetValue(Color value)
|
||||
{
|
||||
ConVar* pCVar = reinterpret_cast<ConVar*>(m_pParent);
|
||||
pCVar->InternalSetColorValue(value);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *value -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::InternalSetColorValue(Color value)
|
||||
{
|
||||
// Stuff color values into an int
|
||||
int nValue = 0;
|
||||
|
||||
unsigned char* pColorElement = (reinterpret_cast<unsigned char*>(&nValue));
|
||||
pColorElement[0] = value[0];
|
||||
pColorElement[1] = value[1];
|
||||
pColorElement[2] = value[2];
|
||||
pColorElement[3] = value[3];
|
||||
|
||||
// Call the int internal set
|
||||
InternalSetIntValue(nValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Reset to default value.
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::Revert(void)
|
||||
{
|
||||
SetValue(m_pszDefaultValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the default ConVar value.
|
||||
// Output : const char
|
||||
//-----------------------------------------------------------------------------
|
||||
const char* ConVar::GetDefault(void) const
|
||||
{
|
||||
return m_pParent->m_pszDefaultValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the default ConVar value.
|
||||
// Input : *pszDefault -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetDefault(const char* pszDefault)
|
||||
{
|
||||
static const char* pszEmpty = "";
|
||||
m_pszDefaultValue = pszDefault ? pszDefault : pszEmpty;
|
||||
assert(m_pszDefaultValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the ConVar color value from string.
|
||||
// Input : *pszValue -
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::SetColorFromString(const char* pszValue)
|
||||
{
|
||||
bool bColor = false;
|
||||
|
||||
// Try pulling RGBA color values out of the string.
|
||||
int nRGBA[4];
|
||||
int nParamsRead = sscanf_s(pszValue, "%i %i %i %i",
|
||||
&(nRGBA[0]), &(nRGBA[1]), &(nRGBA[2]), &(nRGBA[3]));
|
||||
|
||||
if (nParamsRead >= 3)
|
||||
{
|
||||
// This is probably a color!
|
||||
if (nParamsRead == 3)
|
||||
{
|
||||
// Assume they wanted full alpha.
|
||||
nRGBA[3] = 255;
|
||||
}
|
||||
|
||||
if (nRGBA[0] >= 0 && nRGBA[0] <= 255 &&
|
||||
nRGBA[1] >= 0 && nRGBA[1] <= 255 &&
|
||||
nRGBA[2] >= 0 && nRGBA[2] <= 255 &&
|
||||
nRGBA[3] >= 0 && nRGBA[3] <= 255)
|
||||
{
|
||||
//printf("*** WOW! Found a color!! ***\n");
|
||||
|
||||
// This is definitely a color!
|
||||
bColor = true;
|
||||
|
||||
// Stuff all the values into each byte of our int.
|
||||
unsigned char* pColorElement =
|
||||
(reinterpret_cast<unsigned char*>(&m_Value.m_nValue));
|
||||
|
||||
pColorElement[0] = (unsigned char)nRGBA[0];
|
||||
pColorElement[1] = (unsigned char)nRGBA[1];
|
||||
pColorElement[2] = (unsigned char)nRGBA[2];
|
||||
pColorElement[3] = (unsigned char)nRGBA[3];
|
||||
|
||||
// Copy that value into our float.
|
||||
m_Value.m_fValue = static_cast<float>(m_Value.m_nValue);
|
||||
}
|
||||
}
|
||||
|
||||
return bColor;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: changes the ConVar string value.
|
||||
// Input : *pszTempVal - flOldValue
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::ChangeStringValue(const char* pszTempVal)
|
||||
{
|
||||
Assert(!(m_nFlags & FCVAR_NEVER_AS_STRING));
|
||||
|
||||
char* pszOldValue = (char*)stackalloc(m_Value.m_iStringLength);
|
||||
memcpy(pszOldValue, m_Value.m_pszString, m_Value.m_iStringLength);
|
||||
|
||||
size_t len = strlen(pszTempVal) + 1;
|
||||
|
||||
if (len > m_Value.m_iStringLength)
|
||||
{
|
||||
if (m_Value.m_pszString)
|
||||
{
|
||||
delete[] m_Value.m_pszString;
|
||||
}
|
||||
|
||||
m_Value.m_pszString = new char[len];
|
||||
m_Value.m_iStringLength = len;
|
||||
}
|
||||
|
||||
memcpy(reinterpret_cast<void*>(m_Value.m_pszString), pszTempVal, len);
|
||||
|
||||
// Invoke any necessary callback function
|
||||
for (int i = 0; i < m_fnChangeCallbacks.Count(); ++i)
|
||||
{
|
||||
m_fnChangeCallbacks[i](this, pszOldValue, NULL);
|
||||
}
|
||||
|
||||
if (g_pCVar)
|
||||
{
|
||||
g_pCVar->CallGlobalChangeCallbacks(this, pszOldValue);
|
||||
}
|
||||
|
||||
stackfree(pszOldValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Install a change callback (there shouldn't already be one....)
|
||||
// Input : callback -
|
||||
// bInvoke -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::InstallChangeCallback(FnChangeCallback_t callback, bool bInvoke /*=true*/)
|
||||
{
|
||||
if (!callback)
|
||||
{
|
||||
Warning(eDLL_T::COMMON, "%s: Called with NULL callback; ignoring!!!\n",
|
||||
__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pParent->m_fnChangeCallbacks.Find(callback)
|
||||
!= m_pParent->m_fnChangeCallbacks.InvalidIndex())
|
||||
{
|
||||
// Same ptr added twice, sigh...
|
||||
Warning(eDLL_T::COMMON, "%s: Ignoring duplicate change callback!!!\n",
|
||||
__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
m_pParent->m_fnChangeCallbacks.AddToTail(callback);
|
||||
|
||||
// Call it immediately to set the initial value...
|
||||
if (bInvoke)
|
||||
{
|
||||
callback(this, m_Value.m_pszString, m_Value.m_fValue);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Install a change callback (there shouldn't already be one....)
|
||||
// Input : callback -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::RemoveChangeCallback(FnChangeCallback_t callback)
|
||||
{
|
||||
m_pParent->m_fnChangeCallbacks.FindAndRemove(callback);
|
||||
}
|
@ -1,398 +1,12 @@
|
||||
#include "tier1/utlrbtree.h"
|
||||
#include "tier1/utlmap.h"
|
||||
#include "tier1/NetAdr.h"
|
||||
//=============================================================================//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
#include "mathlib/color.h"
|
||||
#include "tier1/convar.h"
|
||||
#include "tier1/cvar.h"
|
||||
#include "public/const.h"
|
||||
#include "engine/sys_dll2.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "vstdlib/concommandhash.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: create
|
||||
//-----------------------------------------------------------------------------
|
||||
ConVar* ConVar::StaticCreate(const char* pszName, const char* pszDefaultValue,
|
||||
int nFlags, const char* pszHelpString, bool bMin, float fMin, bool bMax,
|
||||
float fMax, FnChangeCallback_t pCallback, const char* pszUsageString)
|
||||
{
|
||||
ConVar* pNewConVar = (ConVar*)malloc(sizeof(ConVar));
|
||||
|
||||
pNewConVar->m_bRegistered = false;
|
||||
*(ConVar**)pNewConVar = g_pConVarVBTable;
|
||||
char* pConVarVFTable = (char*)pNewConVar + sizeof(ConCommandBase);
|
||||
*(IConVar**)pConVarVFTable = g_pConVarVFTable;
|
||||
|
||||
pNewConVar->m_pszName = nullptr;
|
||||
pNewConVar->m_pszHelpString = nullptr;
|
||||
pNewConVar->m_pszUsageString = nullptr;
|
||||
pNewConVar->s_pAccessor = nullptr;
|
||||
pNewConVar->m_nFlags = FCVAR_NONE;
|
||||
pNewConVar->m_pNext = nullptr;
|
||||
|
||||
pNewConVar->m_fnChangeCallbacks.Init();
|
||||
|
||||
v_ConVar_Register(pNewConVar, pszName, pszDefaultValue, nFlags,
|
||||
pszHelpString, bMin, fMin, bMax, fMax, pCallback, pszUsageString);
|
||||
return pNewConVar;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: destroy
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::Destroy(void)
|
||||
{
|
||||
v_ConVar_Unregister(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: construct/allocate
|
||||
//-----------------------------------------------------------------------------
|
||||
ConVar::ConVar(void)
|
||||
: m_pParent(nullptr)
|
||||
, m_pszDefaultValue(nullptr)
|
||||
, m_bHasMin(false)
|
||||
, m_fMinVal(0.f)
|
||||
, m_bHasMax(false)
|
||||
, m_fMaxVal(0.f)
|
||||
{
|
||||
m_Value.m_pszString = nullptr;
|
||||
m_Value.m_iStringLength = 0;
|
||||
m_Value.m_fValue = 0.0f;
|
||||
m_Value.m_nValue = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: destructor
|
||||
//-----------------------------------------------------------------------------
|
||||
//ConVar::~ConVar(void)
|
||||
//{
|
||||
// if (m_Value.m_pszString)
|
||||
// {
|
||||
// delete[] m_Value.m_pszString);
|
||||
// m_Value.m_pszString = NULL;
|
||||
// }
|
||||
//}
|
||||
|
||||
////-----------------------------------------------------------------------------
|
||||
//// Purpose: Returns the base ConVar name.
|
||||
//// Output : const char*
|
||||
////-----------------------------------------------------------------------------
|
||||
//const char* ConVar::GetBaseName(void) const
|
||||
//{
|
||||
// return m_pParent->m_pszName;
|
||||
//}
|
||||
//
|
||||
////-----------------------------------------------------------------------------
|
||||
//// Purpose: Returns the ConVar help text.
|
||||
//// Output : const char*
|
||||
////-----------------------------------------------------------------------------
|
||||
//const char* ConVar::GetHelpText(void) const
|
||||
//{
|
||||
// return m_pParent->m_pszHelpString;
|
||||
//}
|
||||
//
|
||||
////-----------------------------------------------------------------------------
|
||||
//// Purpose: Returns the ConVar usage text.
|
||||
//// Output : const char*
|
||||
////-----------------------------------------------------------------------------
|
||||
//const char* ConVar::GetUsageText(void) const
|
||||
//{
|
||||
// return m_pParent->m_pszUsageString;
|
||||
//}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flMaxVal -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetMax(float flMaxVal)
|
||||
{
|
||||
m_pParent->m_fMaxVal = flMaxVal;
|
||||
m_pParent->m_bHasMax = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flMinVal -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetMin(float flMinVal)
|
||||
{
|
||||
m_pParent->m_fMinVal = flMinVal;
|
||||
m_pParent->m_bHasMin = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flMinVal -
|
||||
// Output : true if there is a min set.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::GetMin(float& flMinVal) const
|
||||
{
|
||||
flMinVal = m_pParent->m_fMinVal;
|
||||
return m_pParent->m_bHasMin;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flMaxVal -
|
||||
// Output : true if there is a max set.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::GetMax(float& flMaxVal) const
|
||||
{
|
||||
flMaxVal = m_pParent->m_fMaxVal;
|
||||
return m_pParent->m_bHasMax;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the min value.
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
float ConVar::GetMinValue(void) const
|
||||
{
|
||||
return m_pParent->m_fMinVal;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the max value.
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
float ConVar::GetMaxValue(void) const
|
||||
{
|
||||
return m_pParent->m_fMaxVal;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if ConVar has min value.
|
||||
// Output : bool
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::HasMin(void) const
|
||||
{
|
||||
return m_pParent->m_bHasMin;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if ConVar has max value.
|
||||
// Output : bool
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::HasMax(void) const
|
||||
{
|
||||
return m_pParent->m_bHasMax;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the ConVar int value.
|
||||
// Input : nValue -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetValue(int nValue)
|
||||
{
|
||||
ConVar* pCVar = reinterpret_cast<ConVar*>(m_pParent);
|
||||
pCVar->InternalSetIntValue(nValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the ConVar float value.
|
||||
// Input : flValue -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetValue(float flValue)
|
||||
{
|
||||
ConVar* pCVar = reinterpret_cast<ConVar*>(m_pParent);
|
||||
pCVar->InternalSetFloatValue(flValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the ConVar string value.
|
||||
// Input : *szValue -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetValue(const char* pszValue)
|
||||
{
|
||||
ConVar* pCVar = reinterpret_cast<ConVar*>(m_pParent);
|
||||
pCVar->InternalSetValue(pszValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the ConVar color value.
|
||||
// Input : value -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetValue(Color value)
|
||||
{
|
||||
ConVar* pCVar = reinterpret_cast<ConVar*>(m_pParent);
|
||||
pCVar->InternalSetColorValue(value);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *value -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::InternalSetColorValue(Color value)
|
||||
{
|
||||
// Stuff color values into an int
|
||||
int nValue = 0;
|
||||
|
||||
unsigned char* pColorElement = (reinterpret_cast<unsigned char*>(&nValue));
|
||||
pColorElement[0] = value[0];
|
||||
pColorElement[1] = value[1];
|
||||
pColorElement[2] = value[2];
|
||||
pColorElement[3] = value[3];
|
||||
|
||||
// Call the int internal set
|
||||
InternalSetIntValue(nValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Reset to default value.
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::Revert(void)
|
||||
{
|
||||
SetValue(m_pszDefaultValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns the default ConVar value.
|
||||
// Output : const char
|
||||
//-----------------------------------------------------------------------------
|
||||
const char* ConVar::GetDefault(void) const
|
||||
{
|
||||
return m_pParent->m_pszDefaultValue;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the default ConVar value.
|
||||
// Input : *pszDefault -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetDefault(const char* pszDefault)
|
||||
{
|
||||
static const char* pszEmpty = "";
|
||||
m_pszDefaultValue = pszDefault ? pszDefault : pszEmpty;
|
||||
assert(m_pszDefaultValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets the ConVar color value from string.
|
||||
// Input : *pszValue -
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::SetColorFromString(const char* pszValue)
|
||||
{
|
||||
bool bColor = false;
|
||||
|
||||
// Try pulling RGBA color values out of the string.
|
||||
int nRGBA[4];
|
||||
int nParamsRead = sscanf_s(pszValue, "%i %i %i %i",
|
||||
&(nRGBA[0]), &(nRGBA[1]), &(nRGBA[2]), &(nRGBA[3]));
|
||||
|
||||
if (nParamsRead >= 3)
|
||||
{
|
||||
// This is probably a color!
|
||||
if (nParamsRead == 3)
|
||||
{
|
||||
// Assume they wanted full alpha.
|
||||
nRGBA[3] = 255;
|
||||
}
|
||||
|
||||
if (nRGBA[0] >= 0 && nRGBA[0] <= 255 &&
|
||||
nRGBA[1] >= 0 && nRGBA[1] <= 255 &&
|
||||
nRGBA[2] >= 0 && nRGBA[2] <= 255 &&
|
||||
nRGBA[3] >= 0 && nRGBA[3] <= 255)
|
||||
{
|
||||
//printf("*** WOW! Found a color!! ***\n");
|
||||
|
||||
// This is definitely a color!
|
||||
bColor = true;
|
||||
|
||||
// Stuff all the values into each byte of our int.
|
||||
unsigned char* pColorElement =
|
||||
(reinterpret_cast<unsigned char*>(&m_Value.m_nValue));
|
||||
|
||||
pColorElement[0] = (unsigned char)nRGBA[0];
|
||||
pColorElement[1] = (unsigned char)nRGBA[1];
|
||||
pColorElement[2] = (unsigned char)nRGBA[2];
|
||||
pColorElement[3] = (unsigned char)nRGBA[3];
|
||||
|
||||
// Copy that value into our float.
|
||||
m_Value.m_fValue = static_cast<float>(m_Value.m_nValue);
|
||||
}
|
||||
}
|
||||
|
||||
return bColor;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: changes the ConVar string value.
|
||||
// Input : *pszTempVal - flOldValue
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::ChangeStringValue(const char* pszTempVal)
|
||||
{
|
||||
Assert(!(m_nFlags & FCVAR_NEVER_AS_STRING));
|
||||
|
||||
char* pszOldValue = (char*)stackalloc(m_Value.m_iStringLength);
|
||||
memcpy(pszOldValue, m_Value.m_pszString, m_Value.m_iStringLength);
|
||||
|
||||
size_t len = strlen(pszTempVal) + 1;
|
||||
|
||||
if (len > m_Value.m_iStringLength)
|
||||
{
|
||||
if (m_Value.m_pszString)
|
||||
{
|
||||
delete[] m_Value.m_pszString;
|
||||
}
|
||||
|
||||
m_Value.m_pszString = new char[len];
|
||||
m_Value.m_iStringLength = len;
|
||||
}
|
||||
|
||||
memcpy(reinterpret_cast<void*>(m_Value.m_pszString), pszTempVal, len);
|
||||
|
||||
// Invoke any necessary callback function
|
||||
for (int i = 0; i < m_fnChangeCallbacks.Count(); ++i)
|
||||
{
|
||||
m_fnChangeCallbacks[i](this, pszOldValue, NULL);
|
||||
}
|
||||
|
||||
if (g_pCVar)
|
||||
{
|
||||
g_pCVar->CallGlobalChangeCallbacks(this, pszOldValue);
|
||||
}
|
||||
|
||||
stackfree(pszOldValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Install a change callback (there shouldn't already be one....)
|
||||
// Input : callback -
|
||||
// bInvoke -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::InstallChangeCallback(FnChangeCallback_t callback, bool bInvoke /*=true*/)
|
||||
{
|
||||
if (!callback)
|
||||
{
|
||||
Warning(eDLL_T::COMMON, "%s: Called with NULL callback; ignoring!!!\n",
|
||||
__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pParent->m_fnChangeCallbacks.Find(callback)
|
||||
!= m_pParent->m_fnChangeCallbacks.InvalidIndex())
|
||||
{
|
||||
// Same ptr added twice, sigh...
|
||||
Warning(eDLL_T::COMMON, "%s: Ignoring duplicate change callback!!!\n",
|
||||
__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
m_pParent->m_fnChangeCallbacks.AddToTail(callback);
|
||||
|
||||
// Call it immediately to set the initial value...
|
||||
if (bInvoke)
|
||||
{
|
||||
callback(this, m_Value.m_pszString, m_Value.m_fValue);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Install a change callback (there shouldn't already be one....)
|
||||
// Input : callback -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::RemoveChangeCallback(FnChangeCallback_t callback)
|
||||
{
|
||||
m_pParent->m_fnChangeCallbacks.FindAndRemove(callback);
|
||||
}
|
||||
|
||||
#define SET_CONVARFLAG(x, y) SetFlag(FCVAR_##x, #x, y)
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1064,212 +678,6 @@ int CCvarUtilities::CvarFindFlagsCompletionCallback(const char* partial,
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
CCvar* g_pCVar = nullptr;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Console command hash data structure
|
||||
//-----------------------------------------------------------------------------
|
||||
CConCommandHash::CConCommandHash()
|
||||
{
|
||||
Purge(true);
|
||||
}
|
||||
|
||||
CConCommandHash::~CConCommandHash()
|
||||
{
|
||||
Purge(false);
|
||||
}
|
||||
|
||||
void CConCommandHash::Purge(bool bReinitialize)
|
||||
{
|
||||
m_aBuckets.Purge();
|
||||
m_aDataPool.Purge();
|
||||
if (bReinitialize)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize.
|
||||
void CConCommandHash::Init(void)
|
||||
{
|
||||
// kNUM_BUCKETS must be a power of two.
|
||||
COMPILE_TIME_ASSERT((kNUM_BUCKETS & (kNUM_BUCKETS - 1)) == 0);
|
||||
|
||||
// Set the bucket size.
|
||||
m_aBuckets.SetSize(kNUM_BUCKETS);
|
||||
for (int iBucket = 0; iBucket < kNUM_BUCKETS; ++iBucket)
|
||||
{
|
||||
m_aBuckets[iBucket] = m_aDataPool.InvalidIndex();
|
||||
}
|
||||
|
||||
// Calculate the grow size.
|
||||
int nGrowSize = 4 * kNUM_BUCKETS;
|
||||
m_aDataPool.SetGrowSize(nGrowSize);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Insert data into the hash table given its key (unsigned int),
|
||||
// WITH a check to see if the element already exists within the hash.
|
||||
//-----------------------------------------------------------------------------
|
||||
CConCommandHash::CCommandHashHandle_t CConCommandHash::Insert(ConCommandBase* cmd)
|
||||
{
|
||||
// Check to see if that key already exists in the buckets (should be unique).
|
||||
CCommandHashHandle_t hHash = Find(cmd);
|
||||
if (hHash != InvalidHandle())
|
||||
return hHash;
|
||||
|
||||
return FastInsert(cmd);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Insert data into the hash table given its key (unsigned int),
|
||||
// WITHOUT a check to see if the element already exists within the hash.
|
||||
//-----------------------------------------------------------------------------
|
||||
CConCommandHash::CCommandHashHandle_t CConCommandHash::FastInsert(ConCommandBase* cmd)
|
||||
{
|
||||
// Get a new element from the pool.
|
||||
intptr_t iHashData = m_aDataPool.Alloc(true);
|
||||
HashEntry_t* RESTRICT pHashData = &m_aDataPool[iHashData];
|
||||
if (!pHashData)
|
||||
return InvalidHandle();
|
||||
|
||||
HashKey_t key = Hash(cmd);
|
||||
|
||||
// Add data to new element.
|
||||
pHashData->m_uiKey = key;
|
||||
pHashData->m_Data = cmd;
|
||||
|
||||
// Link element.
|
||||
int iBucket = key & kBUCKETMASK; // HashFuncs::Hash( uiKey, m_uiBucketMask );
|
||||
m_aDataPool.LinkBefore(m_aBuckets[iBucket], iHashData);
|
||||
m_aBuckets[iBucket] = iHashData;
|
||||
|
||||
return iHashData;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Remove a given element from the hash.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CConCommandHash::Remove(CCommandHashHandle_t hHash) /*RESTRICT*/
|
||||
{
|
||||
HashEntry_t* /*RESTRICT*/ entry = &m_aDataPool[hHash];
|
||||
HashKey_t iBucket = entry->m_uiKey & kBUCKETMASK;
|
||||
if (m_aBuckets[iBucket] == hHash)
|
||||
{
|
||||
// It is a bucket head.
|
||||
m_aBuckets[iBucket] = m_aDataPool.Next(hHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not a bucket head.
|
||||
m_aDataPool.Unlink(hHash);
|
||||
}
|
||||
|
||||
// Remove the element.
|
||||
m_aDataPool.Remove(hHash);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Remove all elements from the hash
|
||||
//-----------------------------------------------------------------------------
|
||||
void CConCommandHash::RemoveAll(void)
|
||||
{
|
||||
m_aBuckets.RemoveAll();
|
||||
m_aDataPool.RemoveAll();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Find hash entry corresponding to a string name
|
||||
//-----------------------------------------------------------------------------
|
||||
CConCommandHash::CCommandHashHandle_t CConCommandHash::Find(
|
||||
const char* name, HashKey_t hashkey) const /*RESTRICT*/
|
||||
{
|
||||
// hash the "key" - get the correct hash table "bucket"
|
||||
int iBucket = hashkey & kBUCKETMASK;
|
||||
|
||||
for (datapool_t::IndexLocalType_t iElement = m_aBuckets[iBucket];
|
||||
iElement != m_aDataPool.InvalidIndex(); iElement = m_aDataPool.Next(iElement))
|
||||
{
|
||||
const HashEntry_t& element = m_aDataPool[iElement];
|
||||
if (element.m_uiKey == hashkey && // if hashes of strings match,
|
||||
Q_stricmp(name, element.m_Data->GetName()) == 0) // then test the actual strings
|
||||
{
|
||||
return iElement;
|
||||
}
|
||||
}
|
||||
|
||||
// found nuffink
|
||||
return InvalidHandle();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Find a command in the hash.
|
||||
//-----------------------------------------------------------------------------
|
||||
CConCommandHash::CCommandHashHandle_t CConCommandHash::Find(const ConCommandBase* cmd) const /*RESTRICT*/
|
||||
{
|
||||
// Set this #if to 1 if the assert at bottom starts whining --
|
||||
// that indicates that a console command is being double-registered,
|
||||
// or something similarly non-fatally bad. With this #if 1, we'll search
|
||||
// by name instead of by pointer, which is more robust in the face
|
||||
// of double registered commands, but obviously slower.
|
||||
#if 0
|
||||
return Find(cmd->GetName());
|
||||
#else
|
||||
HashKey_t hashkey = Hash(cmd);
|
||||
int iBucket = hashkey & kBUCKETMASK;
|
||||
|
||||
// hunt through all entries in that bucket
|
||||
for (datapool_t::IndexLocalType_t iElement = m_aBuckets[iBucket];
|
||||
iElement != m_aDataPool.InvalidIndex(); iElement = m_aDataPool.Next(iElement))
|
||||
{
|
||||
const HashEntry_t& element = m_aDataPool[iElement];
|
||||
if (element.m_uiKey == hashkey && // if the hashes match...
|
||||
element.m_Data == cmd) // and the pointers...
|
||||
{
|
||||
// in debug, test to make sure we don't have commands under the same name
|
||||
// or something goofy like that
|
||||
Assert(iElement == Find(cmd->GetName()),
|
||||
"ConCommand %s had two entries in the hash!", cmd->GetName());
|
||||
|
||||
// return this element
|
||||
return iElement;
|
||||
}
|
||||
}
|
||||
|
||||
// found nothing.
|
||||
#ifdef DBGFLAG_ASSERT // double check against search by name
|
||||
CCommandHashHandle_t dbghand = Find(cmd->GetName());
|
||||
|
||||
Assert(InvalidHandle() == dbghand,
|
||||
"ConCommand %s couldn't be found by pointer, but was found by name!", cmd->GetName());
|
||||
#endif
|
||||
return InvalidHandle();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//#ifdef _DEBUG
|
||||
// Dump a report to MSG
|
||||
void CConCommandHash::Report(void)
|
||||
{
|
||||
DevMsg(eDLL_T::COMMON, "Console command hash bucket load:\n");
|
||||
int total = 0;
|
||||
for (int iBucket = 0; iBucket < kNUM_BUCKETS; ++iBucket)
|
||||
{
|
||||
int count = 0;
|
||||
CCommandHashHandle_t iElement = m_aBuckets[iBucket]; // get the head of the bucket
|
||||
while (iElement != m_aDataPool.InvalidIndex())
|
||||
{
|
||||
++count;
|
||||
iElement = m_aDataPool.Next(iElement);
|
||||
}
|
||||
|
||||
DevMsg(eDLL_T::COMMON, "%d: %d\n", iBucket, count);
|
||||
total += count;
|
||||
}
|
||||
|
||||
DevMsg(eDLL_T::COMMON, "\tAverage: %.1f\n", total / ((float)(kNUM_BUCKETS)));
|
||||
}
|
||||
//#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void VCVar::Attach() const
|
||||
{
|
||||
|
@ -6,6 +6,7 @@ start_sources()
|
||||
add_sources( SOURCE_GROUP "Private"
|
||||
"autocompletefilelist.cpp"
|
||||
"autocompletefilelist.h"
|
||||
"concommandhash.cpp"
|
||||
"concommandhash.h"
|
||||
"keyvaluessystem.cpp"
|
||||
"keyvaluessystem.h"
|
||||
|
211
r5dev/vstdlib/concommandhash.cpp
Normal file
211
r5dev/vstdlib/concommandhash.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
//=============================================================================//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
#include "concommandhash.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Console command hash data structure
|
||||
//-----------------------------------------------------------------------------
|
||||
CConCommandHash::CConCommandHash()
|
||||
{
|
||||
Purge(true);
|
||||
}
|
||||
|
||||
CConCommandHash::~CConCommandHash()
|
||||
{
|
||||
Purge(false);
|
||||
}
|
||||
|
||||
void CConCommandHash::Purge(bool bReinitialize)
|
||||
{
|
||||
m_aBuckets.Purge();
|
||||
m_aDataPool.Purge();
|
||||
if (bReinitialize)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize.
|
||||
void CConCommandHash::Init(void)
|
||||
{
|
||||
// kNUM_BUCKETS must be a power of two.
|
||||
COMPILE_TIME_ASSERT((kNUM_BUCKETS & (kNUM_BUCKETS - 1)) == 0);
|
||||
|
||||
// Set the bucket size.
|
||||
m_aBuckets.SetSize(kNUM_BUCKETS);
|
||||
for (int iBucket = 0; iBucket < kNUM_BUCKETS; ++iBucket)
|
||||
{
|
||||
m_aBuckets[iBucket] = m_aDataPool.InvalidIndex();
|
||||
}
|
||||
|
||||
// Calculate the grow size.
|
||||
int nGrowSize = 4 * kNUM_BUCKETS;
|
||||
m_aDataPool.SetGrowSize(nGrowSize);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Insert data into the hash table given its key (unsigned int),
|
||||
// WITH a check to see if the element already exists within the hash.
|
||||
//-----------------------------------------------------------------------------
|
||||
CConCommandHash::CCommandHashHandle_t CConCommandHash::Insert(ConCommandBase* cmd)
|
||||
{
|
||||
// Check to see if that key already exists in the buckets (should be unique).
|
||||
CCommandHashHandle_t hHash = Find(cmd);
|
||||
if (hHash != InvalidHandle())
|
||||
return hHash;
|
||||
|
||||
return FastInsert(cmd);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Insert data into the hash table given its key (unsigned int),
|
||||
// WITHOUT a check to see if the element already exists within the hash.
|
||||
//-----------------------------------------------------------------------------
|
||||
CConCommandHash::CCommandHashHandle_t CConCommandHash::FastInsert(ConCommandBase* cmd)
|
||||
{
|
||||
// Get a new element from the pool.
|
||||
intptr_t iHashData = m_aDataPool.Alloc(true);
|
||||
HashEntry_t* RESTRICT pHashData = &m_aDataPool[iHashData];
|
||||
if (!pHashData)
|
||||
return InvalidHandle();
|
||||
|
||||
HashKey_t key = Hash(cmd);
|
||||
|
||||
// Add data to new element.
|
||||
pHashData->m_uiKey = key;
|
||||
pHashData->m_Data = cmd;
|
||||
|
||||
// Link element.
|
||||
int iBucket = key & kBUCKETMASK; // HashFuncs::Hash( uiKey, m_uiBucketMask );
|
||||
m_aDataPool.LinkBefore(m_aBuckets[iBucket], iHashData);
|
||||
m_aBuckets[iBucket] = iHashData;
|
||||
|
||||
return iHashData;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Remove a given element from the hash.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CConCommandHash::Remove(CCommandHashHandle_t hHash) /*RESTRICT*/
|
||||
{
|
||||
HashEntry_t* /*RESTRICT*/ entry = &m_aDataPool[hHash];
|
||||
HashKey_t iBucket = entry->m_uiKey & kBUCKETMASK;
|
||||
if (m_aBuckets[iBucket] == hHash)
|
||||
{
|
||||
// It is a bucket head.
|
||||
m_aBuckets[iBucket] = m_aDataPool.Next(hHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not a bucket head.
|
||||
m_aDataPool.Unlink(hHash);
|
||||
}
|
||||
|
||||
// Remove the element.
|
||||
m_aDataPool.Remove(hHash);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Remove all elements from the hash
|
||||
//-----------------------------------------------------------------------------
|
||||
void CConCommandHash::RemoveAll(void)
|
||||
{
|
||||
m_aBuckets.RemoveAll();
|
||||
m_aDataPool.RemoveAll();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Find hash entry corresponding to a string name
|
||||
//-----------------------------------------------------------------------------
|
||||
CConCommandHash::CCommandHashHandle_t CConCommandHash::Find(
|
||||
const char* name, HashKey_t hashkey) const /*RESTRICT*/
|
||||
{
|
||||
// hash the "key" - get the correct hash table "bucket"
|
||||
int iBucket = hashkey & kBUCKETMASK;
|
||||
|
||||
for (datapool_t::IndexLocalType_t iElement = m_aBuckets[iBucket];
|
||||
iElement != m_aDataPool.InvalidIndex(); iElement = m_aDataPool.Next(iElement))
|
||||
{
|
||||
const HashEntry_t& element = m_aDataPool[iElement];
|
||||
if (element.m_uiKey == hashkey && // if hashes of strings match,
|
||||
Q_stricmp(name, element.m_Data->GetName()) == 0) // then test the actual strings
|
||||
{
|
||||
return iElement;
|
||||
}
|
||||
}
|
||||
|
||||
// found nuffink
|
||||
return InvalidHandle();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Find a command in the hash.
|
||||
//-----------------------------------------------------------------------------
|
||||
CConCommandHash::CCommandHashHandle_t CConCommandHash::Find(const ConCommandBase* cmd) const /*RESTRICT*/
|
||||
{
|
||||
// Set this #if to 1 if the assert at bottom starts whining --
|
||||
// that indicates that a console command is being double-registered,
|
||||
// or something similarly non-fatally bad. With this #if 1, we'll search
|
||||
// by name instead of by pointer, which is more robust in the face
|
||||
// of double registered commands, but obviously slower.
|
||||
#if 0
|
||||
return Find(cmd->GetName());
|
||||
#else
|
||||
HashKey_t hashkey = Hash(cmd);
|
||||
int iBucket = hashkey & kBUCKETMASK;
|
||||
|
||||
// hunt through all entries in that bucket
|
||||
for (datapool_t::IndexLocalType_t iElement = m_aBuckets[iBucket];
|
||||
iElement != m_aDataPool.InvalidIndex(); iElement = m_aDataPool.Next(iElement))
|
||||
{
|
||||
const HashEntry_t& element = m_aDataPool[iElement];
|
||||
if (element.m_uiKey == hashkey && // if the hashes match...
|
||||
element.m_Data == cmd) // and the pointers...
|
||||
{
|
||||
// in debug, test to make sure we don't have commands under the same name
|
||||
// or something goofy like that
|
||||
Assert(iElement == Find(cmd->GetName()),
|
||||
"ConCommand %s had two entries in the hash!", cmd->GetName());
|
||||
|
||||
// return this element
|
||||
return iElement;
|
||||
}
|
||||
}
|
||||
|
||||
// found nothing.
|
||||
#ifdef DBGFLAG_ASSERT // double check against search by name
|
||||
CCommandHashHandle_t dbghand = Find(cmd->GetName());
|
||||
|
||||
Assert(InvalidHandle() == dbghand,
|
||||
"ConCommand %s couldn't be found by pointer, but was found by name!", cmd->GetName());
|
||||
#endif
|
||||
return InvalidHandle();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//#ifdef _DEBUG
|
||||
// Dump a report to MSG
|
||||
void CConCommandHash::Report(void)
|
||||
{
|
||||
DevMsg(eDLL_T::COMMON, "Console command hash bucket load:\n");
|
||||
int total = 0;
|
||||
for (int iBucket = 0; iBucket < kNUM_BUCKETS; ++iBucket)
|
||||
{
|
||||
int count = 0;
|
||||
CCommandHashHandle_t iElement = m_aBuckets[iBucket]; // get the head of the bucket
|
||||
while (iElement != m_aDataPool.InvalidIndex())
|
||||
{
|
||||
++count;
|
||||
iElement = m_aDataPool.Next(iElement);
|
||||
}
|
||||
|
||||
DevMsg(eDLL_T::COMMON, "%d: %d\n", iBucket, count);
|
||||
total += count;
|
||||
}
|
||||
|
||||
DevMsg(eDLL_T::COMMON, "\tAverage: %.1f\n", total / ((float)(kNUM_BUCKETS)));
|
||||
}
|
||||
//#endif
|
@ -12,10 +12,10 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier1/cmd.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "tier1/utllinkedlist.h"
|
||||
#include "tier1/generichash.h"
|
||||
#include "tier1/convar.h"
|
||||
|
||||
// This is a hash table class very similar to the CUtlHashFast, but
|
||||
// modified specifically so that we can look up ConCommandBases
|
||||
|
Loading…
x
Reference in New Issue
Block a user