From 7fd64a4c3de36e27e38f3b19672d2bf178570cc1 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 27 Aug 2023 21:41:51 +0100 Subject: [PATCH] Get the Server Browser working again - KartKrew/Kart-Public!313 has finally been integrated with the changed menu code - Attempts multiple times to get every public server, up to nettimeout - Clear the server list when entering/exiting and refrehing - Show visible servers and potential servers opposite the Refresh input - I would have done this in another commit, but the system was too broken to repair without just putting the working solution in wholesale - Improved visual scrolling behaviour - Pressing A actually joins the server - CORE vs MODDED is handled in SL_InsertServer, not a seperate function to drop/memcpy things around Also, abstract out the little "PLEASE WAIT..." message popup during potential IO block into M_PleaseWait (only used on connect process via Menu) --- src/d_clisrv.c | 63 ++++++++++--- src/d_clisrv.h | 3 +- src/k_menu.h | 9 +- src/k_menudraw.c | 85 +++++++++++++++++ src/menus/play-online-join-ip.c | 24 +++-- src/menus/play-online-server-browser.c | 126 +++++++++++++------------ 6 files changed, 223 insertions(+), 87 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 92d67f224..bebaae8f3 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1550,6 +1550,10 @@ static void SendAskInfo(INT32 node) serverelem_t serverlist[MAXSERVERLIST]; UINT32 serverlistcount = 0; +UINT32 serverlistultimatecount = 0; + +static boolean resendserverlistnode[MAXNETNODES]; +static tic_t serverlistepoch; static void SL_ClearServerList(INT32 connectedserver) { @@ -1562,6 +1566,8 @@ static void SL_ClearServerList(INT32 connectedserver) serverlist[i].node = 0; } serverlistcount = 0; + + memset(resendserverlistnode, 0, sizeof resendserverlistnode); } static UINT32 SL_SearchServer(INT32 node) @@ -1578,6 +1584,8 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node) { UINT32 i; + resendserverlistnode[node] = false; + // search if not already on it i = SL_SearchServer(node); if (i == UINT32_MAX) @@ -1601,6 +1609,9 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node) if (strcmp(info->application, SRB2APPLICATION)) return;/* that's a different mod */ + if (info->modifiedgame != (mpmenu.room == 1)) + return;/* CORE vs MODDED! */ + i = serverlistcount++; } @@ -1617,6 +1628,8 @@ void CL_QueryServerList (msg_server_t *server_list) CL_UpdateServerList(); + serverlistepoch = I_GetTime(); + for (i = 0; server_list[i].header.buffer[0]; i++) { // Make sure MS version matches our own, to @@ -1629,19 +1642,43 @@ void CL_QueryServerList (msg_server_t *server_list) if (node == -1) break; // no more node free SendAskInfo(node); - // Force close the connection so that servers can't eat - // up nodes forever if we never get a reply back from them - // (usually when they've not forwarded their ports). - // - // Don't worry, we'll get in contact with the working - // servers again when they send SERVERINFO to us later! - // - // (Note: as a side effect this probably means every - // server in the list will probably be using the same node (e.g. node 1), - // not that it matters which nodes they use when - // the connections are closed afterwards anyway) - // -- Monster Iestyn 12/11/18 - Net_CloseConnection(node|FORCECLOSE); + + resendserverlistnode[node] = true; + // Leave this node open. It'll be closed if the + // request times out (CL_TimeoutServerList). + } + } + + serverlistultimatecount = i; +} + +#define SERVERLISTRESENDRATE NEWTICRATE + +void CL_TimeoutServerList(void) +{ + if (netgame && serverlistultimatecount > serverlistcount) + { + const tic_t timediff = I_GetTime() - serverlistepoch; + const tic_t timetoresend = timediff % SERVERLISTRESENDRATE; + const boolean timedout = timediff > connectiontimeout; + + if (timedout || (timediff > 0 && timetoresend == 0)) + { + INT32 node; + + for (node = 1; node < MAXNETNODES; ++node) + { + if (resendserverlistnode[node]) + { + if (timedout) + Net_CloseConnection(node|FORCECLOSE); + else + SendAskInfo(node); + } + } + + if (timedout) + serverlistultimatecount = serverlistcount; } } } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index fdcf4d0fe..04221aeb9 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -460,7 +460,7 @@ struct serverelem_t }; extern serverelem_t serverlist[MAXSERVERLIST]; -extern UINT32 serverlistcount; +extern UINT32 serverlistcount, serverlistultimatecount; extern INT32 mapchangepending; // Points inside doomcom @@ -595,6 +595,7 @@ void CL_ClearPlayer(INT32 playernum); void CL_RemovePlayer(INT32 playernum, kickreason_t reason); void CL_QueryServerList(msg_server_t *list); void CL_UpdateServerList(void); +void CL_TimeoutServerList(void); // Is there a game running boolean Playing(void); diff --git a/src/k_menu.h b/src/k_menu.h index 875da6535..cd740df55 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -29,8 +29,6 @@ extern "C" { #endif -#define SERVERLISTDEBUG - // flags for items in the menu // menu handle (what we do when key is pressed #define IT_TYPE 14 // (2+4+8) @@ -842,6 +840,8 @@ extern struct mpmenu_s { } mpmenu; +void M_PleaseWait(void); + // Time Attack void M_PrepareTimeAttack(INT32 choice); void M_StartTimeAttack(INT32 choice); @@ -895,11 +895,6 @@ void Fetch_servers_thread (int *id); void M_RefreshServers(INT32 choice); void M_ServersMenu(INT32 choice); -// for debugging purposes... -#ifdef SERVERLISTDEBUG -void M_ServerListFillDebug(void); -#endif - // Options menu: // mode descriptions for video mode menu diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 800ff3c6c..78b96ee87 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -3408,6 +3408,89 @@ void M_DrawMPRoomSelect(void) } // SERVER BROWSER +static void M_DrawServerCountAndHorizontalBar(void) +{ + const char *text; + INT32 y = currentMenu->y+STRINGHEIGHT; + + const char throbber[4] = {'-', '\\', '|', '/'}; + UINT8 throbindex = (mpmenu.ticker/4) % 4; + + switch (M_GetWaitingMode()) + { + case M_WAITING_VERSION: + text = "Checking for updates"; + break; + + case M_WAITING_SERVERS: + text = "Loading server list"; + break; + + default: + if (serverlistultimatecount > serverlistcount) + { + text = va("%d/%d server%s found...", + serverlistcount, + serverlistultimatecount, + serverlistultimatecount == 1 ? "" : "s" + ); + } + else + { + throbindex = UINT8_MAX; // No throbber! + if (serverlistcount > 0) + { + text = va("%d server%s found", + serverlistcount, + serverlistcount == 1 ? "" : "s" + ); + } + else + { + text = "No servers found"; + } + } + } + + if (throbindex == UINT8_MAX) + { + V_DrawRightAlignedString( + BASEVIDWIDTH - currentMenu->x, + y, + highlightflags, + text + ); + } + else + { + V_DrawRightAlignedString( + BASEVIDWIDTH - currentMenu->x - 12, y, + highlightflags, + text + ); + + V_DrawCenteredString( // Only clean way to center the throbber without exposing character width + BASEVIDWIDTH - currentMenu->x - 4, y, + highlightflags, + va("%c", throbber[throbindex]) + ); + } + + // Did you change the Server Browser address? Have a little reminder. + + INT32 mservflags = 0; + if (CV_IsSetToDefault(&cv_masterserver)) + mservflags = highlightflags|V_30TRANS; + else + mservflags = warningflags; + + y = BASEVIDHEIGHT - 24; + + V_DrawFadeFill(0, y-1, BASEVIDWIDTH, 10, 0, 31, 5); + V_DrawCenteredString(BASEVIDWIDTH/2, y, + mservflags, va("MS: %s", cv_masterserver.string)); +} + void M_DrawMPServerBrowser(void) { patch_t *text1 = W_CachePatchName("MENUBGT1", PU_CACHE); @@ -3508,6 +3591,8 @@ void M_DrawMPServerBrowser(void) // normal menu options M_DrawGenericMenu(); + // And finally, the overlay bar! + M_DrawServerCountAndHorizontalBar(); } // OPTIONS MENU diff --git a/src/menus/play-online-join-ip.c b/src/menus/play-online-join-ip.c index a176d4e72..b3b0b3e8e 100644 --- a/src/menus/play-online-join-ip.c +++ b/src/menus/play-online-join-ip.c @@ -6,6 +6,7 @@ #include "../i_system.h" // I_OsPolling #include "../i_video.h" // I_UpdateNoBlit #include "../m_misc.h" // NUMLOGIP +#include "../f_finale.h" // g_wipeskiprender menuitem_t PLAY_MP_JoinIP[] = { @@ -56,6 +57,21 @@ void M_MPJoinIPInit(INT32 choice) M_SetupNextMenu(&PLAY_MP_JoinIPDef, true); } +void M_PleaseWait(void) +{ + if (rendermode == render_none) + return; + + g_wipeskiprender = true; + + M_DrawTextBox(56, BASEVIDHEIGHT/2-12, 24, 2); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "PLEASE WAIT..."); + I_OsPolling(); + I_UpdateNoBlit(); + if (rendermode == render_soft) + I_FinishUpdate(); // page flip or blit buffer +} + // Attempts to join a given IP from the menu. void M_JoinIP(const char *ipa) { @@ -67,13 +83,7 @@ void M_JoinIP(const char *ipa) COM_BufAddText(va("connect \"%s\"\n", ipa)); - // A little "please wait" message. - M_DrawTextBox(56, BASEVIDHEIGHT/2-12, 24, 2); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Connecting to server..."); - I_OsPolling(); - I_UpdateNoBlit(); - if (rendermode == render_soft) - I_FinishUpdate(); // page flip or blit buffer + M_PleaseWait(); } boolean M_JoinIPInputs(INT32 ch) diff --git a/src/menus/play-online-server-browser.c b/src/menus/play-online-server-browser.c index 730a34956..80aa41038 100644 --- a/src/menus/play-online-server-browser.c +++ b/src/menus/play-online-server-browser.c @@ -3,11 +3,14 @@ #include "../k_menu.h" #include "../v_video.h" -#include "../i_system.h" // I_OsPolling -#include "../i_video.h" // I_UpdateNoBlit +#include "../s_sound.h" + +//#define SERVERLISTDEBUG #ifdef SERVERLISTDEBUG #include "../m_random.h" + +void M_ServerListFillDebug(void); #endif menuitem_t PLAY_MP_ServerBrowser[] = @@ -16,8 +19,8 @@ menuitem_t PLAY_MP_ServerBrowser[] = {IT_STRING | IT_CVAR, "SORT BY", NULL, // tooltip MUST be null. NULL, {.cvar = &cv_serversort}, 0, 0}, - {IT_STRING, "REFRESH", NULL, - NULL, {NULL}, 0, 0}, + {IT_STRING | IT_CALL, "REFRESH", NULL, + NULL, {.routine = &M_RefreshServers}, 0, 0}, {IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0}, }; @@ -42,28 +45,6 @@ menu_t PLAY_MP_ServerBrowserDef = { // for server fetch threads... M_waiting_mode_t m_waiting_mode = M_NOT_WAITING; -// depending on mpmenu.room, either allows only unmodded servers or modded ones. Remove others from the list. -// we do this by iterating backwards. -static void M_CleanServerList(void) -{ - UINT8 i = serverlistcount; - - while (i) - { - - if (serverlist[i].info.modifiedgame != mpmenu.room) - { - // move everything after this index 1 slot down... - if (i != serverlistcount) - memcpy(&serverlist[i], &serverlist[i+1], sizeof(serverelem_t)*(serverlistcount-i)); - - serverlistcount--; - } - - i--; - } -} - void M_SetWaitingMode (int mode) { @@ -180,31 +161,19 @@ void M_RefreshServers(INT32 choice) { (void)choice; - // Display a little "please wait" message. - M_DrawTextBox(52, BASEVIDHEIGHT/2-10, 25, 3); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, "Searching for servers..."); - V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2)+12, 0, "Please wait."); - I_OsPolling(); - I_UpdateNoBlit(); - if (rendermode == render_soft) - I_FinishUpdate(); // page flip or blit buffer + CL_UpdateServerList(); +#ifdef SERVERLISTDEBUG + M_ServerListFillDebug(); +#else /*SERVERLISTDEBUG*/ #ifdef MASTERSERVER #ifdef HAVE_THREADS Spawn_masterserver_thread("fetch-servers", Fetch_servers_thread); #else/*HAVE_THREADS*/ Fetch_servers_thread(NULL); #endif/*HAVE_THREADS*/ -#else/*MASTERSERVER*/ - CL_UpdateServerList(); #endif/*MASTERSERVER*/ - -#ifdef SERVERLISTDEBUG - M_ServerListFillDebug(); -#endif - M_CleanServerList(); - M_SortServerList(); - +#endif /*SERVERLISTDEBUG*/ } #ifdef UPDATE_ALERT @@ -253,6 +222,9 @@ void M_ServersMenu(INT32 choice) // modified game check: no longer handled // we don't request a restart unless the filelist differs + CL_UpdateServerList(); + + mpmenu.ticker = 0; mpmenu.servernum = 0; mpmenu.scrolln = 0; mpmenu.slide = 0; @@ -260,6 +232,10 @@ void M_ServersMenu(INT32 choice) M_SetupNextMenu(&PLAY_MP_ServerBrowserDef, false); itemOn = 0; +#ifdef SERVERLISTDEBUG + M_ServerListFillDebug(); +#else /*SERVERLISTDEBUG*/ + #if defined (MASTERSERVER) && defined (HAVE_THREADS) I_lock_mutex(&ms_QueryId_mutex); { @@ -289,12 +265,7 @@ void M_ServersMenu(INT32 choice) M_RefreshServers(0); #endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ -#ifdef SERVERLISTDEBUG - M_ServerListFillDebug(); -#endif - - M_CleanServerList(); - M_SortServerList(); +#endif /*SERVERLISTDEBUG*/ } #ifdef SERVERLISTDEBUG @@ -304,7 +275,7 @@ void M_ServerListFillDebug(void) { UINT8 i = 0; - serverlistcount = 10; + serverlistcount = 40; memset(serverlist, 0, sizeof(serverlist)); // zero out the array for convenience... for (i = 0; i < serverlistcount; i++) @@ -327,6 +298,8 @@ void M_ServerListFillDebug(void) CONS_Printf("Serv %d | %d...\n", i, serverlist[i].info.modifiedgame); } + + M_SortServerList(); } #endif // SERVERLISTDEBUG @@ -397,14 +370,33 @@ void M_SortServerList(void) // Server browser inputs & ticker void M_MPServerBrowserTick(void) { + mpmenu.ticker++; mpmenu.slide /= 2; + +#if defined (MASTERSERVER) && defined (HAVE_THREADS) + I_lock_mutex(&ms_ServerList_mutex); + { + if (ms_ServerList) + { + CL_QueryServerList(ms_ServerList); + free(ms_ServerList); + ms_ServerList = NULL; + } + } + I_unlock_mutex(ms_ServerList_mutex); +#endif + + CL_TimeoutServerList(); } // Input handler for server browser. boolean M_ServerBrowserInputs(INT32 ch) { UINT8 pid = 0; - UINT8 maxscroll = serverlistcount-(SERVERSPERPAGE/2); + INT16 maxscroll = serverlistcount - (SERVERSPERPAGE/2) - 2; // Why? Because + if (maxscroll < 0) + maxscroll = 0; + (void) ch; if (!itemOn && menucmd[pid].dpad_ud < 0) @@ -412,21 +404,37 @@ boolean M_ServerBrowserInputs(INT32 ch) M_PrevOpt(); // go to itemOn 2 if (serverlistcount) { - UINT8 prevscroll = mpmenu.scrolln; + INT32 prevscroll = mpmenu.scrolln; - mpmenu.servernum = serverlistcount; + mpmenu.servernum = serverlistcount-1; mpmenu.scrolln = maxscroll; - mpmenu.slide = SERVERSPACE * (prevscroll - mpmenu.scrolln); + mpmenu.slide = SERVERSPACE * (prevscroll - (INT32)mpmenu.scrolln); } else { itemOn = 1; // Sike! If there are no servers, go to refresh instead. } + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + return true; // overwrite behaviour. } else if (itemOn == 2) // server browser itself... { +#ifndef SERVERLISTDEBUG + if (M_MenuConfirmPressed(pid)) + { + M_SetMenuDelay(pid); + + COM_BufAddText(va("connect node %d\n", serverlist[mpmenu.servernum].node)); + + M_PleaseWait(); + + return true; + } +#endif + // we have to manually do that here. if (M_MenuBackPressed(pid)) { @@ -436,12 +444,13 @@ boolean M_ServerBrowserInputs(INT32 ch) else if (menucmd[pid].dpad_ud > 0) // down { - if (mpmenu.servernum >= serverlistcount-1) + if ((UINT32)(mpmenu.servernum+1) >= serverlistcount) { - UINT8 prevscroll = mpmenu.scrolln; + INT32 prevscroll = mpmenu.scrolln; + mpmenu.servernum = 0; mpmenu.scrolln = 0; - mpmenu.slide = SERVERSPACE * (prevscroll - mpmenu.scrolln); + mpmenu.slide = SERVERSPACE * (prevscroll - (INT32)mpmenu.scrolln); M_NextOpt(); // Go back to the top of the real menu. } @@ -460,14 +469,13 @@ boolean M_ServerBrowserInputs(INT32 ch) } else if (menucmd[pid].dpad_ud < 0) { - if (!mpmenu.servernum) { M_PrevOpt(); } else { - if (mpmenu.servernum <= serverlistcount-(SERVERSPERPAGE/2) && mpmenu.scrolln) + if (mpmenu.servernum <= (INT16)maxscroll && mpmenu.scrolln) { mpmenu.scrolln--; mpmenu.slide -= SERVERSPACE;