- 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)
This commit is contained in:
Thilo Schulz 2009-11-09 22:41:42 +00:00
parent 606ce66726
commit 258429efe7
8 changed files with 414 additions and 143 deletions

2
README
View file

@ -200,6 +200,7 @@ New commands
stopvideo - stop video capture stopvideo - stop video capture
print - print out the contents of a cvar 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 banaddr <range> - ban an ip address range from joining a game on this
server, valid <range> is either playernum or CIDR server, valid <range> is either playernum or CIDR
@ -212,6 +213,7 @@ New commands
flushbans - delete all bans flushbans - delete all bans
net_restart - restart network subsystem to change latched settings net_restart - restart network subsystem to change latched settings
game_restart <fs_game> - Switch to another mod
------------------------------------------------------------ Miscellaneous ----- ------------------------------------------------------------ Miscellaneous -----

View file

@ -1030,6 +1030,18 @@ void CL_NextDemo( void ) {
//====================================================================== //======================================================================
/*
=====================
CL_ShutdownVMs
=====================
*/
void CL_ShutdownVMs(void)
{
CL_ShutdownCGame();
CL_ShutdownUI();
}
/* /*
===================== =====================
CL_ShutdownAll CL_ShutdownAll
@ -1251,6 +1263,9 @@ void CL_Disconnect( qboolean showMainMenu ) {
CL_WritePacket(); CL_WritePacket();
} }
// Remove pure paks
FS_PureServerSetLoadedPaks("", "");
CL_ClearState (); CL_ClearState ();
// wipe the client connection // 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 CL_Snd_Restart_f
@ -1742,10 +1770,9 @@ The cgame and game must also be forced to restart because
handles will be invalid handles will be invalid
================= =================
*/ */
void CL_Snd_Restart_f( void ) { void CL_Snd_Restart_f(void)
S_Shutdown(); {
S_Init(); CL_Snd_Restart();
CL_Vid_Restart_f(); CL_Vid_Restart_f();
} }

View file

@ -85,6 +85,10 @@ void CL_FlushMemory( void ) {
void CL_StartHunkUsers( qboolean rendererOnly ) { void CL_StartHunkUsers( qboolean rendererOnly ) {
} }
void CL_Snd_Restart(void)
{
}
void CL_ShutdownAll(void) {} void CL_ShutdownAll(void) {}
qboolean CL_CDKeyValidate( const char *key, const char *checksum ) { return qtrue; } qboolean CL_CDKeyValidate( const char *key, const char *checksum ) { return qtrue; }

View file

@ -93,8 +93,9 @@ int com_frameTime;
int com_frameMsec; int com_frameMsec;
int com_frameNumber; int com_frameNumber;
qboolean com_errorEntered; qboolean com_errorEntered = qfalse;
qboolean com_fullyInitialized; qboolean com_fullyInitialized = qfalse;
qboolean com_gameRestarting = qfalse;
char com_errorMessage[MAXPRINTMSG]; char com_errorMessage[MAXPRINTMSG];
@ -243,9 +244,20 @@ void QDECL Com_Error( int code, const char *fmt, ... ) {
va_list argptr; va_list argptr;
static int lastErrorTime; static int lastErrorTime;
static int errorCount; static int errorCount;
static qboolean calledSysError = qfalse;
int currentTime; 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 // when we are running automated scripts, make sure we
// know if anything failed // know if anything failed
@ -264,11 +276,6 @@ void QDECL Com_Error( int code, const char *fmt, ... ) {
} }
lastErrorTime = currentTime; lastErrorTime = currentTime;
if ( com_errorEntered ) {
Sys_Error( "recursive error after: %s", com_errorMessage );
}
com_errorEntered = qtrue;
va_start (argptr,fmt); va_start (argptr,fmt);
Q_vsnprintf (com_errorMessage, sizeof(com_errorMessage),fmt,argptr); Q_vsnprintf (com_errorMessage, sizeof(com_errorMessage),fmt,argptr);
va_end (argptr); va_end (argptr);
@ -303,12 +310,13 @@ void QDECL Com_Error( int code, const char *fmt, ... ) {
VM_Forced_Unload_Start(); VM_Forced_Unload_Start();
CL_FlushMemory( ); CL_FlushMemory( );
VM_Forced_Unload_Done(); VM_Forced_Unload_Done();
com_errorEntered = qfalse;
CL_CDDialog(); CL_CDDialog();
} else { } else {
Com_Printf("Server didn't have CD\n" ); Com_Printf("Server didn't have CD\n" );
} }
FS_PureServerSetLoadedPaks("", ""); FS_PureServerSetLoadedPaks("", "");
com_errorEntered = qfalse;
longjmp (abortframe, -1); longjmp (abortframe, -1);
} else { } else {
CL_Shutdown (); CL_Shutdown ();
@ -317,6 +325,7 @@ void QDECL Com_Error( int code, const char *fmt, ... ) {
Com_Shutdown (); Com_Shutdown ();
calledSysError = qtrue;
Sys_Error ("%s", com_errorMessage); 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 #ifndef STANDALONE
// TTimo: centralizing the cl_cdkey stuff after I discovered a buffer overflow problem with the dedicated server version // 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 ("changeVectors", MSG_ReportChangeVectors_f );
Cmd_AddCommand ("writeconfig", Com_WriteConfig_f ); Cmd_AddCommand ("writeconfig", Com_WriteConfig_f );
Cmd_SetCommandCompletionFunc( "writeconfig", Cmd_CompleteCfgName ); Cmd_SetCommandCompletionFunc( "writeconfig", Cmd_CompleteCfgName );
Cmd_AddCommand("game_restart", Com_GameRestart_f);
// Make it execute the configuration files Com_ExecuteCfg();
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 ();
// override anything from the config files with command line args // override anything from the config files with command line args
Com_StartupVariable( NULL ); Com_StartupVariable( NULL );

View file

@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "q_shared.h" #include "q_shared.h"
#include "qcommon.h" #include "qcommon.h"
cvar_t *cvar_vars; cvar_t *cvar_vars = NULL;
cvar_t *cvar_cheats; cvar_t *cvar_cheats;
int cvar_modifiedFlags; int cvar_modifiedFlags;
@ -33,7 +33,7 @@ cvar_t cvar_indexes[MAX_CVARS];
int cvar_numIndexes; int cvar_numIndexes;
#define FILE_HASH_SIZE 256 #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); 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 Cvar_CommandCompletion
============ ============
*/ */
void Cvar_CommandCompletion( void(*callback)(const char *s) ) { void Cvar_CommandCompletion(void (*callback)(const char *s))
{
cvar_t *cvar; cvar_t *cvar;
for ( cvar = cvar_vars ; cvar ; cvar = cvar->next ) { for(cvar = cvar_vars; cvar; cvar = cvar->next)
callback( cvar->name ); {
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 *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
cvar_t *var; cvar_t *var;
long hash; long hash;
int index;
if ( !var_name || ! var_value ) { if ( !var_name || ! var_value ) {
Com_Error( ERR_FATAL, "Cvar_Get: NULL parameter" ); 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 #endif
var = Cvar_FindVar (var_name); 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 // 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 // set a value for, take the new value as the reset value
if ( ( var->flags & CVAR_USER_CREATED ) && !( flags & CVAR_USER_CREATED ) if(var->flags & CVAR_USER_CREATED)
&& var_value[0] ) { {
var->flags &= ~CVAR_USER_CREATED; var->flags &= ~CVAR_USER_CREATED;
Z_Free( var->resetString ); Z_Free( var->resetString );
var->resetString = CopyString( var_value ); 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); 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 // only allow one non-empty reset string without a warning
if ( !var->resetString[0] ) { if ( !var->resetString[0] ) {
// we don't have a reset string yet // 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 var->latchedString = NULL; // otherwise cvar_set2 would free it
Cvar_Set2( var_name, s, qtrue ); Cvar_Set2( var_name, s, qtrue );
Z_Free( s ); 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; return var;
@ -375,11 +394,27 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) {
// //
// allocate a new cvar // 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->name = CopyString (var_name);
var->string = CopyString (var_value); var->string = CopyString (var_value);
var->modified = qtrue; 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 // link the variable in
var->next = cvar_vars; var->next = cvar_vars;
if(cvar_vars)
cvar_vars->prev = var;
var->prev = NULL;
cvar_vars = var; cvar_vars = var;
var->flags = flags; 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; cvar_modifiedFlags |= var->flags;
hash = generateHashValue(var_name); hash = generateHashValue(var_name);
var->hashIndex = hash;
var->hashNext = hashTable[hash]; var->hashNext = hashTable[hash];
if(hashTable[hash])
hashTable[hash]->hashPrev = var;
var->hashPrev = NULL;
hashTable[hash] = var; hashTable[hash] = var;
return var; return var;
@ -470,15 +515,23 @@ cvar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) {
value = var->resetString; value = var->resetString;
} }
value = Cvar_Validate( var, value, qtrue ); value = Cvar_Validate(var, value, qtrue);
if((var->flags & CVAR_LATCH) && var->latchedString) { if((var->flags & CVAR_LATCH) && var->latchedString)
if(!strcmp(value,var->latchedString)) {
if(!strcmp(value, var->string))
{
Z_Free(var->latchedString);
var->latchedString = NULL;
return var;
}
if(!strcmp(value, var->latchedString))
return var; return var;
} }
else if (!strcmp(value,var->string)) { else if(!strcmp(value, var->string))
return var; return var;
}
// note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo)
cvar_modifiedFlags |= var->flags; cvar_modifiedFlags |= var->flags;
@ -609,12 +662,15 @@ Cvar_SetCheatState
Any testing variables will be reset to the safe values Any testing variables will be reset to the safe values
============ ============
*/ */
void Cvar_SetCheatState( void ) { void Cvar_SetCheatState(void)
{
cvar_t *var; cvar_t *var;
// set all default vars to the safe value // set all default vars to the safe value
for ( var = cvar_vars ; var ; var = var->next ) { for(var = cvar_vars; var ; var = var->next)
if ( var->flags & CVAR_CHEAT ) { {
if(var->flags & CVAR_CHEAT)
{
// the CVAR_LATCHED|CVAR_CHEAT vars might escape the reset here // the CVAR_LATCHED|CVAR_CHEAT vars might escape the reset here
// because of a different var->latchedString // because of a different var->latchedString
if (var->latchedString) if (var->latchedString)
@ -622,9 +678,8 @@ void Cvar_SetCheatState( void ) {
Z_Free(var->latchedString); Z_Free(var->latchedString);
var->latchedString = NULL; var->latchedString = NULL;
} }
if (strcmp(var->resetString,var->string)) { if (strcmp(var->resetString,var->string))
Cvar_Set( var->name, var->resetString ); 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. with the archive flag set to qtrue.
============ ============
*/ */
void Cvar_WriteVariables( fileHandle_t f ) { void Cvar_WriteVariables(fileHandle_t f)
{
cvar_t *var; cvar_t *var;
char buffer[1024]; char buffer[1024];
for (var = cvar_vars ; var ; var = var->next) { for (var = cvar_vars; var; var = var->next)
if( Q_stricmp( var->name, "cl_cdkey" ) == 0 ) { {
if(!var->name || Q_stricmp( var->name, "cl_cdkey" ) == 0)
continue; continue;
}
if( var->flags & CVAR_ARCHIVE ) { if( var->flags & CVAR_ARCHIVE ) {
// write the latched value, even if it hasn't taken effect yet // write the latched value, even if it hasn't taken effect yet
if ( var->latchedString ) { if ( var->latchedString ) {
@ -851,7 +908,8 @@ void Cvar_List_f( void ) {
i = 0; i = 0;
for (var = cvar_vars ; var ; var = var->next, i++) 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) { if (var->flags & CVAR_SERVERINFO) {
Com_Printf("S"); Com_Printf("S");
@ -906,6 +964,113 @@ void Cvar_List_f( void ) {
Com_Printf ("%i cvar indexes\n", cvar_numIndexes); 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 <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 Cvar_Restart_f
@ -913,69 +1078,29 @@ Cvar_Restart_f
Resets all cvars to their hardcoded values Resets all cvars to their hardcoded values
============ ============
*/ */
void Cvar_Restart_f( void ) { void Cvar_Restart_f(void)
cvar_t *var; {
cvar_t **prev; Cvar_Restart(qfalse);
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;
}
} }
/* /*
===================== =====================
Cvar_InfoString Cvar_InfoString
===================== =====================
*/ */
char *Cvar_InfoString( int bit ) { char *Cvar_InfoString(int bit)
{
static char info[MAX_INFO_STRING]; static char info[MAX_INFO_STRING];
cvar_t *var; cvar_t *var;
info[0] = 0; info[0] = 0;
for (var = cvar_vars ; var ; var = var->next) { for(var = cvar_vars; var; var = var->next)
if (var->flags & bit) { {
if(var->name && (var->flags & bit))
Info_SetValueForKey (info, var->name, var->string); Info_SetValueForKey (info, var->name, var->string);
}
} }
return info; return info;
} }
@ -986,16 +1111,17 @@ Cvar_InfoString_Big
handles large info strings ( CS_SYSTEMINFO ) handles large info strings ( CS_SYSTEMINFO )
===================== =====================
*/ */
char *Cvar_InfoString_Big( int bit ) { char *Cvar_InfoString_Big(int bit)
{
static char info[BIG_INFO_STRING]; static char info[BIG_INFO_STRING];
cvar_t *var; cvar_t *var;
info[0] = 0; info[0] = 0;
for (var = cvar_vars ; var ; var = var->next) { for (var = cvar_vars; var; var = var->next)
if (var->flags & bit) { {
if(var->name && (var->flags & bit))
Info_SetValueForKey_Big (info, var->name, var->string); Info_SetValueForKey_Big (info, var->name, var->string);
}
} }
return info; return info;
} }
@ -1034,13 +1160,15 @@ Cvar_Register
basically a slightly modified Cvar_Get for the interpreted modules 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; cvar_t *cv;
cv = Cvar_Get( varName, defaultValue, flags ); cv = Cvar_Get(varName, defaultValue, flags | CVAR_VM_CREATED);
if ( !vmCvar ) {
if (!vmCvar)
return; return;
}
vmCvar->handle = cv - cvar_indexes; vmCvar->handle = cv - cvar_indexes;
vmCvar->modificationCount = -1; vmCvar->modificationCount = -1;
Cvar_Update( vmCvar ); Cvar_Update( vmCvar );
@ -1105,7 +1233,11 @@ Cvar_Init
Reads in all archived cvars 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 ); cvar_cheats = Cvar_Get("sv_cheats", "1", CVAR_ROM | CVAR_SYSTEMINFO );
Cmd_AddCommand ("print", Cvar_Print_f); Cmd_AddCommand ("print", Cvar_Print_f);
@ -1121,6 +1253,9 @@ void Cvar_Init (void) {
Cmd_SetCommandCompletionFunc( "seta", Cvar_CompleteCvarName ); Cmd_SetCommandCompletionFunc( "seta", Cvar_CompleteCvarName );
Cmd_AddCommand ("reset", Cvar_Reset_f); Cmd_AddCommand ("reset", Cvar_Reset_f);
Cmd_SetCommandCompletionFunc( "reset", Cvar_CompleteCvarName ); Cmd_SetCommandCompletionFunc( "reset", Cvar_CompleteCvarName );
Cmd_AddCommand ("unset", Cvar_Unset_f);
Cmd_SetCommandCompletionFunc("unset", Cvar_CompleteCvarName);
Cmd_AddCommand ("cvarlist", Cvar_List_f); Cmd_AddCommand ("cvarlist", Cvar_List_f);
Cmd_AddCommand ("cvar_restart", Cvar_Restart_f); Cmd_AddCommand ("cvar_restart", Cvar_Restart_f);
} }

View file

@ -248,7 +248,7 @@ static searchpath_t *fs_searchpaths;
static int fs_readCount; // total bytes read static int fs_readCount; // total bytes read
static int fs_loadCount; // total files read static int fs_loadCount; // total files read
static int fs_loadStack; // total files in memory 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; static int fs_checksumFeed;
@ -280,7 +280,7 @@ static fileHandleData_t fsh[MAX_FILE_HANDLES];
static qboolean fs_reordered; static qboolean fs_reordered;
// never load anything from pk3 files that are not present at the server when pure // 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 int fs_serverPaks[MAX_SEARCH_PATHS]; // checksums
static char *fs_serverPakNames[MAX_SEARCH_PATHS]; // pk3 names 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" ); Com_Printf( "----- FS_Startup -----\n" );
fs_packFiles = 0;
fs_debug = Cvar_Get( "fs_debug", "0", 0 ); fs_debug = Cvar_Get( "fs_debug", "0", 0 );
fs_basepath = Cvar_Get ("fs_basepath", Sys_DefaultInstallPath(), CVAR_INIT ); fs_basepath = Cvar_Get ("fs_basepath", Sys_DefaultInstallPath(), CVAR_INIT );
fs_basegame = Cvar_Get ("fs_basegame", "", CVAR_INIT ); fs_basegame = Cvar_Get ("fs_basegame", "", CVAR_INIT );
@ -3437,11 +3439,20 @@ FS_ConditionalRestart
restart if necessary restart if necessary
================= =================
*/ */
qboolean FS_ConditionalRestart( int checksumFeed ) { qboolean FS_ConditionalRestart(int checksumFeed)
if( fs_gamedirvar->modified || checksumFeed != fs_checksumFeed ) { {
FS_Restart( checksumFeed ); if(fs_gamedirvar->modified)
{
Com_GameRestart(checksumFeed, qfalse);
return qtrue; return qtrue;
} }
else if(checksumFeed != fs_checksumFeed)
{
FS_Restart(checksumFeed);
return qtrue;
}
return qfalse; return qfalse;
} }

View file

@ -787,30 +787,33 @@ default values.
========================================================== ==========================================================
*/ */
#define CVAR_ARCHIVE 1 // set to cause it to be saved to vars.rc #define CVAR_ARCHIVE 0x0001 // set to cause it to be saved to vars.rc
// used for system variables, not for player // used for system variables, not for player
// specific configurations // specific configurations
#define CVAR_USERINFO 2 // sent to server on connect or change #define CVAR_USERINFO 0x0002 // sent to server on connect or change
#define CVAR_SERVERINFO 4 // sent in response to front end requests #define CVAR_SERVERINFO 0x0004 // sent in response to front end requests
#define CVAR_SYSTEMINFO 8 // these cvars will be duplicated on all clients #define CVAR_SYSTEMINFO 0x0008 // these cvars will be duplicated on all clients
#define CVAR_INIT 16 // don't allow change from console at all, #define CVAR_INIT 0x0010 // don't allow change from console at all,
// but can be set from the command line // but can be set from the command line
#define CVAR_LATCH 32 // will only change when C code next does #define CVAR_LATCH 0x0020 // will only change when C code next does
// a Cvar_Get(), so it can't be changed // a Cvar_Get(), so it can't be changed
// without proper initialization. modified // without proper initialization. modified
// will be set, even though the value hasn't // will be set, even though the value hasn't
// changed yet // changed yet
#define CVAR_ROM 64 // display only, cannot be set by user at all #define CVAR_ROM 0x0040 // display only, cannot be set by user at all
#define CVAR_USER_CREATED 128 // created by a set command #define CVAR_USER_CREATED 0x0080 // created by a set command
#define CVAR_TEMP 256 // can be set even when cheats are disabled, but is not archived #define CVAR_TEMP 0x0100 // 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_CHEAT 0x0200 // can not be changed if cheats are disabled
#define CVAR_NORESTART 1024 // do not clear when a cvar_restart is issued #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. #define CVAR_NONEXISTENT 0xFFFFFFFF // Cvar doesn't exist.
// nothing outside the Cvar_*() functions should modify these fields! // 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 *name;
char *string; char *string;
char *resetString; // cvar_restart will reset to this value char *resetString; // cvar_restart will reset to this value
@ -824,9 +827,13 @@ typedef struct cvar_s {
qboolean integral; qboolean integral;
float min; float min;
float max; float max;
struct cvar_s *next;
struct cvar_s *hashNext; cvar_t *next;
} cvar_t; cvar_t *prev;
cvar_t *hashNext;
cvar_t *hashPrev;
int hashIndex;
};
#define MAX_CVAR_VALUE_STRING 256 #define MAX_CVAR_VALUE_STRING 256

View file

@ -545,6 +545,7 @@ char *Cvar_InfoString_Big( int bit );
void Cvar_InfoStringBuffer( int bit, char *buff, int buffsize ); void Cvar_InfoStringBuffer( int bit, char *buff, int buffsize );
void Cvar_CheckRange( cvar_t *cv, float minVal, float maxVal, qboolean shouldBeIntegral ); void Cvar_CheckRange( cvar_t *cv, float minVal, float maxVal, qboolean shouldBeIntegral );
void Cvar_Restart(qboolean unsetVM);
void Cvar_Restart_f( void ); void Cvar_Restart_f( void );
void Cvar_CompleteCvarName( char *args, int argNum ); 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_DPrintf( const char *fmt, ... ) __attribute__ ((format (printf, 1, 2)));
void QDECL Com_Error( int code, const char *fmt, ... ) __attribute__ ((format (printf, 2, 3))); void QDECL Com_Error( int code, const char *fmt, ... ) __attribute__ ((format (printf, 2, 3)));
void Com_Quit_f( void ); void Com_Quit_f( void );
void Com_GameRestart(int checksumFeed, qboolean clientRestart);
int Com_Milliseconds( void ); // will be journaled properly int Com_Milliseconds( void ); // will be journaled properly
unsigned Com_BlockChecksum( const void *buffer, int length ); unsigned Com_BlockChecksum( const void *buffer, int length );
@ -974,6 +976,9 @@ void CL_FlushMemory( void );
void CL_StartHunkUsers( qboolean rendererOnly ); void CL_StartHunkUsers( qboolean rendererOnly );
// start all the client stuff using the hunk // start all the client stuff using the hunk
void CL_Snd_Restart(void);
// Restart sound subsystem
void Key_KeynameCompletion( void(*callback)(const char *s) ); void Key_KeynameCompletion( void(*callback)(const char *s) );
// for keyname autocompletion // for keyname autocompletion