[quake3-commits] r1745 - in trunk: . code/client code/null code/qcommon

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Mon Nov 9 17:41:42 EST 2009


Author: thilo
Date: 2009-11-09 17:41:42 -0500 (Mon, 09 Nov 2009)
New Revision: 1745

Modified:
   trunk/README
   trunk/code/client/cl_main.c
   trunk/code/null/null_client.c
   trunk/code/qcommon/common.c
   trunk/code/qcommon/cvar.c
   trunk/code/qcommon/files.c
   trunk/code/qcommon/q_shared.h
   trunk/code/qcommon/qcommon.h
Log:
- Add unset command for cvars created by the user
- Fix crash bug when maximum number of cvars has been reached
- Fix cvar_restart
- Add possibility to cleanly switch mods ingame (#2819)


Modified: trunk/README
===================================================================
--- trunk/README	2009-11-09 13:50:48 UTC (rev 1744)
+++ trunk/README	2009-11-09 22:41:42 UTC (rev 1745)
@@ -200,6 +200,7 @@
   stopvideo               - stop video capture
 
   print                   - print out the contents of a cvar
+  unset                   - unset a user created cvar
 
   banaddr <range>         - ban an ip address range from joining a game on this
                             server, valid <range> is either playernum or CIDR
@@ -212,6 +213,7 @@
   flushbans               - delete all bans
 
   net_restart             - restart network subsystem to change latched settings
+  game_restart <fs_game>  - Switch to another mod
 
 ------------------------------------------------------------ Miscellaneous -----
 

Modified: trunk/code/client/cl_main.c
===================================================================
--- trunk/code/client/cl_main.c	2009-11-09 13:50:48 UTC (rev 1744)
+++ trunk/code/client/cl_main.c	2009-11-09 22:41:42 UTC (rev 1745)
@@ -1032,6 +1032,18 @@
 
 /*
 =====================
+CL_ShutdownVMs
+=====================
+*/
+
+void CL_ShutdownVMs(void)
+{
+	CL_ShutdownCGame();
+	CL_ShutdownUI();
+}
+
+/*
+=====================
 CL_ShutdownAll
 =====================
 */
@@ -1251,6 +1263,9 @@
 		CL_WritePacket();
 	}
 	
+	// Remove pure paks
+	FS_PureServerSetLoadedPaks("", "");
+	
 	CL_ClearState ();
 
 	// wipe the client connection
@@ -1735,6 +1750,19 @@
 
 /*
 =================
+CL_Snd_Restart
+
+Restart the sound subsystem
+=================
+*/
+void CL_Snd_Restart(void)
+{
+	S_Shutdown();
+	S_Init();
+}
+
+/*
+=================
 CL_Snd_Restart_f
 
 Restart the sound subsystem
@@ -1742,10 +1770,9 @@
 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();
 }
 

Modified: trunk/code/null/null_client.c
===================================================================
--- trunk/code/null/null_client.c	2009-11-09 13:50:48 UTC (rev 1744)
+++ trunk/code/null/null_client.c	2009-11-09 22:41:42 UTC (rev 1745)
@@ -85,6 +85,10 @@
 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; }

Modified: trunk/code/qcommon/common.c
===================================================================
--- trunk/code/qcommon/common.c	2009-11-09 13:50:48 UTC (rev 1744)
+++ trunk/code/qcommon/common.c	2009-11-09 22:41:42 UTC (rev 1745)
@@ -93,8 +93,9 @@
 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,10 +244,21 @@
 	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
 	if ( com_buildScript && com_buildScript->integer ) {
@@ -264,11 +276,6 @@
 	}
 	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 @@
 			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 @@
 
 	Com_Shutdown ();
 
+	calledSysError = qtrue;
 	Sys_Error ("%s", com_errorMessage);
 }
 
@@ -2375,6 +2384,85 @@
         }
 }
 
+/*
+==================
+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,18 +2681,10 @@
 	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");
+	Com_ExecuteCfg();
 
-	// 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 ();
-
 	// override anything from the config files with command line args
 	Com_StartupVariable( NULL );
 

Modified: trunk/code/qcommon/cvar.c
===================================================================
--- trunk/code/qcommon/cvar.c	2009-11-09 13:50:48 UTC (rev 1744)
+++ trunk/code/qcommon/cvar.c	2009-11-09 22:41:42 UTC (rev 1745)
@@ -24,7 +24,7 @@
 #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 @@
 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 @@
 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 @@
 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 @@
 #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 @@
 				
 				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;
 
-		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 @@
 			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 @@
 	//
 	// 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 @@
 
 	// 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_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 @@
 		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 @@
 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 @@
 				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 @@
 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 @@
 	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");
@@ -908,74 +966,141 @@
 
 /*
 ============
-Cvar_Restart_f
+Cvar_Unset
 
-Resets all cvars to their hardcoded values
+Unsets a cvar
 ============
 */
-void Cvar_Restart_f( void ) {
-	cvar_t	*var;
-	cvar_t	**prev;
 
-	prev = &cvar_vars;
-	while ( 1 ) {
-		var = *prev;
-		if ( !var ) {
-			break;
-		}
+cvar_t *Cvar_Unset(cvar_t *cv)
+{
+	cvar_t *next = cv->next;
 
-		// 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;
-		}
+	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);
 
-		// 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;
-		}
+	if(cv->prev)
+		cv->prev->next = cv->next;
+	else
+		cvar_vars = cv->next;
+	if(cv->next)
+		cv->next->prev = cv->prev;
 
-		Cvar_Set( var->name, var->resetString );
+	if(cv->hashPrev)
+		cv->hashPrev->hashNext = cv->hashNext;
+	else
+		hashTable[cv->hashIndex] = cv->hashNext;
+	if(cv->hashNext)
+		cv->hashNext->hashPrev = cv->hashPrev;
 
-		prev = &var->next;
+	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 <varname>\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
+
+Resets all cvars to their hardcoded values
+============
+*/
+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 @@
   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 @@
 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 @@
 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 @@
 	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);
 }

Modified: trunk/code/qcommon/files.c
===================================================================
--- trunk/code/qcommon/files.c	2009-11-09 13:50:48 UTC (rev 1744)
+++ trunk/code/qcommon/files.c	2009-11-09 22:41:42 UTC (rev 1745)
@@ -248,7 +248,7 @@
 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 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 @@
 
 	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 @@
 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;
 }
 

Modified: trunk/code/qcommon/q_shared.h
===================================================================
--- trunk/code/qcommon/q_shared.h	2009-11-09 13:50:48 UTC (rev 1744)
+++ trunk/code/qcommon/q_shared.h	2009-11-09 22:41:42 UTC (rev 1745)
@@ -787,30 +787,33 @@
 ==========================================================
 */
 
-#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,10 +827,14 @@
 	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
 
 typedef int	cvarHandle_t;

Modified: trunk/code/qcommon/qcommon.h
===================================================================
--- trunk/code/qcommon/qcommon.h	2009-11-09 13:50:48 UTC (rev 1744)
+++ trunk/code/qcommon/qcommon.h	2009-11-09 22:41:42 UTC (rev 1745)
@@ -545,6 +545,7 @@
 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_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_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
 



More information about the quake3-commits mailing list