Seaside/SpyCustom/ConVars.cpp
2021-06-16 16:08:23 +03:00

1296 lines
33 KiB
C++

#include "convar.h"
#include <string>
#include "Interfaces.hpp"
//extern auto iff.g_pCVar;
//typedef void(__cdecl* CONMSGPROC)(const char*, ...);
//extern auto iff.myConMsg;
static void V_strncpy(char* pDest, char const* pSrc, int maxLen)
{
strncpy(pDest, pSrc, maxLen);
if (maxLen > 0)
{
pDest[maxLen - 1] = 0;
}
}
static int V_snprintf(char* pDest, int maxLen, const char* pFormat, ...)
{
va_list marker;
va_start(marker, pFormat);
#ifdef _WIN32
int len = _vsnprintf(pDest, maxLen, pFormat, marker);
#elif POSIX
int len = vsnprintf(pDest, maxLen, pFormat, marker);
#else
#error "define vsnprintf type."
#endif
va_end(marker);
// Len < 0 represents an overflow
if (len < 0)
{
len = maxLen;
pDest[maxLen - 1] = 0;
}
return len;
}
//-----------------------------------------------------------------------------
// Base class, containing simple memory management
//-----------------------------------------------------------------------------
CUtlBinaryBlock::CUtlBinaryBlock(int growSize, int initSize)
{
MEM_ALLOC_CREDIT();
m_Memory.Init(growSize, initSize);
m_nActualLength = 0;
}
CUtlBinaryBlock::CUtlBinaryBlock(void* pMemory, int nSizeInBytes, int nInitialLength) : m_Memory((unsigned char*)pMemory, nSizeInBytes)
{
m_nActualLength = nInitialLength;
}
CUtlBinaryBlock::CUtlBinaryBlock(const void* pMemory, int nSizeInBytes) : m_Memory((const unsigned char*)pMemory, nSizeInBytes)
{
m_nActualLength = nSizeInBytes;
}
CUtlBinaryBlock::CUtlBinaryBlock(const CUtlBinaryBlock& src)
{
Set(src.Get(), src.Length());
}
void CUtlBinaryBlock::SetLength(int nLength)
{
MEM_ALLOC_CREDIT();
Assert(!m_Memory.IsReadOnly());
m_nActualLength = nLength;
if (nLength > m_Memory.NumAllocated())
{
int nOverFlow = nLength - m_Memory.NumAllocated();
m_Memory.Grow(nOverFlow);
// If the reallocation failed, clamp length
if (nLength > m_Memory.NumAllocated())
{
m_nActualLength = m_Memory.NumAllocated();
}
}
#ifdef _DEBUG
if (m_Memory.NumAllocated() > m_nActualLength)
{
memset(((char*)m_Memory.Base()) + m_nActualLength, 0xEB, m_Memory.NumAllocated() - m_nActualLength);
}
#endif
}
void CUtlBinaryBlock::Set(const void* pValue, int nLen)
{
Assert(!m_Memory.IsReadOnly());
if (!pValue)
{
nLen = 0;
}
SetLength(nLen);
if (m_nActualLength)
{
if (((const char*)m_Memory.Base()) >= ((const char*)pValue) + nLen ||
((const char*)m_Memory.Base()) + m_nActualLength <= ((const char*)pValue))
{
memcpy(m_Memory.Base(), pValue, m_nActualLength);
}
else
{
memmove(m_Memory.Base(), pValue, m_nActualLength);
}
}
}
// Simple string class.
//-----------------------------------------------------------------------------
CUtlString::CUtlString()
{
}
CUtlString::CUtlString(const char* pString)
{
Set(pString);
}
CUtlString::CUtlString(const CUtlString& string)
{
Set(string.Get());
}
// Attaches the string to external memory. Useful for avoiding a copy
CUtlString::CUtlString(void* pMemory, int nSizeInBytes, int nInitialLength) : m_Storage(pMemory, nSizeInBytes, nInitialLength)
{
}
CUtlString::CUtlString(const void* pMemory, int nSizeInBytes) : m_Storage(pMemory, nSizeInBytes)
{
}
void CUtlString::Set(const char* pValue)
{
Assert(!m_Storage.IsReadOnly());
int nLen = pValue ? Q_strlen(pValue) + 1 : 0;
m_Storage.Set(pValue, nLen);
}
const char* CUtlString::Get() const
{
if (m_Storage.Length() == 0)
{
return "";
}
return reinterpret_cast<const char*>(m_Storage.Get());
}
//-----------------------------------------------------------------------------
// Statically constructed list of ConCommandBases,
// used for registering them with the ICVar interface
//-----------------------------------------------------------------------------
ConCommandBase* ConCommandBase::s_pConCommandBases = NULL;
IConCommandBaseAccessor* ConCommandBase::s_pAccessor = NULL;
static int s_nCVarFlag = 0;
static int s_nDLLIdentifier = -1; // A unique identifier indicating which DLL this convar came from
static bool s_bRegistered = false;
class CDefaultAccessor : public IConCommandBaseAccessor
{
public:
virtual bool RegisterConCommandBase(ConCommandBase* pVar)
{
// Link to engine's list instead
iff.g_pCVar->RegisterConCommand(pVar);
return true;
}
};
static CDefaultAccessor s_DefaultAccessor;
//-----------------------------------------------------------------------------
// Called by the framework to register ConCommandBases with the ICVar
//-----------------------------------------------------------------------------
void ConVar_Register(int nCVarFlag, IConCommandBaseAccessor* pAccessor)
{
if (!iff.g_pCVar || s_bRegistered)
return;
Assert(s_nDLLIdentifier < 0);
s_bRegistered = true;
s_nCVarFlag = nCVarFlag;
s_nDLLIdentifier = iff.g_pCVar->AllocateDLLIdentifier();
ConCommandBase* pCur, * pNext;
ConCommandBase::s_pAccessor = pAccessor ? pAccessor : &s_DefaultAccessor;
pCur = ConCommandBase::s_pConCommandBases;
while (pCur)
{
pNext = pCur->m_pNext;
pCur->AddFlags(s_nCVarFlag);
pCur->Init();
pCur = pNext;
}
//3//g_pCVar->ProcessQueuedMaterialThreadConVarSets();
ConCommandBase::s_pConCommandBases = NULL;
}
void ConVar_Unregister()
{
if (!iff.g_pCVar || !s_bRegistered)
return;
Assert(s_nDLLIdentifier >= 0);
iff.g_pCVar->UnregisterConCommands(s_nDLLIdentifier);
s_nDLLIdentifier = -1;
s_bRegistered = false;
}
//-----------------------------------------------------------------------------
// Purpose: Default constructor
//-----------------------------------------------------------------------------
ConCommandBase::ConCommandBase(void)
{
m_bRegistered = false;
m_pszName = NULL;
m_pszHelpString = NULL;
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*/, int flags /*= 0*/)
{
Create(pName, pHelpString, flags);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
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*/, int flags /*= 0*/)
{
static char* empty_string = (char*)"";
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 (iff.g_pCVar)
{
iff.g_pCVar->UnregisterConCommand(this);
}
}
//-----------------------------------------------------------------------------
// Purpose: Return name of the command/var
// Output : const char
//-----------------------------------------------------------------------------
const char* ConCommandBase::GetName(void) const
{
return m_pszName;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : flag -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool ConCommandBase::IsFlagSet(int flag) const
{
return (flag & m_nFlags) ? true : false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : flags -
//-----------------------------------------------------------------------------
void ConCommandBase::AddFlags(int flags)
{
m_nFlags |= flags;
#ifdef ALLOW_DEVELOPMENT_CVARS
m_nFlags &= ~FCVAR_DEVELOPMENTONLY;
#endif
}
void ConCommandBase::RemoveFlags(int flags)
{
m_nFlags &= ~flags;
}
int ConCommandBase::GetFlags(void) const
{
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 = V_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:
// Output : const char
//-----------------------------------------------------------------------------
const char* ConCommandBase::GetHelpText(void) const
{
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;
}
//-----------------------------------------------------------------------------
//
// Con Commands start here
//
//-----------------------------------------------------------------------------
struct characterset_t
{
char set[256];
};
//-----------------------------------------------------------------------------
// Global methods
//-----------------------------------------------------------------------------
static characterset_t s_BreakSet;
static bool s_bBuiltBreakSet = false;
//-----------------------------------------------------------------------------
// Tokenizer class
//-----------------------------------------------------------------------------
void CCommand::Reset()
{
m_nArgc = 0;
m_nArgv0Size = 0;
m_pArgSBuffer[0] = 0;
}
characterset_t* CCommand::DefaultBreakSet()
{
return &s_BreakSet;
}
//-----------------------------------------------------------------------------
// Default console command autocompletion function
//-----------------------------------------------------------------------------
int DefaultCompletionFunc(const char* partial, char commands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH])
{
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: Constructs a console command
//-----------------------------------------------------------------------------
//ConCommand::ConCommand()
//{
// m_bIsNewConCommand = true;
//}
ConCommand::ConCommand(const char* pName, FnCommandCallbackVoid_t callback, const char* pHelpString /*= 0*/, int flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/)
{
// Set the callback
m_fnCommandCallbackV1 = callback;
m_bUsingNewCommandCallback = false;
m_bUsingCommandCallbackInterface = false;
m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc;
m_bHasCompletionCallback = completionFunc != 0 ? true : false;
// Setup the rest
BaseClass::Create(pName, pHelpString, flags);
}
ConCommand::ConCommand(const char* pName, FnCommandCallback_t callback, const char* pHelpString /*= 0*/, int flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/)
{
// Set the callback
m_fnCommandCallback = callback;
m_bUsingNewCommandCallback = true;
m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc;
m_bHasCompletionCallback = completionFunc != 0 ? true : false;
m_bUsingCommandCallbackInterface = false;
// Setup the rest
BaseClass::Create(pName, pHelpString, flags);
}
ConCommand::ConCommand(const char* pName, ICommandCallback* pCallback, const char* pHelpString /*= 0*/, int flags /*= 0*/, ICommandCompletionCallback* pCompletionCallback /*= 0*/)
{
// Set the callback
m_pCommandCallback = pCallback;
m_bUsingNewCommandCallback = false;
m_pCommandCompletionCallback = pCompletionCallback;
m_bHasCompletionCallback = (pCompletionCallback != 0);
m_bUsingCommandCallbackInterface = true;
// Setup the rest
BaseClass::Create(pName, pHelpString, flags);
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
ConCommand::~ConCommand(void)
{
}
//-----------------------------------------------------------------------------
// Purpose: Returns true if this is a command
//-----------------------------------------------------------------------------
bool ConCommand::IsCommand(void) const
{
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Invoke the function if there is one
//-----------------------------------------------------------------------------
void ConCommand::Dispatch(const CCommand& command)
{
if (m_bUsingNewCommandCallback)
{
if (m_fnCommandCallback)
{
(*m_fnCommandCallback)(command);
return;
}
}
else if (m_bUsingCommandCallbackInterface)
{
if (m_pCommandCallback)
{
m_pCommandCallback->CommandCallback(command);
return;
}
}
else
{
if (m_fnCommandCallbackV1)
{
(*m_fnCommandCallbackV1)();
return;
}
}
// Command without callback!!!
AssertMsg(0, ("Encountered ConCommand '%s' without a callback!\n", GetName()));
}
//-----------------------------------------------------------------------------
// Purpose: Calls the autocompletion method to get autocompletion suggestions
//-----------------------------------------------------------------------------
int ConCommand::AutoCompleteSuggest(const char* partial, CUtlVector< CUtlString >& commands)
{
if (m_bUsingCommandCallbackInterface)
{
if (!m_pCommandCompletionCallback)
return 0;
return m_pCommandCompletionCallback->CommandCompletionCallback(partial, commands);
}
Assert(m_fnCompletionCallback);
if (!m_fnCompletionCallback)
return 0;
char rgpchCommands[COMMAND_COMPLETION_MAXITEMS][COMMAND_COMPLETION_ITEM_LENGTH];
int iret = (m_fnCompletionCallback)(partial, rgpchCommands);
for (int i = 0; i < iret; ++i)
{
CUtlString str = rgpchCommands[i];
commands.AddToTail(str);
}
return iret;
}
//-----------------------------------------------------------------------------
// Returns true if the console command can autocomplete
//-----------------------------------------------------------------------------
bool ConCommand::CanAutoComplete(void)
{
return m_bHasCompletionCallback;
}
//-----------------------------------------------------------------------------
//
// Console Variables
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Various constructors
//-----------------------------------------------------------------------------
ConVar::ConVar(const char* pName, const char* pDefaultValue, int flags /* = 0 */)
{
Create(pName, pDefaultValue, flags);
}
ConVar::ConVar(const char* pName, const char* pDefaultValue, int flags, const char* pHelpString)
{
Create(pName, pDefaultValue, flags, pHelpString);
}
ConVar::ConVar(const char* pName, const char* pDefaultValue, int flags, const char* pHelpString, bool bMin, float fMin, bool bMax, float fMax)
{
Create(pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax);
}
ConVar::ConVar(const char* pName, const char* pDefaultValue, int flags, const char* pHelpString, FnChangeCallback_t callback)
{
Create(pName, pDefaultValue, flags, pHelpString, false, 0.0, false, 0.0, callback);
}
ConVar::ConVar(const char* pName, const char* pDefaultValue, int flags, const char* pHelpString, bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback_t callback)
{
Create(pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax, callback);
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
ConVar::~ConVar(void)
{
//if(IsRegistered())
// convar->UnregisterConCommand(this);
if (m_Value.m_pszString) {
delete[] m_Value.m_pszString;
m_Value.m_pszString = NULL;
}
}
//-----------------------------------------------------------------------------
// Install a change callback (there shouldn't already be one....)
//-----------------------------------------------------------------------------
void ConVar::InstallChangeCallback(FnChangeCallback_t callback, bool bInvoke)
{
if (callback) {
if (m_fnChangeCallbacks.GetOffset(callback) != -1) {
m_fnChangeCallbacks.AddToTail(callback);
if (bInvoke)
callback(this, m_Value.m_pszString, m_Value.m_fValue);
}
else {
//Warning("InstallChangeCallback ignoring duplicate change callback!!!\n");
}
}
else {
//Warning("InstallChangeCallback called with NULL callback, ignoring!!!\n");
}
}
bool ConVar::IsFlagSet(int flag) const
{
return (flag & m_pParent->m_nFlags) ? true : false;
}
const char* ConVar::GetHelpText(void) const
{
return m_pParent->m_pszHelpString;
}
void ConVar::AddFlags(int flags)
{
m_pParent->m_nFlags |= flags;
#ifdef ALLOW_DEVELOPMENT_CVARS
m_pParent->m_nFlags &= ~FCVAR_DEVELOPMENTONLY;
#endif
}
bool ConVar::IsRegistered(void) const
{
return m_pParent->m_bRegistered;
}
const char* ConVar::GetName(void) const
{
//printf("getname called\n");
return m_pParent->m_pszName;
}
//void ConVar::convarplaceholder(){}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool ConVar::IsCommand(void) const
{
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input :
//-----------------------------------------------------------------------------
void ConVar::Init()
{
BaseClass::Init();
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *value -
//-----------------------------------------------------------------------------
void ConVar::InternalSetValue(const char* value)
{
printf("Executed ConVar::InternalSetValue to %s\n", value);
float fNewValue;
char tempVal[32];
char* val;
auto temp = *(uint32_t*)&m_Value.m_fValue ^ (uint32_t)this;
float flOldValue = *(float*)(&temp);
val = (char*)value;
fNewValue = (float)atof(value);
if (ClampValue(fNewValue)) {
snprintf(tempVal, sizeof(tempVal), "%f", fNewValue);
val = tempVal;
}
// Redetermine value
*(uint32_t*)&m_Value.m_fValue = *(uint32_t*)&fNewValue ^ (uint32_t)this;
*(uint32_t*)&m_Value.m_nValue = (uint32_t)fNewValue ^ (uint32_t)this;
if (!(m_nFlags & FCVAR_NEVER_AS_STRING)) {
ChangeStringValue(val, flOldValue);
}
}
/*
void ConVar::InternalSetValue(const char* value)
{
if (IsFlagSet(FCVAR_MATERIAL_THREAD_MASK))
{
if (g_pCVar && !g_pCVar->IsMaterialThreadSetAllowed())
{
g_pCVar->QueueMaterialThreadSetValue(this, value);
return;
}
}
float fNewValue;
char tempVal[32];
char* val;
Assert(m_pParent == this); // Only valid for root convars.
float flOldValue = m_fValue;
val = (char*)value;
if (!value)
fNewValue = 0.0f;
else
fNewValue = (float)atof(value);
if (ClampValue(fNewValue))
{
Q_snprintf(tempVal, sizeof(tempVal), "%f", fNewValue);
val = tempVal;
}
// Redetermine value
m_fValue = fNewValue;
m_nValue = (int)(m_fValue);
if (!(m_nFlags & FCVAR_NEVER_AS_STRING))
{
ChangeStringValue(val, flOldValue);
}
}
*/
//-----------------------------------------------------------------------------
// Purpose:
// Input : *tempVal -
//-----------------------------------------------------------------------------
void ConVar::ChangeStringValue(const char* tempVal, float flOldValue)
{
printf("Executed ConVar::ChangeStringValue (tempVal %s; flOldValue %f)\n", tempVal, flOldValue);
char* pszOldValue = (char*)stackalloc(m_Value.m_StringLength);
memcpy(pszOldValue, m_Value.m_pszString, m_Value.m_StringLength);
int len = strlen(tempVal) + 1;
if (len > m_Value.m_StringLength) {
if (m_Value.m_pszString) {
delete[] m_Value.m_pszString;
}
m_Value.m_pszString = new char[len];
m_Value.m_StringLength = len;
}
memcpy(m_Value.m_pszString, std::to_string(this->GetFloat()).c_str(), len);
// Invoke any necessary callback function
for (int i = 0; i < m_fnChangeCallbacks.Count(); i++) {
m_fnChangeCallbacks[i](this, pszOldValue, flOldValue);
}
if (iff.g_pCVar)
iff.g_pCVar->CallGlobalChangeCallbacks(this, pszOldValue, flOldValue);
}
void ConVar::InternalSetColorValue(Color cValue)
{
int color = (int)cValue.GetRawColor();
InternalSetIntValue(color);
}
//-----------------------------------------------------------------------------
// Purpose: Check whether to clamp and then perform clamp
// Input : value -
// Output : Returns true if value changed
//-----------------------------------------------------------------------------
bool ConVar::ClampValue(float& value)
{
if (m_bHasMin && (value < m_fMinVal))
{
value = m_fMinVal;
return true;
}
if (m_bHasMax && (value > m_fMaxVal))
{
value = m_fMaxVal;
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *value -
//-----------------------------------------------------------------------------
/*
void ConVar::InternalSetFloatValue(float fNewValue)
{
if (fNewValue == m_fValue)
return;
if (IsFlagSet(FCVAR_MATERIAL_THREAD_MASK))
{
if (g_pCVar && !g_pCVar->IsMaterialThreadSetAllowed())
{
g_pCVar->QueueMaterialThreadSetValue(this, fNewValue);
return;
}
}
Assert(m_pParent == this); // Only valid for root convars.
// Check bounds
ClampValue(fNewValue);
// Redetermine value
float flOldValue = m_fValue;
m_fValue = fNewValue;
m_nValue = (int)m_fValue;
if (!(m_nFlags & FCVAR_NEVER_AS_STRING))
{
char tempVal[32];
Q_snprintf(tempVal, sizeof(tempVal), "%f", m_fValue);
ChangeStringValue(tempVal, flOldValue);
}
else
{
Assert(!m_fnChangeCallback);
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *value -
//-----------------------------------------------------------------------------
void ConVar::InternalSetIntValue(int nValue)
{
if (nValue == m_nValue)
return;
if (IsFlagSet(FCVAR_MATERIAL_THREAD_MASK))
{
if (g_pCVar && !g_pCVar->IsMaterialThreadSetAllowed())
{
g_pCVar->QueueMaterialThreadSetValue(this, nValue);
return;
}
}
Assert(m_pParent == this); // Only valid for root convars.
float fValue = (float)nValue;
if (ClampValue(fValue))
{
nValue = (int)(fValue);
}
// Redetermine value
float flOldValue = m_fValue;
m_fValue = fValue;
m_nValue = nValue;
if (!(m_nFlags & FCVAR_NEVER_AS_STRING))
{
char tempVal[32];
Q_snprintf(tempVal, sizeof(tempVal), "%d", m_nValue);
ChangeStringValue(tempVal, flOldValue);
}
else
{
Assert(!m_fnChangeCallback);
}
}
*/
void ConVar::InternalSetFloatValue(float fNewValue)
{
printf("Executed ConVar::InternalSetFloatValue to %f\n",fNewValue);
if (fNewValue == m_Value.m_fValue)
return;
ClampValue(fNewValue);
// Redetermine value
float flOldValue = m_Value.m_fValue;
*(uint32_t*)&m_Value.m_fValue = *(uint32_t*)&fNewValue ^ (uint32_t)this;
*(uint32_t*)&m_Value.m_nValue = (uint32_t)fNewValue ^ (uint32_t)this;
if (!(m_nFlags & FCVAR_NEVER_AS_STRING)) {
char tempVal[32];
snprintf(tempVal, sizeof(tempVal), "%f", m_Value.m_fValue);
ChangeStringValue(tempVal, flOldValue);
}
else {
//assert(m_fnChangeCallbacks.Count() == 0);
}
}
void ConVar::InternalSetIntValue(int nValue)
{
printf("Executed ConVar::InternalSetIntValue to %d\n",nValue);
if (nValue == ((int)m_Value.m_nValue ^ (int)this))
return;
float fValue = (float)nValue;
if (ClampValue(fValue)) {
nValue = (int)(fValue);
}
// Redetermine value
float flOldValue = m_Value.m_fValue;
*(uint32_t*)&m_Value.m_fValue = *(uint32_t*)&fValue ^ (uint32_t)this;
*(uint32_t*)&m_Value.m_nValue = *(uint32_t*)&nValue ^ (uint32_t)this;
if (!(m_nFlags & FCVAR_NEVER_AS_STRING)) {
char tempVal[32];
snprintf(tempVal, sizeof(tempVal), "%d", m_Value.m_nValue);
ChangeStringValue(tempVal, flOldValue);
}
else {
//assert(m_fnChangeCallbacks.Count() == 0);
}
}
//-----------------------------------------------------------------------------
// Purpose: Private creation
//-----------------------------------------------------------------------------
void ConVar::Create(const char* pName, const char* pDefaultValue, int flags /*= 0*/,
const char* pHelpString /*= NULL*/, bool bMin /*= false*/, float fMin /*= 0.0*/,
bool bMax /*= false*/, float fMax /*= false*/, FnChangeCallback_t callback /*= NULL*/)
{
static const char* empty_string = "";
m_pParent = this;
// Name should be static data
m_pszDefaultValue = pDefaultValue ? pDefaultValue : empty_string;
m_Value.m_StringLength = strlen(m_pszDefaultValue) + 1;
m_Value.m_pszString = new char[m_Value.m_StringLength];
memcpy(m_Value.m_pszString, m_pszDefaultValue, m_Value.m_StringLength);
m_bHasMin = bMin;
m_fMinVal = fMin;
m_bHasMax = bMax;
m_fMaxVal = fMax;
if (callback)
m_fnChangeCallbacks.AddToTail(callback);
float value = (float)atof(m_Value.m_pszString);
*(uint32_t*)&m_Value.m_fValue = *(uint32_t*)&value ^ (uint32_t)this;
*(uint32_t*)&m_Value.m_nValue = *(uint32_t*)&value ^ (uint32_t)this;
BaseClass::Create(pName, pHelpString, flags);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *value -
//-----------------------------------------------------------------------------
void ConVar::SetValue(const char* value)
{
printf("Executed ConVar::SetValue to %s\n",value);
ConVar* var = (ConVar*)m_pParent;
var->InternalSetValue(value);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : value -
//-----------------------------------------------------------------------------
void ConVar::SetValue(float value)
{
printf("Executed ConVar::SetValue to %f\n", value);
ConVar* var = (ConVar*)m_pParent;
var->InternalSetFloatValue(value);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : value -
//-----------------------------------------------------------------------------
void ConVar::SetValue(int value)
{
printf("Executed ConVar::SetValue to %d\n", value);
ConVar* var = (ConVar*)m_pParent;
var->InternalSetIntValue(value);
}
void ConVar::SetValue(Color value)
{
ConVar* var = (ConVar*)m_pParent;
var->InternalSetColorValue(value);
}
///
int ConVar::GetFlags(void) const
{
return m_pParent->m_nFlags;
}
int ConVar::GetSplitScreenPlayerSlot(void) const
{
return 0;
}
const char* ConVar::GetBaseName(void) const
{
return m_pParent->m_pszName;
}
//-----------------------------------------------------------------------------
// Purpose: Reset to default value
//-----------------------------------------------------------------------------
void ConVar::Revert(void)
{
// Force default value again
ConVar* var = (ConVar*)m_pParent;
var->SetValue(var->m_pszDefaultValue);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : minVal -
// Output : true if there is a min set
//-----------------------------------------------------------------------------
bool ConVar::GetMin(float& minVal) const
{
minVal = m_pParent->m_fMinVal;
return m_pParent->m_bHasMin;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : maxVal -
//-----------------------------------------------------------------------------
bool ConVar::GetMax(float& maxVal) const
{
maxVal = m_pParent->m_fMaxVal;
return m_pParent->m_bHasMax;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : const char
//-----------------------------------------------------------------------------
const char* ConVar::GetDefault(void) const
{
return m_pParent->m_pszDefaultValue;
}
/*
void ConVar::SetDefault(const char* pszDefault)
{
static char* empty_string = (char*)"";
m_pszDefaultValue = pszDefault ? pszDefault : empty_string;
Assert(m_pszDefaultValue);
}
*/
//-----------------------------------------------------------------------------
// This version is simply used to make reading convars simpler.
// Writing convars isn't allowed in this mode
//-----------------------------------------------------------------------------
class CEmptyConVar : public ConVar
{
public:
CEmptyConVar() : ConVar("", "0") {}
// Used for optimal read access
virtual void SetValue(const char* pValue) {}
virtual void SetValue(float flValue) {}
virtual void SetValue(int nValue) {}
virtual const char* GetName(void) const { return ""; }
virtual bool IsFlagSet(int nFlags) const { return false; }
};
static CEmptyConVar s_EmptyConVar;
ConVarRef::ConVarRef(const char* pName)
{
Init(pName, false);
}
ConVarRef::ConVarRef(const char* pName, bool bIgnoreMissing)
{
Init(pName, bIgnoreMissing);
}
void ConVarRef::Init(const char* pName, bool bIgnoreMissing)
{
m_pConVar = iff.g_pCVar ? iff.g_pCVar->FindVar(pName) : &s_EmptyConVar;
if (!m_pConVar)
{
m_pConVar = &s_EmptyConVar;
}
m_pConVarState = static_cast<ConVar*>(m_pConVar);
if (!IsValid())
{
static bool bFirst = true;
if (iff.g_pCVar || bFirst)
{
if (!bIgnoreMissing)
{
printf("ConVarRef %s doesn't point to an existing ConVar\n", pName);
}
bFirst = false;
}
}
}
ConVarRef::ConVarRef(IConVar* pConVar)
{
m_pConVar = pConVar ? pConVar : &s_EmptyConVar;
m_pConVarState = static_cast<ConVar*>(m_pConVar);
}
bool ConVarRef::IsValid() const
{
return m_pConVar != &s_EmptyConVar;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void ConVar_PrintFlags(const ConCommandBase* var)
{
bool any = false;
if (var->IsFlagSet(FCVAR_GAMEDLL))
{
iff.myConMsg(" game");
any = true;
}
if (var->IsFlagSet(FCVAR_CLIENTDLL))
{
iff.myConMsg(" client");
any = true;
}
if (var->IsFlagSet(FCVAR_ARCHIVE))
{
iff.myConMsg(" archive");
any = true;
}
if (var->IsFlagSet(FCVAR_NOTIFY))
{
iff.myConMsg(" notify");
any = true;
}
if (var->IsFlagSet(FCVAR_SPONLY))
{
iff.myConMsg(" singleplayer");
any = true;
}
if (var->IsFlagSet(FCVAR_NOT_CONNECTED))
{
iff.myConMsg(" notconnected");
any = true;
}
if (var->IsFlagSet(FCVAR_CHEAT))
{
iff.myConMsg(" cheat");
any = true;
}
if (var->IsFlagSet(FCVAR_REPLICATED))
{
iff.myConMsg(" replicated");
any = true;
}
if (var->IsFlagSet(FCVAR_SERVER_CAN_EXECUTE))
{
iff.myConMsg(" server_can_execute");
any = true;
}
if (var->IsFlagSet(FCVAR_CLIENTCMD_CAN_EXECUTE))
{
iff.myConMsg(" clientcmd_can_execute");
any = true;
}
if (any)
{
iff.myConMsg("\n");
}
}