Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
  3.  * It is copyright by its individual contributors, as recorded in the
  4.  * project's Git history.  See COPYING.txt at the top level for license
  5.  * terms and a link to the Git history.
  6.  *
  7.  */
  8. /*
  9.  *
  10.  * Console variables
  11.  *
  12.  */
  13.  
  14. #include <cstdarg>
  15. #include <map>
  16. #include <stdlib.h>
  17. #include <physfs.h>
  18.  
  19. #include "console.h"
  20. #include "cvar.h"
  21. #include "dxxerror.h"
  22. #include "strutil.h"
  23. #include "u_mem.h"
  24. #include "game.h"
  25. #include "physfsx.h"
  26.  
  27. #include "dxxsconf.h"
  28. #include "compiler-range_for.h"
  29.  
  30. #define CVAR_MAX_LENGTH 1024
  31.  
  32. /* The list of cvars */
  33. typedef std::map<const char *, std::reference_wrapper<cvar_t>> cvar_list_type;
  34. static cvar_list_type cvar_list;
  35.  
  36. const char *cvar_t::operator=(const char *s)
  37. {
  38.         cvar_set_cvar(this, s);
  39.         return s;
  40. }
  41.  
  42. int         cvar_t::operator=(int i)         { cvar_set_cvarf(this, "%d", i);  return this->intval; }
  43.  
  44. void cvar_cmd_set(unsigned long argc, const char *const *const argv)
  45. {
  46.         char buf[CVAR_MAX_LENGTH];
  47.         int ret;
  48.  
  49.         if (argc == 2) {
  50.                 cvar_t *ptr;
  51.                
  52.                 if ((ptr = cvar_find(argv[1])))
  53.                         con_printf(CON_NORMAL, "%s: %s", ptr->name, ptr->string.c_str());
  54.                 else
  55.                         con_printf(CON_NORMAL, "set: variable %s not found", argv[1]);
  56.                 return;
  57.         }
  58.        
  59.         if (argc == 1) {
  60.                 range_for (const auto &i, cvar_list)
  61.                         con_printf(CON_NORMAL, "%s: %s", i.first, i.second.get().string.c_str());
  62.                 return;
  63.         }
  64.        
  65.         ret = snprintf(buf, sizeof(buf), "%s", argv[2]);
  66.         if (ret >= CVAR_MAX_LENGTH) {
  67.                 con_printf(CON_CRITICAL, "set: value too long (max %d characters)", CVAR_MAX_LENGTH);
  68.                 return;
  69.         }
  70.        
  71.         size_t position = ret;
  72.         for (int i = 3; i < argc; i++) {
  73.                 ret = snprintf(&buf[position], CVAR_MAX_LENGTH - position, " %s", argv[i]);
  74.                 position += ret;
  75.                 if (position >= CVAR_MAX_LENGTH)
  76.                 {
  77.                         con_printf(CON_CRITICAL, "set: value too long (max %d characters)", CVAR_MAX_LENGTH);
  78.                         return;
  79.                 }
  80.         }
  81.         cvar_set(argv[1], buf);
  82. }
  83.  
  84.  
  85. void cvar_init(void)
  86. {
  87.         cmd_addcommand("set", cvar_cmd_set, "set <name> <value>\n"  "    set variable <name> equal to <value>\n"
  88.                                             "set <name>\n"          "    show value of <name>\n"
  89.                                             "set\n"                 "    show value of all variables");
  90. }
  91.  
  92.  
  93. cvar_t *cvar_find(const char *cvar_name)
  94. {
  95.         const auto i = cvar_list.find(cvar_name);
  96.         return i == cvar_list.end() ? nullptr : &i->second.get();
  97. }
  98.  
  99.  
  100. const char *cvar_complete(const char *text)
  101. {
  102.         uint_fast32_t len = strlen(text);
  103.         if (!len)
  104.                 return NULL;
  105.         range_for (const auto &i, cvar_list)
  106.                 if (!d_strnicmp(text, i.first, len))
  107.                         return i.first;
  108.         return NULL;
  109. }
  110.  
  111.  
  112. /* Register a cvar */
  113. void cvar_registervariable (cvar_t &cvar)
  114. {
  115.         cvar.value = fl2f(strtod(cvar.string.c_str(), NULL));
  116.         cvar.intval = static_cast<int>(strtol(cvar.string.c_str(), NULL, 10));
  117.  
  118.         const auto i = cvar_list.insert(cvar_list_type::value_type(cvar.name, cvar));
  119.         if (!i.second)
  120.         {
  121.                 Int3();
  122.                 con_printf(CON_URGENT, "cvar %s already exists!", cvar.name);
  123.                 return;
  124.         }
  125.         /* insert at end of list */
  126. }
  127.  
  128.  
  129. /* Set a CVar's value */
  130. void cvar_set_cvar(cvar_t *cvar, const char *value)
  131. {
  132.         if (!cvar)
  133.                 return;
  134.        
  135.         cvar->string = value;
  136.         cvar->value = fl2f(strtod(value, NULL));
  137.         cvar->intval = static_cast<int>(strtol(value, NULL, 10));
  138.         con_printf(CON_VERBOSE, "%s: %s", cvar->name, value);
  139. }
  140.  
  141.  
  142. void cvar_set_cvarf(cvar_t *cvar, const char *fmt, ...)
  143. {
  144.         va_list arglist;
  145.         char buf[CVAR_MAX_LENGTH];
  146.         int n;
  147.        
  148.         va_start (arglist, fmt);
  149.         n = vsnprintf(buf, sizeof(buf), fmt, arglist);
  150.         va_end (arglist);
  151.        
  152.         if (n < 0 || n > CVAR_MAX_LENGTH) {
  153.                 Int3();
  154.                 con_printf(CON_CRITICAL, "error setting cvar %s", cvar->name);
  155.                 return;
  156.         }
  157.  
  158.         cvar_set_cvar(cvar, buf);
  159. }
  160.  
  161.  
  162. void cvar_set(const char *cvar_name, char *value)
  163. {
  164.         cvar_t *cvar;
  165.        
  166.         cvar = cvar_find(cvar_name);
  167.         if (!cvar) {
  168.                 Int3();
  169.                 con_printf(CON_NORMAL, "cvar %s not found", cvar_name);
  170.                 return;
  171.         }
  172.  
  173.         if (cvar->flags & CVAR_CHEAT && !cheats_enabled())
  174.         {
  175.                 con_printf(CON_NORMAL, "cvar %s is cheat protected.", cvar_name);
  176.                 return;
  177.         }
  178.  
  179.         cvar_set_cvar(cvar, value);
  180. }
  181.  
  182.  
  183. /* Write archive cvars to file */
  184. void cvar_write(PHYSFS_File *file)
  185. {
  186.         range_for (const auto &i, cvar_list)
  187.                 if (i.second.get().flags & CVAR_ARCHIVE)
  188.                         PHYSFSX_printf(file, "%s=%s\n", i.first, i.second.get().string.c_str());
  189. }
  190.