Implement convar_list and convar_differences

Also added more CCvarUtilities methods which are yet to be implemented.
This commit is contained in:
Kawe Mazidjatari 2022-08-13 12:39:57 +02:00
parent aa72579656
commit 4551f6d494
12 changed files with 897 additions and 13 deletions

View File

@ -176,6 +176,68 @@ void HexDump(const char* szHeader, const char* szLogger, const void* pData, int
///////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////
// For stripping tabs and return characters from input buffer.
char* StripTabsAndReturns(const char* pInBuffer, char* pOutBuffer, int nOutBufferSize)
{
char* out = pOutBuffer;
const char* i = pInBuffer;
char* o = out;
out[0] = 0;
while (*i && o - out < nOutBufferSize - 1)
{
if (*i == '\n' ||
*i == '\r' ||
*i == '\t')
{
*o++ = ' ';
i++;
continue;
}
if (*i == '\"')
{
*o++ = '\'';
i++;
continue;
}
*o++ = *i++;
}
*o = '\0';
return out;
}
///////////////////////////////////////////////////////////////////////////////
// For stripping quote characters from input buffer.
char* StripQuotes(const char* pInBuffer, char* pOutBuffer, int nOutBufferSize)
{
char* out = pOutBuffer;
const char* i = pInBuffer;
char* o = out;
out[0] = 0;
while (*i && o - out < nOutBufferSize - 1)
{
if (*i == '\"')
{
*o++ = '\'';
i++;
continue;
}
*o++ = *i++;
}
*o = '\0';
return out;
}
///////////////////////////////////////////////////////////////////////////////
// For checking if file name has a specific extension.
bool HasExtension(const string& svInput, const string& svExtension)
@ -728,6 +790,20 @@ void PrintM128i64(__m128i in)
printf("v2_u64: %llx %llx\n", v[0], v[1]);
}
///////////////////////////////////////////////////////////////////////////////
// For appending characters to a printf buffer.
void AppendPrintf(char* pBuffer, size_t nBufSize, char const* pFormat, ...)
{
char scratch[1024];
va_list argptr;
va_start(argptr, pFormat);
_vsnprintf(scratch, sizeof(scratch) - 1, pFormat, argptr);
va_end(argptr);
scratch[sizeof(scratch) - 1] = 0;
strncat(pBuffer, scratch, nBufSize);
}
///////////////////////////////////////////////////////////////////////////////
// For escaping the '%' character for *rintf.
string PrintPercentageEscape(const string& svInput)

View File

@ -12,6 +12,11 @@ void DbgPrint(LPCSTR sFormat, ...);
void PrintLastError(void);
void HexDump(const char* szHeader, const char* szLogger, const void* pData, int nSize);
/////////////////////////////////////////////////////////////////////////////
// Char
char* StripTabsAndReturns(const char* pInBuffer, char* pOutBuffer, int nOutBufferSize);
char* StripQuotes(const char* pInBuffer, char* pOutBuffer, int nOutBufferSize);
/////////////////////////////////////////////////////////////////////////////
// String
bool HasExtension(const string& svInput, const string& svExtension);
@ -58,6 +63,7 @@ void PrintM128i16(__m128i in);
void PrintM128i32(__m128i in);
void PrintM128i64(__m128i in);
void AppendPrintf(char* pBuffer, size_t nBufSize, char const* pFormat, ...);
string PrintPercentageEscape(const string& svInput);
/////////////////////////////////////////////////////////////////////////////

View File

@ -534,7 +534,7 @@ void ConVar::SetValue(Color value)
//-----------------------------------------------------------------------------
void ConVar::InternalSetValue(const char* pszValue)
{
if (IsFlagSet(this, FCVAR_MATERIAL_THREAD_MASK))
if (IsFlagSet(FCVAR_MATERIAL_THREAD_MASK))
{
if (g_pCVar && !g_pCVar->IsMaterialThreadSetAllowed())
{
@ -593,7 +593,7 @@ void ConVar::InternalSetIntValue(int nValue)
if (nValue == m_Value.m_nValue)
return;
if (IsFlagSet(this, FCVAR_MATERIAL_THREAD_MASK))
if (IsFlagSet(FCVAR_MATERIAL_THREAD_MASK))
{
if (g_pCVar && !g_pCVar->IsMaterialThreadSetAllowed())
{
@ -631,7 +631,7 @@ void ConVar::InternalSetFloatValue(float flValue)
if (flValue == m_Value.m_fValue)
return;
if (IsFlagSet(this, FCVAR_MATERIAL_THREAD_MASK))
if (IsFlagSet(FCVAR_MATERIAL_THREAD_MASK))
{
if (g_pCVar && !g_pCVar->IsMaterialThreadSetAllowed())
{
@ -885,7 +885,7 @@ bool ConVar::IsCommand(void) const
// Input : *pConVar - nFlags
// Output : False if change is permitted, true if not.
//-----------------------------------------------------------------------------
bool ConVar::IsFlagSet(ConVar* pConVar, int nFlags)
bool ConVar::IsFlagSetInternal(ConVar* pConVar, int nFlags)
{
if (cm_debug_cmdquery->GetBool())
{
@ -924,12 +924,139 @@ bool ConVar::IsFlagSet(ConVar* pConVar, int nFlags)
///////////////////////////////////////////////////////////////////////////////
void IConVar_Attach()
{
DetourAttach((LPVOID*)&IConVar_IsFlagSet, &ConVar::IsFlagSet);
DetourAttach((LPVOID*)&IConVar_IsFlagSet, &ConVar::IsFlagSetInternal);
}
void IConVar_Detach()
{
DetourDetach((LPVOID*)&IConVar_IsFlagSet, &ConVar::IsFlagSet);
DetourDetach((LPVOID*)&IConVar_IsFlagSet, &ConVar::IsFlagSetInternal);
}
///////////////////////////////////////////////////////////////////////////////
struct PrintConVarFlags_t
{
int flag;
const char* desc;
};
static PrintConVarFlags_t g_PrintConVarFlags[] =
{
{ FCVAR_GAMEDLL, "game" },
{ FCVAR_CLIENTDLL, "client" },
{ FCVAR_ARCHIVE, "archive" },
{ FCVAR_NOTIFY, "notify" },
{ FCVAR_SPONLY, "singleplayer" },
{ FCVAR_NOT_CONNECTED, "notconnected" },
{ FCVAR_CHEAT, "cheat" },
{ FCVAR_REPLICATED, "replicated" },
{ FCVAR_SERVER_CAN_EXECUTE, "server_can_execute" },
{ FCVAR_CLIENTCMD_CAN_EXECUTE, "clientcmd_can_execute" },
{ FCVAR_USERINFO, "user" },
{ FCVAR_SS, "ss" },
{ FCVAR_SS_ADDED, "ss_added" },
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ConVar_AppendFlags(ConCommandBase* var, char* buf, size_t bufsize)
{
for (int i = 0; i < ARRAYSIZE(g_PrintConVarFlags); ++i)
{
const PrintConVarFlags_t& info = g_PrintConVarFlags[i];
if (var->IsFlagSet(info.flag))
{
char append[128];
snprintf(append, sizeof(append), " %s", info.desc);
strncat(buf, append, bufsize);
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ConVar_PrintDescription(ConCommandBase* pVar)
{
bool bMin, bMax;
float fMin, fMax;
const char* pStr;
Assert(pVar);
Color clr(255, 100, 100, 255);
char outstr[4096];
outstr[0] = 0;
if (!pVar->IsCommand())
{
ConVar* var = (ConVar*)pVar;
bMin = var->GetMin(fMin);
bMax = var->GetMax(fMax);
const char* value = NULL;
char tempVal[256];
if (var->IsFlagSet(FCVAR_NEVER_AS_STRING))
{
value = tempVal;
int intVal = var->GetInt();
float floatVal = var->GetFloat();
if (fabs((float)intVal - floatVal) < 0.000001)
{
snprintf(tempVal, sizeof(tempVal), "%d", intVal);
}
else
{
snprintf(tempVal, sizeof(tempVal), "%f", floatVal);
}
}
else
{
value = var->GetString();
}
if (value)
{
AppendPrintf(outstr, sizeof(outstr), "\"%s\" = \"%s\"", var->GetName(), value);
if (_stricmp(value, var->GetDefault()))
{
AppendPrintf(outstr, sizeof(outstr), " ( def. \"%s\" )", var->GetDefault());
}
}
if (bMin)
{
AppendPrintf(outstr, sizeof(outstr), " min. %f", fMin);
}
if (bMax)
{
AppendPrintf(outstr, sizeof(outstr), " max. %f", fMax);
}
}
else
{
ConCommand* var = (ConCommand*)pVar;
AppendPrintf(outstr, sizeof(outstr), "\"%s\" ", var->GetName());
}
ConVar_AppendFlags(pVar, outstr, sizeof(outstr));
pStr = pVar->GetHelpText();
if (pStr && *pStr)
{
DevMsg(eDLL_T::ENGINE, "%-80s - %.80s\n", outstr, pStr);
}
else
{
DevMsg(eDLL_T::ENGINE, "%-80s\n", outstr);
}
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -69,7 +69,9 @@ public:
bool IsRegistered(void) const;
bool IsCommand(void) const;
static bool IsFlagSet(ConVar* pConVar, int nFlags);
bool IsFlagSet(int nFlags) { return IsFlagSetInternal(this, nFlags); };
static bool IsFlagSetInternal(ConVar* pConVar, int nFlags);
struct CVValue_t
{
@ -108,6 +110,8 @@ inline CMemory g_pIConVarVFTable;
void IConVar_Attach();
void IConVar_Detach();
void ConVar_PrintDescription(ConCommandBase* pVar);
extern ConVar* g_pConVar;
///////////////////////////////////////////////////////////////////////////////

View File

@ -373,6 +373,10 @@ void ConCommand::Init(void)
//-----------------------------------------------------------------------------
void ConCommand::InitShipped(void)
{
//-------------------------------------------------------------------------
// ENGINE DLL |
g_pCVar->FindCommand("convar_list")->m_fnCommandCallback = CVList_f;
g_pCVar->FindCommand("convar_differences")->m_fnCommandCallback = CVDiff_f;
#ifndef DEDICATED
//-------------------------------------------------------------------------
// MATERIAL SYSTEM
@ -477,7 +481,7 @@ bool ConCommandBase::IsRegistered(void) const
// Input : *pCommandBase - nFlags
// Output : False if execution is permitted, true if not.
//-----------------------------------------------------------------------------
bool ConCommandBase::IsFlagSet(ConCommandBase* pCommandBase, int nFlags)
bool ConCommandBase::IsFlagSetInternal(ConCommandBase* pCommandBase, int nFlags)
{
if (cm_debug_cmdquery->GetBool())
{
@ -518,7 +522,7 @@ bool ConCommandBase::IsFlagSet(ConCommandBase* pCommandBase, int nFlags)
// Input : nFlags -
// Output : True if ConCommand has nFlags.
//-----------------------------------------------------------------------------
bool ConCommandBase::HasFlags(int nFlags)
bool ConCommandBase::HasFlags(int nFlags) const
{
return m_nFlags & nFlags;
}
@ -623,10 +627,10 @@ ECommandTarget_t Cbuf_GetCurrentPlayer(void)
///////////////////////////////////////////////////////////////////////////////
void ConCommand_Attach()
{
DetourAttach((LPVOID*)&ConCommandBase_IsFlagSet, &ConCommandBase::IsFlagSet);
DetourAttach((LPVOID*)&ConCommandBase_IsFlagSet, &ConCommandBase::IsFlagSetInternal);
}
void ConCommand_Detach()
{
DetourDetach((LPVOID*)&ConCommandBase_IsFlagSet, &ConCommandBase::IsFlagSet);
DetourDetach((LPVOID*)&ConCommandBase_IsFlagSet, &ConCommandBase::IsFlagSetInternal);
}
ConCommand* g_pConCommand = new ConCommand();

View File

@ -89,13 +89,15 @@ private:
class ConCommandBase
{
public:
bool HasFlags(int nFlags);
bool HasFlags(int nFlags) const;
void AddFlags(int nFlags);
void RemoveFlags(int nFlags);
bool IsCommand(void) const;
bool IsRegistered(void) const;
static bool IsFlagSet(ConCommandBase* pCommandBase, int nFlags);
bool IsFlagSet(int nFlags) { return IsFlagSetInternal(this, nFlags); };
static bool IsFlagSetInternal(ConCommandBase* pCommandBase, int nFlags);
int GetFlags(void) const;
ConCommandBase* GetNext(void) const;

View File

@ -1,7 +1,9 @@
#include "core/stdafx.h"
#include "tier1/utlrbtree.h"
#include "tier1/cvar.h"
#include "tier1/IConVar.h"
#include "engine/sys_dll2.h"
#include "filesystem/filesystem.h"
//-----------------------------------------------------------------------------
// ENGINE |
@ -166,6 +168,483 @@ ConVar* pylon_showdebug = nullptr;
ConVar* rui_drawEnable = nullptr;
#endif // !DEDICATED
struct ConVarFlags_t
{
int bit;
const char* desc;
const char* shortdesc;
};
#define CONVARFLAG( x, y ) { FCVAR_##x, #x, #y }
static ConVarFlags_t g_ConVarFlags[] =
{
// CONVARFLAG( UNREGISTERED, "u" ),
CONVARFLAG(ARCHIVE, "a"),
CONVARFLAG(SPONLY, "sp"),
CONVARFLAG(GAMEDLL, "sv"),
CONVARFLAG(CHEAT, "cheat"),
CONVARFLAG(USERINFO, "user"),
CONVARFLAG(NOTIFY, "nf"),
CONVARFLAG(PROTECTED, "prot"),
CONVARFLAG(PRINTABLEONLY, "print"),
CONVARFLAG(UNLOGGED, "log"),
CONVARFLAG(NEVER_AS_STRING, "numeric"),
CONVARFLAG(REPLICATED, "rep"),
CONVARFLAG(DEMO, "demo"),
CONVARFLAG(DONTRECORD, "norecord"),
CONVARFLAG(SERVER_CAN_EXECUTE, "server_can_execute"),
CONVARFLAG(CLIENTCMD_CAN_EXECUTE, "clientcmd_can_execute"),
CONVARFLAG(CLIENTDLL, "cl"),
};
static void PrintListHeader(FileHandle_t& f)
{
char csvflagstr[1024];
csvflagstr[0] = 0;
int c = ARRAYSIZE(g_ConVarFlags);
for (int i = 0; i < c; ++i)
{
char csvf[64];
ConVarFlags_t& entry = g_ConVarFlags[i];
snprintf(csvf, sizeof(csvf), "\"%s\",", entry.desc);
strncat(csvflagstr, csvf, sizeof(csvflagstr));
}
FileSystem()->FPrintf(f, "\"%s\",\"%s\",%s,\"%s\"\n", "Name", "Value", csvflagstr, "Help Text");
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *var -
// *f -
//-----------------------------------------------------------------------------
static void PrintCvar(ConVar* var, bool logging, FileHandle_t& fh)
{
char flagstr[128];
char csvflagstr[1024];
flagstr[0] = 0;
csvflagstr[0] = 0;
int c = ARRAYSIZE(g_ConVarFlags);
for (int i = 0; i < c; ++i)
{
char f[32];
char csvf[64];
ConVarFlags_t& entry = g_ConVarFlags[i];
if (var->IsFlagSet(entry.bit))
{
snprintf(f, sizeof(f), ", %s", entry.shortdesc);
strncat(flagstr, f, sizeof(flagstr));
snprintf(csvf, sizeof(csvf), "\"%s\",", entry.desc);
}
else
{
snprintf(csvf, sizeof(csvf), ",");
}
strncat(csvflagstr, csvf, sizeof(csvflagstr));
}
char valstr[32];
char tempbuff[512] = { 0 };
// Clean up integers
if (var->GetInt() == (int)var->GetFloat())
{
snprintf(valstr, sizeof(valstr), "%-8i", var->GetInt());
}
else
{
snprintf(valstr, sizeof(valstr), "%-8.3f", var->GetFloat());
}
// Print to console
DevMsg(eDLL_T::ENGINE, "%-40s : %-8s : %-16s : %s\n", var->GetName(), valstr, flagstr, StripTabsAndReturns(var->GetHelpText(), tempbuff, sizeof(tempbuff)));
if (logging)
{
FileSystem()->FPrintf(fh, "\"%s\",\"%s\",%s,\"%s\"\n", var->GetName(), valstr, csvflagstr, StripQuotes(var->GetHelpText(), tempbuff, sizeof(tempbuff)));
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output :
//-----------------------------------------------------------------------------
static void PrintCommand(const ConCommand* cmd, bool logging, FileHandle_t& f)
{
// Print to console
char tempbuff[512] = { 0 };
DevMsg(eDLL_T::ENGINE, "%-40s : %-8s : %-16s : %s\n", cmd->GetName(), "cmd", "", StripTabsAndReturns(cmd->GetHelpText(), tempbuff, sizeof(tempbuff)));
if (logging)
{
char emptyflags[256];
emptyflags[0] = 0;
int c = ARRAYSIZE(g_ConVarFlags);
for (int i = 0; i < c; ++i)
{
char csvf[64];
Q_snprintf(csvf, sizeof(csvf), ",");
Q_strncat(emptyflags, csvf, sizeof(emptyflags));
}
// Names staring with +/- need to be wrapped in single quotes
char name[256];
snprintf(name, sizeof(name), "%s", cmd->GetName());
if (name[0] == '+' || name[0] == '-')
{
snprintf(name, sizeof(name), "'%s'", cmd->GetName());
}
FileSystem()->FPrintf(f, "\"%s\",\"%s\",%s,\"%s\"\n", name, "cmd", emptyflags, StripQuotes(cmd->GetHelpText(), tempbuff, sizeof(tempbuff)));
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output : bool
//-----------------------------------------------------------------------------
static bool ConCommandBaseLessFunc(ConCommandBase* const& lhs, ConCommandBase* const& rhs)
{
const char* left = lhs->GetName();
const char* right = rhs->GetName();
if (*left == '-' || *left == '+')
left++;
if (*right == '-' || *right == '+')
right++;
return (Q_stricmp(left, right) < 0);
}
//-----------------------------------------------------------------------------
// Singleton CCvarUtilities
//-----------------------------------------------------------------------------
static CCvarUtilities g_CvarUtilities;
CCvarUtilities* cv = &g_CvarUtilities;
//-----------------------------------------------------------------------------
// Purpose:
// Input :
// Output : int
//-----------------------------------------------------------------------------
int CCvarUtilities::CountVariablesWithFlags(int flags)
{
int i = 0;
ConCommandBase* var;
// Loop through cvars...
CCVarIteratorInternal* pFactory = g_pCVar->FactoryInternalIterator();
pFactory->SetFirst();
while (pFactory->IsValid())
{
var = pFactory->Get();
if (!var->IsCommand())
{
if (var->IsFlagSet(flags))
{
i++;
}
}
pFactory->Next();
}
return i;
}
//-----------------------------------------------------------------------------
// Purpose: Removes the FCVAR_DEVELOPMENTONLY flag from all cvars, making them accessible
//-----------------------------------------------------------------------------
void CCvarUtilities::EnableDevCvars()
{
// Loop through cvars...
CCVarIteratorInternal* pFactory = g_pCVar->FactoryInternalIterator();
pFactory->SetFirst();
while (pFactory->IsValid())
{
// remove flag from all cvars
ConCommandBase* pCommandBase = pFactory->Get();
pCommandBase->RemoveFlags(FCVAR_DEVELOPMENTONLY);
pFactory->Next();
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : void CCvar::CvarList_f
//-----------------------------------------------------------------------------
void CCvarUtilities::CvarList(const CCommand& args)
{
ConCommandBase* var; // Temporary Pointer to cvars
int iArgs; // Argument count
const char* partial = NULL; // Partial cvar to search for...
// E.eg
int ipLen = 0; // Length of the partial cvar
FileHandle_t f = FILESYSTEM_INVALID_HANDLE; // FilePointer for logging
bool bLogging = false;
// Are we logging?
iArgs = args.ArgC(); // Get count
// Print usage?
if (iArgs == 2 && !Q_strcasecmp(args[1], "?"))
{
DevMsg(eDLL_T::ENGINE, "cvarlist: [log logfile] [ partial ]\n");
return;
}
if (!Q_strcasecmp(args[1], "log") && iArgs >= 3)
{
char fn[256];
Q_snprintf(fn, sizeof(fn), "%s", args[2]);
f = FileSystem()->Open(fn, "wb", nullptr, 0);
if (f)
{
bLogging = true;
}
else
{
DevMsg(eDLL_T::ENGINE, "Couldn't open '%s' for writing!\n", fn);
return;
}
if (iArgs == 4)
{
partial = args[3];
ipLen = Q_strlen(partial);
}
}
else
{
partial = args[1];
ipLen = Q_strlen(partial);
}
// Banner
DevMsg(eDLL_T::ENGINE, "cvar list\n--------------\n");
CUtlRBTree< ConCommandBase* > sorted(0, 0, ConCommandBaseLessFunc);
// Loop through cvars...
CCVarIteratorInternal* pFactory = g_pCVar->FactoryInternalIterator();
pFactory->SetFirst();
while (pFactory->IsValid())
{
var = pFactory->Get();
if (!var->IsFlagSet(FCVAR_DEVELOPMENTONLY) &&
!var->IsFlagSet(FCVAR_HIDDEN))
{
bool print = false;
if (partial) // Partial string searching?
{
if (!Q_strncasecmp(var->GetName(), partial, ipLen))
{
print = true;
}
}
else
{
print = true;
}
if (print)
{
sorted.Insert(var);
}
}
pFactory->Next();
}
if (bLogging)
{
PrintListHeader(f);
}
for (int i = sorted.FirstInorder(); i != sorted.InvalidIndex(); i = sorted.NextInorder(i))
{
var = sorted[i];
if (var->IsCommand())
{
PrintCommand((ConCommand*)var, bLogging, f);
}
else
{
PrintCvar((ConVar*)var, bLogging, f);
}
}
// Show total and syntax help...
if (partial && partial[0])
{
DevMsg(eDLL_T::ENGINE, "--------------\n%3i convars/concommands for [%s]\n", sorted.Count(), partial);
}
else
{
DevMsg(eDLL_T::ENGINE, "--------------\n%3i total convars/concommands\n", sorted.Count());
}
if (bLogging)
{
FileSystem()->Close(f);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCvarUtilities::CvarHelp(const CCommand& args)
{
const char* search;
ConCommandBase* var;
if (args.ArgC() != 2)
{
DevMsg(eDLL_T::ENGINE, "Usage: help <cvarname>\n");
return;
}
// Get name of var to find
search = args[1];
// Search for it
var = g_pCVar->FindCommandBase(search);
if (!var)
{
DevMsg(eDLL_T::ENGINE, "Help: no cvar or command named %s\n", search);
return;
}
// Show info
ConVar_PrintDescription(var);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCvarUtilities::CvarDifferences(const CCommand& args)
{
CCVarIteratorInternal* pFactory = g_pCVar->FactoryInternalIterator();
pFactory->SetFirst();
while (pFactory->IsValid())
{
ConCommandBase* pCommandBase = pFactory->Get();
if (!pCommandBase->IsCommand() &&
!pCommandBase->IsFlagSet(FCVAR_HIDDEN))
{
ConVar* pConVar = reinterpret_cast<ConVar*>(pCommandBase);
if (strcmp(pConVar->GetString(), "FCVAR_NEVER_AS_STRING") != NULL)
{
ConVar_PrintDescription(pConVar);
}
}
pFactory->Next();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CCvarUtilities::CvarFindFlags_f(const CCommand& args)
{
if (args.ArgC() < 2)
{
DevMsg(eDLL_T::ENGINE, "Usage: findflags <string>\n");
DevMsg(eDLL_T::ENGINE, "Available flags to search for: \n");
for (int i = 0; i < ARRAYSIZE(g_ConVarFlags); i++)
{
DevMsg(eDLL_T::ENGINE, " - %s\n", g_ConVarFlags[i].desc);
}
return;
}
// Get substring to find
const char* search = args[1];
ConCommandBase* var;
// Loop through vars and print out findings
CCVarIteratorInternal* pFactory = g_pCVar->FactoryInternalIterator();
pFactory->SetFirst();
while (pFactory->IsValid())
{
var = pFactory->Get();
if (!var->IsFlagSet(FCVAR_DEVELOPMENTONLY) || !var->IsFlagSet(FCVAR_HIDDEN))
{
for (int i = 0; i < ARRAYSIZE(g_ConVarFlags); i++)
{
if (var->IsFlagSet(g_ConVarFlags[i].bit))
{
if (V_stristr(g_ConVarFlags[i].desc, search))
{
ConVar_PrintDescription(var);
}
}
}
}
pFactory->Next();
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
int CCvarUtilities::CvarFindFlagsCompletionCallback(const char* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])
{
int flagC = ARRAYSIZE(g_ConVarFlags);
char const* pcmd = "findflags ";
int len = Q_strlen(partial);
if (len < Q_strlen(pcmd))
{
int i = 0;
for (; i < MIN(flagC, COMMAND_COMPLETION_MAXITEMS); i++)
{
Q_snprintf(commands[i], sizeof(commands[i]), "%s %s", pcmd, g_ConVarFlags[i].desc);
Q_strlower(commands[i]);
}
return i;
}
char const* pSub = partial + Q_strlen(pcmd);
int nSubLen = Q_strlen(pSub);
int values = 0;
for (int i = 0; i < flagC; ++i)
{
if (Q_strnicmp(g_ConVarFlags[i].desc, pSub, nSubLen))
continue;
Q_snprintf(commands[values], sizeof(commands[values]), "%s %s", pcmd, g_ConVarFlags[i].desc);
Q_strlower(commands[values]);
++values;
if (values >= COMMAND_COMPLETION_MAXITEMS)
break;
}
return values;
}
//-----------------------------------------------------------------------------
// Purpose: registers input commands.
// Input : *pszCommandName -

View File

@ -163,6 +163,54 @@ extern ConVar* pylon_showdebug;
extern ConVar* rui_drawEnable;
#endif // !DEDICATED
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CCvarUtilities
{
public:
//bool IsCommand(const CCommand& args);
// Writes lines containing "set variable value" for all variables
// with the archive flag set to true.
//void WriteVariables(CUtlBuffer& buff, bool bAllVars);
// Returns the # of cvars with the server flag set.
int CountVariablesWithFlags(int flags);
// Enable cvars marked with FCVAR_DEVELOPMENTONLY
void EnableDevCvars();
// Lists cvars to console
void CvarList(const CCommand& args);
// Prints help text for cvar
void CvarHelp(const CCommand& args);
// Revert all cvar values
//void CvarRevert(const CCommand& args);
// Revert all cvar values
void CvarDifferences(const CCommand& args);
// Toggles a cvar on/off, or cycles through a set of values
//void CvarToggle(const CCommand& args);
// Finds commands with a specified flag.
void CvarFindFlags_f(const CCommand& args);
int CvarFindFlagsCompletionCallback(const char* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH]);
private:
// just like Cvar_set, but optimizes out the search
//void SetDirect(ConVar* var, const char* value);
//bool IsValidToggleCommand(const char* cmd);
};
extern CCvarUtilities* cv;
class CCVarIteratorInternal // Fully reversed table, just look at the virtual function table and rename the function.
{
public:
@ -180,6 +228,7 @@ public:
ConCommandBase* FindCommandBase(const char* pszCommandName); // @0x1405983A0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
ConVar* FindVar(const char* pszVarName); // @0x1405983B0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
ConCommand* FindCommand(const char* pszCommandName);
ConCommandBase* GetCommands(void) const { return m_pConCommandList; };
void CallGlobalChangeCallbacks(ConVar* pConVar, const char* pOldString);
bool IsMaterialThreadSetAllowed(void);
@ -189,6 +238,35 @@ public:
CCVarIteratorInternal* FactoryInternalIterator(void);
unordered_map<string, ConCommandBase*> DumpToMap(void);
protected:
friend class CCVarIteratorInternal;
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; // !TODO:
};
private:
void* m_pVFTable;
CUtlVector< FnChangeCallback_t > m_GlobalChangeCallbacks;
char pad0[22]; //!TODO:
int m_nNextDLLIdentifier;
ConCommandBase* m_pConCommandList;
char m_CommandHash[208]; //!TODO:
CUtlVector< QueuedConVarSet_t > m_QueuedConVarSets;
bool m_bMaterialSystemThreadSetAllowed;
};
///////////////////////////////////////////////////////////////////////////////

View File

@ -1,5 +1,65 @@
#include "core/stdafx.h"
FORCEINLINE unsigned char tolower_fast(unsigned char c)
{
if ((c >= 'A') && (c <= 'Z'))
return c + ('a' - 'A');
return c;
}
//-----------------------------------------------------------------------------
// Finds a string in another string with a case insensitive test
//-----------------------------------------------------------------------------
char const* V_stristr(char const* pStr, char const* pSearch)
{
AssertValidStringPtr(reinterpret_cast<const TCHAR*>(pStr));
AssertValidStringPtr(reinterpret_cast<const TCHAR*>(pSearch));
if (!pStr || !pSearch)
return 0;
char const* pLetter = pStr;
// Check the entire string
while (*pLetter != 0)
{
// Skip over non-matches
if (tolower_fast((unsigned char)*pLetter) == tolower_fast((unsigned char)*pSearch))
{
// Check for match
char const* pMatch = pLetter + 1;
char const* pTest = pSearch + 1;
while (*pTest != 0)
{
// We've run off the end; don't bother.
if (*pMatch == 0)
return 0;
if (tolower_fast((unsigned char)*pMatch) != tolower_fast((unsigned char)*pTest))
break;
++pMatch;
++pTest;
}
// Found a match!
if (*pTest == 0)
return pLetter;
}
++pLetter;
}
return 0;
}
char* V_stristr(char* pStr, char const* pSearch)
{
AssertValidStringPtr(reinterpret_cast<const TCHAR*>(pStr));
AssertValidStringPtr(reinterpret_cast<const TCHAR*>(pSearch));
return (char*)V_stristr((char const*)pStr, pSearch);
}
//-----------------------------------------------------------------------------
// Purpose: Converts a UTF8 string into a unicode string

View File

@ -1,4 +1,24 @@
#pragma once
#define V_snprintf snprintf
#define V_strlower strlwr
#define V_strlen strlen
#define V_strncat strncat
#define V_stricmp _stricmp
#define V_strnicmp strnicmp
#define V_strcmp strcmp
#define Q_snprintf V_snprintf
#define Q_strlower V_strlower
#define Q_strlen V_strlen
#define Q_strncat V_strncat
#define Q_stricmp V_stricmp
#define Q_strnicmp V_strnicmp
#define Q_strncasecmp V_strnicmp
#define Q_strcasecmp V_stricmp
#define Q_strcmp V_strcmp
char const* V_stristr(char const* pStr, char const* pSearch);
int V_UTF8ToUnicode(const char* pUTF8, wchar_t* pwchDest, int cubDestSizeInBytes);
int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes);

View File

@ -1053,3 +1053,29 @@ void BHit_f(const CCommand& args)
}
#endif // !DEDICATED
}
/*
=====================
CVList_f
List all ConCommandBases
=====================
*/
void CVList_f(const CCommand& args)
{
cv->CvarList(args);
}
/*
=====================
CVDiff_f
List all ConVar's
who's values deviate
from default value
=====================
*/
void CVDiff_f(const CCommand& args)
{
cv->CvarDifferences(args);
}

View File

@ -53,6 +53,8 @@ void Sphere_f(const CCommand& args);
void Capsule_f(const CCommand& args);
#endif // !DEDICATED
void BHit_f(const CCommand& args);
void CVList_f(const CCommand& args);
void CVDiff_f(const CCommand& args);
///////////////////////////////////////////////////////////////////////////////
class VCallback : public IDetour
{