added ping and packet loss display to scoreboard, and pings/pingplreport commands...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 8 Jul 2006 09:24:58 +0000 (09:24 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 8 Jul 2006 09:24:58 +0000 (09:24 +0000)
revised scoreboard layout and added column titles above it

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

cl_input.c
host_cmd.c
netconn.c
netconn.h
sbar.c
sv_user.c

index ae0ba2f..2824743 100644 (file)
@@ -1187,7 +1187,7 @@ CL_SendMove
 extern cvar_t cl_netinputpacketspersecond;
 void CL_SendMove(void)
 {
-       int i;
+       int i, j, packetloss;
        int bits;
        int impulse;
        sizebuf_t buf;
@@ -1334,8 +1334,9 @@ void CL_SendMove(void)
                                checksumindex = buf.cursize;
                                MSG_WriteByte(&buf, 0);
                                // packet loss percentage
-                               // FIXME: netgraph stuff
-                               MSG_WriteByte(&buf, 0);
+                               for (j = 0, packetloss = 0;j < 100;j++)
+                                       packetloss += cls.netcon->packetlost[j];
+                               MSG_WriteByte(&buf, packetloss);
                                // write most recent 3 moves
                                i = (cls.netcon->qw.outgoing_sequence-2) & QW_UPDATE_MASK;
                                cmd = &cl.qw_moves[i];
index ebfd6d4..8e6930d 100644 (file)
@@ -2324,6 +2324,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 +2480,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);
index a37505c..79448a9 100755 (executable)
--- a/netconn.c
+++ b/netconn.c
@@ -846,6 +846,8 @@ static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int len
        if (length < 8)
                return 0;
 
+       // TODO: add netgraph stuff rather than just packetloss counting...
+
        if (protocol == PROTOCOL_QUAKEWORLD)
        {
                int sequence, sequence_ack;
@@ -876,15 +878,22 @@ static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int len
                sequence_ack &= ~(1<<31);
                if (sequence <= conn->qw.incoming_sequence)
                {
-                       Con_DPrint("Got a stale datagram\n");
+                       //Con_DPrint("Got a stale datagram\n");
                        return 0;
                }
                count = sequence - (conn->qw.incoming_sequence + 1);
                if (count > 0)
                {
                        droppedDatagrams += count;
-                       Con_DPrintf("Dropped %u datagram(s)\n", count);
+                       //Con_DPrintf("Dropped %u datagram(s)\n", count);
+                       while (count--)
+                       {
+                               conn->packetlost[conn->packetlostcounter] = true;
+                               conn->packetlostcounter = (conn->packetlostcounter + 1) % 100;
+                       }
                }
+               conn->packetlost[conn->packetlostcounter] = false;
+               conn->packetlostcounter = (conn->packetlostcounter + 1) % 100;
                if (reliable_ack == conn->qw.reliable_sequence)
                {
                        // received, now we will be able to send another reliable message
@@ -931,8 +940,15 @@ static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int len
                                        {
                                                count = sequence - conn->nq.unreliableReceiveSequence;
                                                droppedDatagrams += count;
-                                               Con_DPrintf("Dropped %u datagram(s)\n", count);
+                                               //Con_DPrintf("Dropped %u datagram(s)\n", count);
+                                               while (count--)
+                                               {
+                                                       conn->packetlost[conn->packetlostcounter] = true;
+                                                       conn->packetlostcounter = (conn->packetlostcounter + 1) % 100;
+                                               }
                                        }
+                                       conn->packetlost[conn->packetlostcounter] = false;
+                                       conn->packetlostcounter = (conn->packetlostcounter + 1) % 100;
                                        conn->nq.unreliableReceiveSequence = sequence + 1;
                                        conn->lastMessageTime = realtime;
                                        conn->timeout = realtime + net_messagetimeout.value;
@@ -945,8 +961,8 @@ static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int len
                                                return 2;
                                        }
                                }
-                               else
-                                       Con_DPrint("Got a stale datagram\n");
+                               //else
+                               //      Con_DPrint("Got a stale datagram\n");
                                return 1;
                        }
                        else if (flags & NETFLAG_ACK)
@@ -999,11 +1015,11 @@ static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int len
                                                else
                                                        conn->sendMessageLength = 0;
                                        }
-                                       else
-                                               Con_DPrint("Duplicate ACK received\n");
+                                       //else
+                                       //      Con_DPrint("Duplicate ACK received\n");
                                }
-                               else
-                                       Con_DPrint("Stale ACK received\n");
+                               //else
+                               //      Con_DPrint("Stale ACK received\n");
                                return 1;
                        }
                        else if (flags & NETFLAG_DATA)
index ddbce41..bbd1b88 100755 (executable)
--- a/netconn.h
+++ b/netconn.h
@@ -185,6 +185,10 @@ typedef struct netconn_s
        }
        qw;
 
+       // this tracks which of the last 100 received packet sequence numbers were lost
+       int packetlostcounter;
+       unsigned char packetlost[100];
+
        char address[128];
 } netconn_t;
 
diff --git a/sbar.c b/sbar.c
index 95a79f3..01df2be 100644 (file)
--- a/sbar.c
+++ b/sbar.c
@@ -1370,33 +1370,19 @@ float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
 {
        int minutes;
        unsigned char *c;
-       if (cls.protocol == PROTOCOL_QUAKEWORLD)
-       {
-               minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : realtime - s->qw_entertime) / 60.0);
-               if (s->qw_spectator)
-                       DrawQ_ColoredString(x, y, va("%c%4i %2i %4i spec %-4s %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, cl.qw_teamplay ? s->qw_team : "", s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
-               else
-               {
-                       // draw colors behind score
-                       c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
-                       DrawQ_Pic(x + 14*8, y+1, NULL, 32, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
-                       c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
-                       DrawQ_Pic(x + 14*8, y+4, NULL, 32, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
-                       // print the text
-                       //DrawQ_String(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
-                       DrawQ_ColoredString(x, y, va("%c%4i %2i %4i %4i %-4s %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
-               }
-       }
+       minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : realtime - s->qw_entertime) / 60.0);
+       if (s->qw_spectator)
+               DrawQ_ColoredString(x, y, va("%4i %3i %4i spect %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
        else
        {
                // draw colors behind score
                c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
-               DrawQ_Pic(x + 1*8, y+1, NULL, 32, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
+               DrawQ_Pic(x + 14*8, y+1, NULL, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
                c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
-               DrawQ_Pic(x + 1*8, y+4, NULL, 32, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
+               DrawQ_Pic(x + 14*8, y+4, NULL, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
                // print the text
                //DrawQ_String(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
-               DrawQ_ColoredString(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+               DrawQ_ColoredString(x, y, va("%4i %3i %4i %5i %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
        }
        return 8;
 }
@@ -1406,14 +1392,19 @@ void Sbar_DeathmatchOverlay (void)
        int i, x, y;
 
        // request new ping times every two second
-       if (cl.last_ping_request < realtime - 2)
+       if (cl.last_ping_request < realtime - 2 && cls.netcon)
        {
                cl.last_ping_request = realtime;
-               if (cls.protocol == PROTOCOL_QUAKEWORLD && cls.netcon)
+               if (cls.protocol == PROTOCOL_QUAKEWORLD)
                {
                        MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
                        MSG_WriteString(&cls.netcon->message, "pings");
                }
+               else
+               {
+                       MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
+                       MSG_WriteString(&cls.netcon->message, "pings");
+               }
        }
 
        DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
@@ -1421,11 +1412,10 @@ void Sbar_DeathmatchOverlay (void)
        // scores
        Sbar_SortFrags ();
        // draw the text
-       if (cls.protocol == PROTOCOL_QUAKEWORLD)
-               x = (vid_conwidth.integer - (6 + 17 + 15) * 8) / 2;
-       else
-               x = (vid_conwidth.integer - (6 + 15) * 8) / 2;
+       x = (vid_conwidth.integer - (6 + 18 + 15) * 8) / 2;
        y = 40;
+       DrawQ_ColoredString(x, y, va("ping pl%% time frags team  name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
+       y += 8;
 
        if (Sbar_IsTeammatch ())
        {
index 9ef6b38..e899801 100644 (file)
--- a/sv_user.c
+++ b/sv_user.c
@@ -706,6 +706,7 @@ void SV_ReadClientMessage(void)
                         || strncasecmp(s, "pause", 5) == 0
                         || strncasecmp(s, "kick", 4) == 0
                         || strncasecmp(s, "ping", 4) == 0
+                        || strncasecmp(s, "pings", 5) == 0
                         || strncasecmp(s, "ban", 3) == 0
                         || strncasecmp(s, "pmodel", 6) == 0
                         || strncasecmp(s, "rate", 4) == 0