From 15338c4e320b19dde5c3ca1f66667909c32e64fc Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Fri, 20 Oct 2023 20:33:37 -0700 Subject: [PATCH] Packet loss indicator --- src/cvars.cpp | 2 +- src/d_clisrv.c | 32 ++++++++++++++++++++++++++------ src/d_clisrv.h | 9 ++++++++- src/d_net.c | 2 ++ src/d_net.h | 5 +++++ src/hu_stuff.c | 22 +++++++++++++++++++++- src/hu_stuff.h | 2 +- src/k_hud.c | 2 +- src/p_user.c | 2 +- src/r_main.h | 1 + src/screen.c | 3 ++- src/typedef.h | 1 + src/y_inter.c | 1 + 13 files changed, 71 insertions(+), 13 deletions(-) diff --git a/src/cvars.cpp b/src/cvars.cpp index 4aa73492f..4acadb22d 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -810,7 +810,6 @@ consvar_t cv_timescale = OnlineCheat(cvlist_timer)("timescale", "1.0").floating_ consvar_t cv_ufo_follow = OnlineCheat("ufo_follow", "0").min_max(0, MAXPLAYERS).description("Make UFO Catcher folow this player"); consvar_t cv_ufo_health = OnlineCheat("ufo_health", "-1").min_max(-1, 100).description("Override UFO Catcher health -- applied at spawn or when value is changed"); - // // Server local cheats. // Not netsynced, not saved... @@ -853,6 +852,7 @@ consvar_t cv_debugrender_portal = PlayerCheat("debugrender_portal", "Off").on_of consvar_t cv_debugrender_spriteclip = PlayerCheat("debugrender_spriteclip", "Off").on_off().description("Let sprites draw through walls"); consvar_t cv_devmode_screen = PlayerCheat("devmode_screen", "1").min_max(1, 4).description("Choose which splitscreen player devmode applies to"); consvar_t cv_drawpickups = PlayerCheat("drawpickups", "Yes").yes_no().description("Hide rings, spheres, item capsules, prison capsules (visual only)"); +consvar_t cv_drawinput = PlayerCheat("drawinput", "No").yes_no().description("Draw turn inputs outside of Record Attack (turn solver debugging)"); void CV_palette_OnChange(void); consvar_t cv_palette = PlayerCheat("palette", "").onchange_noinit(CV_palette_OnChange).description("Force palette to a different lump"); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 691fa1b55..3647191ea 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -117,6 +117,7 @@ static tic_t joindelay = 0; UINT16 pingmeasurecount = 1; UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone. UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values. +UINT32 playerpacketlosstable[MAXPLAYERS]; #define GENTLEMANSMOOTHING (TICRATE) static tic_t reference_lag; @@ -5317,10 +5318,15 @@ static void HandlePacketFromPlayer(SINT8 node) { UINT8 i; for (i = 0; i < MAXPLAYERS; i++) + { if (playeringame[i]) - playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i]; + { + playerpingtable[i] = (tic_t)netbuffer->u.netinfo.pingtable[i]; + playerpacketlosstable[i] = netbuffer->u.netinfo.packetloss[i]; + } + } - servermaxping = (tic_t)netbuffer->u.pingtable[MAXPLAYERS]; + servermaxping = (tic_t)netbuffer->u.netinfo.pingtable[MAXPLAYERS]; } break; @@ -6021,6 +6027,8 @@ static void SV_Maketic(void) for (i = 0; i < MAXPLAYERS; i++) { + packetloss[i][maketic%PACKETMEASUREWINDOW] = false; + if (!playeringame[i]) continue; @@ -6048,6 +6056,9 @@ static void SV_Maketic(void) *ticcmd = *prevticcmd; ticcmd->flags &= ~TICCMD_RECEIVED; } + + // packetloss[i][leveltime%PACKETMEASUREWINDOW] = (cmd->flags & TICCMD_RECEIVED) ? false : true; + packetloss[i][maketic%PACKETMEASUREWINDOW] = true; } } @@ -6190,7 +6201,7 @@ static INT32 pingtimeout[MAXPLAYERS]; static inline void PingUpdate(void) { - INT32 i; + INT32 i, j; boolean pingkick[MAXPLAYERS]; UINT8 nonlaggers = 0; memset(pingkick, 0, sizeof(pingkick)); @@ -6250,20 +6261,29 @@ static inline void PingUpdate(void) { //CONS_Printf("player %d - total pings: %d\n", i, realpingtable[i]); - netbuffer->u.pingtable[i] = realpingtable[i] / pingmeasurecount; + netbuffer->u.netinfo.pingtable[i] = realpingtable[i] / pingmeasurecount; //server takes a snapshot of the real ping for display. //otherwise, pings fluctuate a lot and would be odd to look at. playerpingtable[i] = realpingtable[i] / pingmeasurecount; realpingtable[i] = 0; //Reset each as we go. + + UINT32 lost = 0; + for (j = 0; j < PACKETMEASUREWINDOW; j++) + { + if (packetloss[i][j]) + lost++; + } + + netbuffer->u.netinfo.packetloss[i] = lost; } // send the server's maxping as last element of our ping table. This is useful to let us know when we're about to get kicked. - netbuffer->u.pingtable[MAXPLAYERS] = cv_maxping.value; + netbuffer->u.netinfo.pingtable[MAXPLAYERS] = cv_maxping.value; //send out our ping packets for (i = 0; i < MAXNETNODES; i++) if (nodeingame[i]) - HSendPacket(i, true, 0, sizeof(INT32) * (MAXPLAYERS+1)); + HSendPacket(i, true, 0, sizeof(netinfo_pak)); pingmeasurecount = 0; //Reset count } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index aff074f51..a237cce7e 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -402,6 +402,12 @@ struct say_pak UINT8 source; } ATTRPACK; +struct netinfo_pak +{ + UINT32 pingtable[MAXPLAYERS+1]; + UINT32 packetloss[MAXPLAYERS+1]; +} ATTRPACK; + // // Network packet data // @@ -438,7 +444,7 @@ struct doomdata_t plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) INT32 filesneedednum; // 4 bytes filesneededconfig_pak filesneededcfg; // ??? bytes - UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes + netinfo_pak netinfo; // Don't believe their lies clientkey_pak clientkey; // 32 bytes serverchallenge_pak serverchallenge; // 256 bytes challengeall_pak challengeall; // 256 bytes @@ -536,6 +542,7 @@ extern tic_t jointimeout; extern UINT16 pingmeasurecount; extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; +extern UINT32 playerpacketlosstable[MAXPLAYERS]; extern tic_t servermaxping; extern boolean server_lagless; diff --git a/src/d_net.c b/src/d_net.c index ef48a55ab..22fd1ce5c 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -95,6 +95,8 @@ static INT32 retransmit = 0, duppacket = 0; static INT32 sendackpacket = 0, getackpacket = 0; INT32 ticruned = 0, ticmiss = 0; +boolean packetloss[MAXPLAYERS][PACKETMEASUREWINDOW]; + // globals INT32 getbps, sendbps; float lostpercent, duppercent, gamelostpercent; diff --git a/src/d_net.h b/src/d_net.h index 90283ce6c..5d76915e8 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -22,6 +22,8 @@ extern "C" { #endif +#include "doomdef.h" + // Max computers in a game // 127 is probably as high as this can go, because // SINT8 is used for nodes sometimes >:( @@ -40,6 +42,9 @@ boolean Net_GetNetStat(void); extern INT32 getbytes; extern INT64 sendbytes; // Realtime updated +#define PACKETMEASUREWINDOW (TICRATE*2) +extern boolean packetloss[MAXPLAYERS][PACKETMEASUREWINDOW]; + extern SINT8 nodetoplayer[MAXNETNODES]; extern SINT8 nodetoplayer2[MAXNETNODES]; // Say the numplayer for this node if any (splitscreen) extern SINT8 nodetoplayer3[MAXNETNODES]; // Say the numplayer for this node if any (splitscreen == 2) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 0b0434f70..427a0b8c4 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2201,10 +2201,25 @@ Ping_gfx_color (int lag) return SKINCOLOR_MAGENTA; } +static int +PL_gfx_color (int pl) +{ + if (pl == 0) + return SKINCOLOR_JAWZ; + else if (pl <= 2) + return SKINCOLOR_MINT; + else if (pl <= 4) + return SKINCOLOR_GOLD; + else if (pl <= 6) + return SKINCOLOR_RASPBERRY; + else + return SKINCOLOR_MAGENTA; +} + // // HU_drawPing // -void HU_drawPing(fixed_t x, fixed_t y, UINT32 lag, INT32 flags, boolean offline, SINT8 toside) +void HU_drawPing(fixed_t x, fixed_t y, UINT32 lag, UINT32 pl, INT32 flags, boolean offline, SINT8 toside) { UINT8 *colormap = NULL; INT32 measureid = cv_pingmeasurement.value ? 1 : 0; @@ -2212,6 +2227,8 @@ void HU_drawPing(fixed_t x, fixed_t y, UINT32 lag, INT32 flags, boolean offline, boolean drawlocal = (offline && cv_mindelay.value && lag <= (tic_t)cv_mindelay.value); fixed_t x2, y2; + y = y - 10*FRACUNIT; // Making space for connection quality, sorry. + if (!server && lag <= (tic_t)cv_mindelay.value) { lag = cv_mindelay.value; @@ -2276,6 +2293,9 @@ void HU_drawPing(fixed_t x, fixed_t y, UINT32 lag, INT32 flags, boolean offline, colormap = R_GetTranslationColormap(TC_RAINBOW, Ping_gfx_color(lag), GTC_CACHE); + if (pl) + V_DrawPingNum(x2, y2 + 8*FRACUNIT, flags, 100*(PACKETMEASUREWINDOW - pl)/PACKETMEASUREWINDOW, R_GetTranslationColormap(TC_RAINBOW, PL_gfx_color(pl), GTC_CACHE)); + if (servermaxping && lag > servermaxping && hu_tick < 4) { // flash ping red if too high diff --git a/src/hu_stuff.h b/src/hu_stuff.h index db1cfcc57..897e31c19 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -156,7 +156,7 @@ void HU_TickSongCredits(void); char HU_dequeueChatChar(void); void HU_Erase(void); void HU_clearChatChars(void); -void HU_drawPing(fixed_t x, fixed_t y, UINT32 ping, INT32 flags, boolean offline, SINT8 toside); // Lat': Ping drawer for scoreboard. +void HU_drawPing(fixed_t x, fixed_t y, UINT32 ping, UINT32 packetloss, INT32 flags, boolean offline, SINT8 toside); // Lat': Ping drawer for scoreboard. void HU_drawMiniPing(INT32 x, INT32 y, UINT32 ping, INT32 flags); // CECHO interface. diff --git a/src/k_hud.c b/src/k_hud.c index 82c8232d3..a4dcf09d2 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -5539,7 +5539,7 @@ void K_drawKartHUD(void) K_drawRingCounter(gametypeinfoshown); } - if (modeattacking && !bossinfo.valid) + if ((modeattacking && !bossinfo.valid) || cv_drawinput.value) { // Draw the input UI if (LUA_HudEnabled(hud_position)) diff --git a/src/p_user.c b/src/p_user.c index 17f04c76f..d10319e06 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2366,7 +2366,7 @@ void P_MovePlayer(player_t *player) ////////////////////// P_UpdatePlayerAngle(player); - + ticruned++; if (!(cmd->flags & TICCMD_RECEIVED)) ticmiss++; diff --git a/src/r_main.h b/src/r_main.h index f3687dd8c..97b73712c 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -135,6 +135,7 @@ extern consvar_t cv_fov[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_skybox; extern consvar_t cv_drawpickups; extern consvar_t cv_debugfinishline; +extern consvar_t cv_drawinput; // debugging diff --git a/src/screen.c b/src/screen.c index e49c939cb..7c931275d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -577,6 +577,7 @@ void SCR_DisplayLocalPing(void) } UINT32 ping = playerpingtable[consoleplayer]; + UINT32 pl = playerpacketlosstable[consoleplayer]; if (cv_showping.value == 2 && ping <= servermaxping) // only show 2 (warning) if our ping is at a bad level { @@ -586,7 +587,7 @@ void SCR_DisplayLocalPing(void) INT32 dispy = cv_ticrate.value ? 170 : 181; boolean offline = (consoleplayer == serverplayer); - HU_drawPing(307 * FRACUNIT, dispy * FRACUNIT, ping, V_SNAPTORIGHT | V_SNAPTOBOTTOM, offline, 0); + HU_drawPing(307 * FRACUNIT, dispy * FRACUNIT, ping, pl, V_SNAPTORIGHT | V_SNAPTOBOTTOM, offline, 0); } diff --git a/src/typedef.h b/src/typedef.h index f6979f09d..6e7ebd9c5 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -82,6 +82,7 @@ TYPEDEF (challengeall_pak); TYPEDEF (responseall_pak); TYPEDEF (resultsall_pak); TYPEDEF (say_pak); +TYPEDEF (netinfo_pak); // d_event.h TYPEDEF (event_t); diff --git a/src/y_inter.c b/src/y_inter.c index 9856a7df8..e2fc11a6e 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -697,6 +697,7 @@ void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 xoffset) HU_drawPing( (x2 - 2) * FRACUNIT, (y-2) * FRACUNIT, playerpingtable[pnum], + playerpacketlosstable[pnum], 0, false, (datarightofcolumn ? 1 : -1)