diff --git a/README b/README index 0daf2ffb..aa7b1f4d 100644 --- a/README +++ b/README @@ -200,6 +200,7 @@ New commands stopvideo - stop video capture print - print out the contents of a cvar + unset - unset a user created cvar banaddr - ban an ip address range from joining a game on this server, valid is either playernum or CIDR @@ -212,6 +213,7 @@ New commands flushbans - delete all bans net_restart - restart network subsystem to change latched settings + game_restart - Switch to another mod ------------------------------------------------------------ Miscellaneous ----- diff --git a/code/client/cl_main.c b/code/client/cl_main.c index be4d1bc9..38a8dce0 100644 --- a/code/client/cl_main.c +++ b/code/client/cl_main.c @@ -1030,6 +1030,18 @@ void CL_NextDemo( void ) { //====================================================================== +/* +===================== +CL_ShutdownVMs +===================== +*/ + +void CL_ShutdownVMs(void) +{ + CL_ShutdownCGame(); + CL_ShutdownUI(); +} + /* ===================== CL_ShutdownAll @@ -1251,6 +1263,9 @@ void CL_Disconnect( qboolean showMainMenu ) { CL_WritePacket(); } + // Remove pure paks + FS_PureServerSetLoadedPaks("", ""); + CL_ClearState (); // wipe the client connection @@ -1733,6 +1748,19 @@ void CL_Vid_Restart_f( void ) { } } +/* +================= +CL_Snd_Restart + +Restart the sound subsystem +================= +*/ +void CL_Snd_Restart(void) +{ + S_Shutdown(); + S_Init(); +} + /* ================= CL_Snd_Restart_f @@ -1742,10 +1770,9 @@ The cgame and game must also be forced to restart because handles will be invalid ================= */ -void CL_Snd_Restart_f( void ) { - S_Shutdown(); - S_Init(); - +void CL_Snd_Restart_f(void) +{ + CL_Snd_Restart(); CL_Vid_Restart_f(); } diff --git a/code/null/null_client.c b/code/null/null_client.c index 8b0d1ab5..e67b95b0 100644 --- a/code/null/null_client.c +++ b/code/null/null_client.c @@ -85,6 +85,10 @@ void CL_FlushMemory( void ) { void CL_StartHunkUsers( qboolean rendererOnly ) { } +void CL_Snd_Restart(void) +{ +} + void CL_ShutdownAll(void) {} qboolean CL_CDKeyValidate( const char *key, const char *checksum ) { return qtrue; } diff --git a/code/qcommon/common.c b/code/qcommon/common.c index aae81bda..b3dc1c07 100644 --- a/code/qcommon/common.c +++ b/code/qcommon/common.c @@ -93,8 +93,9 @@ int com_frameTime; int com_frameMsec; int com_frameNumber; -qboolean com_errorEntered; -qboolean com_fullyInitialized; +qboolean com_errorEntered = qfalse; +qboolean com_fullyInitialized = qfalse; +qboolean com_gameRestarting = qfalse; char com_errorMessage[MAXPRINTMSG]; @@ -243,9 +244,20 @@ void QDECL Com_Error( int code, const char *fmt, ... ) { va_list argptr; static int lastErrorTime; static int errorCount; + static qboolean calledSysError = qfalse; int currentTime; - Cvar_Set( "com_errorCode", va( "%i", code ) ); + if(com_errorEntered) + { + if(!calledSysError) + Sys_Error("recursive error after: %s", com_errorMessage); + + return; + } + + com_errorEntered = qtrue; + + Cvar_Set("com_errorCode", va("%i", code)); // when we are running automated scripts, make sure we // know if anything failed @@ -264,11 +276,6 @@ void QDECL Com_Error( int code, const char *fmt, ... ) { } lastErrorTime = currentTime; - if ( com_errorEntered ) { - Sys_Error( "recursive error after: %s", com_errorMessage ); - } - com_errorEntered = qtrue; - va_start (argptr,fmt); Q_vsnprintf (com_errorMessage, sizeof(com_errorMessage),fmt,argptr); va_end (argptr); @@ -303,12 +310,13 @@ void QDECL Com_Error( int code, const char *fmt, ... ) { VM_Forced_Unload_Start(); CL_FlushMemory( ); VM_Forced_Unload_Done(); - com_errorEntered = qfalse; CL_CDDialog(); } else { Com_Printf("Server didn't have CD\n" ); } FS_PureServerSetLoadedPaks("", ""); + + com_errorEntered = qfalse; longjmp (abortframe, -1); } else { CL_Shutdown (); @@ -317,6 +325,7 @@ void QDECL Com_Error( int code, const char *fmt, ... ) { Com_Shutdown (); + calledSysError = qtrue; Sys_Error ("%s", com_errorMessage); } @@ -2375,6 +2384,85 @@ void Com_Setenv_f(void) } } +/* +================== +Com_ExecuteCfg + +For controlling environment variables +================== +*/ + +void Com_ExecuteCfg(void) +{ + Cbuf_ExecuteText(EXEC_NOW, "exec default.cfg\n"); + Cbuf_Execute(); // Always execute after exec to prevent text buffer overflowing + + if(!Com_SafeMode()) + { + // skip the q3config.cfg and autoexec.cfg if "safe" is on the command line + Cbuf_ExecuteText(EXEC_NOW, "exec " Q3CONFIG_CFG "\n"); + Cbuf_Execute(); + Cbuf_ExecuteText(EXEC_NOW, "exec autoexec.cfg\n"); + Cbuf_Execute(); + } +} + +/* +================== +Com_GameRestart + +Change to a new mod properly with cleaning up cvars before switching. +================== +*/ + +void Com_GameRestart(int checksumFeed, qboolean clientRestart) +{ + // make sure no recursion can be triggered + if(!com_gameRestarting && com_fullyInitialized) + { + com_gameRestarting = qtrue; + + if(clientRestart) + { + CL_Disconnect(qfalse); + CL_ShutdownAll(); + } + + // Kill server if we have one + if(com_sv_running->integer) + SV_Shutdown("Game directory changed"); + + FS_Restart(checksumFeed); + + // Clean out any user and VM created cvars + Cvar_Restart(qtrue); + Com_ExecuteCfg(); + + // Restart sound subsystem so old handles are flushed + CL_Snd_Restart(); + + if(clientRestart) + CL_StartHunkUsers(qfalse); + + com_gameRestarting = qfalse; + } +} + +/* +================== +Com_GameRestart_f + +Expose possibility to change current running mod to the user +================== +*/ + +void Com_GameRestart_f(void) +{ + Cvar_Set("fs_game", Cmd_Argv(1)); + + Com_GameRestart(0, qtrue); +} + #ifndef STANDALONE // TTimo: centralizing the cl_cdkey stuff after I discovered a buffer overflow problem with the dedicated server version @@ -2593,17 +2681,9 @@ void Com_Init( char *commandLine ) { Cmd_AddCommand ("changeVectors", MSG_ReportChangeVectors_f ); Cmd_AddCommand ("writeconfig", Com_WriteConfig_f ); Cmd_SetCommandCompletionFunc( "writeconfig", Cmd_CompleteCfgName ); + Cmd_AddCommand("game_restart", Com_GameRestart_f); - // Make it execute the configuration files - Cbuf_AddText ("exec default.cfg\n"); - - // skip the q3config.cfg if "safe" is on the command line - if (!Com_SafeMode()) - Cbuf_AddText("exec " Q3CONFIG_CFG "\n"); - - Cbuf_AddText ("exec autoexec.cfg\n"); - - Cbuf_Execute (); + Com_ExecuteCfg(); // override anything from the config files with command line args Com_StartupVariable( NULL ); diff --git a/code/qcommon/cvar.c b/code/qcommon/cvar.c index a37de12c..5d52803f 100644 --- a/code/qcommon/cvar.c +++ b/code/qcommon/cvar.c @@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "q_shared.h" #include "qcommon.h" -cvar_t *cvar_vars; +cvar_t *cvar_vars = NULL; cvar_t *cvar_cheats; int cvar_modifiedFlags; @@ -33,7 +33,7 @@ cvar_t cvar_indexes[MAX_CVARS]; int cvar_numIndexes; #define FILE_HASH_SIZE 256 -static cvar_t* hashTable[FILE_HASH_SIZE]; +static cvar_t *hashTable[FILE_HASH_SIZE]; cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force); @@ -181,11 +181,14 @@ int Cvar_Flags(const char *var_name) Cvar_CommandCompletion ============ */ -void Cvar_CommandCompletion( void(*callback)(const char *s) ) { +void Cvar_CommandCompletion(void (*callback)(const char *s)) +{ cvar_t *cvar; - for ( cvar = cvar_vars ; cvar ; cvar = cvar->next ) { - callback( cvar->name ); + for(cvar = cvar_vars; cvar; cvar = cvar->next) + { + if(cvar->name) + callback(cvar->name); } } @@ -304,6 +307,7 @@ The flags will be or'ed in if the variable exists. cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) { cvar_t *var; long hash; + int index; if ( !var_name || ! var_value ) { Com_Error( ERR_FATAL, "Cvar_Get: NULL parameter" ); @@ -322,13 +326,15 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) { #endif var = Cvar_FindVar (var_name); - if ( var ) { - var_value = Cvar_Validate( var, var_value, qfalse ); + + if(var) + { + var_value = Cvar_Validate(var, var_value, qfalse); // if the C code is now specifying a variable that the user already // set a value for, take the new value as the reset value - if ( ( var->flags & CVAR_USER_CREATED ) && !( flags & CVAR_USER_CREATED ) - && var_value[0] ) { + if(var->flags & CVAR_USER_CREATED) + { var->flags &= ~CVAR_USER_CREATED; Z_Free( var->resetString ); var->resetString = CopyString( var_value ); @@ -343,13 +349,22 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) { var->latchedString = CopyString(var_value); } - - // ZOID--needs to be set so that cvars the game sets as - // SERVERINFO get sent to clients - cvar_modifiedFlags |= flags; } - + + // Make sure the game code cannot mark engine-added variables as gamecode vars + if(var->flags & CVAR_VM_CREATED) + { + if(!(flags & CVAR_VM_CREATED)) + var->flags &= ~CVAR_VM_CREATED; + } + else + { + if(flags & CVAR_VM_CREATED) + flags &= ~CVAR_VM_CREATED; + } + var->flags |= flags; + // only allow one non-empty reset string without a warning if ( !var->resetString[0] ) { // we don't have a reset string yet @@ -367,6 +382,10 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) { var->latchedString = NULL; // otherwise cvar_set2 would free it Cvar_Set2( var_name, s, qtrue ); Z_Free( s ); + + // ZOID--needs to be set so that cvars the game sets as + // SERVERINFO get sent to clients + cvar_modifiedFlags |= flags; } return var; @@ -375,11 +394,27 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) { // // allocate a new cvar // - if ( cvar_numIndexes >= MAX_CVARS ) { - Com_Error( ERR_FATAL, "MAX_CVARS" ); + + // find a free cvar + for(index = 0; index < MAX_CVARS; index++) + { + if(!cvar_indexes[index].name) + break; } - var = &cvar_indexes[cvar_numIndexes]; - cvar_numIndexes++; + + if(index >= MAX_CVARS) + { + if(!com_errorEntered) + Com_Error(ERR_FATAL, "Error: Too many cvars, cannot create a new one!"); + + return NULL; + } + + var = &cvar_indexes[index]; + + if(index >= cvar_numIndexes) + cvar_numIndexes = index + 1; + var->name = CopyString (var_name); var->string = CopyString (var_value); var->modified = qtrue; @@ -391,6 +426,10 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) { // link the variable in var->next = cvar_vars; + if(cvar_vars) + cvar_vars->prev = var; + + var->prev = NULL; cvar_vars = var; var->flags = flags; @@ -398,7 +437,13 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) { cvar_modifiedFlags |= var->flags; hash = generateHashValue(var_name); + var->hashIndex = hash; + var->hashNext = hashTable[hash]; + if(hashTable[hash]) + hashTable[hash]->hashPrev = var; + + var->hashPrev = NULL; hashTable[hash] = var; return var; @@ -470,15 +515,23 @@ cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) { value = var->resetString; } - value = Cvar_Validate( var, value, qtrue ); + value = Cvar_Validate(var, value, qtrue); - if((var->flags & CVAR_LATCH) && var->latchedString) { - if(!strcmp(value,var->latchedString)) + if((var->flags & CVAR_LATCH) && var->latchedString) + { + if(!strcmp(value, var->string)) + { + Z_Free(var->latchedString); + var->latchedString = NULL; + return var; + } + + if(!strcmp(value, var->latchedString)) return var; } - else if (!strcmp(value,var->string)) { + else if(!strcmp(value, var->string)) return var; - } + // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) cvar_modifiedFlags |= var->flags; @@ -609,12 +662,15 @@ Cvar_SetCheatState Any testing variables will be reset to the safe values ============ */ -void Cvar_SetCheatState( void ) { +void Cvar_SetCheatState(void) +{ cvar_t *var; // set all default vars to the safe value - for ( var = cvar_vars ; var ; var = var->next ) { - if ( var->flags & CVAR_CHEAT ) { + for(var = cvar_vars; var ; var = var->next) + { + if(var->flags & CVAR_CHEAT) + { // the CVAR_LATCHED|CVAR_CHEAT vars might escape the reset here // because of a different var->latchedString if (var->latchedString) @@ -622,9 +678,8 @@ void Cvar_SetCheatState( void ) { Z_Free(var->latchedString); var->latchedString = NULL; } - if (strcmp(var->resetString,var->string)) { - Cvar_Set( var->name, var->resetString ); - } + if (strcmp(var->resetString,var->string)) + Cvar_Set(var->name, var->resetString); } } } @@ -802,14 +857,16 @@ Appends lines containing "set variable value" for all variables with the archive flag set to qtrue. ============ */ -void Cvar_WriteVariables( fileHandle_t f ) { +void Cvar_WriteVariables(fileHandle_t f) +{ cvar_t *var; char buffer[1024]; - for (var = cvar_vars ; var ; var = var->next) { - if( Q_stricmp( var->name, "cl_cdkey" ) == 0 ) { + for (var = cvar_vars; var; var = var->next) + { + if(!var->name || Q_stricmp( var->name, "cl_cdkey" ) == 0) continue; - } + if( var->flags & CVAR_ARCHIVE ) { // write the latched value, even if it hasn't taken effect yet if ( var->latchedString ) { @@ -851,7 +908,8 @@ void Cvar_List_f( void ) { i = 0; for (var = cvar_vars ; var ; var = var->next, i++) { - if (match && !Com_Filter(match, var->name, qfalse)) continue; + if(!var->name || (match && !Com_Filter(match, var->name, qfalse))) + continue; if (var->flags & CVAR_SERVERINFO) { Com_Printf("S"); @@ -906,6 +964,113 @@ void Cvar_List_f( void ) { Com_Printf ("%i cvar indexes\n", cvar_numIndexes); } +/* +============ +Cvar_Unset + +Unsets a cvar +============ +*/ + +cvar_t *Cvar_Unset(cvar_t *cv) +{ + cvar_t *next = cv->next; + + if(cv->name) + Z_Free(cv->name); + if(cv->string) + Z_Free(cv->string); + if(cv->latchedString) + Z_Free(cv->latchedString); + if(cv->resetString) + Z_Free(cv->resetString); + + if(cv->prev) + cv->prev->next = cv->next; + else + cvar_vars = cv->next; + if(cv->next) + cv->next->prev = cv->prev; + + if(cv->hashPrev) + cv->hashPrev->hashNext = cv->hashNext; + else + hashTable[cv->hashIndex] = cv->hashNext; + if(cv->hashNext) + cv->hashNext->hashPrev = cv->hashPrev; + + Com_Memset(cv, '\0', sizeof(*cv)); + + return next; +} + +/* +============ +Cvar_Unset_f + +Unsets a userdefined cvar +============ +*/ + +void Cvar_Unset_f(void) +{ + cvar_t *cv; + + if(Cmd_Argc() != 2) + { + Com_Printf("Usage: %s \n", Cmd_Argv(0)); + return; + } + + cv = Cvar_FindVar(Cmd_Argv(1)); + + if(!cv) + return; + + if(cv->flags & CVAR_USER_CREATED) + Cvar_Unset(cv); + else + Com_Printf("Error: %s: Variable %s is not user created.\n", Cmd_Argv(0), cv->name); +} + + + +/* +============ +Cvar_Restart + +Resets all cvars to their hardcoded values and removes userdefined variables +and variables added via the VMs if requested. +============ +*/ + +void Cvar_Restart(qboolean unsetVM) +{ + cvar_t *curvar; + + curvar = cvar_vars; + + while(curvar) + { + if((curvar->flags & CVAR_USER_CREATED) || + (unsetVM && (curvar->flags & CVAR_VM_CREATED))) + { + // throw out any variables the user/vm created + curvar = Cvar_Unset(curvar); + continue; + } + + if(!(curvar->flags & (CVAR_ROM | CVAR_INIT | CVAR_NORESTART))) + { + // Just reset the rest to their default values. + Cvar_Set2(curvar->name, curvar->resetString, qfalse); + } + + curvar = curvar->next; + } +} + + /* ============ Cvar_Restart_f @@ -913,69 +1078,29 @@ Cvar_Restart_f Resets all cvars to their hardcoded values ============ */ -void Cvar_Restart_f( void ) { - cvar_t *var; - cvar_t **prev; - - prev = &cvar_vars; - while ( 1 ) { - var = *prev; - if ( !var ) { - break; - } - - // don't mess with rom values, or some inter-module - // communication will get broken (com_cl_running, etc) - if ( var->flags & ( CVAR_ROM | CVAR_INIT | CVAR_NORESTART ) ) { - prev = &var->next; - continue; - } - - // throw out any variables the user created - if ( var->flags & CVAR_USER_CREATED ) { - *prev = var->next; - if ( var->name ) { - Z_Free( var->name ); - } - if ( var->string ) { - Z_Free( var->string ); - } - if ( var->latchedString ) { - Z_Free( var->latchedString ); - } - if ( var->resetString ) { - Z_Free( var->resetString ); - } - // clear the var completely, since we - // can't remove the index from the list - Com_Memset( var, 0, sizeof( var ) ); - continue; - } - - Cvar_Set( var->name, var->resetString ); - - prev = &var->next; - } +void Cvar_Restart_f(void) +{ + Cvar_Restart(qfalse); } - - /* ===================== Cvar_InfoString ===================== */ -char *Cvar_InfoString( int bit ) { +char *Cvar_InfoString(int bit) +{ static char info[MAX_INFO_STRING]; cvar_t *var; info[0] = 0; - for (var = cvar_vars ; var ; var = var->next) { - if (var->flags & bit) { + for(var = cvar_vars; var; var = var->next) + { + if(var->name && (var->flags & bit)) Info_SetValueForKey (info, var->name, var->string); - } } + return info; } @@ -986,16 +1111,17 @@ Cvar_InfoString_Big handles large info strings ( CS_SYSTEMINFO ) ===================== */ -char *Cvar_InfoString_Big( int bit ) { +char *Cvar_InfoString_Big(int bit) +{ static char info[BIG_INFO_STRING]; cvar_t *var; info[0] = 0; - for (var = cvar_vars ; var ; var = var->next) { - if (var->flags & bit) { + for (var = cvar_vars; var; var = var->next) + { + if(var->name && (var->flags & bit)) Info_SetValueForKey_Big (info, var->name, var->string); - } } return info; } @@ -1034,13 +1160,15 @@ Cvar_Register basically a slightly modified Cvar_Get for the interpreted modules ===================== */ -void Cvar_Register( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags ) { +void Cvar_Register(vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags) +{ cvar_t *cv; - cv = Cvar_Get( varName, defaultValue, flags ); - if ( !vmCvar ) { + cv = Cvar_Get(varName, defaultValue, flags | CVAR_VM_CREATED); + + if (!vmCvar) return; - } + vmCvar->handle = cv - cvar_indexes; vmCvar->modificationCount = -1; Cvar_Update( vmCvar ); @@ -1105,7 +1233,11 @@ Cvar_Init Reads in all archived cvars ============ */ -void Cvar_Init (void) { +void Cvar_Init (void) +{ + Com_Memset(cvar_indexes, '\0', sizeof(cvar_indexes)); + Com_Memset(hashTable, '\0', sizeof(hashTable)); + cvar_cheats = Cvar_Get("sv_cheats", "1", CVAR_ROM | CVAR_SYSTEMINFO ); Cmd_AddCommand ("print", Cvar_Print_f); @@ -1121,6 +1253,9 @@ void Cvar_Init (void) { Cmd_SetCommandCompletionFunc( "seta", Cvar_CompleteCvarName ); Cmd_AddCommand ("reset", Cvar_Reset_f); Cmd_SetCommandCompletionFunc( "reset", Cvar_CompleteCvarName ); + Cmd_AddCommand ("unset", Cvar_Unset_f); + Cmd_SetCommandCompletionFunc("unset", Cvar_CompleteCvarName); + Cmd_AddCommand ("cvarlist", Cvar_List_f); Cmd_AddCommand ("cvar_restart", Cvar_Restart_f); } diff --git a/code/qcommon/files.c b/code/qcommon/files.c index 4f8b72f5..0b4a783c 100644 --- a/code/qcommon/files.c +++ b/code/qcommon/files.c @@ -248,7 +248,7 @@ static searchpath_t *fs_searchpaths; static int fs_readCount; // total bytes read static int fs_loadCount; // total files read static int fs_loadStack; // total files in memory -static int fs_packFiles; // total number of files in packs +static int fs_packFiles = 0; // total number of files in packs static int fs_checksumFeed; @@ -280,7 +280,7 @@ static fileHandleData_t fsh[MAX_FILE_HANDLES]; static qboolean fs_reordered; // never load anything from pk3 files that are not present at the server when pure -static int fs_numServerPaks; +static int fs_numServerPaks = 0; static int fs_serverPaks[MAX_SEARCH_PATHS]; // checksums static char *fs_serverPakNames[MAX_SEARCH_PATHS]; // pk3 names @@ -2802,6 +2802,8 @@ static void FS_Startup( const char *gameName ) Com_Printf( "----- FS_Startup -----\n" ); + fs_packFiles = 0; + fs_debug = Cvar_Get( "fs_debug", "0", 0 ); fs_basepath = Cvar_Get ("fs_basepath", Sys_DefaultInstallPath(), CVAR_INIT ); fs_basegame = Cvar_Get ("fs_basegame", "", CVAR_INIT ); @@ -3437,11 +3439,20 @@ FS_ConditionalRestart restart if necessary ================= */ -qboolean FS_ConditionalRestart( int checksumFeed ) { - if( fs_gamedirvar->modified || checksumFeed != fs_checksumFeed ) { - FS_Restart( checksumFeed ); +qboolean FS_ConditionalRestart(int checksumFeed) +{ + if(fs_gamedirvar->modified) + { + Com_GameRestart(checksumFeed, qfalse); return qtrue; } + + else if(checksumFeed != fs_checksumFeed) + { + FS_Restart(checksumFeed); + return qtrue; + } + return qfalse; } diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index 06807339..6942a62f 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -787,30 +787,33 @@ default values. ========================================================== */ -#define CVAR_ARCHIVE 1 // set to cause it to be saved to vars.rc - // used for system variables, not for player - // specific configurations -#define CVAR_USERINFO 2 // sent to server on connect or change -#define CVAR_SERVERINFO 4 // sent in response to front end requests -#define CVAR_SYSTEMINFO 8 // these cvars will be duplicated on all clients -#define CVAR_INIT 16 // don't allow change from console at all, - // but can be set from the command line -#define CVAR_LATCH 32 // will only change when C code next does - // a Cvar_Get(), so it can't be changed - // without proper initialization. modified - // will be set, even though the value hasn't - // changed yet -#define CVAR_ROM 64 // display only, cannot be set by user at all -#define CVAR_USER_CREATED 128 // created by a set command -#define CVAR_TEMP 256 // can be set even when cheats are disabled, but is not archived -#define CVAR_CHEAT 512 // can not be changed if cheats are disabled -#define CVAR_NORESTART 1024 // do not clear when a cvar_restart is issued +#define CVAR_ARCHIVE 0x0001 // set to cause it to be saved to vars.rc + // used for system variables, not for player + // specific configurations +#define CVAR_USERINFO 0x0002 // sent to server on connect or change +#define CVAR_SERVERINFO 0x0004 // sent in response to front end requests +#define CVAR_SYSTEMINFO 0x0008 // these cvars will be duplicated on all clients +#define CVAR_INIT 0x0010 // don't allow change from console at all, + // but can be set from the command line +#define CVAR_LATCH 0x0020 // will only change when C code next does + // a Cvar_Get(), so it can't be changed + // without proper initialization. modified + // will be set, even though the value hasn't + // changed yet +#define CVAR_ROM 0x0040 // display only, cannot be set by user at all +#define CVAR_USER_CREATED 0x0080 // created by a set command +#define CVAR_TEMP 0x0100 // can be set even when cheats are disabled, but is not archived +#define CVAR_CHEAT 0x0200 // can not be changed if cheats are disabled +#define CVAR_NORESTART 0x0400 // do not clear when a cvar_restart is issued -#define CVAR_SERVER_CREATED 2048 // cvar was created by a server the client connected to. +#define CVAR_SERVER_CREATED 0x0800 // cvar was created by a server the client connected to. +#define CVAR_VM_CREATED 0x1000 // cvar was created exclusively in one of the VMs. #define CVAR_NONEXISTENT 0xFFFFFFFF // Cvar doesn't exist. // nothing outside the Cvar_*() functions should modify these fields! -typedef struct cvar_s { +typedef struct cvar_s cvar_t; + +struct cvar_s { char *name; char *string; char *resetString; // cvar_restart will reset to this value @@ -824,9 +827,13 @@ typedef struct cvar_s { qboolean integral; float min; float max; - struct cvar_s *next; - struct cvar_s *hashNext; -} cvar_t; + + cvar_t *next; + cvar_t *prev; + cvar_t *hashNext; + cvar_t *hashPrev; + int hashIndex; +}; #define MAX_CVAR_VALUE_STRING 256 diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h index 0078e446..de1dba0f 100644 --- a/code/qcommon/qcommon.h +++ b/code/qcommon/qcommon.h @@ -545,6 +545,7 @@ char *Cvar_InfoString_Big( int bit ); void Cvar_InfoStringBuffer( int bit, char *buff, int buffsize ); void Cvar_CheckRange( cvar_t *cv, float minVal, float maxVal, qboolean shouldBeIntegral ); +void Cvar_Restart(qboolean unsetVM); void Cvar_Restart_f( void ); void Cvar_CompleteCvarName( char *args, int argNum ); @@ -797,6 +798,7 @@ void QDECL Com_Printf( const char *fmt, ... ) __attribute__ ((format (printf, void QDECL Com_DPrintf( const char *fmt, ... ) __attribute__ ((format (printf, 1, 2))); void QDECL Com_Error( int code, const char *fmt, ... ) __attribute__ ((format (printf, 2, 3))); void Com_Quit_f( void ); +void Com_GameRestart(int checksumFeed, qboolean clientRestart); int Com_Milliseconds( void ); // will be journaled properly unsigned Com_BlockChecksum( const void *buffer, int length ); @@ -974,6 +976,9 @@ void CL_FlushMemory( void ); void CL_StartHunkUsers( qboolean rendererOnly ); // start all the client stuff using the hunk +void CL_Snd_Restart(void); +// Restart sound subsystem + void Key_KeynameCompletion( void(*callback)(const char *s) ); // for keyname autocompletion