From 093510618980031cb96296650c2fee955dd15793 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 27 Aug 2023 21:03:47 +0100 Subject: [PATCH 01/19] F_RunWipe: Don't draw menus on top if there's no renderer Fixes crash on dedicated --- src/f_wipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/f_wipe.c b/src/f_wipe.c index 5a1df0e96..48dfc0f60 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -454,7 +454,7 @@ void F_RunWipe(UINT8 wipemode, UINT8 wipetype, boolean drawMenu, const char *col I_OsPolling(); I_UpdateNoBlit(); - if (drawMenu) + if (drawMenu && rendermode != render_none) { #ifdef HAVE_THREADS I_lock_mutex(&k_menu_mutex); From c2148bf501f6f5decf387fb46d8f4e568e60de2c Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 27 Aug 2023 21:08:49 +0100 Subject: [PATCH 02/19] Testing #define for testing Master Server Listing by yourself, without a second IP address to host Disabled by default --- src/http-mserv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/http-mserv.c b/src/http-mserv.c index d47122cbf..368f1cdda 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -441,7 +441,12 @@ HMS_fetch_servers (msg_server_t *list, int query_id) break; #endif +//#define MSERVTESTALONE +#ifdef MSERVTESTALONE + strcpy(list[i].ip, "127.0.0.1"); // MS test without needing a second person to host +#else strlcpy(list[i].ip, address, sizeof list[i].ip); +#endif strlcpy(list[i].port, port, sizeof list[i].port); if (contact) From 170894ee7129ec7592c7b30906c37b86444919c6 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 27 Aug 2023 21:11:31 +0100 Subject: [PATCH 03/19] Update SRB2VERSION for impending release Was previously "2.0" in reference to how this was once just a major patch for the previous entry in the series. --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index e350082fc..c8b673542 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define SRB2VERSION "2.0"/* this must be the first line, for cmake !! */ +#define SRB2VERSION "1.0"/* this must be the first line, for cmake !! */ // The Modification ID; must be obtained from a Master Server Admin ( https://mb.srb2.org/showgroups.php ). // DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server. From 7fd64a4c3de36e27e38f3b19672d2bf178570cc1 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 27 Aug 2023 21:41:51 +0100 Subject: [PATCH 04/19] 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; From 000e6e273cd7d7cd1c5bc77a4eb461af16ecc0b0 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 27 Aug 2023 23:22:41 +0100 Subject: [PATCH 05/19] M_DrawServerListDebug: Produce more useful spread of test case fake servers --- src/menus/play-online-server-browser.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/menus/play-online-server-browser.c b/src/menus/play-online-server-browser.c index 80aa41038..e6db83227 100644 --- a/src/menus/play-online-server-browser.c +++ b/src/menus/play-online-server-browser.c @@ -281,20 +281,20 @@ void M_ServerListFillDebug(void) for (i = 0; i < serverlistcount; i++) { // We don't really care about the server node for this, let's just fill in the info so that we have a visual... - serverlist[i].info.numberofplayer = min(i, 8); - serverlist[i].info.maxplayer = 8; + serverlist[i].info.maxplayer = M_RandomRange(8, 16); + UINT8 val = i % 16; + serverlist[i].info.numberofplayer = min(val, serverlist[i].info.maxplayer); - serverlist[i].info.avgpwrlv = P_RandomRange(PR_UNDEFINED, 500, 1500); - serverlist[i].info.time = P_RandomRange(PR_UNDEFINED, 1, 8); // ping + serverlist[i].info.avgpwrlv = M_RandomRange(500, 1500); + serverlist[i].info.time = M_RandomRange(1, 8); // ping strcpy(serverlist[i].info.servername, va("Serv %d", i+1)); strcpy(serverlist[i].info.gametypename, i & 1 ? "Race" : "Battle"); - P_RandomRange(PR_UNDEFINED, 0, 5); // change results... - serverlist[i].info.kartvars = P_RandomRange(PR_UNDEFINED, 0, 3) & SV_SPEEDMASK; + serverlist[i].info.kartvars = M_RandomRange(0, 3) & SV_SPEEDMASK; - serverlist[i].info.modifiedgame = P_RandomRange(PR_UNDEFINED, 0, 1); + serverlist[i].info.modifiedgame = M_RandomRange(0, 1); CONS_Printf("Serv %d | %d...\n", i, serverlist[i].info.modifiedgame); } From b009ab3c23efa19499d5d9db0dc1799350e19da0 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 27 Aug 2023 23:40:58 +0100 Subject: [PATCH 06/19] "Recommended" server sorting option Sorts by reverse player count, with 0-player servers sitting empty at the far end. Breaks ties with ping instead of strcmp. --- src/cvars.cpp | 15 +++++----- src/menus/play-online-server-browser.c | 40 +++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/cvars.cpp b/src/cvars.cpp index 6f7e3e812..416ed70f9 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -540,13 +540,14 @@ consvar_t cv_server_contact = Server("server_contact", "").onchange_noinit(Updat consvar_t cv_servername = Server("servername", "Ring Racers server").onchange_noinit(Update_parameters); void M_SortServerList(void); -consvar_t cv_serversort = Server("serversort", "Ping").dont_save().onchange(M_SortServerList).values({ - {0,"Ping"}, - {1,"AVG. Power Level"}, - {2,"Most Players"}, - {3,"Least Players"}, - {4,"Max Player Slots"}, - {5,"Gametype"}, +consvar_t cv_serversort = Server("serversort", "Recommended").dont_save().onchange(M_SortServerList).values({ + {-1, "Recommended"}, + { 0, "Ping"}, + { 1, "AVG. Power Level"}, + { 2, "Most Players"}, + { 3, "Least Players"}, + { 4, "Max Player Slots"}, + { 5, "Gametype"}, }); // show your ping on the HUD next to framerate. Defaults to warning only (shows up if your ping is > maxping) diff --git a/src/menus/play-online-server-browser.c b/src/menus/play-online-server-browser.c index e6db83227..687f8e51c 100644 --- a/src/menus/play-online-server-browser.c +++ b/src/menus/play-online-server-browser.c @@ -338,13 +338,51 @@ static int ServerListEntryComparator_gametypename(const void *entry1, const void int c; if (( c = strcasecmp(sa->info.gametypename, sb->info.gametypename) )) return c; - return strcmp(sa->info.servername, sb->info.servername); \ + return strcmp(sa->info.servername, sb->info.servername); +} + +static int ServerListEntryComparator_recommended(const void *entry1, const void *entry2) +{ + const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; + + INT32 saseedval = sa->info.numberofplayer; + INT32 sbseedval = sb->info.numberofplayer; + + // Tyron wrote the following on 25072022: + // "sort should be two parts + // top part of the list is "all non-empty servers sorted by reverse playercount", with servers above a certain reported ping marked as bad connection or whatever + // bottom part of the list is all empty servers sorted by ping" + // toast is implementing on 27082023, over a year later, because + // "fixing server join flow" is saner to do near the end + + { + const UINT8 SERVER_EMPTY = 1; + + // The intent with this nudge is to show you + // good games you could get a memorable Duel in, + // with the possibility to really katamari into + // something more substantial. + // By comparison, empty games are not nearly as + // fun to get going, so let's lower their SEO. + if (!saseedval) + saseedval = MAXPLAYERS + SERVER_EMPTY; + if (!sbseedval) + sbseedval = MAXPLAYERS + SERVER_EMPTY; + } + + if (saseedval != sbseedval) + return saseedval - sbseedval; + + return sa->info.time - sb->info.time; } void M_SortServerList(void) { switch(cv_serversort.value) { + case -1: + qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_recommended); + break; case 0: // Ping. qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_time); break; From acca45d611d5c1daa872931b4e8a67e84019fe03 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 28 Aug 2023 00:02:54 +0100 Subject: [PATCH 07/19] SL_InsertServer: If we have cause to reject a server, remove it from the serverlistultimatecount immediately rather than waiting for it to time out --- src/d_clisrv.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index bebaae8f3..bb051a2ef 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1580,7 +1580,7 @@ static UINT32 SL_SearchServer(INT32 node) return UINT32_MAX; } -static void SL_InsertServer(serverinfo_pak* info, SINT8 node) +static boolean SL_InsertServer(serverinfo_pak* info, SINT8 node) { UINT32 i; @@ -1592,25 +1592,25 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node) { // not found add it if (serverlistcount >= MAXSERVERLIST) - return; // list full + return false; // list full if (info->_255 != 255) - return;/* old packet format */ + return false;/* old packet format */ if (info->packetversion != PACKETVERSION) - return;/* old new packet format */ + return false;/* old new packet format */ if (info->version != VERSION) - return; // Not same version. + return false; // Not same version. if (info->subversion != SUBVERSION) - return; // Close, but no cigar. + return false; // Close, but no cigar. if (strcmp(info->application, SRB2APPLICATION)) - return;/* that's a different mod */ + return false;/* that's a different mod */ if (info->modifiedgame != (mpmenu.room == 1)) - return;/* CORE vs MODDED! */ + return false;/* CORE vs MODDED! */ i = serverlistcount++; } @@ -1620,6 +1620,8 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node) // resort server list M_SortServerList(); + + return true; } void CL_QueryServerList (msg_server_t *server_list) @@ -4646,7 +4648,9 @@ static void HandleServerInfo(SINT8 node) memcpy(servername, netbuffer->u.serverinfo.servername, MAXSERVERNAME); CopyCaretColors(netbuffer->u.serverinfo.servername, servername, MAXSERVERNAME); - SL_InsertServer(&netbuffer->u.serverinfo, node); + // If we have cause to reject it, it's not worth observing. + if (SL_InsertServer(&netbuffer->u.serverinfo, node) == false) + serverlistultimatecount--; } static void PT_WillResendGamestate(void) From 4483f9fc0ea6911156d553014045308c77731b5f Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 28 Aug 2023 14:17:19 +0100 Subject: [PATCH 08/19] M_ServerBrowserInputs; Clean up significantly - No longer reimplement base functionality in confusing overlapping situations, only add on top of it where necessary - Fix the case where no servers were found to not allow scrolling past the bottom --- src/menus/play-online-server-browser.c | 71 +++++++++++--------------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/src/menus/play-online-server-browser.c b/src/menus/play-online-server-browser.c index 687f8e51c..68e496982 100644 --- a/src/menus/play-online-server-browser.c +++ b/src/menus/play-online-server-browser.c @@ -435,13 +435,15 @@ boolean M_ServerBrowserInputs(INT32 ch) if (maxscroll < 0) maxscroll = 0; + const INT16 serverbrowserOn = (currentMenu->numitems - 1); + (void) ch; if (!itemOn && menucmd[pid].dpad_ud < 0) { - M_PrevOpt(); // go to itemOn 2 if (serverlistcount) { + // Return the MS listing to the bottom. INT32 prevscroll = mpmenu.scrolln; mpmenu.servernum = serverlistcount-1; @@ -450,15 +452,14 @@ boolean M_ServerBrowserInputs(INT32 ch) } else { - itemOn = 1; // Sike! If there are no servers, go to refresh instead. + M_PrevOpt(); // Double apply } - - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); - - return true; // overwrite behaviour. } - else if (itemOn == 2) // server browser itself... + else if (itemOn == (serverbrowserOn - 1) && menucmd[pid].dpad_ud > 0 && !serverlistcount) + { + M_NextOpt(); // Double apply + } + else if (itemOn == serverbrowserOn) // server browser itself... { #ifndef SERVERLISTDEBUG if (M_MenuConfirmPressed(pid)) @@ -473,59 +474,49 @@ boolean M_ServerBrowserInputs(INT32 ch) } #endif - // we have to manually do that here. - if (M_MenuBackPressed(pid)) + if (menucmd[pid].dpad_ud > 0) // down { - M_GoBack(0); - M_SetMenuDelay(pid); - } - - else if (menucmd[pid].dpad_ud > 0) // down - { - if ((UINT32)(mpmenu.servernum+1) >= serverlistcount) - { - INT32 prevscroll = mpmenu.scrolln; - - mpmenu.servernum = 0; - mpmenu.scrolln = 0; - mpmenu.slide = SERVERSPACE * (prevscroll - (INT32)mpmenu.scrolln); - - M_NextOpt(); // Go back to the top of the real menu. - } - else + if ((UINT32)(mpmenu.servernum+1) < serverlistcount) { + // Listing scroll down mpmenu.servernum++; if (mpmenu.scrolln < maxscroll && mpmenu.servernum > SERVERSPERPAGE/2) { mpmenu.scrolln++; mpmenu.slide += SERVERSPACE; } - } - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + + return true; + } + + // Return the MS listing to the top. + INT32 prevscroll = mpmenu.scrolln; + + mpmenu.servernum = 0; + mpmenu.scrolln = 0; + mpmenu.slide = SERVERSPACE * (prevscroll - (INT32)mpmenu.scrolln); } else if (menucmd[pid].dpad_ud < 0) { - if (!mpmenu.servernum) - { - M_PrevOpt(); - } - else + if (mpmenu.servernum) { + // Listing scroll up if (mpmenu.servernum <= (INT16)maxscroll && mpmenu.scrolln) { mpmenu.scrolln--; mpmenu.slide -= SERVERSPACE; } - mpmenu.servernum--; - } - S_StartSound(NULL, sfx_s3k5b); - M_SetMenuDelay(pid); + S_StartSound(NULL, sfx_s3k5b); + M_SetMenuDelay(pid); + + return true; + } } - return true; // Overwrite behaviour. } return false; // use normal behaviour. } From 9d689c5e0c327c4cc9d1ed3a5820e9f762b74958 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 28 Aug 2023 16:32:42 +0100 Subject: [PATCH 09/19] M_DrawServerCountAndHorizontalBar: Improve general overlaid text --- src/k_menudraw.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 78b96ee87..bc0233f1d 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -3419,11 +3419,11 @@ static void M_DrawServerCountAndHorizontalBar(void) switch (M_GetWaitingMode()) { case M_WAITING_VERSION: - text = "Checking for updates"; + text = "Checking for updates..."; break; case M_WAITING_SERVERS: - text = "Loading server list"; + text = "Loading server list..."; break; default: @@ -3438,17 +3438,10 @@ static void M_DrawServerCountAndHorizontalBar(void) else { throbindex = UINT8_MAX; // No throbber! - if (serverlistcount > 0) - { - text = va("%d server%s found", - serverlistcount, - serverlistcount == 1 ? "" : "s" - ); - } - else - { - text = "No servers found"; - } + text = va("%d server%s found", + serverlistcount, + serverlistcount == 1 ? "" : "s" + ); } } @@ -3480,15 +3473,15 @@ static void M_DrawServerCountAndHorizontalBar(void) INT32 mservflags = 0; if (CV_IsSetToDefault(&cv_masterserver)) - mservflags = highlightflags|V_30TRANS; + mservflags = highlightflags; 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)); + V_DrawFadeFill(0, y-1, BASEVIDWIDTH, 10+1, 0, 31, 5); + V_DrawCenteredThinString(BASEVIDWIDTH/2, y, + mservflags, va("List from \"%s\"", cv_masterserver.string)); } void M_DrawMPServerBrowser(void) From 47055bcda7bf8da326969299fec8c99cd250c778 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 28 Aug 2023 20:13:17 +0100 Subject: [PATCH 10/19] M_StartMessage: ACTUALLY use automatic newline generation --- src/menus/transient/message-box.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/menus/transient/message-box.c b/src/menus/transient/message-box.c index f69b3ebfe..72bc50731 100644 --- a/src/menus/transient/message-box.c +++ b/src/menus/transient/message-box.c @@ -31,19 +31,20 @@ static inline size_t M_StringHeight(const char *string) void M_StartMessage(const char *header, const char *string, void (*routine)(INT32), menumessagetype_t itemtype, const char *confirmstr, const char *defaultstr) { const UINT8 pid = 0; - static char *message = NULL; - Z_Free(message); DEBFILE(string); - message = V_ScaledWordWrap( - BASEVIDWIDTH << FRACBITS, + char *message = V_ScaledWordWrap( + (BASEVIDWIDTH - 8) << FRACBITS, FRACUNIT, FRACUNIT, FRACUNIT, 0, HU_FONT, string ); - strncpy(menumessage.message, string, MAXMENUMESSAGE); + strncpy(menumessage.message, message, MAXMENUMESSAGE); + + Z_Free(message); + menumessage.header = header; menumessage.flags = itemtype; menumessage.routine = routine; @@ -84,7 +85,7 @@ void M_StartMessage(const char *header, const char *string, void (*routine)(INT3 // oogh my god this was replaced in 2023 menumessage.x = (8 * MAXSTRINGLENGTH) - 1; - menumessage.y = M_StringHeight(message); + menumessage.y = M_StringHeight(menumessage.message); M_SetMenuDelay(pid); // Set menu delay to avoid setting off any of the handlers. } From afb7328aa4e3b48c3663e8c680dd70f706408c14 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 28 Aug 2023 20:16:12 +0100 Subject: [PATCH 11/19] SV_SpawnServer: Register netgame-advertised servers with the MS This is done in a different location in the previous entry in the series, but the author of this commit couldn't find it. Since we're using the 2.2 codebase, it's been put where they have it instead. --- src/d_clisrv.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index bb051a2ef..3fc62490e 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4226,6 +4226,11 @@ boolean SV_SpawnServer(void) I_NetOpenSocket(); } + if (cv_advertise.value) + { + RegisterServer(); + } + ourIP = 0; STUN_bind(GotOurIP); } From 5b958f5a0ce7b7455ed83636624b2c70e7335256 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 28 Aug 2023 20:41:01 +0100 Subject: [PATCH 12/19] http-mserv.c: Update documentation URL to newest version --- src/http-mserv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http-mserv.c b/src/http-mserv.c index 368f1cdda..ddb47ad03 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -11,7 +11,7 @@ /* Documentation available here. - + */ #ifdef HAVE_CURL From 782d98fb0972c4be49fd4ac7955cc42e05179283 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 28 Aug 2023 22:07:56 +0100 Subject: [PATCH 13/19] Master Server Listing rules prompts Ported from KartKrew/Kart-Public!286 Unlike the previous entry in the series, this actually defers outbound rules checks for either selecting "Host Game" on the menu, or starting a server via the console/command line parameters. Only attempting to host a non-advertised game via the menu will have sent out an unnecessary rules request to the MS! --- src/http-mserv.c | 29 +++++++++++ src/k_menu.h | 1 + src/menus/play-online-host.c | 32 +++++++++++- src/mserv.c | 98 +++++++++++++++++++++++++++++++++++- src/mserv.h | 5 ++ 5 files changed, 162 insertions(+), 3 deletions(-) diff --git a/src/http-mserv.c b/src/http-mserv.c index ddb47ad03..46ab9cd42 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -516,6 +516,35 @@ HMS_compare_mod_version (char *buffer, size_t buffer_size) return ok; } +const char * +HMS_fetch_rules (char *buffer, size_t buffer_size) +{ + struct HMS_buffer *hms; + + hms = HMS_connect("rules"); + + if (! hms) + return NULL; + + if (HMS_do(hms)) + { + char *p = strstr(hms->buffer, "\n\n"); + + if (p) + { + p[1] = '\0'; + + strlcpy(buffer, hms->buffer, buffer_size); + } + else + buffer = NULL; + } + + HMS_end(hms); + + return buffer; +} + static char * Strip_trailing_slashes (char *api) { diff --git a/src/k_menu.h b/src/k_menu.h index cd740df55..6360896ae 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -841,6 +841,7 @@ extern struct mpmenu_s { } mpmenu; void M_PleaseWait(void); +void M_PopupMasterServerRules(void); // Time Attack void M_PrepareTimeAttack(INT32 choice); diff --git a/src/menus/play-online-host.c b/src/menus/play-online-host.c index a7061a32a..0b34f36b1 100644 --- a/src/menus/play-online-host.c +++ b/src/menus/play-online-host.c @@ -3,6 +3,8 @@ #include "../k_menu.h" #include "../s_sound.h" +#include "../z_zone.h" +#include "../mserv.h" // MULTIPLAYER HOST SCREEN -- see mhost_e menuitem_t PLAY_MP_Host[] = @@ -43,13 +45,41 @@ menu_t PLAY_MP_HostDef = { NULL }; +void M_PopupMasterServerRules(void) +{ +#ifdef MASTERSERVER + if (cv_advertise.value && (serverrunning || currentMenu == &PLAY_MP_HostDef)) + { + char *rules = GetMasterServerRules(); + + if (rules != NULL) + { + M_StartMessage("Server List Rules", rules, NULL, MM_NOTHING, NULL, NULL); + Z_Free(rules); + } + } +#endif +} + void M_MPHostInit(INT32 choice) { - (void)choice; mpmenu.modewinextend[0][0] = 1; M_SetupNextMenu(&PLAY_MP_HostDef, true); itemOn = mhost_go; + + Get_rules(); + // There's one downside to doing it this way: + // if you turn advertise on via the console, + // then access this menu for the first time, + // no rules will pop up because they haven't + // arrived yet. + M_PopupMasterServerRules(); + // HOWEVER, this menu popup isn't for people + // who know how to use the Developer Console. + // People who CAN do that should already know + // what kind of service they're connecting to. + // (it'll still appear in the logs later, too!) } void M_HandleHostMenuGametype(INT32 choice) diff --git a/src/mserv.c b/src/mserv.c index e1f2b9820..2f851d3e8 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -17,6 +17,7 @@ #include "doomstat.h" #include "doomdef.h" +#include "console.h" // con_startup #include "command.h" #include "i_threads.h" #include "mserv.h" @@ -40,6 +41,8 @@ static boolean MSUpdateAgain; static time_t MSLastPing; +static char *MSRules; + #ifdef HAVE_THREADS static I_mutex MSMutex; static I_cond MSCond; @@ -157,6 +160,43 @@ static void Command_Listserv_f(void) } } +static boolean firstmsrules = false; + +static void +Get_masterserver_rules (boolean checkfirst) +{ + char rules[256]; + + if (checkfirst) + { + boolean MSRulesExist; + + Lock_state(); + MSRulesExist = (MSRules != NULL); + Unlock_state(); + + if (MSRulesExist) + return; + } + + if (HMS_fetch_rules(rules, sizeof rules)) + { + Lock_state(); + Z_Free(MSRules); + MSRules = Z_StrDup(rules); + + if (MSRegistered == true) + { + CONS_Printf("\n"); + CONS_Alert(CONS_NOTICE, "%s\n", rules); + } + + firstmsrules = true; + + Unlock_state(); + } +} + static void Finish_registration (void) { @@ -175,6 +215,17 @@ Finish_registration (void) } Unlock_state(); + char *rules = GetMasterServerRules(); + if (rules == NULL) + { + Get_masterserver_rules(true); + } + else + { + CONS_Printf("\n"); + CONS_Alert(CONS_NOTICE, "%s\n", rules); + } + if (registered) CONS_Printf("Master server registration successful.\n"); } @@ -257,6 +308,15 @@ Finish_unlist (void) } } +static void +Finish_masterserver_change (char *api) +{ + HMS_set_api(api); + + if (!con_startup) + Get_masterserver_rules(false); +} + #ifdef HAVE_THREADS static int * Server_id (void) @@ -350,7 +410,14 @@ Change_masterserver_thread (char *api) } Unlock_state(); - HMS_set_api(api); + Finish_masterserver_change(api); +} + +static void +Get_masterserver_rules_thread (void) +{ + // THIS FUNC has its own lock check in it + Get_masterserver_rules(true); } #endif/*HAVE_THREADS*/ @@ -397,6 +464,17 @@ void UnregisterServer(void) #endif/*MASTERSERVER*/ } +char *GetMasterServerRules(void) +{ + char *rules; + + Lock_state(); + rules = MSRules ? Z_StrDup(MSRules) : NULL; + Unlock_state(); + + return rules; +} + static boolean Online (void) { @@ -447,7 +525,21 @@ Set_api (const char *api) strdup(api) ); #else - HMS_set_api(strdup(api)); + Finish_masterserver_change(strdup(api)); +#endif +} + +void +Get_rules (void) +{ +#ifdef HAVE_THREADS + I_spawn_thread( + "get-masterserver-rules", + (I_thread_fn)Get_masterserver_rules_thread, + NULL + ); +#else + Get_masterserver_rules(true); #endif } @@ -521,6 +613,8 @@ void Advertise_OnChange(void) #ifdef HAVE_DISCORDRPC DRPC_UpdatePresence(); #endif + + M_PopupMasterServerRules(); } #ifdef DEVELOP diff --git a/src/mserv.h b/src/mserv.h index 7417585d6..dd9a548fd 100644 --- a/src/mserv.h +++ b/src/mserv.h @@ -77,6 +77,8 @@ extern I_mutex ms_ServerList_mutex; void RegisterServer(void); void UnregisterServer(void); +void Get_rules(void); + void MasterClient_Ticker(void); msg_server_t *GetShortServersList(int id); @@ -84,6 +86,8 @@ msg_server_t *GetShortServersList(int id); char *GetMODVersion(int id); #endif +char *GetMasterServerRules(void); + void AddMServCommands(void); /* HTTP */ @@ -94,6 +98,7 @@ int HMS_update (void); void HMS_list_servers (void); msg_server_t * HMS_fetch_servers (msg_server_t *list, int id); int HMS_compare_mod_version (char *buffer, size_t size_of_buffer); +const char * HMS_fetch_rules (char *buffer, size_t size_of_buffer); #ifdef __cplusplus } // extern "C" From 339d368d7dd82feeb182ccda26f504efb577762b Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 28 Aug 2023 23:33:39 +0100 Subject: [PATCH 14/19] HMS_fetch_rules: Return NULL if the curl connection failed, instead of producing garbled rules --- src/http-mserv.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/http-mserv.c b/src/http-mserv.c index 46ab9cd42..7794a8f7c 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -526,7 +526,9 @@ HMS_fetch_rules (char *buffer, size_t buffer_size) if (! hms) return NULL; - if (HMS_do(hms)) + boolean ok = HMS_do(hms); + + if (ok) { char *p = strstr(hms->buffer, "\n\n"); @@ -542,6 +544,9 @@ HMS_fetch_rules (char *buffer, size_t buffer_size) HMS_end(hms); + if (!ok) + return NULL; + return buffer; } From c14ff69d9a6ce316a5bc35575656ece4570a023d Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 28 Aug 2023 23:38:00 +0100 Subject: [PATCH 15/19] Server Browser change alert (KartKrew/Kart-Public!277) - Let players know if their cv_masterserver was changed, and give them the opportunity to change it back - A limited number of nag attempts, so if people are using a legitimate custom Server Browser they won't be annoyed for the rest of the game's lifespan - Show the Server Browser at the bottom of all online menus - KNOWN BUG: currently overlaps with the Join IP - we're redoing this menu before launch because it's buggy so this is just another bug on that pile --- src/cvars.cpp | 1 + src/k_menudraw.c | 33 +++++++++++--------- src/menus/play-online-1.c | 66 +++++++++++++++++++++++++++++++++++++-- src/mserv.h | 1 + 4 files changed, 85 insertions(+), 16 deletions(-) diff --git a/src/cvars.cpp b/src/cvars.cpp index 416ed70f9..e1dbbc8af 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -502,6 +502,7 @@ consvar_t cv_kicktime = Server("kicktime", "20").values(CV_Unsigned); void MasterServer_OnChange(void); consvar_t cv_masterserver = Server("masterserver", "https://ms.kartkrew.org/ms/api").onchange(MasterServer_OnChange); +consvar_t cv_masterserver_nagattempts = Server("masterserver_nagattempts", "5").values(CV_Unsigned); void MasterServer_Debug_OnChange (void); consvar_t cv_masterserver_debug = Server("masterserver_debug", "Off").on_off().onchange(MasterServer_Debug_OnChange); diff --git a/src/k_menudraw.c b/src/k_menudraw.c index bc0233f1d..8fef30a7b 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -3086,6 +3086,23 @@ void M_DrawTimeAttack(void) // NOTE: This is pretty rigid and only intended for use with the multiplayer options menu which has *3* choices. +static void M_DrawMasterServerReminder(void) +{ + // Did you change the Server Browser address? Have a little reminder. + + INT32 mservflags = 0; + if (CV_IsSetToDefault(&cv_masterserver)) + mservflags = highlightflags; + else + mservflags = warningflags; + + INT32 y = BASEVIDHEIGHT - 24; + + V_DrawFadeFill(0, y-1, BASEVIDWIDTH, 10+1, 0, 31, 5); + V_DrawCenteredThinString(BASEVIDWIDTH/2, y, + mservflags, va("List via \"%s\"", cv_masterserver.string)); +} + static void M_MPOptDrawer(menu_t *m, INT16 extend[3][3]) { // This is a copypaste of the generic gamemode menu code with a few changes. @@ -3149,6 +3166,7 @@ void M_DrawMPOptSelect(void) M_DrawEggaChannel(); M_DrawMenuTooltips(); M_MPOptDrawer(&PLAY_MP_OptSelectDef, mpmenu.modewinextend); + M_DrawMasterServerReminder(); } // Multiplayer mode option select: HOST GAME! @@ -3468,20 +3486,6 @@ static void M_DrawServerCountAndHorizontalBar(void) 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; - else - mservflags = warningflags; - - y = BASEVIDHEIGHT - 24; - - V_DrawFadeFill(0, y-1, BASEVIDWIDTH, 10+1, 0, 31, 5); - V_DrawCenteredThinString(BASEVIDWIDTH/2, y, - mservflags, va("List from \"%s\"", cv_masterserver.string)); } void M_DrawMPServerBrowser(void) @@ -3586,6 +3590,7 @@ void M_DrawMPServerBrowser(void) // And finally, the overlay bar! M_DrawServerCountAndHorizontalBar(); + M_DrawMasterServerReminder(); } // OPTIONS MENU diff --git a/src/menus/play-online-1.c b/src/menus/play-online-1.c index 7f9a9c294..e58490187 100644 --- a/src/menus/play-online-1.c +++ b/src/menus/play-online-1.c @@ -4,6 +4,7 @@ #include "../k_menu.h" #include "../m_cond.h" #include "../s_sound.h" +#include "../mserv.h" // cv_masterserver #if defined (TESTERS) #define IT_STRING_CALL_NOTESTERS IT_DISABLED @@ -11,13 +12,74 @@ #define IT_STRING_CALL_NOTESTERS (IT_STRING | IT_CALL) #endif // TESTERS +static boolean firstDismissedNagThisBoot = true; + +static void M_HandleMasterServerResetChoice(INT32 ch) +{ + if (ch == MA_YES) + { + CV_Set(&cv_masterserver, cv_masterserver.defaultvalue); + CV_Set(&cv_masterserver_nagattempts, cv_masterserver_nagattempts.defaultvalue); + S_StartSound(NULL, sfx_s221); + } + else + { + if (firstDismissedNagThisBoot) + { + if (cv_masterserver_nagattempts.value > 0) + { + CV_SetValue(&cv_masterserver_nagattempts, cv_masterserver_nagattempts.value - 1); + } + firstDismissedNagThisBoot = false; + } + } +} + +static void M_PreMPHostInitChoice(INT32 ch) +{ + M_HandleMasterServerResetChoice(ch); + M_MPHostInit(0); +} + +static void M_PreMPHostInit(INT32 choice) +{ + (void)choice; + + if (!CV_IsSetToDefault(&cv_masterserver) && cv_masterserver_nagattempts.value > 0) + { + M_StartMessage("Server Browser Alert", M_GetText("Hey! You've changed the game's\naddress for the Server Browser.\n\nYou won't be able to host games on\nthe official Server Browser.\n\nUnless you're from the future, this\nprobably isn't what you want.\n"), &M_PreMPHostInitChoice, MM_YESNO, "Fix and continue", "I changed the URL intentionally"); + return; + } + + M_MPHostInit(0); +} + +static void M_PreMPRoomSelectInitChoice(INT32 ch) +{ + M_HandleMasterServerResetChoice(ch); + M_MPRoomSelectInit(0); +} + +static void M_PreMPRoomSelectInit(INT32 choice) +{ + (void)choice; + + if (!CV_IsSetToDefault(&cv_masterserver) && cv_masterserver_nagattempts.value > 0) + { + M_StartMessage("Server Browser Alert", M_GetText("Hey! You've changed the game's\naddress for the Server Browser.\n\nYou won't be able to see games from\nthe official Server Browser.\n\nUnless you're from the future, this\nprobably isn't what you want.\n"), &M_PreMPRoomSelectInitChoice, MM_YESNO, "Fix and continue", "I changed the URL intentionally"); + return; + } + + M_MPRoomSelectInit(0); +} + menuitem_t PLAY_MP_OptSelect[] = { {IT_STRING_CALL_NOTESTERS, "Host Game", "Start your own online game!", - NULL, {.routine = M_MPHostInit}, 0, 0}, + NULL, {.routine = M_PreMPHostInit}, 0, 0}, {IT_STRING_CALL_NOTESTERS, "Server Browser", "Search for game servers to play in.", - NULL, {.routine = M_MPRoomSelectInit}, 0, 0}, + NULL, {.routine = M_PreMPRoomSelectInit}, 0, 0}, {IT_STRING | IT_CALL, "Join by IP", "Join an online game by its IP address.", NULL, {.routine = M_MPJoinIPInit}, 0, 0}, diff --git a/src/mserv.h b/src/mserv.h index dd9a548fd..6fe9a77c4 100644 --- a/src/mserv.h +++ b/src/mserv.h @@ -57,6 +57,7 @@ struct msg_ban_t // ================================ GLOBALS =============================== extern consvar_t cv_masterserver, cv_servername; +extern consvar_t cv_masterserver_nagattempts; extern consvar_t cv_server_contact; extern consvar_t cv_masterserver_update_rate; extern consvar_t cv_masterserver_timeout; From cdf5eaaa16d425cd2543563db6f0889c3ae4bc97 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 28 Aug 2023 23:44:37 +0100 Subject: [PATCH 16/19] Server Browser Room Select changes Instead of putting you on the room select but forbidding changing the room... - You haven't unlocked add-ons (formerly forced to CORE) - Skips the Room Select and takes you directly to the CORE mode Server Browser - Game has add-ons loaded (formerly forced to MODDED) - Forbid accessing the Server Browser with a helpful message. - Reduces tech support burden. - Parity with the previous entry in the series. --- src/k_menu.h | 1 - src/k_menudraw.c | 8 ++++---- src/menus/play-online-room-select.c | 21 ++++++++++++++++++--- src/menus/play-online-server-browser.c | 1 + 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/k_menu.h b/src/k_menu.h index 6360896ae..ea894fd3e 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -829,7 +829,6 @@ extern struct mpmenu_s { // See M_OptSelectTick, it'll make more sense there. Sorry if this is a bit of a mess! UINT8 room; - boolean roomforced; tic_t ticker; UINT8 servernum; diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 8fef30a7b..7a1f883b7 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -3418,11 +3418,11 @@ void M_DrawMPRoomSelect(void) // Draw buttons: - if (!mpmenu.roomforced || mpmenu.room == 0) - V_DrawFixedPatch(160< Date: Mon, 28 Aug 2023 23:55:54 +0100 Subject: [PATCH 17/19] Room Select: Add a tooltip --- src/k_menudraw.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 7a1f883b7..acbfd41df 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -3422,6 +3422,9 @@ void M_DrawMPRoomSelect(void) V_DrawFixedPatch(160< Date: Tue, 29 Aug 2023 00:35:59 +0100 Subject: [PATCH 18/19] Server sort: Tiebreaker for all methods is Ping, except for Ping only, which is still strcmp Reduces the toxicity of "userlist-bumping", the phenomena where you pick a name that begins as early in ASCII as possible for clout. Now that only continues to apply to the sort that is already just a little toxic. --- src/menus/play-online-server-browser.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/menus/play-online-server-browser.c b/src/menus/play-online-server-browser.c index 2c6a3def4..29c2e4379 100644 --- a/src/menus/play-online-server-browser.c +++ b/src/menus/play-online-server-browser.c @@ -313,7 +313,7 @@ static int ServerListEntryComparator_##key(const void *entry1, const void *entry const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \ if (sa->info.key != sb->info.key) \ return sa->info.key - sb->info.key; \ - return strcmp(sa->info.servername, sb->info.servername); \ + return sa->info.time - sb->info.time; \ } // This does descending instead of ascending. @@ -323,15 +323,22 @@ static int ServerListEntryComparator_##key##_reverse(const void *entry1, const v const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \ if (sb->info.key != sa->info.key) \ return sb->info.key - sa->info.key; \ - return strcmp(sb->info.servername, sa->info.servername); \ + return sa->info.time - sb->info.time; \ } -SERVER_LIST_ENTRY_COMPARATOR(time) +//SERVER_LIST_ENTRY_COMPARATOR(time) -- done seperately due to the usual tiebreaker being time SERVER_LIST_ENTRY_COMPARATOR(numberofplayer) SERVER_LIST_ENTRY_COMPARATOR_REVERSE(numberofplayer) SERVER_LIST_ENTRY_COMPARATOR_REVERSE(maxplayer) SERVER_LIST_ENTRY_COMPARATOR(avgpwrlv) +static int ServerListEntryComparator_time(const void *entry1, const void *entry2) +{ + const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; + if (sa->info.time != sb->info.time) + return sa->info.time - sb->info.time; + return strcmp(sa->info.servername, sb->info.servername); +} static int ServerListEntryComparator_gametypename(const void *entry1, const void *entry2) { @@ -339,7 +346,7 @@ static int ServerListEntryComparator_gametypename(const void *entry1, const void int c; if (( c = strcasecmp(sa->info.gametypename, sb->info.gametypename) )) return c; - return strcmp(sa->info.servername, sb->info.servername); + return sa->info.time - sb->info.time; } static int ServerListEntryComparator_recommended(const void *entry1, const void *entry2) From 244db81f04c767abd9fb964784fa190a5334a340 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 31 Aug 2023 20:50:15 +0100 Subject: [PATCH 19/19] Visual adjustments to the Server Browser and Room Select Based on VC discussions - When you've unlocked add-ons, show "Core Servers" or "Modded Servers" in lieu of "Server Browser - Adjust the vertical height of the Room Select graphics to not be visually overlapped --- src/k_menudraw.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index acbfd41df..6e6e5864a 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -3418,9 +3418,9 @@ void M_DrawMPRoomSelect(void) // Draw buttons: - V_DrawFixedPatch(160<