diff options
Diffstat (limited to 'src/qcommon/cvar.c')
-rw-r--r-- | src/qcommon/cvar.c | 306 |
1 files changed, 222 insertions, 84 deletions
diff --git a/src/qcommon/cvar.c b/src/qcommon/cvar.c index f82eb78f..459f602b 100644 --- a/src/qcommon/cvar.c +++ b/src/qcommon/cvar.c @@ -25,7 +25,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; @@ -34,7 +34,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); @@ -182,11 +182,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); } } @@ -305,6 +308,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" ); @@ -323,13 +327,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 ); @@ -344,13 +350,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 @@ -368,6 +383,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; @@ -376,11 +395,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; + } + + 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[cvar_numIndexes]; - cvar_numIndexes++; + + 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; @@ -392,6 +427,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; @@ -399,7 +438,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; @@ -471,15 +516,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; @@ -610,12 +663,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) @@ -623,9 +679,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); } } } @@ -803,11 +858,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) { + for (var = cvar_vars; var; var = var->next) + { + if(!var->name) + continue; + if( var->flags & CVAR_ARCHIVE ) { // write the latched value, even if it hasn't taken effect yet if ( var->latchedString ) { @@ -849,7 +909,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,74 +967,141 @@ void Cvar_List_f( void ) { /* ============ -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; + + 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; - // 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->hashPrev) + cv->hashPrev->hashNext = cv->hashNext; + else + hashTable[cv->hashIndex] = cv->hashNext; + if(cv->hashNext) + cv->hashNext->hashPrev = cv->hashPrev; - // 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; - } + Com_Memset(cv, '\0', sizeof(*cv)); + + return next; +} - Cvar_Set( var->name, var->resetString ); +/* +============ +Cvar_Unset_f + +Unsets a userdefined cvar +============ +*/ - prev = &var->next; +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; } @@ -984,16 +1112,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; } @@ -1032,13 +1161,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 ); @@ -1103,7 +1234,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); @@ -1119,6 +1254,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); } |