/* * This file is part of the DXX-Rebirth project . * It is copyright by its individual contributors, as recorded in the * project's Git history. See COPYING.txt at the top level for license * terms and a link to the Git history. * */ /* * * Console variables * */ #include #include #include #include #include "cmd.h" #include "console.h" #include "cvar.h" #include "dxxerror.h" #include "strutil.h" #include "u_mem.h" #include "game.h" #include "physfsx.h" #include "dxxsconf.h" #include "compiler-range_for.h" #define CVAR_MAX_LENGTH 1024 /* The list of cvars */ typedef std::map> cvar_list_type; static cvar_list_type cvar_list; const char *cvar_t::operator=(const char *s) { cvar_set_cvar(this, s); return s; } int cvar_t::operator=(int i) { cvar_set_cvarf(this, "%d", i); return this->intval; } void cvar_cmd_set(unsigned long argc, const char *const *const argv) { char buf[CVAR_MAX_LENGTH]; int ret; if (argc == 2) { cvar_t *ptr; if ((ptr = cvar_find(argv[1]))) con_printf(CON_NORMAL, "%s: %s", ptr->name, ptr->string.c_str()); else con_printf(CON_NORMAL, "set: variable %s not found", argv[1]); return; } if (argc == 1) { range_for (const auto &i, cvar_list) con_printf(CON_NORMAL, "%s: %s", i.first, i.second.get().string.c_str()); return; } ret = snprintf(buf, sizeof(buf), "%s", argv[2]); if (ret >= CVAR_MAX_LENGTH) { con_printf(CON_CRITICAL, "set: value too long (max %d characters)", CVAR_MAX_LENGTH); return; } size_t position = ret; for (int i = 3; i < argc; i++) { ret = snprintf(&buf[position], CVAR_MAX_LENGTH - position, " %s", argv[i]); position += ret; if (position >= CVAR_MAX_LENGTH) { con_printf(CON_CRITICAL, "set: value too long (max %d characters)", CVAR_MAX_LENGTH); return; } } cvar_set(argv[1], buf); } void cvar_init(void) { cmd_addcommand("set", cvar_cmd_set, "set \n" " set variable equal to \n" "set \n" " show value of \n" "set\n" " show value of all variables"); } cvar_t *cvar_find(const char *cvar_name) { const auto i = cvar_list.find(cvar_name); return i == cvar_list.end() ? nullptr : &i->second.get(); } const char *cvar_complete(const char *text) { uint_fast32_t len = strlen(text); if (!len) return NULL; range_for (const auto &i, cvar_list) if (!d_strnicmp(text, i.first, len)) return i.first; return NULL; } /* Register a cvar */ void cvar_registervariable (cvar_t &cvar) { cvar.value = fl2f(strtod(cvar.string.c_str(), NULL)); cvar.intval = static_cast(strtol(cvar.string.c_str(), NULL, 10)); const auto i = cvar_list.insert(cvar_list_type::value_type(cvar.name, cvar)); if (!i.second) { Int3(); con_printf(CON_URGENT, "cvar %s already exists!", cvar.name); return; } /* insert at end of list */ } /* Set a CVar's value */ void cvar_set_cvar(cvar_t *cvar, const char *value) { if (!cvar) return; cvar->string = value; cvar->value = fl2f(strtod(value, NULL)); cvar->intval = static_cast(strtol(value, NULL, 10)); con_printf(CON_VERBOSE, "%s: %s", cvar->name, value); } void cvar_set_cvarf(cvar_t *cvar, const char *fmt, ...) { va_list arglist; char buf[CVAR_MAX_LENGTH]; int n; va_start (arglist, fmt); n = vsnprintf(buf, sizeof(buf), fmt, arglist); va_end (arglist); if (n < 0 || n > CVAR_MAX_LENGTH) { Int3(); con_printf(CON_CRITICAL, "error setting cvar %s", cvar->name); return; } cvar_set_cvar(cvar, buf); } void cvar_set(const char *cvar_name, char *value) { cvar_t *cvar; cvar = cvar_find(cvar_name); if (!cvar) { Int3(); con_printf(CON_NORMAL, "cvar %s not found", cvar_name); return; } if (cvar->flags & CVAR_CHEAT && !cheats_enabled()) { con_printf(CON_NORMAL, "cvar %s is cheat protected.", cvar_name); return; } cvar_set_cvar(cvar, value); } /* Write archive cvars to file */ void cvar_write(PHYSFS_File *file) { range_for (const auto &i, cvar_list) if (i.second.get().flags & CVAR_ARCHIVE) PHYSFSX_printf(file, "%s=%s\n", i.first, i.second.get().string.c_str()); }