diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 3fb82cd46..9a81e0e5d 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -4468,8 +4468,8 @@ int main(int argc, const char **argv) } pEngine->Init(); - pConfigManager->Init(); pConsole->Init(); + pConfigManager->Init(); // register all console commands pClient->RegisterCommands(); diff --git a/src/engine/config.h b/src/engine/config.h index 79b5b3257..bccf50437 100644 --- a/src/engine/config.h +++ b/src/engine/config.h @@ -12,8 +12,9 @@ public: typedef void (*SAVECALLBACKFUNC)(IConfigManager *pConfig, void *pUserData); virtual void Init() = 0; - virtual void Reset() = 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 class CConfig *Values() = 0; diff --git a/src/engine/console.h b/src/engine/console.h index ecbd80660..774e06358 100644 --- a/src/engine/console.h +++ b/src/engine/console.h @@ -34,6 +34,8 @@ public: TEMPCMD_HELP_LENGTH = 192, TEMPCMD_PARAMS_LENGTH = 96, + CMDLINE_LENGTH = 512, + CLIENT_ID_GAME = -2, CLIENT_ID_NO_GAME = -3, }; @@ -117,8 +119,6 @@ public: virtual void SetAccessLevel(int AccessLevel) = 0; - virtual void ResetGameSettings() = 0; - static LEVEL ToLogLevel(int ConsoleLevel); static int ToLogLevelFilter(int ConsoleLevel); diff --git a/src/engine/server/main.cpp b/src/engine/server/main.cpp index 2f12200ab..ea1987531 100644 --- a/src/engine/server/main.cpp +++ b/src/engine/server/main.cpp @@ -153,8 +153,8 @@ int main(int argc, const char **argv) } pEngine->Init(); - pConfigManager->Init(); pConsole->Init(); + pConfigManager->Init(); // register all console commands pServer->RegisterCommands(); @@ -173,8 +173,8 @@ int main(int argc, const char **argv) if(argc > 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)"); - 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_test_cmds", true); + pConfigManager->SetReadOnly("sv_rescue", true); const int Mode = g_Config.m_Logappend ? IOFLAG_APPEND : IOFLAG_WRITE; if(g_Config.m_Logfile[0]) diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 359363a69..b6fff9c1f 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -3096,22 +3096,6 @@ int CServer::Run() return ErrorShutdown(); } -void CServer::ConTestingCommands(CConsole::IResult *pResult, void *pUser) -{ - CConsole *pThis = static_cast(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(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) { if(pResult->NumArguments() > 1) diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 4c9e55922..6b0b3708a 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -413,8 +413,6 @@ public: 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 ConStatus(IConsole::IResult *pResult, void *pUser); static void ConShutdown(IConsole::IResult *pResult, void *pUser); diff --git a/src/engine/shared/config.cpp b/src/engine/shared/config.cpp index ce930d27f..b262c493a 100644 --- a/src/engine/shared/config.cpp +++ b/src/engine/shared/config.cpp @@ -1,65 +1,463 @@ /* (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. */ + +#include + #include #include +#include #include #include 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); } +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(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(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(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(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(*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() { - m_pStorage = 0; + m_pConsole = nullptr; + m_pStorage = nullptr; m_ConfigFile = 0; - m_NumCallbacks = 0; m_Failed = false; } void CConfigManager::Init() { + m_pConsole = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); - Reset(); -} -void CConfigManager::Reset() -{ -#define MACRO_CONFIG_INT(Name, ScriptName, def, min, max, flags, desc) g_Config.m_##Name = def; -#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) str_copy(g_Config.m_##Name, def, len); + const auto &&AddVariable = [this](SConfigVariable *pVariable) { + m_vpAllVariables.push_back(pVariable); + if((pVariable->m_Flags & CFGFLAG_GAME) != 0) + m_vpGameVariables.push_back(pVariable); + 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(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(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(ColorHSLA(Def, Alpha)).Pack(Alpha)); \ + AddVariable(m_ConfigHeap.Allocate(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(m_ConfigHeap.Allocate(HelpSize)); \ + str_format(pHelp, HelpSize, "%s (default: \"%s\", max length: %d)", Desc, Def, Len - 1); \ + char *pOldValue = static_cast(m_ConfigHeap.Allocate(Len)); \ + AddVariable(m_ConfigHeap.Allocate(m_pConsole, #ScriptName, SConfigVariable::VAR_STRING, Flags, pHelp, g_Config.m_##Name, Def, Len, pOldValue)); \ + } #include "config_variables.h" #undef MACRO_CONFIG_INT #undef MACRO_CONFIG_COL #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) { -#define MACRO_CONFIG_INT(Name, ScriptName, def, min, max, flags, desc) \ - if(str_comp(pScriptName, #ScriptName) == 0) \ - { \ - g_Config.m_##Name = def; \ - 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; \ - }; + for(SConfigVariable *pVariable : m_vpAllVariables) + { + if((pVariable->m_Flags & m_pConsole->FlagMask()) != 0 && str_comp(pScriptName, pVariable->m_pScriptName) == 0) + { + pVariable->ResetToDefault(); + 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 -#undef MACRO_CONFIG_COL -#undef MACRO_CONFIG_STR +void CConfigManager::ResetGameSettings() +{ + 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() @@ -72,47 +470,30 @@ bool CConfigManager::Save() if(!m_ConfigFile) { - dbg_msg("config", "ERROR: opening %s failed", aConfigFileTmp); + log_error("config", "ERROR: opening %s failed", aConfigFileTmp); return false; } m_Failed = false; - char aLineBuf[1024 * 2]; - char aEscapeBuf[1024 * 2]; - -#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) + char aLineBuf[2048]; + for(const SConfigVariable *pVariable : m_vpAllVariables) { - 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) @@ -127,13 +508,13 @@ bool CConfigManager::Save() if(m_Failed) { - dbg_msg("config", "ERROR: writing to %s failed", aConfigFileTmp); + log_error("config", "ERROR: writing to %s failed", aConfigFileTmp); return false; } 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; } @@ -142,10 +523,7 @@ bool CConfigManager::Save() void CConfigManager::RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) { - dbg_assert(m_NumCallbacks < MAX_CALLBACKS, "too many config callbacks"); - m_aCallbacks[m_NumCallbacks].m_pfnFunc = pfnFunc; - m_aCallbacks[m_NumCallbacks].m_pUserData = pUserData; - m_NumCallbacks++; + m_vCallbacks.emplace_back(pfnFunc, pUserData); } void CConfigManager::WriteLine(const char *pLine) @@ -160,7 +538,76 @@ void CConfigManager::WriteLine(const char *pLine) 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(pUserData)->Reset(pResult->GetString(0)); +} + +void CConfigManager::Con_Toggle(IConsole::IResult *pResult, void *pUserData) +{ + CConfigManager *pConfigManager = static_cast(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(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(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(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(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(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; } diff --git a/src/engine/shared/config.h b/src/engine/shared/config.h index 63c640fb6..826c0dd61 100644 --- a/src/engine/shared/config.h +++ b/src/engine/shared/config.h @@ -4,9 +4,11 @@ #define ENGINE_SHARED_CONFIG_H #include -#include -#include +#include +#include +#include + #include // include protocol for MAX_CLIENT used in config_variables @@ -20,13 +22,13 @@ class CConfig { 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; \ 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; \ 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; \ char m_##Name[Len]; // Flawfinder: ignore #include "config_variables.h" @@ -58,31 +60,41 @@ enum class CConfigManager : public IConfigManager { - enum - { - MAX_CALLBACKS = 16 - }; + IConsole *m_pConsole; + class IStorage *m_pStorage; - struct CCallback + IOHANDLE m_ConfigFile; + bool m_Failed; + + struct SCallback { SAVECALLBACKFUNC m_pfnFunc; void *m_pUserData; + + SCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData) : + m_pfnFunc(pfnFunc), + m_pUserData(pUserData) + { + } }; + std::vector m_vCallbacks; - class IStorage *m_pStorage; - IOHANDLE m_ConfigFile; - bool m_Failed; - CCallback m_aCallbacks[MAX_CALLBACKS]; - int m_NumCallbacks; + std::vector m_vpAllVariables; + std::vector m_vpGameVariables; + std::vector m_vpUnknownCommands; + CHeap m_ConfigHeap; - std::vector 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: CConfigManager(); void Init() override; - void Reset() override; void Reset(const char *pScriptName) override; + void ResetGameSettings() override; + void SetReadOnly(const char *pScriptName, bool ReadOnly) override; bool Save() override; CConfig *Values() override { return &g_Config; } diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp index 39b2bae35..f89bf6810 100644 --- a/src/engine/shared/console.cpp +++ b/src/engine/shared/console.cpp @@ -459,7 +459,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID, bo { 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); Print(OUTPUT_LEVEL_STANDARD, "console", aBuf); } @@ -468,7 +468,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID, bo { 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); 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); @@ -489,8 +489,8 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientID, bo { if(ParseArgs(&Result, pCommand->m_pParams)) { - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "Invalid arguments... Usage: %s %s", pCommand->m_pName, pCommand->m_pParams); + 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); Print(OUTPUT_LEVEL_STANDARD, "chatresp", aBuf); } 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) { - char aBuf[256]; + char aBuf[CMDLINE_LENGTH + 32]; str_format(aBuf, sizeof(aBuf), "Access for command %s denied.", Result.m_pCommand); 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. 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); 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); } -void CConsole::Con_Reset(IResult *pResult, void *pUserData) -{ - ((CConsole *)pUserData)->ConfigManager()->Reset(pResult->GetString(0)); -} - void CConsole::ConCommandAccess(IResult *pResult, void *pUser) { CConsole *pConsole = static_cast(pUser); - char aBuf[128]; + char aBuf[CMDLINE_LENGTH + 64]; CCommand *pCommand = pConsole->FindCommand(pResult->GetString(0), CFGFLAG_SERVER); if(pCommand) { @@ -738,136 +733,6 @@ void CConsole::ConUserCommandStatus(IResult *pResult, void *pUser) 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(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(*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) { 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(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(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(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(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(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) { m_FlagMask = FlagMask; @@ -977,10 +763,6 @@ CConsole::CConsole(int FlagMask) // register some basic commands 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("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_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() { - m_pConfigManager = Kernel()->RequestInterface(); - m_pConfig = m_pConfigManager->Values(); m_pStorage = Kernel()->RequestInterface(); - -// 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((Flags)&CFGFLAG_COLLIGHT), \ - static_cast((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) @@ -1274,54 +1024,6 @@ const IConsole::CCommandInfo *CConsole::GetCommandInfo(const char *pName, int Fl std::unique_ptr CreateConsole(int FlagMask) { return std::make_unique(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 { return m_Victim; diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h index d16770c46..f5c4c97ea 100644 --- a/src/engine/shared/console.h +++ b/src/engine/shared/console.h @@ -46,8 +46,6 @@ class CConsole : public IConsole }; CExecFile *m_pFirstExec; - IConfigManager *m_pConfigManager; - CConfig *m_pConfig; IStorage *m_pStorage; int m_AccessLevel; @@ -59,9 +57,6 @@ class CConsole : public IConsole static void Con_Chain(IResult *pResult, void *pUserData); static void Con_Echo(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 ConCommandStatus(IConsole::IResult *pResult, void *pUser); @@ -194,9 +189,6 @@ class CConsole : public IConsole bool m_Cheated; public: - IConfigManager *ConfigManager() { return m_pConfigManager; } - CConfig *Config() { return m_pConfig; } - CConsole(int FlagMask); ~CConsole(); @@ -225,7 +217,7 @@ public: void InitChecksum(CChecksumData *pData) const override; void SetAccessLevel(int AccessLevel) override { m_AccessLevel = clamp(AccessLevel, (int)(ACCESS_LEVEL_ADMIN), (int)(ACCESS_LEVEL_USER)); } - void ResetGameSettings() override; + // DDRace static void ConUserCommandStatus(IConsole::IResult *pResult, void *pUser); diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp index f6458dc53..7c2ae0470 100644 --- a/src/game/client/components/console.cpp +++ b/src/game/client/components/console.cpp @@ -227,7 +227,7 @@ void CGameConsole::CInstance::PossibleArgumentsCompleteCallback(int Index, const if(pInstance->m_CompletionChosenArgument == Index) { // get command - char aBuf[512]; + char aBuf[IConsole::CMDLINE_LENGTH]; StrCopyUntilSpace(aBuf, sizeof(aBuf), pInstance->GetString()); 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); } // 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()); m_pGameConsole->PrintLine(m_Type, aBuf); } @@ -400,7 +400,7 @@ bool CGameConsole::CInstance::OnInput(const IInput::CEvent &Event) // find the current command { - char aBuf[512]; + char aBuf[IConsole::CMDLINE_LENGTH]; StrCopyUntilSpace(aBuf, sizeof(aBuf), GetString()); 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()); diff --git a/src/game/client/components/console.h b/src/game/client/components/console.h index b088f0642..cadaefd95 100644 --- a/src/game/client/components/console.h +++ b/src/game/client/components/console.h @@ -40,7 +40,7 @@ class CGameConsole : public CComponent CStaticRingBuffer m_History; char *m_pHistoryEntry; - CLineInputBuffered<512> m_Input; + CLineInputBuffered m_Input; const char *m_pName; int m_Type; int m_BacklogCurPage; @@ -59,9 +59,9 @@ class CGameConsole : public CComponent CGameConsole *m_pGameConsole; - char m_aCompletionBuffer[128]; + char m_aCompletionBuffer[IConsole::CMDLINE_LENGTH]; int m_CompletionChosen; - char m_aCompletionBufferArgument[128]; + char m_aCompletionBufferArgument[IConsole::CMDLINE_LENGTH]; int m_CompletionChosenArgument; int m_CompletionFlagmask; float m_CompletionRenderOffset; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 19c929677..17e20f8bb 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -530,7 +530,7 @@ void CGameClient::OnConnected() m_GameWorld.m_WorldConfig.m_InfiniteAmmo = true; mem_zero(&m_GameInfo, sizeof(m_GameInfo)); m_PredictedDummyID = -1; - Console()->ResetGameSettings(); + ConfigManager()->ResetGameSettings(); LoadMapSettings(); if(Client()->State() != IClient::STATE_DEMOPLAYBACK && g_Config.m_ClAutoDemoOnConnect) diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 2f7cf788b..f81ca1af6 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -3422,7 +3422,8 @@ void CGameContext::ConchainSettingUpdate(IConsole::IResult *pResult, void *pUser void CGameContext::OnConsoleInit() { m_pServer = Kernel()->RequestInterface(); - m_pConfig = Kernel()->RequestInterface()->Values(); + m_pConfigManager = Kernel()->RequestInterface(); + m_pConfig = m_pConfigManager->Values(); m_pConsole = Kernel()->RequestInterface(); m_pEngine = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); @@ -3477,7 +3478,8 @@ void CGameContext::OnInit(const void *pPersistentData) const CPersistentData *pPersistent = (const CPersistentData *)pPersistentData; m_pServer = Kernel()->RequestInterface(); - m_pConfig = Kernel()->RequestInterface()->Values(); + m_pConfigManager = Kernel()->RequestInterface(); + m_pConfig = m_pConfigManager->Values(); m_pConsole = Kernel()->RequestInterface(); m_pEngine = Kernel()->RequestInterface(); m_pStorage = Kernel()->RequestInterface(); @@ -3949,7 +3951,7 @@ void CGameContext::OnShutdown(void *pPersistentData) } DeleteTempfile(); - Console()->ResetGameSettings(); + ConfigManager()->ResetGameSettings(); Collision()->Dest(); delete m_pController; m_pController = 0; diff --git a/src/game/server/gamecontext.h b/src/game/server/gamecontext.h index e01caba57..d521bfbcd 100644 --- a/src/game/server/gamecontext.h +++ b/src/game/server/gamecontext.h @@ -47,6 +47,7 @@ enum }; class CCharacter; +class IConfigManager; class CConfig; class CHeap; class CPlayer; @@ -77,6 +78,7 @@ private: class CGameContext : public IGameServer { IServer *m_pServer; + IConfigManager *m_pConfigManager; CConfig *m_pConfig; IConsole *m_pConsole; IEngine *m_pEngine; @@ -155,6 +157,7 @@ class CGameContext : public IGameServer public: IServer *Server() const { return m_pServer; } + IConfigManager *ConfigManager() const { return m_pConfigManager; } CConfig *Config() { return m_pConfig; } IConsole *Console() { return m_pConsole; } IEngine *Engine() { return m_pEngine; } diff --git a/src/game/server/teehistorian.cpp b/src/game/server/teehistorian.cpp index 083ccd65d..355916b02 100644 --- a/src/game/server/teehistorian.cpp +++ b/src/game/server/teehistorian.cpp @@ -157,7 +157,7 @@ void CTeeHistorian::WriteHeader(const CGameInfo *pGameInfo) 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) \ if((Flags)&CFGFLAG_SERVER && !((Flags)&CFGFLAG_NONTEEHISTORIC) && str_comp(pGameInfo->m_pConfig->m_##Name, (Def)) != 0) \