Commit 50d2c954 by LJ Sonic

Merge branch 'next' of https://git.do.srb2.org/STJr/SRB2.git into resend-gamestate

parents 9dd5c113 e9fce200
......@@ -43,7 +43,7 @@ jobs:
- v1-SRB2-APT
- run:
name: Install SDK
command: apt-get -qq -y --no-install-recommends install git build-essential nasm libpng-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 libopenmpt-dev:i386 gettext ccache wget gcc-multilib upx openssh-client
command: apt-get -qq -y --no-install-recommends install git build-essential nasm libpng-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 libcurl4-openssl-dev:i386 libopenmpt-dev:i386 gettext ccache wget gcc-multilib upx openssh-client
- save_cache:
key: v1-SRB2-APT
......@@ -71,4 +71,4 @@ jobs:
- save_cache:
key: v1-SRB2-{{ .Branch }}-{{ checksum "objs/Linux/SDL/Release/depend.dep" }}
paths:
- /root/.ccache
\ No newline at end of file
- /root/.ccache
version: 2.2.6.{branch}-{build}
version: 2.2.8.{branch}-{build}
os: MinGW
environment:
......
......@@ -32,6 +32,7 @@ set(SRB2_CORE_SOURCES
m_fixed.c
m_menu.c
m_misc.c
m_perfstats.c
m_queue.c
m_random.c
md5.c
......@@ -97,12 +98,12 @@ set(SRB2_CORE_HEADERS
m_fixed.h
m_menu.h
m_misc.h
m_perfstats.h
m_queue.h
m_random.h
m_swap.h
md5.h
mserv.h
http-mserv.h
p5prof.h
s_sound.h
screen.h
......@@ -128,7 +129,8 @@ set(SRB2_CORE_RENDER_SOURCES
r_sky.c
r_splats.c
r_things.c
r_patch.c
r_textures.c
r_picformats.c
r_portal.c
r_bsp.h
......@@ -144,7 +146,8 @@ set(SRB2_CORE_RENDER_SOURCES
r_splats.h
r_state.h
r_things.h
r_patch.h
r_textures.h
r_picformats.h
r_portal.h
)
......@@ -230,6 +233,8 @@ set(SRB2_CONFIG_HAVE_OPENMPT ON CACHE BOOL
"Enable OpenMPT support.")
set(SRB2_CONFIG_HAVE_CURL ON CACHE BOOL
"Enable curl support, used for downloading files via HTTP.")
set(SRB2_CONFIG_HAVE_THREADS ON CACHE BOOL
"Enable multithreading support.")
if(${CMAKE_SYSTEM} MATCHES Windows)
set(SRB2_CONFIG_HAVE_MIXERX ON CACHE BOOL
"Enable SDL Mixer X support.")
......@@ -262,6 +267,7 @@ set(SRB2_LUA_SOURCES
lua_mathlib.c
lua_mobjlib.c
lua_playerlib.c
lua_polyobjlib.c
lua_script.c
lua_skinlib.c
lua_thinkerlib.c
......@@ -469,6 +475,12 @@ if(${SRB2_CONFIG_HAVE_CURL})
endif()
endif()
if(${SRB2_CONFIG_HAVE_THREADS})
set(SRB2_HAVE_THREADS ON)
set(SRB2_CORE_HEADERS ${SRB2_CORE_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/i_threads.h)
add_definitions(-DHAVE_THREADS)
endif()
if(${SRB2_CONFIG_HWRENDER})
add_definitions(-DHWRENDER)
set(SRB2_HWRENDER_SOURCES
......
......@@ -56,10 +56,10 @@
# Compile with GCC 4.6x version, add 'GCC46=1'
# Compile a profile version, add 'PROFILEMODE=1'
# Compile a debug version, add 'DEBUGMODE=1'
# Compile with extra warnings, add 'WARNINGMODE=1'
# Compile with less warnings, add 'RELAXWARNINGS=1'
# Generate compiler errors for most compiler warnings, add 'ERRORMODE=1'
# Compile without NASM's tmap.nas, add 'NOASM=1'
# Compile without 3D hardware support, add 'NOHW=1'
# Compile without 3D sound support, add 'NOHS=1'
# Compile with GDBstubs, add 'RDB=1'
# Compile without PNG, add 'NOPNG=1'
# Compile without zlib, add 'NOZLIB=1'
......@@ -80,6 +80,58 @@
#
#############################################################################
ALL_SYSTEMS=\
PANDORA\
LINUX64\
MINGW64\
HAIKU\
DUMMY\
DJGPPDOS\
MINGW\
UNIX\
LINUX\
SOLARIS\
FREEBSD\
MACOSX\
SDL\
# check for user specified system
ifeq (,$(filter $(ALL_SYSTEMS),$(.VARIABLES)))
ifeq ($(OS),Windows_NT) # all windows are Windows_NT...
$(info Detected a Windows system, compiling for 32-bit MinGW SDL2...)
# go for a 32-bit sdl mingw exe by default
MINGW=1
SDL=1
WINDOWSHELL=1
else # if you on the *nix
system:=$(shell uname -s)
ifeq ($(system),Linux)
new_system=LINUX
else
$(error \
Could not automatically detect your system,\
try specifying a system manually)
endif
ifeq ($(shell getconf LONG_BIT),64)
system+=64-bit
new_system:=$(new_system)64
endif
$(info Detected $(system) ($(new_system))...)
$(new_system)=1
endif
endif
# SRB2 data files
D_DIR?=../bin/Resources
D_FILES=$(D_DIR)/srb2.pk3 \
......@@ -119,7 +171,6 @@ NOPNG=1
NOZLIB=1
NONET=1
NOHW=1
NOHS=1
NOASM=1
NOIPX=1
EXENAME?=srb2dummy
......@@ -141,7 +192,6 @@ endif
ifdef PANDORA
NONX86=1
NOHW=1
NOHS=1
endif
ifndef NOOPENMPT
......@@ -223,13 +273,6 @@ else
$(OBJDIR)/hw_md2load.o $(OBJDIR)/hw_md3load.o $(OBJDIR)/hw_model.o $(OBJDIR)/u_list.o $(OBJDIR)/hw_batching.o
endif
ifdef NOHS
OPTS+=-DNOHS
else
OPTS+=-DHW3SOUND
OBJS+=$(OBJDIR)/hw3sound.o
endif
OPTS += -DCOMPVERSION
ifndef NONX86
......@@ -443,6 +486,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/m_fixed.o \
$(OBJDIR)/m_menu.o \
$(OBJDIR)/m_misc.o \
$(OBJDIR)/m_perfstats.o \
$(OBJDIR)/m_random.o \
$(OBJDIR)/m_queue.o \
$(OBJDIR)/info.o \
......@@ -474,7 +518,8 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/r_sky.o \
$(OBJDIR)/r_splats.o \
$(OBJDIR)/r_things.o \
$(OBJDIR)/r_patch.o \
$(OBJDIR)/r_textures.o \
$(OBJDIR)/r_picformats.o \
$(OBJDIR)/r_portal.o \
$(OBJDIR)/screen.o \
$(OBJDIR)/v_video.o \
......@@ -562,8 +607,9 @@ ifndef VALGRIND
ifndef NOOBJDUMP
@echo Dumping debugging info
$(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(EXENAME) > $(BIN)/$(DBGNAME).txt
ifdef WINDOWSHELL
-$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt
ifndef WINDOWSHELL
else
-$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt
endif
endif
......@@ -583,8 +629,9 @@ endif
reobjdump:
@echo Redumping debugging info
$(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(DBGNAME) > $(BIN)/$(DBGNAME).txt
ifdef WINDOWSHELL
-$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt
ifndef WINDOWSHELL
else
-$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt
endif
......@@ -750,19 +797,6 @@ $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
endif
ifndef NOHS
$(OBJDIR)/s_ds3d.o: hardware/s_ds3d/s_ds3d.c hardware/hw3dsdrv.h \
hardware/hw_dll.h
$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_ds3d.o $(WFLAGS) -D_WINDOWS -mwindows -c hardware/s_ds3d/s_ds3d.c
$(OBJDIR)/s_fmod.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \
hardware/hw_dll.h
$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_fmod.o $(WFLAGS) -D_WINDOWS -mwindows -c hardware/s_fmod/s_fmod.c
$(OBJDIR)/s_openal.o: hardware/s_openal/s_openal.c hardware/hw3dsdrv.h \
hardware/hw_dll.h
$(CC) $(ARCHOPTS) -Os -o $(OBJDIR)/s_openal.o $(WFLAGS) -D_WINDOWS -mwindows -c hardware/s_openal/s_openal.c
endif
endif
endif
......
......@@ -48,7 +48,9 @@ endif
# Automatically set version flag, but not if one was manually set
ifeq (,$(filter GCC%,$(.VARIABLES)))
ifneq (,$(findstring gcc,$(shell $(CC) --version))) # if it's GCC
version:=$(shell $(CC) --version)
# check if this is in fact GCC
ifneq (,$(or $(findstring gcc,$(version)),$(findstring GCC,$(version))))
version:=$(shell $(CC) -dumpversion)
# Turn version into words of major, minor
......@@ -208,10 +210,7 @@ WFLAGS=-Wall
ifndef GCC295
#WFLAGS+=-Wno-packed
endif
ifdef ERRORMODE
WARNINGMODE=1
endif
ifdef WARNINGMODE
ifndef RELAXWARNINGS
WFLAGS+=-W
#WFLAGS+=-Wno-sign-compare
ifndef GCC295
......
......@@ -8,8 +8,8 @@
UINT8 cdaudio_started = 0;
consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cd_volume = CVAR_INIT ("cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL);
consvar_t cdUpdate = CVAR_INIT ("cd_update","1",CV_SAVE, NULL, NULL);
void I_InitCD(void){}
......
......@@ -16,7 +16,7 @@ boolean allow_fullscreen = false;
consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, NULL);
void I_StartupGraphics(void){}
void I_ShutdownGraphics(void){}
......
......@@ -47,5 +47,6 @@ OBJS:=$(OBJS) \
$(OBJDIR)/lua_skinlib.o \
$(OBJDIR)/lua_thinkerlib.o \
$(OBJDIR)/lua_maplib.o \
$(OBJDIR)/lua_polyobjlib.o \
$(OBJDIR)/lua_blockmaplib.o \
$(OBJDIR)/lua_hudlib.o
......@@ -19,6 +19,7 @@
#include "lauxlib.h"
#include "lualib.h"
#include "../m_fixed.h"
/* macro to `unsign' a character */
#define uchar(c) ((unsigned char)(c))
......@@ -790,7 +791,7 @@ static int str_format (lua_State *L) {
case 'e': case 'E': case 'f':
case 'g': case 'G': {
lua_Number n = luaL_checknumber(L, arg);
sprintf(buff, form, (double)n);
sprintf(buff, form, (double)n / FRACUNIT);
break;
}
case 'q': {
......
......@@ -322,8 +322,8 @@ static void Arith (lua_State *L, StkId ra, TValue *rb,
case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
case TM_DIV: if (nc == 0) { lua_pushliteral(L, "divide by zero error"); lua_error(L); } else setnvalue(ra, luai_numdiv(nb, nc)); break;
case TM_MOD: if (nc == 0) { lua_pushliteral(L, "modulo by zero error"); lua_error(L); } else setnvalue(ra, luai_nummod(nb, nc)); break;
case TM_DIV: if (nc == 0) { luaG_runerror(L, "divide by zero error"); } else setnvalue(ra, luai_numdiv(nb, nc)); break;
case TM_MOD: if (nc == 0) { luaG_runerror(L, "modulo by zero error"); } else setnvalue(ra, luai_nummod(nb, nc)); break;
case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
case TM_AND: setnvalue(ra, luai_numand(nb, nc)); break;
......@@ -492,8 +492,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
if (ttisnumber(rb) && ttisnumber(rc)) {
lua_Number nb = nvalue(rb), nc = nvalue(rc);
if (nc == 0) {
lua_pushliteral(L, "divide by zero error");
lua_error(L);
luaG_runerror(L, "divide by zero error");
}
else
setnvalue(ra, luai_numdiv(nb, nc));
......@@ -508,8 +507,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
if (ttisnumber(rb) && ttisnumber(rc)) {
lua_Number nb = nvalue(rb), nc = nvalue(rc);
if (nc == 0) {
lua_pushliteral(L, "modulo by zero error");
lua_error(L);
luaG_runerror(L, "modulo by zero error");
}
else
setnvalue(ra, luai_nummod(nb, nc));
......
......@@ -79,7 +79,7 @@ CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}};
// First implementation is 26 (2.1.21), so earlier configs default at 25 (2.1.20)
// Also set CV_HIDEN during runtime, after config is loaded
static boolean execversion_enabled = false;
consvar_t cv_execversion = {"execversion","25",CV_CALL,CV_Unsigned, CV_EnforceExecVersion, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_execversion = CVAR_INIT ("execversion","25",CV_CALL,CV_Unsigned, CV_EnforceExecVersion);
// for default joyaxis detection
static boolean joyaxis_default = false;
......@@ -165,6 +165,8 @@ void COM_BufAddTextEx(const char *ptext, int flags)
*/
void COM_BufInsertTextEx(const char *ptext, int flags)
{
const INT32 old_wait = com_wait;
char *temp = NULL;
size_t templen;
......@@ -176,10 +178,14 @@ void COM_BufInsertTextEx(const char *ptext, int flags)
VS_Clear(&com_text);
}
com_wait = 0;
// add the entire text of the file (or alias)
COM_BufAddTextEx(ptext, flags);
COM_BufExecute(); // do it right away
com_wait += old_wait;
// add the copied off data
if (templen)
{
......@@ -560,7 +566,7 @@ static boolean COM_Exists(const char *com_name)
* \param partial The partial name of the command (potentially).
* \param skips Number of commands to skip.
* \return The complete command name, or NULL.
* \sa CV_CompleteVar
* \sa CV_CompleteAlias, CV_CompleteVar
*/
const char *COM_CompleteCommand(const char *partial, INT32 skips)
{
......@@ -581,6 +587,32 @@ const char *COM_CompleteCommand(const char *partial, INT32 skips)
return NULL;
}
/** Completes the name of an alias.
*
* \param partial The partial name of the alias (potentially).
* \param skips Number of aliases to skip.
* \return The complete alias name, or NULL.
* \sa CV_CompleteCommand, CV_CompleteVar
*/
const char *COM_CompleteAlias(const char *partial, INT32 skips)
{
cmdalias_t *a;
size_t len;
len = strlen(partial);
if (!len)
return NULL;
// check functions
for (a = com_alias; a; a = a->next)
if (!strncmp(partial, a->name, len))
if (!skips--)
return a->name;
return NULL;
}
/** Parses a single line of text into arguments and tries to execute it.
* The text can come from the command buffer, a remote client, or stdin.
*
......@@ -875,6 +907,9 @@ static void COM_Help_f(void)
CONS_Printf(" Current value: %s\n", cvar->string);
else
CONS_Printf(" Current value: %d\n", cvar->value);
if (cvar->revert.v.string != NULL && strcmp(cvar->revert.v.string, cvar->string) != 0)
CONS_Printf(" Value before netgame: %s\n", cvar->revert.v.string);
}
else
{
......@@ -1201,7 +1236,7 @@ static consvar_t *CV_FindNetVar(UINT16 netid)
{
consvar_t *cvar;
if (netid >= consvar_number_of_netids)
if (netid > consvar_number_of_netids)
return NULL;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
......@@ -1262,12 +1297,12 @@ void CV_RegisterVar(consvar_t *variable)
// check net variables
if (variable->flags & CV_NETVAR)
{
variable->netid = consvar_number_of_netids++;
/* in case of overflow... */
if (variable->netid > consvar_number_of_netids)
if (consvar_number_of_netids == UINT16_MAX)
I_Error("Way too many netvars");
variable->netid = ++consvar_number_of_netids;
#ifdef OLD22DEMOCOMPAT
CV_RegisterOldDemoVar(variable);
#endif
......@@ -1280,6 +1315,7 @@ void CV_RegisterVar(consvar_t *variable)
consvar_vars = variable;
}
variable->string = variable->zstring = NULL;
memset(&variable->revert, 0, sizeof variable->revert);
variable->changed = 0; // new variable has not been modified by the user
#ifdef PARANOIA
......@@ -1321,7 +1357,7 @@ static const char *CV_StringValue(const char *var_name)
* \param partial The partial name of the variable (potentially).
* \param skips Number of variables to skip.
* \return The complete variable name, or NULL.
* \sa COM_CompleteCommand
* \sa COM_CompleteCommand, CV_CompleteAlias
*/
const char *CV_CompleteVar(char *partial, INT32 skips)
{
......@@ -1392,6 +1428,18 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
for (i = MAXVAL+1; var->PossibleValue[i].strvalue; i++)
if (v == var->PossibleValue[i].value || !stricmp(var->PossibleValue[i].strvalue, valstr))
{
if (client && execversion_enabled)
{
if (var->revert.allocated)
{
Z_Free(var->revert.v.string);
}
var->revert.v.const_munge = var->PossibleValue[i].strvalue;
return;
}
var->value = var->PossibleValue[i].value;
var->string = var->PossibleValue[i].strvalue;
goto finish;
......@@ -1452,12 +1500,36 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
// ...or not.
goto badinput;
found:
if (client && execversion_enabled)
{
if (var->revert.allocated)
{
Z_Free(var->revert.v.string);
}
var->revert.v.const_munge = var->PossibleValue[i].strvalue;
return;
}
var->value = var->PossibleValue[i].value;
var->string = var->PossibleValue[i].strvalue;
goto finish;
}
}
if (client && execversion_enabled)
{
if (var->revert.allocated)
{
Z_Free(var->revert.v.string);
}
var->revert.v.string = Z_StrDup(valstr);
return;
}
// free the old value string
Z_Free(var->zstring);
......@@ -1676,8 +1748,19 @@ static void CV_LoadVars(UINT8 **p,
serverloading = true;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (cvar->flags & CV_NETVAR)
{
if (client && cvar->revert.v.string == NULL)
{
cvar->revert.v.const_munge = cvar->string;
cvar->revert.allocated = ( cvar->zstring != NULL );
cvar->zstring = NULL;/* don't free this */
}
Setvalue(cvar, cvar->defaultvalue, true);
}
}
count = READUINT16(*p);
while (count--)
......@@ -1691,6 +1774,26 @@ static void CV_LoadVars(UINT8 **p,
serverloading = false;
}
void CV_RevertNetVars(void)
{
consvar_t * cvar;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (cvar->revert.v.string != NULL)
{
Setvalue(cvar, cvar->revert.v.string, false);
if (cvar->revert.allocated)
{
Z_Free(cvar->revert.v.string);
}
cvar->revert.v.string = NULL;
}
}
}
void CV_LoadNetVars(UINT8 **p)
{
CV_LoadVars(p, ReadNetVar);
......@@ -1764,6 +1867,14 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth)
// send the value of the variable
UINT8 buf[128];
UINT8 *p = buf;
// Loading from a config in a netgame? Set revert value.
if (client && execversion_enabled)
{
Setvalue(var, value, true);
return;
}
if (!(server || (addedtogame && IsPlayerAdmin(consoleplayer))))
{
CONS_Printf(M_GetText("Only the server or admin can change: %s %s\n"), var->name, var->string);
......@@ -2297,18 +2408,43 @@ void CV_SaveVariables(FILE *f)
{
char stringtowrite[MAXTEXTCMD+1];
// Silly hack for Min/Max vars
if (!strcmp(cvar->string, "MAX") || !strcmp(cvar->string, "MIN"))
const char * string;
if (cvar->revert.v.string != NULL)
{
if (cvar->flags & CV_FLOAT)
sprintf(stringtowrite, "%f", FIXED_TO_FLOAT(cvar->value));
else
sprintf(stringtowrite, "%d", cvar->value);
string = cvar->revert.v.string;
}
else
strcpy(stringtowrite, cvar->string);
{
string = cvar->string;
}
// Silly hack for Min/Max vars
#define MINVAL 0
#define MAXVAL 1
if (
cvar->PossibleValue != NULL &&
cvar->PossibleValue[0].strvalue &&
stricmp(cvar->PossibleValue[0].strvalue, "MIN") == 0
){ // bounded cvar
int which = stricmp(string, "MAX") == 0;
if (which || stricmp(string, "MIN") == 0)
{
INT32 value = cvar->PossibleValue[which].value;
fprintf(f, "%s \"%s\"\n", cvar->name, stringtowrite);
if (cvar->flags & CV_FLOAT)
sprintf(stringtowrite, "%f", FIXED_TO_FLOAT(value));
else
sprintf(stringtowrite, "%d", value);
string = stringtowrite;
}
}
#undef MINVAL
#undef MAXVAL
fprintf(f, "%s \"%s\"\n", cvar->name, string);
}
}
......@@ -2370,15 +2506,6 @@ skipwhite:
}
}
// parse single characters
if (c == '{' || c == '}' || c == ')' || c == '(' || c == '\'')
{
com_token[len] = c;
len++;
com_token[len] = 0;
return data + 1;
}
// parse a regular word
do
{
......@@ -2398,8 +2525,6 @@ skipwhite:
len++;
c = *data;
}
if (c == '{' || c == '}' || c == ')'|| c == '(' || c == '\'')
break;
} while (c > 32);
com_token[len] = 0;
......
......@@ -49,6 +49,8 @@ size_t COM_FirstOption(void);
// match existing command or NULL
const char *COM_CompleteCommand(const char *partial, INT32 skips);
const char *COM_CompleteAlias(const char *partial, INT32 skips);
// insert at queu (at end of other command)
#define COM_BufAddText(s) COM_BufAddTextEx(s, 0)
void COM_BufAddTextEx(const char *btext, int flags);
......@@ -138,12 +140,26 @@ typedef struct consvar_s //NULL, NULL, 0, NULL, NULL |, 0, NULL, NULL, 0, 0, NUL
const char *string; // value in string
char *zstring; // Either NULL or same as string.
// If non-NULL, must be Z_Free'd later.
struct
{
char allocated; // whether to Z_Free
union
{
char * string;
const char * const_munge;
} v;
} revert; // value of netvar before joining netgame
UINT16 netid; // used internaly : netid for send end receive
// used only with CV_NETVAR
char changed; // has variable been changed by the user? 0 = no, 1 = yes
struct consvar_s *next;
} consvar_t;
/* name, defaultvalue, flags, PossibleValue, func */
#define CVAR_INIT( ... ) \
{ __VA_ARGS__, 0, NULL, NULL, {0}, 0U, (char)0, NULL }
#ifdef OLD22DEMOCOMPAT
typedef struct old_demo_var old_demo_var_t;