bool Register(CvarProxy* cvar, const std::string& name, std::string description, int flags, const std::string& defaultValue) { if (cvarsInitialized) { GetCvarMap()[name] = {cvar, "", 0, defaultValue}; RegisterCvarRPC(name, std::move(description), flags, defaultValue); } else { GetCvarMap()[name] = {cvar, std::move(description), flags, defaultValue}; } 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); } }
static void InitializeProxy() { for (auto& record : GetCvarMap()) { RegisterCvarRPC(record.first, std::move(record.second.description), record.second.flags, std::move(record.second.defaultValue)); } cvarsInitialized = true; }
cvar_t* FindCCvar(const std::string& cvarName) { CvarMap& cvars = GetCvarMap(); auto iter = cvars.find(cvarName); if (iter != cvars.end()) { return &iter->second->ccvar; } return nullptr; }
void PopulateInfoMap(int flag, InfoMap& map) { for (auto& entry : GetCvarMap()) { cvarRecord_t* cvar = entry.second; if (cvar->flags & flag) { map[entry.first] = cvar->value; } } }
void Unregister(const std::string& cvarName) { CvarMap& cvars = GetCvarMap(); auto it = cvars.find(cvarName); if (it != cvars.end()) { cvarRecord_t* cvar = it->second; cvar->proxy = nullptr; cvar->flags |= CVAR_USER_CREATED; } // TODO else what? }
std::string GetValue(const std::string& cvarName) { CvarMap& cvars = GetCvarMap(); std::string result = ""; auto iter = cvars.find(cvarName); if (iter != cvars.end()) { result = iter->second->value; } return result; }
Cmd::CompletionResult Complete(Str::StringRef prefix) { CvarMap& cvars = GetCvarMap(); Cmd::CompletionResult res; for (auto& entry : cvars) { if (Str::IsIPrefix(prefix, entry.first)) { res.push_back(std::make_pair(entry.first, entry.second->description)); } } return res; }
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; }
char* InfoString(int flag, bool big) { static char info[BIG_INFO_STRING]; info[0] = 0; CvarMap& cvars = GetCvarMap(); for (auto& entry : cvars) { cvarRecord_t* cvar = entry.second; if (cvar->flags & flag) { Info_SetValueForKey(info, entry.first.c_str(), cvar->value.c_str(), big); } } return info; }
bool ClearFlags(const std::string& cvarName, int flags) { CvarMap& cvars = GetCvarMap(); auto it = cvars.find(cvarName); if (it != cvars.end()) { cvarRecord_t* cvar = it->second; cvar->flags &= ~flags; // TODO: remove it, overkill ? // Make sure to trigger the event as if this variable was changed cvar_modifiedFlags |= flags; return true; // success } // TODO else what? return false; // not found }
void WriteVariables(fileHandle_t f) { CvarMap& cvars = GetCvarMap(); for (auto& entry : cvars) { cvarRecord_t* cvar = entry.second; if (cvar->IsArchived()) { const char* value; if (cvar->ccvar.latchedString) { value = cvar->ccvar.latchedString; } else { value = cvar->value.c_str(); } FS_Printf(f, "seta %s %s\n", entry.first.c_str(), Cmd::Escape(value).c_str()); } } }
void CallOnValueChangedSyscall(Util::Reader& reader, IPC::Channel& channel) { IPC::HandleMsg<VM::OnValueChangedMsg>( channel, std::move(reader), [](std::string name, std::string value, bool& success, std::string& description) { auto map = GetCvarMap(); auto it = map.find(name); if (it == map.end()) { success = true; description = ""; return; } auto res = it->second.cvar->OnValueChanged(value); success = res.success; description = res.description; }); }
std::string GetCvarConfigText() { CvarMap& cvars = GetCvarMap(); std::ostringstream result; for (auto& entry : cvars) { cvarRecord_t* cvar = entry.second; if (cvar->IsArchived()) { const char* value; if (cvar->ccvar.latchedString) { value = cvar->ccvar.latchedString; } else { value = cvar->value.c_str(); } result << Str::Format("seta %s %s\n", entry.first.c_str(), Cmd::Escape(value).c_str()); } } return result.str(); }
bool AddFlags(const std::string& cvarName, int flags) { CvarMap& cvars = GetCvarMap(); auto it = cvars.find(cvarName); if (it != cvars.end()) { cvarRecord_t* cvar = it->second; // User error. Possibly coder error too, but unlikely if ((cvar->flags & TEMPORARY) && (flags & (ARCHIVE | USER_ARCHIVE))) { Com_Printf("Cvar '%s' is temporary and will not be archived\n", cvarName.c_str()); flags &= ~(ARCHIVE | USER_ARCHIVE); } cvar->flags |= flags; // TODO: remove it, overkill ? // Make sure to trigger the event as if this variable was changed cvar_modifiedFlags |= flags; return true; // success } // TODO else what? return false; // not found }