mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Refactor config manager, move config variable handling
Move all code for handling of config variables from console to config manager. The console no longer depends on the config manager, instead the config manager now depends on the console. Add `struct`s to manage config variables of different types (int, color and string). The config manager now keeps a list of all config variables, so usage of the preprocessor can be avoided except for code to initially create all config variables. Additionally, a separate list of just the game config variables (config variables with `CFGFLAG_GAME`) is kept to optimize the `ResetGameSettings` function, as this function is called whenever connecting to a server and should be fast. Previously, this function was even less efficient because it preformed a linear search for every individual game config variable to find the respective command data. Move console commands that opperate only on config variables (`reset`, `toggle` and `+toggle`) to config manager. Ensure that these commands only opperate on the desired config variables (client or server, respectively) by checking `IConsole::FlagMask`. Add `IConfigManager::SetReadOnly` function to set/unset config variables as read-only instead of manually overriding the command handlers for the `sv_rescue` and `sv_test_cmds` config variables. This also fixes that read-only config variables could still be changed by using the `reset` command. A console message is now printed when trying to change a read-only config variable. Removing the special handling for these two config variables is additionally useful so the console does not need to keep a pointer to config values and manager. Use a `CHeap` for the config variables, their help texts and the previous values of string config variables to avoid many separate allocations as well usage of static variables. Also use the heap to store the unknown commands instead of using `std::string`s. Properly trigger command chain when resetting config variables with the `reset` command and when resetting game settings on map loading. Closes #7461. Format default value for color variables as RGB/RGBA hex with dollar sign prefix. Closes #5523. Add log message when using `reset` with a variable that does not exist. Use `log_error` instead of `dbg_msg` when saving config file fails. Support unlimited number of config save callbacks instead of at most 16. The code also becomes more readable by using an `std::vector` instead of a fixed-size array and a separate num variable. Consistently name `MACRO_CONFIG_*` parameters when declaring the macros. Add `IConsole::CMDLINE_LENGTH` constant to represent the maximum length of the console input and thereby reduce usage of magic numbers for buffer sizes.
This commit is contained in:
parent
1cf80edb2a
commit
159ddf5534
|
@ -4467,8 +4467,8 @@ int main(int argc, const char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
pEngine->Init();
|
pEngine->Init();
|
||||||
pConfigManager->Init();
|
|
||||||
pConsole->Init();
|
pConsole->Init();
|
||||||
|
pConfigManager->Init();
|
||||||
|
|
||||||
// register all console commands
|
// register all console commands
|
||||||
pClient->RegisterCommands();
|
pClient->RegisterCommands();
|
||||||
|
|
|
@ -12,8 +12,9 @@ public:
|
||||||
typedef void (*SAVECALLBACKFUNC)(IConfigManager *pConfig, void *pUserData);
|
typedef void (*SAVECALLBACKFUNC)(IConfigManager *pConfig, void *pUserData);
|
||||||
|
|
||||||
virtual void Init() = 0;
|
virtual void Init() = 0;
|
||||||
virtual void Reset() = 0;
|
|
||||||
virtual void Reset(const char *pScriptName) = 0;
|
virtual void Reset(const char *pScriptName) = 0;
|
||||||
|
virtual void ResetGameSettings() = 0;
|
||||||
|
virtual void SetReadOnly(const char *pScriptName, bool ReadOnly) = 0;
|
||||||
virtual bool Save() = 0;
|
virtual bool Save() = 0;
|
||||||
virtual class CConfig *Values() = 0;
|
virtual class CConfig *Values() = 0;
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@ public:
|
||||||
TEMPCMD_HELP_LENGTH = 192,
|
TEMPCMD_HELP_LENGTH = 192,
|
||||||
TEMPCMD_PARAMS_LENGTH = 96,
|
TEMPCMD_PARAMS_LENGTH = 96,
|
||||||
|
|
||||||
|
CMDLINE_LENGTH = 512,
|
||||||
|
|
||||||
CLIENT_ID_GAME = -2,
|
CLIENT_ID_GAME = -2,
|
||||||
CLIENT_ID_NO_GAME = -3,
|
CLIENT_ID_NO_GAME = -3,
|
||||||
};
|
};
|
||||||
|
@ -117,8 +119,6 @@ public:
|
||||||
|
|
||||||
virtual void SetAccessLevel(int AccessLevel) = 0;
|
virtual void SetAccessLevel(int AccessLevel) = 0;
|
||||||
|
|
||||||
virtual void ResetGameSettings() = 0;
|
|
||||||
|
|
||||||
static LEVEL ToLogLevel(int ConsoleLevel);
|
static LEVEL ToLogLevel(int ConsoleLevel);
|
||||||
static int ToLogLevelFilter(int ConsoleLevel);
|
static int ToLogLevelFilter(int ConsoleLevel);
|
||||||
|
|
||||||
|
|
|
@ -153,8 +153,8 @@ int main(int argc, const char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
pEngine->Init();
|
pEngine->Init();
|
||||||
pConfigManager->Init();
|
|
||||||
pConsole->Init();
|
pConsole->Init();
|
||||||
|
pConfigManager->Init();
|
||||||
|
|
||||||
// register all console commands
|
// register all console commands
|
||||||
pServer->RegisterCommands();
|
pServer->RegisterCommands();
|
||||||
|
@ -173,8 +173,8 @@ int main(int argc, const char **argv)
|
||||||
if(argc > 1)
|
if(argc > 1)
|
||||||
pConsole->ParseArguments(argc - 1, &argv[1]);
|
pConsole->ParseArguments(argc - 1, &argv[1]);
|
||||||
|
|
||||||
pConsole->Register("sv_test_cmds", "", CFGFLAG_SERVER, CServer::ConTestingCommands, pConsole, "Turns testing commands aka cheats on/off (setting only works in initial config)");
|
pConfigManager->SetReadOnly("sv_test_cmds", true);
|
||||||
pConsole->Register("sv_rescue", "", CFGFLAG_SERVER, CServer::ConRescue, pConsole, "Allow /rescue command so players can teleport themselves out of freeze (setting only works in initial config)");
|
pConfigManager->SetReadOnly("sv_rescue", true);
|
||||||
|
|
||||||
const int Mode = g_Config.m_Logappend ? IOFLAG_APPEND : IOFLAG_WRITE;
|
const int Mode = g_Config.m_Logappend ? IOFLAG_APPEND : IOFLAG_WRITE;
|
||||||
if(g_Config.m_Logfile[0])
|
if(g_Config.m_Logfile[0])
|
||||||
|
|
|
@ -3096,22 +3096,6 @@ int CServer::Run()
|
||||||
return ErrorShutdown();
|
return ErrorShutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServer::ConTestingCommands(CConsole::IResult *pResult, void *pUser)
|
|
||||||
{
|
|
||||||
CConsole *pThis = static_cast<CConsole *>(pUser);
|
|
||||||
char aBuf[128];
|
|
||||||
str_format(aBuf, sizeof(aBuf), "Value: %d", pThis->Config()->m_SvTestingCommands);
|
|
||||||
pThis->Print(CConsole::OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CServer::ConRescue(CConsole::IResult *pResult, void *pUser)
|
|
||||||
{
|
|
||||||
CConsole *pThis = static_cast<CConsole *>(pUser);
|
|
||||||
char aBuf[128];
|
|
||||||
str_format(aBuf, sizeof(aBuf), "Value: %d", pThis->Config()->m_SvRescue);
|
|
||||||
pThis->Print(CConsole::OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CServer::ConKick(IConsole::IResult *pResult, void *pUser)
|
void CServer::ConKick(IConsole::IResult *pResult, void *pUser)
|
||||||
{
|
{
|
||||||
if(pResult->NumArguments() > 1)
|
if(pResult->NumArguments() > 1)
|
||||||
|
|
|
@ -413,8 +413,6 @@ public:
|
||||||
|
|
||||||
int Run();
|
int Run();
|
||||||
|
|
||||||
static void ConTestingCommands(IConsole::IResult *pResult, void *pUser);
|
|
||||||
static void ConRescue(IConsole::IResult *pResult, void *pUser);
|
|
||||||
static void ConKick(IConsole::IResult *pResult, void *pUser);
|
static void ConKick(IConsole::IResult *pResult, void *pUser);
|
||||||
static void ConStatus(IConsole::IResult *pResult, void *pUser);
|
static void ConStatus(IConsole::IResult *pResult, void *pUser);
|
||||||
static void ConShutdown(IConsole::IResult *pResult, void *pUser);
|
static void ConShutdown(IConsole::IResult *pResult, void *pUser);
|
||||||
|
|
|
@ -1,65 +1,463 @@
|
||||||
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
||||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||||
|
|
||||||
|
#include <base/log.h>
|
||||||
|
|
||||||
#include <engine/config.h>
|
#include <engine/config.h>
|
||||||
#include <engine/shared/config.h>
|
#include <engine/shared/config.h>
|
||||||
|
#include <engine/shared/console.h>
|
||||||
#include <engine/shared/protocol.h>
|
#include <engine/shared/protocol.h>
|
||||||
#include <engine/storage.h>
|
#include <engine/storage.h>
|
||||||
|
|
||||||
CConfig g_Config;
|
CConfig g_Config;
|
||||||
|
|
||||||
void EscapeParam(char *pDst, const char *pSrc, int Size)
|
static void EscapeParam(char *pDst, const char *pSrc, int Size)
|
||||||
{
|
{
|
||||||
str_escape(&pDst, pSrc, pDst + Size);
|
str_escape(&pDst, pSrc, pDst + Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SConfigVariable
|
||||||
|
{
|
||||||
|
enum EVariableType
|
||||||
|
{
|
||||||
|
VAR_INT,
|
||||||
|
VAR_COLOR,
|
||||||
|
VAR_STRING,
|
||||||
|
};
|
||||||
|
IConsole *m_pConsole;
|
||||||
|
const char *m_pScriptName;
|
||||||
|
EVariableType m_Type;
|
||||||
|
int m_Flags;
|
||||||
|
const char *m_pHelp;
|
||||||
|
// Note that this only applies to the console command and the SetValue function,
|
||||||
|
// but the underlying config variable can still be modified programatically.
|
||||||
|
bool m_ReadOnly = false;
|
||||||
|
|
||||||
|
SConfigVariable(IConsole *pConsole, const char *pScriptName, EVariableType Type, int Flags, const char *pHelp) :
|
||||||
|
m_pConsole(pConsole),
|
||||||
|
m_pScriptName(pScriptName),
|
||||||
|
m_Type(Type),
|
||||||
|
m_Flags(Flags),
|
||||||
|
m_pHelp(pHelp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~SConfigVariable() = default;
|
||||||
|
|
||||||
|
virtual void Register() = 0;
|
||||||
|
virtual bool IsDefault() const = 0;
|
||||||
|
virtual void Serialize(char *pOut, size_t Size) const = 0;
|
||||||
|
virtual void ResetToDefault() = 0;
|
||||||
|
virtual void ResetToOld() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ExecuteLine(const char *pLine)
|
||||||
|
{
|
||||||
|
m_pConsole->ExecuteLine(pLine, (m_Flags & CFGFLAG_GAME) != 0 ? IConsole::CLIENT_ID_GAME : -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckReadOnly()
|
||||||
|
{
|
||||||
|
if(!m_ReadOnly)
|
||||||
|
return false;
|
||||||
|
char aBuf[IConsole::CMDLINE_LENGTH + 64];
|
||||||
|
str_format(aBuf, sizeof(aBuf), "The config variable '%s' cannot be changed right now.", m_pScriptName);
|
||||||
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "config", aBuf);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SIntConfigVariable : public SConfigVariable
|
||||||
|
{
|
||||||
|
int *m_pVariable;
|
||||||
|
int m_Default;
|
||||||
|
int m_Min;
|
||||||
|
int m_Max;
|
||||||
|
int m_OldValue;
|
||||||
|
|
||||||
|
SIntConfigVariable(IConsole *pConsole, const char *pScriptName, EVariableType Type, int Flags, const char *pHelp, int *pVariable, int Default, int Min, int Max) :
|
||||||
|
SConfigVariable(pConsole, pScriptName, Type, Flags, pHelp),
|
||||||
|
m_pVariable(pVariable),
|
||||||
|
m_Default(Default),
|
||||||
|
m_Min(Min),
|
||||||
|
m_Max(Max),
|
||||||
|
m_OldValue(Default)
|
||||||
|
{
|
||||||
|
*m_pVariable = m_Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
~SIntConfigVariable() override = default;
|
||||||
|
|
||||||
|
static void CommandCallback(IConsole::IResult *pResult, void *pUserData)
|
||||||
|
{
|
||||||
|
SIntConfigVariable *pData = static_cast<SIntConfigVariable *>(pUserData);
|
||||||
|
|
||||||
|
if(pResult->NumArguments())
|
||||||
|
{
|
||||||
|
if(pData->CheckReadOnly())
|
||||||
|
return;
|
||||||
|
|
||||||
|
int Value = pResult->GetInteger(0);
|
||||||
|
|
||||||
|
// do clamping
|
||||||
|
if(pData->m_Min != pData->m_Max)
|
||||||
|
{
|
||||||
|
if(Value < pData->m_Min)
|
||||||
|
Value = pData->m_Min;
|
||||||
|
if(pData->m_Max != 0 && Value > pData->m_Max)
|
||||||
|
Value = pData->m_Max;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pData->m_pVariable = Value;
|
||||||
|
if(pResult->m_ClientID != IConsole::CLIENT_ID_GAME)
|
||||||
|
pData->m_OldValue = Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char aBuf[32];
|
||||||
|
str_format(aBuf, sizeof(aBuf), "Value: %d", *pData->m_pVariable);
|
||||||
|
pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "config", aBuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Register() override
|
||||||
|
{
|
||||||
|
m_pConsole->Register(m_pScriptName, "?i", m_Flags, CommandCallback, this, m_pHelp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDefault() const override
|
||||||
|
{
|
||||||
|
return *m_pVariable == m_Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(char *pOut, size_t Size, int Value) const
|
||||||
|
{
|
||||||
|
str_format(pOut, Size, "%s %i", m_pScriptName, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(char *pOut, size_t Size) const override
|
||||||
|
{
|
||||||
|
Serialize(pOut, Size, *m_pVariable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetValue(int Value)
|
||||||
|
{
|
||||||
|
if(CheckReadOnly())
|
||||||
|
return;
|
||||||
|
char aBuf[IConsole::CMDLINE_LENGTH];
|
||||||
|
Serialize(aBuf, sizeof(aBuf), Value);
|
||||||
|
ExecuteLine(aBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetToDefault() override
|
||||||
|
{
|
||||||
|
SetValue(m_Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetToOld() override
|
||||||
|
{
|
||||||
|
SetValue(m_OldValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SColorConfigVariable : public SConfigVariable
|
||||||
|
{
|
||||||
|
unsigned *m_pVariable;
|
||||||
|
unsigned m_Default;
|
||||||
|
bool m_Light;
|
||||||
|
bool m_Alpha;
|
||||||
|
unsigned m_OldValue;
|
||||||
|
|
||||||
|
SColorConfigVariable(IConsole *pConsole, const char *pScriptName, EVariableType Type, int Flags, const char *pHelp, unsigned *pVariable, unsigned Default) :
|
||||||
|
SConfigVariable(pConsole, pScriptName, Type, Flags, pHelp),
|
||||||
|
m_pVariable(pVariable),
|
||||||
|
m_Default(Default),
|
||||||
|
m_Light(Flags & CFGFLAG_COLLIGHT),
|
||||||
|
m_Alpha(Flags & CFGFLAG_COLALPHA),
|
||||||
|
m_OldValue(Default)
|
||||||
|
{
|
||||||
|
*m_pVariable = m_Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
~SColorConfigVariable() override = default;
|
||||||
|
|
||||||
|
static void CommandCallback(IConsole::IResult *pResult, void *pUserData)
|
||||||
|
{
|
||||||
|
SColorConfigVariable *pData = static_cast<SColorConfigVariable *>(pUserData);
|
||||||
|
|
||||||
|
if(pResult->NumArguments())
|
||||||
|
{
|
||||||
|
if(pData->CheckReadOnly())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const ColorHSLA Color = pResult->GetColor(0, pData->m_Light);
|
||||||
|
const unsigned Value = Color.Pack(pData->m_Light ? 0.5f : 0.0f, pData->m_Alpha);
|
||||||
|
|
||||||
|
*pData->m_pVariable = Value;
|
||||||
|
if(pResult->m_ClientID != IConsole::CLIENT_ID_GAME)
|
||||||
|
pData->m_OldValue = Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char aBuf[256];
|
||||||
|
str_format(aBuf, sizeof(aBuf), "Value: %u", *pData->m_pVariable);
|
||||||
|
pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "config", aBuf);
|
||||||
|
|
||||||
|
ColorHSLA Hsla = ColorHSLA(*pData->m_pVariable, true);
|
||||||
|
if(pData->m_Light)
|
||||||
|
Hsla = Hsla.UnclampLighting();
|
||||||
|
str_format(aBuf, sizeof(aBuf), "H: %d°, S: %d%%, L: %d%%", round_truncate(Hsla.h * 360), round_truncate(Hsla.s * 100), round_truncate(Hsla.l * 100));
|
||||||
|
pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "config", aBuf);
|
||||||
|
|
||||||
|
const ColorRGBA Rgba = color_cast<ColorRGBA>(Hsla);
|
||||||
|
str_format(aBuf, sizeof(aBuf), "R: %d, G: %d, B: %d, #%06X", round_truncate(Rgba.r * 255), round_truncate(Rgba.g * 255), round_truncate(Rgba.b * 255), Rgba.Pack(false));
|
||||||
|
pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "config", aBuf);
|
||||||
|
|
||||||
|
if(pData->m_Alpha)
|
||||||
|
{
|
||||||
|
str_format(aBuf, sizeof(aBuf), "A: %d%%", round_truncate(Hsla.a * 100));
|
||||||
|
pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "config", aBuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Register() override
|
||||||
|
{
|
||||||
|
m_pConsole->Register(m_pScriptName, "?i", m_Flags, CommandCallback, this, m_pHelp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDefault() const override
|
||||||
|
{
|
||||||
|
return *m_pVariable == m_Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(char *pOut, size_t Size, unsigned Value) const
|
||||||
|
{
|
||||||
|
str_format(pOut, Size, "%s %u", m_pScriptName, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(char *pOut, size_t Size) const override
|
||||||
|
{
|
||||||
|
Serialize(pOut, Size, *m_pVariable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetValue(unsigned Value)
|
||||||
|
{
|
||||||
|
if(CheckReadOnly())
|
||||||
|
return;
|
||||||
|
char aBuf[IConsole::CMDLINE_LENGTH];
|
||||||
|
Serialize(aBuf, sizeof(aBuf), Value);
|
||||||
|
ExecuteLine(aBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetToDefault() override
|
||||||
|
{
|
||||||
|
SetValue(m_Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetToOld() override
|
||||||
|
{
|
||||||
|
SetValue(m_OldValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SStringConfigVariable : public SConfigVariable
|
||||||
|
{
|
||||||
|
char *m_pStr;
|
||||||
|
const char *m_pDefault;
|
||||||
|
size_t m_MaxSize;
|
||||||
|
char *m_pOldValue;
|
||||||
|
|
||||||
|
SStringConfigVariable(IConsole *pConsole, const char *pScriptName, EVariableType Type, int Flags, const char *pHelp, char *pStr, const char *pDefault, size_t MaxSize, char *pOldValue) :
|
||||||
|
SConfigVariable(pConsole, pScriptName, Type, Flags, pHelp),
|
||||||
|
m_pStr(pStr),
|
||||||
|
m_pDefault(pDefault),
|
||||||
|
m_MaxSize(MaxSize),
|
||||||
|
m_pOldValue(pOldValue)
|
||||||
|
{
|
||||||
|
str_copy(m_pStr, m_pDefault, m_MaxSize);
|
||||||
|
str_copy(m_pOldValue, m_pDefault, m_MaxSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
~SStringConfigVariable() override = default;
|
||||||
|
|
||||||
|
static void CommandCallback(IConsole::IResult *pResult, void *pUserData)
|
||||||
|
{
|
||||||
|
SStringConfigVariable *pData = static_cast<SStringConfigVariable *>(pUserData);
|
||||||
|
|
||||||
|
if(pResult->NumArguments())
|
||||||
|
{
|
||||||
|
if(pData->CheckReadOnly())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char *pString = pResult->GetString(0);
|
||||||
|
if(!str_utf8_check(pString))
|
||||||
|
{
|
||||||
|
char aTemp[4];
|
||||||
|
size_t Length = 0;
|
||||||
|
while(*pString)
|
||||||
|
{
|
||||||
|
size_t Size = str_utf8_encode(aTemp, static_cast<unsigned char>(*pString++));
|
||||||
|
if(Length + Size < pData->m_MaxSize)
|
||||||
|
{
|
||||||
|
mem_copy(pData->m_pStr + Length, aTemp, Size);
|
||||||
|
Length += Size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pData->m_pStr[Length] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
str_copy(pData->m_pStr, pString, pData->m_MaxSize);
|
||||||
|
|
||||||
|
if(pResult->m_ClientID != IConsole::CLIENT_ID_GAME)
|
||||||
|
str_copy(pData->m_pOldValue, pData->m_pStr, pData->m_MaxSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char aBuf[1024];
|
||||||
|
str_format(aBuf, sizeof(aBuf), "Value: %s", pData->m_pStr);
|
||||||
|
pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "config", aBuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Register() override
|
||||||
|
{
|
||||||
|
m_pConsole->Register(m_pScriptName, "?r", m_Flags, CommandCallback, this, m_pHelp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDefault() const override
|
||||||
|
{
|
||||||
|
return str_comp(m_pStr, m_pDefault) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(char *pOut, size_t Size, const char *pValue) const
|
||||||
|
{
|
||||||
|
str_copy(pOut, m_pScriptName, Size);
|
||||||
|
str_append(pOut, " \"", Size);
|
||||||
|
const int OutLen = str_length(pOut);
|
||||||
|
EscapeParam(pOut + OutLen, pValue, Size - OutLen - 1); // -1 to ensure space for final quote
|
||||||
|
str_append(pOut, "\"", Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serialize(char *pOut, size_t Size) const override
|
||||||
|
{
|
||||||
|
Serialize(pOut, Size, m_pStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetValue(const char *pValue)
|
||||||
|
{
|
||||||
|
if(CheckReadOnly())
|
||||||
|
return;
|
||||||
|
char aBuf[2048];
|
||||||
|
Serialize(aBuf, sizeof(aBuf), pValue);
|
||||||
|
ExecuteLine(aBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetToDefault() override
|
||||||
|
{
|
||||||
|
SetValue(m_pDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetToOld() override
|
||||||
|
{
|
||||||
|
SetValue(m_pOldValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
CConfigManager::CConfigManager()
|
CConfigManager::CConfigManager()
|
||||||
{
|
{
|
||||||
m_pStorage = 0;
|
m_pConsole = nullptr;
|
||||||
|
m_pStorage = nullptr;
|
||||||
m_ConfigFile = 0;
|
m_ConfigFile = 0;
|
||||||
m_NumCallbacks = 0;
|
|
||||||
m_Failed = false;
|
m_Failed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConfigManager::Init()
|
void CConfigManager::Init()
|
||||||
{
|
{
|
||||||
|
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
||||||
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CConfigManager::Reset()
|
const auto &&AddVariable = [this](SConfigVariable *pVariable) {
|
||||||
{
|
m_vpAllVariables.push_back(pVariable);
|
||||||
#define MACRO_CONFIG_INT(Name, ScriptName, def, min, max, flags, desc) g_Config.m_##Name = def;
|
if((pVariable->m_Flags & CFGFLAG_GAME) != 0)
|
||||||
#define MACRO_CONFIG_COL(Name, ScriptName, def, flags, desc) MACRO_CONFIG_INT(Name, ScriptName, def, 0, 0, flags, desc)
|
m_vpGameVariables.push_back(pVariable);
|
||||||
#define MACRO_CONFIG_STR(Name, ScriptName, len, def, flags, desc) str_copy(g_Config.m_##Name, def, len);
|
pVariable->Register();
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MACRO_CONFIG_INT(Name, ScriptName, Def, Min, Max, Flags, Desc) \
|
||||||
|
{ \
|
||||||
|
const char *pHelp = Min == Max ? Desc " (default: " #Def ")" : Max == 0 ? Desc " (default: " #Def ", min: " #Min ")" : Desc " (default: " #Def ", min: " #Min ", max: " #Max ")"; \
|
||||||
|
AddVariable(m_ConfigHeap.Allocate<SIntConfigVariable>(m_pConsole, #ScriptName, SConfigVariable::VAR_INT, Flags, pHelp, &g_Config.m_##Name, Def, Min, Max)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MACRO_CONFIG_COL(Name, ScriptName, Def, Flags, Desc) \
|
||||||
|
{ \
|
||||||
|
const size_t HelpSize = (size_t)str_length(Desc) + 32; \
|
||||||
|
char *pHelp = static_cast<char *>(m_ConfigHeap.Allocate(HelpSize)); \
|
||||||
|
const bool Alpha = ((Flags)&CFGFLAG_COLALPHA) != 0; \
|
||||||
|
str_format(pHelp, HelpSize, "%s (default: $%0*X)", Desc, Alpha ? 8 : 6, color_cast<ColorRGBA>(ColorHSLA(Def, Alpha)).Pack(Alpha)); \
|
||||||
|
AddVariable(m_ConfigHeap.Allocate<SColorConfigVariable>(m_pConsole, #ScriptName, SConfigVariable::VAR_COLOR, Flags, pHelp, &g_Config.m_##Name, Def)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MACRO_CONFIG_STR(Name, ScriptName, Len, Def, Flags, Desc) \
|
||||||
|
{ \
|
||||||
|
const size_t HelpSize = (size_t)str_length(Desc) + str_length(Def) + 64; \
|
||||||
|
char *pHelp = static_cast<char *>(m_ConfigHeap.Allocate(HelpSize)); \
|
||||||
|
str_format(pHelp, HelpSize, "%s (default: \"%s\", max length: %d)", Desc, Def, Len - 1); \
|
||||||
|
char *pOldValue = static_cast<char *>(m_ConfigHeap.Allocate(Len)); \
|
||||||
|
AddVariable(m_ConfigHeap.Allocate<SStringConfigVariable>(m_pConsole, #ScriptName, SConfigVariable::VAR_STRING, Flags, pHelp, g_Config.m_##Name, Def, Len, pOldValue)); \
|
||||||
|
}
|
||||||
|
|
||||||
#include "config_variables.h"
|
#include "config_variables.h"
|
||||||
|
|
||||||
#undef MACRO_CONFIG_INT
|
#undef MACRO_CONFIG_INT
|
||||||
#undef MACRO_CONFIG_COL
|
#undef MACRO_CONFIG_COL
|
||||||
#undef MACRO_CONFIG_STR
|
#undef MACRO_CONFIG_STR
|
||||||
|
|
||||||
|
m_pConsole->Register("reset", "s[config-name]", CFGFLAG_SERVER | CFGFLAG_CLIENT | CFGFLAG_STORE, Con_Reset, this, "Reset a config to its default value");
|
||||||
|
m_pConsole->Register("toggle", "s[config-option] i[value 1] i[value 2]", CFGFLAG_SERVER | CFGFLAG_CLIENT, Con_Toggle, this, "Toggle config value");
|
||||||
|
m_pConsole->Register("+toggle", "s[config-option] i[value 1] i[value 2]", CFGFLAG_CLIENT, Con_ToggleStroke, this, "Toggle config value via keypress");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConfigManager::Reset(const char *pScriptName)
|
void CConfigManager::Reset(const char *pScriptName)
|
||||||
{
|
{
|
||||||
#define MACRO_CONFIG_INT(Name, ScriptName, def, min, max, flags, desc) \
|
for(SConfigVariable *pVariable : m_vpAllVariables)
|
||||||
if(str_comp(pScriptName, #ScriptName) == 0) \
|
{
|
||||||
{ \
|
if((pVariable->m_Flags & m_pConsole->FlagMask()) != 0 && str_comp(pScriptName, pVariable->m_pScriptName) == 0)
|
||||||
g_Config.m_##Name = def; \
|
{
|
||||||
return; \
|
pVariable->ResetToDefault();
|
||||||
};
|
return;
|
||||||
#define MACRO_CONFIG_COL(Name, ScriptName, def, flags, desc) MACRO_CONFIG_INT(Name, ScriptName, def, 0, 0, flags, desc)
|
}
|
||||||
#define MACRO_CONFIG_STR(Name, ScriptName, len, def, flags, desc) \
|
}
|
||||||
if(str_comp(pScriptName, #ScriptName) == 0) \
|
|
||||||
{ \
|
|
||||||
str_copy(g_Config.m_##Name, def, len); \
|
|
||||||
return; \
|
|
||||||
};
|
|
||||||
|
|
||||||
#include "config_variables.h"
|
char aBuf[IConsole::CMDLINE_LENGTH + 32];
|
||||||
|
str_format(aBuf, sizeof(aBuf), "Invalid command: '%s'.", pScriptName);
|
||||||
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "config", aBuf);
|
||||||
|
}
|
||||||
|
|
||||||
#undef MACRO_CONFIG_INT
|
void CConfigManager::ResetGameSettings()
|
||||||
#undef MACRO_CONFIG_COL
|
{
|
||||||
#undef MACRO_CONFIG_STR
|
for(SConfigVariable *pVariable : m_vpGameVariables)
|
||||||
|
{
|
||||||
|
pVariable->ResetToOld();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConfigManager::SetReadOnly(const char *pScriptName, bool ReadOnly)
|
||||||
|
{
|
||||||
|
for(SConfigVariable *pVariable : m_vpAllVariables)
|
||||||
|
{
|
||||||
|
if(str_comp(pScriptName, pVariable->m_pScriptName) == 0)
|
||||||
|
{
|
||||||
|
pVariable->m_ReadOnly = ReadOnly;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char aBuf[IConsole::CMDLINE_LENGTH + 32];
|
||||||
|
str_format(aBuf, sizeof(aBuf), "Invalid command for SetReadOnly: '%s'", pScriptName);
|
||||||
|
dbg_assert(false, aBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CConfigManager::Save()
|
bool CConfigManager::Save()
|
||||||
|
@ -72,47 +470,30 @@ bool CConfigManager::Save()
|
||||||
|
|
||||||
if(!m_ConfigFile)
|
if(!m_ConfigFile)
|
||||||
{
|
{
|
||||||
dbg_msg("config", "ERROR: opening %s failed", aConfigFileTmp);
|
log_error("config", "ERROR: opening %s failed", aConfigFileTmp);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Failed = false;
|
m_Failed = false;
|
||||||
|
|
||||||
char aLineBuf[1024 * 2];
|
char aLineBuf[2048];
|
||||||
char aEscapeBuf[1024 * 2];
|
for(const SConfigVariable *pVariable : m_vpAllVariables)
|
||||||
|
|
||||||
#define MACRO_CONFIG_INT(Name, ScriptName, def, min, max, flags, desc) \
|
|
||||||
if((flags)&CFGFLAG_SAVE && g_Config.m_##Name != (def)) \
|
|
||||||
{ \
|
|
||||||
str_format(aLineBuf, sizeof(aLineBuf), "%s %i", #ScriptName, g_Config.m_##Name); \
|
|
||||||
WriteLine(aLineBuf); \
|
|
||||||
}
|
|
||||||
#define MACRO_CONFIG_COL(Name, ScriptName, def, flags, desc) \
|
|
||||||
if((flags)&CFGFLAG_SAVE && g_Config.m_##Name != (def)) \
|
|
||||||
{ \
|
|
||||||
str_format(aLineBuf, sizeof(aLineBuf), "%s %u", #ScriptName, g_Config.m_##Name); \
|
|
||||||
WriteLine(aLineBuf); \
|
|
||||||
}
|
|
||||||
#define MACRO_CONFIG_STR(Name, ScriptName, len, def, flags, desc) \
|
|
||||||
if((flags)&CFGFLAG_SAVE && str_comp(g_Config.m_##Name, def) != 0) \
|
|
||||||
{ \
|
|
||||||
EscapeParam(aEscapeBuf, g_Config.m_##Name, sizeof(aEscapeBuf)); \
|
|
||||||
str_format(aLineBuf, sizeof(aLineBuf), "%s \"%s\"", #ScriptName, aEscapeBuf); \
|
|
||||||
WriteLine(aLineBuf); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "config_variables.h"
|
|
||||||
|
|
||||||
#undef MACRO_CONFIG_INT
|
|
||||||
#undef MACRO_CONFIG_COL
|
|
||||||
#undef MACRO_CONFIG_STR
|
|
||||||
|
|
||||||
for(int i = 0; i < m_NumCallbacks; i++)
|
|
||||||
m_aCallbacks[i].m_pfnFunc(this, m_aCallbacks[i].m_pUserData);
|
|
||||||
|
|
||||||
for(const auto &Command : m_vUnknownCommands)
|
|
||||||
{
|
{
|
||||||
WriteLine(Command.c_str());
|
if((pVariable->m_Flags & CFGFLAG_SAVE) != 0 && !pVariable->IsDefault())
|
||||||
|
{
|
||||||
|
pVariable->Serialize(aLineBuf, sizeof(aLineBuf));
|
||||||
|
WriteLine(aLineBuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto &Callback : m_vCallbacks)
|
||||||
|
{
|
||||||
|
Callback.m_pfnFunc(this, Callback.m_pUserData);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const char *pCommand : m_vpUnknownCommands)
|
||||||
|
{
|
||||||
|
WriteLine(pCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(io_sync(m_ConfigFile) != 0)
|
if(io_sync(m_ConfigFile) != 0)
|
||||||
|
@ -127,13 +508,13 @@ bool CConfigManager::Save()
|
||||||
|
|
||||||
if(m_Failed)
|
if(m_Failed)
|
||||||
{
|
{
|
||||||
dbg_msg("config", "ERROR: writing to %s failed", aConfigFileTmp);
|
log_error("config", "ERROR: writing to %s failed", aConfigFileTmp);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!m_pStorage->RenameFile(aConfigFileTmp, CONFIG_FILE, IStorage::TYPE_SAVE))
|
if(!m_pStorage->RenameFile(aConfigFileTmp, CONFIG_FILE, IStorage::TYPE_SAVE))
|
||||||
{
|
{
|
||||||
dbg_msg("config", "ERROR: renaming %s to " CONFIG_FILE " failed", aConfigFileTmp);
|
log_error("config", "ERROR: renaming %s to " CONFIG_FILE " failed", aConfigFileTmp);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,10 +523,7 @@ bool CConfigManager::Save()
|
||||||
|
|
||||||
void CConfigManager::RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData)
|
void CConfigManager::RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData)
|
||||||
{
|
{
|
||||||
dbg_assert(m_NumCallbacks < MAX_CALLBACKS, "too many config callbacks");
|
m_vCallbacks.emplace_back(pfnFunc, pUserData);
|
||||||
m_aCallbacks[m_NumCallbacks].m_pfnFunc = pfnFunc;
|
|
||||||
m_aCallbacks[m_NumCallbacks].m_pUserData = pUserData;
|
|
||||||
m_NumCallbacks++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConfigManager::WriteLine(const char *pLine)
|
void CConfigManager::WriteLine(const char *pLine)
|
||||||
|
@ -160,7 +538,76 @@ void CConfigManager::WriteLine(const char *pLine)
|
||||||
|
|
||||||
void CConfigManager::StoreUnknownCommand(const char *pCommand)
|
void CConfigManager::StoreUnknownCommand(const char *pCommand)
|
||||||
{
|
{
|
||||||
m_vUnknownCommands.emplace_back(pCommand);
|
m_vpUnknownCommands.push_back(m_ConfigHeap.StoreString(pCommand));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConfigManager::Con_Reset(IConsole::IResult *pResult, void *pUserData)
|
||||||
|
{
|
||||||
|
static_cast<CConfigManager *>(pUserData)->Reset(pResult->GetString(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConfigManager::Con_Toggle(IConsole::IResult *pResult, void *pUserData)
|
||||||
|
{
|
||||||
|
CConfigManager *pConfigManager = static_cast<CConfigManager *>(pUserData);
|
||||||
|
IConsole *pConsole = pConfigManager->m_pConsole;
|
||||||
|
|
||||||
|
const char *pScriptName = pResult->GetString(0);
|
||||||
|
for(SConfigVariable *pVariable : pConfigManager->m_vpAllVariables)
|
||||||
|
{
|
||||||
|
if((pVariable->m_Flags & pConsole->FlagMask()) == 0 ||
|
||||||
|
str_comp(pScriptName, pVariable->m_pScriptName) != 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pVariable->m_Type == SConfigVariable::VAR_INT)
|
||||||
|
{
|
||||||
|
SIntConfigVariable *pIntVariable = static_cast<SIntConfigVariable *>(pVariable);
|
||||||
|
pIntVariable->SetValue(*pIntVariable->m_pVariable == pResult->GetInteger(1) ? pResult->GetInteger(2) : pResult->GetInteger(1));
|
||||||
|
}
|
||||||
|
else if(pVariable->m_Type == SConfigVariable::VAR_COLOR)
|
||||||
|
{
|
||||||
|
SColorConfigVariable *pColorVariable = static_cast<SColorConfigVariable *>(pVariable);
|
||||||
|
const float Darkest = pColorVariable->m_Light ? 0.5f : 0.0f;
|
||||||
|
const ColorHSLA Value = *pColorVariable->m_pVariable == pResult->GetColor(1, pColorVariable->m_Light).Pack(Darkest, pColorVariable->m_Alpha) ? pResult->GetColor(2, pColorVariable->m_Light) : pResult->GetColor(1, pColorVariable->m_Light);
|
||||||
|
pColorVariable->SetValue(Value.Pack(Darkest, pColorVariable->m_Alpha));
|
||||||
|
}
|
||||||
|
else if(pVariable->m_Type == SConfigVariable::VAR_STRING)
|
||||||
|
{
|
||||||
|
SStringConfigVariable *pStringVariable = static_cast<SStringConfigVariable *>(pVariable);
|
||||||
|
pStringVariable->SetValue(str_comp(pStringVariable->m_pStr, pResult->GetString(1)) == 0 ? pResult->GetString(2) : pResult->GetString(1));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char aBuf[IConsole::CMDLINE_LENGTH + 32];
|
||||||
|
str_format(aBuf, sizeof(aBuf), "Invalid command: '%s'.", pScriptName);
|
||||||
|
pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "config", aBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CConfigManager::Con_ToggleStroke(IConsole::IResult *pResult, void *pUserData)
|
||||||
|
{
|
||||||
|
CConfigManager *pConfigManager = static_cast<CConfigManager *>(pUserData);
|
||||||
|
IConsole *pConsole = pConfigManager->m_pConsole;
|
||||||
|
|
||||||
|
const char *pScriptName = pResult->GetString(1);
|
||||||
|
for(SConfigVariable *pVariable : pConfigManager->m_vpAllVariables)
|
||||||
|
{
|
||||||
|
if((pVariable->m_Flags & pConsole->FlagMask()) == 0 ||
|
||||||
|
pVariable->m_Type != SConfigVariable::VAR_INT ||
|
||||||
|
str_comp(pScriptName, pVariable->m_pScriptName) != 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SIntConfigVariable *pIntVariable = static_cast<SIntConfigVariable *>(pVariable);
|
||||||
|
pIntVariable->SetValue(pResult->GetInteger(0) == 0 ? pResult->GetInteger(3) : pResult->GetInteger(2));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char aBuf[IConsole::CMDLINE_LENGTH + 32];
|
||||||
|
str_format(aBuf, sizeof(aBuf), "Invalid command: '%s'.", pScriptName);
|
||||||
|
pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "config", aBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
IConfigManager *CreateConfigManager() { return new CConfigManager; }
|
IConfigManager *CreateConfigManager() { return new CConfigManager; }
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
#define ENGINE_SHARED_CONFIG_H
|
#define ENGINE_SHARED_CONFIG_H
|
||||||
|
|
||||||
#include <base/detect.h>
|
#include <base/detect.h>
|
||||||
#include <engine/config.h>
|
|
||||||
|
|
||||||
#include <string>
|
#include <engine/config.h>
|
||||||
|
#include <engine/console.h>
|
||||||
|
#include <engine/shared/memheap.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// include protocol for MAX_CLIENT used in config_variables
|
// include protocol for MAX_CLIENT used in config_variables
|
||||||
|
@ -20,13 +22,13 @@
|
||||||
class CConfig
|
class CConfig
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
#define MACRO_CONFIG_INT(Name, ScriptName, Def, Min, Max, Save, Desc) \
|
#define MACRO_CONFIG_INT(Name, ScriptName, Def, Min, Max, Flags, Desc) \
|
||||||
static constexpr int ms_##Name = Def; \
|
static constexpr int ms_##Name = Def; \
|
||||||
int m_##Name;
|
int m_##Name;
|
||||||
#define MACRO_CONFIG_COL(Name, ScriptName, Def, Save, Desc) \
|
#define MACRO_CONFIG_COL(Name, ScriptName, Def, Flags, Desc) \
|
||||||
static constexpr unsigned ms_##Name = Def; \
|
static constexpr unsigned ms_##Name = Def; \
|
||||||
unsigned m_##Name;
|
unsigned m_##Name;
|
||||||
#define MACRO_CONFIG_STR(Name, ScriptName, Len, Def, Save, Desc) \
|
#define MACRO_CONFIG_STR(Name, ScriptName, Len, Def, Flags, Desc) \
|
||||||
static constexpr const char *ms_p##Name = Def; \
|
static constexpr const char *ms_p##Name = Def; \
|
||||||
char m_##Name[Len]; // Flawfinder: ignore
|
char m_##Name[Len]; // Flawfinder: ignore
|
||||||
#include "config_variables.h"
|
#include "config_variables.h"
|
||||||
|
@ -58,31 +60,41 @@ enum
|
||||||
|
|
||||||
class CConfigManager : public IConfigManager
|
class CConfigManager : public IConfigManager
|
||||||
{
|
{
|
||||||
enum
|
IConsole *m_pConsole;
|
||||||
{
|
class IStorage *m_pStorage;
|
||||||
MAX_CALLBACKS = 16
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CCallback
|
IOHANDLE m_ConfigFile;
|
||||||
|
bool m_Failed;
|
||||||
|
|
||||||
|
struct SCallback
|
||||||
{
|
{
|
||||||
SAVECALLBACKFUNC m_pfnFunc;
|
SAVECALLBACKFUNC m_pfnFunc;
|
||||||
void *m_pUserData;
|
void *m_pUserData;
|
||||||
|
|
||||||
|
SCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) :
|
||||||
|
m_pfnFunc(pfnFunc),
|
||||||
|
m_pUserData(pUserData)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
std::vector<SCallback> m_vCallbacks;
|
||||||
|
|
||||||
class IStorage *m_pStorage;
|
std::vector<struct SConfigVariable *> m_vpAllVariables;
|
||||||
IOHANDLE m_ConfigFile;
|
std::vector<struct SConfigVariable *> m_vpGameVariables;
|
||||||
bool m_Failed;
|
std::vector<const char *> m_vpUnknownCommands;
|
||||||
CCallback m_aCallbacks[MAX_CALLBACKS];
|
CHeap m_ConfigHeap;
|
||||||
int m_NumCallbacks;
|
|
||||||
|
|
||||||
std::vector<std::string> m_vUnknownCommands;
|
static void Con_Reset(IConsole::IResult *pResult, void *pUserData);
|
||||||
|
static void Con_Toggle(IConsole::IResult *pResult, void *pUserData);
|
||||||
|
static void Con_ToggleStroke(IConsole::IResult *pResult, void *pUserData);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CConfigManager();
|
CConfigManager();
|
||||||
|
|
||||||
void Init() override;
|
void Init() override;
|
||||||
void Reset() override;
|
|
||||||
void Reset(const char *pScriptName) override;
|
void Reset(const char *pScriptName) override;
|
||||||
|
void ResetGameSettings() override;
|
||||||
|
void SetReadOnly(const char *pScriptName, bool ReadOnly) override;
|
||||||
bool Save() override;
|
bool Save() override;
|
||||||
CConfig *Values() override { return &g_Config; }
|
CConfig *Values() override { return &g_Config; }
|
||||||
|
|
||||||
|
|
|
@ -459,7 +459,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID, bo
|
||||||
{
|
{
|
||||||
if(Stroke)
|
if(Stroke)
|
||||||
{
|
{
|
||||||
char aBuf[96];
|
char aBuf[CMDLINE_LENGTH + 64];
|
||||||
str_format(aBuf, sizeof(aBuf), "Command '%s' cannot be executed from a map.", Result.m_pCommand);
|
str_format(aBuf, sizeof(aBuf), "Command '%s' cannot be executed from a map.", Result.m_pCommand);
|
||||||
Print(OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
Print(OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
||||||
}
|
}
|
||||||
|
@ -468,7 +468,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID, bo
|
||||||
{
|
{
|
||||||
if(Stroke)
|
if(Stroke)
|
||||||
{
|
{
|
||||||
char aBuf[96];
|
char aBuf[CMDLINE_LENGTH + 64];
|
||||||
str_format(aBuf, sizeof(aBuf), "Command '%s' cannot be executed from a non-map config file.", Result.m_pCommand);
|
str_format(aBuf, sizeof(aBuf), "Command '%s' cannot be executed from a non-map config file.", Result.m_pCommand);
|
||||||
Print(OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
Print(OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
||||||
str_format(aBuf, sizeof(aBuf), "Hint: Put the command in '%s.cfg' instead of '%s.map.cfg' ", g_Config.m_SvMap, g_Config.m_SvMap);
|
str_format(aBuf, sizeof(aBuf), "Hint: Put the command in '%s.cfg' instead of '%s.map.cfg' ", g_Config.m_SvMap, g_Config.m_SvMap);
|
||||||
|
@ -489,8 +489,8 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID, bo
|
||||||
{
|
{
|
||||||
if(ParseArgs(&Result, pCommand->m_pParams))
|
if(ParseArgs(&Result, pCommand->m_pParams))
|
||||||
{
|
{
|
||||||
char aBuf[256];
|
char aBuf[TEMPCMD_NAME_LENGTH + TEMPCMD_PARAMS_LENGTH + 32];
|
||||||
str_format(aBuf, sizeof(aBuf), "Invalid arguments... Usage: %s %s", pCommand->m_pName, pCommand->m_pParams);
|
str_format(aBuf, sizeof(aBuf), "Invalid arguments. Usage: %s %s", pCommand->m_pName, pCommand->m_pParams);
|
||||||
Print(OUTPUT_LEVEL_STANDARD, "chatresp", aBuf);
|
Print(OUTPUT_LEVEL_STANDARD, "chatresp", aBuf);
|
||||||
}
|
}
|
||||||
else if(m_StoreCommands && pCommand->m_Flags & CFGFLAG_STORE)
|
else if(m_StoreCommands && pCommand->m_Flags & CFGFLAG_STORE)
|
||||||
|
@ -532,7 +532,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID, bo
|
||||||
}
|
}
|
||||||
else if(Stroke)
|
else if(Stroke)
|
||||||
{
|
{
|
||||||
char aBuf[256];
|
char aBuf[CMDLINE_LENGTH + 32];
|
||||||
str_format(aBuf, sizeof(aBuf), "Access for command %s denied.", Result.m_pCommand);
|
str_format(aBuf, sizeof(aBuf), "Access for command %s denied.", Result.m_pCommand);
|
||||||
Print(OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
Print(OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
||||||
}
|
}
|
||||||
|
@ -543,7 +543,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID, bo
|
||||||
// ends at the first whitespace, which breaks for unknown commands (filenames) containing spaces.
|
// ends at the first whitespace, which breaks for unknown commands (filenames) containing spaces.
|
||||||
if(!m_pfnUnknownCommandCallback(pStr, m_pUnknownCommandUserdata))
|
if(!m_pfnUnknownCommandCallback(pStr, m_pUnknownCommandUserdata))
|
||||||
{
|
{
|
||||||
char aBuf[512 + 32];
|
char aBuf[CMDLINE_LENGTH + 32];
|
||||||
str_format(aBuf, sizeof(aBuf), "No such command: %s.", Result.m_pCommand);
|
str_format(aBuf, sizeof(aBuf), "No such command: %s.", Result.m_pCommand);
|
||||||
Print(OUTPUT_LEVEL_STANDARD, "chatresp", aBuf);
|
Print(OUTPUT_LEVEL_STANDARD, "chatresp", aBuf);
|
||||||
}
|
}
|
||||||
|
@ -655,15 +655,10 @@ void CConsole::Con_Exec(IResult *pResult, void *pUserData)
|
||||||
((CConsole *)pUserData)->ExecuteFile(pResult->GetString(0), -1, true, IStorage::TYPE_ALL);
|
((CConsole *)pUserData)->ExecuteFile(pResult->GetString(0), -1, true, IStorage::TYPE_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConsole::Con_Reset(IResult *pResult, void *pUserData)
|
|
||||||
{
|
|
||||||
((CConsole *)pUserData)->ConfigManager()->Reset(pResult->GetString(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CConsole::ConCommandAccess(IResult *pResult, void *pUser)
|
void CConsole::ConCommandAccess(IResult *pResult, void *pUser)
|
||||||
{
|
{
|
||||||
CConsole *pConsole = static_cast<CConsole *>(pUser);
|
CConsole *pConsole = static_cast<CConsole *>(pUser);
|
||||||
char aBuf[128];
|
char aBuf[CMDLINE_LENGTH + 64];
|
||||||
CCommand *pCommand = pConsole->FindCommand(pResult->GetString(0), CFGFLAG_SERVER);
|
CCommand *pCommand = pConsole->FindCommand(pResult->GetString(0), CFGFLAG_SERVER);
|
||||||
if(pCommand)
|
if(pCommand)
|
||||||
{
|
{
|
||||||
|
@ -738,136 +733,6 @@ void CConsole::ConUserCommandStatus(IResult *pResult, void *pUser)
|
||||||
pConsole->ConCommandStatus(&Result, pConsole);
|
pConsole->ConCommandStatus(&Result, pConsole);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CIntVariableData
|
|
||||||
{
|
|
||||||
IConsole *m_pConsole;
|
|
||||||
int *m_pVariable;
|
|
||||||
int m_Min;
|
|
||||||
int m_Max;
|
|
||||||
int m_OldValue;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CColVariableData
|
|
||||||
{
|
|
||||||
IConsole *m_pConsole;
|
|
||||||
unsigned *m_pVariable;
|
|
||||||
bool m_Light;
|
|
||||||
bool m_Alpha;
|
|
||||||
unsigned m_OldValue;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CStrVariableData
|
|
||||||
{
|
|
||||||
IConsole *m_pConsole;
|
|
||||||
char *m_pStr;
|
|
||||||
int m_MaxSize;
|
|
||||||
char *m_pOldValue;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void IntVariableCommand(IConsole::IResult *pResult, void *pUserData)
|
|
||||||
{
|
|
||||||
CIntVariableData *pData = (CIntVariableData *)pUserData;
|
|
||||||
|
|
||||||
if(pResult->NumArguments())
|
|
||||||
{
|
|
||||||
int Val = pResult->GetInteger(0);
|
|
||||||
|
|
||||||
// do clamping
|
|
||||||
if(pData->m_Min != pData->m_Max)
|
|
||||||
{
|
|
||||||
if(Val < pData->m_Min)
|
|
||||||
Val = pData->m_Min;
|
|
||||||
if(pData->m_Max != 0 && Val > pData->m_Max)
|
|
||||||
Val = pData->m_Max;
|
|
||||||
}
|
|
||||||
|
|
||||||
*(pData->m_pVariable) = Val;
|
|
||||||
if(pResult->m_ClientID != IConsole::CLIENT_ID_GAME)
|
|
||||||
pData->m_OldValue = Val;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char aBuf[32];
|
|
||||||
str_format(aBuf, sizeof(aBuf), "Value: %d", *(pData->m_pVariable));
|
|
||||||
pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ColVariableCommand(IConsole::IResult *pResult, void *pUserData)
|
|
||||||
{
|
|
||||||
CColVariableData *pData = (CColVariableData *)pUserData;
|
|
||||||
|
|
||||||
if(pResult->NumArguments())
|
|
||||||
{
|
|
||||||
ColorHSLA Col = pResult->GetColor(0, pData->m_Light);
|
|
||||||
int Val = Col.Pack(pData->m_Light ? 0.5f : 0.0f, pData->m_Alpha);
|
|
||||||
|
|
||||||
*(pData->m_pVariable) = Val;
|
|
||||||
if(pResult->m_ClientID != IConsole::CLIENT_ID_GAME)
|
|
||||||
pData->m_OldValue = Val;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char aBuf[256];
|
|
||||||
str_format(aBuf, sizeof(aBuf), "Value: %u", *(pData->m_pVariable));
|
|
||||||
pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
|
||||||
|
|
||||||
ColorHSLA Hsla(*(pData->m_pVariable), true);
|
|
||||||
if(pData->m_Light)
|
|
||||||
Hsla = Hsla.UnclampLighting();
|
|
||||||
str_format(aBuf, sizeof(aBuf), "H: %d°, S: %d%%, L: %d%%", round_truncate(Hsla.h * 360), round_truncate(Hsla.s * 100), round_truncate(Hsla.l * 100));
|
|
||||||
pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
|
||||||
|
|
||||||
ColorRGBA Rgba = color_cast<ColorRGBA>(Hsla);
|
|
||||||
str_format(aBuf, sizeof(aBuf), "R: %d, G: %d, B: %d, #%06X", round_truncate(Rgba.r * 255), round_truncate(Rgba.g * 255), round_truncate(Rgba.b * 255), Rgba.Pack(false));
|
|
||||||
pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
|
||||||
|
|
||||||
if(pData->m_Alpha)
|
|
||||||
{
|
|
||||||
str_format(aBuf, sizeof(aBuf), "A: %d%%", round_truncate(Hsla.a * 100));
|
|
||||||
pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StrVariableCommand(IConsole::IResult *pResult, void *pUserData)
|
|
||||||
{
|
|
||||||
CStrVariableData *pData = (CStrVariableData *)pUserData;
|
|
||||||
|
|
||||||
if(pResult->NumArguments())
|
|
||||||
{
|
|
||||||
const char *pString = pResult->GetString(0);
|
|
||||||
if(!str_utf8_check(pString))
|
|
||||||
{
|
|
||||||
char aTemp[4];
|
|
||||||
int Length = 0;
|
|
||||||
while(*pString)
|
|
||||||
{
|
|
||||||
int Size = str_utf8_encode(aTemp, static_cast<unsigned char>(*pString++));
|
|
||||||
if(Length + Size < pData->m_MaxSize)
|
|
||||||
{
|
|
||||||
mem_copy(pData->m_pStr + Length, aTemp, Size);
|
|
||||||
Length += Size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pData->m_pStr[Length] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
str_copy(pData->m_pStr, pString, pData->m_MaxSize);
|
|
||||||
|
|
||||||
if(pResult->m_ClientID != IConsole::CLIENT_ID_GAME)
|
|
||||||
str_copy(pData->m_pOldValue, pData->m_pStr, pData->m_MaxSize);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char aBuf[1024];
|
|
||||||
str_format(aBuf, sizeof(aBuf), "Value: %s", pData->m_pStr);
|
|
||||||
pData->m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CConsole::TraverseChain(FCommandCallback *ppfnCallback, void **ppUserData)
|
void CConsole::TraverseChain(FCommandCallback *ppfnCallback, void **ppUserData)
|
||||||
{
|
{
|
||||||
while(*ppfnCallback == Con_Chain)
|
while(*ppfnCallback == Con_Chain)
|
||||||
|
@ -878,85 +743,6 @@ void CConsole::TraverseChain(FCommandCallback *ppfnCallback, void **ppUserData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConsole::ConToggle(IConsole::IResult *pResult, void *pUser)
|
|
||||||
{
|
|
||||||
CConsole *pConsole = static_cast<CConsole *>(pUser);
|
|
||||||
char aBuf[512 + 32] = {0};
|
|
||||||
CCommand *pCommand = pConsole->FindCommand(pResult->GetString(0), pConsole->m_FlagMask);
|
|
||||||
if(pCommand)
|
|
||||||
{
|
|
||||||
FCommandCallback pfnCallback = pCommand->m_pfnCallback;
|
|
||||||
void *pUserData = pCommand->m_pUserData;
|
|
||||||
TraverseChain(&pfnCallback, &pUserData);
|
|
||||||
if(pfnCallback == IntVariableCommand)
|
|
||||||
{
|
|
||||||
CIntVariableData *pData = static_cast<CIntVariableData *>(pUserData);
|
|
||||||
int Val = *(pData->m_pVariable) == pResult->GetInteger(1) ? pResult->GetInteger(2) : pResult->GetInteger(1);
|
|
||||||
str_format(aBuf, sizeof(aBuf), "%s %i", pResult->GetString(0), Val);
|
|
||||||
pConsole->ExecuteLine(aBuf);
|
|
||||||
aBuf[0] = 0;
|
|
||||||
}
|
|
||||||
else if(pfnCallback == StrVariableCommand)
|
|
||||||
{
|
|
||||||
CStrVariableData *pData = static_cast<CStrVariableData *>(pUserData);
|
|
||||||
const char *pStr = !str_comp(pData->m_pStr, pResult->GetString(1)) ? pResult->GetString(2) : pResult->GetString(1);
|
|
||||||
str_format(aBuf, sizeof(aBuf), "%s \"", pResult->GetString(0));
|
|
||||||
char *pDst = aBuf + str_length(aBuf);
|
|
||||||
str_escape(&pDst, pStr, aBuf + sizeof(aBuf));
|
|
||||||
str_append(aBuf, "\"");
|
|
||||||
pConsole->ExecuteLine(aBuf);
|
|
||||||
aBuf[0] = 0;
|
|
||||||
}
|
|
||||||
else if(pfnCallback == ColVariableCommand)
|
|
||||||
{
|
|
||||||
CColVariableData *pData = static_cast<CColVariableData *>(pUserData);
|
|
||||||
bool Light = pData->m_Light;
|
|
||||||
float Darkest = Light ? 0.5f : 0.0f;
|
|
||||||
bool Alpha = pData->m_Alpha;
|
|
||||||
unsigned Cur = *pData->m_pVariable;
|
|
||||||
ColorHSLA Val = Cur == pResult->GetColor(1, Light).Pack(Darkest, Alpha) ? pResult->GetColor(2, Light) : pResult->GetColor(1, Light);
|
|
||||||
|
|
||||||
str_format(aBuf, sizeof(aBuf), "%s %u", pResult->GetString(0), Val.Pack(Darkest, Alpha));
|
|
||||||
pConsole->ExecuteLine(aBuf);
|
|
||||||
aBuf[0] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
str_format(aBuf, sizeof(aBuf), "Invalid command: '%s'.", pResult->GetString(0));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
str_format(aBuf, sizeof(aBuf), "No such command: '%s'.", pResult->GetString(0));
|
|
||||||
|
|
||||||
if(aBuf[0] != 0)
|
|
||||||
pConsole->Print(OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CConsole::ConToggleStroke(IConsole::IResult *pResult, void *pUser)
|
|
||||||
{
|
|
||||||
CConsole *pConsole = static_cast<CConsole *>(pUser);
|
|
||||||
char aBuf[512 + 32] = {0};
|
|
||||||
CCommand *pCommand = pConsole->FindCommand(pResult->GetString(1), pConsole->m_FlagMask);
|
|
||||||
if(pCommand)
|
|
||||||
{
|
|
||||||
FCommandCallback pfnCallback = pCommand->m_pfnCallback;
|
|
||||||
void *pUserData = pCommand->m_pUserData;
|
|
||||||
TraverseChain(&pfnCallback, &pUserData);
|
|
||||||
if(pfnCallback == IntVariableCommand)
|
|
||||||
{
|
|
||||||
int Val = pResult->GetInteger(0) == 0 ? pResult->GetInteger(3) : pResult->GetInteger(2);
|
|
||||||
str_format(aBuf, sizeof(aBuf), "%s %i", pResult->GetString(1), Val);
|
|
||||||
pConsole->ExecuteLine(aBuf);
|
|
||||||
aBuf[0] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
str_format(aBuf, sizeof(aBuf), "Invalid command: '%s'.", pResult->GetString(1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
str_format(aBuf, sizeof(aBuf), "No such command: '%s'.", pResult->GetString(1));
|
|
||||||
|
|
||||||
if(aBuf[0] != 0)
|
|
||||||
pConsole->Print(OUTPUT_LEVEL_STANDARD, "console", aBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
CConsole::CConsole(int FlagMask)
|
CConsole::CConsole(int FlagMask)
|
||||||
{
|
{
|
||||||
m_FlagMask = FlagMask;
|
m_FlagMask = FlagMask;
|
||||||
|
@ -977,10 +763,6 @@ CConsole::CConsole(int FlagMask)
|
||||||
// register some basic commands
|
// register some basic commands
|
||||||
Register("echo", "r[text]", CFGFLAG_SERVER, Con_Echo, this, "Echo the text");
|
Register("echo", "r[text]", CFGFLAG_SERVER, Con_Echo, this, "Echo the text");
|
||||||
Register("exec", "r[file]", CFGFLAG_SERVER | CFGFLAG_CLIENT, Con_Exec, this, "Execute the specified file");
|
Register("exec", "r[file]", CFGFLAG_SERVER | CFGFLAG_CLIENT, Con_Exec, this, "Execute the specified file");
|
||||||
Register("reset", "s[config-name]", CFGFLAG_SERVER | CFGFLAG_CLIENT | CFGFLAG_STORE, Con_Reset, this, "Reset a config to its default value");
|
|
||||||
|
|
||||||
Register("toggle", "s[config-option] i[value 1] i[value 2]", CFGFLAG_SERVER | CFGFLAG_CLIENT, ConToggle, this, "Toggle config value");
|
|
||||||
Register("+toggle", "s[config-option] i[value 1] i[value 2]", CFGFLAG_CLIENT, ConToggleStroke, this, "Toggle config value via keypress");
|
|
||||||
|
|
||||||
Register("access_level", "s[command] ?i[accesslevel]", CFGFLAG_SERVER, ConCommandAccess, this, "Specify command accessibility (admin = 0, moderator = 1, helper = 2, all = 3)");
|
Register("access_level", "s[command] ?i[accesslevel]", CFGFLAG_SERVER, ConCommandAccess, this, "Specify command accessibility (admin = 0, moderator = 1, helper = 2, all = 3)");
|
||||||
Register("access_status", "i[accesslevel]", CFGFLAG_SERVER, ConCommandStatus, this, "List all commands which are accessible for admin = 0, moderator = 1, helper = 2, all = 3");
|
Register("access_status", "i[accesslevel]", CFGFLAG_SERVER, ConCommandStatus, this, "List all commands which are accessible for admin = 0, moderator = 1, helper = 2, all = 3");
|
||||||
|
@ -1018,39 +800,7 @@ CConsole::~CConsole()
|
||||||
|
|
||||||
void CConsole::Init()
|
void CConsole::Init()
|
||||||
{
|
{
|
||||||
m_pConfigManager = Kernel()->RequestInterface<IConfigManager>();
|
|
||||||
m_pConfig = m_pConfigManager->Values();
|
|
||||||
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
||||||
|
|
||||||
// TODO: this should disappear
|
|
||||||
#define MACRO_CONFIG_INT(Name, ScriptName, Def, Min, Max, Flags, Desc) \
|
|
||||||
{ \
|
|
||||||
static CIntVariableData Data = {this, &g_Config.m_##Name, Min, Max, Def}; \
|
|
||||||
Register(#ScriptName, "?i", Flags, IntVariableCommand, &Data, \
|
|
||||||
Min == Max ? Desc " (default: " #Def ")" : Max == 0 ? Desc " (default: " #Def ", min: " #Min ")" : Desc " (default: " #Def ", min: " #Min ", max: " #Max ")"); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MACRO_CONFIG_COL(Name, ScriptName, Def, Flags, Desc) \
|
|
||||||
{ \
|
|
||||||
static CColVariableData Data = {this, &g_Config.m_##Name, static_cast<bool>((Flags)&CFGFLAG_COLLIGHT), \
|
|
||||||
static_cast<bool>((Flags)&CFGFLAG_COLALPHA), Def}; \
|
|
||||||
Register(#ScriptName, "?i", Flags, ColVariableCommand, &Data, Desc " (default: " #Def ")"); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MACRO_CONFIG_STR(Name, ScriptName, Len, Def, Flags, Desc) \
|
|
||||||
{ \
|
|
||||||
static char s_aOldValue[Len] = Def; \
|
|
||||||
static CStrVariableData Data = {this, g_Config.m_##Name, Len, s_aOldValue}; \
|
|
||||||
static char s_aHelp[256]; \
|
|
||||||
str_format(s_aHelp, sizeof(s_aHelp), "%s (default: \"%s\", max length: %d)", Desc, Def, Len - 1); \
|
|
||||||
Register(#ScriptName, "?r", Flags, StrVariableCommand, &Data, s_aHelp); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "config_variables.h"
|
|
||||||
|
|
||||||
#undef MACRO_CONFIG_INT
|
|
||||||
#undef MACRO_CONFIG_COL
|
|
||||||
#undef MACRO_CONFIG_STR
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConsole::ParseArguments(int NumArgs, const char **ppArguments)
|
void CConsole::ParseArguments(int NumArgs, const char **ppArguments)
|
||||||
|
@ -1274,54 +1024,6 @@ const IConsole::CCommandInfo *CConsole::GetCommandInfo(const char *pName, int Fl
|
||||||
|
|
||||||
std::unique_ptr<IConsole> CreateConsole(int FlagMask) { return std::make_unique<CConsole>(FlagMask); }
|
std::unique_ptr<IConsole> CreateConsole(int FlagMask) { return std::make_unique<CConsole>(FlagMask); }
|
||||||
|
|
||||||
void CConsole::ResetGameSettings()
|
|
||||||
{
|
|
||||||
#define MACRO_CONFIG_INT(Name, ScriptName, Def, Min, Max, Flags, Desc) \
|
|
||||||
{ \
|
|
||||||
if(((Flags)&CFGFLAG_GAME) == CFGFLAG_GAME) \
|
|
||||||
{ \
|
|
||||||
CCommand *pCommand = FindCommand(#ScriptName, CFGFLAG_GAME); \
|
|
||||||
void *pUserData = pCommand->m_pUserData; \
|
|
||||||
FCommandCallback pfnCallback = pCommand->m_pfnCallback; \
|
|
||||||
TraverseChain(&pfnCallback, &pUserData); \
|
|
||||||
CIntVariableData *pData = (CIntVariableData *)pUserData; \
|
|
||||||
*pData->m_pVariable = pData->m_OldValue; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MACRO_CONFIG_COL(Name, ScriptName, Def, Flags, Desc) \
|
|
||||||
{ \
|
|
||||||
if(((Flags)&CFGFLAG_GAME) == CFGFLAG_GAME) \
|
|
||||||
{ \
|
|
||||||
CCommand *pCommand = FindCommand(#ScriptName, CFGFLAG_GAME); \
|
|
||||||
void *pUserData = pCommand->m_pUserData; \
|
|
||||||
FCommandCallback pfnCallback = pCommand->m_pfnCallback; \
|
|
||||||
TraverseChain(&pfnCallback, &pUserData); \
|
|
||||||
CColVariableData *pData = (CColVariableData *)pUserData; \
|
|
||||||
*pData->m_pVariable = pData->m_OldValue; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MACRO_CONFIG_STR(Name, ScriptName, Len, Def, Flags, Desc) \
|
|
||||||
{ \
|
|
||||||
if(((Flags)&CFGFLAG_GAME) == CFGFLAG_GAME) \
|
|
||||||
{ \
|
|
||||||
CCommand *pCommand = FindCommand(#ScriptName, CFGFLAG_GAME); \
|
|
||||||
void *pUserData = pCommand->m_pUserData; \
|
|
||||||
FCommandCallback pfnCallback = pCommand->m_pfnCallback; \
|
|
||||||
TraverseChain(&pfnCallback, &pUserData); \
|
|
||||||
CStrVariableData *pData = (CStrVariableData *)pUserData; \
|
|
||||||
str_copy(pData->m_pStr, pData->m_pOldValue, pData->m_MaxSize); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "config_variables.h"
|
|
||||||
|
|
||||||
#undef MACRO_CONFIG_INT
|
|
||||||
#undef MACRO_CONFIG_COL
|
|
||||||
#undef MACRO_CONFIG_STR
|
|
||||||
}
|
|
||||||
|
|
||||||
int CConsole::CResult::GetVictim() const
|
int CConsole::CResult::GetVictim() const
|
||||||
{
|
{
|
||||||
return m_Victim;
|
return m_Victim;
|
||||||
|
|
|
@ -46,8 +46,6 @@ class CConsole : public IConsole
|
||||||
};
|
};
|
||||||
|
|
||||||
CExecFile *m_pFirstExec;
|
CExecFile *m_pFirstExec;
|
||||||
IConfigManager *m_pConfigManager;
|
|
||||||
CConfig *m_pConfig;
|
|
||||||
IStorage *m_pStorage;
|
IStorage *m_pStorage;
|
||||||
int m_AccessLevel;
|
int m_AccessLevel;
|
||||||
|
|
||||||
|
@ -59,9 +57,6 @@ class CConsole : public IConsole
|
||||||
static void Con_Chain(IResult *pResult, void *pUserData);
|
static void Con_Chain(IResult *pResult, void *pUserData);
|
||||||
static void Con_Echo(IResult *pResult, void *pUserData);
|
static void Con_Echo(IResult *pResult, void *pUserData);
|
||||||
static void Con_Exec(IResult *pResult, void *pUserData);
|
static void Con_Exec(IResult *pResult, void *pUserData);
|
||||||
static void Con_Reset(IResult *pResult, void *pUserData);
|
|
||||||
static void ConToggle(IResult *pResult, void *pUser);
|
|
||||||
static void ConToggleStroke(IResult *pResult, void *pUser);
|
|
||||||
static void ConCommandAccess(IResult *pResult, void *pUser);
|
static void ConCommandAccess(IResult *pResult, void *pUser);
|
||||||
static void ConCommandStatus(IConsole::IResult *pResult, void *pUser);
|
static void ConCommandStatus(IConsole::IResult *pResult, void *pUser);
|
||||||
|
|
||||||
|
@ -194,9 +189,6 @@ class CConsole : public IConsole
|
||||||
bool m_Cheated;
|
bool m_Cheated;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IConfigManager *ConfigManager() { return m_pConfigManager; }
|
|
||||||
CConfig *Config() { return m_pConfig; }
|
|
||||||
|
|
||||||
CConsole(int FlagMask);
|
CConsole(int FlagMask);
|
||||||
~CConsole();
|
~CConsole();
|
||||||
|
|
||||||
|
@ -225,7 +217,7 @@ public:
|
||||||
void InitChecksum(CChecksumData *pData) const override;
|
void InitChecksum(CChecksumData *pData) const override;
|
||||||
|
|
||||||
void SetAccessLevel(int AccessLevel) override { m_AccessLevel = clamp(AccessLevel, (int)(ACCESS_LEVEL_ADMIN), (int)(ACCESS_LEVEL_USER)); }
|
void SetAccessLevel(int AccessLevel) override { m_AccessLevel = clamp(AccessLevel, (int)(ACCESS_LEVEL_ADMIN), (int)(ACCESS_LEVEL_USER)); }
|
||||||
void ResetGameSettings() override;
|
|
||||||
// DDRace
|
// DDRace
|
||||||
|
|
||||||
static void ConUserCommandStatus(IConsole::IResult *pResult, void *pUser);
|
static void ConUserCommandStatus(IConsole::IResult *pResult, void *pUser);
|
||||||
|
|
|
@ -227,7 +227,7 @@ void CGameConsole::CInstance::PossibleArgumentsCompleteCallback(int Index, const
|
||||||
if(pInstance->m_CompletionChosenArgument == Index)
|
if(pInstance->m_CompletionChosenArgument == Index)
|
||||||
{
|
{
|
||||||
// get command
|
// get command
|
||||||
char aBuf[512];
|
char aBuf[IConsole::CMDLINE_LENGTH];
|
||||||
StrCopyUntilSpace(aBuf, sizeof(aBuf), pInstance->GetString());
|
StrCopyUntilSpace(aBuf, sizeof(aBuf), pInstance->GetString());
|
||||||
str_append(aBuf, " ");
|
str_append(aBuf, " ");
|
||||||
|
|
||||||
|
@ -256,7 +256,7 @@ bool CGameConsole::CInstance::OnInput(const IInput::CEvent &Event)
|
||||||
str_copy(pEntry, m_Input.GetString(), m_Input.GetLength() + 1);
|
str_copy(pEntry, m_Input.GetString(), m_Input.GetLength() + 1);
|
||||||
}
|
}
|
||||||
// print out the user's commands before they get run
|
// print out the user's commands before they get run
|
||||||
char aBuf[256];
|
char aBuf[IConsole::CMDLINE_LENGTH + 3];
|
||||||
str_format(aBuf, sizeof(aBuf), "> %s", m_Input.GetString());
|
str_format(aBuf, sizeof(aBuf), "> %s", m_Input.GetString());
|
||||||
m_pGameConsole->PrintLine(m_Type, aBuf);
|
m_pGameConsole->PrintLine(m_Type, aBuf);
|
||||||
}
|
}
|
||||||
|
@ -400,7 +400,7 @@ bool CGameConsole::CInstance::OnInput(const IInput::CEvent &Event)
|
||||||
|
|
||||||
// find the current command
|
// find the current command
|
||||||
{
|
{
|
||||||
char aBuf[512];
|
char aBuf[IConsole::CMDLINE_LENGTH];
|
||||||
StrCopyUntilSpace(aBuf, sizeof(aBuf), GetString());
|
StrCopyUntilSpace(aBuf, sizeof(aBuf), GetString());
|
||||||
const IConsole::CCommandInfo *pCommand = m_pGameConsole->m_pConsole->GetCommandInfo(aBuf, m_CompletionFlagmask,
|
const IConsole::CCommandInfo *pCommand = m_pGameConsole->m_pConsole->GetCommandInfo(aBuf, m_CompletionFlagmask,
|
||||||
m_Type != CGameConsole::CONSOLETYPE_LOCAL && m_pGameConsole->Client()->RconAuthed() && m_pGameConsole->Client()->UseTempRconCommands());
|
m_Type != CGameConsole::CONSOLETYPE_LOCAL && m_pGameConsole->Client()->RconAuthed() && m_pGameConsole->Client()->UseTempRconCommands());
|
||||||
|
|
|
@ -40,7 +40,7 @@ class CGameConsole : public CComponent
|
||||||
CStaticRingBuffer<char, 64 * 1024, CRingBufferBase::FLAG_RECYCLE> m_History;
|
CStaticRingBuffer<char, 64 * 1024, CRingBufferBase::FLAG_RECYCLE> m_History;
|
||||||
char *m_pHistoryEntry;
|
char *m_pHistoryEntry;
|
||||||
|
|
||||||
CLineInputBuffered<512> m_Input;
|
CLineInputBuffered<IConsole::CMDLINE_LENGTH> m_Input;
|
||||||
const char *m_pName;
|
const char *m_pName;
|
||||||
int m_Type;
|
int m_Type;
|
||||||
int m_BacklogCurPage;
|
int m_BacklogCurPage;
|
||||||
|
@ -59,9 +59,9 @@ class CGameConsole : public CComponent
|
||||||
|
|
||||||
CGameConsole *m_pGameConsole;
|
CGameConsole *m_pGameConsole;
|
||||||
|
|
||||||
char m_aCompletionBuffer[128];
|
char m_aCompletionBuffer[IConsole::CMDLINE_LENGTH];
|
||||||
int m_CompletionChosen;
|
int m_CompletionChosen;
|
||||||
char m_aCompletionBufferArgument[128];
|
char m_aCompletionBufferArgument[IConsole::CMDLINE_LENGTH];
|
||||||
int m_CompletionChosenArgument;
|
int m_CompletionChosenArgument;
|
||||||
int m_CompletionFlagmask;
|
int m_CompletionFlagmask;
|
||||||
float m_CompletionRenderOffset;
|
float m_CompletionRenderOffset;
|
||||||
|
|
|
@ -530,7 +530,7 @@ void CGameClient::OnConnected()
|
||||||
m_GameWorld.m_WorldConfig.m_InfiniteAmmo = true;
|
m_GameWorld.m_WorldConfig.m_InfiniteAmmo = true;
|
||||||
mem_zero(&m_GameInfo, sizeof(m_GameInfo));
|
mem_zero(&m_GameInfo, sizeof(m_GameInfo));
|
||||||
m_PredictedDummyID = -1;
|
m_PredictedDummyID = -1;
|
||||||
Console()->ResetGameSettings();
|
ConfigManager()->ResetGameSettings();
|
||||||
LoadMapSettings();
|
LoadMapSettings();
|
||||||
|
|
||||||
if(Client()->State() != IClient::STATE_DEMOPLAYBACK && g_Config.m_ClAutoDemoOnConnect)
|
if(Client()->State() != IClient::STATE_DEMOPLAYBACK && g_Config.m_ClAutoDemoOnConnect)
|
||||||
|
|
|
@ -3422,7 +3422,8 @@ void CGameContext::ConchainSettingUpdate(IConsole::IResult *pResult, void *pUser
|
||||||
void CGameContext::OnConsoleInit()
|
void CGameContext::OnConsoleInit()
|
||||||
{
|
{
|
||||||
m_pServer = Kernel()->RequestInterface<IServer>();
|
m_pServer = Kernel()->RequestInterface<IServer>();
|
||||||
m_pConfig = Kernel()->RequestInterface<IConfigManager>()->Values();
|
m_pConfigManager = Kernel()->RequestInterface<IConfigManager>();
|
||||||
|
m_pConfig = m_pConfigManager->Values();
|
||||||
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
||||||
m_pEngine = Kernel()->RequestInterface<IEngine>();
|
m_pEngine = Kernel()->RequestInterface<IEngine>();
|
||||||
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
||||||
|
@ -3477,7 +3478,8 @@ void CGameContext::OnInit(const void *pPersistentData)
|
||||||
const CPersistentData *pPersistent = (const CPersistentData *)pPersistentData;
|
const CPersistentData *pPersistent = (const CPersistentData *)pPersistentData;
|
||||||
|
|
||||||
m_pServer = Kernel()->RequestInterface<IServer>();
|
m_pServer = Kernel()->RequestInterface<IServer>();
|
||||||
m_pConfig = Kernel()->RequestInterface<IConfigManager>()->Values();
|
m_pConfigManager = Kernel()->RequestInterface<IConfigManager>();
|
||||||
|
m_pConfig = m_pConfigManager->Values();
|
||||||
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
m_pConsole = Kernel()->RequestInterface<IConsole>();
|
||||||
m_pEngine = Kernel()->RequestInterface<IEngine>();
|
m_pEngine = Kernel()->RequestInterface<IEngine>();
|
||||||
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
m_pStorage = Kernel()->RequestInterface<IStorage>();
|
||||||
|
@ -3949,7 +3951,7 @@ void CGameContext::OnShutdown(void *pPersistentData)
|
||||||
}
|
}
|
||||||
|
|
||||||
DeleteTempfile();
|
DeleteTempfile();
|
||||||
Console()->ResetGameSettings();
|
ConfigManager()->ResetGameSettings();
|
||||||
Collision()->Dest();
|
Collision()->Dest();
|
||||||
delete m_pController;
|
delete m_pController;
|
||||||
m_pController = 0;
|
m_pController = 0;
|
||||||
|
|
|
@ -47,6 +47,7 @@ enum
|
||||||
};
|
};
|
||||||
|
|
||||||
class CCharacter;
|
class CCharacter;
|
||||||
|
class IConfigManager;
|
||||||
class CConfig;
|
class CConfig;
|
||||||
class CHeap;
|
class CHeap;
|
||||||
class CPlayer;
|
class CPlayer;
|
||||||
|
@ -77,6 +78,7 @@ private:
|
||||||
class CGameContext : public IGameServer
|
class CGameContext : public IGameServer
|
||||||
{
|
{
|
||||||
IServer *m_pServer;
|
IServer *m_pServer;
|
||||||
|
IConfigManager *m_pConfigManager;
|
||||||
CConfig *m_pConfig;
|
CConfig *m_pConfig;
|
||||||
IConsole *m_pConsole;
|
IConsole *m_pConsole;
|
||||||
IEngine *m_pEngine;
|
IEngine *m_pEngine;
|
||||||
|
@ -155,6 +157,7 @@ class CGameContext : public IGameServer
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IServer *Server() const { return m_pServer; }
|
IServer *Server() const { return m_pServer; }
|
||||||
|
IConfigManager *ConfigManager() const { return m_pConfigManager; }
|
||||||
CConfig *Config() { return m_pConfig; }
|
CConfig *Config() { return m_pConfig; }
|
||||||
IConsole *Console() { return m_pConsole; }
|
IConsole *Console() { return m_pConsole; }
|
||||||
IEngine *Engine() { return m_pEngine; }
|
IEngine *Engine() { return m_pEngine; }
|
||||||
|
|
|
@ -157,7 +157,7 @@ void CTeeHistorian::WriteHeader(const CGameInfo *pGameInfo)
|
||||||
First = false; \
|
First = false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MACRO_CONFIG_COL(Name, ScriptName, Def, Save, Desc) MACRO_CONFIG_INT(Name, ScriptName, Def, 0, 0, Save, Desc)
|
#define MACRO_CONFIG_COL(Name, ScriptName, Def, Flags, Desc) MACRO_CONFIG_INT(Name, ScriptName, Def, 0, 0, Flags, Desc)
|
||||||
|
|
||||||
#define MACRO_CONFIG_STR(Name, ScriptName, Len, Def, Flags, Desc) \
|
#define MACRO_CONFIG_STR(Name, ScriptName, Len, Def, Flags, Desc) \
|
||||||
if((Flags)&CFGFLAG_SERVER && !((Flags)&CFGFLAG_NONTEEHISTORIC) && str_comp(pGameInfo->m_pConfig->m_##Name, (Def)) != 0) \
|
if((Flags)&CFGFLAG_SERVER && !((Flags)&CFGFLAG_NONTEEHISTORIC) && str_comp(pGameInfo->m_pConfig->m_##Name, (Def)) != 0) \
|
||||||
|
|
Loading…
Reference in a new issue