]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cvar.c
Rename a few of the fake loss and fake latency cvars
[xonotic/darkplaces.git] / cvar.c
diff --git a/cvar.c b/cvar.c
index 354c498bec069d5aa393cc9411cd10bd0bc5621d..53996326d39316b40f3b97ac51d4c988962d948f 100644 (file)
--- a/cvar.c
+++ b/cvar.c
@@ -32,7 +32,7 @@ cvar_state_t cvars_null;
 Cvar_FindVar
 ============
 */
-cvar_t *Cvar_FindVar(cvar_state_t *cvars, const char *var_name, int neededflags)
+cvar_t *Cvar_FindVar(cvar_state_t *cvars, const char *var_name, int neededflags, qboolean alias)
 {
        int hashindex;
        cvar_t *var;
@@ -40,9 +40,12 @@ cvar_t *Cvar_FindVar(cvar_state_t *cvars, const char *var_name, int neededflags)
        // use hash lookup to minimize search time
        hashindex = CRC_Block((const unsigned char *)var_name, strlen(var_name)) % CVAR_HASHSIZE;
        for (var = cvars->hashtable[hashindex];var;var = var->nextonhashchain)
-               if (!strcmp (var_name, var->name) && (var->flags & neededflags))
+               if (!strcmp (var_name, var->name))
+               {
+                       if(!alias && var->alias)
+                               return var->alias;
                        return var;
-
+               }
        return NULL;
 }
 
@@ -52,7 +55,7 @@ cvar_t *Cvar_FindVarAfter(cvar_state_t *cvars, const char *prev_var_name, int ne
 
        if (*prev_var_name)
        {
-               var = Cvar_FindVar(cvars, prev_var_name, neededflags);
+               var = Cvar_FindVar(cvars, prev_var_name, neededflags, false);
                if (!var)
                        return NULL;
                var = var->next;
@@ -109,7 +112,7 @@ float Cvar_VariableValueOr(cvar_state_t *cvars, const char *var_name, float def,
 {
        cvar_t *var;
 
-       var = Cvar_FindVar(cvars, var_name, neededflags);
+       var = Cvar_FindVar(cvars, var_name, neededflags, false);
        if (!var)
                return def;
        return atof (var->string);
@@ -129,7 +132,7 @@ const char *Cvar_VariableStringOr(cvar_state_t *cvars, const char *var_name, con
 {
        cvar_t *var;
 
-       var = Cvar_FindVar(cvars, var_name, neededflags);
+       var = Cvar_FindVar(cvars, var_name, neededflags, false);
        if (!var)
                return def;
        return var->string;
@@ -149,7 +152,7 @@ const char *Cvar_VariableDefString(cvar_state_t *cvars, const char *var_name, in
 {
        cvar_t *var;
 
-       var = Cvar_FindVar(cvars, var_name, neededflags);
+       var = Cvar_FindVar(cvars, var_name, neededflags, false);
        if (!var)
                return cvar_null_string;
        return var->defstring;
@@ -164,7 +167,7 @@ const char *Cvar_VariableDescription(cvar_state_t *cvars, const char *var_name,
 {
        cvar_t *var;
 
-       var = Cvar_FindVar(cvars, var_name, neededflags);
+       var = Cvar_FindVar(cvars, var_name, neededflags, false);
        if (!var)
                return cvar_null_string;
        return var->description;
@@ -251,6 +254,25 @@ const char **Cvar_CompleteBuildList(cvar_state_t *cvars, const char *partial, in
        return buf;
 }
 
+void Cvar_PrintHelp(cvar_t *cvar, qboolean full)
+{
+       cvar_t *cvar_actual;
+
+       Con_Printf("^3%s^7", cvar->name);
+       if(cvar->alias) {
+               cvar_actual = cvar->alias;
+               Con_Printf(" (now ^3%s^7)", cvar_actual->name);
+       } else {
+               cvar_actual = cvar;
+       }
+
+       Con_Printf(" is \"%s\" [\"%s\"] ", ((cvar_actual->flags & CVAR_PRIVATE) ? "********"/*hunter2*/ : cvar_actual->string), cvar_actual->defstring);
+       
+       if (full)
+               Con_Printf("%s", cvar_actual->description);
+       Con_Printf("\n");
+}
+
 // written by LadyHavoc
 void Cvar_CompleteCvarPrint(cvar_state_t *cvars, const char *partial, int neededflags)
 {
@@ -259,7 +281,7 @@ void Cvar_CompleteCvarPrint(cvar_state_t *cvars, const char *partial, int needed
        // Loop through the command list and print all matches
        for (cvar = cvars->vars; cvar; cvar = cvar->next)
                if (!strncasecmp(partial, cvar->name, len) && (cvar->flags & neededflags))
-                       Con_Printf ("^3%s^7 is \"%s\" [\"%s\"] %s\n", cvar->name, cvar->string, cvar->defstring, cvar->description);
+                       Cvar_PrintHelp(cvar, true);
 }
 
 // check if a cvar is held by some progs
@@ -341,25 +363,35 @@ static void Cvar_SetQuick_Internal (cvar_t *var, const char *value)
        qboolean changed;
        size_t valuelen;
        char vabuf[1024];
+       char new_value[MAX_INPUTLINE];
+
+       if(var->alias)
+               var = var->alias;
 
        changed = strcmp(var->string, value) != 0;
        // LadyHavoc: don't reallocate when there is no change
        if (!changed)
                return;
 
+       memcpy(new_value,value,MAX_INPUTLINE);
+
+       // Call the function stored in the cvar for bounds checking, cleanup, etc
+       if (var->callback)
+               var->callback(new_value);
+
        // LadyHavoc: don't reallocate when the buffer is the same size
-       valuelen = strlen(value);
+       valuelen = strlen(new_value);
        if (!var->string || strlen(var->string) != valuelen)
        {
                Z_Free ((char *)var->string);   // free the old value string
 
                var->string = (char *)Z_Malloc (valuelen + 1);
        }
-       memcpy ((char *)var->string, value, valuelen + 1);
+       memcpy ((char *)var->string, new_value, valuelen + 1);
        var->value = atof (var->string);
        var->integer = (int) var->value;
        if ((var->flags & CVAR_NOTIFY) && changed && sv.active && !sv_disablenotify.integer)
-               SV_BroadcastPrintf("\"%s\" changed to \"%s\"\n", var->name, var->string);
+               SV_BroadcastPrintf("\001^3Server cvar \"%s\" changed to \"%s\"\n", var->name, var->string);
 #if 0
        // TODO: add infostring support to the server?
        if ((var->flags & CVAR_SERVERINFO) && changed && sv.active)
@@ -438,7 +470,7 @@ void Cvar_SetQuick (cvar_t *var, const char *value)
 void Cvar_Set(cvar_state_t *cvars, const char *var_name, const char *value)
 {
        cvar_t *var;
-       var = Cvar_FindVar(cvars, var_name, ~0);
+       var = Cvar_FindVar(cvars, var_name, ~0, false);
        if (var == NULL)
        {
                Con_Printf("Cvar_Set: variable %s not found\n", var_name);
@@ -474,6 +506,23 @@ void Cvar_SetValue(cvar_state_t *cvars, const char *var_name, float value)
        Cvar_Set(cvars, var_name, val);
 }
 
+void Cvar_RegisterCallback(cvar_t *var, void (*callback)(char *))
+{
+       var->callback = callback;
+}
+
+void Cvar_RegisterAlias(cvar_t *alias, cvar_t *target)
+{
+       if(!(alias->flags & CVAR_ALIAS)) {
+               Con_Warnf("Cvar_RegisterAlias: \"%s\" is not declared as an alias\n", alias->name);
+               return;
+       }
+       // We'll want to register it first
+       Cvar_RegisterVariable(alias);
+
+       alias->alias = target;
+}
+
 /*
 ============
 Cvar_RegisterVariable
@@ -490,26 +539,33 @@ void Cvar_RegisterVariable (cvar_t *variable)
        size_t alloclen;
        int i;
 
-       switch (variable->flags & (CVAR_CLIENT | CVAR_SERVER))
+       if(!(variable->flags & CVAR_ALIAS))
+       {
+               switch (variable->flags & (CVAR_CLIENT | CVAR_SERVER))
+               {
+               case CVAR_CLIENT:
+               case CVAR_SERVER:
+               case CVAR_CLIENT | CVAR_SERVER:
+                       cvars = &cvars_all;
+                       break;
+               case 0:
+                       Sys_Error("Cvar_RegisterVariable({\"%s\", \"%s\", %i}) with no CVAR_CLIENT | CVAR_SERVER flags\n", variable->name, variable->string, variable->flags);
+                       break;
+               default:
+                       Sys_Error("Cvar_RegisterVariable({\"%s\", \"%s\", %i}) with weird CVAR_CLIENT | CVAR_SERVER flags\n", variable->name, variable->string, variable->flags);
+                       break;
+               }
+       }
+       else
        {
-       case CVAR_CLIENT:
-       case CVAR_SERVER:
-       case CVAR_CLIENT | CVAR_SERVER:
                cvars = &cvars_all;
-               break;
-       case 0:
-               Sys_Error("Cvar_RegisterVariable({\"%s\", \"%s\", %i}) with no CVAR_CLIENT | CVAR_SERVER flags\n", variable->name, variable->string, variable->flags);
-               break;
-       default:
-               Sys_Error("Cvar_RegisterVariable({\"%s\", \"%s\", %i}) with weird CVAR_CLIENT | CVAR_SERVER flags\n", variable->name, variable->string, variable->flags);
-               break;
        }
-
+       
        if (developer_extra.integer)
                Con_DPrintf("Cvar_RegisterVariable({\"%s\", \"%s\", %i});\n", variable->name, variable->string, variable->flags);
 
 // first check to see if it has already been defined
-       cvar = Cvar_FindVar(cvars, variable->name, ~0);
+       cvar = Cvar_FindVar(cvars, variable->name, ~0, true);
        if (cvar)
        {
                if (cvar->flags & CVAR_ALLOCATED)
@@ -560,16 +616,18 @@ void Cvar_RegisterVariable (cvar_t *variable)
                Con_Printf("Cvar_RegisterVariable: %s is a command\n", variable->name);
                return;
        }
-
-// copy the value off, because future sets will Z_Free it
-       oldstr = (char *)variable->string;
-       alloclen = strlen(variable->string) + 1;
-       variable->string = (char *)Z_Malloc (alloclen);
-       memcpy ((char *)variable->string, oldstr, alloclen);
-       variable->defstring = (char *)Z_Malloc (alloclen);
-       memcpy ((char *)variable->defstring, oldstr, alloclen);
-       variable->value = atof (variable->string);
-       variable->integer = (int) variable->value;
+       if(!(variable->flags & CVAR_ALIAS))
+       {
+               // copy the value off, because future sets will Z_Free it
+               oldstr = (char *)variable->string;
+               alloclen = strlen(variable->string) + 1;
+               variable->string = (char *)Z_Malloc (alloclen);
+               memcpy ((char *)variable->string, oldstr, alloclen);
+               variable->defstring = (char *)Z_Malloc (alloclen);
+               memcpy ((char *)variable->defstring, oldstr, alloclen);
+               variable->value = atof (variable->string);
+               variable->integer = (int) variable->value;
+       }
 
        // Mark it as not an autocvar.
        for (i = 0;i < PRVM_PROG_MAX;i++)
@@ -609,7 +667,7 @@ cvar_t *Cvar_Get(cvar_state_t *cvars, const char *name, const char *value, int f
                Con_DPrintf("Cvar_Get(\"%s\", \"%s\", %i);\n", name, value, flags);
 
 // first check to see if it has already been defined
-       cvar = Cvar_FindVar(cvars, name, ~0);
+       cvar = Cvar_FindVar(cvars, name, ~0, true);
        if (cvar)
        {
                cvar->flags |= flags;
@@ -679,6 +737,20 @@ cvar_t *Cvar_Get(cvar_state_t *cvars, const char *name, const char *value, int f
        return cvar;
 }
 
+qboolean Cvar_Readonly (cvar_t *var, const char *cmd_name)
+{
+       if (var->flags & CVAR_READONLY || (var->alias && (var->alias->flags & CVAR_READONLY)))
+       {
+               if(cmd_name)
+                       Con_Printf("%s: ",cmd_name);
+               Con_Printf("%s", var->name);
+               if (var->alias && var->alias->name)
+                       Con_Printf(" (from %s)",var->alias->name);
+               Con_Printf(" is read-only\n");
+               return true;
+       }
+       return false;
+}
 
 /*
 ============
@@ -693,25 +765,23 @@ qboolean  Cvar_Command (cmd_state_t *cmd)
        cvar_t                  *v;
 
 // check variables
-       v = Cvar_FindVar(cvars, Cmd_Argv(cmd, 0), cmd->cvars_flagsmask);
+       v = Cvar_FindVar(cvars, Cmd_Argv(cmd, 0), (cmd->cvars_flagsmask), true);
        if (!v)
                return false;
 
 // perform a variable print or set
        if (Cmd_Argc(cmd) == 1)
        {
-               Con_Printf("\"%s\" is \"%s\" [\"%s\"]\n", v->name, ((v->flags & CVAR_PRIVATE) ? "********"/*hunter2*/ : v->string), v->defstring);
+               Cvar_PrintHelp(v, true);
                return true;
        }
 
        if (developer_extra.integer)
                Con_DPrint("Cvar_Command: ");
-
-       if (v->flags & CVAR_READONLY)
-       {
-               Con_Printf("%s is read-only\n", v->name);
+       
+       if(Cvar_Readonly(v, NULL))
                return true;
-       }
+       
        Cvar_SetQuick(v, Cmd_Argv(cmd, 1));
        if (developer_extra.integer)
                Con_DPrint("\n");
@@ -725,7 +795,11 @@ void Cvar_UnlockDefaults(cmd_state_t *cmd)
        cvar_t *var;
        // unlock the default values of all cvars
        for (var = cvars->vars ; var ; var = var->next)
+       {
+               if(var->flags & CVAR_ALIAS)
+                       continue;
                var->flags &= ~CVAR_DEFAULTSET;
+       }
 }
 
 
@@ -736,6 +810,8 @@ void Cvar_LockDefaults_f(cmd_state_t *cmd)
        // lock in the default values of all cvars
        for (var = cvars->vars ; var ; var = var->next)
        {
+               if(var->flags & CVAR_ALIAS)
+                       continue;
                if (!(var->flags & CVAR_DEFAULTSET))
                {
                        size_t alloclen;
@@ -755,6 +831,8 @@ void Cvar_SaveInitState(cvar_state_t *cvars)
        cvar_t *c;
        for (c = cvars->vars;c;c = c->next)
        {
+               if(c->flags & CVAR_ALIAS)
+                       continue;
                c->initstate = true;
                c->initflags = c->flags;
                c->initdefstring = Mem_strdup(zonemempool, c->defstring);
@@ -772,6 +850,8 @@ void Cvar_RestoreInitState(cvar_state_t *cvars)
        cvar_t *c2, **cp2;
        for (cp = &cvars->vars;(c = *cp);)
        {
+               if(c->flags & CVAR_ALIAS)
+                       continue;
                if (c->initstate)
                {
                        // restore this cvar, it existed at init
@@ -848,8 +928,12 @@ void Cvar_ResetToDefaults_All_f(cmd_state_t *cmd)
        cvar_t *var;
        // restore the default values of all cvars
        for (var = cvars->vars ; var ; var = var->next)
+       {
+               if(var->flags & CVAR_ALIAS)
+                       continue;
                if((var->flags & CVAR_NORESETTODEFAULTS) == 0)
                        Cvar_SetQuick(var, var->defstring);
+       }
 }
 
 
@@ -859,8 +943,12 @@ void Cvar_ResetToDefaults_NoSaveOnly_f(cmd_state_t *cmd)
        cvar_t *var;
        // restore the default values of all cvars
        for (var = cvars->vars ; var ; var = var->next)
+       {
+               if(var->flags & CVAR_ALIAS)
+                       continue;
                if ((var->flags & (CVAR_NORESETTODEFAULTS | CVAR_SAVE)) == 0)
                        Cvar_SetQuick(var, var->defstring);
+       }
 }
 
 
@@ -870,8 +958,12 @@ void Cvar_ResetToDefaults_SaveOnly_f(cmd_state_t *cmd)
        cvar_t *var;
        // restore the default values of all cvars
        for (var = cvars->vars ; var ; var = var->next)
+       {
+               if(var->flags & CVAR_ALIAS)
+                       continue;
                if ((var->flags & (CVAR_NORESETTODEFAULTS | CVAR_SAVE)) == CVAR_SAVE)
                        Cvar_SetQuick(var, var->defstring);
+       }
 }
 
 
@@ -889,13 +981,16 @@ void Cvar_WriteVariables (cvar_state_t *cvars, qfile_t *f)
        char buf1[MAX_INPUTLINE], buf2[MAX_INPUTLINE];
 
        // don't save cvars that match their default value
-       for (var = cvars->vars ; var ; var = var->next)
+       for (var = cvars->vars ; var ; var = var->next) {
+               if(var->flags & CVAR_ALIAS)
+                       continue;
                if ((var->flags & CVAR_SAVE) && (strcmp(var->string, var->defstring) || ((var->flags & CVAR_ALLOCATED) && !(var->flags & CVAR_DEFAULTSET))))
                {
                        Cmd_QuoteString(buf1, sizeof(buf1), var->name, "\"\\$", false);
                        Cmd_QuoteString(buf2, sizeof(buf2), var->string, "\"\\$", false);
                        FS_Printf(f, "%s\"%s\" \"%s\"\n", var->flags & CVAR_ALLOCATED ? "seta " : "", buf1, buf2);
                }
+       }
 }
 
 
@@ -934,7 +1029,7 @@ void Cvar_List_f(cmd_state_t *cmd)
                if (len && (ispattern ? !matchpattern_with_separator(cvar->name, partial, false, "", false) : strncmp (partial,cvar->name,len)))
                        continue;
 
-               Con_Printf("%s is \"%s\" [\"%s\"] %s\n", cvar->name, ((cvar->flags & CVAR_PRIVATE) ? "********"/*hunter2*/ : cvar->string), cvar->defstring, cvar->description);
+               Cvar_PrintHelp(cvar, true);
                count++;
        }
 
@@ -963,12 +1058,10 @@ void Cvar_Set_f(cmd_state_t *cmd)
        }
 
        // check if it's read-only
-       cvar = Cvar_FindVar(cvars, Cmd_Argv(cmd, 1), ~0);
-       if (cvar && cvar->flags & CVAR_READONLY)
-       {
-               Con_Printf("Set: %s is read-only\n", cvar->name);
-               return;
-       }
+       cvar = Cvar_FindVar(cvars, Cmd_Argv(cmd, 1), ~0, true);
+       if (cvar)
+               if(Cvar_Readonly(cvar,"Set"))
+                       return;
 
        if (developer_extra.integer)
                Con_DPrint("Set: ");
@@ -990,12 +1083,10 @@ void Cvar_SetA_f(cmd_state_t *cmd)
        }
 
        // check if it's read-only
-       cvar = Cvar_FindVar(cvars, Cmd_Argv(cmd, 1), ~0);
-       if (cvar && cvar->flags & CVAR_READONLY)
-       {
-               Con_Printf("SetA: %s is read-only\n", cvar->name);
-               return;
-       }
+       cvar = Cvar_FindVar(cvars, Cmd_Argv(cmd, 1), ~0, true);
+       if (cvar)
+               if(Cvar_Readonly(cvar,"SetA"))
+                       return;
 
        if (developer_extra.integer)
                Con_DPrint("SetA: ");
@@ -1024,11 +1115,8 @@ void Cvar_Del_f(cmd_state_t *cmd)
                        Con_Printf("%s: %s is not defined\n", Cmd_Argv(cmd, 0), Cmd_Argv(cmd, i));
                        continue;
                }
-               if(cvar->flags & CVAR_READONLY)
-               {
-                       Con_Printf("%s: %s is read-only\n", Cmd_Argv(cmd, 0), cvar->name);
+               if(Cvar_Readonly(cvar, Cmd_Argv(cmd, 0)))
                        continue;
-               }
                if(!(cvar->flags & CVAR_ALLOCATED))
                {
                        Con_Printf("%s: %s is static and cannot be deleted\n", Cmd_Argv(cmd, 0), cvar->name);
@@ -1049,13 +1137,15 @@ void Cvar_Del_f(cmd_state_t *cmd)
                        parent->nextonhashchain = cvar->nextonhashchain;
                else if(link)
                        *link = cvar->nextonhashchain;
+               if(!(cvar->flags & CVAR_ALIAS))
+               {
+                       if(cvar->description != cvar_dummy_description)
+                               Z_Free((char *)cvar->description);
 
-               if(cvar->description != cvar_dummy_description)
-                       Z_Free((char *)cvar->description);
-
-               Z_Free((char *)cvar->name);
-               Z_Free((char *)cvar->string);
-               Z_Free((char *)cvar->defstring);
+                       Z_Free((char *)cvar->name);
+                       Z_Free((char *)cvar->string);
+                       Z_Free((char *)cvar->defstring);
+               }
                Z_Free(cvar);
        }
 }
@@ -1081,6 +1171,8 @@ void Cvar_FillAll_f(cmd_state_t *cmd)
        buf[n] = 0;
        for(var = cvars->vars; var; var = var->next)
        {
+               if(var->flags & CVAR_ALIAS)
+                       continue;
                for(i = 0, p = buf, q = var->name; i < n; ++i)
                {
                        *p++ = *q++;