Split the global cmd interpreter into 4 separate ones for specific uses (client conso...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 21 Jan 2020 08:36:34 +0000 (08:36 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 21 Jan 2020 08:36:34 +0000 (08:36 +0000)
This also hides some network protocol implementation details from the console command interpreter, and makes the command list a lot shorter in dedicated servers.

Changed Cbuf_LockThreadMutex/Cbuf_UnlockThreadMutex to Cbuf_Lock/Cbuf_Unlock and they now use a spinlock internally.

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

59 files changed:
cd_shared.c
cl_demo.c
cl_input.c
cl_main.c
cl_parse.c
cl_particles.c
cl_screen.c
cl_video.c
client.h
clvm_cmds.c
cmd.c
cmd.h
console.c
console.h
crypto.c
csprogs.c
cvar.c
cvar.h
fs.c
gl_backend.c
gl_draw.c
gl_rmain.c
gl_rsurf.c
gl_textures.c
host.c
host_cmd.c
image.c
image.h
keys.c
keys.h
libcurl.c
menu.c
model_shared.c
mvm_cmds.c
netconn.c
netconn.h
progsvm.h
prvm_cmds.c
prvm_cmds.h
prvm_edict.c
prvm_exec.c
quakedef.h
r_modules.c
r_modules.h
r_shadow.c
r_sky.c
render.h
sbar.c
snd_main.c
sound.h
sv_main.c
sv_user.c
svvm_cmds.c
sys_shared.c
vid.h
vid_sdl.c
vid_shared.c
view.c
zone.c

index c618c50..fdeff89 100644 (file)
@@ -264,7 +264,7 @@ void CDAudio_Resume (void)
        cdPlaying = true;
 }
 
-static void CD_f (void)
+static void CD_f(cmd_state_t *cmd)
 {
        const char *command;
 #ifdef MAXTRACKS
@@ -272,7 +272,7 @@ static void CD_f (void)
        int n;
 #endif
 
-       command = Cmd_Argv (1);
+       command = Cmd_Argv(cmd, 1);
 
        if (strcasecmp(command, "remap") != 0)
                Host_StartVideo();
@@ -312,7 +312,7 @@ static void CD_f (void)
        if (strcasecmp(command, "remap") == 0)
        {
 #ifdef MAXTRACKS
-               ret = Cmd_Argc() - 2;
+               ret = Cmd_Argc(cmd) - 2;
                if (ret <= 0)
                {
                        for (n = 1; n < MAXTRACKS; n++)
@@ -321,7 +321,7 @@ static void CD_f (void)
                        return;
                }
                for (n = 1; n <= ret; n++)
-                       strlcpy(remap[n], Cmd_Argv (n+1), sizeof(*remap));
+                       strlcpy(remap[n], Cmd_Argv(cmd, n+1), sizeof(*remap));
 #endif
                return;
        }
@@ -336,7 +336,7 @@ static void CD_f (void)
        {
                if (music_playlist_index.integer >= 0)
                        return;
-               CDAudio_Play_byName(Cmd_Argv (2), false, true, (Cmd_Argc() > 3) ? atof( Cmd_Argv(3) ) : 0);
+               CDAudio_Play_byName(Cmd_Argv(cmd, 2), false, true, (Cmd_Argc(cmd) > 3) ? atof( Cmd_Argv(cmd, 3) ) : 0);
                return;
        }
 
@@ -344,7 +344,7 @@ static void CD_f (void)
        {
                if (music_playlist_index.integer >= 0)
                        return;
-               CDAudio_Play_byName(Cmd_Argv (2), true, true, (Cmd_Argc() > 3) ? atof( Cmd_Argv(3) ) : 0);
+               CDAudio_Play_byName(Cmd_Argv(cmd, 2), true, true, (Cmd_Argc(cmd) > 3) ? atof( Cmd_Argv(cmd, 3) ) : 0);
                return;
        }
 
@@ -570,7 +570,8 @@ int CDAudio_Init (void)
                Cvar_RegisterVariable(&music_playlist_sampleposition[i]);
        }
 
-       Cmd_AddCommand("cd", CD_f, "execute a CD drive command (cd on/off/reset/remap/close/play/loop/stop/pause/resume/eject/info) - use cd by itself for usage");
+       Cmd_AddCommand(&cmd_client, "cd", CD_f, "execute a CD drive command (cd on/off/reset/remap/close/play/loop/stop/pause/resume/eject/info) - use cd by itself for usage");
+       Cmd_AddCommand(&cmd_clientfromserver, "cd", CD_f, "execute a CD drive command (cd on/off/reset/remap/close/play/loop/stop/pause/resume/eject/info) - use cd by itself for usage");
 
        return 0;
 }
index 595cad5..035f6f8 100644 (file)
--- a/cl_demo.c
+++ b/cl_demo.c
@@ -67,7 +67,7 @@ void CL_NextDemo (void)
        }
 
        dpsnprintf (str, sizeof(str), "playdemo %s\n", cls.demos[cls.demonum]);
-       Cbuf_InsertText (str);
+       Cbuf_InsertText(&cmd_client, str);
        cls.demonum++;
 }
 
@@ -98,7 +98,7 @@ void CL_StopPlayback (void)
 
        if (!cls.demostarting) // only quit if not starting another demo
                if (COM_CheckParm("-demo") || COM_CheckParm("-capturedemo"))
-                       Host_Quit_f();
+                       Host_Quit_f(&cmd_client);
 
 }
 
@@ -275,7 +275,7 @@ void CL_ReadDemoMessage(void)
                        CL_ParseServerMessage();
 
                        if (cls.signon != SIGNONS)
-                               Cbuf_Execute(); // immediately execute svc_stufftext if in the demo before connect!
+                               Cbuf_Execute(&cmd_client); // immediately execute svc_stufftext if in the demo before connect!
 
                        // In case the demo contains a "svc_disconnect" message
                        if (!cls.demoplayback)
@@ -300,7 +300,7 @@ CL_Stop_f
 stop recording a demo
 ====================
 */
-void CL_Stop_f (void)
+void CL_Stop_f(cmd_state_t *cmd)
 {
        sizebuf_t buf;
        unsigned char bufdata[64];
@@ -339,20 +339,20 @@ CL_Record_f
 record <demoname> <map> [cd track]
 ====================
 */
-void CL_Record_f (void)
+void CL_Record_f(cmd_state_t *cmd)
 {
        int c, track;
        char name[MAX_OSPATH];
        char vabuf[1024];
 
-       c = Cmd_Argc();
+       c = Cmd_Argc(cmd);
        if (c != 2 && c != 3 && c != 4)
        {
                Con_Print("record <demoname> [<map> [cd track]]\n");
                return;
        }
 
-       if (strstr(Cmd_Argv(1), ".."))
+       if (strstr(Cmd_Argv(cmd, 1), ".."))
        {
                Con_Print("Relative pathnames are not allowed.\n");
                return;
@@ -370,19 +370,19 @@ void CL_Record_f (void)
        // write the forced cd track number, or -1
        if (c == 4)
        {
-               track = atoi(Cmd_Argv(3));
+               track = atoi(Cmd_Argv(cmd, 3));
                Con_Printf("Forcing CD track to %i\n", cls.forcetrack);
        }
        else
                track = -1;
 
        // get the demo name
-       strlcpy (name, Cmd_Argv(1), sizeof (name));
+       strlcpy (name, Cmd_Argv(cmd, 1), sizeof (name));
        FS_DefaultExtension (name, ".dem", sizeof (name));
 
        // start the map up
        if (c > 2)
-               Cmd_ExecuteString ( va(vabuf, sizeof(vabuf), "map %s", Cmd_Argv(2)), src_command, false);
+               Cmd_ExecuteString ( cmd, va(vabuf, sizeof(vabuf), "map %s", Cmd_Argv(cmd, 2)), src_command, false);
 
        // open the demo file
        Con_Printf("recording to %s.\n", name);
@@ -410,21 +410,21 @@ CL_PlayDemo_f
 play [demoname]
 ====================
 */
-void CL_PlayDemo_f (void)
+void CL_PlayDemo_f(cmd_state_t *cmd)
 {
        char    name[MAX_QPATH];
        int c;
        qboolean neg = false;
        qfile_t *f;
 
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
                Con_Print("play <demoname> : plays a demo\n");
                return;
        }
 
        // open the demo file
-       strlcpy (name, Cmd_Argv(1), sizeof (name));
+       strlcpy (name, Cmd_Argv(cmd, 1), sizeof (name));
        FS_DefaultExtension (name, ".dem", sizeof (name));
        f = FS_OpenVirtualFile(name, false);
        if (!f)
@@ -530,7 +530,7 @@ static void CL_FinishTimeDemo (void)
                        if(atoi(com_argv[i + 1]) > benchmark_runs)
                        {
                                // restart the benchmark
-                               Cbuf_AddText(va(vabuf, sizeof(vabuf), "timedemo %s\n", cls.demoname));
+                               Cbuf_AddText(&cmd_client, va(vabuf, sizeof(vabuf), "timedemo %s\n", cls.demoname));
                                // cannot execute here
                        }
                        else
@@ -579,11 +579,11 @@ static void CL_FinishTimeDemo (void)
                                }
                                Z_Free(history);
                                history = NULL;
-                               Host_Quit_f();
+                               Host_Quit_f(&cmd_client);
                        }
                }
                else
-                       Host_Quit_f();
+                       Host_Quit_f(&cmd_client);
        }
 }
 
@@ -594,9 +594,9 @@ CL_TimeDemo_f
 timedemo [demoname]
 ====================
 */
-void CL_TimeDemo_f (void)
+void CL_TimeDemo_f(cmd_state_t *cmd)
 {
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
                Con_Print("timedemo <demoname> : gets demo speeds\n");
                return;
@@ -604,7 +604,7 @@ void CL_TimeDemo_f (void)
 
        srand(0); // predictable random sequence for benchmarking
 
-       CL_PlayDemo_f ();
+       CL_PlayDemo_f (cmd);
 
 // cls.td_starttime will be grabbed at the second frame of the demo, so
 // all the loading time doesn't get counted
index e0c5514..743990c 100644 (file)
@@ -62,12 +62,12 @@ int                 in_impulse;
 
 
 
-static void KeyDown (kbutton_t *b)
+static void KeyDown (cmd_state_t *cmd, kbutton_t *b)
 {
        int k;
        const char *c;
 
-       c = Cmd_Argv(1);
+       c = Cmd_Argv(cmd, 1);
        if (c[0])
                k = atoi(c);
        else
@@ -91,12 +91,12 @@ static void KeyDown (kbutton_t *b)
        b->state |= 1 + 2;      // down + impulse down
 }
 
-static void KeyUp (kbutton_t *b)
+static void KeyUp (cmd_state_t *cmd, kbutton_t *b)
 {
        int k;
        const char *c;
 
-       c = Cmd_Argv(1);
+       c = Cmd_Argv(cmd, 1);
        if (c[0])
                k = atoi(c);
        else
@@ -121,82 +121,82 @@ static void KeyUp (kbutton_t *b)
        b->state |= 4;          // impulse up
 }
 
-static void IN_KLookDown (void) {KeyDown(&in_klook);}
-static void IN_KLookUp (void) {KeyUp(&in_klook);}
-static void IN_MLookDown (void) {KeyDown(&in_mlook);}
-static void IN_MLookUp (void)
+static void IN_KLookDown(cmd_state_t *cmd) {KeyDown(cmd, &in_klook);}
+static void IN_KLookUp(cmd_state_t *cmd) {KeyUp(cmd, &in_klook);}
+static void IN_MLookDown(cmd_state_t *cmd) {KeyDown(cmd, &in_mlook);}
+static void IN_MLookUp(cmd_state_t *cmd)
 {
-       KeyUp(&in_mlook);
+       KeyUp(cmd, &in_mlook);
        if ( !(in_mlook.state&1) && lookspring.value)
-               V_StartPitchDrift();
+               V_StartPitchDrift_f(cmd);
 }
-static void IN_UpDown(void) {KeyDown(&in_up);}
-static void IN_UpUp(void) {KeyUp(&in_up);}
-static void IN_DownDown(void) {KeyDown(&in_down);}
-static void IN_DownUp(void) {KeyUp(&in_down);}
-static void IN_LeftDown(void) {KeyDown(&in_left);}
-static void IN_LeftUp(void) {KeyUp(&in_left);}
-static void IN_RightDown(void) {KeyDown(&in_right);}
-static void IN_RightUp(void) {KeyUp(&in_right);}
-static void IN_ForwardDown(void) {KeyDown(&in_forward);}
-static void IN_ForwardUp(void) {KeyUp(&in_forward);}
-static void IN_BackDown(void) {KeyDown(&in_back);}
-static void IN_BackUp(void) {KeyUp(&in_back);}
-static void IN_LookupDown(void) {KeyDown(&in_lookup);}
-static void IN_LookupUp(void) {KeyUp(&in_lookup);}
-static void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
-static void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
-static void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
-static void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
-static void IN_MoverightDown(void) {KeyDown(&in_moveright);}
-static void IN_MoverightUp(void) {KeyUp(&in_moveright);}
-
-static void IN_SpeedDown(void) {KeyDown(&in_speed);}
-static void IN_SpeedUp(void) {KeyUp(&in_speed);}
-static void IN_StrafeDown(void) {KeyDown(&in_strafe);}
-static void IN_StrafeUp(void) {KeyUp(&in_strafe);}
-
-static void IN_AttackDown(void) {KeyDown(&in_attack);}
-static void IN_AttackUp(void) {KeyUp(&in_attack);}
-
-static void IN_UseDown(void) {KeyDown(&in_use);}
-static void IN_UseUp(void) {KeyUp(&in_use);}
+static void IN_UpDown(cmd_state_t *cmd) {KeyDown(cmd, &in_up);}
+static void IN_UpUp(cmd_state_t *cmd) {KeyUp(cmd, &in_up);}
+static void IN_DownDown(cmd_state_t *cmd) {KeyDown(cmd, &in_down);}
+static void IN_DownUp(cmd_state_t *cmd) {KeyUp(cmd, &in_down);}
+static void IN_LeftDown(cmd_state_t *cmd) {KeyDown(cmd, &in_left);}
+static void IN_LeftUp(cmd_state_t *cmd) {KeyUp(cmd, &in_left);}
+static void IN_RightDown(cmd_state_t *cmd) {KeyDown(cmd, &in_right);}
+static void IN_RightUp(cmd_state_t *cmd) {KeyUp(cmd, &in_right);}
+static void IN_ForwardDown(cmd_state_t *cmd) {KeyDown(cmd, &in_forward);}
+static void IN_ForwardUp(cmd_state_t *cmd) {KeyUp(cmd, &in_forward);}
+static void IN_BackDown(cmd_state_t *cmd) {KeyDown(cmd, &in_back);}
+static void IN_BackUp(cmd_state_t *cmd) {KeyUp(cmd, &in_back);}
+static void IN_LookupDown(cmd_state_t *cmd) {KeyDown(cmd, &in_lookup);}
+static void IN_LookupUp(cmd_state_t *cmd) {KeyUp(cmd, &in_lookup);}
+static void IN_LookdownDown(cmd_state_t *cmd) {KeyDown(cmd, &in_lookdown);}
+static void IN_LookdownUp(cmd_state_t *cmd) {KeyUp(cmd, &in_lookdown);}
+static void IN_MoveleftDown(cmd_state_t *cmd) {KeyDown(cmd, &in_moveleft);}
+static void IN_MoveleftUp(cmd_state_t *cmd) {KeyUp(cmd, &in_moveleft);}
+static void IN_MoverightDown(cmd_state_t *cmd) {KeyDown(cmd, &in_moveright);}
+static void IN_MoverightUp(cmd_state_t *cmd) {KeyUp(cmd, &in_moveright);}
+
+static void IN_SpeedDown(cmd_state_t *cmd) {KeyDown(cmd, &in_speed);}
+static void IN_SpeedUp(cmd_state_t *cmd) {KeyUp(cmd, &in_speed);}
+static void IN_StrafeDown(cmd_state_t *cmd) {KeyDown(cmd, &in_strafe);}
+static void IN_StrafeUp(cmd_state_t *cmd) {KeyUp(cmd, &in_strafe);}
+
+static void IN_AttackDown(cmd_state_t *cmd) {KeyDown(cmd, &in_attack);}
+static void IN_AttackUp(cmd_state_t *cmd) {KeyUp(cmd, &in_attack);}
+
+static void IN_UseDown(cmd_state_t *cmd) {KeyDown(cmd, &in_use);}
+static void IN_UseUp(cmd_state_t *cmd) {KeyUp(cmd, &in_use);}
 
 // LadyHavoc: added 6 new buttons
-static void IN_Button3Down(void) {KeyDown(&in_button3);}
-static void IN_Button3Up(void) {KeyUp(&in_button3);}
-static void IN_Button4Down(void) {KeyDown(&in_button4);}
-static void IN_Button4Up(void) {KeyUp(&in_button4);}
-static void IN_Button5Down(void) {KeyDown(&in_button5);}
-static void IN_Button5Up(void) {KeyUp(&in_button5);}
-static void IN_Button6Down(void) {KeyDown(&in_button6);}
-static void IN_Button6Up(void) {KeyUp(&in_button6);}
-static void IN_Button7Down(void) {KeyDown(&in_button7);}
-static void IN_Button7Up(void) {KeyUp(&in_button7);}
-static void IN_Button8Down(void) {KeyDown(&in_button8);}
-static void IN_Button8Up(void) {KeyUp(&in_button8);}
-
-static void IN_Button9Down(void) {KeyDown(&in_button9);}
-static void IN_Button9Up(void) {KeyUp(&in_button9);}
-static void IN_Button10Down(void) {KeyDown(&in_button10);}
-static void IN_Button10Up(void) {KeyUp(&in_button10);}
-static void IN_Button11Down(void) {KeyDown(&in_button11);}
-static void IN_Button11Up(void) {KeyUp(&in_button11);}
-static void IN_Button12Down(void) {KeyDown(&in_button12);}
-static void IN_Button12Up(void) {KeyUp(&in_button12);}
-static void IN_Button13Down(void) {KeyDown(&in_button13);}
-static void IN_Button13Up(void) {KeyUp(&in_button13);}
-static void IN_Button14Down(void) {KeyDown(&in_button14);}
-static void IN_Button14Up(void) {KeyUp(&in_button14);}
-static void IN_Button15Down(void) {KeyDown(&in_button15);}
-static void IN_Button15Up(void) {KeyUp(&in_button15);}
-static void IN_Button16Down(void) {KeyDown(&in_button16);}
-static void IN_Button16Up(void) {KeyUp(&in_button16);}
-
-static void IN_JumpDown (void) {KeyDown(&in_jump);}
-static void IN_JumpUp (void) {KeyUp(&in_jump);}
-
-static void IN_Impulse (void) {in_impulse=atoi(Cmd_Argv(1));}
+static void IN_Button3Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button3);}
+static void IN_Button3Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button3);}
+static void IN_Button4Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button4);}
+static void IN_Button4Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button4);}
+static void IN_Button5Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button5);}
+static void IN_Button5Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button5);}
+static void IN_Button6Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button6);}
+static void IN_Button6Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button6);}
+static void IN_Button7Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button7);}
+static void IN_Button7Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button7);}
+static void IN_Button8Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button8);}
+static void IN_Button8Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button8);}
+
+static void IN_Button9Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button9);}
+static void IN_Button9Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button9);}
+static void IN_Button10Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button10);}
+static void IN_Button10Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button10);}
+static void IN_Button11Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button11);}
+static void IN_Button11Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button11);}
+static void IN_Button12Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button12);}
+static void IN_Button12Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button12);}
+static void IN_Button13Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button13);}
+static void IN_Button13Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button13);}
+static void IN_Button14Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button14);}
+static void IN_Button14Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button14);}
+static void IN_Button15Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button15);}
+static void IN_Button15Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button15);}
+static void IN_Button16Down(cmd_state_t *cmd) {KeyDown(cmd, &in_button16);}
+static void IN_Button16Up(cmd_state_t *cmd) {KeyUp(cmd, &in_button16);}
+
+static void IN_JumpDown(cmd_state_t *cmd) {KeyDown(cmd, &in_jump);}
+static void IN_JumpUp(cmd_state_t *cmd) {KeyUp(cmd, &in_jump);}
+
+static void IN_Impulse(cmd_state_t *cmd) {in_impulse=atoi(Cmd_Argv(cmd, 1));}
 
 in_bestweapon_info_t in_bestweapon_info[IN_BESTWEAPON_MAX];
 
@@ -241,45 +241,45 @@ void IN_BestWeapon_ResetData (void)
        IN_BestWeapon_Register("h", 226, HIT_MJOLNIR, HIT_MJOLNIR, STAT_CELLS, 0); // hipnotic mjolnir hammer
 }
 
-static void IN_BestWeapon_Register_f (void)
+static void IN_BestWeapon_Register_f(cmd_state_t *cmd)
 {
-       if(Cmd_Argc() == 7)
+       if(Cmd_Argc(cmd) == 7)
        {
                IN_BestWeapon_Register(
-                       Cmd_Argv(1),
-                       atoi(Cmd_Argv(2)),
-                       atoi(Cmd_Argv(3)),
-                       atoi(Cmd_Argv(4)),
-                       atoi(Cmd_Argv(5)),
-                       atoi(Cmd_Argv(6))
+                       Cmd_Argv(cmd, 1),
+                       atoi(Cmd_Argv(cmd, 2)),
+                       atoi(Cmd_Argv(cmd, 3)),
+                       atoi(Cmd_Argv(cmd, 4)),
+                       atoi(Cmd_Argv(cmd, 5)),
+                       atoi(Cmd_Argv(cmd, 6))
                );
        }
-       else if(Cmd_Argc() == 2 && !strcmp(Cmd_Argv(1), "clear"))
+       else if(Cmd_Argc(cmd) == 2 && !strcmp(Cmd_Argv(cmd, 1), "clear"))
        {
                memset(in_bestweapon_info, 0, sizeof(in_bestweapon_info));
        }
-       else if(Cmd_Argc() == 2 && !strcmp(Cmd_Argv(1), "quake"))
+       else if(Cmd_Argc(cmd) == 2 && !strcmp(Cmd_Argv(cmd, 1), "quake"))
        {
                IN_BestWeapon_ResetData();
        }
        else
        {
-               Con_Printf("Usage: %s weaponshortname impulse itemcode activeweaponcode ammostat ammomin; %s clear; %s quake\n", Cmd_Argv(0), Cmd_Argv(0), Cmd_Argv(0));
+               Con_Printf("Usage: %s weaponshortname impulse itemcode activeweaponcode ammostat ammomin; %s clear; %s quake\n", Cmd_Argv(cmd, 0), Cmd_Argv(cmd, 0), Cmd_Argv(cmd, 0));
        }
 }
 
-static void IN_BestWeapon (void)
+static void IN_BestWeapon_f(cmd_state_t *cmd)
 {
        int i, n;
        const char *t;
-       if (Cmd_Argc() < 2)
+       if (Cmd_Argc(cmd) < 2)
        {
                Con_Printf("bestweapon requires 1 or more parameters\n");
                return;
        }
-       for (i = 1;i < Cmd_Argc();i++)
+       for (i = 1;i < Cmd_Argc(cmd);i++)
        {
-               t = Cmd_Argv(i);
+               t = Cmd_Argv(cmd, i);
                // figure out which weapon this character refers to
                for (n = 0;n < IN_BESTWEAPON_MAX && in_bestweapon_info[n].impulse;n++)
                {
@@ -302,55 +302,6 @@ static void IN_BestWeapon (void)
        // if we couldn't find any of the weapons, there's nothing more we can do...
 }
 
-#if 0
-void IN_CycleWeapon (void)
-{
-       int i, n;
-       int first = -1;
-       qboolean found = false;
-       const char *t;
-       if (Cmd_Argc() < 2)
-       {
-               Con_Printf("bestweapon requires 1 or more parameters\n");
-               return;
-       }
-       for (i = 1;i < Cmd_Argc();i++)
-       {
-               t = Cmd_Argv(i);
-               // figure out which weapon this character refers to
-               for (n = 0;n < IN_BESTWEAPON_MAX && in_bestweapon_info[n].impulse;n++)
-               {
-                       if (!strcmp(in_bestweapon_info[n].name, t))
-                       {
-                               // we found out what weapon this character refers to
-                               // check if the inventory contains the weapon and enough ammo
-                               if ((cl.stats[STAT_ITEMS] & in_bestweapon_info[n].weaponbit) && (cl.stats[in_bestweapon_info[n].ammostat] >= in_bestweapon_info[n].ammomin))
-                               {
-                                       // we found one of the weapons the player wanted
-                                       if(first == -1)
-                                               first = n;
-                                       if(found)
-                                       {
-                                               in_impulse = in_bestweapon_info[n].impulse;
-                                               return;
-                                       }
-                                       if(cl.stats[STAT_ACTIVEWEAPON] == in_bestweapon_info[n].activeweaponcode)
-                                               found = true;
-                               }
-                               break;
-                       }
-               }
-               // if we couldn't identify the weapon we just ignore it and continue checking for other weapons
-       }
-       if(first != -1)
-       {
-               in_impulse = in_bestweapon_info[first].impulse;
-               return;
-       }
-       // if we couldn't find any of the weapons, there's nothing more we can do...
-}
-#endif
-
 /*
 ===============
 CL_KeyState
@@ -2159,80 +2110,75 @@ CL_InitInput
 */
 void CL_InitInput (void)
 {
-       Cmd_AddCommand ("+moveup",IN_UpDown, "swim upward");
-       Cmd_AddCommand ("-moveup",IN_UpUp, "stop swimming upward");
-       Cmd_AddCommand ("+movedown",IN_DownDown, "swim downward");
-       Cmd_AddCommand ("-movedown",IN_DownUp, "stop swimming downward");
-       Cmd_AddCommand ("+left",IN_LeftDown, "turn left");
-       Cmd_AddCommand ("-left",IN_LeftUp, "stop turning left");
-       Cmd_AddCommand ("+right",IN_RightDown, "turn right");
-       Cmd_AddCommand ("-right",IN_RightUp, "stop turning right");
-       Cmd_AddCommand ("+forward",IN_ForwardDown, "move forward");
-       Cmd_AddCommand ("-forward",IN_ForwardUp, "stop moving forward");
-       Cmd_AddCommand ("+back",IN_BackDown, "move backward");
-       Cmd_AddCommand ("-back",IN_BackUp, "stop moving backward");
-       Cmd_AddCommand ("+lookup", IN_LookupDown, "look upward");
-       Cmd_AddCommand ("-lookup", IN_LookupUp, "stop looking upward");
-       Cmd_AddCommand ("+lookdown", IN_LookdownDown, "look downward");
-       Cmd_AddCommand ("-lookdown", IN_LookdownUp, "stop looking downward");
-       Cmd_AddCommand ("+strafe", IN_StrafeDown, "activate strafing mode (move instead of turn)");
-       Cmd_AddCommand ("-strafe", IN_StrafeUp, "deactivate strafing mode");
-       Cmd_AddCommand ("+moveleft", IN_MoveleftDown, "strafe left");
-       Cmd_AddCommand ("-moveleft", IN_MoveleftUp, "stop strafing left");
-       Cmd_AddCommand ("+moveright", IN_MoverightDown, "strafe right");
-       Cmd_AddCommand ("-moveright", IN_MoverightUp, "stop strafing right");
-       Cmd_AddCommand ("+speed", IN_SpeedDown, "activate run mode (faster movement and turning)");
-       Cmd_AddCommand ("-speed", IN_SpeedUp, "deactivate run mode");
-       Cmd_AddCommand ("+attack", IN_AttackDown, "begin firing");
-       Cmd_AddCommand ("-attack", IN_AttackUp, "stop firing");
-       Cmd_AddCommand ("+jump", IN_JumpDown, "jump");
-       Cmd_AddCommand ("-jump", IN_JumpUp, "end jump (so you can jump again)");
-       Cmd_AddCommand ("impulse", IN_Impulse, "send an impulse number to server (select weapon, use item, etc)");
-       Cmd_AddCommand ("+klook", IN_KLookDown, "activate keyboard looking mode, do not recenter view");
-       Cmd_AddCommand ("-klook", IN_KLookUp, "deactivate keyboard looking mode");
-       Cmd_AddCommand ("+mlook", IN_MLookDown, "activate mouse looking mode, do not recenter view");
-       Cmd_AddCommand ("-mlook", IN_MLookUp, "deactivate mouse looking mode");
-
-       // LadyHavoc: added use button
-       Cmd_AddCommand ("+use", IN_UseDown, "use something (may be used by some mods)");
-       Cmd_AddCommand ("-use", IN_UseUp, "stop using something");
-
-       // LadyHavoc: added 6 new buttons
-       Cmd_AddCommand ("+button3", IN_Button3Down, "activate button3 (behavior depends on mod)");
-       Cmd_AddCommand ("-button3", IN_Button3Up, "deactivate button3");
-       Cmd_AddCommand ("+button4", IN_Button4Down, "activate button4 (behavior depends on mod)");
-       Cmd_AddCommand ("-button4", IN_Button4Up, "deactivate button4");
-       Cmd_AddCommand ("+button5", IN_Button5Down, "activate button5 (behavior depends on mod)");
-       Cmd_AddCommand ("-button5", IN_Button5Up, "deactivate button5");
-       Cmd_AddCommand ("+button6", IN_Button6Down, "activate button6 (behavior depends on mod)");
-       Cmd_AddCommand ("-button6", IN_Button6Up, "deactivate button6");
-       Cmd_AddCommand ("+button7", IN_Button7Down, "activate button7 (behavior depends on mod)");
-       Cmd_AddCommand ("-button7", IN_Button7Up, "deactivate button7");
-       Cmd_AddCommand ("+button8", IN_Button8Down, "activate button8 (behavior depends on mod)");
-       Cmd_AddCommand ("-button8", IN_Button8Up, "deactivate button8");
-       Cmd_AddCommand ("+button9", IN_Button9Down, "activate button9 (behavior depends on mod)");
-       Cmd_AddCommand ("-button9", IN_Button9Up, "deactivate button9");
-       Cmd_AddCommand ("+button10", IN_Button10Down, "activate button10 (behavior depends on mod)");
-       Cmd_AddCommand ("-button10", IN_Button10Up, "deactivate button10");
-       Cmd_AddCommand ("+button11", IN_Button11Down, "activate button11 (behavior depends on mod)");
-       Cmd_AddCommand ("-button11", IN_Button11Up, "deactivate button11");
-       Cmd_AddCommand ("+button12", IN_Button12Down, "activate button12 (behavior depends on mod)");
-       Cmd_AddCommand ("-button12", IN_Button12Up, "deactivate button12");
-       Cmd_AddCommand ("+button13", IN_Button13Down, "activate button13 (behavior depends on mod)");
-       Cmd_AddCommand ("-button13", IN_Button13Up, "deactivate button13");
-       Cmd_AddCommand ("+button14", IN_Button14Down, "activate button14 (behavior depends on mod)");
-       Cmd_AddCommand ("-button14", IN_Button14Up, "deactivate button14");
-       Cmd_AddCommand ("+button15", IN_Button15Down, "activate button15 (behavior depends on mod)");
-       Cmd_AddCommand ("-button15", IN_Button15Up, "deactivate button15");
-       Cmd_AddCommand ("+button16", IN_Button16Down, "activate button16 (behavior depends on mod)");
-       Cmd_AddCommand ("-button16", IN_Button16Up, "deactivate button16");
+       Cmd_AddCommand(&cmd_client, "+moveup",IN_UpDown, "swim upward");
+       Cmd_AddCommand(&cmd_client, "-moveup",IN_UpUp, "stop swimming upward");
+       Cmd_AddCommand(&cmd_client, "+movedown",IN_DownDown, "swim downward");
+       Cmd_AddCommand(&cmd_client, "-movedown",IN_DownUp, "stop swimming downward");
+       Cmd_AddCommand(&cmd_client, "+left",IN_LeftDown, "turn left");
+       Cmd_AddCommand(&cmd_client, "-left",IN_LeftUp, "stop turning left");
+       Cmd_AddCommand(&cmd_client, "+right",IN_RightDown, "turn right");
+       Cmd_AddCommand(&cmd_client, "-right",IN_RightUp, "stop turning right");
+       Cmd_AddCommand(&cmd_client, "+forward",IN_ForwardDown, "move forward");
+       Cmd_AddCommand(&cmd_client, "-forward",IN_ForwardUp, "stop moving forward");
+       Cmd_AddCommand(&cmd_client, "+back",IN_BackDown, "move backward");
+       Cmd_AddCommand(&cmd_client, "-back",IN_BackUp, "stop moving backward");
+       Cmd_AddCommand(&cmd_client, "+lookup", IN_LookupDown, "look upward");
+       Cmd_AddCommand(&cmd_client, "-lookup", IN_LookupUp, "stop looking upward");
+       Cmd_AddCommand(&cmd_client, "+lookdown", IN_LookdownDown, "look downward");
+       Cmd_AddCommand(&cmd_client, "-lookdown", IN_LookdownUp, "stop looking downward");
+       Cmd_AddCommand(&cmd_client, "+strafe", IN_StrafeDown, "activate strafing mode (move instead of turn)");
+       Cmd_AddCommand(&cmd_client, "-strafe", IN_StrafeUp, "deactivate strafing mode");
+       Cmd_AddCommand(&cmd_client, "+moveleft", IN_MoveleftDown, "strafe left");
+       Cmd_AddCommand(&cmd_client, "-moveleft", IN_MoveleftUp, "stop strafing left");
+       Cmd_AddCommand(&cmd_client, "+moveright", IN_MoverightDown, "strafe right");
+       Cmd_AddCommand(&cmd_client, "-moveright", IN_MoverightUp, "stop strafing right");
+       Cmd_AddCommand(&cmd_client, "+speed", IN_SpeedDown, "activate run mode (faster movement and turning)");
+       Cmd_AddCommand(&cmd_client, "-speed", IN_SpeedUp, "deactivate run mode");
+       Cmd_AddCommand(&cmd_client, "+attack", IN_AttackDown, "begin firing");
+       Cmd_AddCommand(&cmd_client, "-attack", IN_AttackUp, "stop firing");
+       Cmd_AddCommand(&cmd_client, "+jump", IN_JumpDown, "jump");
+       Cmd_AddCommand(&cmd_client, "-jump", IN_JumpUp, "end jump (so you can jump again)");
+       Cmd_AddCommand(&cmd_client, "impulse", IN_Impulse, "send an impulse number to server (select weapon, use item, etc)");
+       Cmd_AddCommand(&cmd_client, "+klook", IN_KLookDown, "activate keyboard looking mode, do not recenter view");
+       Cmd_AddCommand(&cmd_client, "-klook", IN_KLookUp, "deactivate keyboard looking mode");
+       Cmd_AddCommand(&cmd_client, "+mlook", IN_MLookDown, "activate mouse looking mode, do not recenter view");
+       Cmd_AddCommand(&cmd_client, "-mlook", IN_MLookUp, "deactivate mouse looking mode");
+
+       // LadyHavoc: added lots of buttons
+       Cmd_AddCommand(&cmd_client, "+use", IN_UseDown, "use something (may be used by some mods)");
+       Cmd_AddCommand(&cmd_client, "-use", IN_UseUp, "stop using something");
+       Cmd_AddCommand(&cmd_client, "+button3", IN_Button3Down, "activate button3 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button3", IN_Button3Up, "deactivate button3");
+       Cmd_AddCommand(&cmd_client, "+button4", IN_Button4Down, "activate button4 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button4", IN_Button4Up, "deactivate button4");
+       Cmd_AddCommand(&cmd_client, "+button5", IN_Button5Down, "activate button5 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button5", IN_Button5Up, "deactivate button5");
+       Cmd_AddCommand(&cmd_client, "+button6", IN_Button6Down, "activate button6 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button6", IN_Button6Up, "deactivate button6");
+       Cmd_AddCommand(&cmd_client, "+button7", IN_Button7Down, "activate button7 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button7", IN_Button7Up, "deactivate button7");
+       Cmd_AddCommand(&cmd_client, "+button8", IN_Button8Down, "activate button8 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button8", IN_Button8Up, "deactivate button8");
+       Cmd_AddCommand(&cmd_client, "+button9", IN_Button9Down, "activate button9 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button9", IN_Button9Up, "deactivate button9");
+       Cmd_AddCommand(&cmd_client, "+button10", IN_Button10Down, "activate button10 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button10", IN_Button10Up, "deactivate button10");
+       Cmd_AddCommand(&cmd_client, "+button11", IN_Button11Down, "activate button11 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button11", IN_Button11Up, "deactivate button11");
+       Cmd_AddCommand(&cmd_client, "+button12", IN_Button12Down, "activate button12 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button12", IN_Button12Up, "deactivate button12");
+       Cmd_AddCommand(&cmd_client, "+button13", IN_Button13Down, "activate button13 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button13", IN_Button13Up, "deactivate button13");
+       Cmd_AddCommand(&cmd_client, "+button14", IN_Button14Down, "activate button14 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button14", IN_Button14Up, "deactivate button14");
+       Cmd_AddCommand(&cmd_client, "+button15", IN_Button15Down, "activate button15 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button15", IN_Button15Up, "deactivate button15");
+       Cmd_AddCommand(&cmd_client, "+button16", IN_Button16Down, "activate button16 (behavior depends on mod)");
+       Cmd_AddCommand(&cmd_client, "-button16", IN_Button16Up, "deactivate button16");
 
        // LadyHavoc: added bestweapon command
-       Cmd_AddCommand ("bestweapon", IN_BestWeapon, "send an impulse number to server to select the first usable weapon out of several (example: 8 7 6 5 4 3 2 1)");
-#if 0
-       Cmd_AddCommand ("cycleweapon", IN_CycleWeapon, "send an impulse number to server to select the next usable weapon out of several (example: 9 4 8) if you are holding one of these, and choose the first one if you are holding none of these");
-#endif
-       Cmd_AddCommand ("register_bestweapon", IN_BestWeapon_Register_f, "(for QC usage only) change weapon parameters to be used by bestweapon; stuffcmd this in ClientConnect");
+       Cmd_AddCommand(&cmd_client, "bestweapon", IN_BestWeapon_f, "send an impulse number to server to select the first usable weapon out of several (example: 8 7 6 5 4 3 2 1)");
+       Cmd_AddCommand(&cmd_client, "register_bestweapon", IN_BestWeapon_Register_f, "(for QC usage only) change weapon parameters to be used by bestweapon; stuffcmd this in ClientConnect");
 
        Cvar_RegisterVariable(&cl_movecliptokeyboard);
        Cvar_RegisterVariable(&cl_movement);
index bfb3360..8a0d538 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -368,7 +368,7 @@ void CL_Disconnect(void)
                sizebuf_t buf;
                unsigned char bufdata[8];
                if (cls.demorecording)
-                       CL_Stop_f();
+                       CL_Stop_f(&cmd_client);
 
                // send disconnect message 3 times to improve chances of server
                // receiving it (but it still fails sometimes)
@@ -399,7 +399,7 @@ void CL_Disconnect(void)
        cls.signon = 0;
 }
 
-void CL_Disconnect_f(void)
+void CL_Disconnect_f(cmd_state_t *cmd)
 {
        CL_Disconnect ();
        if (sv.active)
@@ -452,8 +452,8 @@ void CL_EstablishConnection(const char *host, int firstarg)
                {
                        int i;
                        *cls.connect_userinfo = 0;
-                       for(i = firstarg; i+2 <= Cmd_Argc(); i += 2)
-                               InfoString_SetValue(cls.connect_userinfo, sizeof(cls.connect_userinfo), Cmd_Argv(i), Cmd_Argv(i+1));
+                       for(i = firstarg; i+2 <= Cmd_Argc(&cmd_client); i += 2)
+                               InfoString_SetValue(cls.connect_userinfo, sizeof(cls.connect_userinfo), Cmd_Argv(&cmd_client, i), Cmd_Argv(&cmd_client, i+1));
                }
                else if(firstarg < -1)
                {
@@ -480,7 +480,7 @@ void CL_EstablishConnection(const char *host, int firstarg)
 CL_PrintEntities_f
 ==============
 */
-static void CL_PrintEntities_f(void)
+static void CL_PrintEntities_f(cmd_state_t *cmd)
 {
        entity_t *ent;
        int i;
@@ -507,7 +507,7 @@ CL_ModelIndexList_f
 List information on all models in the client modelindex
 ===============
 */
-static void CL_ModelIndexList_f(void)
+static void CL_ModelIndexList_f(cmd_state_t *cmd)
 {
        int i;
        dp_model_t *model;
@@ -535,7 +535,7 @@ CL_SoundIndexList_f
 List all sounds in the client soundindex
 ===============
 */
-static void CL_SoundIndexList_f(void)
+static void CL_SoundIndexList_f(cmd_state_t *cmd)
 {
        int i = 1;
 
@@ -1953,7 +1953,7 @@ void CL_UpdateWorld(void)
 }
 
 // LadyHavoc: pausedemo command
-static void CL_PauseDemo_f (void)
+static void CL_PauseDemo_f(cmd_state_t *cmd)
 {
        cls.demopaused = !cls.demopaused;
        if (cls.demopaused)
@@ -1967,32 +1967,32 @@ static void CL_PauseDemo_f (void)
 CL_Fog_f
 ======================
 */
-static void CL_Fog_f (void)
+static void CL_Fog_f(cmd_state_t *cmd)
 {
-       if (Cmd_Argc () == 1)
+       if (Cmd_Argc (cmd) == 1)
        {
                Con_Printf("\"fog\" is \"%f %f %f %f %f %f %f %f %f\"\n", r_refdef.fog_density, r_refdef.fog_red, r_refdef.fog_green, r_refdef.fog_blue, r_refdef.fog_alpha, r_refdef.fog_start, r_refdef.fog_end, r_refdef.fog_height, r_refdef.fog_fadedepth);
                return;
        }
        FOG_clear(); // so missing values get good defaults
-       if(Cmd_Argc() > 1)
-               r_refdef.fog_density = atof(Cmd_Argv(1));
-       if(Cmd_Argc() > 2)
-               r_refdef.fog_red = atof(Cmd_Argv(2));
-       if(Cmd_Argc() > 3)
-               r_refdef.fog_green = atof(Cmd_Argv(3));
-       if(Cmd_Argc() > 4)
-               r_refdef.fog_blue = atof(Cmd_Argv(4));
-       if(Cmd_Argc() > 5)
-               r_refdef.fog_alpha = atof(Cmd_Argv(5));
-       if(Cmd_Argc() > 6)
-               r_refdef.fog_start = atof(Cmd_Argv(6));
-       if(Cmd_Argc() > 7)
-               r_refdef.fog_end = atof(Cmd_Argv(7));
-       if(Cmd_Argc() > 8)
-               r_refdef.fog_height = atof(Cmd_Argv(8));
-       if(Cmd_Argc() > 9)
-               r_refdef.fog_fadedepth = atof(Cmd_Argv(9));
+       if(Cmd_Argc(cmd) > 1)
+               r_refdef.fog_density = atof(Cmd_Argv(cmd, 1));
+       if(Cmd_Argc(cmd) > 2)
+               r_refdef.fog_red = atof(Cmd_Argv(cmd, 2));
+       if(Cmd_Argc(cmd) > 3)
+               r_refdef.fog_green = atof(Cmd_Argv(cmd, 3));
+       if(Cmd_Argc(cmd) > 4)
+               r_refdef.fog_blue = atof(Cmd_Argv(cmd, 4));
+       if(Cmd_Argc(cmd) > 5)
+               r_refdef.fog_alpha = atof(Cmd_Argv(cmd, 5));
+       if(Cmd_Argc(cmd) > 6)
+               r_refdef.fog_start = atof(Cmd_Argv(cmd, 6));
+       if(Cmd_Argc(cmd) > 7)
+               r_refdef.fog_end = atof(Cmd_Argv(cmd, 7));
+       if(Cmd_Argc(cmd) > 8)
+               r_refdef.fog_height = atof(Cmd_Argv(cmd, 8));
+       if(Cmd_Argc(cmd) > 9)
+               r_refdef.fog_fadedepth = atof(Cmd_Argv(cmd, 9));
 }
 
 /*
@@ -2000,24 +2000,24 @@ static void CL_Fog_f (void)
 CL_FogHeightTexture_f
 ======================
 */
-static void CL_Fog_HeightTexture_f (void)
+static void CL_Fog_HeightTexture_f(cmd_state_t *cmd)
 {
-       if (Cmd_Argc () < 11)
+       if (Cmd_Argc (cmd) < 11)
        {
                Con_Printf("\"fog_heighttexture\" is \"%f %f %f %f %f %f %f %f %f %s\"\n", r_refdef.fog_density, r_refdef.fog_red, r_refdef.fog_green, r_refdef.fog_blue, r_refdef.fog_alpha, r_refdef.fog_start, r_refdef.fog_end, r_refdef.fog_height, r_refdef.fog_fadedepth, r_refdef.fog_height_texturename);
                return;
        }
        FOG_clear(); // so missing values get good defaults
-       r_refdef.fog_density = atof(Cmd_Argv(1));
-       r_refdef.fog_red = atof(Cmd_Argv(2));
-       r_refdef.fog_green = atof(Cmd_Argv(3));
-       r_refdef.fog_blue = atof(Cmd_Argv(4));
-       r_refdef.fog_alpha = atof(Cmd_Argv(5));
-       r_refdef.fog_start = atof(Cmd_Argv(6));
-       r_refdef.fog_end = atof(Cmd_Argv(7));
-       r_refdef.fog_height = atof(Cmd_Argv(8));
-       r_refdef.fog_fadedepth = atof(Cmd_Argv(9));
-       strlcpy(r_refdef.fog_height_texturename, Cmd_Argv(10), sizeof(r_refdef.fog_height_texturename));
+       r_refdef.fog_density = atof(Cmd_Argv(cmd, 1));
+       r_refdef.fog_red = atof(Cmd_Argv(cmd, 2));
+       r_refdef.fog_green = atof(Cmd_Argv(cmd, 3));
+       r_refdef.fog_blue = atof(Cmd_Argv(cmd, 4));
+       r_refdef.fog_alpha = atof(Cmd_Argv(cmd, 5));
+       r_refdef.fog_start = atof(Cmd_Argv(cmd, 6));
+       r_refdef.fog_end = atof(Cmd_Argv(cmd, 7));
+       r_refdef.fog_height = atof(Cmd_Argv(cmd, 8));
+       r_refdef.fog_fadedepth = atof(Cmd_Argv(cmd, 9));
+       strlcpy(r_refdef.fog_height_texturename, Cmd_Argv(cmd, 10), sizeof(r_refdef.fog_height_texturename));
 }
 
 
@@ -2028,7 +2028,7 @@ CL_TimeRefresh_f
 For program optimization
 ====================
 */
-static void CL_TimeRefresh_f (void)
+static void CL_TimeRefresh_f(cmd_state_t *cmd)
 {
        int i;
        double timestart, timedelta;
@@ -2047,7 +2047,7 @@ static void CL_TimeRefresh_f (void)
        Con_Printf("%f seconds (%f fps)\n", timedelta, 128/timedelta);
 }
 
-static void CL_AreaStats_f(void)
+static void CL_AreaStats_f(cmd_state_t *cmd)
 {
        World_PrintAreaStats(&cl.world, "client");
 }
@@ -2122,29 +2122,29 @@ static void CL_Locs_AddNode(vec3_t mins, vec3_t maxs, const char *name)
        *pointer = node;
 }
 
-static void CL_Locs_Add_f(void)
+static void CL_Locs_Add_f(cmd_state_t *cmd)
 {
        vec3_t mins, maxs;
-       if (Cmd_Argc() != 5 && Cmd_Argc() != 8)
+       if (Cmd_Argc(cmd) != 5 && Cmd_Argc(cmd) != 8)
        {
-               Con_Printf("usage: %s x y z[ x y z] name\n", Cmd_Argv(0));
+               Con_Printf("usage: %s x y z[ x y z] name\n", Cmd_Argv(cmd, 0));
                return;
        }
-       mins[0] = atof(Cmd_Argv(1));
-       mins[1] = atof(Cmd_Argv(2));
-       mins[2] = atof(Cmd_Argv(3));
-       if (Cmd_Argc() == 8)
+       mins[0] = atof(Cmd_Argv(cmd, 1));
+       mins[1] = atof(Cmd_Argv(cmd, 2));
+       mins[2] = atof(Cmd_Argv(cmd, 3));
+       if (Cmd_Argc(cmd) == 8)
        {
-               maxs[0] = atof(Cmd_Argv(4));
-               maxs[1] = atof(Cmd_Argv(5));
-               maxs[2] = atof(Cmd_Argv(6));
-               CL_Locs_AddNode(mins, maxs, Cmd_Argv(7));
+               maxs[0] = atof(Cmd_Argv(cmd, 4));
+               maxs[1] = atof(Cmd_Argv(cmd, 5));
+               maxs[2] = atof(Cmd_Argv(cmd, 6));
+               CL_Locs_AddNode(mins, maxs, Cmd_Argv(cmd, 7));
        }
        else
-               CL_Locs_AddNode(mins, mins, Cmd_Argv(4));
+               CL_Locs_AddNode(mins, mins, Cmd_Argv(cmd, 4));
 }
 
-static void CL_Locs_RemoveNearest_f(void)
+static void CL_Locs_RemoveNearest_f(cmd_state_t *cmd)
 {
        cl_locnode_t *loc;
        loc = CL_Locs_FindNearest(r_refdef.view.origin);
@@ -2154,13 +2154,13 @@ static void CL_Locs_RemoveNearest_f(void)
                Con_Printf("no loc point or box found for your location\n");
 }
 
-static void CL_Locs_Clear_f(void)
+static void CL_Locs_Clear_f(cmd_state_t *cmd)
 {
        while (cl.locnodes)
                CL_Locs_FreeNode(cl.locnodes);
 }
 
-static void CL_Locs_Save_f(void)
+static void CL_Locs_Save_f(cmd_state_t *cmd)
 {
        cl_locnode_t *loc;
        qfile_t *outfile;
@@ -2233,7 +2233,7 @@ static void CL_Locs_Save_f(void)
        FS_Close(outfile);
 }
 
-void CL_Locs_Reload_f(void)
+void CL_Locs_Reload_f(cmd_state_t *cmd)
 {
        int i, linenumber, limit, len;
        const char *s;
@@ -2249,7 +2249,7 @@ void CL_Locs_Reload_f(void)
                return;
        }
 
-       CL_Locs_Clear_f();
+       CL_Locs_Clear_f(cmd);
 
        // try maps/something.loc first (LadyHavoc: where I think they should be)
        dpsnprintf(locfilename, sizeof(locfilename), "%s.loc", cl.worldnamenoextension);
@@ -2687,29 +2687,29 @@ void CL_Init (void)
        Cvar_RegisterVariable (&cl_itembobspeed);
        Cvar_RegisterVariable (&cl_itembobheight);
 
-       Cmd_AddCommand ("entities", CL_PrintEntities_f, "print information on network entities known to client");
-       Cmd_AddCommand ("disconnect", CL_Disconnect_f, "disconnect from server (or disconnect all clients if running a server)");
-       Cmd_AddCommand ("record", CL_Record_f, "record a demo");
-       Cmd_AddCommand ("stop", CL_Stop_f, "stop recording or playing a demo");
-       Cmd_AddCommand ("playdemo", CL_PlayDemo_f, "watch a demo file");
-       Cmd_AddCommand ("timedemo", CL_TimeDemo_f, "play back a demo as fast as possible and save statistics to benchmark.log");
+       Cmd_AddCommand(&cmd_client, "entities", CL_PrintEntities_f, "print information on network entities known to client");
+       Cmd_AddCommand(&cmd_client, "disconnect", CL_Disconnect_f, "disconnect from server (or disconnect all clients if running a server)");
+       Cmd_AddCommand(&cmd_client, "record", CL_Record_f, "record a demo");
+       Cmd_AddCommand(&cmd_client, "stop", CL_Stop_f, "stop recording or playing a demo");
+       Cmd_AddCommand(&cmd_client, "playdemo", CL_PlayDemo_f, "watch a demo file");
+       Cmd_AddCommand(&cmd_client, "timedemo", CL_TimeDemo_f, "play back a demo as fast as possible and save statistics to benchmark.log");
 
        // Support Client-side Model Index List
-       Cmd_AddCommand ("cl_modelindexlist", CL_ModelIndexList_f, "list information on all models in the client modelindex");
+       Cmd_AddCommand(&cmd_client, "cl_modelindexlist", CL_ModelIndexList_f, "list information on all models in the client modelindex");
        // Support Client-side Sound Index List
-       Cmd_AddCommand ("cl_soundindexlist", CL_SoundIndexList_f, "list all sounds in the client soundindex");
+       Cmd_AddCommand(&cmd_client, "cl_soundindexlist", CL_SoundIndexList_f, "list all sounds in the client soundindex");
 
        Cvar_RegisterVariable (&cl_autodemo);
        Cvar_RegisterVariable (&cl_autodemo_nameformat);
        Cvar_RegisterVariable (&cl_autodemo_delete);
 
-       Cmd_AddCommand ("fog", CL_Fog_f, "set global fog parameters (density red green blue [alpha [mindist [maxdist [top [fadedepth]]]]])");
-       Cmd_AddCommand ("fog_heighttexture", CL_Fog_HeightTexture_f, "set global fog parameters (density red green blue alpha mindist maxdist top depth textures/mapname/fogheight.tga)");
+       Cmd_AddCommand(&cmd_client, "fog", CL_Fog_f, "set global fog parameters (density red green blue [alpha [mindist [maxdist [top [fadedepth]]]]])");
+       Cmd_AddCommand(&cmd_client, "fog_heighttexture", CL_Fog_HeightTexture_f, "set global fog parameters (density red green blue alpha mindist maxdist top depth textures/mapname/fogheight.tga)");
 
        // LadyHavoc: added pausedemo
-       Cmd_AddCommand ("pausedemo", CL_PauseDemo_f, "pause demo playback (can also safely pause demo recording if using QUAKE, QUAKEDP or NEHAHRAMOVIE protocol, useful for making movies)");
+       Cmd_AddCommand(&cmd_client, "pausedemo", CL_PauseDemo_f, "pause demo playback (can also safely pause demo recording if using QUAKE, QUAKEDP or NEHAHRAMOVIE protocol, useful for making movies)");
 
-       Cmd_AddCommand ("cl_areastats", CL_AreaStats_f, "prints statistics on entity culling during collision traces");
+       Cmd_AddCommand(&cmd_client, "cl_areastats", CL_AreaStats_f, "prints statistics on entity culling during collision traces");
 
        Cvar_RegisterVariable(&r_draweffects);
        Cvar_RegisterVariable(&cl_explosions_alpha_start);
@@ -2736,15 +2736,15 @@ void CL_Init (void)
        Cvar_RegisterVariable(&qport);
        Cvar_SetValueQuick(&qport, (rand() * RAND_MAX + rand()) & 0xffff);
 
-       Cmd_AddCommand("timerefresh", CL_TimeRefresh_f, "turn quickly and print rendering statistcs");
+       Cmd_AddCommand(&cmd_client, "timerefresh", CL_TimeRefresh_f, "turn quickly and print rendering statistcs");
 
        Cvar_RegisterVariable(&cl_locs_enable);
        Cvar_RegisterVariable(&cl_locs_show);
-       Cmd_AddCommand("locs_add", CL_Locs_Add_f, "add a point or box location (usage: x y z[ x y z] \"name\", if two sets of xyz are supplied it is a box, otherwise point)");
-       Cmd_AddCommand("locs_removenearest", CL_Locs_RemoveNearest_f, "remove the nearest point or box (note: you need to be very near a box to remove it)");
-       Cmd_AddCommand("locs_clear", CL_Locs_Clear_f, "remove all loc points/boxes");
-       Cmd_AddCommand("locs_reload", CL_Locs_Reload_f, "reload .loc file for this map");
-       Cmd_AddCommand("locs_save", CL_Locs_Save_f, "save .loc file for this map containing currently defined points and boxes");
+       Cmd_AddCommand(&cmd_client, "locs_add", CL_Locs_Add_f, "add a point or box location (usage: x y z[ x y z] \"name\", if two sets of xyz are supplied it is a box, otherwise point)");
+       Cmd_AddCommand(&cmd_client, "locs_removenearest", CL_Locs_RemoveNearest_f, "remove the nearest point or box (note: you need to be very near a box to remove it)");
+       Cmd_AddCommand(&cmd_client, "locs_clear", CL_Locs_Clear_f, "remove all loc points/boxes");
+       Cmd_AddCommand(&cmd_client, "locs_reload", CL_Locs_Reload_f, "reload .loc file for this map");
+       Cmd_AddCommand(&cmd_client, "locs_save", CL_Locs_Save_f, "save .loc file for this map containing currently defined points and boxes");
 
        CL_Parse_Init();
        CL_Particles_Init();
index 5d8ff31..f216777 100644 (file)
@@ -192,9 +192,9 @@ cvar_t cl_iplog_name = {CVAR_SAVE, "cl_iplog_name", "darkplaces_iplog.txt", "nam
 
 static qboolean QW_CL_CheckOrDownloadFile(const char *filename);
 static void QW_CL_RequestNextDownload(void);
-static void QW_CL_NextUpload(void);
+static void QW_CL_NextUpload_f(cmd_state_t *cmd);
 //static qboolean QW_CL_IsUploading(void);
-static void QW_CL_StopUpload(void);
+static void QW_CL_StopUpload_f(cmd_state_t *cmd);
 
 /*
 ==================
@@ -500,7 +500,7 @@ static void CL_SetupWorldModel(void)
        World_Start(&cl.world);
 
        // load or reload .loc file for team chat messages
-       CL_Locs_Reload_f();
+       CL_Locs_Reload_f(&cmd_client);
 
        // make sure we send enough keepalives
        CL_KeepaliveMessage(false);
@@ -885,14 +885,14 @@ static void QW_CL_ParseSoundList(void)
        QW_CL_RequestNextDownload();
 }
 
-static void QW_CL_Skins_f(void)
+static void QW_CL_Skins_f(cmd_state_t *cmd)
 {
        cls.qw_downloadnumber = 0;
        cls.qw_downloadtype = dl_skin;
        QW_CL_RequestNextDownload();
 }
 
-static void QW_CL_Changing_f(void)
+static void QW_CL_Changing_f(cmd_state_t *cmd)
 {
        if (cls.qw_downloadmemory)  // don't change when downloading
                return;
@@ -903,7 +903,7 @@ static void QW_CL_Changing_f(void)
        Con_Printf("\nChanging map...\n");
 }
 
-void QW_CL_NextUpload(void)
+void QW_CL_NextUpload_f(cmd_state_t *cmd)
 {
        int r, percent, size;
 
@@ -930,7 +930,7 @@ void QW_CL_NextUpload(void)
 
        Con_Printf("Upload completed\n");
 
-       QW_CL_StopUpload();
+       QW_CL_StopUpload_f(cmd);
 }
 
 void QW_CL_StartUpload(unsigned char *data, int size)
@@ -940,7 +940,7 @@ void QW_CL_StartUpload(unsigned char *data, int size)
                return;
 
        // abort existing upload if in progress
-       QW_CL_StopUpload();
+       QW_CL_StopUpload_f(&cmd_client);
 
        Con_DPrintf("Starting upload of %d bytes...\n", size);
 
@@ -949,7 +949,7 @@ void QW_CL_StartUpload(unsigned char *data, int size)
        cls.qw_uploadsize = size;
        cls.qw_uploadpos = 0;
 
-       QW_CL_NextUpload();
+       QW_CL_NextUpload_f(&cmd_client);
 }
 
 #if 0
@@ -959,7 +959,7 @@ qboolean QW_CL_IsUploading(void)
 }
 #endif
 
-void QW_CL_StopUpload(void)
+void QW_CL_StopUpload_f(cmd_state_t *cmd)
 {
        if (cls.qw_uploaddata)
                Mem_Free(cls.qw_uploaddata);
@@ -1366,7 +1366,7 @@ static void CL_BeginDownloads(qboolean aborteddownload)
        }
 }
 
-static void CL_BeginDownloads_f(void)
+static void CL_BeginDownloads_f(cmd_state_t *cmd)
 {
        // prevent cl_begindownloads from being issued multiple times in one match
        // to prevent accidentally cancelled downloads
@@ -1509,11 +1509,11 @@ static void CL_ParseDownload(void)
        cls.qw_downloadspeedcount += size;
 }
 
-static void CL_DownloadBegin_f(void)
+static void CL_DownloadBegin_f(cmd_state_t *cmd)
 {
-       int size = atoi(Cmd_Argv(1));
+       int size = atoi(Cmd_Argv(cmd, 1));
 
-       if (size < 0 || size > 1<<30 || FS_CheckNastyPath(Cmd_Argv(2), false))
+       if (size < 0 || size > 1<<30 || FS_CheckNastyPath(Cmd_Argv(cmd, 2), false))
        {
                Con_Printf("cl_downloadbegin: received bogus information\n");
                CL_StopDownload(0, 0);
@@ -1526,15 +1526,15 @@ static void CL_DownloadBegin_f(void)
        CL_StopDownload(0, 0);
 
        // we're really beginning a download now, so initialize stuff
-       strlcpy(cls.qw_downloadname, Cmd_Argv(2), sizeof(cls.qw_downloadname));
+       strlcpy(cls.qw_downloadname, Cmd_Argv(cmd, 2), sizeof(cls.qw_downloadname));
        cls.qw_downloadmemorymaxsize = size;
        cls.qw_downloadmemory = (unsigned char *) Mem_Alloc(cls.permanentmempool, cls.qw_downloadmemorymaxsize);
        cls.qw_downloadnumber++;
 
        cls.qw_download_deflate = false;
-       if(Cmd_Argc() >= 4)
+       if(Cmd_Argc(cmd) >= 4)
        {
-               if(!strcmp(Cmd_Argv(3), "deflate"))
+               if(!strcmp(Cmd_Argv(cmd, 3), "deflate"))
                        cls.qw_download_deflate = true;
                // check further encodings here
        }
@@ -1542,7 +1542,7 @@ static void CL_DownloadBegin_f(void)
        Cmd_ForwardStringToServer("sv_startdownload");
 }
 
-static void CL_StopDownload_f(void)
+static void CL_StopDownload_f(cmd_state_t *cmd)
 {
        Curl_CancelAll();
        if (cls.qw_downloadname[0])
@@ -1553,14 +1553,14 @@ static void CL_StopDownload_f(void)
        CL_BeginDownloads(true);
 }
 
-static void CL_DownloadFinished_f(void)
+static void CL_DownloadFinished_f(cmd_state_t *cmd)
 {
-       if (Cmd_Argc() < 3)
+       if (Cmd_Argc(cmd) < 3)
        {
                Con_Printf("Malformed cl_downloadfinished command\n");
                return;
        }
-       CL_StopDownload(atoi(Cmd_Argv(1)), atoi(Cmd_Argv(2)));
+       CL_StopDownload(atoi(Cmd_Argv(cmd, 1)), atoi(Cmd_Argv(cmd, 2)));
        CL_BeginDownloads(false);
 }
 
@@ -1619,7 +1619,7 @@ static void CL_SignonReply (void)
                        // execute cl_begindownloads next frame
                        // (after any commands added by svc_stufftext have been executed)
                        // when done with downloads the "prespawn" will be sent
-                       Cbuf_AddText("\ncl_begindownloads\n");
+                       Cbuf_AddText(&cmd_client, "\ncl_begindownloads\n");
 
                        //MSG_WriteByte (&cls.netcon->message, clc_stringcmd);
                        //MSG_WriteString (&cls.netcon->message, "prespawn");
@@ -1920,7 +1920,7 @@ static void CL_ParseServerInfo (void)
                        if (cls.demorecording)
                        {
                                // finish the previous level's demo file
-                               CL_Stop_f();
+                               CL_Stop_f(&cmd_client);
                        }
 
                        // start a new demo file
@@ -3094,18 +3094,18 @@ static void CL_IPLog_Load(void)
        }
 }
 
-static void CL_IPLog_List_f(void)
+static void CL_IPLog_List_f(cmd_state_t *cmd)
 {
        int i, j;
        const char *addressprefix;
-       if (Cmd_Argc() > 2)
+       if (Cmd_Argc(cmd) > 2)
        {
-               Con_Printf("usage: %s 123.456.789.\n", Cmd_Argv(0));
+               Con_Printf("usage: %s 123.456.789.\n", Cmd_Argv(cmd, 0));
                return;
        }
        addressprefix = "";
-       if (Cmd_Argc() >= 2)
-               addressprefix = Cmd_Argv(1);
+       if (Cmd_Argc(cmd) >= 2)
+               addressprefix = Cmd_Argv(cmd, 1);
        if (!cl_iplog_loaded)
                CL_IPLog_Load();
        if (addressprefix && addressprefix[0])
@@ -3663,7 +3663,7 @@ void CL_ParseServerMessage(void)
                                break;
 
                        case qw_svc_sellscreen:
-                               Cmd_ExecuteString ("help", src_command, true);
+                               Cmd_ExecuteString(&cmd_client, "help", src_command, true);
                                break;
 
                        case qw_svc_smallkick:
@@ -4170,7 +4170,7 @@ void CL_ParseServerMessage(void)
                                break;
 
                        case svc_sellscreen:
-                               Cmd_ExecuteString ("help", src_command, true);
+                               Cmd_ExecuteString(&cmd_client, "help", src_command, true);
                                break;
                        case svc_hidelmp:
                                if (gamemode == GAME_TENEBRAE)
@@ -4273,7 +4273,7 @@ void CL_Parse_DumpPacket(void)
 void CL_Parse_ErrorCleanUp(void)
 {
        CL_StopDownload(0, 0);
-       QW_CL_StopUpload();
+       QW_CL_StopUpload_f(&cmd_client);
 }
 
 void CL_Parse_Init(void)
@@ -4306,15 +4306,15 @@ void CL_Parse_Init(void)
        Cvar_RegisterVariable(&cl_iplog_name);
        Cvar_RegisterVariable(&cl_readpicture_force);
 
-       Cmd_AddCommand("nextul", QW_CL_NextUpload, "sends next fragment of current upload buffer (screenshot for example)");
-       Cmd_AddCommand("stopul", QW_CL_StopUpload, "aborts current upload (screenshot for example)");
-       Cmd_AddCommand("skins", QW_CL_Skins_f, "downloads missing qw skins from server");
-       Cmd_AddCommand("changing", QW_CL_Changing_f, "sent by qw servers to tell client to wait for level change");
-       Cmd_AddCommand("cl_begindownloads", CL_BeginDownloads_f, "used internally by darkplaces client while connecting (causes loading of models and sounds or triggers downloads for missing ones)");
-       Cmd_AddCommand("cl_downloadbegin", CL_DownloadBegin_f, "(networking) informs client of download file information, client replies with sv_startsoundload to begin the transfer");
-       Cmd_AddCommand("stopdownload", CL_StopDownload_f, "terminates a download");
-       Cmd_AddCommand("cl_downloadfinished", CL_DownloadFinished_f, "signals that a download has finished and provides the client with file size and crc to check its integrity");
-       Cmd_AddCommand("iplog_list", CL_IPLog_List_f, "lists names of players whose IP address begins with the supplied text (example: iplog_list 123.456.789)");
+       Cmd_AddCommand(&cmd_client, "nextul", QW_CL_NextUpload_f, "sends next fragment of current upload buffer (screenshot for example)");
+       Cmd_AddCommand(&cmd_client, "stopul", QW_CL_StopUpload_f, "aborts current upload (screenshot for example)");
+       Cmd_AddCommand(&cmd_client, "skins", QW_CL_Skins_f, "downloads missing qw skins from server");
+       Cmd_AddCommand(&cmd_client, "changing", QW_CL_Changing_f, "sent by qw servers to tell client to wait for level change");
+       Cmd_AddCommand(&cmd_client, "cl_begindownloads", CL_BeginDownloads_f, "used internally by darkplaces client while connecting (causes loading of models and sounds or triggers downloads for missing ones)");
+       Cmd_AddCommand(&cmd_client, "cl_downloadbegin", CL_DownloadBegin_f, "(networking) informs client of download file information, client replies with sv_startsoundload to begin the transfer");
+       Cmd_AddCommand(&cmd_client, "stopdownload", CL_StopDownload_f, "terminates a download");
+       Cmd_AddCommand(&cmd_client, "cl_downloadfinished", CL_DownloadFinished_f, "signals that a download has finished and provides the client with file size and crc to check its integrity");
+       Cmd_AddCommand(&cmd_client, "iplog_list", CL_IPLog_List_f, "lists names of players whose IP address begins with the supplied text (example: iplog_list 123.456.789)");
 }
 
 void CL_Parse_Shutdown(void)
index e85b10b..e778ba1 100644 (file)
@@ -571,9 +571,9 @@ static void CL_Particles_LoadEffectInfo(const char *customfile)
        }
 }
 
-static void CL_Particles_LoadEffectInfo_f(void)
+static void CL_Particles_LoadEffectInfo_f(cmd_state_t *cmd)
 {
-       CL_Particles_LoadEffectInfo(Cmd_Argc() > 1 ? Cmd_Argv(1) : NULL);
+       CL_Particles_LoadEffectInfo(Cmd_Argc(cmd) > 1 ? Cmd_Argv(cmd, 1) : NULL);
 }
 
 /*
@@ -581,11 +581,11 @@ static void CL_Particles_LoadEffectInfo_f(void)
 CL_InitParticles
 ===============
 */
-void CL_ReadPointFile_f (void);
+void CL_ReadPointFile_f(cmd_state_t *cmd);
 void CL_Particles_Init (void)
 {
-       Cmd_AddCommand ("pointfile", CL_ReadPointFile_f, "display point file produced by qbsp when a leak was detected in the map (a line leading through the leak hole, to an entity inside the level)");
-       Cmd_AddCommand ("cl_particles_reloadeffects", CL_Particles_LoadEffectInfo_f, "reloads effectinfo.txt and maps/levelname_effectinfo.txt (where levelname is the current map) if parameter is given, loads from custom file (no levelname_effectinfo are loaded in this case)");
+       Cmd_AddCommand(&cmd_client, "pointfile", CL_ReadPointFile_f, "display point file produced by qbsp when a leak was detected in the map (a line leading through the leak hole, to an entity inside the level)");
+       Cmd_AddCommand(&cmd_client, "cl_particles_reloadeffects", CL_Particles_LoadEffectInfo_f, "reloads effectinfo.txt and maps/levelname_effectinfo.txt (where levelname is the current map) if parameter is given, loads from custom file (no levelname_effectinfo are loaded in this case)");
 
        Cvar_RegisterVariable (&cl_particles);
        Cvar_RegisterVariable (&cl_particles_quality);
@@ -1728,7 +1728,7 @@ void CL_EntityParticles (const entity_t *ent)
 }
 
 
-void CL_ReadPointFile_f (void)
+void CL_ReadPointFile_f(cmd_state_t *cmd)
 {
        double org[3], leakorg[3];
        vec3_t vecorg;
index 5584e08..27701b0 100644 (file)
@@ -125,8 +125,8 @@ int                 scr_con_margin_bottom;
 
 extern int     con_vislines;
 
-static void SCR_ScreenShot_f (void);
-static void R_Envmap_f (void);
+static void SCR_ScreenShot_f(cmd_state_t *cmd);
+static void R_Envmap_f(cmd_state_t *cmd);
 
 // backend
 void R_ClearScreen(qboolean fogcolor);
@@ -649,12 +649,12 @@ static int SCR_InfobarHeight(void)
 SCR_InfoBar_f
 ==============
 */
-static void SCR_InfoBar_f(void)
+static void SCR_InfoBar_f(cmd_state_t *cmd)
 {
-       if(Cmd_Argc() == 3)
+       if(Cmd_Argc(cmd) == 3)
        {
-               scr_infobartime_off = atof(Cmd_Argv(1));
-               strlcpy(scr_infobarstring, Cmd_Argv(2), sizeof(scr_infobarstring));
+               scr_infobartime_off = atof(Cmd_Argv(cmd, 1));
+               strlcpy(scr_infobarstring, Cmd_Argv(cmd, 2), sizeof(scr_infobarstring));
        }
        else
        {
@@ -1241,7 +1241,7 @@ SCR_SizeUp_f
 Keybinding command
 =================
 */
-static void SCR_SizeUp_f (void)
+static void SCR_SizeUp_f(cmd_state_t *cmd)
 {
        Cvar_SetValue ("viewsize",scr_viewsize.value+10);
 }
@@ -1254,7 +1254,7 @@ SCR_SizeDown_f
 Keybinding command
 =================
 */
-static void SCR_SizeDown_f (void)
+static void SCR_SizeDown_f(cmd_state_t *cmd)
 {
        Cvar_SetValue ("viewsize",scr_viewsize.value-10);
 }
@@ -1362,11 +1362,11 @@ void CL_Screen_Init(void)
        if (COM_CheckParm ("-noconsole"))
                Cvar_SetQuick(&scr_conforcewhiledisconnected, "0");
 
-       Cmd_AddCommand ("sizeup",SCR_SizeUp_f, "increase view size (increases viewsize cvar)");
-       Cmd_AddCommand ("sizedown",SCR_SizeDown_f, "decrease view size (decreases viewsize cvar)");
-       Cmd_AddCommand ("screenshot",SCR_ScreenShot_f, "takes a screenshot of the next rendered frame");
-       Cmd_AddCommand ("envmap", R_Envmap_f, "render a cubemap (skybox) of the current scene");
-       Cmd_AddCommand ("infobar", SCR_InfoBar_f, "display a text in the infobar (usage: infobar expiretime string)");
+       Cmd_AddCommand(&cmd_client, "sizeup",SCR_SizeUp_f, "increase view size (increases viewsize cvar)");
+       Cmd_AddCommand(&cmd_client, "sizedown",SCR_SizeDown_f, "decrease view size (decreases viewsize cvar)");
+       Cmd_AddCommand(&cmd_client, "screenshot",SCR_ScreenShot_f, "takes a screenshot of the next rendered frame");
+       Cmd_AddCommand(&cmd_client, "envmap", R_Envmap_f, "render a cubemap (skybox) of the current scene");
+       Cmd_AddCommand(&cmd_client, "infobar", SCR_InfoBar_f, "display a text in the infobar (usage: infobar expiretime string)");
 
 #ifdef CONFIG_VIDEO_CAPTURE
        SCR_CaptureVideo_Ogg_Init();
@@ -1380,7 +1380,7 @@ void CL_Screen_Init(void)
 SCR_ScreenShot_f
 ==================
 */
-void SCR_ScreenShot_f (void)
+void SCR_ScreenShot_f(cmd_state_t *cmd)
 {
        static int shotnumber;
        static char old_prefix_name[MAX_QPATH];
@@ -1392,10 +1392,10 @@ void SCR_ScreenShot_f (void)
        qboolean png = (scr_screenshot_png.integer != 0) && !jpeg;
        char vabuf[1024];
 
-       if (Cmd_Argc() == 2)
+       if (Cmd_Argc(cmd) == 2)
        {
                const char *ext;
-               strlcpy(filename, Cmd_Argv(1), sizeof(filename));
+               strlcpy(filename, Cmd_Argv(cmd, 1), sizeof(filename));
                ext = FS_FileExtension(filename);
                if (!strcasecmp(ext, "jpg"))
                {
@@ -1800,7 +1800,7 @@ envmapinfo[12] =
        {{ 90, 180, 0}, "nz", false, false,  true}
 };
 
-static void R_Envmap_f (void)
+static void R_Envmap_f(cmd_state_t *cmd)
 {
        int j, size;
        char filename[MAX_QPATH], basename[MAX_QPATH];
@@ -1808,14 +1808,14 @@ static void R_Envmap_f (void)
        unsigned char *buffer2;
        r_rendertarget_t *rt;
 
-       if (Cmd_Argc() != 3)
+       if (Cmd_Argc(cmd) != 3)
        {
                Con_Print("envmap <basename> <size>: save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n");
                return;
        }
 
-       strlcpy (basename, Cmd_Argv(1), sizeof (basename));
-       size = atoi(Cmd_Argv(2));
+       strlcpy (basename, Cmd_Argv(cmd, 1), sizeof (basename));
+       size = atoi(Cmd_Argv(cmd, 2));
        if (size != 128 && size != 256 && size != 512 && size != 1024)
        {
                Con_Print("envmap: size must be one of 128, 256, 512, or 1024\n");
index 9e5ca0d..7dbc4d2 100644 (file)
@@ -610,7 +610,7 @@ void CL_VideoStop(void)
        CL_CloseVideo( cl_videos );
 }
 
-static void CL_PlayVideo_f(void)
+static void CL_PlayVideo_f(cmd_state_t *cmd)
 {
        char name[MAX_QPATH], subtitlesfile[MAX_QPATH];
        const char *extension;
@@ -620,27 +620,27 @@ static void CL_PlayVideo_f(void)
        if (COM_CheckParm("-benchmark"))
                return;
 
-       if (Cmd_Argc() < 2)
+       if (Cmd_Argc(cmd) < 2)
        {
                Con_Print("usage: playvideo <videoname> [custom_subtitles_file]\nplays video named video/<videoname>.dpv\nif custom subtitles file is not presented\nit tries video/<videoname>.sub");
                return;
        }
 
-       extension = FS_FileExtension(Cmd_Argv(1));
+       extension = FS_FileExtension(Cmd_Argv(cmd, 1));
        if (extension[0])
-               dpsnprintf(name, sizeof(name), "video/%s", Cmd_Argv(1));
+               dpsnprintf(name, sizeof(name), "video/%s", Cmd_Argv(cmd, 1));
        else
-               dpsnprintf(name, sizeof(name), "video/%s.dpv", Cmd_Argv(1));
-       if ( Cmd_Argc() > 2)
-               CL_VideoStart(name, Cmd_Argv(2));
+               dpsnprintf(name, sizeof(name), "video/%s.dpv", Cmd_Argv(cmd, 1));
+       if ( Cmd_Argc(cmd) > 2)
+               CL_VideoStart(name, Cmd_Argv(cmd, 2));
        else
        {
-               dpsnprintf(subtitlesfile, sizeof(subtitlesfile), "video/%s.dpsubs", Cmd_Argv(1));
+               dpsnprintf(subtitlesfile, sizeof(subtitlesfile), "video/%s.dpsubs", Cmd_Argv(cmd, 1));
                CL_VideoStart(name, subtitlesfile);
        }
 }
 
-static void CL_StopVideo_f(void)
+static void CL_StopVideo_f(cmd_state_t *cmd)
 {
        CL_VideoStop();
 }
@@ -689,8 +689,8 @@ void CL_Video_Init( void )
        bgra.i = 0;bgra.b[1] = 0xFF;cl_videogmask = bgra.i;
        bgra.i = 0;bgra.b[2] = 0xFF;cl_videormask = bgra.i;
 
-       Cmd_AddCommand( "playvideo", CL_PlayVideo_f, "play a .dpv video file" );
-       Cmd_AddCommand( "stopvideo", CL_StopVideo_f, "stop playing a .dpv video file" );
+       Cmd_AddCommand(&cmd_client, "playvideo", CL_PlayVideo_f, "play a .dpv video file" );
+       Cmd_AddCommand(&cmd_client, "stopvideo", CL_StopVideo_f, "stop playing a .dpv video file" );
 
        Cvar_RegisterVariable(&cl_video_subtitles);
        Cvar_RegisterVariable(&cl_video_subtitles_lines);
index 02a34c0..7bd78e0 100644 (file)
--- a/client.h
+++ b/client.h
@@ -1560,7 +1560,7 @@ void CL_Init (void);
 void CL_EstablishConnection(const char *host, int firstarg);
 
 void CL_Disconnect (void);
-void CL_Disconnect_f (void);
+void CL_Disconnect_f(cmd_state_t *cmd);
 
 void CL_UpdateRenderEntity(entity_render_t *ent);
 void CL_SetEntityColormapColors(entity_render_t *ent, int colormap);
@@ -1624,10 +1624,10 @@ void CL_CutDemo(unsigned char **buf, fs_offset_t *filesize);
 void CL_PasteDemo(unsigned char **buf, fs_offset_t *filesize);
 
 void CL_NextDemo(void);
-void CL_Stop_f(void);
-void CL_Record_f(void);
-void CL_PlayDemo_f(void);
-void CL_TimeDemo_f(void);
+void CL_Stop_f(cmd_state_t *cmd);
+void CL_Record_f(cmd_state_t *cmd);
+void CL_PlayDemo_f(cmd_state_t *cmd);
+void CL_TimeDemo_f(cmd_state_t *cmd);
 
 //
 // cl_parse.c
@@ -1644,7 +1644,7 @@ void CL_KeepaliveMessage(qboolean readmessages); // call this during loading of
 //
 // view
 //
-void V_StartPitchDrift (void);
+void V_StartPitchDrift_f(cmd_state_t *cmd);
 void V_StopPitchDrift (void);
 
 void V_Init (void);
@@ -2062,7 +2062,7 @@ void CL_Beam_AddPolygons(const beam_t *b);
 void Sbar_ShowFPS(void);
 void Sbar_ShowFPS_Update(void);
 void Host_SaveConfig(void);
-void Host_LoadConfig_f(void);
+void Host_LoadConfig_f(cmd_state_t *cmd);
 void CL_UpdateMoveVars(void);
 void SCR_CaptureVideo_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length);
 void V_DriftPitch(void);
@@ -2070,7 +2070,7 @@ void V_FadeViewFlashs(void);
 void V_CalcViewBlend(void);
 void V_CalcRefdefUsing (const matrix4x4_t *entrendermatrix, const vec3_t clviewangles, qboolean teleported, qboolean clonground, qboolean clcmdjump, float clstatsviewheight, qboolean cldead, qboolean clintermission, const vec3_t clvelocity);
 void V_CalcRefdef(void);
-void CL_Locs_Reload_f(void);
+void CL_Locs_Reload_f(cmd_state_t *cmd);
 
 #endif
 
index 6e4b3fc..b1060a5 100644 (file)
@@ -1625,17 +1625,17 @@ static void VM_CL_registercmd (prvm_prog_t *prog)
 {
        char *t;
        VM_SAFEPARMCOUNT(1, VM_CL_registercmd);
-       if(!Cmd_Exists(PRVM_G_STRING(OFS_PARM0)))
+       if(!Cmd_Exists(&cmd_client, PRVM_G_STRING(OFS_PARM0)))
        {
                size_t alloclen;
 
                alloclen = strlen(PRVM_G_STRING(OFS_PARM0)) + 1;
                t = (char *)Z_Malloc(alloclen);
                memcpy(t, PRVM_G_STRING(OFS_PARM0), alloclen);
-               Cmd_AddCommand(t, NULL, "console command created by QuakeC");
+               Cmd_AddCommand(&cmd_client, t, NULL, "console command created by QuakeC");
        }
        else
-               Cmd_AddCommand(PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC");
+               Cmd_AddCommand(&cmd_client, PRVM_G_STRING(OFS_PARM0), NULL, "console command created by QuakeC");
 
 }
 
@@ -4157,7 +4157,7 @@ NULL,                                                     // #42 (QUAKE)
 VM_fabs,                                               // #43 float(float f) fabs (QUAKE)
 NULL,                                                  // #44 vector(entity e, float speed) aim (QUAKE)
 VM_cvar,                                               // #45 float(string s) cvar (QUAKE)
-VM_localcmd,                                   // #46 void(string s) localcmd (QUAKE)
+VM_localcmd_client,                            // #46 void(string s) localcmd (QUAKE)
 VM_nextent,                                            // #47 entity(entity e) nextent (QUAKE)
 VM_CL_particle,                                        // #48 void(vector o, vector d, float color, float count) particle (QUAKE)
 VM_changeyaw,                                  // #49 void() ChangeYaw (QUAKE)
diff --git a/cmd.c b/cmd.c
index 8d6d1ea..401e44c 100644 (file)
--- a/cmd.c
+++ b/cmd.c
@@ -22,26 +22,41 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "quakedef.h"
 #include "thread.h"
 
-typedef struct cmdalias_s
-{
-       struct cmdalias_s *next;
-       char name[MAX_ALIAS_NAME];
-       char *value;
-       qboolean initstate; // indicates this command existed at init
-       char *initialvalue; // backup copy of value at init
-} cmdalias_t;
+cmd_state_t cmd_client;
+cmd_state_t cmd_clientfromserver;
+cmd_state_t cmd_server;
+cmd_state_t cmd_serverfromclient;
 
-static cmdalias_t *cmd_alias;
+typedef struct cmd_iter_s {
+       cmd_state_t *cmd;
+}
+cmd_iter_t;
 
-static qboolean cmd_wait;
+static cmd_iter_t cmd_iter_all[] = {
+       {&cmd_client},
+       {&cmd_clientfromserver},
+       {&cmd_server},
+       {&cmd_serverfromclient},
+       {NULL},
+};
 
-static mempool_t *cmd_mempool;
 
-static char cmd_tokenizebuffer[CMD_TOKENIZELENGTH];
-static int cmd_tokenizebufferpos = 0;
+// we only run the +whatever commandline arguments once
+qboolean host_stuffcmdsrun = false;
 
 //=============================================================================
 
+void Cbuf_Lock(cmd_state_t *cmd)
+{
+       Thread_AtomicLock(&cmd->text_lock);
+}
+
+void Cbuf_Unlock(cmd_state_t *cmd)
+{
+       Thread_AtomicUnlock(&cmd->text_lock);
+}
+
+
 /*
 ============
 Cmd_Wait_f
@@ -51,20 +66,11 @@ next frame.  This allows commands like:
 bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2"
 ============
 */
-static void Cmd_Wait_f (void)
+static void Cmd_Wait_f (cmd_state_t *cmd)
 {
-       cmd_wait = true;
+       cmd->wait = true;
 }
 
-typedef struct cmddeferred_s
-{
-       struct cmddeferred_s *next;
-       char *value;
-       double delay;
-} cmddeferred_t;
-
-static cmddeferred_t *cmd_deferred_list = NULL;
-
 /*
 ============
 Cmd_Defer_f
@@ -72,11 +78,11 @@ Cmd_Defer_f
 Cause a command to be executed after a delay.
 ============
 */
-static void Cmd_Defer_f (void)
+static void Cmd_Defer_f (cmd_state_t *cmd)
 {
-       if(Cmd_Argc() == 1)
+       if(Cmd_Argc(cmd) == 1)
        {
-               cmddeferred_t *next = cmd_deferred_list;
+               cmddeferred_t *next = cmd->deferred_list;
                if(!next)
                        Con_Printf("No commands are pending.\n");
                while(next)
@@ -84,34 +90,34 @@ static void Cmd_Defer_f (void)
                        Con_Printf("-> In %9.2f: %s\n", next->delay, next->value);
                        next = next->next;
                }
-       } else if(Cmd_Argc() == 2 && !strcasecmp("clear", Cmd_Argv(1)))
+       } else if(Cmd_Argc(cmd) == 2 && !strcasecmp("clear", Cmd_Argv(cmd, 1)))
        {
-               while(cmd_deferred_list)
+               while(cmd->deferred_list)
                {
-                       cmddeferred_t *cmd = cmd_deferred_list;
-                       cmd_deferred_list = cmd->next;
-                       Mem_Free(cmd->value);
-                       Mem_Free(cmd);
+                       cmddeferred_t *defcmd = cmd->deferred_list;
+                       cmd->deferred_list = defcmd->next;
+                       Mem_Free(defcmd->value);
+                       Mem_Free(defcmd);
                }
-       } else if(Cmd_Argc() == 3)
+       } else if(Cmd_Argc(cmd) == 3)
        {
-               const char *value = Cmd_Argv(2);
+               const char *value = Cmd_Argv(cmd, 2);
                cmddeferred_t *defcmd = (cmddeferred_t*)Mem_Alloc(tempmempool, sizeof(*defcmd));
                size_t len = strlen(value);
 
-               defcmd->delay = atof(Cmd_Argv(1));
+               defcmd->delay = atof(Cmd_Argv(cmd, 1));
                defcmd->value = (char*)Mem_Alloc(tempmempool, len+1);
                memcpy(defcmd->value, value, len+1);
                defcmd->next = NULL;
 
-               if(cmd_deferred_list)
+               if(cmd->deferred_list)
                {
-                       cmddeferred_t *next = cmd_deferred_list;
+                       cmddeferred_t *next = cmd->deferred_list;
                        while(next->next)
                                next = next->next;
                        next->next = defcmd;
                } else
-                       cmd_deferred_list = defcmd;
+                       cmd->deferred_list = defcmd;
                /* Stupid me... this changes the order... so commands with the same delay go blub :S
                  defcmd->next = cmd_deferred_list;
                  cmd_deferred_list = defcmd;*/
@@ -129,18 +135,18 @@ Cmd_Centerprint_f
 Print something to the center of the screen using SCR_Centerprint
 ============
 */
-static void Cmd_Centerprint_f (void)
+static void Cmd_Centerprint_f (cmd_state_t *cmd)
 {
        char msg[MAX_INPUTLINE];
        unsigned int i, c, p;
-       c = Cmd_Argc();
+       c = Cmd_Argc(cmd);
        if(c >= 2)
        {
-               strlcpy(msg, Cmd_Argv(1), sizeof(msg));
+               strlcpy(msg, Cmd_Argv(cmd,1), sizeof(msg));
                for(i = 2; i < c; ++i)
                {
                        strlcat(msg, " ", sizeof(msg));
-                       strlcat(msg, Cmd_Argv(i), sizeof(msg));
+                       strlcat(msg, Cmd_Argv(cmd, i), sizeof(msg));
                }
                c = (unsigned int)strlen(msg);
                for(p = 0, i = 0; i < c; ++i)
@@ -173,10 +179,6 @@ static void Cmd_Centerprint_f (void)
 =============================================================================
 */
 
-static sizebuf_t       cmd_text;
-static unsigned char           cmd_text_buf[CMDBUFSIZE];
-void *cmd_text_mutex = NULL;
-
 /*
 ============
 Cbuf_AddText
@@ -184,18 +186,18 @@ Cbuf_AddText
 Adds command text at the end of the buffer
 ============
 */
-void Cbuf_AddText (const char *text)
+void Cbuf_AddText (cmd_state_t *cmd, const char *text)
 {
        int             l;
 
        l = (int)strlen(text);
 
-       Cbuf_LockThreadMutex();
-       if (cmd_text.cursize + l >= cmd_text.maxsize)
+       Cbuf_Lock(cmd);
+       if (cmd->text.cursize + l >= (size_t)cmd->text.maxsize)
                Con_Print("Cbuf_AddText: overflow\n");
        else
-               SZ_Write(&cmd_text, (const unsigned char *)text, l);
-       Cbuf_UnlockThreadMutex();
+               SZ_Write(&cmd->text, (const unsigned char *)text, l);
+       Cbuf_Unlock(cmd);
 }
 
 
@@ -208,21 +210,21 @@ Adds a \n to the text
 FIXME: actually change the command buffer to do less copying
 ============
 */
-void Cbuf_InsertText (const char *text)
+void Cbuf_InsertText (cmd_state_t *cmd, const char *text)
 {
        size_t l = strlen(text);
-       Cbuf_LockThreadMutex();
+       Cbuf_Lock(cmd);
        // we need to memmove the existing text and stuff this in before it...
-       if (cmd_text.cursize + l >= (size_t)cmd_text.maxsize)
+       if (cmd->text.cursize + l >= (size_t)cmd->text.maxsize)
                Con_Print("Cbuf_InsertText: overflow\n");
        else
        {
                // we don't have a SZ_Prepend, so...
-               memmove(cmd_text.data + l, cmd_text.data, cmd_text.cursize);
-               cmd_text.cursize += (int)l;
-               memcpy(cmd_text.data, text, l);
+               memmove(cmd->text.data + l, cmd->text.data, cmd->text.cursize);
+               cmd->text.cursize += (int)l;
+               memcpy(cmd->text.data, text, l);
        }
-       Cbuf_UnlockThreadMutex();
+       Cbuf_Unlock(cmd);
 }
 
 /*
@@ -230,10 +232,10 @@ void Cbuf_InsertText (const char *text)
 Cbuf_Execute_Deferred --blub
 ============
 */
-static void Cbuf_Execute_Deferred (void)
+static void Cbuf_Execute_Deferred (cmd_state_t *cmd)
 {
        static double oldrealtime = 0;
-       cmddeferred_t *cmd, *prev;
+       cmddeferred_t *defcmd, *prev;
        double eat;
        if (realtime - oldrealtime < 0 || realtime - oldrealtime > 1800) oldrealtime = realtime;
        eat = realtime - oldrealtime;
@@ -241,29 +243,29 @@ static void Cbuf_Execute_Deferred (void)
                return;
        oldrealtime = realtime;
        prev = NULL;
-       cmd = cmd_deferred_list;
-       while(cmd)
+       defcmd = cmd->deferred_list;
+       while(defcmd)
        {
-               cmd->delay -= eat;
-               if(cmd->delay <= 0)
+               defcmd->delay -= eat;
+               if(defcmd->delay <= 0)
                {
-                       Cbuf_AddText(cmd->value);
-                       Cbuf_AddText(";\n");
-                       Mem_Free(cmd->value);
+                       Cbuf_AddText(cmd, defcmd->value);
+                       Cbuf_AddText(cmd, ";\n");
+                       Mem_Free(defcmd->value);
 
                        if(prev) {
-                               prev->next = cmd->next;
-                               Mem_Free(cmd);
-                               cmd = prev->next;
+                               prev->next = defcmd->next;
+                               Mem_Free(defcmd);
+                               defcmd = prev->next;
                        } else {
-                               cmd_deferred_list = cmd->next;
-                               Mem_Free(cmd);
-                               cmd = cmd_deferred_list;
+                               cmd->deferred_list = defcmd->next;
+                               Mem_Free(defcmd);
+                               defcmd = cmd->deferred_list;
                        }
                        continue;
                }
-               prev = cmd;
-               cmd = cmd->next;
+               prev = defcmd;
+               defcmd = defcmd->next;
        }
 }
 
@@ -272,8 +274,8 @@ static void Cbuf_Execute_Deferred (void)
 Cbuf_Execute
 ============
 */
-static qboolean Cmd_PreprocessString( const char *intext, char *outtext, unsigned maxoutlen, cmdalias_t *alias );
-void Cbuf_Execute (void)
+static qboolean Cmd_PreprocessString(cmd_state_t *cmd, const char *intext, char *outtext, unsigned maxoutlen, cmdalias_t *alias );
+void Cbuf_Execute (cmd_state_t *cmd)
 {
        int i;
        char *text;
@@ -284,16 +286,16 @@ void Cbuf_Execute (void)
        char *comment;
 
        // LadyHavoc: making sure the tokenizebuffer doesn't get filled up by repeated crashes
-       cmd_tokenizebufferpos = 0;
+       cmd->tokenizebufferpos = 0;
 
-       while (cmd_text.cursize)
+       while (cmd->text.cursize)
        {
 // find a \n or ; line break
-               text = (char *)cmd_text.data;
+               text = (char *)cmd->text.data;
 
                quotes = false;
                comment = NULL;
-               for (i=0 ; i < cmd_text.cursize ; i++)
+               for (i=0 ; i < cmd->text.cursize ; i++)
                {
                        if(!comment)
                        {
@@ -304,7 +306,7 @@ void Cbuf_Execute (void)
                                {
                                        // make sure i doesn't get > cursize which causes a negative
                                        // size in memmove, which is fatal --blub
-                                       if (i < (cmd_text.cursize-1) && (text[i] == '\\' && (text[i+1] == '"' || text[i+1] == '\\')))
+                                       if (i < (cmd->text.cursize-1) && (text[i] == '\\' && (text[i+1] == '"' || text[i+1] == '\\')))
                                                i++;
                                }
                                else
@@ -336,13 +338,13 @@ void Cbuf_Execute (void)
 // this is necessary because commands (exec, alias) can insert data at the
 // beginning of the text buffer
 
-               if (i == cmd_text.cursize)
-                       cmd_text.cursize = 0;
+               if (i == cmd->text.cursize)
+                       cmd->text.cursize = 0;
                else
                {
                        i++;
-                       cmd_text.cursize -= i;
-                       memmove (cmd_text.data, text+i, cmd_text.cursize);
+                       cmd->text.cursize -= i;
+                       memmove (cmd->text.data, text+i, cmd->text.cursize);
                }
 
 // execute the command line
@@ -357,30 +359,30 @@ void Cbuf_Execute (void)
                        (strncmp(firstchar, "in_bind", 7) || !ISWHITESPACE(firstchar[7]))
                )
                {
-                       if(Cmd_PreprocessString( line, preprocessed, sizeof(preprocessed), NULL ))
-                               Cmd_ExecuteString (preprocessed, src_command, false);
+                       if(Cmd_PreprocessString( cmd, line, preprocessed, sizeof(preprocessed), NULL ))
+                               Cmd_ExecuteString (cmd, preprocessed, src_command, false);
                }
                else
                {
-                       Cmd_ExecuteString (line, src_command, false);
+                       Cmd_ExecuteString (cmd, line, src_command, false);
                }
 
-               if (cmd_wait)
+               if (cmd->wait)
                {       // skip out while text still remains in buffer, leaving it
                        // for next frame
-                       cmd_wait = false;
+                       cmd->wait = false;
                        break;
                }
        }
 }
 
-void Cbuf_Frame(void)
+void Cbuf_Frame(cmd_state_t *cmd)
 {
-       Cbuf_Execute_Deferred();
-       if (cmd_text.cursize)
+       Cbuf_Execute_Deferred(cmd);
+       if (cmd->text.cursize)
        {
                SV_LockThreadMutex();
-               Cbuf_Execute();
+               Cbuf_Execute(cmd);
                SV_UnlockThreadMutex();
        }
 }
@@ -403,14 +405,13 @@ quake +prog jctest.qp +cmd amlev1
 quake -nosound +cmd amlev1
 ===============
 */
-qboolean host_stuffcmdsrun = false;
-static void Cmd_StuffCmds_f (void)
+static void Cmd_StuffCmds_f (cmd_state_t *cmd)
 {
        int             i, j, l;
        // this is for all commandline options combined (and is bounds checked)
        char    build[MAX_INPUTLINE];
 
-       if (Cmd_Argc () != 1)
+       if (Cmd_Argc (cmd) != 1)
        {
                Con_Print("stuffcmds : execute command line parameters\n");
                return;
@@ -454,10 +455,10 @@ static void Cmd_StuffCmds_f (void)
        // now terminate the combined string and prepend it to the command buffer
        // we already reserved space for the terminator
        build[l++] = 0;
-       Cbuf_InsertText (build);
+       Cbuf_InsertText (cmd, build);
 }
 
-static void Cmd_Exec(const char *filename)
+static void Cmd_Exec(cmd_state_t *cmd, const char *filename)
 {
        char *f;
        size_t filenameLen = strlen(filename);
@@ -484,12 +485,12 @@ static void Cmd_Exec(const char *filename)
        // it may seem backwards to insert this text BEFORE the default.cfg
        // but Cbuf_InsertText inserts before, so this actually ends up after it.
        if (isdefaultcfg)
-               Cbuf_InsertText("\ncvar_lockdefaults\n");
+               Cbuf_InsertText(cmd, "\ncvar_lockdefaults\n");
 
        // insert newline after the text to make sure the last line is terminated (some text editors omit the trailing newline)
        // (note: insertion order here is backwards from execution order, so this adds it after the text, by calling it before...)
-       Cbuf_InsertText ("\n");
-       Cbuf_InsertText (f);
+       Cbuf_InsertText (cmd, "\n");
+       Cbuf_InsertText (cmd, f);
        Mem_Free(f);
 
        if (isdefaultcfg)
@@ -500,7 +501,7 @@ static void Cmd_Exec(const char *filename)
                switch(gamemode)
                {
                case GAME_NORMAL:
-                       Cbuf_InsertText("\n"
+                       Cbuf_InsertText(cmd, "\n"
 "sv_gameplayfix_blowupfallenzombies 0\n"
 "sv_gameplayfix_findradiusdistancetobox 0\n"
 "sv_gameplayfix_grenadebouncedownslopes 0\n"
@@ -524,7 +525,7 @@ static void Cmd_Exec(const char *filename)
                                );
                        break;
                case GAME_NEHAHRA:
-                       Cbuf_InsertText("\n"
+                       Cbuf_InsertText(cmd, "\n"
 "sv_gameplayfix_blowupfallenzombies 0\n"
 "sv_gameplayfix_findradiusdistancetobox 0\n"
 "sv_gameplayfix_grenadebouncedownslopes 0\n"
@@ -552,7 +553,7 @@ static void Cmd_Exec(const char *filename)
                // hipnotic mission pack has issues in their proximity mine sticking code, which causes them to bounce off.
                case GAME_HIPNOTIC:
                case GAME_QUOTH:
-                       Cbuf_InsertText("\n"
+                       Cbuf_InsertText(cmd, "\n"
 "sv_gameplayfix_blowupfallenzombies 0\n"
 "sv_gameplayfix_findradiusdistancetobox 0\n"
 "sv_gameplayfix_grenadebouncedownslopes 0\n"
@@ -577,7 +578,7 @@ static void Cmd_Exec(const char *filename)
                        break;
                // rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area
                case GAME_ROGUE:
-                       Cbuf_InsertText("\n"
+                       Cbuf_InsertText(cmd, "\n"
 "sv_gameplayfix_blowupfallenzombies 0\n"
 "sv_gameplayfix_findradiusdistancetobox 0\n"
 "sv_gameplayfix_grenadebouncedownslopes 0\n"
@@ -601,7 +602,7 @@ static void Cmd_Exec(const char *filename)
                                );
                        break;
                case GAME_TENEBRAE:
-                       Cbuf_InsertText("\n"
+                       Cbuf_InsertText(cmd, "\n"
 "sv_gameplayfix_blowupfallenzombies 0\n"
 "sv_gameplayfix_findradiusdistancetobox 0\n"
 "sv_gameplayfix_grenadebouncedownslopes 0\n"
@@ -625,7 +626,7 @@ static void Cmd_Exec(const char *filename)
                                );
                        break;
                case GAME_NEXUIZ:
-                       Cbuf_InsertText("\n"
+                       Cbuf_InsertText(cmd, "\n"
 "sv_gameplayfix_blowupfallenzombies 1\n"
 "sv_gameplayfix_findradiusdistancetobox 1\n"
 "sv_gameplayfix_grenadebouncedownslopes 1\n"
@@ -650,7 +651,7 @@ static void Cmd_Exec(const char *filename)
                        break;
                // Steel Storm: Burning Retribution csqc misinterprets CSQC_InputEvent if type is a value other than 0 or 1
                case GAME_STEELSTORM:
-                       Cbuf_InsertText("\n"
+                       Cbuf_InsertText(cmd, "\n"
 "sv_gameplayfix_blowupfallenzombies 1\n"
 "sv_gameplayfix_findradiusdistancetobox 1\n"
 "sv_gameplayfix_grenadebouncedownslopes 1\n"
@@ -673,7 +674,7 @@ static void Cmd_Exec(const char *filename)
                                );
                        break;
                default:
-                       Cbuf_InsertText("\n"
+                       Cbuf_InsertText(cmd, "\n"
 "sv_gameplayfix_blowupfallenzombies 1\n"
 "sv_gameplayfix_findradiusdistancetobox 1\n"
 "sv_gameplayfix_grenadebouncedownslopes 1\n"
@@ -703,26 +704,26 @@ static void Cmd_Exec(const char *filename)
 Cmd_Exec_f
 ===============
 */
-static void Cmd_Exec_f (void)
+static void Cmd_Exec_f (cmd_state_t *cmd)
 {
        fssearch_t *s;
        int i;
 
-       if (Cmd_Argc () != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
                Con_Print("exec <filename> : execute a script file\n");
                return;
        }
 
-       s = FS_Search(Cmd_Argv(1), true, true);
+       s = FS_Search(Cmd_Argv(cmd, 1), true, true);
        if(!s || !s->numfilenames)
        {
-               Con_Printf("couldn't exec %s\n",Cmd_Argv(1));
+               Con_Printf("couldn't exec %s\n",Cmd_Argv(cmd, 1));
                return;
        }
 
        for(i = 0; i < s->numfilenames; ++i)
-               Cmd_Exec(s->filenames[i]);
+               Cmd_Exec(cmd, s->filenames[i]);
 
        FS_FreeSearch(s);
 }
@@ -735,12 +736,12 @@ Cmd_Echo_f
 Just prints the rest of the line to the console
 ===============
 */
-static void Cmd_Echo_f (void)
+static void Cmd_Echo_f (cmd_state_t *cmd)
 {
        int             i;
 
-       for (i=1 ; i<Cmd_Argc() ; i++)
-               Con_Printf("%s ",Cmd_Argv(i));
+       for (i=1 ; i<Cmd_Argc(cmd) ; i++)
+               Con_Printf("%s ",Cmd_Argv(cmd, i));
        Con_Print("\n");
 }
 
@@ -753,10 +754,10 @@ Cmd_Toggle_f
 Toggles a specified console variable amongst the values specified (default is 0 and 1)
 ===============
 */
-static void Cmd_Toggle_f(void)
+static void Cmd_Toggle_f(cmd_state_t *cmd)
 {
        // Acquire Number of Arguments
-       int nNumArgs = Cmd_Argc();
+       int nNumArgs = Cmd_Argc(cmd);
 
        if(nNumArgs == 1)
                // No Arguments Specified; Print Usage
@@ -764,7 +765,7 @@ static void Cmd_Toggle_f(void)
        else
        { // Correct Arguments Specified
                // Acquire Potential CVar
-               cvar_t* cvCVar = Cvar_FindVar( Cmd_Argv(1) );
+               cvar_t* cvCVar = Cvar_FindVar( Cmd_Argv(cmd, 1) );
 
                if(cvCVar != NULL)
                { // Valid CVar
@@ -778,13 +779,13 @@ static void Cmd_Toggle_f(void)
                        else
                        if(nNumArgs == 3)
                        { // 0 and Specified Usage
-                               if(cvCVar->integer == atoi(Cmd_Argv(2) ) )
+                               if(cvCVar->integer == atoi(Cmd_Argv(cmd, 2) ) )
                                        // CVar is Specified Value; // Reset to 0
                                        Cvar_SetValueQuick(cvCVar, 0);
                                else
                                if(cvCVar->integer == 0)
                                        // CVar is 0; Specify Value
-                                       Cvar_SetQuick(cvCVar, Cmd_Argv(2) );
+                                       Cvar_SetQuick(cvCVar, Cmd_Argv(cmd, 2) );
                                else
                                        // CVar does not match; Reset to 0
                                        Cvar_SetValueQuick(cvCVar, 0);
@@ -796,14 +797,14 @@ static void Cmd_Toggle_f(void)
 
                                for(nCnt = 2; nCnt < nNumArgs; nCnt++)
                                { // Cycle through Values
-                                       if( strcmp(cvCVar->string, Cmd_Argv(nCnt) ) == 0)
+                                       if( strcmp(cvCVar->string, Cmd_Argv(cmd, nCnt) ) == 0)
                                        { // Current Value Located; Increment to Next
                                                if( (nCnt + 1) == nNumArgs)
                                                        // Max Value Reached; Reset
-                                                       Cvar_SetQuick(cvCVar, Cmd_Argv(2) );
+                                                       Cvar_SetQuick(cvCVar, Cmd_Argv(cmd, 2) );
                                                else
                                                        // Next Value
-                                                       Cvar_SetQuick(cvCVar, Cmd_Argv(nCnt + 1) );
+                                                       Cvar_SetQuick(cvCVar, Cmd_Argv(cmd, nCnt + 1) );
 
                                                // End Loop
                                                nCnt = nNumArgs;
@@ -813,13 +814,13 @@ static void Cmd_Toggle_f(void)
                                }
                                if(!bFound)
                                        // Value not Found; Reset to Original
-                                       Cvar_SetQuick(cvCVar, Cmd_Argv(2) );
+                                       Cvar_SetQuick(cvCVar, Cmd_Argv(cmd, 2) );
                        }
 
                }
                else
                { // Invalid CVar
-                       Con_Printf("ERROR : CVar '%s' not found\n", Cmd_Argv(1) );
+                       Con_Printf("ERROR : CVar '%s' not found\n", Cmd_Argv(cmd, 1) );
                }
        }
 }
@@ -831,23 +832,23 @@ Cmd_Alias_f
 Creates a new command that executes a command string (possibly ; seperated)
 ===============
 */
-static void Cmd_Alias_f (void)
+static void Cmd_Alias_f (cmd_state_t *cmd)
 {
        cmdalias_t      *a;
-       char            cmd[MAX_INPUTLINE];
+       char            line[MAX_INPUTLINE];
        int                     i, c;
        const char              *s;
        size_t          alloclen;
 
-       if (Cmd_Argc() == 1)
+       if (Cmd_Argc(cmd) == 1)
        {
                Con_Print("Current alias commands:\n");
-               for (a = cmd_alias ; a ; a=a->next)
+               for (a = cmd->alias ; a ; a=a->next)
                        Con_Printf("%s : %s", a->name, a->value);
                return;
        }
 
-       s = Cmd_Argv(1);
+       s = Cmd_Argv(cmd, 1);
        if (strlen(s) >= MAX_ALIAS_NAME)
        {
                Con_Print("Alias name is too long\n");
@@ -855,7 +856,7 @@ static void Cmd_Alias_f (void)
        }
 
        // if the alias already exists, reuse it
-       for (a = cmd_alias ; a ; a=a->next)
+       for (a = cmd->alias ; a ; a=a->next)
        {
                if (!strcmp(s, a->name))
                {
@@ -871,33 +872,33 @@ static void Cmd_Alias_f (void)
                a = (cmdalias_t *)Z_Malloc (sizeof(cmdalias_t));
                strlcpy (a->name, s, sizeof (a->name));
                // insert it at the right alphanumeric position
-               for( prev = NULL, current = cmd_alias ; current && strcmp( current->name, a->name ) < 0 ; prev = current, current = current->next )
+               for( prev = NULL, current = cmd->alias ; current && strcmp( current->name, a->name ) < 0 ; prev = current, current = current->next )
                        ;
                if( prev ) {
                        prev->next = a;
                } else {
-                       cmd_alias = a;
+                       cmd->alias = a;
                }
                a->next = current;
        }
 
 
 // copy the rest of the command line
-       cmd[0] = 0;             // start out with a null string
-       c = Cmd_Argc();
+       line[0] = 0;            // start out with a null string
+       c = Cmd_Argc(cmd);
        for (i=2 ; i < c ; i++)
        {
                if (i != 2)
-                       strlcat (cmd, " ", sizeof (cmd));
-               strlcat (cmd, Cmd_Argv(i), sizeof (cmd));
+                       strlcat (line, " ", sizeof (line));
+               strlcat (line, Cmd_Argv(cmd, i), sizeof (line));
        }
-       strlcat (cmd, "\n", sizeof (cmd));
+       strlcat (line, "\n", sizeof (line));
 
-       alloclen = strlen (cmd) + 1;
+       alloclen = strlen (line) + 1;
        if(alloclen >= 2)
-               cmd[alloclen - 2] = '\n'; // to make sure a newline is appended even if too long
+               line[alloclen - 2] = '\n'; // to make sure a newline is appended even if too long
        a->value = (char *)Z_Malloc (alloclen);
-       memcpy (a->value, cmd, alloclen);
+       memcpy (a->value, line, alloclen);
 }
 
 /*
@@ -907,30 +908,30 @@ Cmd_UnAlias_f
 Remove existing aliases.
 ===============
 */
-static void Cmd_UnAlias_f (void)
+static void Cmd_UnAlias_f (cmd_state_t *cmd)
 {
        cmdalias_t      *a, *p;
        int i;
        const char *s;
 
-       if(Cmd_Argc() == 1)
+       if(Cmd_Argc(cmd) == 1)
        {
                Con_Print("unalias: Usage: unalias alias1 [alias2 ...]\n");
                return;
        }
 
-       for(i = 1; i < Cmd_Argc(); ++i)
+       for(i = 1; i < Cmd_Argc(cmd); ++i)
        {
-               s = Cmd_Argv(i);
+               s = Cmd_Argv(cmd, i);
                p = NULL;
-               for(a = cmd_alias; a; p = a, a = a->next)
+               for(a = cmd->alias; a; p = a, a = a->next)
                {
                        if(!strcmp(s, a->name))
                        {
                                if (a->initstate) // we can not remove init aliases
                                        continue;
-                               if(a == cmd_alias)
-                                       cmd_alias = a->next;
+                               if(a == cmd->alias)
+                                       cmd->alias = a->next;
                                if(p)
                                        p->next = a->next;
                                Z_Free(a->value);
@@ -951,27 +952,7 @@ static void Cmd_UnAlias_f (void)
 =============================================================================
 */
 
-typedef struct cmd_function_s
-{
-       struct cmd_function_s *next;
-       const char *name;
-       const char *description;
-       xcommand_t consolefunction;
-       xcommand_t clientfunction;
-       qboolean csqcfunc;
-       qboolean initstate; // indicates this command existed at init
-} cmd_function_t;
-
-static int cmd_argc;
-static const char *cmd_argv[MAX_ARGS];
-static const char *cmd_null_string = "";
-static const char *cmd_args;
-cmd_source_t cmd_source;
-
-
-static cmd_function_t *cmd_functions;          // possible commands to execute
-
-static const char *Cmd_GetDirectCvarValue(const char *varname, cmdalias_t *alias, qboolean *is_multiple)
+static const char *Cmd_GetDirectCvarValue(cmd_state_t *cmd, const char *varname, cmdalias_t *alias, qboolean *is_multiple)
 {
        cvar_t *cvar;
        long argno;
@@ -990,11 +971,11 @@ static const char *Cmd_GetDirectCvarValue(const char *varname, cmdalias_t *alias
                {
                        if(is_multiple)
                                *is_multiple = true;
-                       return Cmd_Args();
+                       return Cmd_Args(cmd);
                }
                else if(!strcmp(varname, "#"))
                {
-                       return va(vabuf, sizeof(vabuf), "%d", Cmd_Argc());
+                       return va(vabuf, sizeof(vabuf), "%d", Cmd_Argc(cmd));
                }
                else if(varname[strlen(varname) - 1] == '-')
                {
@@ -1002,7 +983,7 @@ static const char *Cmd_GetDirectCvarValue(const char *varname, cmdalias_t *alias
                        if(endptr == varname + strlen(varname) - 1)
                        {
                                // whole string is a number, apart from the -
-                               const char *p = Cmd_Args();
+                               const char *p = Cmd_Args(cmd);
                                for(; argno > 1; --argno)
                                        if(!COM_ParseToken_Console(&p))
                                                break;
@@ -1026,8 +1007,8 @@ static const char *Cmd_GetDirectCvarValue(const char *varname, cmdalias_t *alias
                        {
                                // whole string is a number
                                // NOTE: we already made sure we don't have an empty cvar name!
-                               if(argno >= 0 && argno < Cmd_Argc())
-                                       return Cmd_Argv(argno);
+                               if(argno >= 0 && argno < Cmd_Argc(cmd))
+                                       return Cmd_Argv(cmd, argno);
                        }
                }
        }
@@ -1097,7 +1078,7 @@ fail:
        return false;
 }
 
-static const char *Cmd_GetCvarValue(const char *var, size_t varlen, cmdalias_t *alias)
+static const char *Cmd_GetCvarValue(cmd_state_t *cmd, const char *var, size_t varlen, cmdalias_t *alias)
 {
        static char varname[MAX_INPUTLINE]; // cmd_mutex
        static char varval[MAX_INPUTLINE]; // cmd_mutex
@@ -1155,12 +1136,12 @@ static const char *Cmd_GetCvarValue(const char *var, size_t varlen, cmdalias_t *
        }
 
        if(varname[0] == '$')
-               varstr = Cmd_GetDirectCvarValue(Cmd_GetDirectCvarValue(varname + 1, alias, NULL), alias, NULL);
+               varstr = Cmd_GetDirectCvarValue(cmd, Cmd_GetDirectCvarValue(cmd, varname + 1, alias, NULL), alias, NULL);
        else
        {
                qboolean is_multiple = false;
                // Exception: $* and $n- don't use the quoted form by default
-               varstr = Cmd_GetDirectCvarValue(varname, alias, &is_multiple);
+               varstr = Cmd_GetDirectCvarValue(cmd, varname, alias, &is_multiple);
                if(is_multiple)
                        if(!varfunc)
                                varfunc = asis;
@@ -1213,7 +1194,7 @@ Cmd_PreprocessString
 
 Preprocesses strings and replaces $*, $param#, $cvar accordingly. Also strips comments.
 */
-static qboolean Cmd_PreprocessString( const char *intext, char *outtext, unsigned maxoutlen, cmdalias_t *alias ) {
+static qboolean Cmd_PreprocessString(cmd_state_t *cmd, const char *intext, char *outtext, unsigned maxoutlen, cmdalias_t *alias ) {
        const char *in;
        size_t eat, varlen;
        unsigned outlen;
@@ -1292,7 +1273,7 @@ static qboolean Cmd_PreprocessString( const char *intext, char *outtext, unsigne
                                varlen = strcspn(in + 1, "}");
                                if(in[varlen + 1] == '}')
                                {
-                                       val = Cmd_GetCvarValue(in + 1, varlen, alias);
+                                       val = Cmd_GetCvarValue(cmd, in + 1, varlen, alias);
                                        if(!val)
                                                return false;
                                        eat = varlen + 2;
@@ -1305,7 +1286,7 @@ static qboolean Cmd_PreprocessString( const char *intext, char *outtext, unsigne
                                }
                        } else {
                                varlen = strspn(in, "#*0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-");
-                               val = Cmd_GetCvarValue(in, varlen, alias);
+                               val = Cmd_GetCvarValue(cmd, in, varlen, alias);
                                if(!val)
                                        return false;
                                eat = varlen;
@@ -1342,11 +1323,11 @@ Cmd_ExecuteAlias
 Called for aliases and fills in the alias into the cbuffer
 ============
 */
-static void Cmd_ExecuteAlias (cmdalias_t *alias)
+static void Cmd_ExecuteAlias (cmd_state_t *cmd, cmdalias_t *alias)
 {
        static char buffer[ MAX_INPUTLINE ]; // cmd_mutex
        static char buffer2[ MAX_INPUTLINE ]; // cmd_mutex
-       qboolean ret = Cmd_PreprocessString( alias->value, buffer, sizeof(buffer) - 2, alias );
+       qboolean ret = Cmd_PreprocessString( cmd, alias->value, buffer, sizeof(buffer) - 2, alias );
        if(!ret)
                return;
        // insert at start of command buffer, so that aliases execute in order
@@ -1356,7 +1337,7 @@ static void Cmd_ExecuteAlias (cmdalias_t *alias)
        // have to make sure that no second variable expansion takes place, otherwise
        // alias parameters containing dollar signs can have bad effects.
        Cmd_QuoteString(buffer2, sizeof(buffer2), buffer, "$", false);
-       Cbuf_InsertText( buffer2 );
+       Cbuf_InsertText(cmd, buffer2);
 }
 
 /*
@@ -1368,17 +1349,17 @@ Cmd_List
 
 ========
 */
-static void Cmd_List_f (void)
+static void Cmd_List_f (cmd_state_t *cmd)
 {
-       cmd_function_t *cmd;
+       cmd_function_t *func;
        const char *partial;
        size_t len;
        int count;
        qboolean ispattern;
 
-       if (Cmd_Argc() > 1)
+       if (Cmd_Argc(cmd) > 1)
        {
-               partial = Cmd_Argv (1);
+               partial = Cmd_Argv(cmd, 1);
                len = strlen(partial);
                ispattern = (strchr(partial, '*') || strchr(partial, '?'));
        }
@@ -1390,11 +1371,11 @@ static void Cmd_List_f (void)
        }
 
        count = 0;
-       for (cmd = cmd_functions; cmd; cmd = cmd->next)
+       for (func = cmd->functions; func; func = func->next)
        {
-               if (partial && (ispattern ? !matchpattern_with_separator(cmd->name, partial, false, "", false) : strncmp(partial, cmd->name, len)))
+               if (partial && (ispattern ? !matchpattern_with_separator(func->name, partial, false, "", false) : strncmp(partial, func->name, len)))
                        continue;
-               Con_Printf("%s : %s\n", cmd->name, cmd->description);
+               Con_Printf("%s : %s\n", func->name, func->description);
                count++;
        }
 
@@ -1409,9 +1390,9 @@ static void Cmd_List_f (void)
                Con_Printf("%i Command%s\n\n", count, (count > 1) ? "s" : "");
 }
 
-static void Cmd_Apropos_f(void)
+static void Cmd_Apropos_f(cmd_state_t *cmd)
 {
-       cmd_function_t *cmd;
+       cmd_function_t *func;
        cvar_t *cvar;
        cmdalias_t *alias;
        const char *partial;
@@ -1419,8 +1400,8 @@ static void Cmd_Apropos_f(void)
        qboolean ispattern;
        char vabuf[1024];
 
-       if (Cmd_Argc() > 1)
-               partial = Cmd_Args();
+       if (Cmd_Argc(cmd) > 1)
+               partial = Cmd_Args(cmd);
        else
        {
                Con_Printf("usage: apropos <string>\n");
@@ -1440,15 +1421,15 @@ static void Cmd_Apropos_f(void)
                Con_Printf ("cvar ^3%s^7 is \"%s\" [\"%s\"] %s\n", cvar->name, cvar->string, cvar->defstring, cvar->description);
                count++;
        }
-       for (cmd = cmd_functions; cmd; cmd = cmd->next)
+       for (func = cmd->functions; func; func = func->next)
        {
-               if (!matchpattern_with_separator(cmd->name, partial, true, "", false))
-               if (!matchpattern_with_separator(cmd->description, partial, true, "", false))
+               if (!matchpattern_with_separator(func->name, partial, true, "", false))
+               if (!matchpattern_with_separator(func->description, partial, true, "", false))
                        continue;
-               Con_Printf("command ^2%s^7: %s\n", cmd->name, cmd->description);
+               Con_Printf("command ^2%s^7: %s\n", func->name, func->description);
                count++;
        }
-       for (alias = cmd_alias; alias; alias = alias->next)
+       for (alias = cmd->alias; alias; alias = alias->next)
        {
                // procede here a bit differently as an alias value always got a final \n
                if (!matchpattern_with_separator(alias->name, partial, true, "", false))
@@ -1465,54 +1446,88 @@ static void Cmd_Apropos_f(void)
 Cmd_Init
 ============
 */
-void Cmd_Init (void)
+void Cmd_Init(void)
 {
-       cmd_mempool = Mem_AllocPool("commands", 0, NULL);
-       // space for commands and script files
-       cmd_text.data = cmd_text_buf;
-       cmd_text.maxsize = sizeof(cmd_text_buf);
-       cmd_text.cursize = 0;
-
-       if (Thread_HasThreads())
-               cmd_text_mutex = Thread_CreateMutex();
+       cmd_iter_t *cmd_iter;
+       for (cmd_iter = cmd_iter_all; cmd_iter->cmd; cmd_iter++)
+       {
+               cmd_state_t *cmd = cmd_iter->cmd;
+               cmd->mempool = Mem_AllocPool("commands", 0, NULL);
+               // space for commands and script files
+               cmd->text.data = cmd->text_buf;
+               cmd->text.maxsize = sizeof(cmd->text_buf);
+               cmd->text.cursize = 0;
+               cmd->null_string = "";
+       }
 }
 
-void Cmd_Init_Commands (void)
+void Cmd_Init_Commands(qboolean dedicated_server)
 {
 //
 // register our commands
 //
-       Cmd_AddCommand ("stuffcmds",Cmd_StuffCmds_f, "execute commandline parameters (must be present in quake.rc script)");
-       Cmd_AddCommand ("exec",Cmd_Exec_f, "execute a script file");
-       Cmd_AddCommand ("echo",Cmd_Echo_f, "print a message to the console (useful in scripts)");
-       Cmd_AddCommand ("alias",Cmd_Alias_f, "create a script function (parameters are passed in as $X (being X a number), $* for all parameters, $X- for all parameters starting from $X). Without arguments show the list of all alias");
-       Cmd_AddCommand ("unalias",Cmd_UnAlias_f, "remove an alias");
-       Cmd_AddCommand ("cmd", Cmd_ForwardToServer, "send a console commandline to the server (used by some mods)");
-       Cmd_AddCommand ("wait", Cmd_Wait_f, "make script execution wait for next rendered frame");
-       Cmd_AddCommand ("set", Cvar_Set_f, "create or change the value of a console 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 ("unset", Cvar_Del_f, "delete a cvar (does not work for static ones like _cl_name, or read-only ones)");
+       // client-only commands
+       Cmd_AddCommand(&cmd_client, "cmd", Cmd_ForwardToServer_f, "send a console commandline to the server (used by some mods)");
+       Cmd_AddCommand(&cmd_client, "wait", Cmd_Wait_f, "make script execution wait for next rendered frame");
+       Cmd_AddCommand(&cmd_client, "cprint", Cmd_Centerprint_f, "print something at the screen center");
+
+       // maintenance commands used for upkeep of cvars and saved configs
+       Cmd_AddCommand(&cmd_client, "stuffcmds", Cmd_StuffCmds_f, "execute commandline parameters (must be present in quake.rc script)");
+       Cmd_AddCommand(&cmd_client, "cvar_lockdefaults", Cvar_LockDefaults_f, "stores the current values of all cvars into their default values, only used once during startup after parsing default.cfg");
+       Cmd_AddCommand(&cmd_client, "cvar_resettodefaults_all", Cvar_ResetToDefaults_All_f, "sets all cvars to their locked default values");
+       Cmd_AddCommand(&cmd_client, "cvar_resettodefaults_nosaveonly", Cvar_ResetToDefaults_NoSaveOnly_f, "sets all non-saved cvars to their locked default values (variables that will not be saved to config.cfg)");
+       Cmd_AddCommand(&cmd_client, "cvar_resettodefaults_saveonly", Cvar_ResetToDefaults_SaveOnly_f, "sets all saved cvars to their locked default values (variables that will be saved to config.cfg)");
+       Cmd_AddCommand(&cmd_server, "stuffcmds", Cmd_StuffCmds_f, "execute commandline parameters (must be present in quake.rc script)");
+       Cmd_AddCommand(&cmd_server, "cvar_lockdefaults", Cvar_LockDefaults_f, "stores the current values of all cvars into their default values, only used once during startup after parsing default.cfg");
+       Cmd_AddCommand(&cmd_server, "cvar_resettodefaults_all", Cvar_ResetToDefaults_All_f, "sets all cvars to their locked default values");
+       Cmd_AddCommand(&cmd_server, "cvar_resettodefaults_nosaveonly", Cvar_ResetToDefaults_NoSaveOnly_f, "sets all non-saved cvars to their locked default values (variables that will not be saved to config.cfg)");
+       Cmd_AddCommand(&cmd_server, "cvar_resettodefaults_saveonly", Cvar_ResetToDefaults_SaveOnly_f, "sets all saved cvars to their locked default values (variables that will be saved to config.cfg)");
+
+       // general console commands used in multiple environments
+       Cmd_AddCommand(&cmd_client, "exec", Cmd_Exec_f, "execute a script file");
+       Cmd_AddCommand(&cmd_client, "echo",Cmd_Echo_f, "print a message to the console (useful in scripts)");
+       Cmd_AddCommand(&cmd_client, "alias",Cmd_Alias_f, "create a script function (parameters are passed in as $X (being X a number), $* for all parameters, $X- for all parameters starting from $X). Without arguments show the list of all alias");
+       Cmd_AddCommand(&cmd_client, "unalias",Cmd_UnAlias_f, "remove an alias");
+       Cmd_AddCommand(&cmd_client, "set", Cvar_Set_f, "create or change the value of a console variable");
+       Cmd_AddCommand(&cmd_client, "seta", Cvar_SetA_f, "create or change the value of a console variable that will be saved to config.cfg");
+       Cmd_AddCommand(&cmd_client, "unset", Cvar_Del_f, "delete a cvar (does not work for static ones like _cl_name, or read-only ones)");
+       Cmd_AddCommand(&cmd_clientfromserver, "exec", Cmd_Exec_f, "execute a script file");
+       Cmd_AddCommand(&cmd_clientfromserver, "echo", Cmd_Echo_f, "print a message to the console (useful in scripts)");
+       Cmd_AddCommand(&cmd_clientfromserver, "alias", Cmd_Alias_f, "create a script function (parameters are passed in as $X (being X a number), $* for all parameters, $X- for all parameters starting from $X). Without arguments show the list of all alias");
+       Cmd_AddCommand(&cmd_clientfromserver, "unalias", Cmd_UnAlias_f, "remove an alias");
+       Cmd_AddCommand(&cmd_clientfromserver, "set", Cvar_Set_f, "create or change the value of a console variable");
+       Cmd_AddCommand(&cmd_clientfromserver, "seta", Cvar_SetA_f, "create or change the value of a console variable that will be saved to config.cfg");
+       Cmd_AddCommand(&cmd_clientfromserver, "unset", Cvar_Del_f, "delete a cvar (does not work for static ones like _cl_name, or read-only ones)");
+       Cmd_AddCommand(&cmd_server, "exec", Cmd_Exec_f, "execute a script file");
+       Cmd_AddCommand(&cmd_server, "echo", Cmd_Echo_f, "print a message to the console (useful in scripts)");
+       Cmd_AddCommand(&cmd_server, "alias", Cmd_Alias_f, "create a script function (parameters are passed in as $X (being X a number), $* for all parameters, $X- for all parameters starting from $X). Without arguments show the list of all alias");
+       Cmd_AddCommand(&cmd_server, "unalias", Cmd_UnAlias_f, "remove an alias");
+       Cmd_AddCommand(&cmd_server, "set", Cvar_Set_f, "create or change the value of a console variable");
+       Cmd_AddCommand(&cmd_server, "seta", Cvar_SetA_f, "create or change the value of a console variable that will be saved to config.cfg");
+       Cmd_AddCommand(&cmd_server, "unset", Cvar_Del_f, "delete a cvar (does not work for static ones like _cl_name, or read-only ones)");
+
 #ifdef FILLALLCVARSWITHRUBBISH
-       Cmd_AddCommand ("fillallcvarswithrubbish", Cvar_FillAll_f, "fill all cvars with a specified number of characters to provoke buffer overruns");
+       Cmd_AddCommand(&cmd_client, "fillallcvarswithrubbish", Cvar_FillAll_f, "fill all cvars with a specified number of characters to provoke buffer overruns");
+       Cmd_AddCommand(&cmd_server, "fillallcvarswithrubbish", Cvar_FillAll_f, "fill all cvars with a specified number of characters to provoke buffer overruns");
 #endif /* FILLALLCVARSWITHRUBBISH */
 
        // 2000-01-09 CmdList, CvarList commands By Matthias "Maddes" Buecher
        // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
-       Cmd_AddCommand ("cmdlist", Cmd_List_f, "lists all console commands beginning with the specified prefix or matching the specified wildcard pattern");
-       Cmd_AddCommand ("cvarlist", Cvar_List_f, "lists all console variables beginning with the specified prefix or matching the specified wildcard pattern");
-       Cmd_AddCommand ("apropos", Cmd_Apropos_f, "lists all console variables/commands/aliases containing the specified string in the name or description");
-
-       Cmd_AddCommand ("cvar_lockdefaults", Cvar_LockDefaults_f, "stores the current values of all cvars into their default values, only used once during startup after parsing default.cfg");
-       Cmd_AddCommand ("cvar_resettodefaults_all", Cvar_ResetToDefaults_All_f, "sets all cvars to their locked default values");
-       Cmd_AddCommand ("cvar_resettodefaults_nosaveonly", Cvar_ResetToDefaults_NoSaveOnly_f, "sets all non-saved cvars to their locked default values (variables that will not be saved to config.cfg)");
-       Cmd_AddCommand ("cvar_resettodefaults_saveonly", Cvar_ResetToDefaults_SaveOnly_f, "sets all saved cvars to their locked default values (variables that will be saved to config.cfg)");
+       Cmd_AddCommand(&cmd_client, "cmdlist", Cmd_List_f, "lists all console commands beginning with the specified prefix or matching the specified wildcard pattern");
+       Cmd_AddCommand(&cmd_client, "cvarlist", Cvar_List_f, "lists all console variables beginning with the specified prefix or matching the specified wildcard pattern");
+       Cmd_AddCommand(&cmd_client, "apropos", Cmd_Apropos_f, "lists all console variables/commands/aliases containing the specified string in the name or description");
+       Cmd_AddCommand(&cmd_server, "cmdlist", Cmd_List_f, "lists all console commands beginning with the specified prefix or matching the specified wildcard pattern");
+       Cmd_AddCommand(&cmd_server, "cvarlist", Cvar_List_f, "lists all console variables beginning with the specified prefix or matching the specified wildcard pattern");
+       Cmd_AddCommand(&cmd_server, "apropos", Cmd_Apropos_f, "lists all console variables/commands/aliases containing the specified string in the name or description");
 
-       Cmd_AddCommand ("cprint", Cmd_Centerprint_f, "print something at the screen center");
-       Cmd_AddCommand ("defer", Cmd_Defer_f, "execute a command in the future");
+       Cmd_AddCommand(&cmd_client, "defer", Cmd_Defer_f, "execute a command in the future");
+       Cmd_AddCommand(&cmd_server, "defer", Cmd_Defer_f, "execute a command in the future");
 
        // DRESK - 5/14/06
        // Support Doom3-style Toggle Command
-       Cmd_AddCommand( "toggle", Cmd_Toggle_f, "toggles a console variable's values (use for more info)");
+       Cmd_AddCommand(&cmd_client, "toggle", Cmd_Toggle_f, "toggles a console variable's values (use for more info)");
+       Cmd_AddCommand(&cmd_server, "toggle", Cmd_Toggle_f, "toggles a console variable's values (use for more info)");
+       Cmd_AddCommand(&cmd_clientfromserver, "toggle", Cmd_Toggle_f, "toggles a console variable's values (use for more info)");
 }
 
 /*
@@ -1522,15 +1537,19 @@ Cmd_Shutdown
 */
 void Cmd_Shutdown(void)
 {
-       if (cmd_text_mutex)
+       cmd_iter_t *cmd_iter;
+       for (cmd_iter = cmd_iter_all; cmd_iter->cmd; cmd_iter++)
        {
-               // we usually have this locked when we get here from Host_Quit_f
-               Cbuf_UnlockThreadMutex();
-               Thread_DestroyMutex(cmd_text_mutex);
-       }
-       cmd_text_mutex = NULL;
+               cmd_state_t *cmd = cmd_iter->cmd;
 
-       Mem_FreePool(&cmd_mempool);
+               if (cmd->text_lock)
+               {
+                       // we usually have this locked when we get here from Host_Quit_f
+                       Cbuf_Unlock(cmd);
+               }
+
+               Mem_FreePool(&cmd->mempool);
+       }
 }
 
 /*
@@ -1538,9 +1557,9 @@ void Cmd_Shutdown(void)
 Cmd_Argc
 ============
 */
-int            Cmd_Argc (void)
+int            Cmd_Argc (cmd_state_t *cmd)
 {
-       return cmd_argc;
+       return cmd->argc;
 }
 
 /*
@@ -1548,11 +1567,11 @@ int             Cmd_Argc (void)
 Cmd_Argv
 ============
 */
-const char *Cmd_Argv (int arg)
+const char *Cmd_Argv(cmd_state_t *cmd, int arg)
 {
-       if (arg >= cmd_argc )
-               return cmd_null_string;
-       return cmd_argv[arg];
+       if (arg >= cmd->argc )
+               return cmd->null_string;
+       return cmd->argv[arg];
 }
 
 /*
@@ -1560,9 +1579,9 @@ const char *Cmd_Argv (int arg)
 Cmd_Args
 ============
 */
-const char *Cmd_Args (void)
+const char *Cmd_Args (cmd_state_t *cmd)
 {
-       return cmd_args;
+       return cmd->args;
 }
 
 
@@ -1574,12 +1593,12 @@ Parses the given string into command line tokens.
 ============
 */
 // AK: This function should only be called from ExcuteString because the current design is a bit of an hack
-static void Cmd_TokenizeString (const char *text)
+static void Cmd_TokenizeString (cmd_state_t *cmd, const char *text)
 {
        int l;
 
-       cmd_argc = 0;
-       cmd_args = NULL;
+       cmd->argc = 0;
+       cmd->args = NULL;
 
        while (1)
        {
@@ -1603,24 +1622,24 @@ static void Cmd_TokenizeString (const char *text)
                if (!*text)
                        return;
 
-               if (cmd_argc == 1)
-                       cmd_args = text;
+               if (cmd->argc == 1)
+                       cmd->args = text;
 
                if (!COM_ParseToken_Console(&text))
                        return;
 
-               if (cmd_argc < MAX_ARGS)
+               if (cmd->argc < MAX_ARGS)
                {
                        l = (int)strlen(com_token) + 1;
-                       if (cmd_tokenizebufferpos + l > CMD_TOKENIZELENGTH)
+                       if (cmd->tokenizebufferpos + l > CMD_TOKENIZELENGTH)
                        {
                                Con_Printf("Cmd_TokenizeString: ran out of %i character buffer space for command arguements\n", CMD_TOKENIZELENGTH);
                                break;
                        }
-                       memcpy (cmd_tokenizebuffer + cmd_tokenizebufferpos, com_token, l);
-                       cmd_argv[cmd_argc] = cmd_tokenizebuffer + cmd_tokenizebufferpos;
-                       cmd_tokenizebufferpos += l;
-                       cmd_argc++;
+                       memcpy (cmd->tokenizebuffer + cmd->tokenizebufferpos, com_token, l);
+                       cmd->argv[cmd->argc] = cmd->tokenizebuffer + cmd->tokenizebufferpos;
+                       cmd->tokenizebufferpos += l;
+                       cmd->argc++;
                }
        }
 }
@@ -1631,9 +1650,9 @@ static void Cmd_TokenizeString (const char *text)
 Cmd_AddCommand
 ============
 */
-void Cmd_AddCommand_WithClientCommand (const char *cmd_name, xcommand_t consolefunction, xcommand_t clientfunction, const char *description)
+void Cmd_AddCommand(cmd_state_t *cmd, const char *cmd_name, xcommand_t function, const char *description)
 {
-       cmd_function_t *cmd;
+       cmd_function_t *func;
        cmd_function_t *prev, *current;
 
 // fail if the command is a variable name
@@ -1643,47 +1662,40 @@ void Cmd_AddCommand_WithClientCommand (const char *cmd_name, xcommand_t consolef
                return;
        }
 
-// fail if the command already exists
-       for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
+       // fail if the command already exists in this interpreter
+       for (func = cmd->functions; func; func = func->next)
+               if (!strcmp(cmd_name, func->name))
+                       break;
+
+       if (func)
        {
-               if (!strcmp (cmd_name, cmd->name))
-               {
-                       if (consolefunction || clientfunction)
-                       {
-                               Con_Printf("Cmd_AddCommand: %s already defined\n", cmd_name);
-                               return;
-                       }
-                       else    //[515]: csqc
-                       {
-                               cmd->csqcfunc = true;
-                               return;
-                       }
-               }
+               // command already defined...
+               if (function)
+                       Con_Printf("Cmd_AddCommand: %s already defined\n", cmd_name);
+               else    //[515]: csqc
+                       func->csqcfunc = true;
        }
+       else
+       {
+               func = (cmd_function_t *)Mem_Alloc(cmd->mempool, sizeof(cmd_function_t));
+               func->name = cmd_name;
+               func->function = function;
+               func->description = description;
+               if (!function)                  //[515]: csqc
+                       func->csqcfunc = true;
+               func->next = cmd->functions;
 
-       cmd = (cmd_function_t *)Mem_Alloc(cmd_mempool, sizeof(cmd_function_t));
-       cmd->name = cmd_name;
-       cmd->consolefunction = consolefunction;
-       cmd->clientfunction = clientfunction;
-       cmd->description = description;
-       if(!consolefunction && !clientfunction)                 //[515]: csqc
-               cmd->csqcfunc = true;
-       cmd->next = cmd_functions;
-
-// insert it at the right alphanumeric position
-       for( prev = NULL, current = cmd_functions ; current && strcmp( current->name, cmd->name ) < 0 ; prev = current, current = current->next )
-               ;
-       if( prev ) {
-               prev->next = cmd;
-       } else {
-               cmd_functions = cmd;
+               // insert it at the right alphanumeric position
+               for (prev = NULL, current = cmd->functions; current && strcmp(current->name, func->name) < 0; prev = current, current = current->next)
+                       ;
+               if (prev) {
+                       prev->next = func;
+               }
+               else {
+                       cmd->functions = func;
+               }
+               func->next = current;
        }
-       cmd->next = current;
-}
-
-void Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *description)
-{
-       Cmd_AddCommand_WithClientCommand (cmd_name, function, NULL, description);
 }
 
 /*
@@ -1691,12 +1703,12 @@ void Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *desc
 Cmd_Exists
 ============
 */
-qboolean Cmd_Exists (const char *cmd_name)
+qboolean Cmd_Exists (cmd_state_t *cmd, const char *cmd_name)
 {
-       cmd_function_t  *cmd;
+       cmd_function_t  *func;
 
-       for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
-               if (!strcmp (cmd_name,cmd->name))
+       for (func=cmd->functions ; func ; func=func->next)
+               if (!strcmp (cmd_name,func->name))
                        return true;
 
        return false;
@@ -1708,9 +1720,9 @@ qboolean Cmd_Exists (const char *cmd_name)
 Cmd_CompleteCommand
 ============
 */
-const char *Cmd_CompleteCommand (const char *partial)
+const char *Cmd_CompleteCommand (cmd_state_t *cmd, const char *partial)
 {
-       cmd_function_t *cmd;
+       cmd_function_t *func;
        size_t len;
 
        len = strlen(partial);
@@ -1719,9 +1731,9 @@ const char *Cmd_CompleteCommand (const char *partial)
                return NULL;
 
 // check functions
-       for (cmd = cmd_functions; cmd; cmd = cmd->next)
-               if (!strncasecmp(partial, cmd->name, len))
-                       return cmd->name;
+       for (func = cmd->functions; func; func = func->next)
+               if (!strncasecmp(partial, func->name, len))
+                       return func->name;
 
        return NULL;
 }
@@ -1735,9 +1747,9 @@ const char *Cmd_CompleteCommand (const char *partial)
        Thanks to taniwha
 
 */
-int Cmd_CompleteCountPossible (const char *partial)
+int Cmd_CompleteCountPossible (cmd_state_t *cmd, const char *partial)
 {
-       cmd_function_t *cmd;
+       cmd_function_t *func;
        size_t len;
        int h;
 
@@ -1748,8 +1760,8 @@ int Cmd_CompleteCountPossible (const char *partial)
                return 0;
 
        // Loop through the command list and count all partial matches
-       for (cmd = cmd_functions; cmd; cmd = cmd->next)
-               if (!strncasecmp(partial, cmd->name, len))
+       for (func = cmd->functions; func; func = func->next)
+               if (!strncasecmp(partial, func->name, len))
                        h++;
 
        return h;
@@ -1764,34 +1776,34 @@ int Cmd_CompleteCountPossible (const char *partial)
        Thanks to taniwha
 
 */
-const char **Cmd_CompleteBuildList (const char *partial)
+const char **Cmd_CompleteBuildList (cmd_state_t *cmd, const char *partial)
 {
-       cmd_function_t *cmd;
+       cmd_function_t *func;
        size_t len = 0;
        size_t bpos = 0;
-       size_t sizeofbuf = (Cmd_CompleteCountPossible (partial) + 1) * sizeof (const char *);
+       size_t sizeofbuf = (Cmd_CompleteCountPossible (cmd, partial) + 1) * sizeof (const char *);
        const char **buf;
 
        len = strlen(partial);
        buf = (const char **)Mem_Alloc(tempmempool, sizeofbuf + sizeof (const char *));
        // Loop through the alias list and print all matches
-       for (cmd = cmd_functions; cmd; cmd = cmd->next)
-               if (!strncasecmp(partial, cmd->name, len))
-                       buf[bpos++] = cmd->name;
+       for (func = cmd->functions; func; func = func->next)
+               if (!strncasecmp(partial, func->name, len))
+                       buf[bpos++] = func->name;
 
        buf[bpos] = NULL;
        return buf;
 }
 
 // written by LadyHavoc
-void Cmd_CompleteCommandPrint (const char *partial)
+void Cmd_CompleteCommandPrint (cmd_state_t *cmd, const char *partial)
 {
-       cmd_function_t *cmd;
+       cmd_function_t *func;
        size_t len = strlen(partial);
        // Loop through the command list and print all matches
-       for (cmd = cmd_functions; cmd; cmd = cmd->next)
-               if (!strncasecmp(partial, cmd->name, len))
-                       Con_Printf("^2%s^7: %s\n", cmd->name, cmd->description);
+       for (func = cmd->functions; func; func = func->next)
+               if (!strncasecmp(partial, func->name, len))
+                       Con_Printf("^2%s^7: %s\n", func->name, func->description);
 }
 
 /*
@@ -1803,7 +1815,7 @@ void Cmd_CompleteCommandPrint (const char *partial)
        Thanks to taniwha
 
 */
-const char *Cmd_CompleteAlias (const char *partial)
+const char *Cmd_CompleteAlias (cmd_state_t *cmd, const char *partial)
 {
        cmdalias_t *alias;
        size_t len;
@@ -1814,7 +1826,7 @@ const char *Cmd_CompleteAlias (const char *partial)
                return NULL;
 
        // Check functions
-       for (alias = cmd_alias; alias; alias = alias->next)
+       for (alias = cmd->alias; alias; alias = alias->next)
                if (!strncasecmp(partial, alias->name, len))
                        return alias->name;
 
@@ -1822,12 +1834,12 @@ const char *Cmd_CompleteAlias (const char *partial)
 }
 
 // written by LadyHavoc
-void Cmd_CompleteAliasPrint (const char *partial)
+void Cmd_CompleteAliasPrint (cmd_state_t *cmd, const char *partial)
 {
        cmdalias_t *alias;
        size_t len = strlen(partial);
        // Loop through the alias list and print all matches
-       for (alias = cmd_alias; alias; alias = alias->next)
+       for (alias = cmd->alias; alias; alias = alias->next)
                if (!strncasecmp(partial, alias->name, len))
                        Con_Printf("^5%s^7: %s", alias->name, alias->value);
 }
@@ -1842,7 +1854,7 @@ void Cmd_CompleteAliasPrint (const char *partial)
        Thanks to taniwha
 
 */
-int Cmd_CompleteAliasCountPossible (const char *partial)
+int Cmd_CompleteAliasCountPossible (cmd_state_t *cmd, const char *partial)
 {
        cmdalias_t      *alias;
        size_t          len;
@@ -1856,7 +1868,7 @@ int Cmd_CompleteAliasCountPossible (const char *partial)
                return 0;
 
        // Loop through the command list and count all partial matches
-       for (alias = cmd_alias; alias; alias = alias->next)
+       for (alias = cmd->alias; alias; alias = alias->next)
                if (!strncasecmp(partial, alias->name, len))
                        h++;
 
@@ -1872,18 +1884,18 @@ int Cmd_CompleteAliasCountPossible (const char *partial)
        Thanks to taniwha
 
 */
-const char **Cmd_CompleteAliasBuildList (const char *partial)
+const char **Cmd_CompleteAliasBuildList (cmd_state_t *cmd, const char *partial)
 {
        cmdalias_t *alias;
        size_t len = 0;
        size_t bpos = 0;
-       size_t sizeofbuf = (Cmd_CompleteAliasCountPossible (partial) + 1) * sizeof (const char *);
+       size_t sizeofbuf = (Cmd_CompleteAliasCountPossible (cmd, partial) + 1) * sizeof (const char *);
        const char **buf;
 
        len = strlen(partial);
        buf = (const char **)Mem_Alloc(tempmempool, sizeofbuf + sizeof (const char *));
        // Loop through the alias list and print all matches
-       for (alias = cmd_alias; alias; alias = alias->next)
+       for (alias = cmd->alias; alias; alias = alias->next)
                if (!strncasecmp(partial, alias->name, len))
                        buf[bpos++] = alias->name;
 
@@ -1891,11 +1903,11 @@ const char **Cmd_CompleteAliasBuildList (const char *partial)
        return buf;
 }
 
-void Cmd_ClearCsqcFuncs (void)
+void Cmd_ClearCsqcFuncs (cmd_state_t *cmd)
 {
-       cmd_function_t *cmd;
-       for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
-               cmd->csqcfunc = false;
+       cmd_function_t *func;
+       for (func = cmd->functions; func; func = func->next)
+               func->csqcfunc = false;
 }
 
 /*
@@ -1906,91 +1918,73 @@ A complete command line has been parsed, so try to execute it
 FIXME: lookupnoadd the token to speed search?
 ============
 */
-void Cmd_ExecuteString (const char *text, cmd_source_t src, qboolean lockmutex)
+void Cmd_ExecuteString (cmd_state_t *cmd, const char *text, cmd_source_t src, qboolean lockmutex)
 {
        int oldpos;
-       int found;
-       cmd_function_t *cmd;
+       cmd_function_t *func;
        cmdalias_t *a;
        if (lockmutex)
-               Cbuf_LockThreadMutex();
-       oldpos = cmd_tokenizebufferpos;
-       cmd_source = src;
-       found = false;
+               Cbuf_Lock(cmd);
+       oldpos = cmd->tokenizebufferpos;
+       cmd->source = src;
 
-       Cmd_TokenizeString (text);
+       Cmd_TokenizeString (cmd, text);
 
 // execute the command line
-       if (!Cmd_Argc())
+       if (!Cmd_Argc(cmd))
                goto done; // no tokens
 
 // check functions
-       for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
+       for (func = cmd->functions; func; func=func->next)
        {
-               if (!strcasecmp (cmd_argv[0],cmd->name))
+               if (!strcasecmp (cmd->argv[0], func->name))
                {
-                       if (cmd->csqcfunc && CL_VM_ConsoleCommand (text))       //[515]: csqc
+                       if (func->csqcfunc && CL_VM_ConsoleCommand (text))      //[515]: csqc
                                goto done;
                        switch (src)
                        {
                        case src_command:
-                               if (cmd->consolefunction)
-                                       cmd->consolefunction ();
-                               else if (cmd->clientfunction)
-                               {
-                                       if (cls.state == ca_connected)
-                                       {
-                                               // forward remote commands to the server for execution
-                                               Cmd_ForwardToServer();
-                                       }
-                                       else
-                                               Con_Printf("Can not send command \"%s\", not connected.\n", Cmd_Argv(0));
-                               }
+                               if (func->function)
+                                       func->function(cmd);
                                else
-                                       Con_Printf("Command \"%s\" can not be executed\n", Cmd_Argv(0));
-                               found = true;
-                               goto command_found;
+                                       Con_Printf("Command \"%s\" can not be executed\n", Cmd_Argv(cmd, 0));
+                               goto done;
                        case src_client:
-                               if (cmd->clientfunction)
+                               if (func->function)
                                {
-                                       cmd->clientfunction ();
+                                       func->function(cmd);
                                        goto done;
                                }
-                               break;
                        }
                        break;
                }
        }
-command_found:
 
        // if it's a client command and no command was found, say so.
-       if (cmd_source == src_client)
+       if (cmd->source == src_client)
        {
                Con_Printf("player \"%s\" tried to %s\n", host_client->name, text);
                goto done;
        }
 
 // check alias
-       for (a=cmd_alias ; a ; a=a->next)
+       for (a=cmd->alias ; a ; a=a->next)
        {
-               if (!strcasecmp (cmd_argv[0], a->name))
+               if (!strcasecmp (cmd->argv[0], a->name))
                {
-                       Cmd_ExecuteAlias(a);
+                       Cmd_ExecuteAlias(cmd, a);
                        goto done;
                }
        }
 
-       if(found) // if the command was hooked and found, all is good
-               goto done;
-
 // check cvars
-       if (!Cvar_Command () && host_framecount > 0)
-               Con_Printf("Unknown command \"%s\"\n", Cmd_Argv(0));
+       if (!Cvar_Command (cmd) && host_framecount > 0)
+               Con_Printf("Unknown command \"%s\"\n", Cmd_Argv(cmd, 0));
 
 done:
-       cmd_tokenizebufferpos = oldpos;
+       cmd->tokenizebufferpos = oldpos;
        if (lockmutex)
-               Cbuf_UnlockThreadMutex();
+               Cbuf_Unlock(cmd);
 }
 
 
@@ -2128,19 +2122,19 @@ Cmd_ForwardToServer
 Sends the entire command line over to the server
 ===================
 */
-void Cmd_ForwardToServer (void)
+void Cmd_ForwardToServer_f (cmd_state_t *cmd)
 {
        const char *s;
        char vabuf[1024];
-       if (!strcasecmp(Cmd_Argv(0), "cmd"))
+       if (!strcasecmp(Cmd_Argv(cmd, 0), "cmd"))
        {
                // we want to strip off "cmd", so just send the args
-               s = Cmd_Argc() > 1 ? Cmd_Args() : "";
+               s = Cmd_Argc(cmd) > 1 ? Cmd_Args(cmd) : "";
        }
        else
        {
-               // we need to keep the command name, so send Cmd_Argv(0), a space and then Cmd_Args()
-               s = va(vabuf, sizeof(vabuf), "%s %s", Cmd_Argv(0), Cmd_Argc() > 1 ? Cmd_Args() : "");
+               // we need to keep the command name, so send Cmd_Argv(cmd, 0), a space and then Cmd_Args(cmd)
+               s = va(vabuf, sizeof(vabuf), "%s %s", Cmd_Argv(cmd, 0), Cmd_Argc(cmd) > 1 ? Cmd_Args(cmd) : "");
        }
        // don't send an empty forward message if the user tries "cmd" by itself
        if (!s || !*s)
@@ -2158,7 +2152,7 @@ where the given parameter apears, or 0 if not present
 ================
 */
 
-int Cmd_CheckParm (const char *parm)
+int Cmd_CheckParm (cmd_state_t *cmd, const char *parm)
 {
        int i;
 
@@ -2168,8 +2162,8 @@ int Cmd_CheckParm (const char *parm)
                return 0;
        }
 
-       for (i = 1; i < Cmd_Argc (); i++)
-               if (!strcasecmp (parm, Cmd_Argv (i)))
+       for (i = 1; i < Cmd_Argc (cmd); i++)
+               if (!strcasecmp (parm, Cmd_Argv(cmd, i)))
                        return i;
 
        return 0;
@@ -2179,56 +2173,66 @@ int Cmd_CheckParm (const char *parm)
 
 void Cmd_SaveInitState(void)
 {
-       cmd_function_t *f;
-       cmdalias_t *a;
-       for (f = cmd_functions;f;f = f->next)
-               f->initstate = true;
-       for (a = cmd_alias;a;a = a->next)
+       cmd_iter_t *cmd_iter;
+       for (cmd_iter = cmd_iter_all; cmd_iter->cmd; cmd_iter++)
        {
-               a->initstate = true;
-               a->initialvalue = Mem_strdup(zonemempool, a->value);
+               cmd_state_t *cmd = cmd_iter->cmd;
+               cmd_function_t *f;
+               cmdalias_t *a;
+               for (f = cmd->functions; f; f = f->next)
+                       f->initstate = true;
+               for (a = cmd->alias; a; a = a->next)
+               {
+                       a->initstate = true;
+                       a->initialvalue = Mem_strdup(zonemempool, a->value);
+               }
        }
        Cvar_SaveInitState();
 }
 
 void Cmd_RestoreInitState(void)
 {
-       cmd_function_t *f, **fp;
-       cmdalias_t *a, **ap;
-       for (fp = &cmd_functions;(f = *fp);)
+       cmd_iter_t *cmd_iter;
+       for (cmd_iter = cmd_iter_all; cmd_iter->cmd; cmd_iter++)
        {
-               if (f->initstate)
-                       fp = &f->next;
-               else
+               cmd_state_t *cmd = cmd_iter->cmd;
+               cmd_function_t *f, **fp;
+               cmdalias_t *a, **ap;
+               for (fp = &cmd->functions; (f = *fp);)
                {
-                       // destroy this command, it didn't exist at init
-                       Con_DPrintf("Cmd_RestoreInitState: Destroying command %s\n", f->name);
-                       *fp = f->next;
-                       Z_Free(f);
+                       if (f->initstate)
+                               fp = &f->next;
+                       else
+                       {
+                               // destroy this command, it didn't exist at init
+                               Con_DPrintf("Cmd_RestoreInitState: Destroying command %s\n", f->name);
+                               *fp = f->next;
+                               Z_Free(f);
+                       }
                }
-       }
-       for (ap = &cmd_alias;(a = *ap);)
-       {
-               if (a->initstate)
+               for (ap = &cmd->alias; (a = *ap);)
                {
-                       // restore this alias, it existed at init
-                       if (strcmp(a->value ? a->value : "", a->initialvalue ? a->initialvalue : ""))
+                       if (a->initstate)
+                       {
+                               // restore this alias, it existed at init
+                               if (strcmp(a->value ? a->value : "", a->initialvalue ? a->initialvalue : ""))
+                               {
+                                       Con_DPrintf("Cmd_RestoreInitState: Restoring alias %s\n", a->name);
+                                       if (a->value)
+                                               Z_Free(a->value);
+                                       a->value = Mem_strdup(zonemempool, a->initialvalue);
+                               }
+                               ap = &a->next;
+                       }
+                       else
                        {
-                               Con_DPrintf("Cmd_RestoreInitState: Restoring alias %s\n", a->name);
+                               // free this alias, it didn't exist at init...
+                               Con_DPrintf("Cmd_RestoreInitState: Destroying alias %s\n", a->name);
+                               *ap = a->next;
                                if (a->value)
                                        Z_Free(a->value);
-                               a->value = Mem_strdup(zonemempool, a->initialvalue);
+                               Z_Free(a);
                        }
-                       ap = &a->next;
-               }
-               else
-               {
-                       // free this alias, it didn't exist at init...
-                       Con_DPrintf("Cmd_RestoreInitState: Destroying alias %s\n", a->name);
-                       *ap = a->next;
-                       if (a->value)
-                               Z_Free(a->value);
-                       Z_Free(a);
                }
        }
        Cvar_RestoreInitState();
diff --git a/cmd.h b/cmd.h
index bb1a84f..c08d92c 100644 (file)
--- a/cmd.h
+++ b/cmd.h
@@ -37,36 +37,107 @@ The game starts with a Cbuf_AddText ("exec quake.rc\n"); Cbuf_Execute ();
 #ifndef CMD_H
 #define CMD_H
 
-extern void *cmd_text_mutex;
-#define Cbuf_LockThreadMutex() (void)(cmd_text_mutex ? Thread_LockMutex(cmd_text_mutex) : 0)
-#define Cbuf_UnlockThreadMutex() (void)(cmd_text_mutex ? Thread_UnlockMutex(cmd_text_mutex) : 0)
+#include "thread.h"
 
-/// allocates an initial text buffer that will grow as needed
-void Cbuf_Init (void);
+struct cmd_state_s;
 
-void Cmd_Init_Commands (void);
+typedef void(*xcommand_t) (struct cmd_state_s *cmd);
 
-void Cbuf_Shutdown (void);
+typedef enum
+{
+       src_client,             ///< came in over a net connection as a clc_stringcmd
+                                       ///< host_client will be valid during this state.
+       src_command             ///< from the command buffer
+} cmd_source_t;
+
+typedef struct cmdalias_s
+{
+       struct cmdalias_s *next;
+       char name[MAX_ALIAS_NAME];
+       char *value;
+       qboolean initstate; // indicates this command existed at init
+       char *initialvalue; // backup copy of value at init
+} cmdalias_t;
+
+typedef struct cmd_function_s
+{
+       struct cmd_function_s *next;
+       const char *name;
+       const char *description;
+       xcommand_t function;
+       qboolean csqcfunc;
+       qboolean initstate; // indicates this command existed at init
+} cmd_function_t;
+
+typedef struct cmddeferred_s
+{
+       struct cmddeferred_s *next;
+       char *value;
+       double delay;
+} cmddeferred_t;
+
+typedef struct cmd_state_s
+{
+       cmdalias_t *alias;
+
+       qboolean wait;
+
+       mempool_t *mempool;
+
+       char tokenizebuffer[CMD_TOKENIZELENGTH];
+       int tokenizebufferpos;
+
+       cmddeferred_t *deferred_list;
+
+       sizebuf_t text;
+       unsigned char text_buf[CMDBUFSIZE];
+       Thread_SpinLock text_lock;
+
+       int argc;
+       const char *argv[MAX_ARGS];
+       const char *null_string;
+       const char *args;
+       cmd_source_t source;
+
+       cmd_function_t *functions;              // possible commands to execute
+}
+cmd_state_t;
+
+// command interpreter for client commands injected by CSQC, MQC or client engine code
+extern cmd_state_t cmd_client;
+// command interpreter for client commands received over network from server
+extern cmd_state_t cmd_clientfromserver;
+// command interpreter for server commands injected by MQC, SVQC, menu engine code or server engine code
+extern cmd_state_t cmd_server;
+// command interpreter for server commands received over network from clients
+extern cmd_state_t cmd_serverfromclient;
+
+extern qboolean host_stuffcmdsrun;
+
+void Cbuf_Lock(cmd_state_t *cmd);
+void Cbuf_Unlock(cmd_state_t *cmd);
+
+void Cmd_Init_Commands(qboolean dedicated_server);
 
 /*! as new commands are generated from the console or keybindings,
  * the text is added to the end of the command buffer.
  */
-void Cbuf_AddText (const char *text);
+void Cbuf_AddText (cmd_state_t *cmd, const char *text);
 
 /*! when a command wants to issue other commands immediately, the text is
  * inserted at the beginning of the buffer, before any remaining unexecuted
  * commands.
  */
-void Cbuf_InsertText (const char *text);
+void Cbuf_InsertText (cmd_state_t *cmd, const char *text);
 
 /*! Pulls off terminated lines of text from the command buffer and sends
  * them through Cmd_ExecuteString.  Stops when the buffer is empty.
  * Normally called once per frame, but may be explicitly invoked.
  * \note Do not call inside a command function!
  */
-void Cbuf_Execute (void);
+void Cbuf_Execute (cmd_state_t *cmd);
 /*! Performs deferred commands and runs Cbuf_Execute, called by Host_Main */
-void Cbuf_Frame (void);
+void Cbuf_Frame (cmd_state_t *cmd);
 
 //===========================================================================
 
@@ -81,66 +152,54 @@ not apropriate.
 
 */
 
-typedef void (*xcommand_t) (void);
-
-typedef enum
-{
-       src_client,             ///< came in over a net connection as a clc_stringcmd
-                                       ///< host_client will be valid during this state.
-       src_command             ///< from the command buffer
-} cmd_source_t;
-
-extern cmd_source_t cmd_source;
-
-void Cmd_Init (void);
-void Cmd_Shutdown (void);
+void Cmd_Init(void);
+void Cmd_Shutdown(void);
 
 // called by Host_Init, this marks cvars, commands and aliases with their init values
-void Cmd_SaveInitState (void);
+void Cmd_SaveInitState(void);
 // called by FS_GameDir_f, this restores cvars, commands and aliases to init values
-void Cmd_RestoreInitState (void);
+void Cmd_RestoreInitState(void);
 
-void Cmd_AddCommand_WithClientCommand (const char *cmd_name, xcommand_t consolefunction, xcommand_t clientfunction, const char *description);
-void Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *description);
+void Cmd_AddCommand(cmd_state_t *cmd, const char *cmd_name, xcommand_t function, const char *description);
 // called by the init functions of other parts of the program to
 // register commands and functions to call for them.
 // The cmd_name is referenced later, so it should not be in temp memory
 
 /// used by the cvar code to check for cvar / command name overlap
-qboolean Cmd_Exists (const char *cmd_name);
+qboolean Cmd_Exists (cmd_state_t *cmd, const char *cmd_name);
 
 /// attempts to match a partial command for automatic command line completion
 /// returns NULL if nothing fits
-const char *Cmd_CompleteCommand (const char *partial);
+const char *Cmd_CompleteCommand (cmd_state_t *cmd, const char *partial);
 
-int Cmd_CompleteAliasCountPossible (const char *partial);
+int Cmd_CompleteAliasCountPossible (cmd_state_t *cmd, const char *partial);
 
-const char **Cmd_CompleteAliasBuildList (const char *partial);
+const char **Cmd_CompleteAliasBuildList (cmd_state_t *cmd, const char *partial);
 
-int Cmd_CompleteCountPossible (const char *partial);
+int Cmd_CompleteCountPossible (cmd_state_t *cmd, const char *partial);
 
-const char **Cmd_CompleteBuildList (const char *partial);
+const char **Cmd_CompleteBuildList (cmd_state_t *cmd, const char *partial);
 
-void Cmd_CompleteCommandPrint (const char *partial);
+void Cmd_CompleteCommandPrint (cmd_state_t *cmd, const char *partial);
 
-const char *Cmd_CompleteAlias (const char *partial);
+const char *Cmd_CompleteAlias (cmd_state_t *cmd, const char *partial);
 
-void Cmd_CompleteAliasPrint (const char *partial);
+void Cmd_CompleteAliasPrint (cmd_state_t *cmd, const char *partial);
 
 // Enhanced console completion by Fett erich@heintz.com
 
 // Added by EvilTypeGuy eviltypeguy@qeradiant.com
 
-int Cmd_Argc (void);
-const char *Cmd_Argv (int arg);
-const char *Cmd_Args (void);
+int Cmd_Argc (cmd_state_t *cmd);
+const char *Cmd_Argv (cmd_state_t *cmd, int arg);
+const char *Cmd_Args (cmd_state_t *cmd);
 // The functions that execute commands get their parameters with these
-// functions. Cmd_Argv () will return an empty string, not a NULL
+// functions. Cmd_Argv(cmd, ) will return an empty string, not a NULL
 // if arg > argc, so string operations are always safe.
 
 /// Returns the position (1 to argc-1) in the command's argument list
 /// where the given parameter apears, or 0 if not present
-int Cmd_CheckParm (const char *parm);
+int Cmd_CheckParm (cmd_state_t *cmd, const char *parm);
 
 //void Cmd_TokenizeString (char *text);
 // Takes a null terminated string.  Does not need to be /n terminated.
@@ -148,7 +207,7 @@ int Cmd_CheckParm (const char *parm);
 
 /// Parses a single line of text into arguments and tries to execute it.
 /// The text can come from the command buffer, a remote client, or stdin.
-void Cmd_ExecuteString (const char *text, cmd_source_t src, qboolean lockmutex);
+void Cmd_ExecuteString (cmd_state_t *cmd, const char *text, cmd_source_t src, qboolean lockmutex);
 
 /// adds the string as a clc_stringcmd to the client message.
 /// (used when there is no reason to generate a local command to do it)
@@ -157,11 +216,7 @@ void Cmd_ForwardStringToServer (const char *s);
 /// adds the current command line as a clc_stringcmd to the client message.
 /// things like godmode, noclip, etc, are commands directed to the server,
 /// so when they are typed in at the console, they will need to be forwarded.
-void Cmd_ForwardToServer (void);
-
-/// used by command functions to send output to either the graphics console or
-/// passed as a print message to the client
-void Cmd_Print(const char *text);
+void Cmd_ForwardToServer_f (cmd_state_t *cmd);
 
 /// quotes a string so that it can be used as a command argument again;
 /// quoteset is a string that contains one or more of ", \, $ and specifies
@@ -171,7 +226,7 @@ void Cmd_Print(const char *text);
 /// enclosing quote marks are also put.
 qboolean Cmd_QuoteString(char *out, size_t outlen, const char *in, const char *quoteset, qboolean putquotes);
 
-void Cmd_ClearCsqcFuncs (void);
+void Cmd_ClearCsqcFuncs (cmd_state_t *cmd);
 
 #endif
 
index 2b9baa6..dcbceca 100644 (file)
--- a/console.c
+++ b/console.c
@@ -677,7 +677,7 @@ CONSOLE
 Con_ToggleConsole_f
 ================
 */
-void Con_ToggleConsole_f (void)
+void Con_ToggleConsole_f(cmd_state_t *cmd)
 {
        if (COM_CheckParm ("-noconsole"))
                if (!(key_consoleactive & KEY_CONSOLEACTIVE_USER))
@@ -707,13 +707,13 @@ void Con_ClearNotify (void)
 Con_MessageMode_f
 ================
 */
-static void Con_MessageMode_f (void)
+static void Con_MessageMode_f(cmd_state_t *cmd)
 {
        key_dest = key_message;
        chat_mode = 0; // "say"
-       if(Cmd_Argc() > 1)
+       if(Cmd_Argc(cmd) > 1)
        {
-               dpsnprintf(chat_buffer, sizeof(chat_buffer), "%s ", Cmd_Args());
+               dpsnprintf(chat_buffer, sizeof(chat_buffer), "%s ", Cmd_Args(cmd));
                chat_bufferlen = (unsigned int)strlen(chat_buffer);
        }
 }
@@ -724,13 +724,13 @@ static void Con_MessageMode_f (void)
 Con_MessageMode2_f
 ================
 */
-static void Con_MessageMode2_f (void)
+static void Con_MessageMode2_f(cmd_state_t *cmd)
 {
        key_dest = key_message;
        chat_mode = 1; // "say_team"
-       if(Cmd_Argc() > 1)
+       if(Cmd_Argc(cmd) > 1)
        {
-               dpsnprintf(chat_buffer, sizeof(chat_buffer), "%s ", Cmd_Args());
+               dpsnprintf(chat_buffer, sizeof(chat_buffer), "%s ", Cmd_Args(cmd));
                chat_bufferlen = (unsigned int)strlen(chat_buffer);
        }
 }
@@ -740,12 +740,12 @@ static void Con_MessageMode2_f (void)
 Con_CommandMode_f
 ================
 */
-static void Con_CommandMode_f (void)
+static void Con_CommandMode_f(cmd_state_t *cmd)
 {
        key_dest = key_message;
-       if(Cmd_Argc() > 1)
+       if(Cmd_Argc(cmd) > 1)
        {
-               dpsnprintf(chat_buffer, sizeof(chat_buffer), "%s ", Cmd_Args());
+               dpsnprintf(chat_buffer, sizeof(chat_buffer), "%s ", Cmd_Args(cmd));
                chat_bufferlen = (unsigned int)strlen(chat_buffer);
        }
        chat_mode = -1; // command
@@ -782,32 +782,32 @@ void Con_CheckResize (void)
 
 //[515]: the simplest command ever
 //LadyHavoc: not so simple after I made it print usage...
-static void Con_Maps_f (void)
+static void Con_Maps_f(cmd_state_t *cmd)
 {
-       if (Cmd_Argc() > 2)
+       if (Cmd_Argc(cmd) > 2)
        {
                Con_Printf("usage: maps [mapnameprefix]\n");
                return;
        }
-       else if (Cmd_Argc() == 2)
-               GetMapList(Cmd_Argv(1), NULL, 0);
+       else if (Cmd_Argc(cmd) == 2)
+               GetMapList(Cmd_Argv(cmd, 1), NULL, 0);
        else
                GetMapList("", NULL, 0);
 }
 
-static void Con_ConDump_f (void)
+static void Con_ConDump_f(cmd_state_t *cmd)
 {
        int i;
        qfile_t *file;
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
                Con_Printf("usage: condump <filename>\n");
                return;
        }
-       file = FS_OpenRealFile(Cmd_Argv(1), "w", false);
+       file = FS_OpenRealFile(Cmd_Argv(cmd, 1), "w", false);
        if (!file)
        {
-               Con_Printf("condump: unable to write file \"%s\"\n", Cmd_Argv(1));
+               Con_Printf("condump: unable to write file \"%s\"\n", Cmd_Argv(cmd, 1));
                return;
        }
        if (con_mutex) Thread_LockMutex(con_mutex);
@@ -833,7 +833,7 @@ static void Con_ConDump_f (void)
        FS_Close(file);
 }
 
-void Con_Clear_f (void)
+void Con_Clear_f(cmd_state_t *cmd)
 {
        if (con_mutex) Thread_LockMutex(con_mutex);
        ConBuffer_Clear(&con);
@@ -896,13 +896,16 @@ void Con_Init (void)
        Cvar_RegisterVariable (&condump_stripcolors);
 
        // register our commands
-       Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f, "opens or closes the console");
-       Cmd_AddCommand ("messagemode", Con_MessageMode_f, "input a chat message to say to everyone");
-       Cmd_AddCommand ("messagemode2", Con_MessageMode2_f, "input a chat message to say to only your team");
-       Cmd_AddCommand ("commandmode", Con_CommandMode_f, "input a console command");
-       Cmd_AddCommand ("clear", Con_Clear_f, "clear console history");
-       Cmd_AddCommand ("maps", Con_Maps_f, "list information about available maps");
-       Cmd_AddCommand ("condump", Con_ConDump_f, "output console history to a file (see also log_file)");
+       Cmd_AddCommand(&cmd_client, "toggleconsole", Con_ToggleConsole_f, "opens or closes the console");
+       Cmd_AddCommand(&cmd_client, "messagemode", Con_MessageMode_f, "input a chat message to say to everyone");
+       Cmd_AddCommand(&cmd_client, "messagemode2", Con_MessageMode2_f, "input a chat message to say to only your team");
+       Cmd_AddCommand(&cmd_client, "commandmode", Con_CommandMode_f, "input a console command");
+       Cmd_AddCommand(&cmd_client, "clear", Con_Clear_f, "clear console history");
+       Cmd_AddCommand(&cmd_client, "maps", Con_Maps_f, "list information about available maps");
+       Cmd_AddCommand(&cmd_client, "condump", Con_ConDump_f, "output console history to a file (see also log_file)");
+
+       Cmd_AddCommand(&cmd_server, "maps", Con_Maps_f, "list information about available maps");
+       Cmd_AddCommand(&cmd_server, "condump", Con_ConDump_f, "output console history to a file (see also log_file)");
 
        con_initialized = true;
        Con_DPrint("Console initialized.\n");
@@ -2737,9 +2740,9 @@ int Nicks_CompleteChatLine(char *buffer, size_t size, unsigned int pos)
        Enhanced to tab-complete map names by [515]
 
 */
-void Con_CompleteCommandLine (void)
+void Con_CompleteCommandLine (cmd_state_t *cmd)
 {
-       const char *cmd = "";
+       const char *text = "";
        char *s;
        const char **list[4] = {0, 0, 0, 0};
        char s2[512];
@@ -2939,11 +2942,11 @@ void Con_CompleteCommandLine (void)
        }
 
        // Count number of possible matches and print them
-       c = Cmd_CompleteCountPossible(s);
+       c = Cmd_CompleteCountPossible(cmd, s);
        if (c)
        {
                Con_Printf("\n%i possible command%s\n", c, (c > 1) ? "s: " : ":");
-               Cmd_CompleteCommandPrint(s);
+               Cmd_CompleteCommandPrint(cmd, s);
        }
        v = Cvar_CompleteCountPossible(s);
        if (v)
@@ -2951,11 +2954,11 @@ void Con_CompleteCommandLine (void)
                Con_Printf("\n%i possible variable%s\n", v, (v > 1) ? "s: " : ":");
                Cvar_CompleteCvarPrint(s);
        }
-       a = Cmd_CompleteAliasCountPossible(s);
+       a = Cmd_CompleteAliasCountPossible(cmd, s);
        if (a)
        {
                Con_Printf("\n%i possible alias%s\n", a, (a > 1) ? "es: " : ":");
-               Cmd_CompleteAliasPrint(s);
+               Cmd_CompleteAliasPrint(cmd, s);
        }
        n = Nicks_CompleteCountPossible(key_line, key_linepos, s, true);
        if (n)
@@ -2972,13 +2975,13 @@ void Con_CompleteCommandLine (void)
        }
 
        if (c)
-               cmd = *(list[0] = Cmd_CompleteBuildList(s));
+               text = *(list[0] = Cmd_CompleteBuildList(cmd, s));
        if (v)
-               cmd = *(list[1] = Cvar_CompleteBuildList(s));
+               text = *(list[1] = Cvar_CompleteBuildList(s));
        if (a)
-               cmd = *(list[2] = Cmd_CompleteAliasBuildList(s));
+               text = *(list[2] = Cmd_CompleteAliasBuildList(cmd, s));
        if (n)
-               cmd = *(list[3] = Nicks_CompleteBuildList(n));
+               text = *(list[3] = Nicks_CompleteBuildList(n));
 
        for (cmd_len = (int)strlen(s);;cmd_len++)
        {
@@ -2986,10 +2989,10 @@ void Con_CompleteCommandLine (void)
                for (i = 0; i < 3; i++)
                        if (list[i])
                                for (l = list[i];*l;l++)
-                                       if ((*l)[cmd_len] != cmd[cmd_len])
+                                       if ((*l)[cmd_len] != text[cmd_len])
                                                goto done;
                // all possible matches share this character, so we continue...
-               if (!cmd[cmd_len])
+               if (!text[cmd_len])
                {
                        // if all matches ended at the same position, stop
                        // (this means there is only one match)
@@ -3000,10 +3003,10 @@ done:
 
        // prevent a buffer overrun by limiting cmd_len according to remaining space
        cmd_len = min(cmd_len, (int)sizeof(key_line) - 1 - pos);
-       if (cmd)
+       if (text)
        {
                key_linepos = pos;
-               memcpy(&key_line[key_linepos], cmd, cmd_len);
+               memcpy(&key_line[key_linepos], text, cmd_len);
                key_linepos += cmd_len;
                // if there is only one match, add a space after it
                if (c + v + a + n == 1 && key_linepos < (int)sizeof(key_line) - 1)
index 860c501..35ce4dc 100644 (file)
--- a/console.h
+++ b/console.h
@@ -56,12 +56,12 @@ void Con_DPrint(const char *msg);
 
 /// A Con_Printf that only shows up if the "developer" cvar is set
 void Con_DPrintf(const char *fmt, ...) DP_FUNC_PRINTF(1);
-void Con_Clear_f (void);
+void Con_Clear_f(cmd_state_t *cmd);
 void Con_DrawNotify (void);
 
 /// Clear all notify lines.
 void Con_ClearNotify (void);
-void Con_ToggleConsole_f (void);
+void Con_ToggleConsole_f(cmd_state_t *cmd);
 
 int Nicks_CompleteChatLine(char *buffer, size_t size, unsigned int pos);
 
@@ -71,7 +71,7 @@ qboolean GetMapList (const char *s, char *completedname, int completednamebuffer
 /// or to list possible matches grouped by type
 /// (i.e. will display possible variables, aliases, commands
 /// that match what they've typed so far)
-void Con_CompleteCommandLine(void);
+void Con_CompleteCommandLine(cmd_state_t *cmd);
 
 /// Generic libs/util/console.c function to display a list
 /// formatted in columns on the console
index 05d763d..db3288b 100644 (file)
--- a/crypto.c
+++ b/crypto.c
@@ -1193,7 +1193,7 @@ static void Crypto_KeyGen_Finished(int code, size_t length_received, unsigned ch
        SV_UnlockThreadMutex();
 }
 
-static void Crypto_KeyGen_f(void)
+static void Crypto_KeyGen_f(cmd_state_t *cmd)
 {
        int i;
        const char *p[1];
@@ -1211,14 +1211,14 @@ static void Crypto_KeyGen_f(void)
                Con_Print("libd0_blind_id DLL not found, this command is inactive.\n");
                return;
        }
-       if(Cmd_Argc() != 3)
+       if(Cmd_Argc(cmd) != 3)
        {
-               Con_Printf("usage:\n%s id url\n", Cmd_Argv(0));
+               Con_Printf("usage:\n%s id url\n", Cmd_Argv(cmd, 0));
                return;
        }
        SV_LockThreadMutex();
        Crypto_LoadKeys();
-       i = atoi(Cmd_Argv(1));
+       i = atoi(Cmd_Argv(cmd, 1));
        if(!pubkeys[i])
        {
                Con_Printf("there is no public key %d\n", i);
@@ -1318,8 +1318,8 @@ static void Crypto_KeyGen_f(void)
                SV_UnlockThreadMutex();
                return;
        }
-       buf2pos = strlen(Cmd_Argv(2));
-       memcpy(buf2, Cmd_Argv(2), buf2pos);
+       buf2pos = strlen(Cmd_Argv(cmd, 2));
+       memcpy(buf2, Cmd_Argv(cmd, 2), buf2pos);
        if(!(buf2l = Crypto_UnParsePack(buf2 + buf2pos, sizeof(buf2) - buf2pos - 1, FOURCC_D0IQ, p, l, 1)))
        {
                Con_Printf("Crypto_UnParsePack failed\n");
@@ -1349,14 +1349,14 @@ static void Crypto_KeyGen_f(void)
 // end
 
 // console commands
-static void Crypto_Reload_f(void)
+static void Crypto_Reload_f(cmd_state_t *cmd)
 {
        Crypto_ClearHostKeys();
        Crypto_UnloadKeys();
        Crypto_LoadKeys();
 }
 
-static void Crypto_Keys_f(void)
+static void Crypto_Keys_f(cmd_state_t *cmd)
 {
        int i;
        if(!d0_blind_id_dll)
@@ -1379,7 +1379,7 @@ static void Crypto_Keys_f(void)
        }
 }
 
-static void Crypto_HostKeys_f(void)
+static void Crypto_HostKeys_f(cmd_state_t *cmd)
 {
        int i;
        crypto_storedhostkey_t *hk;
@@ -1404,7 +1404,7 @@ static void Crypto_HostKeys_f(void)
        }
 }
 
-static void Crypto_HostKey_Clear_f(void)
+static void Crypto_HostKey_Clear_f(cmd_state_t *cmd)
 {
        lhnetaddress_t addr;
        int i;
@@ -1415,12 +1415,12 @@ static void Crypto_HostKey_Clear_f(void)
                return;
        }
 
-       for(i = 1; i < Cmd_Argc(); ++i)
+       for(i = 1; i < Cmd_Argc(cmd); ++i)
        {
-               LHNETADDRESS_FromString(&addr, Cmd_Argv(i), 26000);
+               LHNETADDRESS_FromString(&addr, Cmd_Argv(cmd, i), 26000);
                if(Crypto_ClearHostKey(&addr))
                {
-                       Con_Printf("cleared host key for %s\n", Cmd_Argv(i));
+                       Con_Printf("cleared host key for %s\n", Cmd_Argv(cmd, i));
                }
        }
 }
@@ -1429,11 +1429,18 @@ void Crypto_Init_Commands(void)
 {
        if(d0_blind_id_dll)
        {
-               Cmd_AddCommand("crypto_reload", Crypto_Reload_f, "reloads cryptographic keys");
-               Cmd_AddCommand("crypto_keygen", Crypto_KeyGen_f, "generates and saves a cryptographic key");
-               Cmd_AddCommand("crypto_keys", Crypto_Keys_f, "lists the loaded keys");
-               Cmd_AddCommand("crypto_hostkeys", Crypto_HostKeys_f, "lists the cached host keys");
-               Cmd_AddCommand("crypto_hostkey_clear", Crypto_HostKey_Clear_f, "clears a cached host key");
+               Cmd_AddCommand(&cmd_client, "crypto_reload", Crypto_Reload_f, "reloads cryptographic keys");
+               Cmd_AddCommand(&cmd_client, "crypto_keygen", Crypto_KeyGen_f, "generates and saves a cryptographic key");
+               Cmd_AddCommand(&cmd_client, "crypto_keys", Crypto_Keys_f, "lists the loaded keys");
+               Cmd_AddCommand(&cmd_client, "crypto_hostkeys", Crypto_HostKeys_f, "lists the cached host keys");
+               Cmd_AddCommand(&cmd_client, "crypto_hostkey_clear", Crypto_HostKey_Clear_f, "clears a cached host key");
+
+               Cmd_AddCommand(&cmd_server, "crypto_reload", Crypto_Reload_f, "reloads cryptographic keys");
+               Cmd_AddCommand(&cmd_server, "crypto_keygen", Crypto_KeyGen_f, "generates and saves a cryptographic key");
+               Cmd_AddCommand(&cmd_server, "crypto_keys", Crypto_Keys_f, "lists the loaded keys");
+               Cmd_AddCommand(&cmd_server, "crypto_hostkeys", Crypto_HostKeys_f, "lists the cached host keys");
+               Cmd_AddCommand(&cmd_server, "crypto_hostkey_clear", Crypto_HostKey_Clear_f, "clears a cached host key");
+
                Cvar_RegisterVariable(&crypto_developer);
                if(d0_rijndael_dll)
                        Cvar_RegisterVariable(&crypto_aeslevel);
index 333a760..875f376 100644 (file)
--- a/csprogs.c
+++ b/csprogs.c
@@ -563,7 +563,7 @@ void CL_VM_Parse_StuffCmd (const char *msg)
                int sizeflags = csqc_progcrc.flags;
                csqc_progcrc.flags &= ~CVAR_READONLY;
                csqc_progsize.flags &= ~CVAR_READONLY;
-               Cmd_ExecuteString (msg, src_command, true);
+               Cmd_ExecuteString(&cmd_clientfromserver, msg, src_command, true);
                csqc_progcrc.flags = crcflags;
                csqc_progsize.flags = sizeflags;
                return;
@@ -596,7 +596,7 @@ void CL_VM_Parse_StuffCmd (const char *msg)
                                l = sizeof(buf) - 1;
                        strlcpy(buf, p, l + 1); // strlcpy needs a + 1 as it includes the newline!
 
-                       Cmd_ExecuteString(buf, src_command, true);
+                       Cmd_ExecuteString(&cmd_clientfromserver, buf, src_command, true);
 
                        p += l;
                        if(*p == '\n')
@@ -604,13 +604,13 @@ void CL_VM_Parse_StuffCmd (const char *msg)
                        else
                                break; // end of string or overflow
                }
-               Cmd_ExecuteString("curl --clear_autodownload", src_command, true); // don't inhibit CSQC loading
+               Cmd_ExecuteString(&cmd_clientfromserver, "curl --clear_autodownload", src_command, true); // don't inhibit CSQC loading
                return;
        }
 
        if(!cl.csqc_loaded)
        {
-               Cbuf_AddText(msg);
+               Cbuf_AddText(&cmd_clientfromserver, msg);
                return;
        }
        CSQC_BEGIN
@@ -624,7 +624,7 @@ void CL_VM_Parse_StuffCmd (const char *msg)
                prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
        }
        else
-               Cbuf_AddText(msg);
+               Cbuf_AddText(&cmd_clientfromserver, msg);
        CSQC_END
 }
 
@@ -1161,7 +1161,7 @@ void CL_VM_Init (void)
 void CL_VM_ShutDown (void)
 {
        prvm_prog_t *prog = CLVM_prog;
-       Cmd_ClearCsqcFuncs();
+       Cmd_ClearCsqcFuncs(&cmd_client);
        //Cvar_SetValueQuick(&csqc_progcrc, -1);
        //Cvar_SetValueQuick(&csqc_progsize, -1);
        if(!cl.csqc_loaded)
diff --git a/cvar.c b/cvar.c
index 1803064..e36b8f9 100644 (file)
--- a/cvar.c
+++ b/cvar.c
@@ -538,7 +538,7 @@ void Cvar_RegisterVariable (cvar_t *variable)
        }
 
 // check for overlap with a command
-       if (Cmd_Exists (variable->name))
+       if (Cmd_Exists(&cmd_client, variable->name) || Cmd_Exists(&cmd_server, variable->name))
        {
                Con_Printf("Cvar_RegisterVariable: %s is a command\n", variable->name);
                return;
@@ -618,7 +618,7 @@ cvar_t *Cvar_Get (const char *name, const char *value, int flags, const char *ne
        }
 
 // check for overlap with a command
-       if (Cmd_Exists (name))
+       if (Cmd_Exists(&cmd_client, name) || Cmd_Exists(&cmd_server, name))
        {
                Con_Printf("Cvar_Get: %s is a command\n", name);
                return NULL;
@@ -670,17 +670,17 @@ Cvar_Command
 Handles variable inspection and changing from the console
 ============
 */
-qboolean       Cvar_Command (void)
+qboolean       Cvar_Command (cmd_state_t *cmd)
 {
        cvar_t                  *v;
 
 // check variables
-       v = Cvar_FindVar (Cmd_Argv(0));
+       v = Cvar_FindVar (Cmd_Argv(cmd, 0));
        if (!v)
                return false;
 
 // perform a variable print or set
-       if (Cmd_Argc() == 1)
+       if (Cmd_Argc(cmd) == 1)
        {
                Con_Printf("\"%s\" is \"%s\" [\"%s\"]\n", v->name, ((v->flags & CVAR_PRIVATE) ? "********"/*hunter2*/ : v->string), v->defstring);
                return true;
@@ -694,7 +694,7 @@ qboolean    Cvar_Command (void)
                Con_Printf("%s is read-only\n", v->name);
                return true;
        }
-       Cvar_Set (v->name, Cmd_Argv(1));
+       Cvar_Set (v->name, Cmd_Argv(cmd, 1));
        if (developer_extra.integer)
                Con_DPrint("\n");
        return true;
@@ -710,7 +710,7 @@ void Cvar_UnlockDefaults (void)
 }
 
 
-void Cvar_LockDefaults_f (void)
+void Cvar_LockDefaults_f(cmd_state_t *cmd)
 {
        cvar_t *var;
        // lock in the default values of all cvars
@@ -822,7 +822,7 @@ void Cvar_RestoreInitState(void)
        }
 }
 
-void Cvar_ResetToDefaults_All_f (void)
+void Cvar_ResetToDefaults_All_f(cmd_state_t *cmd)
 {
        cvar_t *var;
        // restore the default values of all cvars
@@ -832,7 +832,7 @@ void Cvar_ResetToDefaults_All_f (void)
 }
 
 
-void Cvar_ResetToDefaults_NoSaveOnly_f (void)
+void Cvar_ResetToDefaults_NoSaveOnly_f(cmd_state_t *cmd)
 {
        cvar_t *var;
        // restore the default values of all cvars
@@ -842,7 +842,7 @@ void Cvar_ResetToDefaults_NoSaveOnly_f (void)
 }
 
 
-void Cvar_ResetToDefaults_SaveOnly_f (void)
+void Cvar_ResetToDefaults_SaveOnly_f(cmd_state_t *cmd)
 {
        cvar_t *var;
        // restore the default values of all cvars
@@ -883,7 +883,7 @@ void Cvar_WriteVariables (qfile_t *f)
 Cvar_List
 =========
 */
-void Cvar_List_f (void)
+void Cvar_List_f(cmd_state_t *cmd)
 {
        cvar_t *cvar;
        const char *partial;
@@ -891,9 +891,9 @@ void Cvar_List_f (void)
        int count;
        qboolean ispattern;
 
-       if (Cmd_Argc() > 1)
+       if (Cmd_Argc(cmd) > 1)
        {
-               partial = Cmd_Argv (1);
+               partial = Cmd_Argv(cmd, 1);
                len = strlen(partial);
                ispattern = (strchr(partial, '*') || strchr(partial, '?'));
        }
@@ -926,19 +926,19 @@ void Cvar_List_f (void)
 }
 // 2000-01-09 CvarList command by Maddes
 
-void Cvar_Set_f (void)
+void Cvar_Set_f(cmd_state_t *cmd)
 {
        cvar_t *cvar;
 
        // make sure it's the right number of parameters
-       if (Cmd_Argc() < 3)
+       if (Cmd_Argc(cmd) < 3)
        {
                Con_Printf("Set: wrong number of parameters, usage: set <variablename> <value> [<description>]\n");
                return;
        }
 
        // check if it's read-only
-       cvar = Cvar_FindVar(Cmd_Argv(1));
+       cvar = Cvar_FindVar(Cmd_Argv(cmd, 1));
        if (cvar && cvar->flags & CVAR_READONLY)
        {
                Con_Printf("Set: %s is read-only\n", cvar->name);
@@ -949,22 +949,22 @@ void Cvar_Set_f (void)
                Con_DPrint("Set: ");
 
        // all looks ok, create/modify the cvar
-       Cvar_Get(Cmd_Argv(1), Cmd_Argv(2), 0, Cmd_Argc() > 3 ? Cmd_Argv(3) : NULL);
+       Cvar_Get(Cmd_Argv(cmd, 1), Cmd_Argv(cmd, 2), 0, Cmd_Argc(cmd) > 3 ? Cmd_Argv(cmd, 3) : NULL);
 }
 
-void Cvar_SetA_f (void)
+void Cvar_SetA_f(cmd_state_t *cmd)
 {
        cvar_t *cvar;
 
        // make sure it's the right number of parameters
-       if (Cmd_Argc() < 3)
+       if (Cmd_Argc(cmd) < 3)
        {
                Con_Printf("SetA: wrong number of parameters, usage: seta <variablename> <value> [<description>]\n");
                return;
        }
 
        // check if it's read-only
-       cvar = Cvar_FindVar(Cmd_Argv(1));
+       cvar = Cvar_FindVar(Cmd_Argv(cmd, 1));
        if (cvar && cvar->flags & CVAR_READONLY)
        {
                Con_Printf("SetA: %s is read-only\n", cvar->name);
@@ -975,25 +975,25 @@ void Cvar_SetA_f (void)
                Con_DPrint("SetA: ");
 
        // all looks ok, create/modify the cvar
-       Cvar_Get(Cmd_Argv(1), Cmd_Argv(2), CVAR_SAVE, Cmd_Argc() > 3 ? Cmd_Argv(3) : NULL);
+       Cvar_Get(Cmd_Argv(cmd, 1), Cmd_Argv(cmd, 2), CVAR_SAVE, Cmd_Argc(cmd) > 3 ? Cmd_Argv(cmd, 3) : NULL);
 }
 
-void Cvar_Del_f (void)
+void Cvar_Del_f(cmd_state_t *cmd)
 {
        int i;
        cvar_t *cvar, *parent, **link, *prev;
 
-       if(Cmd_Argc() < 2)
+       if(Cmd_Argc(cmd) < 2)
        {
                Con_Printf("Del: wrong number of parameters, useage: unset <variablename1> [<variablename2> ...]\n");
                return;
        }
-       for(i = 1; i < Cmd_Argc(); ++i)
+       for(i = 1; i < Cmd_Argc(cmd); ++i)
        {
-               cvar = Cvar_FindVarLink(Cmd_Argv(i), &parent, &link, &prev);
+               cvar = Cvar_FindVarLink(Cmd_Argv(cmd, i), &parent, &link, &prev);
                if(!cvar)
                {
-                       Con_Printf("Del: %s is not defined\n", Cmd_Argv(i));
+                       Con_Printf("Del: %s is not defined\n", Cmd_Argv(cmd, i));
                        continue;
                }
                if(cvar->flags & CVAR_READONLY)
@@ -1033,19 +1033,19 @@ void Cvar_Del_f (void)
 }
 
 #ifdef FILLALLCVARSWITHRUBBISH
-void Cvar_FillAll_f()
+void Cvar_FillAll_f(cmd_state_t *cmd)
 {
        char *buf, *p, *q;
        int n, i;
        cvar_t *var;
        qboolean verify;
-       if(Cmd_Argc() != 2)
+       if(Cmd_Argc(cmd) != 2)
        {
-               Con_Printf("Usage: %s length to plant rubbish\n", Cmd_Argv(0));
-               Con_Printf("Usage: %s -length to verify that the rubbish is still there\n", Cmd_Argv(0));
+               Con_Printf("Usage: %s length to plant rubbish\n", Cmd_Argv(cmd, 0));
+               Con_Printf("Usage: %s -length to verify that the rubbish is still there\n", Cmd_Argv(cmd, 0));
                return;
        }
-       n = atoi(Cmd_Argv(1));
+       n = atoi(Cmd_Argv(cmd, 1));
        verify = (n < 0);
        if(verify)
                n = -n;
diff --git a/cvar.h b/cvar.h
index 2ac7f45..9eed561 100644 (file)
--- a/cvar.h
+++ b/cvar.h
@@ -19,6 +19,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 // cvar.h
 
+struct cmd_state_s;
+typedef struct cmd_state_s cmd_state_t;
+
 /*
 
 cvar_t variables are used to hold scalar or string variables that can be changed or displayed at the console or prog code as well as accessed directly
@@ -188,8 +191,8 @@ const char *Cvar_CompleteVariable (const char *partial);
 
 void Cvar_CompleteCvarPrint (const char *partial);
 
-qboolean Cvar_Command (void);
-// called by Cmd_ExecuteString when Cmd_Argv(0) doesn't match a known
+qboolean Cvar_Command (cmd_state_t *cmd);
+// called by Cmd_ExecuteString when Cmd_Argv(cmd, 0) doesn't match a known
 // command.  Returns true if the command was a variable reference that
 // was handled. (print or change)
 
@@ -197,10 +200,10 @@ void Cvar_SaveInitState(void);
 void Cvar_RestoreInitState(void);
 
 void Cvar_UnlockDefaults (void);
-void Cvar_LockDefaults_f (void);
-void Cvar_ResetToDefaults_All_f (void);
-void Cvar_ResetToDefaults_NoSaveOnly_f (void);
-void Cvar_ResetToDefaults_SaveOnly_f (void);
+void Cvar_LockDefaults_f(cmd_state_t *cmd);
+void Cvar_ResetToDefaults_All_f(cmd_state_t *cmd);
+void Cvar_ResetToDefaults_NoSaveOnly_f(cmd_state_t *cmd);
+void Cvar_ResetToDefaults_SaveOnly_f(cmd_state_t *cmd);
 
 void Cvar_WriteVariables (qfile_t *f);
 // Writes lines containing "set variable value" for all variables
@@ -219,11 +222,11 @@ const char **Cvar_CompleteBuildList (const char *partial);
 /// Referenced in cmd.c in Cmd_Init hence it's inclusion here.
 /// Added by EvilTypeGuy eviltypeguy@qeradiant.com
 /// Thanks to Matthias "Maddes" Buecher, http://www.inside3d.com/qip/
-void Cvar_List_f (void);
+void Cvar_List_f(cmd_state_t *cmd);
 
-void Cvar_Set_f (void);
-void Cvar_SetA_f (void);
-void Cvar_Del_f (void);
+void Cvar_Set_f(cmd_state_t *cmd);
+void Cvar_SetA_f(cmd_state_t *cmd);
+void Cvar_Del_f(cmd_state_t *cmd);
 // commands to create new cvars (or set existing ones)
 // seta creates an archived cvar (saved to config)
 
@@ -237,7 +240,7 @@ extern cvar_t *cvar_vars; // used to list all cvars
 void Cvar_UpdateAllAutoCvars(void); // updates ALL autocvars of the active prog to the cvar values (savegame loading)
 
 #ifdef FILLALLCVARSWITHRUBBISH
-void Cvar_FillAll_f();
+void Cvar_FillAll_f(cmd_state_t *cmd);
 #endif /* FILLALLCVARSWITHRUBBISH */
 
 #endif
diff --git a/fs.c b/fs.c
index 15fe262..1612f19 100644 (file)
--- a/fs.c
+++ b/fs.c
@@ -343,9 +343,9 @@ FUNCTION PROTOTYPES
 =============================================================================
 */
 
-void FS_Dir_f(void);
-void FS_Ls_f(void);
-void FS_Which_f(void);
+void FS_Dir_f(cmd_state_t *cmd);
+void FS_Ls_f(cmd_state_t *cmd);
+void FS_Which_f(cmd_state_t *cmd);
 
 static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet);
 static packfile_t* FS_AddFileToPack (const char* name, pack_t* pack,
@@ -976,7 +976,7 @@ FS_Path_f
 
 ============
 */
-static void FS_Path_f (void)
+static void FS_Path_f(cmd_state_t *cmd)
 {
        searchpath_t *s;
 
@@ -1513,7 +1513,7 @@ void FS_Rescan (void)
        W_UnloadAll();
 }
 
-static void FS_Rescan_f(void)
+static void FS_Rescan_f(cmd_state_t *cmd)
 {
        FS_Rescan();
 }
@@ -1574,19 +1574,19 @@ qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean
 
        if (cls.demoplayback)
        {
-               CL_Disconnect_f();
+               CL_Disconnect_f(&cmd_client);
                cls.demonum = 0;
        }
 
        // unload all sounds so they will be reloaded from the new files as needed
-       S_UnloadAllSounds_f();
+       S_UnloadAllSounds_f(&cmd_client);
 
        // close down the video subsystem, it will start up again when the config finishes...
        VID_Stop();
        vid_opened = false;
 
        // restart the video subsystem after the config is executed
-       Cbuf_InsertText("\nloadconfig\nvid_restart\n\n");
+       Cbuf_InsertText(&cmd_client, "\nloadconfig\nvid_restart\n\n");
 
        return true;
 }
@@ -1596,13 +1596,13 @@ qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean
 FS_GameDir_f
 ================
 */
-static void FS_GameDir_f (void)
+static void FS_GameDir_f(cmd_state_t *cmd)
 {
        int i;
        int numgamedirs;
        char gamedirs[MAX_GAMEDIRS][MAX_QPATH];
 
-       if (Cmd_Argc() < 2)
+       if (Cmd_Argc(cmd) < 2)
        {
                Con_Printf("gamedirs active:");
                for (i = 0;i < fs_numgamedirs;i++)
@@ -1611,7 +1611,7 @@ static void FS_GameDir_f (void)
                return;
        }
 
-       numgamedirs = Cmd_Argc() - 1;
+       numgamedirs = Cmd_Argc(cmd) - 1;
        if (numgamedirs > MAX_GAMEDIRS)
        {
                Con_Printf("Too many gamedirs (%i > %i)\n", numgamedirs, MAX_GAMEDIRS);
@@ -1619,7 +1619,7 @@ static void FS_GameDir_f (void)
        }
 
        for (i = 0;i < numgamedirs;i++)
-               strlcpy(gamedirs[i], Cmd_Argv(i+1), sizeof(gamedirs[i]));
+               strlcpy(gamedirs[i], Cmd_Argv(cmd, i+1), sizeof(gamedirs[i]));
 
        if ((cls.state == ca_connected && !cls.demoplayback) || sv.active)
        {
@@ -2181,12 +2181,19 @@ void FS_Init_Commands(void)
        Cvar_RegisterVariable (&fs_empty_files_in_pack_mark_deletions);
        Cvar_RegisterVariable (&cvar_fs_gamedir);
 
-       Cmd_AddCommand ("gamedir", FS_GameDir_f, "changes active gamedir list (can take multiple arguments), not including base directory (example usage: gamedir ctf)");
-       Cmd_AddCommand ("fs_rescan", FS_Rescan_f, "rescans filesystem for new pack archives and any other changes");
-       Cmd_AddCommand ("path", FS_Path_f, "print searchpath (game directories and archives)");
-       Cmd_AddCommand ("dir", FS_Dir_f, "list files in searchpath matching an * filename pattern, one per line");
-       Cmd_AddCommand ("ls", FS_Ls_f, "list files in searchpath matching an * filename pattern, multiple per line");
-       Cmd_AddCommand ("which", FS_Which_f, "accepts a file name as argument and reports where the file is taken from");
+       Cmd_AddCommand(&cmd_client, "gamedir", FS_GameDir_f, "changes active gamedir list (can take multiple arguments), not including base directory (example usage: gamedir ctf)");
+       Cmd_AddCommand(&cmd_client, "fs_rescan", FS_Rescan_f, "rescans filesystem for new pack archives and any other changes");
+       Cmd_AddCommand(&cmd_client, "path", FS_Path_f, "print searchpath (game directories and archives)");
+       Cmd_AddCommand(&cmd_client, "dir", FS_Dir_f, "list files in searchpath matching an * filename pattern, one per line");
+       Cmd_AddCommand(&cmd_client, "ls", FS_Ls_f, "list files in searchpath matching an * filename pattern, multiple per line");
+       Cmd_AddCommand(&cmd_client, "which", FS_Which_f, "accepts a file name as argument and reports where the file is taken from");
+
+       Cmd_AddCommand(&cmd_server, "gamedir", FS_GameDir_f, "changes active gamedir list (can take multiple arguments), not including base directory (example usage: gamedir ctf)");
+       Cmd_AddCommand(&cmd_server, "fs_rescan", FS_Rescan_f, "rescans filesystem for new pack archives and any other changes");
+       Cmd_AddCommand(&cmd_server, "path", FS_Path_f, "print searchpath (game directories and archives)");
+       Cmd_AddCommand(&cmd_server, "dir", FS_Dir_f, "list files in searchpath matching an * filename pattern, one per line");
+       Cmd_AddCommand(&cmd_server, "ls", FS_Ls_f, "list files in searchpath matching an * filename pattern, multiple per line");
+       Cmd_AddCommand(&cmd_server, "which", FS_Which_f, "accepts a file name as argument and reports where the file is taken from");
 }
 
 /*
@@ -3829,43 +3836,43 @@ static int FS_ListDirectory(const char *pattern, int oneperline)
        return (int)numfiles;
 }
 
-static void FS_ListDirectoryCmd (const char* cmdname, int oneperline)
+static void FS_ListDirectoryCmd (cmd_state_t *cmd, const char* cmdname, int oneperline)
 {
        const char *pattern;
-       if (Cmd_Argc() >= 3)
+       if (Cmd_Argc(cmd) >= 3)
        {
                Con_Printf("usage:\n%s [path/pattern]\n", cmdname);
                return;
        }
-       if (Cmd_Argc() == 2)
-               pattern = Cmd_Argv(1);
+       if (Cmd_Argc(cmd) == 2)
+               pattern = Cmd_Argv(cmd, 1);
        else
                pattern = "*";
        if (!FS_ListDirectory(pattern, oneperline))
                Con_Print("No files found.\n");
 }
 
-void FS_Dir_f(void)
+void FS_Dir_f(cmd_state_t *cmd)
 {
-       FS_ListDirectoryCmd("dir", true);
+       FS_ListDirectoryCmd(cmd, "dir", true);
 }
 
-void FS_Ls_f(void)
+void FS_Ls_f(cmd_state_t *cmd)
 {
-       FS_ListDirectoryCmd("ls", false);
+       FS_ListDirectoryCmd(cmd, "ls", false);
 }
 
-void FS_Which_f(void)
+void FS_Which_f(cmd_state_t *cmd)
 {
        const char *filename;
        int index;
        searchpath_t *sp;
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
-               Con_Printf("usage:\n%s <file>\n", Cmd_Argv(0));
+               Con_Printf("usage:\n%s <file>\n", Cmd_Argv(cmd, 0));
                return;
        }  
-       filename = Cmd_Argv(1);
+       filename = Cmd_Argv(cmd, 1);
        sp = FS_FindFile(filename, &index, true);
        if (!sp) {
                Con_Printf("%s isn't anywhere\n", filename);
index 1606c4a..47f4717 100644 (file)
@@ -112,7 +112,7 @@ static void GLAPIENTRY GL_DebugOutputCallback(GLenum source, GLenum type, GLuint
 
 #define BACKENDACTIVECHECK if (!gl_state.active) Sys_Error("GL backend function called when backend is not active");
 
-void SCR_ScreenShot_f (void);
+void SCR_ScreenShot_f(cmd_state_t *cmd);
 
 typedef struct gltextureunit_s
 {
@@ -245,7 +245,7 @@ unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
 
-static void GL_VBOStats_f(void)
+static void GL_VBOStats_f(cmd_state_t *cmd)
 {
        GL_Mesh_ListVBOs(true);
 }
@@ -372,7 +372,7 @@ void gl_backend_init(void)
        Cvar_RegisterVariable(&gl_paranoid);
        Cvar_RegisterVariable(&gl_printcheckerror);
 
-       Cmd_AddCommand("gl_vbostats", GL_VBOStats_f, "prints a list of all buffer objects (vertex data and triangle elements) and total video memory used by them");
+       Cmd_AddCommand(&cmd_client, "gl_vbostats", GL_VBOStats_f, "prints a list of all buffer objects (vertex data and triangle elements) and total video memory used by them");
 
        R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
 }
index 77d6f10..59f49fa 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -536,7 +536,7 @@ static float snap_to_pixel_y(float y, float roundUpAt)
        */
 }
 
-static void LoadFont_f(void)
+static void LoadFont_f(cmd_state_t *cmd)
 {
        dp_font_t *f;
        int i, sizes;
@@ -544,7 +544,7 @@ static void LoadFont_f(void)
        float sz, scale, voffset;
        char mainfont[MAX_QPATH];
 
-       if(Cmd_Argc() < 2)
+       if(Cmd_Argc(cmd) < 2)
        {
                Con_Printf("Available font commands:\n");
                for(i = 0; i < dp_fonts.maxsize; ++i)
@@ -564,17 +564,17 @@ static void LoadFont_f(void)
                        );
                return;
        }
-       f = FindFont(Cmd_Argv(1), true);
+       f = FindFont(Cmd_Argv(cmd, 1), true);
        if(f == NULL)
        {
                Con_Printf("font function not found\n");
                return;
        }
 
-       if(Cmd_Argc() < 3)
+       if(Cmd_Argc(cmd) < 3)
                filelist = "gfx/conchars";
        else
-               filelist = Cmd_Argv(2);
+               filelist = Cmd_Argv(cmd, 2);
 
        memset(f->fallbacks, 0, sizeof(f->fallbacks));
        memset(f->fallback_faces, 0, sizeof(f->fallback_faces));
@@ -633,23 +633,23 @@ static void LoadFont_f(void)
 
        scale = 1;
        voffset = 0;
-       if(Cmd_Argc() >= 4)
+       if(Cmd_Argc(cmd) >= 4)
        {
-               for(sizes = 0, i = 3; i < Cmd_Argc(); ++i)
+               for(sizes = 0, i = 3; i < Cmd_Argc(cmd); ++i)
                {
                        // special switches
-                       if (!strcmp(Cmd_Argv(i), "scale"))
+                       if (!strcmp(Cmd_Argv(cmd, i), "scale"))
                        {
                                i++;
-                               if (i < Cmd_Argc())
-                                       scale = atof(Cmd_Argv(i));
+                               if (i < Cmd_Argc(cmd))
+                                       scale = atof(Cmd_Argv(cmd, i));
                                continue;
                        }
-                       if (!strcmp(Cmd_Argv(i), "voffset"))
+                       if (!strcmp(Cmd_Argv(cmd, i), "voffset"))
                        {
                                i++;
-                               if (i < Cmd_Argc())
-                                       voffset = atof(Cmd_Argv(i));
+                               if (i < Cmd_Argc(cmd))
+                                       voffset = atof(Cmd_Argv(cmd, i));
                                continue;
                        }
 
@@ -657,7 +657,7 @@ static void LoadFont_f(void)
                                continue; // no slot for other sizes
 
                        // parse one of sizes
-                       sz = atof(Cmd_Argv(i));
+                       sz = atof(Cmd_Argv(cmd, i));
                        if (sz > 0.001f && sz < 1000.0f) // do not use crap sizes
                        {
                                // search for duplicated sizes
@@ -769,7 +769,7 @@ void GL_Draw_Init (void)
                if(!FONT_USER(i)->title[0])
                        dpsnprintf(FONT_USER(i)->title, sizeof(FONT_USER(i)->title), "user%d", j++);
 
-       Cmd_AddCommand ("loadfont",LoadFont_f, "loadfont function tganame loads a font; example: loadfont console gfx/veramono; loadfont without arguments lists the available functions");
+       Cmd_AddCommand(&cmd_client, "loadfont", LoadFont_f, "loadfont function tganame loads a font; example: loadfont console gfx/veramono; loadfont without arguments lists the available functions");
        R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap, NULL, NULL);
 }
 
index 2c66ba0..52ddf65 100644 (file)
@@ -1394,7 +1394,7 @@ static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permuta
        CHECKGLERROR
 }
 
-void R_GLSL_Restart_f(void)
+void R_GLSL_Restart_f(cmd_state_t *cmd)
 {
        unsigned int i, limit;
        switch(vid.renderpath)
@@ -1419,7 +1419,7 @@ void R_GLSL_Restart_f(void)
        }
 }
 
-static void R_GLSL_DumpShader_f(void)
+static void R_GLSL_DumpShader_f(cmd_state_t *cmd)
 {
        int i, language, mode, dupe;
        char *text;
@@ -3131,7 +3131,7 @@ static void gl_main_shutdown(void)
        r_texture_numcubemaps = 0;
        //r_texture_fogintensity = NULL;
        memset(&r_fb, 0, sizeof(r_fb));
-       R_GLSL_Restart_f();
+       R_GLSL_Restart_f(&cmd_client);
 
        r_glsl_permutation = NULL;
        memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
@@ -3170,8 +3170,8 @@ void GL_Main_Init(void)
        r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
        R_InitShaderModeInfo();
 
-       Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
-       Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
+       Cmd_AddCommand(&cmd_client, "r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
+       Cmd_AddCommand(&cmd_client, "r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
        // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
        if (gamemode == GAME_NEHAHRA)
        {
@@ -5630,7 +5630,7 @@ void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, i
        rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
 
        if(R_CompileShader_CheckStaticParms())
-               R_GLSL_Restart_f();
+               R_GLSL_Restart_f(&cmd_client);
 
        if (!r_drawentities.integer)
                r_refdef.scene.numentities = 0;
index fc7bc6b..e3fab1b 100644 (file)
@@ -1488,7 +1488,7 @@ void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surface
 }
 
 //Made by [515]
-static void R_ReplaceWorldTexture (void)
+static void R_ReplaceWorldTexture_f(cmd_state_t *cmd)
 {
        dp_model_t              *m;
        texture_t       *t;
@@ -1502,7 +1502,7 @@ static void R_ReplaceWorldTexture (void)
        }
        m = r_refdef.scene.worldmodel;
 
-       if(Cmd_Argc() < 2)
+       if(Cmd_Argc(cmd) < 2)
        {
                Con_Print("r_replacemaptexture <texname> <newtexname> - replaces texture\n");
                Con_Print("r_replacemaptexture <texname> - switch back to default texture\n");
@@ -1513,8 +1513,8 @@ static void R_ReplaceWorldTexture (void)
                Con_Print("This command works only in singleplayer\n");
                return;
        }
-       r = Cmd_Argv(1);
-       newt = Cmd_Argv(2);
+       r = Cmd_Argv(cmd, 1);
+       newt = Cmd_Argv(cmd, 2);
        if(!newt[0])
                newt = r;
        for(i=0,t=m->data_textures;i<m->num_textures;i++,t++)
@@ -1537,7 +1537,7 @@ static void R_ReplaceWorldTexture (void)
 }
 
 //Made by [515]
-static void R_ListWorldTextures (void)
+static void R_ListWorldTextures_f(cmd_state_t *cmd)
 {
        dp_model_t              *m;
        texture_t       *t;
@@ -1587,8 +1587,8 @@ void GL_Surf_Init(void)
        Cvar_RegisterVariable(&r_vis_trace_surfaces);
        Cvar_RegisterVariable(&r_q3bsp_renderskydepth);
 
-       Cmd_AddCommand ("r_replacemaptexture", R_ReplaceWorldTexture, "override a map texture for testing purposes");
-       Cmd_AddCommand ("r_listmaptextures", R_ListWorldTextures, "list all textures used by the current map");
+       Cmd_AddCommand(&cmd_client, "r_replacemaptexture", R_ReplaceWorldTexture_f, "override a map texture for testing purposes");
+       Cmd_AddCommand(&cmd_client, "r_listmaptextures", R_ListWorldTextures_f, "list all textures used by the current map");
 
        //R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap);
 }
index 2d2e511..eeb7432 100644 (file)
@@ -420,14 +420,14 @@ static glmode_t modes[6] =
        {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
 };
 
-static void GL_TextureMode_f (void)
+static void GL_TextureMode_f(cmd_state_t *cmd)
 {
        int i;
        GLint oldbindtexnum;
        gltexture_t *glt;
        gltexturepool_t *pool;
 
-       if (Cmd_Argc() == 1)
+       if (Cmd_Argc(cmd) == 1)
        {
                Con_Printf("Texture mode is %sforced\n", gl_filter_force ? "" : "not ");
                for (i = 0;i < 6;i++)
@@ -443,7 +443,7 @@ static void GL_TextureMode_f (void)
        }
 
        for (i = 0;i < (int)(sizeof(modes)/sizeof(*modes));i++)
-               if (!strcasecmp (modes[i].name, Cmd_Argv(1) ) )
+               if (!strcasecmp (modes[i].name, Cmd_Argv(cmd, 1) ) )
                        break;
        if (i == 6)
        {
@@ -453,7 +453,7 @@ static void GL_TextureMode_f (void)
 
        gl_filter_min = modes[i].minification;
        gl_filter_mag = modes[i].magnification;
-       gl_filter_force = ((Cmd_Argc() > 2) && !strcasecmp(Cmd_Argv(2), "force"));
+       gl_filter_force = ((Cmd_Argc(cmd) > 2) && !strcasecmp(Cmd_Argv(cmd, 2), "force"));
 
        switch(vid.renderpath)
        {
@@ -607,7 +607,7 @@ void R_TextureStats_Print(qboolean printeach, qboolean printpool, qboolean print
                Con_Printf("textures total: %i (%.3fMB, %.3fMB original), uploaded %i (%.3fMB, %.3fMB original), upload on demand %i (%.3fMB, %.3fMB original)\n", sumtotal, sumtotalt / 1048576.0, sumtotalp / 1048576.0, sumloaded, sumloadedt / 1048576.0, sumloadedp / 1048576.0, sumtotal - sumloaded, (sumtotalt - sumloadedt) / 1048576.0, (sumtotalp - sumloadedp) / 1048576.0);
 }
 
-static void R_TextureStats_f(void)
+static void R_TextureStats_f(cmd_state_t *cmd)
 {
        R_TextureStats_Print(true, true, true);
 }
@@ -700,8 +700,8 @@ static void r_textures_devicerestored(void)
 
 void R_Textures_Init (void)
 {
-       Cmd_AddCommand("gl_texturemode", &GL_TextureMode_f, "set texture filtering mode (GL_NEAREST, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, etc); an additional argument 'force' forces the texture mode even in cases where it may not be appropriate");
-       Cmd_AddCommand("r_texturestats", R_TextureStats_f, "print information about all loaded textures and some statistics");
+       Cmd_AddCommand(&cmd_client, "gl_texturemode", &GL_TextureMode_f, "set texture filtering mode (GL_NEAREST, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, etc); an additional argument 'force' forces the texture mode even in cases where it may not be appropriate");
+       Cmd_AddCommand(&cmd_client, "r_texturestats", R_TextureStats_f, "print information about all loaded textures and some statistics");
        Cvar_RegisterVariable (&gl_max_size);
        Cvar_RegisterVariable (&gl_picmip);
        Cvar_RegisterVariable (&gl_picmip_world);
diff --git a/host.c b/host.c
index 1d0ad3b..5c159c0 100644 (file)
--- a/host.c
+++ b/host.c
@@ -229,14 +229,16 @@ static void Host_ServerOptions (void)
 Host_InitLocal
 ======================
 */
-void Host_SaveConfig_f(void);
-void Host_LoadConfig_f(void);
+void Host_SaveConfig_f(cmd_state_t *cmd);
+void Host_LoadConfig_f(cmd_state_t *cmd);
 extern cvar_t sv_writepicture_quality;
 extern cvar_t r_texture_jpeg_fastpicmip;
 static void Host_InitLocal (void)
 {
-       Cmd_AddCommand("saveconfig", Host_SaveConfig_f, "save settings to config.cfg (or a specified filename) immediately (also automatic when quitting)");
-       Cmd_AddCommand("loadconfig", Host_LoadConfig_f, "reset everything and reload configs");
+       Cmd_AddCommand(&cmd_client, "saveconfig", Host_SaveConfig_f, "save settings to config.cfg (or a specified filename) immediately (also automatic when quitting)");
+       Cmd_AddCommand(&cmd_client, "loadconfig", Host_LoadConfig_f, "reset everything and reload configs");
+       Cmd_AddCommand(&cmd_server, "saveconfig", Host_SaveConfig_f, "save settings to config.cfg (or a specified filename) immediately (also automatic when quitting)");
+       Cmd_AddCommand(&cmd_server, "loadconfig", Host_LoadConfig_f, "reset everything and reload configs");
 
        Cvar_RegisterVariable (&cl_maxphysicsframesperserverframe);
        Cvar_RegisterVariable (&host_framerate);
@@ -302,30 +304,30 @@ void Host_SaveConfig(void)
 {
        Host_SaveConfig_to(CONFIGFILENAME);
 }
-void Host_SaveConfig_f(void)
+void Host_SaveConfig_f(cmd_state_t *cmd)
 {
        const char *file = CONFIGFILENAME;
 
-       if(Cmd_Argc() >= 2) {
-               file = Cmd_Argv(1);
+       if(Cmd_Argc(cmd) >= 2) {
+               file = Cmd_Argv(cmd, 1);
                Con_Printf("Saving to %s\n", file);
        }
 
        Host_SaveConfig_to(file);
 }
 
-static void Host_AddConfigText(void)
+static void Host_AddConfigText(cmd_state_t *cmd)
 {
        // set up the default startmap_sp and startmap_dm aliases (mods can
        // override these) and then execute the quake.rc startup script
        if (gamemode == GAME_NEHAHRA)
-               Cbuf_InsertText("alias startmap_sp \"map nehstart\"\nalias startmap_dm \"map nehstart\"\nexec " STARTCONFIGFILENAME "\n");
+               Cbuf_InsertText(cmd, "alias startmap_sp \"map nehstart\"\nalias startmap_dm \"map nehstart\"\nexec " STARTCONFIGFILENAME "\n");
        else if (gamemode == GAME_TRANSFUSION)
-               Cbuf_InsertText("alias startmap_sp \"map e1m1\"\n""alias startmap_dm \"map bb1\"\nexec " STARTCONFIGFILENAME "\n");
+               Cbuf_InsertText(cmd, "alias startmap_sp \"map e1m1\"\n""alias startmap_dm \"map bb1\"\nexec " STARTCONFIGFILENAME "\n");
        else if (gamemode == GAME_TEU)
-               Cbuf_InsertText("alias startmap_sp \"map start\"\nalias startmap_dm \"map start\"\nexec teu.rc\n");
+               Cbuf_InsertText(cmd, "alias startmap_sp \"map start\"\nalias startmap_dm \"map start\"\nexec teu.rc\n");
        else
-               Cbuf_InsertText("alias startmap_sp \"map start\"\nalias startmap_dm \"map start\"\nexec " STARTCONFIGFILENAME "\n");
+               Cbuf_InsertText(cmd, "alias startmap_sp \"map start\"\nalias startmap_dm \"map start\"\nexec " STARTCONFIGFILENAME "\n");
 }
 
 /*
@@ -335,16 +337,16 @@ Host_LoadConfig_f
 Resets key bindings and cvars to defaults and then reloads scripts
 ===============
 */
-void Host_LoadConfig_f(void)
+void Host_LoadConfig_f(cmd_state_t *cmd)
 {
        // reset all cvars, commands and aliases to init values
        Cmd_RestoreInitState();
 #ifdef CONFIG_MENU
        // prepend a menu restart command to execute after the config
-       Cbuf_InsertText("\nmenu_restart\n");
+       Cbuf_InsertText(&cmd_client, "\nmenu_restart\n");
 #endif
        // reset cvars to their defaults, and then exec startup scripts again
-       Host_AddConfigText();
+       Host_AddConfigText(&cmd_client);
 }
 
 /*
@@ -632,14 +634,14 @@ Add them exactly as if they had been typed at the console
 */
 static void Host_GetConsoleCommands (void)
 {
-       char *cmd;
+       char *line;
 
-       while (1)
+       while ((line = Sys_ConsoleInput()))
        {
-               cmd = Sys_ConsoleInput ();
-               if (!cmd)
-                       break;
-               Cbuf_AddText (cmd);
+               if (cls.state == ca_dedicated)
+                       Cbuf_AddText(&cmd_server, line);
+               else
+                       Cbuf_AddText(&cmd_client, line);
        }
 }
 
@@ -779,7 +781,8 @@ void Host_Main(void)
                        // process console commands
 //                     R_TimeReport("preconsole");
                        CL_VM_PreventInformationLeaks();
-                       Cbuf_Frame();
+                       Cbuf_Frame(&cmd_client);
+                       Cbuf_Frame(&cmd_server);
 //                     R_TimeReport("console");
                }
 
@@ -1094,8 +1097,6 @@ char engineversion[128];
 
 qboolean sys_nostdout = false;
 
-extern qboolean host_stuffcmdsrun;
-
 static qfile_t *locksession_fh = NULL;
 static qboolean locksession_run = false;
 static void Host_InitSession(void)
@@ -1165,6 +1166,8 @@ static void Host_Init (void)
        int i;
        const char* os;
        char vabuf[1024];
+       qboolean dedicated_server = COM_CheckParm("-dedicated") || !cl_available;
+       cmd_state_t *cmd = &cmd_client;
 
        if (COM_CheckParm("-profilegameonly"))
                Sys_AllowProfiling(false);
@@ -1215,6 +1218,8 @@ static void Host_Init (void)
        // initialize console command/cvar/alias/command execution systems
        Cmd_Init();
 
+       Cmd_Init_Commands(dedicated_server);
+
        // initialize memory subsystem cvars/commands
        Memory_Init_Commands();
 
@@ -1224,7 +1229,6 @@ static void Host_Init (void)
        // initialize various cvars that could not be initialized earlier
        u8_Init();
        Curl_Init_Commands();
-       Cmd_Init_Commands();
        Sys_Init_Commands();
        COM_Init_Commands();
        FS_Init_Commands();
@@ -1276,7 +1280,10 @@ static void Host_Init (void)
        TaskQueue_Init();
 
        if (cls.state == ca_dedicated)
-               Cmd_AddCommand ("disconnect", CL_Disconnect_f, "disconnect from server (or disconnect all clients if running a server)");
+       {
+               cmd = &cmd_server;
+               Cmd_AddCommand(&cmd_server, "disconnect", CL_Disconnect_f, "disconnect from server (or disconnect all clients if running a server)");
+       }
        else
        {
                Con_DPrintf("Initializing client\n");
@@ -1307,14 +1314,14 @@ static void Host_Init (void)
                return;
        }
 
-       Host_AddConfigText();
-       Cbuf_Execute();
+       Host_AddConfigText(cmd);
+       Cbuf_Execute(cmd);
 
        // if stuffcmds wasn't run, then quake.rc is probably missing, use default
        if (!host_stuffcmdsrun)
        {
-               Cbuf_AddText("exec default.cfg\nexec " CONFIGFILENAME "\nexec autoexec.cfg\nstuffcmds\n");
-               Cbuf_Execute();
+               Cbuf_AddText(cmd, "exec default.cfg\nexec " CONFIGFILENAME "\nexec autoexec.cfg\nstuffcmds\n");
+               Cbuf_Execute(cmd);
        }
 
        // put up the loading image so the user doesn't stare at a black screen...
@@ -1333,8 +1340,8 @@ static void Host_Init (void)
        if (i && i + 1 < com_argc)
        if (!sv.active && !cls.demoplayback && !cls.connect_trying)
        {
-               Cbuf_AddText(va(vabuf, sizeof(vabuf), "timedemo %s\n", com_argv[i + 1]));
-               Cbuf_Execute();
+               Cbuf_AddText(&cmd_client, va(vabuf, sizeof(vabuf), "timedemo %s\n", com_argv[i + 1]));
+               Cbuf_Execute(&cmd_client);
        }
 
        // check for special demo mode
@@ -1343,8 +1350,8 @@ static void Host_Init (void)
        if (i && i + 1 < com_argc)
        if (!sv.active && !cls.demoplayback && !cls.connect_trying)
        {
-               Cbuf_AddText(va(vabuf, sizeof(vabuf), "playdemo %s\n", com_argv[i + 1]));
-               Cbuf_Execute();
+               Cbuf_AddText(&cmd_client, va(vabuf, sizeof(vabuf), "playdemo %s\n", com_argv[i + 1]));
+               Cbuf_Execute(&cmd_client);
        }
 
 // COMMANDLINEOPTION: Client: -capturedemo <demoname> captures a playdemo and quits
@@ -1352,23 +1359,23 @@ static void Host_Init (void)
        if (i && i + 1 < com_argc)
        if (!sv.active && !cls.demoplayback && !cls.connect_trying)
        {
-               Cbuf_AddText(va(vabuf, sizeof(vabuf), "playdemo %s\ncl_capturevideo 1\n", com_argv[i + 1]));
-               Cbuf_Execute();
+               Cbuf_AddText(&cmd_client, va(vabuf, sizeof(vabuf), "playdemo %s\ncl_capturevideo 1\n", com_argv[i + 1]));
+               Cbuf_Execute(&cmd_client);
        }
 
        if (cls.state == ca_dedicated || COM_CheckParm("-listen"))
        if (!sv.active && !cls.demoplayback && !cls.connect_trying)
        {
-               Cbuf_AddText("startmap_dm\n");
-               Cbuf_Execute();
+               Cbuf_AddText(&cmd_client, "startmap_dm\n");
+               Cbuf_Execute(&cmd_client);
        }
 
        if (!sv.active && !cls.demoplayback && !cls.connect_trying)
        {
 #ifdef CONFIG_MENU
-               Cbuf_AddText("togglemenu 1\n");
+               Cbuf_AddText(&cmd_client, "togglemenu 1\n");
 #endif
-               Cbuf_Execute();
+               Cbuf_Execute(&cmd_client);
        }
 
        Con_DPrint("========Initialized=========\n");
index 3412ed8..7bd22ec 100644 (file)
@@ -55,7 +55,7 @@ Host_Quit_f
 ==================
 */
 
-void Host_Quit_f (void)
+void Host_Quit_f(cmd_state_t *cmd)
 {
        if(host_shuttingdown)
                Con_Printf("shutting down already!\n");
@@ -68,7 +68,7 @@ void Host_Quit_f (void)
 Host_Status_f
 ==================
 */
-static void Host_Status_f (void)
+static void Host_Status_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        char qcstatus[256];
@@ -79,12 +79,12 @@ static void Host_Status_f (void)
        int frags;
        char vabuf[1024];
 
-       if (cmd_source == src_command)
+       if (cmd->source == src_command)
        {
                // if running a client, try to send over network so the client's status report parser will see the report
                if (cls.state == ca_connected)
                {
-                       Cmd_ForwardToServer ();
+                       Cmd_ForwardToServer_f(cmd);
                        return;
                }
                print = Con_Printf;
@@ -96,11 +96,11 @@ static void Host_Status_f (void)
                return;
 
        in = 0;
-       if (Cmd_Argc() == 2)
+       if (Cmd_Argc(cmd) == 2)
        {
-               if (strcmp(Cmd_Argv(1), "1") == 0)
+               if (strcmp(Cmd_Argv(cmd, 1), "1") == 0)
                        in = 1;
-               else if (strcmp(Cmd_Argv(1), "2") == 0)
+               else if (strcmp(Cmd_Argv(cmd, 1), "2") == 0)
                        in = 2;
        }
 
@@ -149,7 +149,7 @@ static void Host_Status_f (void)
                        ping = bound(0, (int)floor(client->ping*1000+0.5), 9999);
                }
 
-               if(sv_status_privacy.integer && cmd_source != src_command)
+               if(sv_status_privacy.integer && cmd->source != src_command)
                        strlcpy(ip, client->netconnection ? "hidden" : "botclient", 48);
                else
                        strlcpy(ip, (client->netconnection && client->netconnection->address) ? client->netconnection->address : "botclient", 48);
@@ -208,7 +208,7 @@ Host_God_f
 Sets client to godmode
 ==================
 */
-static void Host_God_f (void)
+static void Host_God_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        if (!allowcheats)
@@ -224,7 +224,7 @@ static void Host_God_f (void)
                SV_ClientPrint("godmode ON\n");
 }
 
-static void Host_Notarget_f (void)
+static void Host_Notarget_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        if (!allowcheats)
@@ -242,7 +242,7 @@ static void Host_Notarget_f (void)
 
 qboolean noclip_anglehack;
 
-static void Host_Noclip_f (void)
+static void Host_Noclip_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        if (!allowcheats)
@@ -272,7 +272,7 @@ Host_Fly_f
 Sets client to flymode
 ==================
 */
-static void Host_Fly_f (void)
+static void Host_Fly_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        if (!allowcheats)
@@ -300,19 +300,18 @@ Host_Ping_f
 
 ==================
 */
-void Host_Pings_f (void); // called by Host_Ping_f
-static void Host_Ping_f (void)
+static void Host_Ping_f(cmd_state_t *cmd)
 {
        int i;
        client_t *client;
        void (*print) (const char *fmt, ...);
 
-       if (cmd_source == src_command)
+       if (cmd->source == src_command)
        {
                // if running a client, try to send over network so the client's ping report parser will see the report
                if (cls.state == ca_connected)
                {
-                       Cmd_ForwardToServer ();
+                       Cmd_ForwardToServer_f(cmd);
                        return;
                }
                print = Con_Printf;
@@ -330,10 +329,6 @@ static void Host_Ping_f (void)
                        continue;
                print("%4i %s\n", bound(0, (int)floor(client->ping*1000+0.5), 9999), client->name);
        }
-
-       // now call the Pings command also, which will send a report that contains packet loss for the scoreboard (as well as a simpler ping report)
-       // actually, don't, it confuses old clients (resulting in "unknown command pingplreport" flooding the console)
-       //Host_Pings_f();
 }
 
 /*
@@ -353,11 +348,11 @@ map <servername>
 command from the console.  Active clients are kicked off.
 ======================
 */
-static void Host_Map_f (void)
+static void Host_Map_f(cmd_state_t *cmd)
 {
        char level[MAX_QPATH];
 
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
                Con_Print("map <levelname> : start a new game (kicks off all players)\n");
                return;
@@ -389,7 +384,7 @@ static void Host_Map_f (void)
 
        svs.serverflags = 0;                    // haven't completed an episode yet
        allowcheats = sv_cheats.integer != 0;
-       strlcpy(level, Cmd_Argv(1), sizeof(level));
+       strlcpy(level, Cmd_Argv(cmd, 1), sizeof(level));
        SV_SpawnServer(level);
        if (sv.active && cls.state == ca_disconnected)
                CL_EstablishConnection("local:1", -2);
@@ -402,18 +397,18 @@ Host_Changelevel_f
 Goes to a new map, taking all clients along
 ==================
 */
-static void Host_Changelevel_f (void)
+static void Host_Changelevel_f(cmd_state_t *cmd)
 {
        char level[MAX_QPATH];
 
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
                Con_Print("changelevel <levelname> : continue game on a new level\n");
                return;
        }
        // HACKHACKHACK
        if (!sv.active) {
-               Host_Map_f();
+               Host_Map_f(cmd);
                return;
        }
 
@@ -426,7 +421,7 @@ static void Host_Changelevel_f (void)
 
        SV_SaveSpawnparms ();
        allowcheats = sv_cheats.integer != 0;
-       strlcpy(level, Cmd_Argv(1), sizeof(level));
+       strlcpy(level, Cmd_Argv(cmd, 1), sizeof(level));
        SV_SpawnServer(level);
        if (sv.active && cls.state == ca_disconnected)
                CL_EstablishConnection("local:1", -2);
@@ -439,11 +434,11 @@ Host_Restart_f
 Restarts the current server for a dead player
 ==================
 */
-static void Host_Restart_f (void)
+static void Host_Restart_f(cmd_state_t *cmd)
 {
        char mapname[MAX_QPATH];
 
-       if (Cmd_Argc() != 1)
+       if (Cmd_Argc(cmd) != 1)
        {
                Con_Print("restart : restart current level\n");
                return;
@@ -476,7 +471,7 @@ This command causes the client to wait for the signon messages again.
 This is sent just before a server changes levels
 ==================
 */
-void Host_Reconnect_f (void)
+void Host_Reconnect_f(cmd_state_t *cmd)
 {
        char temp[128];
        // if not connected, reconnect to the most recent server
@@ -510,7 +505,7 @@ void Host_Reconnect_f (void)
        else
        {
                // netquake uses reconnect on level changes (silly)
-               if (Cmd_Argc() != 1)
+               if (Cmd_Argc(cmd) != 1)
                {
                        Con_Print("reconnect : wait for signon messages again\n");
                        return;
@@ -531,9 +526,9 @@ Host_Connect_f
 User command to connect to server
 =====================
 */
-static void Host_Connect_f (void)
+static void Host_Connect_f(cmd_state_t *cmd)
 {
-       if (Cmd_Argc() < 2)
+       if (Cmd_Argc(cmd) < 2)
        {
                Con_Print("connect <serveraddress> [<key> <value> ...]: connect to a multiplayer game\n");
                return;
@@ -541,7 +536,7 @@ static void Host_Connect_f (void)
        // clear the rcon password, to prevent vulnerability by stuffcmd-ing a connect command
        if(rcon_secure.integer <= 0)
                Cvar_SetQuick(&rcon_password, "");
-       CL_EstablishConnection(Cmd_Argv(1), 2);
+       CL_EstablishConnection(Cmd_Argv(cmd, 1), 2);
 }
 
 
@@ -705,7 +700,7 @@ void Host_Savegame_to(prvm_prog_t *prog, const char *name)
 Host_Savegame_f
 ===============
 */
-static void Host_Savegame_f (void)
+static void Host_Savegame_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        char    name[MAX_QPATH];
@@ -737,19 +732,19 @@ static void Host_Savegame_f (void)
        else
                Con_Print("Warning: saving a multiplayer game may have strange results when restored (to properly resume, all players must join in the same player slots and then the game can be reloaded).\n");
 
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
                Con_Print("save <savename> : save a game\n");
                return;
        }
 
-       if (strstr(Cmd_Argv(1), ".."))
+       if (strstr(Cmd_Argv(cmd, 1), ".."))
        {
                Con_Print("Relative pathnames are not allowed.\n");
                return;
        }
 
-       strlcpy (name, Cmd_Argv(1), sizeof (name));
+       strlcpy (name, Cmd_Argv(cmd, 1), sizeof (name));
        FS_DefaultExtension (name, ".sav", sizeof (name));
 
        Host_Savegame_to(prog, name);
@@ -762,7 +757,7 @@ Host_Loadgame_f
 ===============
 */
 
-static void Host_Loadgame_f (void)
+static void Host_Loadgame_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        char filename[MAX_QPATH];
@@ -779,13 +774,13 @@ static void Host_Loadgame_f (void)
        float spawn_parms[NUM_SPAWN_PARMS];
        prvm_stringbuffer_t *stringbuffer;
 
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
                Con_Print("load <savename> : load a game\n");
                return;
        }
 
-       strlcpy (filename, Cmd_Argv(1), sizeof(filename));
+       strlcpy (filename, Cmd_Argv(cmd, 1), sizeof(filename));
        FS_DefaultExtension (filename, ".sav", sizeof (filename));
 
        Con_Printf("Loading game from %s...\n", filename);
@@ -1112,7 +1107,7 @@ Host_Name_f
 ======================
 */
 cvar_t cl_name = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_name", "player", "internal storage cvar for current player name (changed by name command)"};
-static void Host_Name_f (void)
+static void Host_Name_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        int i, j;
@@ -1120,23 +1115,23 @@ static void Host_Name_f (void)
        const char *newNameSource;
        char newName[sizeof(host_client->name)];
 
-       if (Cmd_Argc () == 1)
+       if (Cmd_Argc (cmd) == 1)
        {
-               if (cmd_source == src_command)
+               if (cmd->source == src_command)
                {
                        Con_Printf("name: %s\n", cl_name.string);
                }
                return;
        }
 
-       if (Cmd_Argc () == 2)
-               newNameSource = Cmd_Argv(1);
+       if (Cmd_Argc (cmd) == 2)
+               newNameSource = Cmd_Argv(cmd, 1);
        else
-               newNameSource = Cmd_Args();
+               newNameSource = Cmd_Args(cmd);
 
        strlcpy(newName, newNameSource, sizeof(newName));
 
-       if (cmd_source == src_command)
+       if (cmd->source == src_command)
        {
                Cvar_Set ("_cl_name", newName);
                if (strlen(newNameSource) >= sizeof(newName)) // overflowed
@@ -1244,32 +1239,32 @@ Host_Playermodel_f
 */
 cvar_t cl_playermodel = {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 Host_Playermodel_f (void)
+static void Host_Playermodel_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        int i, j;
        char newPath[sizeof(host_client->playermodel)];
 
-       if (Cmd_Argc () == 1)
+       if (Cmd_Argc (cmd) == 1)
        {
-               if (cmd_source == src_command)
+               if (cmd->source == src_command)
                {
                        Con_Printf("\"playermodel\" is \"%s\"\n", cl_playermodel.string);
                }
                return;
        }
 
-       if (Cmd_Argc () == 2)
-               strlcpy (newPath, Cmd_Argv(1), sizeof (newPath));
+       if (Cmd_Argc (cmd) == 2)
+               strlcpy (newPath, Cmd_Argv(cmd, 1), sizeof (newPath));
        else
-               strlcpy (newPath, Cmd_Args(), sizeof (newPath));
+               strlcpy (newPath, Cmd_Args(cmd), sizeof (newPath));
 
        for (i = 0, j = 0;newPath[i];i++)
                if (newPath[i] != '\r' && newPath[i] != '\n')
                        newPath[j++] = newPath[i];
        newPath[j] = 0;
 
-       if (cmd_source == src_command)
+       if (cmd->source == src_command)
        {
                Cvar_Set ("_cl_playermodel", newPath);
                return;
@@ -1304,32 +1299,32 @@ Host_Playerskin_f
 ======================
 */
 cvar_t cl_playerskin = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_playerskin", "", "internal storage cvar for current player skin in Nexuiz/Xonotic (changed by playerskin command)"};
-static void Host_Playerskin_f (void)
+static void Host_Playerskin_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        int i, j;
        char newPath[sizeof(host_client->playerskin)];
 
-       if (Cmd_Argc () == 1)
+       if (Cmd_Argc (cmd) == 1)
        {
-               if (cmd_source == src_command)
+               if (cmd->source == src_command)
                {
                        Con_Printf("\"playerskin\" is \"%s\"\n", cl_playerskin.string);
                }
                return;
        }
 
-       if (Cmd_Argc () == 2)
-               strlcpy (newPath, Cmd_Argv(1), sizeof (newPath));
+       if (Cmd_Argc (cmd) == 2)
+               strlcpy (newPath, Cmd_Argv(cmd, 1), sizeof (newPath));
        else
-               strlcpy (newPath, Cmd_Args(), sizeof (newPath));
+               strlcpy (newPath, Cmd_Args(cmd), sizeof (newPath));
 
        for (i = 0, j = 0;newPath[i];i++)
                if (newPath[i] != '\r' && newPath[i] != '\n')
                        newPath[j++] = newPath[i];
        newPath[j] = 0;
 
-       if (cmd_source == src_command)
+       if (cmd->source == src_command)
        {
                Cvar_Set ("_cl_playerskin", newPath);
                return;
@@ -1360,12 +1355,12 @@ static void Host_Playerskin_f (void)
        }
 }
 
-static void Host_Version_f (void)
+static void Host_Version_f(cmd_state_t *cmd)
 {
        Con_Printf("Version: %s build %s\n", gamename, buildstring);
 }
 
-static void Host_Say(qboolean teamonly)
+static void Host_Say(cmd_state_t *cmd, qboolean teamonly)
 {
        prvm_prog_t *prog = SVVM_prog;
        client_t *save;
@@ -1376,7 +1371,7 @@ static void Host_Say(qboolean teamonly)
        char text[1024];
        qboolean fromServer = false;
 
-       if (cmd_source == src_command)
+       if (cmd->source == src_command)
        {
                if (cls.state == ca_dedicated)
                {
@@ -1385,18 +1380,18 @@ static void Host_Say(qboolean teamonly)
                }
                else
                {
-                       Cmd_ForwardToServer ();
+                       Cmd_ForwardToServer_f(cmd);
                        return;
                }
        }
 
-       if (Cmd_Argc () < 2)
+       if (Cmd_Argc (cmd) < 2)
                return;
 
        if (!teamplay.integer)
                teamonly = false;
 
-       p1 = Cmd_Args();
+       p1 = Cmd_Args(cmd);
        quoted = false;
        if (*p1 == '\"')
        {
@@ -1434,19 +1429,19 @@ static void Host_Say(qboolean teamonly)
 }
 
 
-static void Host_Say_f(void)
+static void Host_Say_f(cmd_state_t *cmd)
 {
-       Host_Say(false);
+       Host_Say(cmd, false);
 }
 
 
-static void Host_Say_Team_f(void)
+static void Host_Say_Team_f(cmd_state_t *cmd)
 {
-       Host_Say(true);
+       Host_Say(cmd, true);
 }
 
 
-static void Host_Tell_f(void)
+static void Host_Tell_f(cmd_state_t *cmd)
 {
        const char *playername_start = NULL;
        size_t playername_length = 0;
@@ -1457,18 +1452,18 @@ static void Host_Tell_f(void)
        char text[MAX_INPUTLINE]; // LadyHavoc: FIXME: temporary buffer overflow fix (was 64)
        qboolean fromServer = false;
 
-       if (cmd_source == src_command)
+       if (cmd->source == src_command)
        {
                if (cls.state == ca_dedicated)
                        fromServer = true;
                else
                {
-                       Cmd_ForwardToServer ();
+                       Cmd_ForwardToServer_f(cmd);
                        return;
                }
        }
 
-       if (Cmd_Argc () < 2)
+       if (Cmd_Argc (cmd) < 2)
                return;
 
        // note this uses the chat prefix \001
@@ -1479,7 +1474,7 @@ static void Host_Tell_f(void)
        else
                dpsnprintf (text, sizeof(text), "\001<%s tells you> ", hostname.string);
 
-       p1 = Cmd_Args();
+       p1 = Cmd_Args(cmd);
        p2 = p1 + strlen(p1);
        // remove the target name
        while (p1 < p2 && *p1 == ' ')
@@ -1581,7 +1576,7 @@ Host_Color_f
 ==================
 */
 cvar_t cl_color = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_color", "0", "internal storage cvar for current player colors (changed by color command)"};
-static void Host_Color(int changetop, int changebottom)
+static void Host_Color(cmd_state_t *cmd, int changetop, int changebottom)
 {
        prvm_prog_t *prog = SVVM_prog;
        int top, bottom, playercolor;
@@ -1601,7 +1596,7 @@ static void Host_Color(int changetop, int changebottom)
 
        playercolor = top*16 + bottom;
 
-       if (cmd_source == src_command)
+       if (cmd->source == src_command)
        {
                Cvar_SetValueQuick(&cl_color, playercolor);
                return;
@@ -1637,13 +1632,13 @@ static void Host_Color(int changetop, int changebottom)
        }
 }
 
-static void Host_Color_f(void)
+static void Host_Color_f(cmd_state_t *cmd)
 {
        int             top, bottom;
 
-       if (Cmd_Argc() == 1)
+       if (Cmd_Argc(cmd) == 1)
        {
-               if (cmd_source == src_command)
+               if (cmd->source == src_command)
                {
                        Con_Printf("\"color\" is \"%i %i\"\n", cl_color.integer >> 4, cl_color.integer & 15);
                        Con_Print("color <0-15> [0-15]\n");
@@ -1651,21 +1646,21 @@ static void Host_Color_f(void)
                return;
        }
 
-       if (Cmd_Argc() == 2)
-               top = bottom = atoi(Cmd_Argv(1));
+       if (Cmd_Argc(cmd) == 2)
+               top = bottom = atoi(Cmd_Argv(cmd, 1));
        else
        {
-               top = atoi(Cmd_Argv(1));
-               bottom = atoi(Cmd_Argv(2));
+               top = atoi(Cmd_Argv(cmd, 1));
+               bottom = atoi(Cmd_Argv(cmd, 2));
        }
-       Host_Color(top, bottom);
+       Host_Color(cmd, top, bottom);
 }
 
-static void Host_TopColor_f(void)
+static void Host_TopColor_f(cmd_state_t *cmd)
 {
-       if (Cmd_Argc() == 1)
+       if (Cmd_Argc(cmd) == 1)
        {
-               if (cmd_source == src_command)
+               if (cmd->source == src_command)
                {
                        Con_Printf("\"topcolor\" is \"%i\"\n", (cl_color.integer >> 4) & 15);
                        Con_Print("topcolor <0-15>\n");
@@ -1673,14 +1668,14 @@ static void Host_TopColor_f(void)
                return;
        }
 
-       Host_Color(atoi(Cmd_Argv(1)), -1);
+       Host_Color(cmd, atoi(Cmd_Argv(cmd, 1)), -1);
 }
 
-static void Host_BottomColor_f(void)
+static void Host_BottomColor_f(cmd_state_t *cmd)
 {
-       if (Cmd_Argc() == 1)
+       if (Cmd_Argc(cmd) == 1)
        {
-               if (cmd_source == src_command)
+               if (cmd->source == src_command)
                {
                        Con_Printf("\"bottomcolor\" is \"%i\"\n", cl_color.integer & 15);
                        Con_Print("bottomcolor <0-15>\n");
@@ -1688,18 +1683,18 @@ static void Host_BottomColor_f(void)
                return;
        }
 
-       Host_Color(-1, atoi(Cmd_Argv(1)));
+       Host_Color(cmd, -1, atoi(Cmd_Argv(cmd, 1)));
 }
 
 cvar_t cl_rate = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_rate", "20000", "internal storage cvar for current rate (changed by rate command)"};
 cvar_t cl_rate_burstsize = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_rate_burstsize", "1024", "internal storage cvar for current rate control burst size (changed by rate_burstsize command)"};
-static void Host_Rate_f(void)
+static void Host_Rate_f(cmd_state_t *cmd)
 {
        int rate;
 
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
-               if (cmd_source == src_command)
+               if (cmd->source == src_command)
                {
                        Con_Printf("\"rate\" is \"%i\"\n", cl_rate.integer);
                        Con_Print("rate <bytespersecond>\n");
@@ -1707,9 +1702,9 @@ static void Host_Rate_f(void)
                return;
        }
 
-       rate = atoi(Cmd_Argv(1));
+       rate = atoi(Cmd_Argv(cmd, 1));
 
-       if (cmd_source == src_command)
+       if (cmd->source == src_command)
        {
                Cvar_SetValue ("_cl_rate", max(NET_MINRATE, rate));
                return;
@@ -1717,20 +1712,20 @@ static void Host_Rate_f(void)
 
        host_client->rate = rate;
 }
-static void Host_Rate_BurstSize_f(void)
+static void Host_Rate_BurstSize_f(cmd_state_t *cmd)
 {
        int rate_burstsize;
 
-       if (Cmd_Argc() != 2)
+       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(1));
+       rate_burstsize = atoi(Cmd_Argv(cmd, 1));
 
-       if (cmd_source == src_command)
+       if (cmd->source == src_command)
        {
                Cvar_SetValue ("_cl_rate_burstsize", rate_burstsize);
                return;
@@ -1744,7 +1739,7 @@ static void Host_Rate_BurstSize_f(void)
 Host_Kill_f
 ==================
 */
-static void Host_Kill_f (void)
+static void Host_Kill_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        if (PRVM_serveredictfloat(host_client->edict, health) <= 0)
@@ -1764,15 +1759,15 @@ static void Host_Kill_f (void)
 Host_Pause_f
 ==================
 */
-static void Host_Pause_f (void)
+static void Host_Pause_f(cmd_state_t *cmd)
 {
        void (*print) (const char *fmt, ...);
-       if (cmd_source == src_command)
+       if (cmd->source == src_command)
        {
                // if running a client, try to send over network so the pause is handled by the server
                if (cls.state == ca_connected)
                {
-                       Cmd_ForwardToServer ();
+                       Cmd_ForwardToServer_f(cmd);
                        return;
                }
                print = Con_Printf;
@@ -1782,7 +1777,7 @@ static void Host_Pause_f (void)
 
        if (!pausable.integer)
        {
-               if (cmd_source == src_client)
+               if (cmd->source == src_client)
                {
                        if(cls.state == ca_dedicated || host_client != &svs.clients[0]) // non-admin
                        {
@@ -1793,7 +1788,7 @@ static void Host_Pause_f (void)
        }
        
        sv.paused ^= 1;
-       if (cmd_source != src_command)
+       if (cmd->source != src_command)
                SV_BroadcastPrintf("%s %spaused the game\n", host_client->name, sv.paused ? "" : "un");
        else if(*(sv_adminnick.string))
                SV_BroadcastPrintf("%s %spaused the game\n", sv_adminnick.string, sv.paused ? "" : "un");
@@ -1812,28 +1807,28 @@ LadyHavoc: correction, Mindcrime will be removing pmodel in the future, but it's
 ======================
 */
 cvar_t cl_pmodel = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_pmodel", "0", "internal storage cvar for current player model number in nehahra (changed by pmodel command)"};
-static void Host_PModel_f (void)
+static void Host_PModel_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        int i;
 
-       if (Cmd_Argc () == 1)
+       if (Cmd_Argc (cmd) == 1)
        {
-               if (cmd_source == src_command)
+               if (cmd->source == src_command)
                {
                        Con_Printf("\"pmodel\" is \"%s\"\n", cl_pmodel.string);
                }
                return;
        }
-       i = atoi(Cmd_Argv(1));
+       i = atoi(Cmd_Argv(cmd, 1));
 
-       if (cmd_source == src_command)
+       if (cmd->source == src_command)
        {
                if (cl_pmodel.integer == i)
                        return;
                Cvar_SetValue ("_cl_pmodel", i);
                if (cls.state == ca_connected)
-                       Cmd_ForwardToServer ();
+                       Cmd_ForwardToServer_f(cmd);
                return;
        }
 
@@ -1848,7 +1843,7 @@ static void Host_PModel_f (void)
 Host_PreSpawn_f
 ==================
 */
-static void Host_PreSpawn_f (void)
+static void Host_PreSpawn_f(cmd_state_t *cmd)
 {
        if (host_client->prespawned)
        {
@@ -1874,7 +1869,7 @@ static void Host_PreSpawn_f (void)
 Host_Spawn_f
 ==================
 */
-static void Host_Spawn_f (void)
+static void Host_Spawn_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        int i;
@@ -2017,7 +2012,7 @@ static void Host_Spawn_f (void)
 Host_Begin_f
 ==================
 */
-static void Host_Begin_f (void)
+static void Host_Begin_f(cmd_state_t *cmd)
 {
        if (!host_client->spawned)
        {
@@ -2056,7 +2051,7 @@ Host_Kick_f
 Kicks a user off of the server
 ==================
 */
-static void Host_Kick_f (void)
+static void Host_Kick_f(cmd_state_t *cmd)
 {
        const char *who;
        const char *message = NULL;
@@ -2069,9 +2064,9 @@ static void Host_Kick_f (void)
 
        save = host_client;
 
-       if (Cmd_Argc() > 2 && strcmp(Cmd_Argv(1), "#") == 0)
+       if (Cmd_Argc(cmd) > 2 && strcmp(Cmd_Argv(cmd, 1), "#") == 0)
        {
-               i = (int)(atof(Cmd_Argv(2)) - 1);
+               i = (int)(atof(Cmd_Argv(cmd, 2)) - 1);
                if (i < 0 || i >= svs.maxclients || !(host_client = svs.clients + i)->active)
                        return;
                byNumber = true;
@@ -2082,14 +2077,14 @@ static void Host_Kick_f (void)
                {
                        if (!host_client->active)
                                continue;
-                       if (strcasecmp(host_client->name, Cmd_Argv(1)) == 0)
+                       if (strcasecmp(host_client->name, Cmd_Argv(cmd, 1)) == 0)
                                break;
                }
        }
 
        if (i < svs.maxclients)
        {
-               if (cmd_source == src_command)
+               if (cmd->source == src_command)
                {
                        if (cls.state == ca_dedicated)
                                who = "Console";
@@ -2103,16 +2098,16 @@ static void Host_Kick_f (void)
                if (host_client == save)
                        return;
 
-               if (Cmd_Argc() > 2)
+               if (Cmd_Argc(cmd) > 2)
                {
-                       message = Cmd_Args();
+                       message = Cmd_Args(cmd);
                        COM_ParseToken_Simple(&message, false, false, true);
                        if (byNumber)
                        {
                                message++;                                                      // skip the #
                                while (*message == ' ')                         // skip white space
                                        message++;
-                               message += strlen(Cmd_Argv(2)); // skip the number
+                               message += strlen(Cmd_Argv(cmd, 2));    // skip the number
                        }
                        while (*message && *message == ' ')
                                message++;
@@ -2140,7 +2135,7 @@ DEBUGGING TOOLS
 Host_Give_f
 ==================
 */
-static void Host_Give_f (void)
+static void Host_Give_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        const char *t;
@@ -2152,8 +2147,8 @@ static void Host_Give_f (void)
                return;
        }
 
-       t = Cmd_Argv(1);
-       v = atoi (Cmd_Argv(2));
+       t = Cmd_Argv(cmd, 1);
+       v = atoi (Cmd_Argv(cmd, 2));
 
        switch (t[0])
        {
@@ -2283,7 +2278,7 @@ static prvm_edict_t       *FindViewthing(prvm_prog_t *prog)
 Host_Viewmodel_f
 ==================
 */
-static void Host_Viewmodel_f (void)
+static void Host_Viewmodel_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        prvm_edict_t    *e;
@@ -2295,14 +2290,14 @@ static void Host_Viewmodel_f (void)
        e = FindViewthing(prog);
        if (e)
        {
-               m = Mod_ForName (Cmd_Argv(1), false, true, NULL);
+               m = Mod_ForName (Cmd_Argv(cmd, 1), false, true, NULL);
                if (m && m->loaded && m->Draw)
                {
                        PRVM_serveredictfloat(e, frame) = 0;
                        cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)] = m;
                }
                else
-                       Con_Printf("viewmodel: can't load %s\n", Cmd_Argv(1));
+                       Con_Printf("viewmodel: can't load %s\n", Cmd_Argv(cmd, 1));
        }
 }
 
@@ -2311,7 +2306,7 @@ static void Host_Viewmodel_f (void)
 Host_Viewframe_f
 ==================
 */
-static void Host_Viewframe_f (void)
+static void Host_Viewframe_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        prvm_edict_t    *e;
@@ -2326,7 +2321,7 @@ static void Host_Viewframe_f (void)
        {
                m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
 
-               f = atoi(Cmd_Argv(1));
+               f = atoi(Cmd_Argv(cmd, 1));
                if (f >= m->numframes)
                        f = m->numframes-1;
 
@@ -2348,7 +2343,7 @@ static void PrintFrameName (dp_model_t *m, int frame)
 Host_Viewnext_f
 ==================
 */
-static void Host_Viewnext_f (void)
+static void Host_Viewnext_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        prvm_edict_t    *e;
@@ -2375,7 +2370,7 @@ static void Host_Viewnext_f (void)
 Host_Viewprev_f
 ==================
 */
-static void Host_Viewprev_f (void)
+static void Host_Viewprev_f(cmd_state_t *cmd)
 {
        prvm_prog_t *prog = SVVM_prog;
        prvm_edict_t    *e;
@@ -2411,14 +2406,14 @@ DEMO LOOP CONTROL
 Host_Startdemos_f
 ==================
 */
-static void Host_Startdemos_f (void)
+static void Host_Startdemos_f(cmd_state_t *cmd)
 {
        int             i, c;
 
        if (cls.state == ca_dedicated || COM_CheckParm("-listen") || COM_CheckParm("-benchmark") || COM_CheckParm("-demo") || COM_CheckParm("-capturedemo"))
                return;
 
-       c = Cmd_Argc() - 1;
+       c = Cmd_Argc(cmd) - 1;
        if (c > MAX_DEMOS)
        {
                Con_Printf("Max %i demos in demoloop\n", MAX_DEMOS);
@@ -2427,7 +2422,7 @@ static void Host_Startdemos_f (void)
        Con_DPrintf("%i demo(s) in loop\n", c);
 
        for (i=1 ; i<c+1 ; i++)
-               strlcpy (cls.demos[i-1], Cmd_Argv(i), sizeof (cls.demos[i-1]));
+               strlcpy (cls.demos[i-1], Cmd_Argv(cmd, i), sizeof (cls.demos[i-1]));
 
        // LadyHavoc: clear the remaining slots
        for (;i <= MAX_DEMOS;i++)
@@ -2450,13 +2445,13 @@ Host_Demos_f
 Return to looping demos
 ==================
 */
-static void Host_Demos_f (void)
+static void Host_Demos_f(cmd_state_t *cmd)
 {
        if (cls.state == ca_dedicated)
                return;
        if (cls.demonum == -1)
                cls.demonum = 1;
-       CL_Disconnect_f ();
+       CL_Disconnect_f (cmd);
        CL_NextDemo ();
 }
 
@@ -2467,7 +2462,7 @@ Host_Stopdemo_f
 Return to looping demos
 ==================
 */
-static void Host_Stopdemo_f (void)
+static void Host_Stopdemo_f(cmd_state_t *cmd)
 {
        if (!cls.demoplayback)
                return;
@@ -2475,7 +2470,7 @@ static void Host_Stopdemo_f (void)
        Host_ShutdownServer ();
 }
 
-static void Host_SendCvar_f (void)
+static void Host_SendCvar_f(cmd_state_t *cmd)
 {
        int             i;
        cvar_t  *c;
@@ -2483,9 +2478,9 @@ static void Host_SendCvar_f (void)
        client_t *old;
        char vabuf[1024];
 
-       if(Cmd_Argc() != 2)
+       if(Cmd_Argc(cmd) != 2)
                return;
-       cvarname = Cmd_Argv(1);
+       cvarname = Cmd_Argv(cmd, 1);
        if (cls.state == ca_connected)
        {
                c = Cvar_FindVar(cvarname);
@@ -2514,11 +2509,11 @@ static void Host_SendCvar_f (void)
        host_client = old;
 }
 
-static void MaxPlayers_f(void)
+static void MaxPlayers_f(cmd_state_t *cmd)
 {
        int n;
 
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
                Con_Printf("\"maxplayers\" is \"%u\"\n", svs.maxclients_next);
                return;
@@ -2530,7 +2525,7 @@ static void MaxPlayers_f(void)
                Con_Print("It will be changed on next server startup (\"map\" command).\n");
        }
 
-       n = atoi(Cmd_Argv(1));
+       n = atoi(Cmd_Argv(cmd, 1));
        n = bound(1, n, MAX_SCOREBOARD);
        Con_Printf("\"maxplayers\" set to \"%u\"\n", n);
 
@@ -2548,15 +2543,15 @@ Host_PQRcon_f
 ProQuake rcon support
 =====================
 */
-static void Host_PQRcon_f (void)
+static void Host_PQRcon_f(cmd_state_t *cmd)
 {
        int n;
        const char *e;
        lhnetsocket_t *mysocket;
 
-       if (Cmd_Argc() == 1)
+       if (Cmd_Argc(cmd) == 1)
        {
-               Con_Printf("%s: Usage: %s command\n", Cmd_Argv(0), Cmd_Argv(0));
+               Con_Printf("%s: Usage: %s command\n", Cmd_Argv(cmd, 0), Cmd_Argv(cmd, 0));
                return;
        }
 
@@ -2591,7 +2586,7 @@ static void Host_PQRcon_f (void)
                MSG_WriteByte(&buf, CCREQ_RCON);
                SZ_Write(&buf, (const unsigned char*)rcon_password.string, n);
                MSG_WriteByte(&buf, 0); // terminate the (possibly partial) string
-               MSG_WriteString(&buf, Cmd_Args());
+               MSG_WriteString(&buf, Cmd_Args(cmd));
                StoreBigLong(buf.data, NETFLAG_CTL | (buf.cursize & NETFLAG_LENGTH_MASK));
                NetConn_Write(mysocket, buf.data, buf.cursize, &cls.rcon_address);
                SZ_Clear(&buf);
@@ -2610,15 +2605,15 @@ Host_Rcon_f
   an unconnected command.
 =====================
 */
-static void Host_Rcon_f (void) // credit: taken from QuakeWorld
+static void Host_Rcon_f(cmd_state_t *cmd) // credit: taken from QuakeWorld
 {
        int i, n;
        const char *e;
        lhnetsocket_t *mysocket;
 
-       if (Cmd_Argc() == 1)
+       if (Cmd_Argc(cmd) == 1)
        {
-               Con_Printf("%s: Usage: %s command\n", Cmd_Argv(0), Cmd_Argv(0));
+               Con_Printf("%s: Usage: %s command\n", Cmd_Argv(cmd, 0), Cmd_Argv(cmd, 0));
                return;
        }
 
@@ -2643,10 +2638,10 @@ static void Host_Rcon_f (void) // credit: taken from QuakeWorld
                LHNETADDRESS_FromString(&cls.rcon_address, rcon_address.string, sv_netport.integer);
        }
        mysocket = NetConn_ChooseClientSocketForAddress(&cls.rcon_address);
-       if (mysocket && Cmd_Args()[0])
+       if (mysocket && Cmd_Args(cmd)[0])
        {
                // simply put together the rcon packet and send it
-               if(Cmd_Argv(0)[0] == 's' || rcon_secure.integer > 1)
+               if(Cmd_Argv(cmd, 0)[0] == 's' || rcon_secure.integer > 1)
                {
                        if(cls.rcon_commands[cls.rcon_ringpos][0])
                        {
@@ -2663,7 +2658,7 @@ static void Host_Rcon_f (void) // credit: taken from QuakeWorld
                        ++cls.rcon_trying;
                        if(i >= MAX_RCONS)
                                NetConn_WriteString(mysocket, "\377\377\377\377getchallenge", &cls.rcon_address); // otherwise we'll request the challenge later
-                       strlcpy(cls.rcon_commands[cls.rcon_ringpos], Cmd_Args(), sizeof(cls.rcon_commands[cls.rcon_ringpos]));
+                       strlcpy(cls.rcon_commands[cls.rcon_ringpos], Cmd_Args(cmd), sizeof(cls.rcon_commands[cls.rcon_ringpos]));
                        cls.rcon_addresses[cls.rcon_ringpos] = cls.rcon_address;
                        cls.rcon_timeout[cls.rcon_ringpos] = realtime + rcon_secure_challengetimeout.value;
                        cls.rcon_ringpos = (cls.rcon_ringpos + 1) % MAX_RCONS;
@@ -2672,7 +2667,7 @@ static void Host_Rcon_f (void) // credit: taken from QuakeWorld
                {
                        char buf[1500];
                        char argbuf[1500];
-                       dpsnprintf(argbuf, sizeof(argbuf), "%ld.%06d %s", (long) time(NULL), (int) (rand() % 1000000), Cmd_Args());
+                       dpsnprintf(argbuf, sizeof(argbuf), "%ld.%06d %s", (long) time(NULL), (int) (rand() % 1000000), Cmd_Args(cmd));
                        memcpy(buf, "\377\377\377\377srcon HMAC-MD4 TIME ", 24);
                        if(HMAC_MDFOUR_16BYTES((unsigned char *) (buf + 24), (unsigned char *) argbuf, (int)strlen(argbuf), (unsigned char *) rcon_password.string, n))
                        {
@@ -2685,7 +2680,7 @@ static void Host_Rcon_f (void) // credit: taken from QuakeWorld
                {
                        char buf[1500];
                        memcpy(buf, "\377\377\377\377", 4);
-                       dpsnprintf(buf+4, sizeof(buf)-4, "rcon %.*s %s",  n, rcon_password.string, Cmd_Args());
+                       dpsnprintf(buf+4, sizeof(buf)-4, "rcon %.*s %s",  n, rcon_password.string, Cmd_Args(cmd));
                        NetConn_WriteString(mysocket, buf, &cls.rcon_address);
                }
        }
@@ -2700,24 +2695,24 @@ user <name or userid>
 Dump userdata / masterdata for a user
 ====================
 */
-static void Host_User_f (void) // credit: taken from QuakeWorld
+static void Host_User_f(cmd_state_t *cmd) // credit: taken from QuakeWorld
 {
        int             uid;
        int             i;
 
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
                Con_Printf ("Usage: user <username / userid>\n");
                return;
        }
 
-       uid = atoi(Cmd_Argv(1));
+       uid = atoi(Cmd_Argv(cmd, 1));
 
        for (i = 0;i < cl.maxclients;i++)
        {
                if (!cl.scores[i].name[0])
                        continue;
-               if (cl.scores[i].qw_userid == uid || !strcasecmp(cl.scores[i].name, Cmd_Argv(1)))
+               if (cl.scores[i].qw_userid == uid || !strcasecmp(cl.scores[i].name, Cmd_Argv(cmd, 1)))
                {
                        InfoString_Print(cl.scores[i].qw_userinfo);
                        return;
@@ -2733,7 +2728,7 @@ Host_Users_f
 Dump userids for all current players
 ====================
 */
-static void Host_Users_f (void) // credit: taken from QuakeWorld
+static void Host_Users_f(cmd_state_t *cmd) // credit: taken from QuakeWorld
 {
        int             i;
        int             c;
@@ -2761,16 +2756,16 @@ Sent by server when serverinfo changes
 ==================
 */
 // TODO: shouldn't this be a cvar instead?
-static void Host_FullServerinfo_f (void) // credit: taken from QuakeWorld
+static void Host_FullServerinfo_f(cmd_state_t *cmd) // credit: taken from QuakeWorld
 {
        char temp[512];
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
                Con_Printf ("usage: fullserverinfo <complete info string>\n");
                return;
        }
 
-       strlcpy (cl.qw_serverinfo, Cmd_Argv(1), sizeof(cl.qw_serverinfo));
+       strlcpy (cl.qw_serverinfo, Cmd_Argv(cmd, 1), sizeof(cl.qw_serverinfo));
        InfoString_GetValue(cl.qw_serverinfo, "teamplay", temp, sizeof(temp));
        cl.qw_teamplay = atoi(temp);
 }
@@ -2783,19 +2778,19 @@ Allow clients to change userinfo
 ==================
 Casey was here :)
 */
-static void Host_FullInfo_f (void) // credit: taken from QuakeWorld
+static void Host_FullInfo_f(cmd_state_t *cmd) // credit: taken from QuakeWorld
 {
        char key[512];
        char value[512];
        const char *s;
 
-       if (Cmd_Argc() != 2)
+       if (Cmd_Argc(cmd) != 2)
        {
                Con_Printf ("fullinfo <complete info string>\n");
                return;
        }
 
-       s = Cmd_Argv(1);
+       s = Cmd_Argv(cmd, 1);
        if (*s == '\\')
                s++;
        while (*s)
@@ -2837,19 +2832,19 @@ CL_SetInfo_f
 Allow clients to change userinfo
 ==================
 */
-static void Host_SetInfo_f (void) // credit: taken from QuakeWorld
+static void Host_SetInfo_f(cmd_state_t *cmd) // credit: taken from QuakeWorld
 {
-       if (Cmd_Argc() == 1)
+       if (Cmd_Argc(cmd) == 1)
        {
                InfoString_Print(cls.userinfo);
                return;
        }
-       if (Cmd_Argc() != 3)
+       if (Cmd_Argc(cmd) != 3)
        {
                Con_Printf ("usage: setinfo [ <key> <value> ]\n");
                return;
        }
-       CL_SetInfo(Cmd_Argv(1), Cmd_Argv(2), true, false, false, false);
+       CL_SetInfo(Cmd_Argv(cmd, 1), Cmd_Argv(cmd, 2), true, false, false, false);
 }
 
 /*
@@ -2861,7 +2856,7 @@ packet <destination> <contents>
 Contents allows \n escape character
 ====================
 */
-static void Host_Packet_f (void) // credit: taken from QuakeWorld
+static void Host_Packet_f(cmd_state_t *cmd) // credit: taken from QuakeWorld
 {
        char send[2048];
        int i, l;
@@ -2870,19 +2865,19 @@ static void Host_Packet_f (void) // credit: taken from QuakeWorld
        lhnetaddress_t address;
        lhnetsocket_t *mysocket;
 
-       if (Cmd_Argc() != 3)
+       if (Cmd_Argc(cmd) != 3)
        {
                Con_Printf ("packet <destination> <contents>\n");
                return;
        }
 
-       if (!LHNETADDRESS_FromString (&address, Cmd_Argv(1), sv_netport.integer))
+       if (!LHNETADDRESS_FromString (&address, Cmd_Argv(cmd, 1), sv_netport.integer))
        {
                Con_Printf ("Bad address\n");
                return;
        }
 
-       in = Cmd_Argv(2);
+       in = Cmd_Argv(cmd, 2);
        out = send+4;
        send[0] = send[1] = send[2] = send[3] = -1;
 
@@ -2934,7 +2929,7 @@ Host_Pings_f
 Send back ping and packet loss update for all current players to this player
 ====================
 */
-void Host_Pings_f (void)
+void Host_Pings_f(cmd_state_t *cmd)
 {
        int             i, j, ping, packetloss, movementloss;
        char temp[128];
@@ -2986,17 +2981,17 @@ void Host_Pings_f (void)
                MSG_WriteString(&host_client->netconnection->message, "\n");
 }
 
-static void Host_PingPLReport_f(void)
+static void Host_PingPLReport_f(cmd_state_t *cmd)
 {
        char *errbyte;
        int i;
-       int l = Cmd_Argc();
+       int l = Cmd_Argc(cmd);
        if (l > cl.maxclients)
                l = cl.maxclients;
        for (i = 0;i < l;i++)
        {
-               cl.scores[i].qw_ping = atoi(Cmd_Argv(1+i*2));
-               cl.scores[i].qw_packetloss = strtol(Cmd_Argv(1+i*2+1), &errbyte, 0);
+               cl.scores[i].qw_ping = atoi(Cmd_Argv(cmd, 1+i*2));
+               cl.scores[i].qw_packetloss = strtol(Cmd_Argv(cmd, 1+i*2+1), &errbyte, 0);
                if(errbyte && *errbyte == ',')
                        cl.scores[i].qw_movementloss = atoi(errbyte + 1);
                else
@@ -3015,95 +3010,142 @@ 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");
 
-       Cmd_AddCommand_WithClientCommand ("status", Host_Status_f, Host_Status_f, "print server status information");
-       Cmd_AddCommand ("quit", Host_Quit_f, "quit the game");
-       Cmd_AddCommand_WithClientCommand ("god", NULL, Host_God_f, "god mode (invulnerability)");
-       Cmd_AddCommand_WithClientCommand ("notarget", NULL, Host_Notarget_f, "notarget mode (monsters do not see you)");
-       Cmd_AddCommand_WithClientCommand ("fly", NULL, Host_Fly_f, "fly mode (flight)");
-       Cmd_AddCommand_WithClientCommand ("noclip", NULL, Host_Noclip_f, "noclip mode (flight without collisions, move through walls)");
-       Cmd_AddCommand_WithClientCommand ("give", NULL, Host_Give_f, "alter inventory");
-       Cmd_AddCommand ("map", Host_Map_f, "kick everyone off the server and start a new level");
-       Cmd_AddCommand ("restart", Host_Restart_f, "restart current level");
-       Cmd_AddCommand ("changelevel", Host_Changelevel_f, "change to another level, bringing along all connected clients");
-       Cmd_AddCommand ("connect", Host_Connect_f, "connect to a server by IP address or hostname");
-       Cmd_AddCommand ("reconnect", Host_Reconnect_f, "reconnect to the last server you were on, or resets a quakeworld connection (do not use if currently playing on a netquake server)");
-       Cmd_AddCommand ("version", Host_Version_f, "print engine version");
-       Cmd_AddCommand_WithClientCommand ("say", Host_Say_f, Host_Say_f, "send a chat message to everyone on the server");
-       Cmd_AddCommand_WithClientCommand ("say_team", Host_Say_Team_f, Host_Say_Team_f, "send a chat message to your team on the server");
-       Cmd_AddCommand_WithClientCommand ("tell", Host_Tell_f, Host_Tell_f, "send a chat message to only one person on the server");
-       Cmd_AddCommand_WithClientCommand ("kill", NULL, Host_Kill_f, "die instantly");
-       Cmd_AddCommand_WithClientCommand ("pause", Host_Pause_f, Host_Pause_f, "pause the game (if the server allows pausing)");
-       Cmd_AddCommand ("kick", Host_Kick_f, "kick a player off the server by number or name");
-       Cmd_AddCommand_WithClientCommand ("ping", Host_Ping_f, Host_Ping_f, "print ping times of all players on the server");
-       Cmd_AddCommand ("load", Host_Loadgame_f, "load a saved game file");
-       Cmd_AddCommand ("save", Host_Savegame_f, "save the game to a file");
-
-       Cmd_AddCommand ("startdemos", Host_Startdemos_f, "start playing back the selected demos sequentially (used at end of startup script)");
-       Cmd_AddCommand ("demos", Host_Demos_f, "restart looping demos defined by the last startdemos command");
-       Cmd_AddCommand ("stopdemo", Host_Stopdemo_f, "stop playing or recording demo (like stop command) and return to looping demos");
-
-       Cmd_AddCommand ("viewmodel", Host_Viewmodel_f, "change model of viewthing entity in current level");
-       Cmd_AddCommand ("viewframe", Host_Viewframe_f, "change animation frame of viewthing entity in current level");
-       Cmd_AddCommand ("viewnext", Host_Viewnext_f, "change to next animation frame of viewthing entity in current level");
-       Cmd_AddCommand ("viewprev", Host_Viewprev_f, "change to previous animation frame of viewthing entity in current level");
-
-       Cvar_RegisterVariable (&cl_name);
-       Cmd_AddCommand_WithClientCommand ("name", Host_Name_f, Host_Name_f, "change your player name");
-       Cvar_RegisterVariable (&cl_color);
-       Cmd_AddCommand_WithClientCommand ("color", Host_Color_f, Host_Color_f, "change your player shirt and pants colors");
-       Cvar_RegisterVariable (&cl_rate);
-       Cmd_AddCommand_WithClientCommand ("rate", Host_Rate_f, Host_Rate_f, "change your network connection speed");
-       Cvar_RegisterVariable (&cl_rate_burstsize);
-       Cmd_AddCommand_WithClientCommand ("rate_burstsize", Host_Rate_BurstSize_f, Host_Rate_BurstSize_f, "change your network connection speed");
-       Cvar_RegisterVariable (&cl_pmodel);
-       Cmd_AddCommand_WithClientCommand ("pmodel", Host_PModel_f, Host_PModel_f, "(Nehahra-only) change your player model choice");
-
-       // BLACK: This isnt game specific anymore (it was GAME_NEXUIZ at first)
-       Cvar_RegisterVariable (&cl_playermodel);
-       Cmd_AddCommand_WithClientCommand ("playermodel", Host_Playermodel_f, Host_Playermodel_f, "change your player model");
-       Cvar_RegisterVariable (&cl_playerskin);
-       Cmd_AddCommand_WithClientCommand ("playerskin", Host_Playerskin_f, Host_Playerskin_f, "change your player skin number");
-
-       Cmd_AddCommand_WithClientCommand ("prespawn", NULL, Host_PreSpawn_f, "signon 1 (client acknowledges that server information has been received)");
-       Cmd_AddCommand_WithClientCommand ("spawn", NULL, Host_Spawn_f, "signon 2 (client has sent player information, and is asking server to send scoreboard rankings)");
-       Cmd_AddCommand_WithClientCommand ("begin", NULL, Host_Begin_f, "signon 3 (client asks server to start sending entities, and will go to signon 4 (playing) when the first entity update is received)");
-       Cmd_AddCommand ("maxplayers", MaxPlayers_f, "sets limit on how many players (or bots) may be connected to the server at once");
-
-       Cmd_AddCommand ("sendcvar", Host_SendCvar_f, "sends the value of a cvar to the server as a sentcvar command, for use by QuakeC");
-
-       Cvar_RegisterVariable (&rcon_password);
-       Cvar_RegisterVariable (&rcon_address);
-       Cvar_RegisterVariable (&rcon_secure);
-       Cvar_RegisterVariable (&rcon_secure_challengetimeout);
-       Cmd_AddCommand ("rcon", Host_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");
-       Cmd_AddCommand ("srcon", Host_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); this always works as if rcon_secure is set; note: client and server clocks must be synced e.g. via NTP");
-       Cmd_AddCommand ("pqrcon", Host_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 ("user", Host_User_f, "prints additional information about a player number or name on the scoreboard");
-       Cmd_AddCommand ("users", Host_Users_f, "prints additional information about all players on the scoreboard");
-       Cmd_AddCommand ("fullserverinfo", Host_FullServerinfo_f, "internal use only, sent by server to client to update client's local copy of serverinfo string");
-       Cmd_AddCommand ("fullinfo", Host_FullInfo_f, "allows client to modify their userinfo");
-       Cmd_AddCommand ("setinfo", Host_SetInfo_f, "modifies your userinfo");
-       Cmd_AddCommand ("packet", Host_Packet_f, "send a packet to the specified address:port containing a text string");
-       Cmd_AddCommand ("topcolor", Host_TopColor_f, "QW command to set top color without changing bottom color");
-       Cmd_AddCommand ("bottomcolor", Host_BottomColor_f, "QW command to set bottom color without changing top color");
-
-       Cmd_AddCommand_WithClientCommand ("pings", NULL, Host_Pings_f, "command sent by clients to request updated ping and packetloss of players on scoreboard (originally from QW, but also used on NQ servers)");
-       Cmd_AddCommand ("pingplreport", Host_PingPLReport_f, "command sent by server containing client ping and packet loss values for scoreboard, triggered by pings command from client (not used by QW servers)");
-
-       Cmd_AddCommand ("fixtrans", Image_FixTransparentPixels_f, "change alpha-zero pixels in an image file to sensible values, and write out a new TGA (warning: SLOW)");
-       Cvar_RegisterVariable (&r_fixtrans_auto);
-
-       Cvar_RegisterVariable (&team);
-       Cvar_RegisterVariable (&skin);
-       Cvar_RegisterVariable (&noaim);
-
+       Cvar_RegisterVariable(&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_RegisterVariable(&rcon_password);
+       Cvar_RegisterVariable(&rcon_address);
+       Cvar_RegisterVariable(&rcon_secure);
+       Cvar_RegisterVariable(&rcon_secure_challengetimeout);
+       Cvar_RegisterVariable(&r_fixtrans_auto);
+       Cvar_RegisterVariable(&team);
+       Cvar_RegisterVariable(&skin);
+       Cvar_RegisterVariable(&noaim);
        Cvar_RegisterVariable(&sv_cheats);
        Cvar_RegisterVariable(&sv_adminnick);
        Cvar_RegisterVariable(&sv_status_privacy);
        Cvar_RegisterVariable(&sv_status_show_qcstatus);
        Cvar_RegisterVariable(&sv_namechangetimer);
+
+       // client commands - this includes server commands because the client can host a server, so they must exist
+       Cmd_AddCommand(&cmd_client, "quit", Host_Quit_f, "quit the game");
+       Cmd_AddCommand(&cmd_client, "status", Host_Status_f, "print server status information");
+       Cmd_AddCommand(&cmd_client, "map", Host_Map_f, "kick everyone off the server and start a new level");
+       Cmd_AddCommand(&cmd_client, "restart", Host_Restart_f, "restart current level");
+       Cmd_AddCommand(&cmd_client, "changelevel", Host_Changelevel_f, "change to another level, bringing along all connected clients");
+       Cmd_AddCommand(&cmd_client, "version", Host_Version_f, "print engine version");
+       Cmd_AddCommand(&cmd_client, "say", Host_Say_f, "send a chat message to everyone on the server");
+       Cmd_AddCommand(&cmd_client, "tell", Host_Tell_f, "send a chat message to only one person on the server");
+       Cmd_AddCommand(&cmd_client, "pause", Host_Pause_f, "pause the game (if the server allows pausing)");
+       Cmd_AddCommand(&cmd_client, "kick", Host_Kick_f, "kick a player off the server by number or name");
+       Cmd_AddCommand(&cmd_client, "ping", Host_Ping_f, "print ping times of all players on the server");
+       Cmd_AddCommand(&cmd_client, "load", Host_Loadgame_f, "load a saved game file");
+       Cmd_AddCommand(&cmd_client, "save", Host_Savegame_f, "save the game to a file");
+       Cmd_AddCommand(&cmd_client, "viewmodel", Host_Viewmodel_f, "change model of viewthing entity in current level");
+       Cmd_AddCommand(&cmd_client, "viewframe", Host_Viewframe_f, "change animation frame of viewthing entity in current level");
+       Cmd_AddCommand(&cmd_client, "viewnext", Host_Viewnext_f, "change to next animation frame of viewthing entity in current level");
+       Cmd_AddCommand(&cmd_client, "viewprev", Host_Viewprev_f, "change to previous animation frame of viewthing entity in current level");
+       Cmd_AddCommand(&cmd_client, "maxplayers", MaxPlayers_f, "sets limit on how many players (or bots) may be connected to the server at once");
+       Cmd_AddCommand(&cmd_client, "user", Host_User_f, "prints additional information about a player number or name on the scoreboard");
+       Cmd_AddCommand(&cmd_client, "users", Host_Users_f, "prints additional information about all players on the scoreboard");
+
+       // dedicated server commands
+       Cmd_AddCommand(&cmd_server, "quit", Host_Quit_f, "quit the game");
+       Cmd_AddCommand(&cmd_server, "status", Host_Status_f, "print server status information");
+       Cmd_AddCommand(&cmd_server, "map", Host_Map_f, "kick everyone off the server and start a new level");
+       Cmd_AddCommand(&cmd_server, "restart", Host_Restart_f, "restart current level");
+       Cmd_AddCommand(&cmd_server, "changelevel", Host_Changelevel_f, "change to another level, bringing along all connected clients");
+       Cmd_AddCommand(&cmd_server, "version", Host_Version_f, "print engine version");
+       Cmd_AddCommand(&cmd_server, "say", Host_Say_f, "send a chat message to everyone on the server");
+       Cmd_AddCommand(&cmd_server, "tell", Host_Tell_f, "send a chat message to only one person on the server");
+       Cmd_AddCommand(&cmd_server, "pause", Host_Pause_f, "pause the game (if the server allows pausing)");
+       Cmd_AddCommand(&cmd_server, "kick", Host_Kick_f, "kick a player off the server by number or name");
+       Cmd_AddCommand(&cmd_server, "ping", Host_Ping_f, "print ping times of all players on the server");
+       Cmd_AddCommand(&cmd_server, "load", Host_Loadgame_f, "load a saved game file");
+       Cmd_AddCommand(&cmd_server, "save", Host_Savegame_f, "save the game to a file");
+       Cmd_AddCommand(&cmd_server, "viewmodel", Host_Viewmodel_f, "change model of viewthing entity in current level");
+       Cmd_AddCommand(&cmd_server, "viewframe", Host_Viewframe_f, "change animation frame of viewthing entity in current level");
+       Cmd_AddCommand(&cmd_server, "viewnext", Host_Viewnext_f, "change to next animation frame of viewthing entity in current level");
+       Cmd_AddCommand(&cmd_server, "viewprev", Host_Viewprev_f, "change to previous animation frame of viewthing entity in current level");
+       Cmd_AddCommand(&cmd_server, "maxplayers", MaxPlayers_f, "sets limit on how many players (or bots) may be connected to the server at once");
+       Cmd_AddCommand(&cmd_server, "user", Host_User_f, "prints additional information about a player number or name on the scoreboard");
+       Cmd_AddCommand(&cmd_server, "users", Host_Users_f, "prints additional information about all players on the scoreboard");
+
+       // commands that do not have automatic forwarding from cmd_client, these are internal details of the network protocol and not of interest to users (if they know what they are doing they can still use a generic "cmd prespawn" or similar)
+       Cmd_AddCommand(&cmd_serverfromclient, "prespawn", Host_PreSpawn_f, "internal use - signon 1 (client acknowledges that server information has been received)");
+       Cmd_AddCommand(&cmd_serverfromclient, "spawn", Host_Spawn_f, "internal use - signon 2 (client has sent player information, and is asking server to send scoreboard rankings)");
+       Cmd_AddCommand(&cmd_serverfromclient, "begin", Host_Begin_f, "internal use - signon 3 (client asks server to start sending entities, and will go to signon 4 (playing) when the first entity update is received)");
+       Cmd_AddCommand(&cmd_serverfromclient, "pings", Host_Pings_f, "internal use - command sent by clients to request updated ping and packetloss of players on scoreboard (originally from QW, but also used on NQ servers)");
+
+       Cmd_AddCommand(&cmd_serverfromclient, "status", Host_Status_f, "print server status information");
+       Cmd_AddCommand(&cmd_serverfromclient, "god", Host_God_f, "god mode (invulnerability)");
+       Cmd_AddCommand(&cmd_serverfromclient, "notarget", Host_Notarget_f, "notarget mode (monsters do not see you)");
+       Cmd_AddCommand(&cmd_serverfromclient, "fly", Host_Fly_f, "fly mode (flight)");
+       Cmd_AddCommand(&cmd_serverfromclient, "noclip", Host_Noclip_f, "noclip mode (flight without collisions, move through walls)");
+       Cmd_AddCommand(&cmd_serverfromclient, "give", Host_Give_f, "alter inventory");
+       Cmd_AddCommand(&cmd_serverfromclient, "say", Host_Say_f, "send a chat message to everyone on the server");
+       Cmd_AddCommand(&cmd_serverfromclient, "say_team", Host_Say_Team_f, "send a chat message to your team on the server");
+       Cmd_AddCommand(&cmd_serverfromclient, "tell", Host_Tell_f, "send a chat message to only one person on the server");
+       Cmd_AddCommand(&cmd_serverfromclient, "kill", Host_Kill_f, "die instantly");
+       Cmd_AddCommand(&cmd_serverfromclient, "pause", Host_Pause_f, "pause the game (if the server allows pausing)");
+       Cmd_AddCommand(&cmd_serverfromclient, "ping", Host_Ping_f, "print ping times of all players on the server");
+       Cmd_AddCommand(&cmd_serverfromclient, "name", Host_Name_f, "change your player name");
+       Cmd_AddCommand(&cmd_serverfromclient, "color", Host_Color_f, "change your player shirt and pants colors");
+       Cmd_AddCommand(&cmd_serverfromclient, "rate", Host_Rate_f, "change your network connection speed");
+       Cmd_AddCommand(&cmd_serverfromclient, "rate_burstsize", Host_Rate_BurstSize_f, "change your network connection speed");
+       Cmd_AddCommand(&cmd_serverfromclient, "pmodel", Host_PModel_f, "(Nehahra-only) change your player model choice");
+       Cmd_AddCommand(&cmd_serverfromclient, "playermodel", Host_Playermodel_f, "change your player model");
+       Cmd_AddCommand(&cmd_serverfromclient, "playerskin", Host_Playerskin_f, "change your player skin number");
+
+       // client commands that require a connection and are simply forwarded to server
+       Cmd_AddCommand(&cmd_client, "status", Cmd_ForwardToServer_f, "print server status information");
+       Cmd_AddCommand(&cmd_client, "god", Cmd_ForwardToServer_f, "god mode (invulnerability)");
+       Cmd_AddCommand(&cmd_client, "notarget", Cmd_ForwardToServer_f, "notarget mode (monsters do not see you)");
+       Cmd_AddCommand(&cmd_client, "fly", Cmd_ForwardToServer_f, "fly mode (flight)");
+       Cmd_AddCommand(&cmd_client, "noclip", Cmd_ForwardToServer_f, "noclip mode (flight without collisions, move through walls)");
+       Cmd_AddCommand(&cmd_client, "give", Cmd_ForwardToServer_f, "alter inventory");
+       Cmd_AddCommand(&cmd_client, "say", Cmd_ForwardToServer_f, "send a chat message to everyone on the server");
+       Cmd_AddCommand(&cmd_client, "say_team", Cmd_ForwardToServer_f, "send a chat message to your team on the server");
+       Cmd_AddCommand(&cmd_client, "tell", Cmd_ForwardToServer_f, "send a chat message to only one person on the server");
+       Cmd_AddCommand(&cmd_client, "kill", Cmd_ForwardToServer_f, "die instantly");
+       Cmd_AddCommand(&cmd_client, "pause", Cmd_ForwardToServer_f, "pause the game (if the server allows pausing)");
+       Cmd_AddCommand(&cmd_client, "ping", Cmd_ForwardToServer_f, "print ping times of all players on the server");
+
+       Cmd_AddCommand(&cmd_client, "connect", Host_Connect_f, "connect to a server by IP address or hostname");
+       Cmd_AddCommand(&cmd_client, "reconnect", Host_Reconnect_f, "reconnect to the last server you were on, or resets a quakeworld connection (do not use if currently playing on a netquake server)");
+       Cmd_AddCommand(&cmd_client, "version", Host_Version_f, "print engine version");
+       Cmd_AddCommand(&cmd_client, "startdemos", Host_Startdemos_f, "start playing back the selected demos sequentially (used at end of startup script)");
+       Cmd_AddCommand(&cmd_client, "demos", Host_Demos_f, "restart looping demos defined by the last startdemos command");
+       Cmd_AddCommand(&cmd_client, "stopdemo", Host_Stopdemo_f, "stop playing or recording demo (like stop command) and return to looping demos");
+       Cmd_AddCommand(&cmd_client, "sendcvar", Host_SendCvar_f, "sends the value of a cvar to the server as a sentcvar command, for use by QuakeC");
+       Cmd_AddCommand(&cmd_client, "rcon", Host_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");
+       Cmd_AddCommand(&cmd_client, "srcon", Host_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); this always works as if rcon_secure is set; note: client and server clocks must be synced e.g. via NTP");
+       Cmd_AddCommand(&cmd_client, "pqrcon", Host_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", Host_FullInfo_f, "allows client to modify their userinfo");
+       Cmd_AddCommand(&cmd_client, "setinfo", Host_SetInfo_f, "modifies your userinfo");
+       Cmd_AddCommand(&cmd_client, "packet", Host_Packet_f, "send a packet to the specified address:port containing a text string");
+       Cmd_AddCommand(&cmd_client, "topcolor", Host_TopColor_f, "QW command to set top color without changing bottom color");
+       Cmd_AddCommand(&cmd_client, "bottomcolor", Host_BottomColor_f,&