Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 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
}