]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - host_cmd.c
added prvm_uint_t for bounds check tests in the vm
[xonotic/darkplaces.git] / host_cmd.c
index b8c493b27f68cc455b71530488aa5da731cdf4d0..6a0b99141fbd6165ace0c3238bbe5c9828b86e0b 100644 (file)
@@ -551,7 +551,7 @@ LOAD / SAVE GAME
 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;
@@ -641,11 +641,13 @@ void Host_Savegame_to(prvm_prog_t *prog, 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])
@@ -753,6 +755,11 @@ Host_Loadgame_f
 ===============
 */
 
+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;
@@ -764,12 +771,11 @@ static 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)
        {
@@ -945,7 +951,7 @@ static void Host_Loadgame_f (void)
                        while (entnum >= prog->max_edicts)
                                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)
@@ -988,6 +994,8 @@ static 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));
+                       BufStr_Flush(prog);
+
                        while (COM_ParseToken_Simple(&t, false, false, true))
                        {
                                if (!strcmp(com_token, "sv.lightstyles"))
@@ -1023,44 +1031,48 @@ static void Host_Loadgame_f (void)
                                        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, true);
-                                       i = atoi(com_token);
-                                       COM_ParseToken_Simple(&t, false, false, true);
-                                       k = atoi(com_token);
-                                       COM_ParseToken_Simple(&t, false, false, true);
-                                       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
@@ -1071,6 +1083,15 @@ static void Host_Loadgame_f (void)
        }
        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");
 
@@ -1198,7 +1219,7 @@ static void Host_Name_f (void)
        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
@@ -1316,7 +1337,7 @@ static void Host_Playerskin_f (void)
        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
@@ -1579,7 +1600,7 @@ static void Host_Color(int changetop, int changebottom)
        if (host_client->edict && PRVM_serverfunction(SV_ChangeTeam))
        {
                Con_DPrint("Calling SV_ChangeTeam\n");
-               prog->globals.generic[OFS_PARM0] = playercolor;
+               prog->globals.fp[OFS_PARM0] = playercolor;
                PRVM_serverglobalfloat(time) = sv.time;
                PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(host_client->edict);
                prog->ExecuteProgram(prog, PRVM_serverfunction(SV_ChangeTeam), "QC function SV_ChangeTeam is missing");
@@ -1698,16 +1719,37 @@ Host_Pause_f
 */
 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);
 }
 
 /*
@@ -1753,11 +1795,12 @@ Host_PreSpawn_f
 */
 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)
        {
@@ -1783,11 +1826,17 @@ static void Host_Spawn_f (void)
        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
@@ -1915,7 +1964,17 @@ Host_Begin_f
 */
 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)
@@ -2054,7 +2113,7 @@ static 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')
                        {
@@ -2442,6 +2501,12 @@ static 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");
@@ -2503,6 +2568,12 @@ static void Host_Rcon_f (void) // credit: taken from QuakeWorld
        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])
        {
                Con_Printf ("You must set rcon_password before issuing an rcon command.\n");
@@ -2905,7 +2976,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");