1
0
mirror of https://github.com/alliedmodders/hl2sdk.git synced 2025-09-20 12:36:05 +08:00

Update ConCommand/ConCommandBase/CCommand/ConCommandHandle

This commit is contained in:
Nick Hastings
2023-05-14 10:25:40 -04:00
committed by Nicholas Hastings
parent 2f8a20a49c
commit 2c9f711bbd
5 changed files with 638 additions and 866 deletions

View File

@ -11,43 +11,21 @@
#endif #endif
#include "appframework/IAppSystem.h" #include "appframework/IAppSystem.h"
#include "tier1/convar.h"
#include "tier1/utlvector.h" #include "tier1/utlvector.h"
#include "tier0/memalloc.h" #include "tier0/memalloc.h"
#include "convar.h"
class ConVarSnapshot_t; class ConCommandBase;
class ConCommand;
class ConVar;
class Color;
class IConVarListener;
class CConVarDetail;
struct ConVarSnapshot_t;
union CVValue_t;
class KeyValues; class KeyValues;
class ConVarRefAbstract;
//-----------------------------------------------------------------------------
// ConVars/ComCommands are marked as having a particular DLL identifier
//-----------------------------------------------------------------------------
typedef int CVarDLLIdentifier_t;
//-----------------------------------------------------------------------------
// Used to display console messages
//-----------------------------------------------------------------------------
abstract_class IConsoleDisplayFunc
{
public:
virtual void ColorPrint( const Color& clr, const char *pMessage ) = 0;
virtual void Print( const char *pMessage ) = 0;
virtual void DPrint( const char *pMessage ) = 0;
virtual void GetConsoleText( char *pchText, size_t bufSize ) const = 0;
};
//-----------------------------------------------------------------------------
// Purpose: Applications can implement this to modify behavior in ICvar
//-----------------------------------------------------------------------------
#define CVAR_QUERY_INTERFACE_VERSION "VCvarQuery001"
abstract_class ICvarQuery : public IAppSystem
{
public:
// Can these two convars be aliased?
virtual bool AreConVarsLinkable( const ConVar *child, const ConVar *parent ) = 0;
};
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: DLL interface to ConVars/ConCommands // Purpose: DLL interface to ConVars/ConCommands
@ -55,54 +33,53 @@ public:
abstract_class ICvar : public IAppSystem abstract_class ICvar : public IAppSystem
{ {
public: public:
// allow_developer - Allows finding convars with FCVAR_DEVELOPMENTONLY flag // bAllowDeveloper - Allows finding convars with FCVAR_DEVELOPMENTONLY flag
virtual ConVarHandle FindConVar(const char *szName, bool bAllowDeveloper = false) = 0; virtual ConVarHandle FindConVar( const char *name, bool bAllowDeveloper = false ) = 0;
virtual ConVarHandle FindFirstConVar() = 0; virtual ConVarHandle FindFirstConVar() = 0;
virtual ConVarHandle FindNextConVar(ConVarHandle previous) = 0; virtual ConVarHandle FindNextConVar( ConVarHandle prev ) = 0;
virtual void SetConVarValue( ConVarHandle cvarid, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue ) = 0;
virtual void SetConVarValue(ConVarHandle cvarid, CSplitScreenSlot nSlot, CVValue_t *pNewValue, CVValue_t *pOldValue) = 0; virtual ConCommandHandle FindCommand( const char *name ) = 0;
virtual ConCommandHandle FindCommand(const char *szName) = 0;
virtual ConCommandHandle FindFirstCommand() = 0; virtual ConCommandHandle FindFirstCommand() = 0;
virtual ConCommandHandle FindNextCommand(ConCommandHandle previous) = 0; virtual ConCommandHandle FindNextCommand( ConCommandHandle prev ) = 0;
virtual void DispatchConCommand( ConCommandHandle cmd, const CCommandContext &ctx, const CCommand &args ) = 0;
virtual void DispatchConCommand(ConCommandHandle commandid, CCommandContext& ctx, CCommand& tok) = 0;
// Install a global change callback (to be called when any convar changes) // Install a global change callback (to be called when any convar changes)
virtual void InstallGlobalChangeCallback(FnChangeCallbackGlobal_t callback) = 0; virtual void InstallGlobalChangeCallback( FnChangeCallback_t callback ) = 0;
virtual void RemoveGlobalChangeCallback(FnChangeCallbackGlobal_t callback) = 0; virtual void RemoveGlobalChangeCallback( FnChangeCallback_t callback ) = 0;
virtual void CallGlobalChangeCallbacks(ConVarRefAbstract *cvar, CSplitScreenSlot nSlot, const char *pNewValue, const char* pOldValue) = 0; virtual void CallGlobalChangeCallbacks( ConVarRef *var, CSplitScreenSlot nSlot, const char *pOldString, float flOldValue ) = 0;
// Reverts to default cvars which contain a specific flag // Reverts cvars which contain a specific flag
virtual void RevertFlaggedConVars(int nFlag) = 0; virtual void RevertFlaggedConVars( int nFlag ) = 0;
virtual void SetMaxSplitScreenSlots(int nSlots) = 0; virtual void SetMaxSplitScreenSlots( int nSlots ) = 0;
virtual int GetMaxSplitScreenSlots() const = 0; virtual int GetMaxSplitScreenSlots() const = 0;
virtual void RegisterCreationListeners(ICreationListenerCallbacks *callbacks) = 0; virtual void RegisterCreationListeners( ICVarListenerCallbacks *callbacks ) = 0;
virtual void RemoveCreationListeners(ICreationListenerCallbacks *callbacks) = 0; virtual void RemoveCreationListeners( ICVarListenerCallbacks *callbacks ) = 0;
virtual void unk1() = 0; virtual void unk1() = 0;
virtual void ResetConVarsToDefaultValues(const char *pszSearchString) = 0; virtual void ResetConVarsToDefaultValues( const char *pszPrefix ) = 0;
virtual ConVarSnapshot_t *TakeConVarSnapshot() = 0; virtual ConVarSnapshot_t *TakeConVarSnapshot( void ) = 0;
virtual void ResetConVarsFromSnapshot(ConVarSnapshot_t *snapshot) = 0; virtual void ResetConVarsToSnapshot( ConVarSnapshot_t *pSnapshot ) = 0;
virtual void DestroyConVarSnapshot(ConVarSnapshot_t *snapshot) = 0; virtual void DestroyConVarSnapshot( ConVarSnapshot_t *pSnaoshot ) = 0;
virtual characterset_t GetCharacterSet() = 0; virtual characterset_t GetCharacterSet( void ) = 0;
virtual void SetConVarsFromGameInfo( KeyValues *pKV ) = 0;
virtual void SetConVarsFromGameInfo(KeyValues *) = 0; // Register, unregister vars
virtual void RegisterConVar( ConVar *pConVar, int64 nAdditionalFlags, ConVarHandle &pCvarRef, ConVar &pCvar ) = 0;
virtual void UnregisterConVar( ConVarHandle handle ) = 0;
virtual ConVar* GetConVar( ConVarHandle handle ) = 0;
virtual void RegisterConVar(ConVarDesc_t *pDesc, int64 nAdditionalFlags, ConVarHandle &pCvarRef, ConVar &pCvar) = 0; // Register, unregister commands
virtual void UnregisterConVar(ConVarHandle handle) = 0; virtual ConCommandHandle RegisterConCommand( ConCommand *pCmd, int64 nAdditionalFlags = 0 ) = 0;
virtual ConVar* GetConVar(ConVarHandle handle) = 0; virtual void UnregisterConCommand( ConCommandHandle handle ) = 0;
virtual ConCommand* GetCommand( ConCommandHandle handle ) = 0;
virtual ConCommandHandle RegisterConCommand(ConCommandDesc_t *pDesc, int64 nAdditionalFlags = FCVAR_NONE) = 0; virtual void QueueThreadSetValue( ConVarRefAbstract *ref, CSplitScreenSlot nSlot, CVValue_t *value ) = 0;
virtual void UnregisterConCommand(ConCommandHandle handle) = 0;
virtual ConCommand* GetConCommand(ConCommandHandle handle) = 0;
virtual void QueueThreadSetValue(ConVarRefAbstract *ref, CSplitScreenSlot nSlot, CVValue_t *value) = 0;
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@
#pragma once #pragma once
#endif #endif
#ifdef CONVAR_WORK_FINISHED
// This class is used to virtualize a ConVar's value, so the client can restrict its // This class is used to virtualize a ConVar's value, so the client can restrict its
// value while connected to a server. When using this across modules, it's important // value while connected to a server. When using this across modules, it's important
// to dynamic_cast it to a ConVar_ServerBounded or you won't get the restricted value. // to dynamic_cast it to a ConVar_ServerBounded or you won't get the restricted value.
@ -48,6 +48,7 @@ public:
return ConVar::GetFloat(); return ConVar::GetFloat();
} }
}; };
#endif // CONVAR_WORK_FINISHED
#endif // CONVAR_SERVERBOUNDED_H #endif // CONVAR_SERVERBOUNDED_H

View File

@ -99,6 +99,9 @@ inline char *strlwr( char *start )
#define V_strlower(start) _V_strlower ((start)) #define V_strlower(start) _V_strlower ((start))
#define V_wcslen(pwch) _V_wcslen ((pwch)) #define V_wcslen(pwch) _V_wcslen ((pwch))
// AM TODO: handle this for the rest (above and more) now exported by tier0
PLATFORM_INTERFACE int V_stricmp_fast(const char* s1, const char* s2);
#else #else
inline void V_memset (void *dest, int fill, int count) { memset( dest, fill, count ); } inline void V_memset (void *dest, int fill, int count) { memset( dest, fill, count ); }

View File

@ -14,6 +14,7 @@
#include "tier1/convar.h" #include "tier1/convar.h"
#include "tier1/strtools.h" #include "tier1/strtools.h"
#include "tier1/characterset.h" #include "tier1/characterset.h"
#include "tier1/utlvector.h"
#include "tier1/utlbuffer.h" #include "tier1/utlbuffer.h"
#include "tier1/tier1.h" #include "tier1/tier1.h"
#include "tier1/convar_serverbounded.h" #include "tier1/convar_serverbounded.h"
@ -30,56 +31,160 @@
//#define ALLOW_DEVELOPMENT_CVARS //#define ALLOW_DEVELOPMENT_CVARS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Statically constructed list of ConCommandBases, // Statically constructed list of ConCommandBases,
// used for registering them with the ICVar interface // used for registering them with the ICVar interface
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
ConCommandBase *ConCommandBase::s_pConCommandBases = NULL; class ConCommandRegList;
IConCommandBaseAccessor *ConCommandBase::s_pAccessor = NULL;
static int64 s_nCVarFlag = 0; static int64 s_nCVarFlag = 0;
static int s_nDLLIdentifier = -1; // A unique identifier indicating which DLL this convar came from
static bool s_bRegistered = false; static bool s_bRegistered = false;
static ConCommandRegList* s_pCmdRegList = nullptr;
class CDefaultAccessor : public IConCommandBaseAccessor class ConCommandRegList
{ {
public: public:
virtual bool RegisterConCommandBase( ConCommandBase *pVar ) ConCommandRegList()
{ {
// Link to engine's list instead
g_pCVar->RegisterConCommand( pVar );
return true;
} }
static void RegisterCommand( ConCommand *pCmd )
{
if ( s_bConCommandsRegisterd )
{
g_pCVar->RegisterConCommand( pCmd, s_nCVarFlag );
if ( !pCmd->GetRef()->handle.IsValid() )
{
Plat_FatalErrorFunc( "RegisterConCommand: Unknown error registering con command \"%s\"!\n", pCmd->GetName() );
DebuggerBreakIfDebugging();
}
}
else
{
ConCommandRegList* pList = s_pCmdRegList;
if ( !pList || pList->m_Vec.Count() == 100 )
{
pList = new ConCommandRegList;
pList->m_pNext = s_pCmdRegList;
s_pCmdRegList = pList;
}
pList->m_Vec.AddToTail(*pCmd);
}
}
static void RegisterAll()
{
if (!s_bConCommandsRegisterd && g_pCVar)
{
s_bConCommandsRegisterd = true;
ConCommandRegList* pList = s_pCmdRegList;
while ( pList != nullptr )
{
FOR_EACH_VEC( s_pCmdRegList->m_Vec, i )
{
ConCommand* pCmd = &pList->m_Vec[i];
ConCommandHandle hndl = g_pCVar->RegisterConCommand( pCmd, s_nCVarFlag );
pCmd->SetHandle( hndl );
if ( !hndl.IsValid() )
{
Plat_FatalErrorFunc( "RegisterConCommand: Unknown error registering con command \"%s\"!\n", pCmd->GetName() );
DebuggerBreakIfDebugging();
}
}
ConCommandRegList* pNext = pList->m_pNext;
delete pList;
pList = pNext;
}
s_pCmdRegList = nullptr;
}
}
private:
CUtlVectorFixed<ConCommand, 100> m_Vec;
ConCommandRegList* m_pNext = nullptr;
static bool s_bConCommandsRegisterd;
}; };
static CDefaultAccessor s_DefaultAccessor; #ifdef CONVAR_WORK_FINISHED
template <typename ToCheck, std::size_t ExpectedSize, std::size_t RealSize = sizeof(ToCheck)>
void check_size() {
static_assert(ExpectedSize == RealSize, "Size mismatch");
};
class ConVarRegList
{
public:
ConVarRegList()
{
check_size<ConVar, 0x60>();
check_size<ConVarRegList, 11216>();
}
static bool AreConVarsRegistered()
{
return s_bConVarsRegisterd;
}
static void RegisterAll()
{
if (!s_bConVarsRegisterd && g_pCVar)
{
s_bConVarsRegisterd = true;
ConVarRegList* pList = s_pConVarRegList;
while (pList != nullptr)
{
FOR_EACH_VEC(s_pConVarRegList->m_Vec, i)
{
ConVar* pConVar = &pList->m_Vec[i];
ConVarHandle hndl;
//g_pCVar->RegisterConVar(pConVar, s_nCVarFlag, hndl);
//pConVar->SetHandle(hndl);
if (!hndl.IsValid())
{
Plat_FatalErrorFunc("RegisterConCommand: Unknown error registering convar \"%s\"!\n", pConVar->GetName());
DebuggerBreakIfDebugging();
}
}
ConVarRegList *pNext = pList->m_pNext;
delete pList;
pList = pNext;
}
s_pConVarRegList = nullptr;
}
}
private:
CUtlVectorFixed<ConVar, 100> m_Vec;
ConVarRegList* m_pNext = nullptr;
static bool s_bConVarsRegisterd;
};
static ConVarRegList* s_pConVarRegList = nullptr;
#endif // CONVAR_WORK_FINISHED
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Called by the framework to register ConCommandBases with the ICVar // Called by the framework to register ConCommandBases with the ICVar
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ConVar_Register( int64 nCVarFlag, IConCommandBaseAccessor *pAccessor ) void ConVar_Register( int64 nCVarFlag)
{ {
if ( !g_pCVar || s_bRegistered ) if ( !g_pCVar || s_bRegistered )
return; return;
Assert( s_nDLLIdentifier < 0 );
s_bRegistered = true; s_bRegistered = true;
s_nCVarFlag = nCVarFlag; s_nCVarFlag = nCVarFlag;
s_nDLLIdentifier = g_pCVar->AllocateDLLIdentifier();
ConCommandBase *pCur, *pNext; ConCommandRegList::RegisterAll();
#ifdef CONVAR_WORK_FINISHED
ConCommandBase::s_pAccessor = pAccessor ? pAccessor : &s_DefaultAccessor; ConVarRegList::RegisterAll();
pCur = ConCommandBase::s_pConCommandBases; #endif // CONVAR_WORK_FINISHED
while ( pCur )
{
pNext = pCur->m_pNext;
pCur->AddFlags( s_nCVarFlag );
pCur->Init();
pCur = pNext;
}
ConCommandBase::s_pConCommandBases = NULL;
} }
void ConVar_Unregister( ) void ConVar_Unregister( )
@ -87,9 +192,6 @@ void ConVar_Unregister( )
if ( !g_pCVar || !s_bRegistered ) if ( !g_pCVar || !s_bRegistered )
return; return;
Assert( s_nDLLIdentifier >= 0 );
g_pCVar->UnregisterConCommands( s_nDLLIdentifier );
s_nDLLIdentifier = -1;
s_bRegistered = false; s_bRegistered = false;
} }
@ -99,23 +201,10 @@ void ConVar_Unregister( )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
ConCommandBase::ConCommandBase( void ) ConCommandBase::ConCommandBase( void )
{ {
m_bRegistered = false;
m_pszName = NULL; m_pszName = NULL;
m_pszHelpString = NULL; m_pszHelpString = NULL;
m_nFlags = 0; m_nFlags = 0;
m_pNext = NULL;
}
//-----------------------------------------------------------------------------
// Purpose: The base console invoked command/cvar interface
// Input : *pName - name of variable/command
// *pHelpString - help text
// flags - flags
//-----------------------------------------------------------------------------
ConCommandBase::ConCommandBase( const char *pName, const char *pHelpString /*=0*/, int64 flags /*= 0*/ )
{
Create( pName, pHelpString, flags );
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -125,90 +214,6 @@ ConCommandBase::~ConCommandBase( void )
{ {
} }
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool ConCommandBase::IsCommand( void ) const
{
// Assert( 0 ); This can't assert. . causes a recursive assert in Sys_Printf, etc.
return true;
}
//-----------------------------------------------------------------------------
// Returns the DLL identifier
//-----------------------------------------------------------------------------
CVarDLLIdentifier_t ConCommandBase::GetDLLIdentifier() const
{
return s_nDLLIdentifier;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pName -
// callback -
// *pHelpString -
// flags -
//-----------------------------------------------------------------------------
void ConCommandBase::Create( const char *pName, const char *pHelpString /*= 0*/, int64 flags /*= 0*/ )
{
static const char *empty_string = "";
m_bRegistered = false;
// Name should be static data
Assert( pName );
m_pszName = pName;
m_pszHelpString = pHelpString ? pHelpString : empty_string;
m_nFlags = flags;
#ifdef ALLOW_DEVELOPMENT_CVARS
m_nFlags &= ~FCVAR_DEVELOPMENTONLY;
#endif
if ( !( m_nFlags & FCVAR_UNREGISTERED ) )
{
m_pNext = s_pConCommandBases;
s_pConCommandBases = this;
}
else
{
// It's unregistered
m_pNext = NULL;
}
// If s_pAccessor is already set (this ConVar is not a global variable),
// register it.
if ( s_pAccessor )
{
Init();
}
}
//-----------------------------------------------------------------------------
// Purpose: Used internally by OneTimeInit to initialize.
//-----------------------------------------------------------------------------
void ConCommandBase::Init()
{
if ( s_pAccessor )
{
s_pAccessor->RegisterConCommandBase( this );
}
}
void ConCommandBase::Shutdown()
{
if ( g_pCVar )
{
g_pCVar->UnregisterConCommand( this );
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Return name of the command/var // Purpose: Return name of the command/var
// Output : const char // Output : const char
@ -252,46 +257,6 @@ int64 ConCommandBase::GetFlags( void ) const
return m_nFlags; return m_nFlags;
} }
//-----------------------------------------------------------------------------
// Purpose:
// Output : const ConCommandBase
//-----------------------------------------------------------------------------
const ConCommandBase *ConCommandBase::GetNext( void ) const
{
return m_pNext;
}
ConCommandBase *ConCommandBase::GetNext( void )
{
return m_pNext;
}
//-----------------------------------------------------------------------------
// Purpose: Copies string using local new/delete operators
// Input : *from -
// Output : char
//-----------------------------------------------------------------------------
char *ConCommandBase::CopyString( const char *from )
{
int len;
char *to;
len = strlen( from );
if ( len <= 0 )
{
to = new char[1];
to[0] = 0;
}
else
{
to = new char[len+1];
Q_strncpy( to, from, len+1 );
}
return to;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: // Purpose:
// Output : const char // Output : const char
@ -301,20 +266,6 @@ const char *ConCommandBase::GetHelpText( void ) const
return m_pszHelpString; return m_pszHelpString;
} }
//-----------------------------------------------------------------------------
// Purpose: Has this cvar been registered
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool ConCommandBase::IsRegistered( void ) const
{
return m_bRegistered;
}
bool ConCommandBase::IsBoundedVar(void) const
{
return false;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// Con Commands start here // Con Commands start here
@ -355,13 +306,12 @@ CCommand::CCommand( int nArgC, const char **ppArgV )
Reset(); Reset();
char *pBuf = m_pArgvBuffer; char *pBuf = m_ArgvBuffer.Base();
char *pSBuf = m_pArgSBuffer; char *pSBuf = m_ArgSBuffer.Base();
m_nArgc = nArgC;
for ( int i = 0; i < nArgC; ++i ) for ( int i = 0; i < nArgC; ++i )
{ {
m_ppArgv[i] = pBuf; m_Args.AddToTail( pBuf );
int nLen = Q_strlen( ppArgV[i] ); int nLen = V_strlen( ppArgV[i] );
memcpy( pBuf, ppArgV[i], nLen+1 ); memcpy( pBuf, ppArgV[i], nLen+1 );
if ( i == 0 ) if ( i == 0 )
{ {
@ -390,9 +340,10 @@ CCommand::CCommand( int nArgC, const char **ppArgV )
void CCommand::Reset() void CCommand::Reset()
{ {
m_nArgc = 0;
m_nArgv0Size = 0; m_nArgv0Size = 0;
m_pArgSBuffer[0] = 0; m_ArgSBuffer.RemoveAll();
m_ArgvBuffer.RemoveAll();
m_Args.RemoveAll();
} }
characterset_t* CCommand::DefaultBreakSet() characterset_t* CCommand::DefaultBreakSet()
@ -415,21 +366,21 @@ bool CCommand::Tokenize( const char *pCommand, characterset_t *pBreakSet )
// Copy the current command into a temp buffer // Copy the current command into a temp buffer
// NOTE: This is here to avoid the pointers returned by DequeueNextCommand // NOTE: This is here to avoid the pointers returned by DequeueNextCommand
// to become invalid by calling AddText. Is there a way we can avoid the memcpy? // to become invalid by calling AddText. Is there a way we can avoid the memcpy?
int nLen = Q_strlen( pCommand ); int nLen = V_strlen( pCommand );
if ( nLen >= COMMAND_MAX_LENGTH - 1 ) if ( nLen >= COMMAND_MAX_LENGTH - 1 )
{ {
Warning( "CCommand::Tokenize: Encountered command which overflows the tokenizer buffer.. Skipping!\n" ); Warning( "CCommand::Tokenize: Encountered command which overflows the tokenizer buffer.. Skipping!\n" );
return false; return false;
} }
memcpy( m_pArgSBuffer, pCommand, nLen + 1 ); memcpy( m_ArgSBuffer.Base(), pCommand, nLen + 1 );
// Parse the current command into the current command buffer // Parse the current command into the current command buffer
CUtlBuffer bufParse( m_pArgSBuffer, nLen, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY ); CUtlBuffer bufParse( m_ArgSBuffer.Base(), nLen, CUtlBuffer::TEXT_BUFFER | CUtlBuffer::READ_ONLY);
int nArgvBufferSize = 0; int nArgvBufferSize = 0;
while ( bufParse.IsValid() && ( m_nArgc < COMMAND_MAX_ARGC ) ) while ( bufParse.IsValid() && ( m_Args.Count() < COMMAND_MAX_ARGC ) )
{ {
char *pArgvBuf = &m_pArgvBuffer[nArgvBufferSize]; char *pArgvBuf = &m_ArgvBuffer[nArgvBufferSize];
int nMaxLen = COMMAND_MAX_LENGTH - nArgvBufferSize; int nMaxLen = COMMAND_MAX_LENGTH - nArgvBufferSize;
int nStartGet = bufParse.TellGet(); int nStartGet = bufParse.TellGet();
int nSize = bufParse.ParseToken( pBreakSet, pArgvBuf, nMaxLen ); int nSize = bufParse.ParseToken( pBreakSet, pArgvBuf, nMaxLen );
@ -443,11 +394,11 @@ bool CCommand::Tokenize( const char *pCommand, characterset_t *pBreakSet )
return false; return false;
} }
if ( m_nArgc == 1 ) if ( m_Args.Count() == 1 )
{ {
// Deal with the case where the arguments were quoted // Deal with the case where the arguments were quoted
m_nArgv0Size = bufParse.TellGet(); m_nArgv0Size = bufParse.TellGet();
bool bFoundEndQuote = m_pArgSBuffer[m_nArgv0Size-1] == '\"'; bool bFoundEndQuote = m_ArgSBuffer[m_nArgv0Size-1] == '\"';
if ( bFoundEndQuote ) if ( bFoundEndQuote )
{ {
--m_nArgv0Size; --m_nArgv0Size;
@ -457,7 +408,7 @@ bool CCommand::Tokenize( const char *pCommand, characterset_t *pBreakSet )
// The StartGet check is to handle this case: "foo"bar // The StartGet check is to handle this case: "foo"bar
// which will parse into 2 different args. ArgS should point to bar. // which will parse into 2 different args. ArgS should point to bar.
bool bFoundStartQuote = ( m_nArgv0Size > nStartGet ) && ( m_pArgSBuffer[m_nArgv0Size-1] == '\"' ); bool bFoundStartQuote = ( m_nArgv0Size > nStartGet ) && ( m_ArgSBuffer[m_nArgv0Size-1] == '\"' );
Assert( bFoundEndQuote == bFoundStartQuote ); Assert( bFoundEndQuote == bFoundStartQuote );
if ( bFoundStartQuote ) if ( bFoundStartQuote )
{ {
@ -465,8 +416,8 @@ bool CCommand::Tokenize( const char *pCommand, characterset_t *pBreakSet )
} }
} }
m_ppArgv[ m_nArgc++ ] = pArgvBuf; m_Args.AddToTail( pArgvBuf );
if( m_nArgc >= COMMAND_MAX_ARGC ) if( m_Args.Count() >= COMMAND_MAX_ARGC )
{ {
Warning( "CCommand::Tokenize: Encountered command which overflows the argument buffer.. Clamped!\n" ); Warning( "CCommand::Tokenize: Encountered command which overflows the argument buffer.. Clamped!\n" );
} }
@ -482,22 +433,22 @@ bool CCommand::Tokenize( const char *pCommand, characterset_t *pBreakSet )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Helper function to parse arguments to commands. // Helper function to parse arguments to commands.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
const char* CCommand::FindArg( const char *pName ) const int CCommand::FindArg( const char *pName ) const
{ {
int nArgC = ArgC(); int nArgC = ArgC();
for ( int i = 1; i < nArgC; i++ ) for ( int i = 1; i < nArgC; i++ )
{ {
if ( !Q_stricmp( Arg(i), pName ) ) if ( !V_stricmp_fast( Arg(i), pName ) )
return (i+1) < nArgC ? Arg( i+1 ) : ""; return (i+1) < nArgC ? i+1 : -1;
} }
return 0; return -1;
} }
int CCommand::FindArgInt( const char *pName, int nDefaultVal ) const int CCommand::FindArgInt( const char *pName, int nDefaultVal ) const
{ {
const char *pVal = FindArg( pName ); int idx = FindArg( pName );
if ( pVal ) if ( idx != -1 )
return atoi( pVal ); return V_atoi( m_Args[idx] );
else else
return nDefaultVal; return nDefaultVal;
} }
@ -512,100 +463,76 @@ int DefaultCompletionFunc( const char *partial, CUtlVector< CUtlString > &comman
} }
ConCommand::ConCommand( const char *pName, FnCommandCallback_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ ) ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallback_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ )
{ {
// Add the callback m_Callback.m_fnCommandCallback = callback;
if (callback) m_Callback.m_bUsingCommandCallbackInterface = false;
{ m_Callback.m_bHasVoidCommandCallback = false;
ConCommandCB cb; m_Callback.m_bHasContextlessCommandCallback = false;
cb.m_fnCommandCallback = callback;
cb.m_bUsingOldCommandCallback = true;
cb.m_bUsingV1CommandCallback = false;
cb.m_bUsingV2CommandCallback = false;
cb.m_bUsingCommandCallbackInterface = false;
m_Callbacks.AddToTail(cb);
}
m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc;
m_bHasCompletionCallback = completionFunc != 0 ? true : false; m_bHasCompletionCallback = completionFunc != 0 ? true : false;
m_bUsingCommandCompletionInterface = false; m_bUsingCommandCompletionInterface = false;
m_pParent = this; m_pReference = pReferenceOut;
m_pReference->handle.Reset();
// Setup the rest // Setup the rest
BaseClass::Create( pName, pHelpString, flags ); Create( pName, pHelpString, flags );
} }
ConCommand::ConCommand(const char *pName, FnCommandCallbackV1_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/) ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallbackVoid_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ )
{ {
// Add the callback m_Callback.m_fnVoidCommandCallback = callback;
if (callback) m_Callback.m_bUsingCommandCallbackInterface = false;
{ m_Callback.m_bHasVoidCommandCallback = true;
ConCommandCB cb; m_Callback.m_bHasContextlessCommandCallback = false;
cb.m_fnCommandCallbackV1 = callback;
cb.m_bUsingOldCommandCallback = false;
cb.m_bUsingV1CommandCallback = true;
cb.m_bUsingV2CommandCallback = false;
cb.m_bUsingCommandCallbackInterface = false;
m_Callbacks.AddToTail(cb);
}
m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc;
m_bHasCompletionCallback = completionFunc != 0 ? true : false; m_bHasCompletionCallback = completionFunc != 0 ? true : false;
m_bUsingCommandCompletionInterface = false; m_bUsingCommandCompletionInterface = false;
m_pParent = this; m_pReference = pReferenceOut;
m_pReference->handle.Reset();
// Setup the rest // Setup the rest
BaseClass::Create(pName, pHelpString, flags); Create( pName, pHelpString, flags );
} }
ConCommand::ConCommand(const char *pName, FnCommandCallbackV2_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/) ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, FnCommandCallbackNoContext_t callback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ )
{ {
// Add the callback m_Callback.m_fnContextlessCommandCallback = callback;
if (callback) m_Callback.m_bUsingCommandCallbackInterface = false;
{ m_Callback.m_bHasVoidCommandCallback = false;
ConCommandCB cb; m_Callback.m_bHasContextlessCommandCallback = true;
cb.m_fnCommandCallbackV2 = callback;
cb.m_bUsingOldCommandCallback = false;
cb.m_bUsingV1CommandCallback = false;
cb.m_bUsingV2CommandCallback = true;
cb.m_bUsingCommandCallbackInterface = false;
m_Callbacks.AddToTail(cb);
}
m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc; m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc;
m_bHasCompletionCallback = completionFunc != 0 ? true : false; m_bHasCompletionCallback = completionFunc != 0 ? true : false;
m_bUsingCommandCompletionInterface = false; m_bUsingCommandCompletionInterface = false;
m_pParent = this; m_pReference = pReferenceOut;
m_pReference->handle.Reset();
// Setup the rest // Setup the rest
BaseClass::Create(pName, pHelpString, flags); Create(pName, pHelpString, flags);
} }
ConCommand::ConCommand( const char *pName, ICommandCallback *pCallback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, ICommandCompletionCallback *pCompletionCallback /*= 0*/ ) ConCommand::ConCommand( ConCommandRefAbstract *pReferenceOut, const char *pName, ICommandCallback *pCallback, const char *pHelpString /*= 0*/, int64 flags /*= 0*/, ICommandCompletionCallback *pCompletionCallback /*= 0*/ )
{ {
// Add the callback iface m_Callback.m_pCommandCallback = pCallback;
if (pCallback) m_Callback.m_bUsingCommandCallbackInterface = true;
{ m_Callback.m_bHasVoidCommandCallback = false;
ConCommandCB cb; m_Callback.m_bHasContextlessCommandCallback = false;
cb.m_pCommandCallback = pCallback;
cb.m_bUsingOldCommandCallback = false;
cb.m_bUsingV1CommandCallback = false;
cb.m_bUsingV2CommandCallback = false;
cb.m_bUsingCommandCallbackInterface = true;
m_Callbacks.AddToTail(cb);
}
m_pCommandCompletionCallback = pCompletionCallback; m_pCommandCompletionCallback = pCompletionCallback;
m_bHasCompletionCallback = ( pCompletionCallback != 0 ); m_bHasCompletionCallback = true;
m_bUsingCommandCompletionInterface = true; m_bUsingCommandCompletionInterface = true;
m_pParent = this; m_pReference = pReferenceOut;
m_pReference->handle.Reset();
// Setup the rest // Setup the rest
BaseClass::Create( pName, pHelpString, flags ); Create( pName, pHelpString, flags );
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -613,54 +540,99 @@ ConCommand::ConCommand( const char *pName, ICommandCallback *pCallback, const ch
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
ConCommand::~ConCommand( void ) ConCommand::~ConCommand( void )
{ {
ConCommandRefAbstract *pRef = GetRef();
if ( pRef )
{
pRef->handle.Unregister();
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Returns true if this is a command // Purpose: Used internally by OneTimeInit to initialize.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool ConCommand::IsCommand( void ) const void ConCommand::Init()
{ {
return true; ConCommandRegList::RegisterCommand( this );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pName -
// callback -
// *pHelpString -
// flags -
//-----------------------------------------------------------------------------
void ConCommand::Create( const char* pName, const char* pHelpString /*= 0*/, int64 flags /*= 0*/ )
{
static const char* empty_string = "";
// Name should be static data
Assert(pName);
m_pszName = pName;
m_pszHelpString = pHelpString ? pHelpString : empty_string;
m_nFlags = flags;
#ifdef ALLOW_DEVELOPMENT_CVARS
m_nFlags &= ~FCVAR_DEVELOPMENTONLY;
#endif
Init();
}
void ConCommand::Shutdown()
{
GetRef()->handle.Unregister();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Invoke the function if there is one // Purpose: Invoke the function if there is one
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ConCommand::Dispatch( const CCommandContext &context, const CCommand &command ) void ConCommandHandle::Dispatch( const CCommandContext &context, const CCommand &command )
{ {
FOR_EACH_VEC(m_Callbacks, i) ConCommand *pCommand = g_pCVar->GetCommand( *this );
if ( pCommand->m_Callback.m_fnCommandCallback )
{ {
ConCommandCB cb = m_Callbacks[i]; if ( pCommand->m_Callback.m_bUsingCommandCallbackInterface )
if (cb.m_fnCallbackAny)
{ {
if (cb.m_bUsingOldCommandCallback) pCommand->m_Callback.m_pCommandCallback->CommandCallback( context, command );
{
(*cb.m_fnCommandCallback)(command);
return;
} }
else if (cb.m_bUsingCommandCallbackInterface) else if ( pCommand->m_Callback.m_bHasVoidCommandCallback )
{ {
cb.m_pCommandCallback->CommandCallback(context, command); pCommand->m_Callback.m_fnVoidCommandCallback();
return;
} }
else if (cb.m_bUsingV1CommandCallback) else if ( pCommand->m_Callback.m_bHasContextlessCommandCallback )
{ {
(*cb.m_fnCommandCallbackV1)(context); pCommand->m_Callback.m_fnContextlessCommandCallback( command );
return;
} }
else if (cb.m_bUsingV2CommandCallback) else
{ {
cb.m_fnCommandCallbackV2(context, command); pCommand->m_Callback.m_fnCommandCallback( context, command );
} }
} }
// Command without callback!!! // Command without callback!!!
AssertMsg(0, ("Encountered ConCommand without a callback!\n")); AssertMsg(0, ("Encountered ConCommand without a callback!\n"));
}
} }
bool ConCommandHandle::HasCallback() const
{
ConCommand *pCommand = g_pCVar->GetCommand( *this );
return pCommand->m_Callback.m_fnCommandCallback != nullptr;
}
void ConCommandHandle::Unregister()
{
if (IsValid())
{
if ( g_pCVar )
g_pCVar->UnregisterConCommand( *this );
Reset();
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Calls the autocompletion method to get autocompletion suggestions // Purpose: Calls the autocompletion method to get autocompletion suggestions
@ -691,7 +663,7 @@ bool ConCommand::CanAutoComplete( void )
} }
#ifdef CONVAR_WORK_FINISHED
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// Console Variables // Console Variables
@ -788,24 +760,11 @@ int64 ConVar::GetFlags( void ) const
return m_pParent->m_nFlags; return m_pParent->m_nFlags;
} }
bool ConVar::IsRegistered( void ) const
{
return m_pParent->m_bRegistered;
}
const char *ConVar::GetName( void ) const const char *ConVar::GetName( void ) const
{ {
return m_pParent->m_pszName; return m_pParent->m_pszName;
} }
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool ConVar::IsCommand( void ) const
{
return false;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: // Purpose:
@ -992,21 +951,6 @@ void ConVar::InternalSetColorValue( Color cValue )
InternalSetIntValue( color ); InternalSetIntValue( color );
} }
bool ConVar::GetBoolVirtualized() const
{
return m_Value.m_nValue != 0;
}
int ConVar::GetIntVirtualized() const
{
return m_Value.m_nValue;
}
float ConVar::GetFloatVirtualized() const
{
return m_Value.m_fValue;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Private creation // Purpose: Private creation
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1358,3 +1302,4 @@ void ConVar_PrintDescription( const ConCommandBase *pVar )
ConMsg( " - %s\n", pStr ); ConMsg( " - %s\n", pStr );
} }
} }
#endif // CONVAR_WORK_FINISHED