]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - host_cmd.c
New rate burst handling; cvars: cl_rate_burstsize, net_usesizelimit, net_burstreserve
[xonotic/darkplaces.git] / host_cmd.c
index b60af2164b63410b49f7641ca28c429cb13f98da..5e8daba3609ca46a058886a3486f5a3e9d62a31b 100644 (file)
@@ -67,14 +67,16 @@ void Host_Quit_f (void)
 Host_Status_f
 ==================
 */
-void Host_Status_f (void)
+static void Host_Status_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        char qcstatus[256];
        client_t *client;
        int seconds = 0, minutes = 0, hours = 0, i, j, k, in, players, ping = 0, packetloss = 0;
        void (*print) (const char *fmt, ...);
        char ip[48]; // can contain a full length v6 address with [] and a port
        int frags;
+       char vabuf[1024];
 
        if (cmd_source == src_command)
        {
@@ -91,10 +93,7 @@ void Host_Status_f (void)
 
        if (!sv.active)
                return;
-       
-       if(cmd_source == src_command)
-               SV_VM_Begin();
-       
+
        in = 0;
        if (Cmd_Argc() == 2)
        {
@@ -111,7 +110,7 @@ void Host_Status_f (void)
        print ("version:  %s build %s\n", gamename, buildstring);
        print ("protocol: %i (%s)\n", Protocol_NumberForEnum(sv.protocol), Protocol_NameForEnum(sv.protocol));
        print ("map:      %s\n", sv.name);
-       print ("timing:   %s\n", Host_TimingReport());
+       print ("timing:   %s\n", Host_TimingReport(vabuf, sizeof(vabuf)));
        print ("players:  %i active (%i max)\n\n", players, svs.maxclients);
 
        if (in == 1)
@@ -159,7 +158,7 @@ void Host_Status_f (void)
                if(sv_status_show_qcstatus.integer)
                {
                        prvm_edict_t *ed = PRVM_EDICT_NUM(i + 1);
-                       const char *str = PRVM_GetString(PRVM_serveredictstring(ed, clientstatus));
+                       const char *str = PRVM_GetString(prog, PRVM_serveredictstring(ed, clientstatus));
                        if(str && *str)
                        {
                                char *p;
@@ -198,9 +197,6 @@ void Host_Status_f (void)
                        print ("%s%-47s #%-3u ^7%s\n", k%2 ? "^3" : "^7", ip, i+1, client->name);
                }
        }
-
-       if(cmd_source == src_command)
-               SV_VM_End();
 }
 
 
@@ -211,8 +207,9 @@ Host_God_f
 Sets client to godmode
 ==================
 */
-void Host_God_f (void)
+static void Host_God_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        if (!allowcheats)
        {
                SV_ClientPrint("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
@@ -226,8 +223,9 @@ void Host_God_f (void)
                SV_ClientPrint("godmode ON\n");
 }
 
-void Host_Notarget_f (void)
+static void Host_Notarget_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        if (!allowcheats)
        {
                SV_ClientPrint("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
@@ -243,8 +241,9 @@ void Host_Notarget_f (void)
 
 qboolean noclip_anglehack;
 
-void Host_Noclip_f (void)
+static void Host_Noclip_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        if (!allowcheats)
        {
                SV_ClientPrint("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
@@ -272,8 +271,9 @@ Host_Fly_f
 Sets client to flymode
 ==================
 */
-void Host_Fly_f (void)
+static void Host_Fly_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        if (!allowcheats)
        {
                SV_ClientPrint("No cheats allowed, use sv_cheats 1 and restart level to enable.\n");
@@ -300,7 +300,7 @@ Host_Ping_f
 ==================
 */
 void Host_Pings_f (void); // called by Host_Ping_f
-void Host_Ping_f (void)
+static void Host_Ping_f (void)
 {
        int i;
        client_t *client;
@@ -352,7 +352,7 @@ map <servername>
 command from the console.  Active clients are kicked off.
 ======================
 */
-void Host_Map_f (void)
+static void Host_Map_f (void)
 {
        char level[MAX_QPATH];
 
@@ -399,7 +399,7 @@ Host_Changelevel_f
 Goes to a new map, taking all clients along
 ==================
 */
-void Host_Changelevel_f (void)
+static void Host_Changelevel_f (void)
 {
        char level[MAX_QPATH];
 
@@ -419,9 +419,7 @@ void Host_Changelevel_f (void)
                MR_ToggleMenu(0);
        key_dest = key_game;
 
-       SV_VM_Begin();
        SV_SaveSpawnparms ();
-       SV_VM_End();
        allowcheats = sv_cheats.integer != 0;
        strlcpy(level, Cmd_Argv(1), sizeof(level));
        SV_SpawnServer(level);
@@ -436,7 +434,7 @@ Host_Restart_f
 Restarts the current server for a dead player
 ==================
 */
-void Host_Restart_f (void)
+static void Host_Restart_f (void)
 {
        char mapname[MAX_QPATH];
 
@@ -526,7 +524,7 @@ Host_Connect_f
 User command to connect to server
 =====================
 */
-void Host_Connect_f (void)
+static void Host_Connect_f (void)
 {
        if (Cmd_Argc() < 2)
        {
@@ -550,10 +548,10 @@ LOAD / SAVE GAME
 
 #define        SAVEGAME_VERSION        5
 
-void Host_Savegame_to (const char *name)
+void Host_Savegame_to(prvm_prog_t *prog, const char *name)
 {
        qfile_t *f;
-       int             i, k, l, lightstyles = 64;
+       int             i, k, l, numbuffers, lightstyles = 64;
        char    comment[SAVEGAME_COMMENT_LENGTH+1];
        char    line[MAX_INPUTLINE];
        qboolean isserver;
@@ -565,7 +563,7 @@ void Host_Savegame_to (const char *name)
                if (sv.lightstyles[i][0])
                        lightstyles = i+1;
 
-       isserver = !strcmp(PRVM_NAME, "server");
+       isserver = prog == SVVM_prog;
 
        Con_Printf("Saving game to %s...\n", name);
        f = FS_OpenRealFile(name, "wb", false);
@@ -579,9 +577,9 @@ void Host_Savegame_to (const char *name)
 
        memset(comment, 0, sizeof(comment));
        if(isserver)
-               dpsnprintf(comment, sizeof(comment), "%-21.21s kills:%3i/%3i", PRVM_GetString(PRVM_serveredictstring(prog->edicts, message)), (int)PRVM_serverglobalfloat(killed_monsters), (int)PRVM_serverglobalfloat(total_monsters));
+               dpsnprintf(comment, sizeof(comment), "%-21.21s kills:%3i/%3i", PRVM_GetString(prog, PRVM_serveredictstring(prog->edicts, message)), (int)PRVM_serverglobalfloat(killed_monsters), (int)PRVM_serverglobalfloat(total_monsters));
        else
-               dpsnprintf(comment, sizeof(comment), "(crash dump of %s progs)", PRVM_NAME);
+               dpsnprintf(comment, sizeof(comment), "(crash dump of %s progs)", prog->name);
        // convert space to _ to make stdio happy
        // LordHavoc: convert control characters to _ as well
        for (i=0 ; i<SAVEGAME_COMMENT_LENGTH ; i++)
@@ -616,12 +614,12 @@ void Host_Savegame_to (const char *name)
                        FS_Print(f,"m\n");
        }
 
-       PRVM_ED_WriteGlobals (f);
+       PRVM_ED_WriteGlobals (prog, f);
        for (i=0 ; i<prog->num_edicts ; i++)
        {
                FS_Printf(f,"// edict %d\n", i);
                //Con_Printf("edict %d...\n", i);
-               PRVM_ED_Write (f, PRVM_EDICT_NUM(i));
+               PRVM_ED_Write (prog, f, PRVM_EDICT_NUM(i));
        }
 
 #if 1
@@ -643,11 +641,13 @@ void Host_Savegame_to (const char *name)
                        FS_Printf(f,"sv.sound_precache %i %s\n", i, sv.sound_precache[i]);
 
        // darkplaces extension - save buffers
-       for (i = 0; i < (int)Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray); i++)
+       numbuffers = Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray);
+       for (i = 0; i < numbuffers; i++)
        {
                prvm_stringbuffer_t *stringbuffer = (prvm_stringbuffer_t*) Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i);
                if(stringbuffer && (stringbuffer->flags & STRINGBUFFER_SAVED))
                {
+                       FS_Printf(f,"sv.buffer %i %i \"string\"\n", i, stringbuffer->flags & STRINGBUFFER_QCFLAGS);
                        for(k = 0; k < stringbuffer->num_strings; k++)
                        {
                                if (!stringbuffer->strings[k])
@@ -698,8 +698,9 @@ void Host_Savegame_to (const char *name)
 Host_Savegame_f
 ===============
 */
-void Host_Savegame_f (void)
+static void Host_Savegame_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        char    name[MAX_QPATH];
        qboolean deadflag = false;
 
@@ -709,9 +710,7 @@ void Host_Savegame_f (void)
                return;
        }
 
-       SV_VM_Begin();
        deadflag = cl.islocalgame && svs.clients[0].active && PRVM_serveredictfloat(svs.clients[0].edict, deadflag);
-       SV_VM_End();
 
        if (cl.islocalgame)
        {
@@ -746,9 +745,7 @@ void Host_Savegame_f (void)
        strlcpy (name, Cmd_Argv(1), sizeof (name));
        FS_DefaultExtension (name, ".sav", sizeof (name));
 
-       SV_VM_Begin();
-       Host_Savegame_to(name);
-       SV_VM_End();
+       Host_Savegame_to(prog, name);
 }
 
 
@@ -758,8 +755,14 @@ Host_Loadgame_f
 ===============
 */
 
-void Host_Loadgame_f (void)
+prvm_stringbuffer_t *BufStr_FindCreateReplace (prvm_prog_t *prog, int bufindex, int flags, char *format);
+void BufStr_Set(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer, int strindex, const char *str);
+void BufStr_Del(prvm_prog_t *prog, prvm_stringbuffer_t *stringbuffer);
+void BufStr_Flush(prvm_prog_t *prog);
+
+static void Host_Loadgame_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        char filename[MAX_QPATH];
        char mapname[MAX_QPATH];
        float time;
@@ -768,12 +771,11 @@ void Host_Loadgame_f (void)
        const char *t;
        char *text;
        prvm_edict_t *ent;
-       int i, k;
+       int i, k, numbuffers;
        int entnum;
        int version;
        float spawn_parms[NUM_SPAWN_PARMS];
        prvm_stringbuffer_t *stringbuffer;
-       size_t alloclen;
 
        if (Cmd_Argc() != 2)
        {
@@ -808,7 +810,7 @@ void Host_Loadgame_f (void)
                Con_Printf("Host_Loadgame_f: loading version\n");
 
        // version
-       COM_ParseToken_Simple(&t, false, false);
+       COM_ParseToken_Simple(&t, false, false, true);
        version = atoi(com_token);
        if (version != SAVEGAME_VERSION)
        {
@@ -821,15 +823,15 @@ void Host_Loadgame_f (void)
                Con_Printf("Host_Loadgame_f: loading description\n");
 
        // description
-       COM_ParseToken_Simple(&t, false, false);
+       COM_ParseToken_Simple(&t, false, false, true);
 
        for (i = 0;i < NUM_SPAWN_PARMS;i++)
        {
-               COM_ParseToken_Simple(&t, false, false);
+               COM_ParseToken_Simple(&t, false, false, true);
                spawn_parms[i] = atof(com_token);
        }
        // skill
-       COM_ParseToken_Simple(&t, false, false);
+       COM_ParseToken_Simple(&t, false, false, true);
 // this silliness is so we can load 1.06 save files, which have float skill values
        current_skill = (int)(atof(com_token) + 0.5);
        Cvar_SetValue ("skill", (float)current_skill);
@@ -838,14 +840,14 @@ void Host_Loadgame_f (void)
                Con_Printf("Host_Loadgame_f: loading mapname\n");
 
        // mapname
-       COM_ParseToken_Simple(&t, false, false);
+       COM_ParseToken_Simple(&t, false, false, true);
        strlcpy (mapname, com_token, sizeof(mapname));
 
        if(developer_entityparsing.integer)
                Con_Printf("Host_Loadgame_f: loading time\n");
 
        // time
-       COM_ParseToken_Simple(&t, false, false);
+       COM_ParseToken_Simple(&t, false, false, true);
        time = atof(com_token);
 
        allowcheats = sv_cheats.integer != 0;
@@ -868,7 +870,6 @@ void Host_Loadgame_f (void)
 
 // load the light styles
 
-       SV_VM_Begin();
        // -1 is the globals
        entnum = -1;
 
@@ -876,7 +877,7 @@ void Host_Loadgame_f (void)
        {
                // light style
                start = t;
-               COM_ParseToken_Simple(&t, false, false);
+               COM_ParseToken_Simple(&t, false, false, true);
                // if this is a 64 lightstyle savegame produced by Quake, stop now
                // we have to check this because darkplaces may save more than 64
                if (com_token[0] == '{')
@@ -897,7 +898,7 @@ void Host_Loadgame_f (void)
        for (;;)
        {
                start = t;
-               if (!COM_ParseToken_Simple(&t, false, false))
+               if (!COM_ParseToken_Simple(&t, false, false, true))
                        break;
                if (com_token[0] == '{')
                {
@@ -914,10 +915,10 @@ void Host_Loadgame_f (void)
        for (;;)
        {
                start = t;
-               while (COM_ParseToken_Simple(&t, false, false))
+               while (COM_ParseToken_Simple(&t, false, false, true))
                        if (!strcmp(com_token, "}"))
                                break;
-               if (!COM_ParseToken_Simple(&start, false, false))
+               if (!COM_ParseToken_Simple(&start, false, false, true))
                {
                        // end of file
                        break;
@@ -934,7 +935,7 @@ void Host_Loadgame_f (void)
                                Con_Printf("Host_Loadgame_f: loading globals\n");
 
                        // parse the global vars
-                       PRVM_ED_ParseGlobals (start);
+                       PRVM_ED_ParseGlobals (prog, start);
 
                        // restore the autocvar globals
                        Cvar_UpdateAllAutoCvars();
@@ -948,15 +949,15 @@ void Host_Loadgame_f (void)
                                Host_Error("Host_PerformLoadGame: too many edicts in save file (reached MAX_EDICTS %i)", MAX_EDICTS);
                        }
                        while (entnum >= prog->max_edicts)
-                               PRVM_MEM_IncreaseEdicts();
+                               PRVM_MEM_IncreaseEdicts(prog);
                        ent = PRVM_EDICT_NUM(entnum);
-                       memset(ent->fields.vp, 0, prog->entityfields * 4);
+                       memset(ent->fields.fp, 0, prog->entityfields * sizeof(prvm_vec_t));
                        ent->priv.server->free = false;
 
                        if(developer_entityparsing.integer)
                                Con_Printf("Host_Loadgame_f: loading edict %d\n", entnum);
 
-                       PRVM_ED_ParseEdict (start, ent);
+                       PRVM_ED_ParseEdict (prog, start, ent);
 
                        // link it into the bsp tree
                        if (!ent->priv.server->free)
@@ -993,13 +994,15 @@ void Host_Loadgame_f (void)
                        memset(sv.lightstyles[0], 0, sizeof(sv.lightstyles));
                        memset(sv.model_precache[0], 0, sizeof(sv.model_precache));
                        memset(sv.sound_precache[0], 0, sizeof(sv.sound_precache));
-                       while (COM_ParseToken_Simple(&t, false, false))
+                       BufStr_Flush(prog);
+
+                       while (COM_ParseToken_Simple(&t, false, false, true))
                        {
                                if (!strcmp(com_token, "sv.lightstyles"))
                                {
-                                       COM_ParseToken_Simple(&t, false, false);
+                                       COM_ParseToken_Simple(&t, false, false, true);
                                        i = atoi(com_token);
-                                       COM_ParseToken_Simple(&t, false, false);
+                                       COM_ParseToken_Simple(&t, false, false, true);
                                        if (i >= 0 && i < MAX_LIGHTSTYLES)
                                                strlcpy(sv.lightstyles[i], com_token, sizeof(sv.lightstyles[i]));
                                        else
@@ -1007,9 +1010,9 @@ void Host_Loadgame_f (void)
                                }
                                else if (!strcmp(com_token, "sv.model_precache"))
                                {
-                                       COM_ParseToken_Simple(&t, false, false);
+                                       COM_ParseToken_Simple(&t, false, false, true);
                                        i = atoi(com_token);
-                                       COM_ParseToken_Simple(&t, false, false);
+                                       COM_ParseToken_Simple(&t, false, false, true);
                                        if (i >= 0 && i < MAX_MODELS)
                                        {
                                                strlcpy(sv.model_precache[i], com_token, sizeof(sv.model_precache[i]));
@@ -1020,67 +1023,78 @@ void Host_Loadgame_f (void)
                                }
                                else if (!strcmp(com_token, "sv.sound_precache"))
                                {
-                                       COM_ParseToken_Simple(&t, false, false);
+                                       COM_ParseToken_Simple(&t, false, false, true);
                                        i = atoi(com_token);
-                                       COM_ParseToken_Simple(&t, false, false);
+                                       COM_ParseToken_Simple(&t, false, false, true);
                                        if (i >= 0 && i < MAX_SOUNDS)
                                                strlcpy(sv.sound_precache[i], com_token, sizeof(sv.sound_precache[i]));
                                        else
                                                Con_Printf("unsupported sound %i \"%s\"\n", i, com_token);
                                }
+                               else if (!strcmp(com_token, "sv.buffer"))
+                               {
+                                       if (COM_ParseToken_Simple(&t, false, false, true))
+                                       {
+                                               i = atoi(com_token);
+                                               if (i >= 0)
+                                               {
+                                                       k = STRINGBUFFER_SAVED;
+                                                       if (COM_ParseToken_Simple(&t, false, false, true))
+                                                               k |= atoi(com_token);
+                                                       if (!BufStr_FindCreateReplace(prog, i, k, "string"))
+                                                               Con_Printf("failed to create stringbuffer %i\n", i);
+                                               }
+                                               else
+                                                       Con_Printf("unsupported stringbuffer index %i \"%s\"\n", i, com_token);
+                                       }
+                                       else
+                                               Con_Printf("unexpected end of line when parsing sv.buffer (expected buffer index)\n");
+                               }
                                else if (!strcmp(com_token, "sv.bufstr"))
                                {
-                                       COM_ParseToken_Simple(&t, false, false);
-                                       i = atoi(com_token);
-                                       COM_ParseToken_Simple(&t, false, false);
-                                       k = atoi(com_token);
-                                       COM_ParseToken_Simple(&t, false, false);
-                                       stringbuffer = (prvm_stringbuffer_t*) Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i);
-                                       // VorteX: nasty code, cleanup required
-                                       // create buffer at this index
-                                       if(!stringbuffer) 
-                                               stringbuffer = (prvm_stringbuffer_t *) Mem_ExpandableArray_AllocRecordAtIndex(&prog->stringbuffersarray, i);
-                                       if (!stringbuffer)
-                                               Con_Printf("cant write string %i into buffer %i\n", k, i);
+                                       if (!COM_ParseToken_Simple(&t, false, false, true))
+                                               Con_Printf("unexpected end of line when parsing sv.bufstr\n");
                                        else
                                        {
-                                               // code copied from VM_bufstr_set
-                                               // expand buffer
-                                               if (stringbuffer->max_strings <= i)
+                                               i = atoi(com_token);
+                                               stringbuffer = BufStr_FindCreateReplace(prog, i, STRINGBUFFER_SAVED, "string");
+                                               if (stringbuffer)
                                                {
-                                                       char **oldstrings = stringbuffer->strings;
-                                                       stringbuffer->max_strings = max(stringbuffer->max_strings * 2, 128);
-                                                       while (stringbuffer->max_strings <= i)
-                                                               stringbuffer->max_strings *= 2;
-                                                       stringbuffer->strings = (char **) Mem_Alloc(prog->progs_mempool, stringbuffer->max_strings * sizeof(stringbuffer->strings[0]));
-                                                       if (stringbuffer->num_strings > 0)
-                                                               memcpy(stringbuffer->strings, oldstrings, stringbuffer->num_strings * sizeof(stringbuffer->strings[0]));
-                                                       if (oldstrings)
-                                                               Mem_Free(oldstrings);
+                                                       if (COM_ParseToken_Simple(&t, false, false, true))
+                                                       {
+                                                               k = atoi(com_token);
+                                                               if (COM_ParseToken_Simple(&t, false, false, true))
+                                                                       BufStr_Set(prog, stringbuffer, k, com_token);
+                                                               else
+                                                                       Con_Printf("unexpected end of line when parsing sv.bufstr (expected string)\n");
+                                                       }
+                                                       else
+                                                               Con_Printf("unexpected end of line when parsing sv.bufstr (expected strindex)\n");
                                                }
-                                               // allocate string
-                                               stringbuffer->num_strings = max(stringbuffer->num_strings, k + 1);
-                                               if(stringbuffer->strings[k])
-                                                       Mem_Free(stringbuffer->strings[k]);
-                                               stringbuffer->strings[k] = NULL;
-                                               alloclen = strlen(com_token) + 1;
-                                               stringbuffer->strings[k] = (char *)Mem_Alloc(prog->progs_mempool, alloclen);
-                                               memcpy(stringbuffer->strings[k], com_token, alloclen);
+                                               else
+                                                       Con_Printf("failed to create stringbuffer %i \"%s\"\n", i, com_token);
                                        }
                                }       
                                // skip any trailing text or unrecognized commands
-                               while (COM_ParseToken_Simple(&t, true, false) && strcmp(com_token, "\n"))
+                               while (COM_ParseToken_Simple(&t, true, false, true) && strcmp(com_token, "\n"))
                                        ;
                        }
                }
        }
        Mem_Free(text);
 
+       // remove all temporary flagged string buffers (ones created with BufStr_FindCreateReplace)
+       numbuffers = Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray);
+       for (i = 0; i < numbuffers; i++)
+       {
+               if ( (stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i)) )
+                       if (stringbuffer->flags & STRINGBUFFER_TEMP)
+                               BufStr_Del(prog, stringbuffer);
+       }
+
        if(developer_entityparsing.integer)
                Con_Printf("Host_Loadgame_f: finished\n");
 
-       SV_VM_End();
-
        // make sure we're connected to loopback
        if (sv.active && cls.state == ca_disconnected)
                CL_EstablishConnection("local:1", -2);
@@ -1094,8 +1108,9 @@ 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)"};
-void Host_Name_f (void)
+static void Host_Name_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        int i, j;
        qboolean valid_colors;
        const char *newNameSource;
@@ -1201,10 +1216,10 @@ void Host_Name_f (void)
        if (j >= 0 && strlen(host_client->name) < sizeof(host_client->name) - 2)
                memcpy(host_client->name + strlen(host_client->name), STRING_COLOR_DEFAULT_STR, strlen(STRING_COLOR_DEFAULT_STR) + 1);
 
-       PRVM_serveredictstring(host_client->edict, netname) = PRVM_SetEngineString(host_client->name);
+       PRVM_serveredictstring(host_client->edict, netname) = PRVM_SetEngineString(prog, host_client->name);
        if (strcmp(host_client->old_name, host_client->name))
        {
-               if (host_client->spawned)
+               if (host_client->begun)
                        SV_BroadcastPrintf("%s ^7changed name to %s\n", host_client->old_name, host_client->name);
                strlcpy(host_client->old_name, host_client->name, sizeof(host_client->old_name));
                // send notification to all clients
@@ -1222,8 +1237,9 @@ 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
-void Host_Playermodel_f (void)
+static void Host_Playermodel_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        int i, j;
        char newPath[sizeof(host_client->playermodel)];
 
@@ -1261,7 +1277,7 @@ void Host_Playermodel_f (void)
 
        // point the string back at updateclient->name to keep it safe
        strlcpy (host_client->playermodel, newPath, sizeof (host_client->playermodel));
-       PRVM_serveredictstring(host_client->edict, playermodel) = PRVM_SetEngineString(host_client->playermodel);
+       PRVM_serveredictstring(host_client->edict, playermodel) = PRVM_SetEngineString(prog, host_client->playermodel);
        if (strcmp(host_client->old_model, host_client->playermodel))
        {
                strlcpy(host_client->old_model, host_client->playermodel, sizeof(host_client->old_model));
@@ -1278,8 +1294,9 @@ 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)"};
-void Host_Playerskin_f (void)
+static void Host_Playerskin_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        int i, j;
        char newPath[sizeof(host_client->playerskin)];
 
@@ -1317,10 +1334,10 @@ void Host_Playerskin_f (void)
 
        // point the string back at updateclient->name to keep it safe
        strlcpy (host_client->playerskin, newPath, sizeof (host_client->playerskin));
-       PRVM_serveredictstring(host_client->edict, playerskin) = PRVM_SetEngineString(host_client->playerskin);
+       PRVM_serveredictstring(host_client->edict, playerskin) = PRVM_SetEngineString(prog, host_client->playerskin);
        if (strcmp(host_client->old_skin, host_client->playerskin))
        {
-               //if (host_client->spawned)
+               //if (host_client->begun)
                //      SV_BroadcastPrintf("%s changed skin to %s\n", host_client->name, host_client->playerskin);
                strlcpy(host_client->old_skin, host_client->playerskin, sizeof(host_client->old_skin));
                /*// send notification to all clients
@@ -1330,13 +1347,14 @@ void Host_Playerskin_f (void)
        }
 }
 
-void Host_Version_f (void)
+static void Host_Version_f (void)
 {
        Con_Printf("Version: %s build %s\n", gamename, buildstring);
 }
 
-void Host_Say(qboolean teamonly)
+static void Host_Say(qboolean teamonly)
 {
+       prvm_prog_t *prog = SVVM_prog;
        client_t *save;
        int j, quoted;
        const char *p1;
@@ -1403,19 +1421,19 @@ void Host_Say(qboolean teamonly)
 }
 
 
-void Host_Say_f(void)
+static void Host_Say_f(void)
 {
        Host_Say(false);
 }
 
 
-void Host_Say_Team_f(void)
+static void Host_Say_Team_f(void)
 {
        Host_Say(true);
 }
 
 
-void Host_Tell_f(void)
+static void Host_Tell_f(void)
 {
        const char *playername_start = NULL;
        size_t playername_length = 0;
@@ -1550,8 +1568,9 @@ 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)"};
-void Host_Color(int changetop, int changebottom)
+static void Host_Color(int changetop, int changebottom)
 {
+       prvm_prog_t *prog = SVVM_prog;
        int top, bottom, playercolor;
 
        // get top and bottom either from the provided values or the current values
@@ -1581,10 +1600,10 @@ void Host_Color(int changetop, int changebottom)
        if (host_client->edict && PRVM_serverfunction(SV_ChangeTeam))
        {
                Con_DPrint("Calling SV_ChangeTeam\n");
+               prog->globals.fp[OFS_PARM0] = playercolor;
                PRVM_serverglobalfloat(time) = sv.time;
-               prog->globals.generic[OFS_PARM0] = playercolor;
                PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
-               PRVM_ExecuteProgram(PRVM_serverfunction(SV_ChangeTeam), "QC function SV_ChangeTeam is missing");
+               prog->ExecuteProgram(prog, PRVM_serverfunction(SV_ChangeTeam), "QC function SV_ChangeTeam is missing");
        }
        else
        {
@@ -1605,7 +1624,7 @@ void Host_Color(int changetop, int changebottom)
        }
 }
 
-void Host_Color_f(void)
+static void Host_Color_f(void)
 {
        int             top, bottom;
 
@@ -1626,7 +1645,7 @@ void Host_Color_f(void)
        Host_Color(top, bottom);
 }
 
-void Host_TopColor_f(void)
+static void Host_TopColor_f(void)
 {
        if (Cmd_Argc() == 1)
        {
@@ -1638,7 +1657,7 @@ void Host_TopColor_f(void)
        Host_Color(atoi(Cmd_Argv(1)), -1);
 }
 
-void Host_BottomColor_f(void)
+static void Host_BottomColor_f(void)
 {
        if (Cmd_Argc() == 1)
        {
@@ -1651,7 +1670,8 @@ void Host_BottomColor_f(void)
 }
 
 cvar_t cl_rate = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "_cl_rate", "20000", "internal storage cvar for current rate (changed by rate command)"};
-void Host_Rate_f(void)
+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)
 {
        int rate;
 
@@ -1672,14 +1692,36 @@ void Host_Rate_f(void)
 
        host_client->rate = rate;
 }
+static void Host_Rate_BurstSize_f(void)
+{
+       int rate_burstsize;
+
+       if (Cmd_Argc() != 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));
+
+       if (cmd_source == src_command)
+       {
+               Cvar_SetValue ("_cl_rate_burstsize", rate_burstsize);
+               return;
+       }
+
+       host_client->rate_burstsize = rate_burstsize;
+}
 
 /*
 ==================
 Host_Kill_f
 ==================
 */
-void Host_Kill_f (void)
+static void Host_Kill_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        if (PRVM_serveredictfloat(host_client->edict, health) <= 0)
        {
                SV_ClientPrint("Can't suicide -- already dead!\n");
@@ -1688,7 +1730,7 @@ void Host_Kill_f (void)
 
        PRVM_serverglobalfloat(time) = sv.time;
        PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
-       PRVM_ExecuteProgram (PRVM_serverfunction(ClientKill), "QC function ClientKill is missing");
+       prog->ExecuteProgram(prog, PRVM_serverfunction(ClientKill), "QC function ClientKill is missing");
 }
 
 
@@ -1697,18 +1739,39 @@ void Host_Kill_f (void)
 Host_Pause_f
 ==================
 */
-void Host_Pause_f (void)
+static void Host_Pause_f (void)
 {
-       if (!pausable.integer)
-               SV_ClientPrint("Pause not allowed.\n");
+       void (*print) (const char *fmt, ...);
+       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 ();
+                       return;
+               }
+               print = Con_Printf;
+       }
        else
+               print = SV_ClientPrintf;
+
+       if (!pausable.integer)
        {
-               sv.paused ^= 1;
-               SV_BroadcastPrintf("%s %spaused the game\n", host_client->name, sv.paused ? "" : "un");
-               // send notification to all clients
-               MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
-               MSG_WriteByte(&sv.reliable_datagram, sv.paused);
+               if (cmd_source == src_client)
+               {
+                       if(cls.state == ca_dedicated || host_client != &svs.clients[0]) // non-admin
+                       {
+                               print("Pause not allowed.\n");
+                               return;
+                       }
+               }
        }
+       
+       sv.paused ^= 1;
+       SV_BroadcastPrintf("%s %spaused the game\n", host_client->name, sv.paused ? "" : "un");
+       // send notification to all clients
+       MSG_WriteByte(&sv.reliable_datagram, svc_setpause);
+       MSG_WriteByte(&sv.reliable_datagram, sv.paused);
 }
 
 /*
@@ -1721,6 +1784,7 @@ LordHavoc: 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)
 {
+       prvm_prog_t *prog = SVVM_prog;
        int i;
 
        if (Cmd_Argc () == 1)
@@ -1751,13 +1815,14 @@ static void Host_PModel_f (void)
 Host_PreSpawn_f
 ==================
 */
-void Host_PreSpawn_f (void)
+static void Host_PreSpawn_f (void)
 {
-       if (host_client->spawned)
+       if (host_client->prespawned)
        {
-               Con_Print("prespawn not valid -- already spawned\n");
+               Con_Print("prespawn not valid -- already prespawned\n");
                return;
        }
+       host_client->prespawned = true;
 
        if (host_client->netconnection)
        {
@@ -1776,17 +1841,24 @@ void Host_PreSpawn_f (void)
 Host_Spawn_f
 ==================
 */
-void Host_Spawn_f (void)
+static void Host_Spawn_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        int i;
        client_t *client;
        int stats[MAX_CL_STATS];
 
+       if (!host_client->prespawned)
+       {
+               Con_Print("Spawn not valid -- not yet prespawned\n");
+               return;
+       }
        if (host_client->spawned)
        {
                Con_Print("Spawn not valid -- already spawned\n");
                return;
        }
+       host_client->spawned = true;
 
        // reset name change timer again because they might want to change name
        // again in the first 5 seconds after connecting
@@ -1806,7 +1878,7 @@ void Host_Spawn_f (void)
                        Con_DPrint("Calling RestoreGame\n");
                        PRVM_serverglobalfloat(time) = sv.time;
                        PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
-                       PRVM_ExecuteProgram(PRVM_serverfunction(RestoreGame), "QC function RestoreGame is missing");
+                       prog->ExecuteProgram(prog, PRVM_serverfunction(RestoreGame), "QC function RestoreGame is missing");
                }
        }
        else
@@ -1821,12 +1893,13 @@ void Host_Spawn_f (void)
                host_client->clientconnectcalled = true;
                PRVM_serverglobalfloat(time) = sv.time;
                PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
-               PRVM_ExecuteProgram (PRVM_serverfunction(ClientConnect), "QC function ClientConnect is missing");
+               prog->ExecuteProgram(prog, PRVM_serverfunction(ClientConnect), "QC function ClientConnect is missing");
 
                if (cls.state == ca_dedicated)
                        Con_Printf("%s connected\n", host_client->name);
 
-               PRVM_ExecuteProgram (PRVM_serverfunction(PutClientInServer), "QC function PutClientInServer is missing");
+               PRVM_serverglobalfloat(time) = sv.time;
+               prog->ExecuteProgram(prog, PRVM_serverfunction(PutClientInServer), "QC function PutClientInServer is missing");
        }
 
        if (!host_client->netconnection)
@@ -1911,9 +1984,19 @@ void Host_Spawn_f (void)
 Host_Begin_f
 ==================
 */
-void Host_Begin_f (void)
+static void Host_Begin_f (void)
 {
-       host_client->spawned = true;
+       if (!host_client->spawned)
+       {
+               Con_Print("Begin not valid -- not yet spawned\n");
+               return;
+       }
+       if (host_client->begun)
+       {
+               Con_Print("Begin not valid -- already begun\n");
+               return;
+       }
+       host_client->begun = true;
 
        // LordHavoc: note: this code also exists in SV_DropClient
        if (sv.loadgame)
@@ -1940,7 +2023,7 @@ Host_Kick_f
 Kicks a user off of the server
 ==================
 */
-void Host_Kick_f (void)
+static void Host_Kick_f (void)
 {
        const char *who;
        const char *message = NULL;
@@ -1951,7 +2034,6 @@ void Host_Kick_f (void)
        if (!sv.active)
                return;
 
-       SV_VM_Begin();
        save = host_client;
 
        if (Cmd_Argc() > 2 && strcmp(Cmd_Argv(1), "#") == 0)
@@ -1991,7 +2073,7 @@ void Host_Kick_f (void)
                if (Cmd_Argc() > 2)
                {
                        message = Cmd_Args();
-                       COM_ParseToken_Simple(&message, false, false);
+                       COM_ParseToken_Simple(&message, false, false, true);
                        if (byNumber)
                        {
                                message++;                                                      // skip the #
@@ -2010,7 +2092,6 @@ void Host_Kick_f (void)
        }
 
        host_client = save;
-       SV_VM_End();
 }
 
 /*
@@ -2026,8 +2107,9 @@ DEBUGGING TOOLS
 Host_Give_f
 ==================
 */
-void Host_Give_f (void)
+static void Host_Give_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        const char *t;
        int v;
 
@@ -2053,7 +2135,7 @@ void Host_Give_f (void)
        case '8':
        case '9':
                // MED 01/04/97 added hipnotic give stuff
-               if (gamemode == GAME_HIPNOTIC)
+               if (gamemode == GAME_HIPNOTIC || gamemode == GAME_QUOTH)
                {
                        if (t[0] == '6')
                        {
@@ -2148,7 +2230,7 @@ void Host_Give_f (void)
        }
 }
 
-prvm_edict_t   *FindViewthing (void)
+static prvm_edict_t    *FindViewthing(prvm_prog_t *prog)
 {
        int             i;
        prvm_edict_t    *e;
@@ -2156,7 +2238,7 @@ prvm_edict_t      *FindViewthing (void)
        for (i=0 ; i<prog->num_edicts ; i++)
        {
                e = PRVM_EDICT_NUM(i);
-               if (!strcmp (PRVM_GetString(PRVM_serveredictstring(e, classname)), "viewthing"))
+               if (!strcmp (PRVM_GetString(prog, PRVM_serveredictstring(e, classname)), "viewthing"))
                        return e;
        }
        Con_Print("No viewthing on map\n");
@@ -2168,29 +2250,27 @@ prvm_edict_t    *FindViewthing (void)
 Host_Viewmodel_f
 ==================
 */
-void Host_Viewmodel_f (void)
+static void Host_Viewmodel_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        prvm_edict_t    *e;
        dp_model_t      *m;
 
        if (!sv.active)
                return;
 
-       SV_VM_Begin();
-       e = FindViewthing ();
-       SV_VM_End();
-       if (!e)
-               return;
-
-       m = Mod_ForName (Cmd_Argv(1), false, true, NULL);
-       if (!m || !m->loaded || !m->Draw)
+       e = FindViewthing(prog);
+       if (e)
        {
-               Con_Printf("viewmodel: can't load %s\n", Cmd_Argv(1));
-               return;
+               m = Mod_ForName (Cmd_Argv(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));
        }
-
-       PRVM_serveredictfloat(e, frame) = 0;
-       cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)] = m;
 }
 
 /*
@@ -2198,8 +2278,9 @@ void Host_Viewmodel_f (void)
 Host_Viewframe_f
 ==================
 */
-void Host_Viewframe_f (void)
+static void Host_Viewframe_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        prvm_edict_t    *e;
        int             f;
        dp_model_t      *m;
@@ -2207,22 +2288,21 @@ void Host_Viewframe_f (void)
        if (!sv.active)
                return;
 
-       SV_VM_Begin();
-       e = FindViewthing ();
-       SV_VM_End();
-       if (!e)
-               return;
-       m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
+       e = FindViewthing(prog);
+       if (e)
+       {
+               m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
 
-       f = atoi(Cmd_Argv(1));
-       if (f >= m->numframes)
-               f = m->numframes-1;
+               f = atoi(Cmd_Argv(1));
+               if (f >= m->numframes)
+                       f = m->numframes-1;
 
-       PRVM_serveredictfloat(e, frame) = f;
+               PRVM_serveredictfloat(e, frame) = f;
+       }
 }
 
 
-void PrintFrameName (dp_model_t *m, int frame)
+static void PrintFrameName (dp_model_t *m, int frame)
 {
        if (m->animscenes)
                Con_Printf("frame %i: %s\n", frame, m->animscenes[frame].name);
@@ -2235,26 +2315,26 @@ void PrintFrameName (dp_model_t *m, int frame)
 Host_Viewnext_f
 ==================
 */
-void Host_Viewnext_f (void)
+static void Host_Viewnext_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        prvm_edict_t    *e;
        dp_model_t      *m;
 
        if (!sv.active)
                return;
 
-       SV_VM_Begin();
-       e = FindViewthing ();
-       SV_VM_End();
-       if (!e)
-               return;
-       m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
+       e = FindViewthing(prog);
+       if (e)
+       {
+               m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
 
-       PRVM_serveredictfloat(e, frame) = PRVM_serveredictfloat(e, frame) + 1;
-       if (PRVM_serveredictfloat(e, frame) >= m->numframes)
-               PRVM_serveredictfloat(e, frame) = m->numframes - 1;
+               PRVM_serveredictfloat(e, frame) = PRVM_serveredictfloat(e, frame) + 1;
+               if (PRVM_serveredictfloat(e, frame) >= m->numframes)
+                       PRVM_serveredictfloat(e, frame) = m->numframes - 1;
 
-       PrintFrameName (m, (int)PRVM_serveredictfloat(e, frame));
+               PrintFrameName (m, (int)PRVM_serveredictfloat(e, frame));
+       }
 }
 
 /*
@@ -2262,27 +2342,26 @@ void Host_Viewnext_f (void)
 Host_Viewprev_f
 ==================
 */
-void Host_Viewprev_f (void)
+static void Host_Viewprev_f (void)
 {
+       prvm_prog_t *prog = SVVM_prog;
        prvm_edict_t    *e;
        dp_model_t      *m;
 
        if (!sv.active)
                return;
 
-       SV_VM_Begin();
-       e = FindViewthing ();
-       SV_VM_End();
-       if (!e)
-               return;
-
-       m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
+       e = FindViewthing(prog);
+       if (e)
+       {
+               m = cl.model_precache[(int)PRVM_serveredictfloat(e, modelindex)];
 
-       PRVM_serveredictfloat(e, frame) = PRVM_serveredictfloat(e, frame) - 1;
-       if (PRVM_serveredictfloat(e, frame) < 0)
-               PRVM_serveredictfloat(e, frame) = 0;
+               PRVM_serveredictfloat(e, frame) = PRVM_serveredictfloat(e, frame) - 1;
+               if (PRVM_serveredictfloat(e, frame) < 0)
+                       PRVM_serveredictfloat(e, frame) = 0;
 
-       PrintFrameName (m, (int)PRVM_serveredictfloat(e, frame));
+               PrintFrameName (m, (int)PRVM_serveredictfloat(e, frame));
+       }
 }
 
 /*
@@ -2299,7 +2378,7 @@ DEMO LOOP CONTROL
 Host_Startdemos_f
 ==================
 */
-void Host_Startdemos_f (void)
+static void Host_Startdemos_f (void)
 {
        int             i, c;
 
@@ -2338,7 +2417,7 @@ Host_Demos_f
 Return to looping demos
 ==================
 */
-void Host_Demos_f (void)
+static void Host_Demos_f (void)
 {
        if (cls.state == ca_dedicated)
                return;
@@ -2355,7 +2434,7 @@ Host_Stopdemo_f
 Return to looping demos
 ==================
 */
-void Host_Stopdemo_f (void)
+static void Host_Stopdemo_f (void)
 {
        if (!cls.demoplayback)
                return;
@@ -2363,12 +2442,13 @@ void Host_Stopdemo_f (void)
        Host_ShutdownServer ();
 }
 
-void Host_SendCvar_f (void)
+static void Host_SendCvar_f (void)
 {
        int             i;
        cvar_t  *c;
        const char *cvarname;
        client_t *old;
+       char vabuf[1024];
 
        if(Cmd_Argc() != 2)
                return;
@@ -2379,9 +2459,9 @@ void Host_SendCvar_f (void)
                // LordHavoc: if there is no such cvar or if it is private, send a
                // reply indicating that it has no value
                if(!c || (c->flags & CVAR_PRIVATE))
-                       Cmd_ForwardStringToServer(va("sentcvar %s", cvarname));
+                       Cmd_ForwardStringToServer(va(vabuf, sizeof(vabuf), "sentcvar %s", cvarname));
                else
-                       Cmd_ForwardStringToServer(va("sentcvar %s \"%s\"", c->name, c->string));
+                       Cmd_ForwardStringToServer(va(vabuf, sizeof(vabuf), "sentcvar %s \"%s\"", c->name, c->string));
                return;
        }
        if(!sv.active)// || !PRVM_serverfunction(SV_ParseClientCommand))
@@ -2435,7 +2515,7 @@ Host_PQRcon_f
 ProQuake rcon support
 =====================
 */
-void Host_PQRcon_f (void)
+static void Host_PQRcon_f (void)
 {
        int n;
        const char *e;
@@ -2443,6 +2523,12 @@ void Host_PQRcon_f (void)
        lhnetsocket_t *mysocket;
        char peer_address[64];
 
+       if (Cmd_Argc() == 1)
+       {
+               Con_Printf("%s: Usage: %s command\n", Cmd_Argv(0), Cmd_Argv(0));
+               return;
+       }
+
        if (!rcon_password.string || !rcon_password.string[0] || rcon_secure.integer > 0)
        {
                Con_Printf ("You must set rcon_password before issuing an pqrcon command, and rcon_secure must be 0.\n");
@@ -2469,15 +2555,18 @@ void Host_PQRcon_f (void)
        mysocket = NetConn_ChooseClientSocketForAddress(&to);
        if (mysocket)
        {
-               SZ_Clear(&net_message);
-               MSG_WriteLong (&net_message, 0);
-               MSG_WriteByte (&net_message, CCREQ_RCON);
-               SZ_Write(&net_message, (const unsigned char*)rcon_password.string, n);
-               MSG_WriteByte (&net_message, 0); // terminate the (possibly partial) string
-               MSG_WriteString (&net_message, Cmd_Args());
-               StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
-               NetConn_Write(mysocket, net_message.data, net_message.cursize, &to);
-               SZ_Clear (&net_message);
+               sizebuf_t buf;
+               unsigned char bufdata[64];
+               buf.data = bufdata;
+               SZ_Clear(&buf);
+               MSG_WriteLong(&buf, 0);
+               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());
+               StoreBigLong(buf.data, NETFLAG_CTL | (buf.cursize & NETFLAG_LENGTH_MASK));
+               NetConn_Write(mysocket, buf.data, buf.cursize, &to);
+               SZ_Clear(&buf);
        }
 }
 
@@ -2493,12 +2582,19 @@ Host_Rcon_f
   an unconnected command.
 =====================
 */
-void Host_Rcon_f (void) // credit: taken from QuakeWorld
+static void Host_Rcon_f (void) // credit: taken from QuakeWorld
 {
        int i, n;
        const char *e;
        lhnetaddress_t to;
        lhnetsocket_t *mysocket;
+       char vabuf[1024];
+
+       if (Cmd_Argc() == 1)
+       {
+               Con_Printf("%s: Usage: %s command\n", Cmd_Argv(0), Cmd_Argv(0));
+               return;
+       }
 
        if (!rcon_password.string || !rcon_password.string[0])
        {
@@ -2561,7 +2657,7 @@ void Host_Rcon_f (void) // credit: taken from QuakeWorld
                }
                else
                {
-                       NetConn_WriteString(mysocket, va("\377\377\377\377rcon %.*s %s", n, rcon_password.string, Cmd_Args()), &to);
+                       NetConn_WriteString(mysocket, va(vabuf, sizeof(vabuf), "\377\377\377\377rcon %.*s %s", n, rcon_password.string, Cmd_Args()), &to);
                }
        }
 }
@@ -2575,7 +2671,7 @@ user <name or userid>
 Dump userdata / masterdata for a user
 ====================
 */
-void Host_User_f (void) // credit: taken from QuakeWorld
+static void Host_User_f (void) // credit: taken from QuakeWorld
 {
        int             uid;
        int             i;
@@ -2608,7 +2704,7 @@ Host_Users_f
 Dump userids for all current players
 ====================
 */
-void Host_Users_f (void) // credit: taken from QuakeWorld
+static void Host_Users_f (void) // credit: taken from QuakeWorld
 {
        int             i;
        int             c;
@@ -2636,7 +2732,7 @@ Sent by server when serverinfo changes
 ==================
 */
 // TODO: shouldn't this be a cvar instead?
-void Host_FullServerinfo_f (void) // credit: taken from QuakeWorld
+static void Host_FullServerinfo_f (void) // credit: taken from QuakeWorld
 {
        char temp[512];
        if (Cmd_Argc() != 2)
@@ -2658,7 +2754,7 @@ Allow clients to change userinfo
 ==================
 Casey was here :)
 */
-void Host_FullInfo_f (void) // credit: taken from QuakeWorld
+static void Host_FullInfo_f (void) // credit: taken from QuakeWorld
 {
        char key[512];
        char value[512];
@@ -2707,7 +2803,7 @@ CL_SetInfo_f
 Allow clients to change userinfo
 ==================
 */
-void Host_SetInfo_f (void) // credit: taken from QuakeWorld
+static void Host_SetInfo_f (void) // credit: taken from QuakeWorld
 {
        if (Cmd_Argc() == 1)
        {
@@ -2731,7 +2827,7 @@ packet <destination> <contents>
 Contents allows \n escape character
 ====================
 */
-void Host_Packet_f (void) // credit: taken from QuakeWorld
+static void Host_Packet_f (void) // credit: taken from QuakeWorld
 {
        char send[2048];
        int i, l;
@@ -2856,7 +2952,7 @@ void Host_Pings_f (void)
                MSG_WriteString(&host_client->netconnection->message, "\n");
 }
 
-void Host_PingPLReport_f(void)
+static void Host_PingPLReport_f(void)
 {
        char *errbyte;
        int i;
@@ -2902,7 +2998,7 @@ void Host_InitCommands (void)
        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", NULL, Host_Pause_f, "pause the game (if the server allows pausing)");
+       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");
@@ -2923,6 +3019,8 @@ void Host_InitCommands (void)
        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");