Fix: Fix default variable values being set incorrectly when preloading

This only affects the "Key" type because of SDL
Incorrect default variables means that all keys will be unbound as soon as a config file is loaded.
This commit essentially replaces e9b9cf16b17f0f42d14e80c97a6bf2577a730228
This commit is contained in:
TotallyNotElite 2020-11-26 12:41:10 +01:00 committed by TotallyNotElite
parent 68829d1178
commit 454943b559
12 changed files with 35 additions and 32 deletions

View File

@ -27,7 +27,7 @@ public:
return VariableType::BOOL;
}
void fromString(const std::string &string) override
void fromString(const std::string &string, bool = false) override
{
if (string == "0" || string == "false")
setInternal(false);

View File

@ -19,7 +19,7 @@ public:
return VariableType::FLOAT;
}
void fromString(const std::string &string) override
void fromString(const std::string &string, bool = false) override
{
errno = 0;
auto next = std::strtof(string.c_str(), nullptr);

View File

@ -19,7 +19,7 @@ public:
return VariableType::INT;
}
void fromString(const std::string &string) override
void fromString(const std::string &string, bool = false) override
{
errno = 0;
auto result = std::strtol(string.c_str(), nullptr, 10);

View File

@ -32,7 +32,7 @@ public:
}
// Valid inputs: "Mouse1", "Mouse5", "Key 6", "Key 10", "Key 2", "Space".
void fromString(const std::string &string) override
void fromString(const std::string &string, bool init = false) override
{
if (string == "<null>")
{
@ -57,6 +57,9 @@ public:
}
setInternal(key);
// This is broken otherwise
if (init)
this->string = string;
}
// Variable & causes segfault with gcc optimizations + these dont even

View File

@ -29,10 +29,10 @@ class Manager
public:
struct VariableDescriptor
{
explicit VariableDescriptor(IVariable &variable);
VariableDescriptor(IVariable &variable, std::string value);
VariableDescriptor(IVariable &variable);
bool isChanged();
void applyDefaults();
IVariable &variable;
std::string defaults{};
@ -43,7 +43,7 @@ public:
public:
void add(IVariable &me, std::string name);
void add(IVariable &me, std::string name, std::string value);
void applyDefaults();
IVariable *lookup(const std::string &string);
std::unordered_map<std::string, VariableDescriptor> registered{};

View File

@ -10,7 +10,6 @@ namespace settings
{
void registerVariable(IVariable &variable, std::string name);
void registerVariable(IVariable &variable, std::string name, std::string value);
template <typename T> class RegisteredVariableProxy : public Variable<T>
{
@ -21,11 +20,10 @@ public:
{
registerVariable(*this, name);
}
RegisteredVariableProxy(std::string name, std::string value)
{
this->fromString(value);
registerVariable(*this, name, value);
this->fromString(value, true);
registerVariable(*this, name);
}
};

View File

@ -30,7 +30,7 @@ public:
return VariableType::COLOR;
}
void fromString(const std::string &string) override
void fromString(const std::string &string, bool = false) override
{
uint8_t rgba[4] = { 0, 0, 0, 255 };

View File

@ -55,8 +55,8 @@ public:
virtual ~IVariable() = default;
// Faster than checking with dynamic_cast
virtual VariableType getType() = 0;
virtual void fromString(const std::string &string) = 0;
virtual VariableType getType() = 0;
virtual void fromString(const std::string &string, bool init = false) = 0;
// Const reference because every variable will cache the string value
// instead of generating it every call
virtual const std::string &toString() = 0;
@ -84,7 +84,6 @@ protected:
}
std::vector<std::function<void(VariableBase<T> &, T)>> callbacks{};
T default_value{};
};
template <typename T> class Variable

View File

@ -19,7 +19,7 @@ public:
return VariableType::STRING;
}
void fromString(const std::string &string) override
void fromString(const std::string &string, bool = false) override
{
fireCallbacks(string);
value = string;

View File

@ -313,6 +313,10 @@ free(logname);*/
#endif
CreateEarlyInterfaces();
// Applying the defaults needs to be delayed, because preloaded Cathook can not properly convert SDL codes to names before TF2 init
settings::Manager::instance().applyDefaults();
logging::Info("Clearing Early initializer stack");
while (!init_stack_early().empty())
{

View File

@ -24,14 +24,13 @@ void Manager::add(IVariable &me, std::string name)
registered.emplace(name, me);
}
void Manager::add(IVariable &me, std::string name, std::string value)
// Applying the defaults needs to be delayed, because preloaded Cathook can not properly convert SDL codes to names before TF2 init
void Manager::applyDefaults()
{
if (registered.find(name) != registered.end())
for (auto &variables : registered)
{
logging::Info(("Double registering variable: " + name).c_str());
throw std::runtime_error("Double registering variable: " + name);
variables.second.applyDefaults();
}
registered.emplace(name, Manager::VariableDescriptor{ me, value });
}
IVariable *Manager::lookup(const std::string &string)
@ -48,14 +47,19 @@ Manager::VariableDescriptor::VariableDescriptor(IVariable &variable) : variable(
defaults = variable.toString();
}
Manager::VariableDescriptor::VariableDescriptor(IVariable &variable, std::string value) : variable(variable)
{
type = variable.getType();
defaults = value;
}
bool Manager::VariableDescriptor::isChanged()
{
return variable.toString() != defaults;
}
// Applying the defaults needs to be delayed, because preloaded Cathook can not properly convert SDL codes to names before TF2 init
void Manager::VariableDescriptor::applyDefaults()
{
if (type == VariableType::KEY)
{
// Shitcode, this is a pain in the you know what to fix
variable.fromString(variable.toString());
defaults = variable.toString();
}
}
} // namespace settings

View File

@ -8,8 +8,3 @@ void settings::registerVariable(IVariable &variable, std::string name)
{
Manager::instance().add(variable, name);
}
void settings::registerVariable(IVariable &variable, std::string name, std::string value)
{
Manager::instance().add(variable, name, value);
}