- 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:
parent
606ce66726
commit
258429efe7
8 changed files with 414 additions and 143 deletions
|
@ -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 <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
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue