]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - host_cmd.c
Removed all calls to strcpy; most of them are now calls to strlcpy or memcpy.
[xonotic/darkplaces.git] / host_cmd.c
index ebfd6d49a0a149bf0252c03dc1253a173dfa1dda..408592e28301ca4af00558e7ff5aef3d2c07d57c 100644 (file)
@@ -55,7 +55,8 @@ void Host_Status_f (void)
 
        if (cmd_source == src_command)
        {
-               if (!sv.active)
+               // 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 ();
                        return;
@@ -65,6 +66,9 @@ void Host_Status_f (void)
        else
                print = SV_ClientPrintf;
 
+       if (!sv.active)
+               return;
+
        for (players = 0, j = 0;j < svs.maxclients;j++)
                if (svs.clients[j].active)
                        players++;
@@ -88,7 +92,7 @@ void Host_Status_f (void)
                }
                else
                        hours = 0;
-               print ("#%-2u %-16.16s  %3i  %2i:%02i:%02i\n", j+1, client->name, (int)client->edict->fields.server->frags, hours, minutes, seconds);
+               print ("#%-3u %-16.16s  %3i  %2i:%02i:%02i\n", j+1, client->name, (int)client->edict->fields.server->frags, hours, minutes, seconds);
                print ("   %s\n", client->netconnection ? client->netconnection->address : "botclient");
        }
 }
@@ -213,6 +217,7 @@ Host_Ping_f
 
 ==================
 */
+void Host_Pings_f (void); // called by Host_Ping_f
 void Host_Ping_f (void)
 {
        int i;
@@ -221,7 +226,8 @@ void Host_Ping_f (void)
 
        if (cmd_source == src_command)
        {
-               if (!sv.active)
+               // 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 ();
                        return;
@@ -231,6 +237,9 @@ void Host_Ping_f (void)
        else
                print = SV_ClientPrintf;
 
+       if (!sv.active)
+               return;
+
        print("Client ping times:\n");
        for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++)
        {
@@ -238,6 +247,9 @@ void Host_Ping_f (void)
                        continue;
                print("%4i %s\n", (int)floor(client->ping*1000+0.5), 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)
+       Host_Pings_f();
 }
 
 /*
@@ -280,7 +292,7 @@ void Host_Map_f (void)
 
        svs.serverflags = 0;                    // haven't completed an episode yet
        allowcheats = sv_cheats.integer != 0;
-       strcpy(level, Cmd_Argv(1));
+       strlcpy(level, Cmd_Argv(1), sizeof(level));
        SV_SpawnServer(level);
        if (sv.active && cls.state == ca_disconnected)
                CL_EstablishConnection("local:1");
@@ -340,7 +352,7 @@ void Host_Changelevel_f (void)
        SV_SaveSpawnparms ();
        SV_VM_End();
        allowcheats = sv_cheats.integer != 0;
-       strcpy(level, Cmd_Argv(1));
+       strlcpy(level, Cmd_Argv(1), sizeof(level));
        SV_SpawnServer(level);
        if (sv.active && cls.state == ca_disconnected)
                CL_EstablishConnection("local:1");
@@ -374,7 +386,7 @@ void Host_Restart_f (void)
        key_dest = key_game;
 
        allowcheats = sv_cheats.integer != 0;
-       strcpy(mapname, sv.name);
+       strlcpy(mapname, sv.name, sizeof(mapname));
        SV_SpawnServer(mapname);
        if (sv.active && cls.state == ca_disconnected)
                CL_EstablishConnection("local:1");
@@ -616,7 +628,7 @@ void Host_Loadgame_f (void)
                return;
        }
 
-       strcpy (filename, Cmd_Argv(1));
+       strlcpy (filename, Cmd_Argv(1), sizeof(filename));
        FS_DefaultExtension (filename, ".sav", sizeof (filename));
 
        Con_Printf("Loading game from %s...\n", filename);
@@ -658,7 +670,7 @@ void Host_Loadgame_f (void)
 
        // mapname
        COM_ParseTokenConsole(&t);
-       strcpy (mapname, com_token);
+       strlcpy (mapname, com_token, sizeof(mapname));
 
        // time
        COM_ParseTokenConsole(&t);
@@ -823,7 +835,7 @@ void Host_Name_f (void)
        {
                if (host_client->spawned)
                        SV_BroadcastPrintf("%s changed name to %s\n", host_client->old_name, host_client->name);
-               strcpy(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
                MSG_WriteByte (&sv.reliable_datagram, svc_updatename);
                MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
@@ -882,7 +894,7 @@ void Host_Playermodel_f (void)
                PRVM_GETEDICTFIELDVALUE(host_client->edict, eval_playermodel)->string = PRVM_SetEngineString(host_client->playermodel);
        if (strcmp(host_client->old_model, host_client->playermodel))
        {
-               strcpy(host_client->old_model, host_client->playermodel);
+               strlcpy(host_client->old_model, host_client->playermodel, sizeof(host_client->old_model));
                /*// send notification to all clients
                MSG_WriteByte (&sv.reliable_datagram, svc_updatepmodel);
                MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
@@ -942,7 +954,7 @@ void Host_Playerskin_f (void)
        {
                //if (host_client->spawned)
                //      SV_BroadcastPrintf("%s changed skin to %s\n", host_client->name, host_client->playerskin);
-               strcpy(host_client->old_skin, host_client->playerskin);
+               strlcpy(host_client->old_skin, host_client->playerskin, sizeof(host_client->old_skin));
                /*// send notification to all clients
                MSG_WriteByte (&sv.reliable_datagram, svc_updatepskin);
                MSG_WriteByte (&sv.reliable_datagram, host_client - svs.clients);
@@ -2324,6 +2336,71 @@ void Host_Packet_f (void) // credit: taken from QuakeWorld
                NetConn_Write(mysocket, send, out - send, &address);
 }
 
+/*
+====================
+Host_Pings_f
+
+Send back ping and packet loss update for all current players to this player
+====================
+*/
+void Host_Pings_f (void)
+{
+       int             i, j, ping, packetloss;
+       char temp[128];
+
+       if (cmd_source == src_command)
+       {
+               Cmd_ForwardToServer ();
+               return;
+       }
+       if (!host_client->netconnection)
+               return;
+
+       if (sv.protocol != PROTOCOL_QUAKEWORLD)
+       {
+               MSG_WriteByte(&host_client->netconnection->message, svc_stufftext);
+               MSG_WriteUnterminatedString(&host_client->netconnection->message, "pingplreport");
+       }
+       for (i = 0;i < svs.maxclients;i++)
+       {
+               packetloss = 0;
+               if (svs.clients[i].netconnection)
+                       for (j = 0;j < 100;j++)
+                               packetloss += svs.clients[i].netconnection->packetlost[j];
+               ping = (int)floor(svs.clients[i].ping*1000+0.5);
+               ping = bound(0, ping, 9999);
+               if (sv.protocol == PROTOCOL_QUAKEWORLD)
+               {
+                       // send qw_svc_updateping and qw_svc_updatepl messages
+                       MSG_WriteByte(&host_client->netconnection->message, qw_svc_updateping);
+                       MSG_WriteShort(&host_client->netconnection->message, ping);
+                       MSG_WriteByte(&host_client->netconnection->message, qw_svc_updatepl);
+                       MSG_WriteByte(&host_client->netconnection->message, packetloss);
+               }
+               else
+               {
+                       // write the string into the packet as multiple unterminated strings to avoid needing a local buffer
+                       dpsnprintf(temp, sizeof(temp), " %d %d", ping, packetloss);
+                       MSG_WriteUnterminatedString(&host_client->netconnection->message, temp);
+               }
+       }
+       if (sv.protocol != PROTOCOL_QUAKEWORLD)
+               MSG_WriteString(&host_client->netconnection->message, "\n");
+}
+
+void Host_PingPLReport_f(void)
+{
+       int i;
+       int l = Cmd_Argc();
+       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 = atoi(Cmd_Argv(1+i*2+1));
+       }
+}
+
 //=============================================================================
 
 /*
@@ -2415,6 +2492,9 @@ void Host_InitCommands (void)
        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 ("pings", 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)");
+
        Cvar_RegisterVariable (&team);
        Cvar_RegisterVariable (&skin);
        Cvar_RegisterVariable (&noaim);