bool Register(CvarProxy* proxy, const std::string& name, std::string description, int flags, const std::string& defaultValue) { CvarMap& cvars = GetCvarMap(); cvarRecord_t* cvar; auto it = cvars.find(name); if (it == cvars.end()) { if (!Cmd::IsValidCvarName(name)) { Log::Notice("Invalid cvar name '%s'", name.c_str()); return false; } //Create the cvar and parse its default value cvar = new cvarRecord_t{defaultValue, defaultValue, flags, description, proxy, {}}; cvars[name] = cvar; Cmd::AddCommand(name, cvarCommand, "cvar - \"" + defaultValue + "\" - " + description); } else { cvar = it->second; if (proxy && cvar->proxy) { Log::Warn("Cvar %s cannot be registered twice", name.c_str()); } // Register the cvar with the previous user_created value cvar->flags &= ~CVAR_USER_CREATED; cvar->flags |= flags; cvar->proxy = proxy; if ((flags & ROM) || (!cheatsAllowed && (flags & CHEAT))) { cvar->value = defaultValue; } cvar->resetValue = defaultValue; cvar->description = ""; if (proxy) { //TODO replace me with an assert once we do not need to support the C API OnValueChangedResult result = proxy->OnValueChanged(cvar->value); if (result.success) { ChangeCvarDescription(name, cvar, result.description); } else { OnValueChangedResult defaultValueResult = proxy->OnValueChanged(defaultValue); if (defaultValueResult.success) { ChangeCvarDescription(name, cvar, result.description); } else { Log::Notice("Default value '%s' is not correct for cvar '%s': %s\n", defaultValue.c_str(), name.c_str(), defaultValueResult.description.c_str()); } } } } GetCCvar(name, *cvar); return true; }
void SetCheatsAllowed(bool allowed) { cheatsAllowed = allowed; if (cheatsAllowed) { return; } CvarMap& cvars = GetCvarMap(); // Reset all the CHEAT cvars to their default value for (auto& entry : cvars) { cvarRecord_t* cvar = entry.second; if (cvar->flags & CHEAT && cvar->value != cvar->resetValue) { cvar->value = cvar->resetValue; SetCCvar(*cvar); if (cvar->proxy) { OnValueChangedResult result = cvar->proxy->OnValueChanged(cvar->resetValue); if (result.success) { ChangeCvarDescription(entry.first, cvar, result.description); } else { Com_Printf("Default value '%s' is not correct for cvar '%s': %s\n", cvar->resetValue.c_str(), entry.first.c_str(), result.description.c_str()); } } } } }
void InternalSetValue(const std::string& cvarName, std::string value, int flags, bool rom, bool warnRom) { CvarMap& cvars = GetCvarMap(); auto it = cvars.find(cvarName); //TODO: rom means the cvar should have been created before? if (it == cvars.end()) { if (!Cmd::IsValidCvarName(cvarName)) { Log::Notice("Invalid cvar name '%s'", cvarName.c_str()); return; } //The user creates a new cvar through a command. cvars[cvarName] = new cvarRecord_t{value, value, flags | CVAR_USER_CREATED, "user created", nullptr, {}}; Cmd::AddCommand(cvarName, cvarCommand, "cvar - user created"); GetCCvar(cvarName, *cvars[cvarName]); } else { cvarRecord_t* cvar = it->second; if (not (cvar->flags & CVAR_USER_CREATED)) { if (cvar->flags & (CVAR_ROM | CVAR_INIT) and not rom) { Log::Notice("%s is read only.\n", cvarName.c_str()); return; } if (rom and warnRom and not (cvar->flags & (CVAR_ROM | CVAR_INIT))) { Log::Notice("SetValueROM called on non-ROM cvar '%s'\n", cvarName.c_str()); } if (not cheatsAllowed && cvar->flags & CHEAT) { Log::Notice("%s is cheat-protected.\n", cvarName.c_str()); return; } } std::swap(cvar->value, value); cvar->flags |= flags; // mark for archival if flagged as archive-on-change if (cvar->flags & ARCHIVE) { cvar->flags |= USER_ARCHIVE; } if (cvar->proxy) { //Tell the cvar proxy about the new value OnValueChangedResult result = cvar->proxy->OnValueChanged(cvar->value); if (result.success) { ChangeCvarDescription(cvarName, cvar, result.description); } else { //The proxy could not parse the value, rollback Log::Notice("Value '%s' is not valid for cvar %s: %s\n", cvar->value.c_str(), cvarName.c_str(), result.description.c_str()); cvar->value = value; } } SetCCvar(*cvar); } }