This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/engine/common/cvar.c

1165 lines
25 KiB
C
Raw Normal View History

2011-05-09 22:00:00 +02:00
/*
cvar.c - dynamic variable tracking
Copyright (C) 2007 Uncle Mike
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
2011-03-09 22:00:00 +01:00
#include "common.h"
2011-04-08 22:00:00 +02:00
convar_t *cvar_vars; // head of list
2011-03-09 22:00:00 +01:00
convar_t *userinfo, *physinfo, *serverinfo, *renderinfo;
2016-11-17 22:00:00 +01:00
convar_t *cmd_scripting;
2011-03-09 22:00:00 +01:00
2012-04-11 22:00:00 +02:00
/*
============
Cvar_GetList
============
*/
cvar_t *Cvar_GetList( void )
{
return (cvar_t *)cvar_vars;
}
/*
============
Cvar_GetName
============
*/
char *Cvar_GetName( cvar_t *cvar )
{
return cvar->name;
}
2011-03-09 22:00:00 +01:00
/*
============
Cvar_InfoValidate
============
*/
static qboolean Cvar_ValidateString( const char *s, qboolean isvalue )
{
if( !s ) return false;
2011-03-11 22:00:00 +01:00
if( Q_strstr( s, "\\" ) && !isvalue )
2011-03-09 22:00:00 +01:00
return false;
2011-03-11 22:00:00 +01:00
if( Q_strstr( s, "\"" )) return false;
if( Q_strstr( s, ";" )) return false;
2011-03-09 22:00:00 +01:00
return true;
}
/*
============
Cvar_FindVar
============
*/
convar_t *Cvar_FindVar( const char *var_name )
{
convar_t *var;
for( var = cvar_vars; var; var = var->next )
{
2011-03-11 22:00:00 +01:00
if( !Q_stricmp( var_name, var->name ))
2011-03-09 22:00:00 +01:00
return var;
}
return NULL;
}
/*
============
Cvar_VariableValue
============
*/
float Cvar_VariableValue( const char *var_name )
{
convar_t *var;
var = Cvar_FindVar( var_name );
if( !var ) return 0;
return var->value;
}
/*
============
Cvar_VariableInteger
============
*/
int Cvar_VariableInteger( const char *var_name )
{
convar_t *var;
var = Cvar_FindVar( var_name );
if( !var ) return 0;
return var->integer;
}
/*
============
Cvar_VariableString
============
*/
char *Cvar_VariableString( const char *var_name )
{
convar_t *var;
var = Cvar_FindVar( var_name );
if( !var ) return "";
return var->string;
}
/*
============
Cvar_LookupVars
============
*/
void Cvar_LookupVars( int checkbit, void *buffer, void *ptr, setpair_t callback )
{
convar_t *cvar;
// nothing to process ?
if( !callback ) return;
// force checkbit to 0 for lookup all cvars
for( cvar = cvar_vars; cvar; cvar = cvar->next )
{
2012-12-21 21:00:00 +01:00
if( checkbit && !( cvar->flags & checkbit ))
continue;
2011-04-08 22:00:00 +02:00
if( buffer )
{
callback( cvar->name, cvar->string, buffer, ptr );
}
2011-03-09 22:00:00 +01:00
else
{
// NOTE: dlls cvars doesn't have description
2016-11-17 22:00:00 +01:00
if( FBitSet( cvar->flags, CVAR_SERVERDLL ))
2011-03-09 22:00:00 +01:00
callback( cvar->name, cvar->string, "game cvar", ptr );
else callback( cvar->name, cvar->string, cvar->description, ptr );
}
}
}
/*
============
Cvar_Get
If the variable already exists, the value will not be set
The flags will be or'ed in if the variable exists.
============
*/
convar_t *Cvar_Get( const char *var_name, const char *var_value, int flags, const char *var_desc )
{
2016-11-17 22:00:00 +01:00
convar_t *cur, *find, *var;
2011-03-09 22:00:00 +01:00
if( !var_name )
{
2016-11-17 22:00:00 +01:00
MsgDev( D_ERROR, "Cvar_Get: passed NULL name\n" );
return NULL;
}
// check for command coexisting
if( Cmd_Exists( var_name ))
{
MsgDev( D_ERROR, "Cvar_Get: %s is a command\n", var_name );
2011-03-09 22:00:00 +01:00
return NULL;
}
if( !var_value ) var_value = "0"; // just apply default value
// all broadcast cvars must be passed this check
2016-11-17 22:00:00 +01:00
if( FBitSet( flags, CVAR_USERINFO|CVAR_SERVERINFO|CVAR_PHYSICINFO ))
2011-03-09 22:00:00 +01:00
{
if( !Cvar_ValidateString( var_name, false ))
{
MsgDev( D_ERROR, "invalid info cvar name string %s\n", var_name );
return NULL;
}
if( !Cvar_ValidateString( var_value, true ))
{
MsgDev( D_WARN, "invalid cvar value string: %s\n", var_value );
var_value = "0"; // just apply default value
}
}
var = Cvar_FindVar( var_name );
if( var )
{
// fast check for short cvars
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_SERVERDLL ))
2011-03-09 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
SetBits( var->flags, flags );
2011-03-09 22:00:00 +01:00
return var;
}
// 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
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_USER_CREATED ) && !FBitSet( flags, CVAR_USER_CREATED ) && var_value[0] )
2011-03-09 22:00:00 +01:00
{
Mem_Free( var->reset_string );
var->reset_string = copystring( var_value );
2016-11-17 22:00:00 +01:00
ClearBits( var->flags, CVAR_USER_CREATED );
2011-03-09 22:00:00 +01:00
}
2016-11-17 22:00:00 +01:00
SetBits( var->flags, flags );
2011-03-09 22:00:00 +01:00
// only allow one non-empty reset string without a warning
2016-11-17 22:00:00 +01:00
if( var->reset_string != NULL && !var->reset_string[0] )
2011-03-09 22:00:00 +01:00
{
// we don't have a reset string yet
Mem_Free( var->reset_string );
var->reset_string = copystring( var_value );
}
// if we have a latched string, take that value now
2016-11-17 22:00:00 +01:00
if( var->latched_string != NULL )
2011-03-09 22:00:00 +01:00
{
2012-12-16 21:00:00 +01:00
char *s = var->latched_string;
2011-03-09 22:00:00 +01:00
var->latched_string = NULL; // otherwise cvar_set2 would free it
Cvar_Set2( var_name, s, true );
Mem_Free( s );
}
2016-11-17 22:00:00 +01:00
if( var_desc != NULL )
2011-03-09 22:00:00 +01:00
{
// update description if needs
if( var->description ) Mem_Free( var->description );
var->description = copystring( var_desc );
}
2016-11-17 22:00:00 +01:00
2011-03-09 22:00:00 +01:00
return var;
}
// allocate a new cvar
var = Z_Malloc( sizeof( *var ));
var->name = copystring( var_name );
var->string = copystring( var_value );
var->reset_string = copystring( var_value );
if( var_desc ) var->description = copystring( var_desc );
2011-03-11 22:00:00 +01:00
var->value = Q_atof( var->string );
var->integer = Q_atoi( var->string );
2011-03-09 22:00:00 +01:00
var->modified = true;
var->flags = flags;
2016-11-17 22:00:00 +01:00
// link the variable in alphanumerical order
for( cur = NULL, find = cvar_vars; find && Q_strcmp( find->name, var->name ) < 0; cur = find, find = find->next );
if( cur ) cur->next = var;
else cvar_vars = var;
var->next = find;
2011-03-09 22:00:00 +01:00
return var;
}
/*
============
Cvar_RegisterVariable
Adds a freestanding variable to the variable list.
============
*/
void Cvar_RegisterVariable( cvar_t *var )
{
2016-11-17 22:00:00 +01:00
convar_t *cur = NULL;
2011-03-09 22:00:00 +01:00
convar_t *find;
ASSERT( var != NULL );
// check for overlap with a command
if( Cmd_Exists( var->name ))
{
MsgDev( D_ERROR, "Cvar_Register: %s is a command\n", var->name );
return;
}
2012-12-21 21:00:00 +01:00
// first check to see if it has already been defined
2011-03-09 22:00:00 +01:00
if(( cur = Cvar_FindVar( var->name )) != NULL )
{
// this cvar is already registered with Cvar_RegisterVariable
// so we can't replace it
2016-11-17 22:00:00 +01:00
if( FBitSet( cur->flags, CVAR_SERVERDLL ))
2011-03-09 22:00:00 +01:00
{
MsgDev( D_ERROR, "can't register variable %s, allready defined\n", var->name );
return;
}
2016-11-17 22:00:00 +01:00
else
2011-03-09 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
var->string = cur->string; // we already have right string
var->value = Q_atof( var->string );
SetBits( var->flags, CVAR_SERVERDLL ); // all cvars passed this function are game cvars
var->next = (cvar_t *)cur->next;
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
if( cvar_vars == cur )
2011-03-15 22:00:00 +01:00
{
// relink at tail
cvar_vars = (convar_t *)var;
}
2016-11-17 22:00:00 +01:00
else
2011-03-09 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
// otherwise find it somewhere in the list
for( find = cvar_vars; find->next != cur; find = find->next );
ASSERT( find != NULL );
find->next = (convar_t *)var;
2011-03-09 22:00:00 +01:00
}
2016-11-17 22:00:00 +01:00
// release current cvar (but keep string)
if( cur->name ) Mem_Free( cur->name );
if( cur->latched_string ) Mem_Free( cur->latched_string );
if( cur->reset_string ) Mem_Free( cur->reset_string );
if( cur->description ) Mem_Free( cur->description );
Mem_Free( cur );
2011-03-09 22:00:00 +01:00
}
}
else
{
// copy the value off, because future sets will Z_Free it
var->string = copystring( var->string );
2011-03-11 22:00:00 +01:00
var->value = Q_atof( var->string );
2016-11-17 22:00:00 +01:00
SetBits( var->flags, CVAR_SERVERDLL ); // all cvars passed this function are game cvars
// link the variable in alphanumerical order
for( cur = NULL, find = cvar_vars; find && Q_strcmp( find->name, var->name ) < 0; cur = find, find = find->next );
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
if( cur ) cur->next = (convar_t *)var;
else cvar_vars = (convar_t *)var;
var->next = (cvar_t *)find;
2011-03-09 22:00:00 +01:00
}
}
/*
============
Cvar_Set2
============
*/
convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force )
{
convar_t *var;
const char *pszValue;
char szNew[MAX_SYSPATH];
if( !Cvar_ValidateString( var_name, false ))
{
MsgDev( D_ERROR, "invalid cvar name string: %s\n", var_name );
return NULL;
}
var = Cvar_FindVar( var_name );
2016-11-17 22:00:00 +01:00
2011-03-09 22:00:00 +01:00
if( !var )
{
// create it
2011-04-08 22:00:00 +02:00
if( force ) return Cvar_Get( var_name, value, 0, NULL );
return Cvar_Get( var_name, value, CVAR_USER_CREATED, NULL );
2011-03-09 22:00:00 +01:00
}
if( !value )
{
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_SERVERDLL ))
value = "0";
2011-03-09 22:00:00 +01:00
else value = var->reset_string;
}
2011-03-11 22:00:00 +01:00
if( !Q_strcmp( value, var->string ))
2011-03-09 22:00:00 +01:00
return var;
// any latched values not allowed for game cvars
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_SERVERDLL ))
force = true;
2011-03-09 22:00:00 +01:00
if( !force )
{
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_READ_ONLY|CVAR_GLCONFIG ))
2011-03-09 22:00:00 +01:00
{
MsgDev( D_INFO, "%s is read only.\n", var_name );
return var;
}
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_INIT ))
2011-03-09 22:00:00 +01:00
{
MsgDev( D_INFO, "%s is write protected.\n", var_name );
return var;
}
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_LATCH ))
2011-03-09 22:00:00 +01:00
{
if( var->latched_string )
{
2011-03-11 22:00:00 +01:00
if(!Q_strcmp( value, var->latched_string ))
2011-03-09 22:00:00 +01:00
return var;
Mem_Free( var->latched_string );
}
else
{
2011-03-11 22:00:00 +01:00
if( !Q_strcmp( value, var->string ))
2011-03-09 22:00:00 +01:00
return var;
}
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_LATCH ) && Cvar_VariableInteger( "host_serverstate" ))
2011-03-09 22:00:00 +01:00
{
MsgDev( D_INFO, "%s will be changed upon restarting.\n", var->name );
var->latched_string = copystring( value );
}
else
{
Mem_Free( var->string ); // free the old value string
var->string = copystring( value );
2011-03-11 22:00:00 +01:00
var->value = Q_atof( var->string );
var->integer = Q_atoi( var->string );
2011-03-09 22:00:00 +01:00
}
var->modified = true;
return var;
}
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_CHEAT ) && !Cvar_VariableInteger( "sv_cheats" ))
2011-03-09 22:00:00 +01:00
{
MsgDev( D_INFO, "%s is cheat protected.\n", var_name );
return var;
}
}
else
{
2016-11-17 22:00:00 +01:00
if( !FBitSet( var->flags, CVAR_SERVERDLL ) && var->latched_string )
2011-03-09 22:00:00 +01:00
{
Mem_Free( var->latched_string );
var->latched_string = NULL;
}
}
pszValue = value;
2016-11-17 22:00:00 +01:00
// this cvar's string must only contain printable characters.
// strip out any other crap.
// we'll fill in "empty" if nothing is left
if( FBitSet( var->flags, CVAR_PRINTABLEONLY ))
2011-03-09 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
const char *s;
char *d;
2011-03-09 22:00:00 +01:00
szNew[0] = '\0';
2016-11-17 22:00:00 +01:00
s = pszValue;
d = szNew;
2011-03-09 22:00:00 +01:00
// step through the string, only copying back in characters that are printable
2016-11-17 22:00:00 +01:00
while( *s )
2011-03-09 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
if( ((byte)*s) < 32 )
2011-03-09 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
s++;
2011-03-09 22:00:00 +01:00
continue;
}
2016-11-17 22:00:00 +01:00
*d++ = *s++;
2011-03-09 22:00:00 +01:00
}
2016-11-17 22:00:00 +01:00
*d = '\0';
2011-03-09 22:00:00 +01:00
2011-03-11 22:00:00 +01:00
if( !Q_strlen( szNew ))
2016-11-17 22:00:00 +01:00
Q_strncpy( szNew, "default", sizeof( szNew ));
2011-03-09 22:00:00 +01:00
// point the value here.
pszValue = szNew;
}
// nothing to change
2011-03-11 22:00:00 +01:00
if( !Q_strcmp( pszValue, var->string ))
2011-03-09 22:00:00 +01:00
return var;
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_USERINFO ))
userinfo->modified = true; // transmit at next oportunity
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_PHYSICINFO ))
physinfo->modified = true; // transmit at next oportunity
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_SERVERINFO ))
serverinfo->modified = true; // transmit at next oportunity
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_RENDERINFO ))
renderinfo->modified = true; // transmit at next oportunity
2011-03-09 22:00:00 +01:00
// free the old value string
Mem_Free( var->string );
var->string = copystring( pszValue );
2011-03-11 22:00:00 +01:00
var->value = Q_atof( var->string );
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
if( !FBitSet( var->flags, CVAR_SERVERDLL ))
2011-03-09 22:00:00 +01:00
{
2011-03-11 22:00:00 +01:00
var->integer = Q_atoi( var->string );
2011-03-09 22:00:00 +01:00
var->modified = true;
}
return var;
}
/*
============
Cvar_Set
============
*/
void Cvar_Set( const char *var_name, const char *value )
{
Cvar_Set2( var_name, value, true );
}
/*
============
Cvar_SetLatched
============
*/
void Cvar_SetLatched( const char *var_name, const char *value )
{
Cvar_Set2( var_name, value, false );
}
/*
============
Cvar_FullSet
============
*/
void Cvar_FullSet( const char *var_name, const char *value, int flags )
{
convar_t *var;
2016-11-17 22:00:00 +01:00
if(( var = Cvar_FindVar( var_name )) == NULL )
2011-03-09 22:00:00 +01:00
{
// create it
Cvar_Get( var_name, value, flags, "" );
return;
}
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_USERINFO ))
userinfo->modified = true; // transmit at next oportunity
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_PHYSICINFO ))
physinfo->modified = true; // transmit at next oportunity
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_SERVERINFO ))
serverinfo->modified = true; // transmit at next oportunity
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_RENDERINFO ))
renderinfo->modified = true; // transmit at next oportunity
2011-03-09 22:00:00 +01:00
Mem_Free( var->string ); // free the old value string
var->string = copystring( value );
2011-03-11 22:00:00 +01:00
var->value = Q_atof( var->string );
2011-03-09 22:00:00 +01:00
var->flags = flags;
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_SERVERDLL ))
return; // below fields doesn't exist in cvar_t
2011-03-09 22:00:00 +01:00
2011-03-11 22:00:00 +01:00
var->integer = Q_atoi( var->string );
2011-03-09 22:00:00 +01:00
var->modified = true;
}
/*
============
Cvar_DirectSet
============
*/
void Cvar_DirectSet( cvar_t *var, const char *value )
{
const char *pszValue;
char szNew[MAX_SYSPATH];
if( !var ) return; // GET_CVAR_POINTER is failed ?
// make sure what is really pointer to the cvar
2016-11-17 22:00:00 +01:00
if( var != (cvar_t *)Cvar_FindVar( var->name ))
{
MsgDev( D_ERROR, "Cvar_DirectSet: invalid pointer to cvar\n" );
return;
}
2011-03-09 22:00:00 +01:00
if( value && !Cvar_ValidateString( value, true ))
{
MsgDev( D_WARN, "invalid cvar value string: %s\n", value );
2012-12-21 21:00:00 +01:00
value = "0";
2011-03-09 22:00:00 +01:00
}
2016-11-17 22:00:00 +01:00
if( !value )
{
if( FBitSet( var->flags, CVAR_SERVERDLL ))
value = "0";
else value = ((convar_t *)var)->reset_string;
}
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_READ_ONLY|CVAR_GLCONFIG|CVAR_INIT|CVAR_RENDERINFO|CVAR_LATCH ))
2011-03-09 22:00:00 +01:00
{
// Cvar_DirectSet cannot change these cvars at all
return;
}
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_CHEAT ) && !Cvar_VariableInteger( "sv_cheats" ))
2011-03-09 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
MsgDev( D_INFO, "%s is cheat protected.\n", var->name );
2011-03-09 22:00:00 +01:00
return;
}
pszValue = value;
2016-11-17 22:00:00 +01:00
// this cvar's string must only contain printable characters.
// strip out any other crap.
// we'll fill in "empty" if nothing is left
if( FBitSet( var->flags, CVAR_PRINTABLEONLY ))
2011-03-09 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
const char *s;
char *d;
2011-03-09 22:00:00 +01:00
szNew[0] = '\0';
2016-11-17 22:00:00 +01:00
s = pszValue;
d = szNew;
2011-03-09 22:00:00 +01:00
// step through the string, only copying back in characters that are printable
2016-11-17 22:00:00 +01:00
while( *s )
2011-03-09 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
if( ((byte)*s) < 32 )
2011-03-09 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
s++;
2011-03-09 22:00:00 +01:00
continue;
}
2016-11-17 22:00:00 +01:00
*d++ = *s++;
2011-03-09 22:00:00 +01:00
}
2016-11-17 22:00:00 +01:00
*d = '\0';
2011-03-09 22:00:00 +01:00
2011-03-11 22:00:00 +01:00
if( !Q_strlen( szNew ))
2016-11-17 22:00:00 +01:00
Q_strncpy( szNew, "default", sizeof( szNew ));
2011-03-09 22:00:00 +01:00
// point the value here.
pszValue = szNew;
}
2016-11-17 22:00:00 +01:00
// nothing to change
2011-03-11 22:00:00 +01:00
if( !Q_strcmp( pszValue, var->string ))
2011-03-09 22:00:00 +01:00
return;
if( var->flags & CVAR_USERINFO )
userinfo->modified = true; // transmit at next oportunity
if( var->flags & CVAR_PHYSICINFO )
physinfo->modified = true; // transmit at next oportunity
if( var->flags & CVAR_SERVERINFO )
serverinfo->modified = true; // transmit at next oportunity
if( var->flags & CVAR_RENDERINFO )
renderinfo->modified = true; // transmit at next oportunity
// free the old value string
Mem_Free( var->string );
var->string = copystring( pszValue );
2011-03-11 22:00:00 +01:00
var->value = Q_atof( var->string );
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_SERVERDLL ))
return; // below fields doesn't exist in cvar_t
((convar_t *)var)->integer = Q_atoi( var->string );
((convar_t *)var)->modified = true;
2011-03-09 22:00:00 +01:00
}
/*
============
Cvar_SetFloat
============
*/
void Cvar_SetFloat( const char *var_name, float value )
{
char val[32];
if( value == (int)value )
2011-03-11 22:00:00 +01:00
Q_sprintf( val, "%i", (int)value );
else Q_sprintf( val, "%f", value );
2011-03-09 22:00:00 +01:00
Cvar_Set( var_name, val );
}
/*
============
Cvar_Reset
============
*/
void Cvar_Reset( const char *var_name )
{
Cvar_Set2( var_name, NULL, false );
}
/*
============
Cvar_SetCheatState
Any testing variables will be reset to the safe values
============
*/
void Cvar_SetCheatState( void )
{
convar_t *var;
// set all default vars to the safe value
for( var = cvar_vars; var; var = var->next )
{
2012-12-21 21:00:00 +01:00
// can't process dll cvars - missed latched_string, reset_string
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_SERVERDLL ))
2012-12-21 21:00:00 +01:00
continue;
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_CHEAT ))
2011-03-09 22:00:00 +01:00
{
// the CVAR_LATCHED|CVAR_CHEAT vars might escape the reset here
// because of a different var->latched_string
if( var->latched_string )
{
Mem_Free( var->latched_string );
var->latched_string = NULL;
}
2012-12-21 21:00:00 +01:00
2011-03-11 22:00:00 +01:00
if( Q_strcmp( var->reset_string, var->string ))
2011-03-09 22:00:00 +01:00
Cvar_Set( var->name, var->reset_string );
}
}
}
/*
============
Cvar_Command
Handles variable inspection and changing from the console
============
*/
qboolean Cvar_Command( void )
{
convar_t *v;
// check variables
v = Cvar_FindVar( Cmd_Argv( 0 ));
if( !v ) return false;
// perform a variable print or set
if( Cmd_Argc() == 1 )
{
2016-11-17 22:00:00 +01:00
if( FBitSet( v->flags, CVAR_INIT|CVAR_SERVERDLL ))
Msg( "%s: %s\n", v->name, v->string );
2011-03-09 22:00:00 +01:00
else Msg( "%s: %s ( ^3%s^7 )\n", v->name, v->string, v->reset_string );
return true;
}
// set the value if forcing isn't required
Cvar_Set2( v->name, Cmd_Argv( 1 ), false );
return true;
}
/*
============
Cvar_Toggle_f
Toggles a cvar for easy single key binding
============
*/
void Cvar_Toggle_f( void )
{
int v;
if( Cmd_Argc() != 2 )
{
Msg( "Usage: toggle <variable>\n" );
return;
}
2016-11-17 22:00:00 +01:00
v = !Cvar_VariableInteger( Cmd_Argv( 1 ));
2011-03-09 22:00:00 +01:00
Cvar_Set2( Cmd_Argv( 1 ), va( "%i", v ), false );
}
/*
============
Cvar_Set_f
Allows setting and defining of arbitrary cvars from console, even if they
weren't declared in C code.
============
*/
void Cvar_Set_f( void )
{
int i, c, l = 0, len;
char combined[MAX_CMD_TOKENS];
c = Cmd_Argc();
2016-11-17 22:00:00 +01:00
2011-03-09 22:00:00 +01:00
if( c < 3 )
{
Msg( "Usage: set <variable> <value>\n" );
return;
}
2016-11-17 22:00:00 +01:00
combined[0] = '\0';
2011-03-09 22:00:00 +01:00
for( i = 2; i < c; i++ )
{
2016-11-17 22:00:00 +01:00
len = Q_strlen( Cmd_Argv( i ) + 1 );
2011-03-15 22:00:00 +01:00
if( l + len >= MAX_CMD_TOKENS - 2 )
2011-03-09 22:00:00 +01:00
break;
2011-03-15 22:00:00 +01:00
Q_strcat( combined, Cmd_Argv( i ));
if( i != c-1 ) Q_strcat( combined, " " );
2011-03-09 22:00:00 +01:00
l += len;
}
Cvar_Set2( Cmd_Argv( 1 ), combined, false );
}
/*
============
Cvar_SetU_f
As Cvar_Set, but also flags it as userinfo
============
*/
void Cvar_SetU_f( void )
{
convar_t *v;
if( Cmd_Argc() != 3 )
{
Msg( "Usage: setu <variable> <value>\n" );
return;
}
Cvar_Set_f();
v = Cvar_FindVar( Cmd_Argv( 1 ));
if( !v ) return;
2016-11-17 22:00:00 +01:00
SetBits( v->flags, CVAR_USERINFO );
2011-03-09 22:00:00 +01:00
}
/*
============
Cvar_SetP_f
As Cvar_Set, but also flags it as physinfo
============
*/
void Cvar_SetP_f( void )
{
convar_t *v;
if( Cmd_Argc() != 3 )
{
Msg( "Usage: setp <variable> <value>\n" );
return;
}
Cvar_Set_f();
v = Cvar_FindVar( Cmd_Argv( 1 ));
if( !v ) return;
2016-11-17 22:00:00 +01:00
SetBits( v->flags, CVAR_PHYSICINFO );
2011-03-09 22:00:00 +01:00
}
/*
============
Cvar_SetS_f
As Cvar_Set, but also flags it as serverinfo
============
*/
void Cvar_SetS_f( void )
{
convar_t *v;
if( Cmd_Argc() != 3 )
{
Msg( "Usage: sets <variable> <value>\n" );
return;
}
2016-11-17 22:00:00 +01:00
2011-03-09 22:00:00 +01:00
Cvar_Set_f();
v = Cvar_FindVar( Cmd_Argv( 1 ));
if( !v ) return;
2016-11-17 22:00:00 +01:00
SetBits( v->flags, CVAR_SERVERINFO );
2011-03-09 22:00:00 +01:00
}
/*
============
Cvar_SetA_f
As Cvar_Set, but also flags it as archived
============
*/
void Cvar_SetA_f( void )
{
convar_t *v;
if( Cmd_Argc() != 3 )
{
Msg( "Usage: seta <variable> <value>\n" );
return;
}
Cvar_Set_f();
v = Cvar_FindVar( Cmd_Argv( 1 ));
if( !v ) return;
2016-11-17 22:00:00 +01:00
SetBits( v->flags, CVAR_ARCHIVE );
2011-03-09 22:00:00 +01:00
}
/*
============
Cvar_SetR_f
As Cvar_Set, but also flags it as renderinfo
============
*/
void Cvar_SetR_f( void )
{
if( Cmd_Argc() != 3 )
{
Msg( "Usage: setr <variable> <value>\n" );
return;
}
Cvar_FullSet( Cmd_Argv( 1 ), Cmd_Argv( 2 ), CVAR_RENDERINFO );
}
/*
============
Cvar_SetGL_f
As Cvar_Set, but also flags it as glconfig
============
*/
void Cvar_SetGL_f( void )
{
if( Cmd_Argc() != 3 )
{
Msg( "Usage: setgl <variable> <value>\n" );
return;
}
Cvar_FullSet( Cmd_Argv( 1 ), Cmd_Argv( 2 ), CVAR_GLCONFIG );
}
/*
============
Cvar_Reset_f
============
*/
void Cvar_Reset_f( void )
{
if( Cmd_Argc() != 2 )
{
Msg( "Usage: reset <variable>\n" );
return;
}
2016-11-17 22:00:00 +01:00
2011-03-09 22:00:00 +01:00
Cvar_Reset( Cmd_Argv( 1 ));
}
/*
============
Cvar_List_f
============
*/
void Cvar_List_f( void )
{
convar_t *var;
2012-12-21 21:00:00 +01:00
char *match = NULL;
2016-11-17 22:00:00 +01:00
int i = 0;
2011-03-09 22:00:00 +01:00
2012-12-21 21:00:00 +01:00
if( Cmd_Argc() > 1 )
match = Cmd_Argv( 1 );
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
for( var = cvar_vars; var; var = var->next )
2011-03-09 22:00:00 +01:00
{
2012-12-21 21:00:00 +01:00
if( var->name[0] == '@' )
continue; // never shows system cvars
2011-03-11 22:00:00 +01:00
if( match && !Q_stricmpext( match, var->name ))
2011-03-09 22:00:00 +01:00
continue;
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_SERVERDLL ))
Msg( " %-*s \"^2%s^7\" ^3%s^7\n", 32, var->name, var->string, "server cvar" );
else Msg( " %-*s \"^2%s^7\" ^3%s^7\n", 32, var->name, var->string, var->description );
i++;
2011-03-09 22:00:00 +01:00
}
2016-11-17 22:00:00 +01:00
Msg( "\n%i cvars\n", i );
2011-03-09 22:00:00 +01:00
}
/*
============
Cvar_Restart_f
Resets all cvars to their hardcoded values
============
*/
void Cvar_Restart_f( void )
{
convar_t *var;
convar_t **prev;
prev = &cvar_vars;
while( 1 )
{
var = *prev;
if( !var ) break;
2016-11-17 22:00:00 +01:00
// don't mess with rom values, or some inter-module communication will get broken (cl.active, etc)
if( FBitSet( var->flags, CVAR_READ_ONLY|CVAR_GLCONFIG|CVAR_INIT|CVAR_RENDERINFO|CVAR_SERVERDLL ))
2011-03-09 22:00:00 +01:00
{
prev = &var->next;
continue;
}
// throw out any variables the user created
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_USER_CREATED ))
2011-03-09 22:00:00 +01:00
{
*prev = var->next;
if( var->name ) Mem_Free( var->name );
if( var->string ) Mem_Free( var->string );
if( var->latched_string ) Mem_Free( var->latched_string );
if( var->reset_string ) Mem_Free( var->reset_string );
if( var->description ) Mem_Free( var->description );
Mem_Free( var );
continue;
}
Cvar_Set( var->name, var->reset_string );
prev = &var->next;
}
}
/*
============
Cvar_Latched_f
Now all latched strings is valid
============
*/
void Cvar_Latched_f( void )
{
convar_t *var;
convar_t **prev;
prev = &cvar_vars;
while( 1 )
{
var = *prev;
if( !var ) break;
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_SERVERDLL ))
2011-03-09 22:00:00 +01:00
{
prev = &var->next;
continue;
}
2016-11-17 22:00:00 +01:00
if( FBitSet( var->flags, CVAR_LATCH ) && var->latched_string )
2011-03-09 22:00:00 +01:00
{
Cvar_FullSet( var->name, var->latched_string, var->flags );
Mem_Free( var->latched_string );
var->latched_string = NULL;
}
2016-11-17 22:00:00 +01:00
2011-03-09 22:00:00 +01:00
prev = &var->next;
}
}
/*
============
2016-11-17 22:00:00 +01:00
Cvar_Unlink
2011-03-09 22:00:00 +01:00
2016-11-17 22:00:00 +01:00
unlink all cvars with specified flag
2011-03-09 22:00:00 +01:00
============
*/
2016-11-17 22:00:00 +01:00
void Cvar_Unlink( int group )
2011-03-09 22:00:00 +01:00
{
convar_t *var;
convar_t **prev;
int count = 0;
2016-11-17 22:00:00 +01:00
if( Cvar_VariableInteger( "host_gameloaded" ) && FBitSet( group, CVAR_SERVERDLL ))
2011-03-09 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
MsgDev( D_INFO, "can't unlink variables while server is loaded\n" );
2011-03-09 22:00:00 +01:00
return;
}
2016-11-17 22:00:00 +01:00
if( Cvar_VariableInteger( "host_clientloaded" ) && FBitSet( group, CVAR_CLIENTDLL ))
2011-03-09 22:00:00 +01:00
{
2016-11-17 22:00:00 +01:00
MsgDev( D_INFO, "can't unlink variables while client is loaded\n" );
return;
2011-03-15 22:00:00 +01:00
}
2016-11-17 22:00:00 +01:00
if( Cvar_VariableInteger( "host_gameuiloaded" ) && FBitSet( group, CVAR_GAMEUIDLL ))
2011-07-22 22:00:00 +02:00
{
2016-11-17 22:00:00 +01:00
MsgDev( D_INFO, "can't unlink variables while GameUI is loaded\n" );
2011-07-22 22:00:00 +02:00
return;
}
2011-03-15 22:00:00 +01:00
prev = &cvar_vars;
while( 1 )
{
var = *prev;
if( !var ) break;
2016-11-17 22:00:00 +01:00
// do filter by specified group
if( group && !FBitSet( var->flags, group ))
2011-03-09 22:00:00 +01:00
{
prev = &var->next;
continue;
}
// throw out any variables the game created
*prev = var->next;
if( var->string ) Mem_Free( var->string );
2016-11-17 22:00:00 +01:00
if( !FBitSet( var->flags, CVAR_SERVERDLL ))
{
if( var->name ) Mem_Free( var->name );
if( var->latched_string ) Mem_Free( var->latched_string );
if( var->reset_string ) Mem_Free( var->reset_string );
if( var->description ) Mem_Free( var->description );
Mem_Free( var );
}
2011-03-09 22:00:00 +01:00
count++;
}
}
/*
============
Cvar_Init
Reads in all archived cvars
============
*/
void Cvar_Init( void )
{
cvar_vars = NULL;
userinfo = Cvar_Get( "@userinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
physinfo = Cvar_Get( "@physinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
serverinfo = Cvar_Get( "@serverinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
renderinfo = Cvar_Get( "@renderinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
2016-11-17 22:00:00 +01:00
cmd_scripting = Cvar_Get( "cmd_scripting", "0", CVAR_ARCHIVE, "enable simple condition checking and variable operations" );
Cmd_AddCommand( "toggle", Cvar_Toggle_f, "toggles a console variable's values (use for more info)" );
Cmd_AddCommand( "set", Cvar_Set_f, "create or change the value of a console variable" );
Cmd_AddCommand( "sets", Cvar_SetS_f, "create or change the value of a serverinfo variable" );
Cmd_AddCommand( "setu", Cvar_SetU_f, "create or change the value of a userinfo variable" );
Cmd_AddCommand( "setp", Cvar_SetP_f, "create or change the value of a physicinfo variable" );
Cmd_AddCommand( "setr", Cvar_SetR_f, "create or change the value of a renderinfo variable" );
Cmd_AddCommand( "setgl", Cvar_SetGL_f, "create or change the value of a opengl variable" );
Cmd_AddCommand( "seta", Cvar_SetA_f, "create or change the value of a console variable that will be saved to config.cfg" );
Cmd_AddCommand( "reset", Cvar_Reset_f, "reset any type variable to initial value" );
Cmd_AddCommand( "latch", Cvar_Latched_f, "apply latched values" );
Cmd_AddCommand( "cvarlist", Cvar_List_f, "display all console variables beginning with the specified prefix" );
Cmd_AddCommand( "unsetall", Cvar_Restart_f, "reset all console variables to their default values" );
}