[Dvar]: Protect saved dvars by default (#694)

This commit is contained in:
Edo 2023-01-03 09:23:08 +00:00 committed by GitHub
parent 9f39834090
commit 406499d919
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 6 additions and 48 deletions

View File

@ -39,7 +39,7 @@
| `-version` | Print IW4x build info on startup. |
| `-zonebuilder` | Start the interactive zonebuilder tool console instead of starting the game. |
| `-nosteam` | Disable friends feature and do not update Steam about the game's current status just like an invisible mode. |
| `-protect-saved-dvars` | Block the server from modifying saved/archive dvars. |
| `-unprotect-dvars` | Allow the server to modify saved/archive dvars. |
## Disclaimer

View File

@ -2,14 +2,11 @@
namespace Components
{
const char* Dvar::ArchiveDvarPath = "userraw/archivedvars.cfg";
Dvar::Var Dvar::Name;
Dvar::Var::Var(const std::string& dvarName)
: dvar_(Game::Dvar_FindVar(dvarName.data()))
{
this->dvar_ = Game::Dvar_FindVar(dvarName.data());
// If the dvar can't be found it will be registered as an empty string dvar
if (this->dvar_ == nullptr)
{
@ -206,16 +203,6 @@ namespace Components
return Game::Dvar_RegisterFloat(dvarName, value, min, max, flag, description);
}
void Dvar::ResetDvarsValue()
{
if (!Utils::IO::FileExists(ArchiveDvarPath))
return;
Command::Execute("exec archivedvars.cfg", true);
// Clean up
Utils::IO::RemoveFile(ArchiveDvarPath);
}
Game::dvar_t* Dvar::Dvar_RegisterName(const char* name, const char* /*default*/, std::uint16_t flags, const char* description)
{
// Name watcher
@ -291,44 +278,31 @@ namespace Components
Game::Dvar_SetFromStringByNameFromSource(dvarName, string, Game::DVAR_SOURCE_EXTERNAL);
}
bool Dvar::AreArchiveDvarsProtected()
bool Dvar::AreArchiveDvarsUnprotected()
{
static std::optional<bool> flag;
if (!flag.has_value())
{
flag.emplace(Flags::HasFlag("protect-saved-dvars"));
flag.emplace(Flags::HasFlag("unprotect-dvars"));
}
return flag.value();
}
void Dvar::SaveArchiveDvar(const Game::dvar_t* var)
{
if (!Utils::IO::FileExists(ArchiveDvarPath))
{
Utils::IO::WriteFile(ArchiveDvarPath, "// generated by IW4x, do not modify\n", false);
}
Utils::IO::WriteFile(ArchiveDvarPath, std::format("set {} \"{}\"\n", var->name, Game::Dvar_DisplayableValue(var)), true);
}
void Dvar::DvarSetFromStringByName_Stub(const char* dvarName, const char* value)
{
// Save the dvar original value if it has the archive flag
const auto* dvar = Game::Dvar_FindVar(dvarName);
if (dvar != nullptr && dvar->flags & Game::DVAR_ARCHIVE)
{
if (AreArchiveDvarsProtected())
if (!AreArchiveDvarsUnprotected())
{
Logger::Print(Game::CON_CHANNEL_CONSOLEONLY, "Not allowing server to override saved dvar '{}'\n", dvar->name);
return;
}
#ifdef DEBUG_DVARS
Logger::Print(Game::CON_CHANNEL_CONSOLEONLY, "Server is overriding saved dvar '{}'\n", dvarName);
#endif
SaveArchiveDvar(dvar);
}
if (dvar != nullptr && std::strcmp(dvar->name, "com_errorResolveCommand") == 0)
@ -467,12 +441,6 @@ namespace Components
// Hook Dvar_SetFromStringByName inside CG_SetClientDvarFromServer so we can reset dvars when the player leaves the server
Utils::Hook(0x59386A, DvarSetFromStringByName_Stub, HOOK_CALL).install()->quick();
// If the game closed abruptly, the dvars would not have been restored
Scheduler::Once(ResetDvarsValue, Scheduler::Pipeline::MAIN);
// Reset archive dvars when client leaves a server
Events::OnSteamDisconnect(ResetDvarsValue);
// For debugging
Utils::Hook(0x6483FA, Dvar_RegisterVariant_Stub, HOOK_JUMP).install()->quick();
Utils::Hook(0x648438, Dvar_RegisterVariant_Stub, HOOK_JUMP).install()->quick();
@ -480,9 +448,4 @@ namespace Components
// Fix crash
Utils::Hook(0x4B7120, Dvar_EnumToString_Stub, HOOK_JUMP).install()->quick();
}
Dvar::~Dvar()
{
Utils::IO::RemoveFile(ArchiveDvarPath);
}
}

View File

@ -32,16 +32,12 @@ namespace Components
};
Dvar();
~Dvar();
// Only strings and bools use this type of declaration
template<typename T> static Var Register(const char* dvarName, T value, std::uint16_t flag, const char* description);
template<typename T> static Var Register(const char* dvarName, T value, T min, T max, std::uint16_t flag, const char* description);
static void ResetDvarsValue();
private:
static const char* ArchiveDvarPath;
static Var Name;
static Game::dvar_t* Dvar_RegisterName(const char* name, const char* defaultVal, std::uint16_t flags, const char* description);
@ -49,8 +45,7 @@ namespace Components
static void SetFromStringByNameExternal(const char* dvarName, const char* string);
static void SetFromStringByNameSafeExternal(const char* dvarName, const char* string);
static bool AreArchiveDvarsProtected();
static void SaveArchiveDvar(const Game::dvar_t* var);
static bool AreArchiveDvarsUnprotected();
static void DvarSetFromStringByName_Stub(const char* dvarName, const char* value);
static void OnRegisterVariant(Game::dvar_t* dvar);