Eradicated the CVAR_NQUSERINFOHACK flag, for good
authorcloudwalk <cloudwalk@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 23 Jun 2020 03:54:38 +0000 (03:54 +0000)
committercloudwalk <cloudwalk@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 23 Jun 2020 03:54:38 +0000 (03:54 +0000)
This is a massive commit, admittedly. But pretty much every single
change goes together and this could not be split up, unfortunately.

I implemented a few new functions and turned a lot of the userinfo keys
into cvars, just like their QW counterparts. CMD_INITWAIT is also gone
and replaced by CMD_USERINFO to denote special server-from-client
commands that specifically change a userinfo string of a given client.

I'm sure there's a cleaner way to do this, especially the holy callback
trinity I implemented to avoid an infinite loop when synchronizing
topcolor and bottomcolor with _cl_color and vice versa. But, if this
gets rid of decade old legacy cruft, and makes it all easier to maintain
down the road, that's a plus for me.

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12722 d7cf8633-e32d-0410-b094-e92efae38249

14 files changed:
cl_input.c
cl_main.c
cl_parse.c
cl_screen.c
client.h
cmd.c
cmd.h
cvar.c
cvar.h
host_cmd.c
menu.c
netconn.c
netconn.h
sv_ccmds.c

index 8ccd347..c940395 100644 (file)
@@ -2114,7 +2114,7 @@ void CL_SendMove(void)
 
        // send the reliable message (forwarded commands) if there is one
        if (buf.cursize || cls.netcon->message.cursize)
-               NetConn_SendUnreliableMessage(cls.netcon, &buf, cls.protocol, max(20*(buf.cursize+40), cl_rate.integer), cl_rate_burstsize.integer, false);
+               NetConn_SendUnreliableMessage(cls.netcon, &buf, cls.protocol, max(20*(buf.cursize+40), rate.integer), rate_burstsize.integer, false);
 
        if (quemove)
        {
index 9958ecd..77467bf 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -209,6 +209,9 @@ void CL_ClearState(void)
        CL_Screen_NewMap();
 }
 
+extern cvar_t topcolor;
+extern cvar_t bottomcolor;
+
 void CL_SetInfo(const char *key, const char *value, qboolean send, qboolean allowstarkey, qboolean allowmodel, qboolean quiet)
 {
        int i;
@@ -255,11 +258,13 @@ void CL_SetInfo(const char *key, const char *value, qboolean send, qboolean allo
                }
                else if (!strcasecmp(key, "topcolor"))
                {
-                       // don't send anything, the combined color code will be updated manually
+                       MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
+                       MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "color %i %i", atoi(value), bottomcolor.integer));
                }
                else if (!strcasecmp(key, "bottomcolor"))
                {
-                       // don't send anything, the combined color code will be updated manually
+                       MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
+                       MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "color %i %i", topcolor.integer, atoi(value)));
                }
                else if (!strcasecmp(key, "rate"))
                {
index d7c97f7..d3b0ea8 100644 (file)
@@ -1564,35 +1564,37 @@ static void CL_DownloadFinished_f(cmd_state_t *cmd)
        CL_BeginDownloads(false);
 }
 
+extern cvar_t topcolor;
+extern cvar_t bottomcolor;
 static void CL_SendPlayerInfo(void)
 {
        char vabuf[1024];
        MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
-       MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "name \"%s\"", cl_name.string));
+       MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "name \"%s\"", name.string));
 
        MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
-       MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "color %i %i", cl_color.integer >> 4, cl_color.integer & 15));
+       MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "color %i %i", topcolor.integer, bottomcolor.integer));
 
        MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
-       MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "rate %i", cl_rate.integer));
+       MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "rate %i", rate.integer));
 
        MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
-       MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "rate_burstsize %i", cl_rate_burstsize.integer));
+       MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "rate_burstsize %i", rate_burstsize.integer));
 
-       if (cl_pmodel.integer)
+       if (pmodel.integer)
        {
                MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
-               MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "pmodel %i", cl_pmodel.integer));
+               MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "pmodel %i", pmodel.integer));
        }
-       if (*cl_playermodel.string)
+       if (*playermodel.string)
        {
                MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
-               MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "playermodel %s", cl_playermodel.string));
+               MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "playermodel %s", playermodel.string));
        }
-       if (*cl_playerskin.string)
+       if (*playerskin.string)
        {
                MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
-               MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "playerskin %s", cl_playerskin.string));
+               MSG_WriteString (&cls.netcon->message, va(vabuf, sizeof(vabuf), "playerskin %s", playerskin.string));
        }
 }
 
index 2b0dfe4..312c68e 100644 (file)
@@ -343,7 +343,7 @@ static void SCR_DrawNetGraph (void)
        graphwidth = 120;
        graphheight = 70;
        graphscale = 1.0f / 1500.0f;
-       graphlimit = cl_rate.integer;
+       graphlimit = rate.integer;
 
        netgraphsperrow = (vid_conwidth.integer + separator2) / (graphwidth * 2 + separator1 + separator2);
        netgraphsperrow = max(netgraphsperrow, 1);
index f505f21..835acc9 100644 (file)
--- a/client.h
+++ b/client.h
@@ -1458,13 +1458,13 @@ client_state_t;
 //
 // cvars
 //
-extern cvar_t cl_name;
+extern cvar_t name;
 extern cvar_t cl_color;
-extern cvar_t cl_rate;
-extern cvar_t cl_rate_burstsize;
-extern cvar_t cl_pmodel;
-extern cvar_t cl_playermodel;
-extern cvar_t cl_playerskin;
+extern cvar_t rate;
+extern cvar_t rate_burstsize;
+extern cvar_t pmodel;
+extern cvar_t playermodel;
+extern cvar_t playerskin;
 
 extern cvar_t rcon_password;
 extern cvar_t rcon_address;
diff --git a/cmd.c b/cmd.c
index 095d63b..ea0b608 100644 (file)
--- a/cmd.c
+++ b/cmd.c
@@ -1520,7 +1520,7 @@ void Cmd_Init(void)
        // server commands received from clients have no reason to access cvars, cvar expansion seems perilous.
        cmd_serverfromclient.cvars = &cvars_null;
        cmd_serverfromclient.cvars_flagsmask = 0;
-       cmd_serverfromclient.cmd_flags = CMD_SERVER_FROM_CLIENT;
+       cmd_serverfromclient.cmd_flags = CMD_SERVER_FROM_CLIENT | CMD_USERINFO;
        cmd_serverfromclient.userdefined = &cmd_userdefined_null;
 
 //
diff --git a/cmd.h b/cmd.h
index 4ada589..72f481b 100644 (file)
--- a/cmd.h
+++ b/cmd.h
@@ -46,7 +46,7 @@ struct cmd_state_s;
 #define CMD_SERVER                             (1<<1)
 #define CMD_CLIENT_FROM_SERVER (1<<2)
 #define CMD_SERVER_FROM_CLIENT (1<<3)
-#define CMD_INITWAIT                   (1<<4)
+#define CMD_USERINFO                   (1<<4)
 #define CMD_CHEAT                              (1<<5)
 
 
diff --git a/cvar.c b/cvar.c
index 5c9e0d4..905fa75 100644 (file)
--- a/cvar.c
+++ b/cvar.c
@@ -373,10 +373,8 @@ Cvar_Set
 extern cvar_t sv_disablenotify;
 static void Cvar_SetQuick_Internal (cvar_t *var, const char *value)
 {
-       cvar_state_t *cvars = &cvars_all;
        qboolean changed;
        size_t valuelen;
-       char vabuf[1024];
        char new_value[MAX_INPUTLINE];
 
        changed = strcmp(var->string, value) != 0;
@@ -416,50 +414,8 @@ static void Cvar_SetQuick_Internal (cvar_t *var, const char *value)
                }
        }
 #endif
-       if ((var->flags & CVAR_USERINFO) && cls.state != ca_dedicated)
+       if (var->flags & CVAR_USERINFO)
                CL_SetInfo(var->name, var->string, true, false, false, false);
-       else if ((var->flags & CVAR_NQUSERINFOHACK) && cls.state != ca_dedicated)
-       {
-               // update the cls.userinfo to have proper values for the
-               // silly nq config variables.
-               //
-               // this is done when these variables are changed rather than at
-               // connect time because if the user or code checks the userinfo and it
-               // holds weird values it may cause confusion...
-               if (!strcmp(var->name, "_cl_color"))
-               {
-                       int top = (var->integer >> 4) & 15, bottom = var->integer & 15;
-                       CL_SetInfo("topcolor", va(vabuf, sizeof(vabuf), "%i", top), true, false, false, false);
-                       CL_SetInfo("bottomcolor", va(vabuf, sizeof(vabuf), "%i", bottom), true, false, false, false);
-                       if (cls.protocol != PROTOCOL_QUAKEWORLD && cls.netcon)
-                       {
-                               MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
-                               MSG_WriteString(&cls.netcon->message, va(vabuf, sizeof(vabuf), "color %i %i", top, bottom));
-                       }
-               }
-               else if (!strcmp(var->name, "_cl_rate"))
-                       CL_SetInfo("rate", va(vabuf, sizeof(vabuf), "%i", var->integer), true, false, false, false);
-               else if (!strcmp(var->name, "_cl_rate_burstsize"))
-                       CL_SetInfo("rate_burstsize", va(vabuf, sizeof(vabuf), "%i", var->integer), true, false, false, false);
-               else if (!strcmp(var->name, "_cl_playerskin"))
-                       CL_SetInfo("playerskin", var->string, true, false, false, false);
-               else if (!strcmp(var->name, "_cl_playermodel"))
-                       CL_SetInfo("playermodel", var->string, true, false, false, false);
-               else if (!strcmp(var->name, "_cl_name"))
-                       CL_SetInfo("name", var->string, true, false, false, false);
-               else if (!strcmp(var->name, "rcon_secure"))
-               {
-                       // whenever rcon_secure is changed to 0, clear rcon_password for
-                       // security reasons (prevents a send-rcon-password-as-plaintext
-                       // attack based on NQ protocol session takeover and svc_stufftext)
-                       if(var->integer <= 0)
-                               Cvar_Set(cvars, "rcon_password", "");
-               }
-#ifdef CONFIG_MENU
-               else if (!strcmp(var->name, "net_slist_favorites"))
-                       NetConn_UpdateFavorites();
-#endif
-       }
 
        Cvar_UpdateAutoCvar(var);
 }
@@ -490,6 +446,14 @@ void Cvar_Set(cvar_state_t *cvars, const char *var_name, const char *value)
        Cvar_SetQuick(var, value);
 }
 
+void Cvar_Set_NoCallback(cvar_t *var, const char *value)
+{
+       void (*callback_save)(char *) = var->callback;
+       var->callback = NULL;
+       Cvar_SetQuick_Internal(var, value);
+       var->callback = callback_save;
+}
+
 /*
 ============
 Cvar_SetValue
diff --git a/cvar.h b/cvar.h
index 752c227..e7234b1 100644 (file)
--- a/cvar.h
+++ b/cvar.h
@@ -68,16 +68,14 @@ interface from being ambiguous.
 #define CVAR_USERINFO 16
 // CVAR_PRIVATE means do not $ expand or sendcvar this cvar under any circumstances (rcon_password uses this)
 #define CVAR_PRIVATE 32
-// this means that this cvar should update a userinfo key but the name does not correspond directly to the userinfo key to update, and may require additional conversion ("_cl_color" for example should update "topcolor" and "bottomcolor")
-#define CVAR_NQUSERINFOHACK 64
 // for engine-owned cvars that must not be reset on gametype switch (e.g. scr_screenshot_name, which otherwise isn't set to the mod name properly)
-#define CVAR_NORESETTODEFAULTS 128
+#define CVAR_NORESETTODEFAULTS 64
 // cvar is accessible in client
-#define CVAR_CLIENT 256
+#define CVAR_CLIENT 128
 // cvar is accessible in dedicated server
-#define CVAR_SERVER 512
+#define CVAR_SERVER 256
 // used to determine if flags is valid
-#define CVAR_MAXFLAGSVAL 1023
+#define CVAR_MAXFLAGSVAL 511
 // for internal use only!
 #define CVAR_DEFAULTSET (1<<30)
 #define CVAR_ALLOCATED (1<<31)
@@ -132,6 +130,7 @@ typedef struct cvar_s
        const char *defstring;
 
        void (*callback)(char *value);
+       qboolean ignore_callback;
 
        char **aliases;
        int aliasindex;
@@ -191,6 +190,7 @@ qboolean Cvar_Readonly (cvar_t *var, const char *cmd_name);
 
 /// equivelant to "<name> <variable>" typed at the console
 void Cvar_Set (cvar_state_t *cvars, const char *var_name, const char *value);
+void Cvar_Set_NoCallback (cvar_t *var, const char *value);
 
 /// expands value to a string and calls Cvar_Set
 void Cvar_SetValue (cvar_state_t *cvars, const char *var_name, float value);
index c7f36ef..53e35a3 100644 (file)
@@ -30,29 +30,33 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "mdfour.h"
 #include <time.h>
 
-int current_skill;
 extern cvar_t sv_adminnick;
 extern cvar_t sv_status_privacy;
 extern cvar_t sv_status_show_qcstatus;
 extern cvar_t sv_namechangetimer;
 cvar_t rcon_password = {CVAR_CLIENT | CVAR_SERVER | CVAR_PRIVATE, "rcon_password", "", "password to authenticate rcon commands; NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password; may be set to a string of the form user1:pass1 user2:pass2 user3:pass3 to allow multiple user accounts - the client then has to specify ONE of these combinations"};
-cvar_t rcon_secure = {CVAR_CLIENT | CVAR_SERVER | CVAR_NQUSERINFOHACK, "rcon_secure", "0", "force secure rcon authentication (1 = time based, 2 = challenge based); NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password"};
+cvar_t rcon_secure = {CVAR_CLIENT | CVAR_SERVER, "rcon_secure", "0", "force secure rcon authentication (1 = time based, 2 = challenge based); NOTE: changing rcon_secure clears rcon_password, so set rcon_secure always before rcon_password"};
 cvar_t rcon_secure_challengetimeout = {CVAR_CLIENT, "rcon_secure_challengetimeout", "5", "challenge-based secure rcon: time out requests if no challenge came within this time interval"};
 cvar_t rcon_address = {CVAR_CLIENT, "rcon_address", "", "server address to send rcon commands to (when not connected to a server)"};
+cvar_t name = {CVAR_CLIENT | CVAR_SAVE | CVAR_USERINFO, "name", "player", "change your player name"};
+cvar_t topcolor = {CVAR_CLIENT | CVAR_SAVE | CVAR_USERINFO, "topcolor", "0", "change the color of your shirt"};
+cvar_t bottomcolor = {CVAR_CLIENT | CVAR_SAVE | CVAR_USERINFO, "bottomcolor", "0", "change the color of your pants"};
 cvar_t team = {CVAR_CLIENT | CVAR_USERINFO | CVAR_SAVE, "team", "none", "QW team (4 character limit, example: blue)"};
 cvar_t skin = {CVAR_CLIENT | CVAR_USERINFO | CVAR_SAVE, "skin", "", "QW player skin name (example: base)"};
+cvar_t playermodel = {CVAR_CLIENT | CVAR_USERINFO | CVAR_SAVE, "playermodel", "", "current player model in Nexuiz/Xonotic"};
+cvar_t playerskin = {CVAR_CLIENT | CVAR_USERINFO | CVAR_SAVE, "playerskin", "", "current player skin in Nexuiz/Xonotic"};
 cvar_t noaim = {CVAR_CLIENT | CVAR_USERINFO | CVAR_SAVE, "noaim", "1", "QW option to disable vertical autoaim"};
+cvar_t pmodel = {CVAR_CLIENT | CVAR_USERINFO | CVAR_SAVE, "pmodel", "0", "current player model number in nehahra"};
 cvar_t r_fixtrans_auto = {CVAR_CLIENT, "r_fixtrans_auto", "0", "automatically fixtrans textures (when set to 2, it also saves the fixed versions to a fixtrans directory)"};
 
 //============================================================================
 
 /*
 ======================
-CL_Name_f
+SV_Name_f
 ======================
 */
-cvar_t cl_name = {CVAR_CLIENT | CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_name", "player", "internal storage cvar for current player name (changed by name command)"};
-static void CL_Name_f(cmd_state_t *cmd)
+static void SV_Name_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        int i, j;
@@ -61,13 +65,7 @@ static void CL_Name_f(cmd_state_t *cmd)
        char newName[sizeof(host_client->name)];
 
        if (Cmd_Argc (cmd) == 1)
-       {
-               if (cmd->source == src_command)
-               {
-                       Con_Printf("name: %s\n", cl_name.string);
-               }
                return;
-       }
 
        if (Cmd_Argc (cmd) == 2)
                newNameSource = Cmd_Argv(cmd, 1);
@@ -77,17 +75,9 @@ static void CL_Name_f(cmd_state_t *cmd)
        strlcpy(newName, newNameSource, sizeof(newName));
 
        if (cmd->source == src_command)
-       {
-               Cvar_Set (&cvars_all, "_cl_name", newName);
-               if (strlen(newNameSource) >= sizeof(newName)) // overflowed
-               {
-                       Con_Printf("Your name is longer than %i chars! It has been truncated.\n", (int) (sizeof(newName) - 1));
-                       Con_Printf("name: %s\n", cl_name.string);
-               }
                return;
-       }
 
-       if (host.realtime < host_client->nametime)
+       if (host.realtime < host_client->nametime && strcmp(newName, host_client->name))
        {
                SV_ClientPrintf("You can't change name more than once every %.1f seconds!\n", max(0.0f, sv_namechangetimer.value));
                return;
@@ -182,7 +172,6 @@ static void CL_Name_f(cmd_state_t *cmd)
 CL_Playermodel_f
 ======================
 */
-cvar_t cl_playermodel = {CVAR_CLIENT | CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_playermodel", "", "internal storage cvar for current player model in Nexuiz/Xonotic (changed by playermodel command)"};
 // the old cl_playermodel in cl_main has been renamed to __cl_playermodel
 static void CL_Playermodel_f(cmd_state_t *cmd)
 {
@@ -194,7 +183,7 @@ static void CL_Playermodel_f(cmd_state_t *cmd)
        {
                if (cmd->source == src_command)
                {
-                       Con_Printf("\"playermodel\" is \"%s\"\n", cl_playermodel.string);
+                       Con_Printf("\"playermodel\" is \"%s\"\n", playermodel.string);
                }
                return;
        }
@@ -243,7 +232,6 @@ static void CL_Playermodel_f(cmd_state_t *cmd)
 CL_Playerskin_f
 ======================
 */
-cvar_t cl_playerskin = {CVAR_CLIENT | CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_playerskin", "", "internal storage cvar for current player skin in Nexuiz/Xonotic (changed by playerskin command)"};
 static void CL_Playerskin_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
@@ -254,7 +242,7 @@ static void CL_Playerskin_f(cmd_state_t *cmd)
        {
                if (cmd->source == src_command)
                {
-                       Con_Printf("\"playerskin\" is \"%s\"\n", cl_playerskin.string);
+                       Con_Printf("\"playerskin\" is \"%s\"\n", playerskin.string);
                }
                return;
        }
@@ -305,16 +293,24 @@ static void CL_Playerskin_f(cmd_state_t *cmd)
 CL_Color_f
 ==================
 */
-cvar_t cl_color = {CVAR_CLIENT | CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_color", "0", "internal storage cvar for current player colors (changed by color command)"};
+cvar_t cl_color = {CVAR_READONLY | CVAR_CLIENT | CVAR_SAVE, "_cl_color", "0", "internal storage cvar for current player colors (changed by color command)"};
 static void CL_Color(cmd_state_t *cmd, int changetop, int changebottom)
 {
+       /*
+        * This is just a convenient way to change topcolor and bottomcolor
+        * We can't change cl_color from here directly because topcolor and
+        * bottomcolor may be changed separately and do not call this function.
+        * So it has to be changed when the userinfo strings are updated, which
+        * happens twice here. Perhaps find a cleaner way?
+        */
+
        prvm_prog_t *prog = SVVM_prog;
        int top, bottom, playercolor;
 
        // get top and bottom either from the provided values or the current values
        // (allows changing only top or bottom, or both at once)
-       top = changetop >= 0 ? changetop : (cl_color.integer >> 4);
-       bottom = changebottom >= 0 ? changebottom : cl_color.integer;
+       top = changetop >= 0 ? changetop : (topcolor.integer);
+       bottom = changebottom >= 0 ? changebottom : bottomcolor.integer;
 
        top &= 15;
        bottom &= 15;
@@ -328,7 +324,8 @@ static void CL_Color(cmd_state_t *cmd, int changetop, int changebottom)
 
        if (cmd->source == src_command)
        {
-               Cvar_SetValueQuick(&cl_color, playercolor);
+               Cvar_SetValueQuick(&topcolor, top);
+               Cvar_SetValueQuick(&bottomcolor, bottom);
                return;
        }
 
@@ -362,6 +359,29 @@ static void CL_Color(cmd_state_t *cmd, int changetop, int changebottom)
        }
 }
 
+// Ignore the callbacks so this two-to-three way synchronization doesn't cause an infinite loop.
+static void CL_Color_c(char *string)
+{
+       char vabuf[1024];
+       
+       Cvar_Set_NoCallback(&topcolor, va(vabuf, sizeof(vabuf), "%i", ((atoi(string) >> 4) & 15)));
+       Cvar_Set_NoCallback(&bottomcolor, va(vabuf, sizeof(vabuf), "%i", (atoi(string) & 15)));
+}
+
+static void CL_Topcolor_c(char *string)
+{
+       char vabuf[1024];
+       
+       Cvar_Set_NoCallback(&cl_color, va(vabuf, sizeof(vabuf), "%i", atoi(string)*16 + bottomcolor.integer));
+}
+
+static void CL_Bottomcolor_c(char *string)
+{
+       char vabuf[1024];
+
+       Cvar_Set_NoCallback(&cl_color, va(vabuf, sizeof(vabuf), "%i", topcolor.integer*16 + atoi(string)));
+}
+
 static void CL_Color_f(cmd_state_t *cmd)
 {
        int             top, bottom;
@@ -370,7 +390,7 @@ static void CL_Color_f(cmd_state_t *cmd)
        {
                if (cmd->source == src_command)
                {
-                       Con_Printf("\"color\" is \"%i %i\"\n", cl_color.integer >> 4, cl_color.integer & 15);
+                       Con_Printf("\"color\" is \"%i %i\"\n", topcolor.integer, bottomcolor.integer);
                        Con_Print("color <0-15> [0-15]\n");
                }
                return;
@@ -386,82 +406,29 @@ static void CL_Color_f(cmd_state_t *cmd)
        CL_Color(cmd, top, bottom);
 }
 
-static void CL_TopColor_f(cmd_state_t *cmd)
-{
-       if (Cmd_Argc(cmd) == 1)
-       {
-               if (cmd->source == src_command)
-               {
-                       Con_Printf("\"topcolor\" is \"%i\"\n", (cl_color.integer >> 4) & 15);
-                       Con_Print("topcolor <0-15>\n");
-               }
-               return;
-       }
-
-       CL_Color(cmd, atoi(Cmd_Argv(cmd, 1)), -1);
-}
-
-static void CL_BottomColor_f(cmd_state_t *cmd)
-{
-       if (Cmd_Argc(cmd) == 1)
-       {
-               if (cmd->source == src_command)
-               {
-                       Con_Printf("\"bottomcolor\" is \"%i\"\n", cl_color.integer & 15);
-                       Con_Print("bottomcolor <0-15>\n");
-               }
-               return;
-       }
-
-       CL_Color(cmd, -1, atoi(Cmd_Argv(cmd, 1)));
-}
-
-cvar_t cl_rate = {CVAR_CLIENT | CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_rate", "20000", "internal storage cvar for current rate (changed by rate command)"};
-cvar_t cl_rate_burstsize = {CVAR_CLIENT | CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_rate_burstsize", "1024", "internal storage cvar for current rate control burst size (changed by rate_burstsize command)"};
-static void CL_Rate_f(cmd_state_t *cmd)
+cvar_t rate = {CVAR_CLIENT | CVAR_SAVE | CVAR_USERINFO, "rate", "20000", "change your connection speed"};
+cvar_t rate_burstsize = {CVAR_CLIENT | CVAR_SAVE | CVAR_USERINFO, "rate_burstsize", "1024", "internal storage cvar for current rate control burst size (changed by rate_burstsize command)"};
+static void SV_Rate_f(cmd_state_t *cmd)
 {
        int rate;
 
-       if (Cmd_Argc(cmd) != 2)
-       {
-               if (cmd->source == src_command)
-               {
-                       Con_Printf("\"rate\" is \"%i\"\n", cl_rate.integer);
-                       Con_Print("rate <bytespersecond>\n");
-               }
-               return;
-       }
-
        rate = atoi(Cmd_Argv(cmd, 1));
 
        if (cmd->source == src_command)
-       {
-               Cvar_SetValue (&cvars_all, "_cl_rate", max(NET_MINRATE, rate));
                return;
-       }
 
        host_client->rate = rate;
 }
 
-static void CL_Rate_BurstSize_f(cmd_state_t *cmd)
+static void SV_Rate_BurstSize_f(cmd_state_t *cmd)
 {
        int rate_burstsize;
 
        if (Cmd_Argc(cmd) != 2)
-       {
-               Con_Printf("\"rate_burstsize\" is \"%i\"\n", cl_rate_burstsize.integer);
-               Con_Print("rate_burstsize <bytes>\n");
                return;
-       }
 
        rate_burstsize = atoi(Cmd_Argv(cmd, 1));
 
-       if (cmd->source == src_command)
-       {
-               Cvar_SetValue (&cvars_all, "_cl_rate_burstsize", rate_burstsize);
-               return;
-       }
-
        host_client->rate_burstsize = rate_burstsize;
 }
 
@@ -472,7 +439,6 @@ LadyHavoc: only supported for Nehahra, I personally think this is dumb, but Mind
 LadyHavoc: correction, Mindcrime will be removing pmodel in the future, but it's still stuck here for compatibility.
 ======================
 */
-cvar_t cl_pmodel = {CVAR_CLIENT | CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_pmodel", "0", "internal storage cvar for current player model number in nehahra (changed by pmodel command)"};
 static void CL_PModel_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
@@ -482,7 +448,7 @@ static void CL_PModel_f(cmd_state_t *cmd)
        {
                if (cmd->source == src_command)
                {
-                       Con_Printf("\"pmodel\" is \"%s\"\n", cl_pmodel.string);
+                       Con_Printf("\"pmodel\" is \"%s\"\n", pmodel.string);
                }
                return;
        }
@@ -490,7 +456,7 @@ static void CL_PModel_f(cmd_state_t *cmd)
 
        if (cmd->source == src_command)
        {
-               if (cl_pmodel.integer == i)
+               if (pmodel.integer == i)
                        return;
                Cvar_SetValue (&cvars_all, "_cl_pmodel", i);
                if (cls.state == ca_connected)
@@ -694,6 +660,15 @@ static void CL_Rcon_f(cmd_state_t *cmd) // credit: taken from QuakeWorld
        }
 }
 
+static void CL_RCon_ClearPassword_c(char *string)
+{
+       // whenever rcon_secure is changed to 0, clear rcon_password for
+       // security reasons (prevents a send-rcon-password-as-plaintext
+       // attack based on NQ protocol session takeover and svc_stufftext)
+       if(atoi(string) <= 0)
+               Cvar_SetQuick(&rcon_password, "");
+}
+
 /*
 ==================
 CL_FullServerinfo_f
@@ -897,29 +872,42 @@ void Host_InitCommands (void)
 {
        dpsnprintf(cls.userinfo, sizeof(cls.userinfo), "\\name\\player\\team\\none\\topcolor\\0\\bottomcolor\\0\\rate\\10000\\msg\\1\\noaim\\1\\*ver\\dp");
 
-       Cvar_RegisterVariable(&cl_name);
+       Cvar_RegisterVariable(&name);
+       Cvar_RegisterAlias(&name, "_cl_name");
        Cvar_RegisterVariable(&cl_color);
-       Cvar_RegisterVariable(&cl_rate);
-       Cvar_RegisterVariable(&cl_rate_burstsize);
-       Cvar_RegisterVariable(&cl_pmodel);
-       Cvar_RegisterVariable(&cl_playermodel);
-       Cvar_RegisterVariable(&cl_playerskin);
+       Cvar_RegisterCallback(&cl_color, CL_Color_c);
+       Cvar_RegisterVariable(&topcolor);
+       Cvar_RegisterCallback(&topcolor, CL_Topcolor_c);
+       Cvar_RegisterVariable(&bottomcolor);
+       Cvar_RegisterCallback(&bottomcolor, CL_Bottomcolor_c);
+       Cvar_RegisterVariable(&rate);
+       Cvar_RegisterAlias(&rate, "_cl_rate");
+       Cvar_RegisterVariable(&rate_burstsize);
+       Cvar_RegisterAlias(&rate_burstsize, "_cl_rate_burstsize");
+       Cvar_RegisterVariable(&pmodel);
+       Cvar_RegisterAlias(&pmodel, "_cl_pmodel");
+       Cvar_RegisterVariable(&playermodel);
+       Cvar_RegisterAlias(&playermodel, "_cl_playermodel");
+       Cvar_RegisterVariable(&playerskin);
+       Cvar_RegisterAlias(&playerskin, "_cl_playerskin");
        Cvar_RegisterVariable(&rcon_password);
        Cvar_RegisterVariable(&rcon_address);
        Cvar_RegisterVariable(&rcon_secure);
+       Cvar_RegisterCallback(&rcon_secure, CL_RCon_ClearPassword_c);
        Cvar_RegisterVariable(&rcon_secure_challengetimeout);
        Cvar_RegisterVariable(&r_fixtrans_auto);
        Cvar_RegisterVariable(&team);
        Cvar_RegisterVariable(&skin);
        Cvar_RegisterVariable(&noaim);
 
-       Cmd_AddCommand(CMD_CLIENT | CMD_SERVER_FROM_CLIENT, "name", CL_Name_f, "change your player name");
-       Cmd_AddCommand(CMD_CLIENT | CMD_SERVER_FROM_CLIENT, "color", CL_Color_f, "change your player shirt and pants colors");
-       Cmd_AddCommand(CMD_CLIENT | CMD_SERVER_FROM_CLIENT, "rate", CL_Rate_f, "change your network connection speed");
-       Cmd_AddCommand(CMD_CLIENT | CMD_SERVER_FROM_CLIENT, "rate_burstsize", CL_Rate_BurstSize_f, "change your network connection speed");
-       Cmd_AddCommand(CMD_CLIENT | CMD_SERVER_FROM_CLIENT, "pmodel", CL_PModel_f, "(Nehahra-only) change your player model choice");
-       Cmd_AddCommand(CMD_CLIENT | CMD_SERVER_FROM_CLIENT, "playermodel", CL_Playermodel_f, "change your player model");
-       Cmd_AddCommand(CMD_CLIENT | CMD_SERVER_FROM_CLIENT, "playerskin", CL_Playerskin_f, "change your player skin number");
+       Cmd_AddCommand(CMD_USERINFO, "name", SV_Name_f, "change your player name");
+       Cmd_AddCommand(CMD_CLIENT, "color", CL_Color_f, "change your player shirt and pants colors");
+       Cmd_AddCommand(CMD_USERINFO, "color", CL_Color_f, "change your player shirt and pants colors");
+       Cmd_AddCommand(CMD_USERINFO, "rate", SV_Rate_f, "change your network connection speed");
+       Cmd_AddCommand(CMD_USERINFO, "rate_burstsize", SV_Rate_BurstSize_f, "change your network connection speed");
+       Cmd_AddCommand(CMD_USERINFO, "pmodel", CL_PModel_f, "(Nehahra-only) change your player model choice");
+       Cmd_AddCommand(CMD_USERINFO, "playermodel", CL_Playermodel_f, "change your player model");
+       Cmd_AddCommand(CMD_USERINFO, "playerskin", CL_Playerskin_f, "change your player skin number");
 
        Cmd_AddCommand(CMD_CLIENT, "sendcvar", CL_SendCvar_f, "sends the value of a cvar to the server as a sentcvar command, for use by QuakeC");
        Cmd_AddCommand(CMD_CLIENT, "rcon", CL_Rcon_f, "sends a command to the server console (if your rcon_password matches the server's rcon_password), or to the address specified by rcon_address when not connected (again rcon_password must match the server's); note: if rcon_secure is set, client and server clocks must be synced e.g. via NTP");
@@ -927,9 +915,7 @@ void Host_InitCommands (void)
        Cmd_AddCommand(CMD_CLIENT, "pqrcon", CL_PQRcon_f, "sends a command to a proquake server console (if your rcon_password matches the server's rcon_password), or to the address specified by rcon_address when not connected (again rcon_password must match the server's)");
        Cmd_AddCommand(CMD_CLIENT, "fullinfo", CL_FullInfo_f, "allows client to modify their userinfo");
        Cmd_AddCommand(CMD_CLIENT, "setinfo", CL_SetInfo_f, "modifies your userinfo");
-       Cmd_AddCommand(CMD_CLIENT | CMD_CLIENT_FROM_SERVER, "packet", CL_Packet_f, "send a packet to the specified address:port containing a text string");
-       Cmd_AddCommand(CMD_CLIENT | CMD_CLIENT_FROM_SERVER, "topcolor", CL_TopColor_f, "QW command to set top color without changing bottom color");
-       Cmd_AddCommand(CMD_CLIENT, "bottomcolor", CL_BottomColor_f, "QW command to set bottom color without changing top color");
+       Cmd_AddCommand(CMD_CLIENT, "packet", CL_Packet_f, "send a packet to the specified address:port containing a text string");
        Cmd_AddCommand(CMD_CLIENT, "fixtrans", Image_FixTransparentPixels_f, "change alpha-zero pixels in an image file to sensible values, and write out a new TGA (warning: SLOW)");
 
        // commands that are only sent by server to client for execution
diff --git a/menu.c b/menu.c
index 141d9e2..5cad78b 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -1284,15 +1284,18 @@ static int              setup_oldrate;
 
 #define        NUM_SETUP_CMDS  5
 
+extern cvar_t topcolor;
+extern cvar_t bottomcolor;
+
 void M_Menu_Setup_f(cmd_state_t *cmd)
 {
        key_dest = key_menu;
        m_state = m_setup;
        m_entersound = true;
-       strlcpy(setup_myname, cl_name.string, sizeof(setup_myname));
-       setup_top = setup_oldtop = cl_color.integer >> 4;
-       setup_bottom = setup_oldbottom = cl_color.integer & 15;
-       setup_rate = cl_rate.integer;
+       strlcpy(setup_myname, name.string, sizeof(setup_myname));
+       setup_top = setup_oldtop = topcolor.integer;
+       setup_bottom = setup_oldbottom = bottomcolor.integer;
+       setup_rate = rate.integer;
 }
 
 static int menuplyr_width, menuplyr_height, menuplyr_top, menuplyr_bottom, menuplyr_load;
@@ -1493,7 +1496,7 @@ forward:
                        goto forward;
 
                // setup_cursor == 4 (Accept changes)
-               if (strcmp(cl_name.string, setup_myname) != 0)
+               if (strcmp(name.string, setup_myname) != 0)
                        Cbuf_AddText(cmd, va(vabuf, sizeof(vabuf), "name \"%s\"\n", setup_myname) );
                if (setup_top != setup_oldtop || setup_bottom != setup_oldbottom)
                        Cbuf_AddText(cmd, va(vabuf, sizeof(vabuf), "color %i %i\n", setup_top, setup_bottom) );
index eb61cfe..e4b34ca 100755 (executable)
--- a/netconn.c
+++ b/netconn.c
@@ -93,7 +93,7 @@ static cvar_t net_slist_queriesperframe = {CVAR_CLIENT, "net_slist_queriesperfra
 static cvar_t net_slist_timeout = {CVAR_CLIENT, "net_slist_timeout", "4", "how long to listen for a server information response before giving up"};
 static cvar_t net_slist_pause = {CVAR_CLIENT, "net_slist_pause", "0", "when set to 1, the server list won't update until it is set back to 0"};
 static cvar_t net_slist_maxtries = {CVAR_CLIENT, "net_slist_maxtries", "3", "how many times to ask the same server for information (more times gives better ping reports but takes longer)"};
-static cvar_t net_slist_favorites = {CVAR_CLIENT | CVAR_SAVE | CVAR_NQUSERINFOHACK, "net_slist_favorites", "", "contains a list of IP addresses and ports to always query explicitly"};
+static cvar_t net_slist_favorites = {CVAR_CLIENT | CVAR_SAVE, "net_slist_favorites", "", "contains a list of IP addresses and ports to always query explicitly"};
 static cvar_t net_tos_dscp = {CVAR_CLIENT | CVAR_SAVE, "net_tos_dscp", "32", "DiffServ Codepoint for network sockets (may need game restart to apply)"};
 static cvar_t gameversion = {CVAR_SERVER, "gameversion", "0", "version of game data (mod-specific) to be sent to querying clients"};
 static cvar_t gameversion_min = {CVAR_CLIENT | CVAR_SERVER, "gameversion_min", "-1", "minimum version of game data (mod-specific), when client and server gameversion mismatch in the server browser the server is shown as incompatible; if -1, gameversion is used alone"};
@@ -166,12 +166,12 @@ static lhnetaddress_t favorites[MAX_FAVORITESERVERS];
 static int nFavorites_idfp = 0;
 static char favorites_idfp[MAX_FAVORITESERVERS][FP64_SIZE+1];
 
-void NetConn_UpdateFavorites(void)
+void NetConn_UpdateFavorites_c(char *string)
 {
        const char *p;
        nFavorites = 0;
        nFavorites_idfp = 0;
-       p = net_slist_favorites.string;
+       p = string;
        while((size_t) nFavorites < sizeof(favorites) / sizeof(*favorites) && COM_ParseToken_Console(&p))
        {
                if(com_token[0] != '[' && strlen(com_token) == FP64_SIZE && !strchr(com_token, '.'))
@@ -1265,7 +1265,7 @@ static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, s
                conn->incoming_netgraph[conn->incoming_packetcounter].unreliablebytes = originallength + 28;
                conn->incoming_netgraph[conn->incoming_packetcounter].reliablebytes   = NETGRAPH_NOPACKET;
                conn->incoming_netgraph[conn->incoming_packetcounter].ackbytes        = NETGRAPH_NOPACKET;
-               NetConn_UpdateCleartime(&conn->incoming_cleartime, cl_rate.integer, cl_rate_burstsize.integer, originallength + 28);
+               NetConn_UpdateCleartime(&conn->incoming_cleartime, rate.integer, rate_burstsize.integer, originallength + 28);
 
                // limit bursts to one packet in size ("dialup mode" emulating old behaviour)
                if (net_test.integer)
@@ -1361,7 +1361,7 @@ static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, s
                                        conn->incoming_netgraph[conn->incoming_packetcounter].unreliablebytes = originallength + 28;
                                        conn->incoming_netgraph[conn->incoming_packetcounter].reliablebytes   = NETGRAPH_NOPACKET;
                                        conn->incoming_netgraph[conn->incoming_packetcounter].ackbytes        = NETGRAPH_NOPACKET;
-                                       NetConn_UpdateCleartime(&conn->incoming_cleartime, cl_rate.integer, cl_rate_burstsize.integer, originallength + 28);
+                                       NetConn_UpdateCleartime(&conn->incoming_cleartime, rate.integer, rate_burstsize.integer, originallength + 28);
 
                                        conn->nq.unreliableReceiveSequence = sequence + 1;
                                        conn->lastMessageTime = host.realtime;
@@ -1391,7 +1391,7 @@ static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, s
                        else if (flags & NETFLAG_ACK)
                        {
                                conn->incoming_netgraph[conn->incoming_packetcounter].ackbytes += originallength + 28;
-                               NetConn_UpdateCleartime(&conn->incoming_cleartime, cl_rate.integer, cl_rate_burstsize.integer, originallength + 28);
+                               NetConn_UpdateCleartime(&conn->incoming_cleartime, rate.integer, rate_burstsize.integer, originallength + 28);
 
                                if (sequence == (conn->nq.sendSequence - 1))
                                {
@@ -1451,7 +1451,7 @@ static int NetConn_ReceivedMessage(netconn_t *conn, const unsigned char *data, s
                        {
                                unsigned char temppacket[8];
                                conn->incoming_netgraph[conn->incoming_packetcounter].reliablebytes   += originallength + 28;
-                               NetConn_UpdateCleartime(&conn->incoming_cleartime, cl_rate.integer, cl_rate_burstsize.integer, originallength + 28);
+                               NetConn_UpdateCleartime(&conn->incoming_cleartime, rate.integer, rate_burstsize.integer, originallength + 28);
 
                                conn->outgoing_netgraph[conn->outgoing_packetcounter].ackbytes        += 8 + 28;
 
@@ -3889,6 +3889,7 @@ void NetConn_Init(void)
        Cvar_RegisterVariable(&net_slist_timeout);
        Cvar_RegisterVariable(&net_slist_maxtries);
        Cvar_RegisterVariable(&net_slist_favorites);
+       Cvar_RegisterCallback(&net_slist_favorites, NetConn_UpdateFavorites_c);
        Cvar_RegisterVariable(&net_slist_pause);
        if(LHNET_DefaultDSCP(-1) >= 0) // register cvar only if supported
                Cvar_RegisterVariable(&net_tos_dscp);
index 7120c53..9e568af 100755 (executable)
--- a/netconn.h
+++ b/netconn.h
@@ -470,7 +470,7 @@ void ServerList_ResetMasks(void);
 void ServerList_QueryList(qboolean resetcache, qboolean querydp, qboolean queryqw, qboolean consoleoutput);
 
 /// called whenever net_slist_favorites changes
-void NetConn_UpdateFavorites(void);
+void NetConn_UpdateFavorites_c(char *string);
 #endif
 
 #define MAX_CHALLENGES 128
index 84340c9..2ed5540 100644 (file)
@@ -988,7 +988,7 @@ static void SV_Kick_f(cmd_state_t *cmd)
                        if (cls.state == ca_dedicated)
                                who = "Console";
                        else
-                               who = cl_name.string;
+                               who = name.string;
                }
                else
                        who = save->name;
@@ -1199,7 +1199,7 @@ void SV_InitOperatorCommands(void)
        Cvar_RegisterVariable(&sv_namechangetimer);
        
        Cmd_AddCommand(CMD_SERVER | CMD_SERVER_FROM_CLIENT, "status", SV_Status_f, "print server status information");
-       Cmd_AddCommand(CMD_SHARED | CMD_INITWAIT, "map", SV_Map_f, "kick everyone off the server and start a new level");
+       Cmd_AddCommand(CMD_SHARED, "map", SV_Map_f, "kick everyone off the server and start a new level");
        Cmd_AddCommand(CMD_SHARED, "restart", SV_Restart_f, "restart current level");
        Cmd_AddCommand(CMD_SHARED, "changelevel", SV_Changelevel_f, "change to another level, bringing along all connected clients");
        Cmd_AddCommand(CMD_SHARED | CMD_SERVER_FROM_CLIENT, "say", SV_Say_f, "send a chat message to everyone on the server");
@@ -1208,7 +1208,7 @@ void SV_InitOperatorCommands(void)
        Cmd_AddCommand(CMD_SERVER | CMD_SERVER_FROM_CLIENT, "pause", SV_Pause_f, "pause the game (if the server allows pausing)");
        Cmd_AddCommand(CMD_SHARED, "kick", SV_Kick_f, "kick a player off the server by number or name");
        Cmd_AddCommand(CMD_SHARED | CMD_SERVER_FROM_CLIENT, "ping", SV_Ping_f, "print ping times of all players on the server");
-       Cmd_AddCommand(CMD_SHARED | CMD_INITWAIT, "load", SV_Loadgame_f, "load a saved game file");
+       Cmd_AddCommand(CMD_SHARED, "load", SV_Loadgame_f, "load a saved game file");
        Cmd_AddCommand(CMD_SHARED, "save", SV_Savegame_f, "save the game to a file");
        Cmd_AddCommand(CMD_SHARED, "viewmodel", SV_Viewmodel_f, "change model of viewthing entity in current level");
        Cmd_AddCommand(CMD_SHARED, "viewframe", SV_Viewframe_f, "change animation frame of viewthing entity in current level");