Merge branch 'mserv-servitude' into 'master'

MServ Servitude

See merge request KartKrew/Kart!1438
This commit is contained in:
Oni 2023-09-01 05:35:57 +00:00
commit aa5446cf40
16 changed files with 602 additions and 165 deletions

View file

@ -502,6 +502,7 @@ consvar_t cv_kicktime = Server("kicktime", "20").values(CV_Unsigned);
void MasterServer_OnChange(void); void MasterServer_OnChange(void);
consvar_t cv_masterserver = Server("masterserver", "https://ms.kartkrew.org/ms/api").onchange(MasterServer_OnChange); 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); void MasterServer_Debug_OnChange (void);
consvar_t cv_masterserver_debug = Server("masterserver_debug", "Off").on_off().onchange(MasterServer_Debug_OnChange); consvar_t cv_masterserver_debug = Server("masterserver_debug", "Off").on_off().onchange(MasterServer_Debug_OnChange);
@ -540,13 +541,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); consvar_t cv_servername = Server("servername", "Ring Racers server").onchange_noinit(Update_parameters);
void M_SortServerList(void); void M_SortServerList(void);
consvar_t cv_serversort = Server("serversort", "Ping").dont_save().onchange(M_SortServerList).values({ consvar_t cv_serversort = Server("serversort", "Recommended").dont_save().onchange(M_SortServerList).values({
{0,"Ping"}, {-1, "Recommended"},
{1,"AVG. Power Level"}, { 0, "Ping"},
{2,"Most Players"}, { 1, "AVG. Power Level"},
{3,"Least Players"}, { 2, "Most Players"},
{4,"Max Player Slots"}, { 3, "Least Players"},
{5,"Gametype"}, { 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) // show your ping on the HUD next to framerate. Defaults to warning only (shows up if your ping is > maxping)

View file

@ -1550,6 +1550,10 @@ static void SendAskInfo(INT32 node)
serverelem_t serverlist[MAXSERVERLIST]; serverelem_t serverlist[MAXSERVERLIST];
UINT32 serverlistcount = 0; UINT32 serverlistcount = 0;
UINT32 serverlistultimatecount = 0;
static boolean resendserverlistnode[MAXNETNODES];
static tic_t serverlistepoch;
static void SL_ClearServerList(INT32 connectedserver) static void SL_ClearServerList(INT32 connectedserver)
{ {
@ -1562,6 +1566,8 @@ static void SL_ClearServerList(INT32 connectedserver)
serverlist[i].node = 0; serverlist[i].node = 0;
} }
serverlistcount = 0; serverlistcount = 0;
memset(resendserverlistnode, 0, sizeof resendserverlistnode);
} }
static UINT32 SL_SearchServer(INT32 node) static UINT32 SL_SearchServer(INT32 node)
@ -1574,32 +1580,37 @@ static UINT32 SL_SearchServer(INT32 node)
return UINT32_MAX; return UINT32_MAX;
} }
static void SL_InsertServer(serverinfo_pak* info, SINT8 node) static boolean SL_InsertServer(serverinfo_pak* info, SINT8 node)
{ {
UINT32 i; UINT32 i;
resendserverlistnode[node] = false;
// search if not already on it // search if not already on it
i = SL_SearchServer(node); i = SL_SearchServer(node);
if (i == UINT32_MAX) if (i == UINT32_MAX)
{ {
// not found add it // not found add it
if (serverlistcount >= MAXSERVERLIST) if (serverlistcount >= MAXSERVERLIST)
return; // list full return false; // list full
if (info->_255 != 255) if (info->_255 != 255)
return;/* old packet format */ return false;/* old packet format */
if (info->packetversion != PACKETVERSION) if (info->packetversion != PACKETVERSION)
return;/* old new packet format */ return false;/* old new packet format */
if (info->version != VERSION) if (info->version != VERSION)
return; // Not same version. return false; // Not same version.
if (info->subversion != SUBVERSION) if (info->subversion != SUBVERSION)
return; // Close, but no cigar. return false; // Close, but no cigar.
if (strcmp(info->application, SRB2APPLICATION)) 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 false;/* CORE vs MODDED! */
i = serverlistcount++; i = serverlistcount++;
} }
@ -1609,6 +1620,8 @@ static void SL_InsertServer(serverinfo_pak* info, SINT8 node)
// resort server list // resort server list
M_SortServerList(); M_SortServerList();
return true;
} }
void CL_QueryServerList (msg_server_t *server_list) void CL_QueryServerList (msg_server_t *server_list)
@ -1617,6 +1630,8 @@ void CL_QueryServerList (msg_server_t *server_list)
CL_UpdateServerList(); CL_UpdateServerList();
serverlistepoch = I_GetTime();
for (i = 0; server_list[i].header.buffer[0]; i++) for (i = 0; server_list[i].header.buffer[0]; i++)
{ {
// Make sure MS version matches our own, to // Make sure MS version matches our own, to
@ -1629,19 +1644,43 @@ void CL_QueryServerList (msg_server_t *server_list)
if (node == -1) if (node == -1)
break; // no more node free break; // no more node free
SendAskInfo(node); SendAskInfo(node);
// Force close the connection so that servers can't eat
// up nodes forever if we never get a reply back from them resendserverlistnode[node] = true;
// (usually when they've not forwarded their ports). // Leave this node open. It'll be closed if the
// // request times out (CL_TimeoutServerList).
// 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 serverlistultimatecount = i;
// 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) #define SERVERLISTRESENDRATE NEWTICRATE
// -- Monster Iestyn 12/11/18
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); Net_CloseConnection(node|FORCECLOSE);
else
SendAskInfo(node);
}
}
if (timedout)
serverlistultimatecount = serverlistcount;
} }
} }
} }
@ -4187,6 +4226,11 @@ boolean SV_SpawnServer(void)
I_NetOpenSocket(); I_NetOpenSocket();
} }
if (cv_advertise.value)
{
RegisterServer();
}
ourIP = 0; ourIP = 0;
STUN_bind(GotOurIP); STUN_bind(GotOurIP);
} }
@ -4609,7 +4653,9 @@ static void HandleServerInfo(SINT8 node)
memcpy(servername, netbuffer->u.serverinfo.servername, MAXSERVERNAME); memcpy(servername, netbuffer->u.serverinfo.servername, MAXSERVERNAME);
CopyCaretColors(netbuffer->u.serverinfo.servername, 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) static void PT_WillResendGamestate(void)

View file

@ -460,7 +460,7 @@ struct serverelem_t
}; };
extern serverelem_t serverlist[MAXSERVERLIST]; extern serverelem_t serverlist[MAXSERVERLIST];
extern UINT32 serverlistcount; extern UINT32 serverlistcount, serverlistultimatecount;
extern INT32 mapchangepending; extern INT32 mapchangepending;
// Points inside doomcom // Points inside doomcom
@ -595,6 +595,7 @@ void CL_ClearPlayer(INT32 playernum);
void CL_RemovePlayer(INT32 playernum, kickreason_t reason); void CL_RemovePlayer(INT32 playernum, kickreason_t reason);
void CL_QueryServerList(msg_server_t *list); void CL_QueryServerList(msg_server_t *list);
void CL_UpdateServerList(void); void CL_UpdateServerList(void);
void CL_TimeoutServerList(void);
// Is there a game running // Is there a game running
boolean Playing(void); boolean Playing(void);

View file

@ -454,7 +454,7 @@ void F_RunWipe(UINT8 wipemode, UINT8 wipetype, boolean drawMenu, const char *col
I_OsPolling(); I_OsPolling();
I_UpdateNoBlit(); I_UpdateNoBlit();
if (drawMenu) if (drawMenu && rendermode != render_none)
{ {
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
I_lock_mutex(&k_menu_mutex); I_lock_mutex(&k_menu_mutex);

View file

@ -11,7 +11,7 @@
/* /*
Documentation available here. Documentation available here.
<https://ms.kartkrew.org/tools/api/2/> <https://ms.kartkrew.org/tools/api/2.2/>
*/ */
#ifdef HAVE_CURL #ifdef HAVE_CURL
@ -441,7 +441,12 @@ HMS_fetch_servers (msg_server_t *list, int query_id)
break; break;
#endif #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); strlcpy(list[i].ip, address, sizeof list[i].ip);
#endif
strlcpy(list[i].port, port, sizeof list[i].port); strlcpy(list[i].port, port, sizeof list[i].port);
if (contact) if (contact)
@ -511,6 +516,40 @@ HMS_compare_mod_version (char *buffer, size_t buffer_size)
return ok; 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;
boolean ok = HMS_do(hms);
if (ok)
{
char *p = strstr(hms->buffer, "\n\n");
if (p)
{
p[1] = '\0';
strlcpy(buffer, hms->buffer, buffer_size);
}
else
buffer = NULL;
}
HMS_end(hms);
if (!ok)
return NULL;
return buffer;
}
static char * static char *
Strip_trailing_slashes (char *api) Strip_trailing_slashes (char *api)
{ {

View file

@ -29,8 +29,6 @@
extern "C" { extern "C" {
#endif #endif
#define SERVERLISTDEBUG
// flags for items in the menu // flags for items in the menu
// menu handle (what we do when key is pressed // menu handle (what we do when key is pressed
#define IT_TYPE 14 // (2+4+8) #define IT_TYPE 14 // (2+4+8)
@ -831,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! // See M_OptSelectTick, it'll make more sense there. Sorry if this is a bit of a mess!
UINT8 room; UINT8 room;
boolean roomforced;
tic_t ticker; tic_t ticker;
UINT8 servernum; UINT8 servernum;
@ -842,6 +839,9 @@ extern struct mpmenu_s {
} mpmenu; } mpmenu;
void M_PleaseWait(void);
void M_PopupMasterServerRules(void);
// Time Attack // Time Attack
void M_PrepareTimeAttack(INT32 choice); void M_PrepareTimeAttack(INT32 choice);
void M_StartTimeAttack(INT32 choice); void M_StartTimeAttack(INT32 choice);
@ -895,11 +895,6 @@ void Fetch_servers_thread (int *id);
void M_RefreshServers(INT32 choice); void M_RefreshServers(INT32 choice);
void M_ServersMenu(INT32 choice); void M_ServersMenu(INT32 choice);
// for debugging purposes...
#ifdef SERVERLISTDEBUG
void M_ServerListFillDebug(void);
#endif
// Options menu: // Options menu:
// mode descriptions for video mode menu // mode descriptions for video mode menu

View file

@ -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. // 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]) 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. // 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_DrawEggaChannel();
M_DrawMenuTooltips(); M_DrawMenuTooltips();
M_MPOptDrawer(&PLAY_MP_OptSelectDef, mpmenu.modewinextend); M_MPOptDrawer(&PLAY_MP_OptSelectDef, mpmenu.modewinextend);
M_DrawMasterServerReminder();
} }
// Multiplayer mode option select: HOST GAME! // Multiplayer mode option select: HOST GAME!
@ -3400,14 +3418,79 @@ void M_DrawMPRoomSelect(void)
// Draw buttons: // Draw buttons:
if (!mpmenu.roomforced || mpmenu.room == 0) V_DrawFixedPatch(160<<FRACBITS, 90<<FRACBITS, FRACUNIT, mpmenu.room ? (5<<V_ALPHASHIFT) : 0, butt1[(mpmenu.room) ? 1 : 0], NULL);
V_DrawFixedPatch(160<<FRACBITS, 100<<FRACBITS, FRACUNIT, mpmenu.room ? (5<<V_ALPHASHIFT) : 0, butt1[(mpmenu.room) ? 1 : 0], NULL);
if (!mpmenu.roomforced || mpmenu.room == 1) V_DrawFixedPatch(160<<FRACBITS, 90<<FRACBITS, FRACUNIT, (!mpmenu.room) ? (5<<V_ALPHASHIFT) : 0, butt2[(!mpmenu.room) ? 1 : 0], NULL);
V_DrawFixedPatch(160<<FRACBITS, 100<<FRACBITS, FRACUNIT, (!mpmenu.room) ? (5<<V_ALPHASHIFT) : 0, butt2[(!mpmenu.room) ? 1 : 0], NULL);
V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("MENUHINT", PU_CACHE), NULL);
V_DrawCenteredThinString(BASEVIDWIDTH/2, 12, 0, "Select today's type of play!");
M_DrawMasterServerReminder();
} }
// SERVER BROWSER // 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!
text = va("%d server%s found",
serverlistcount,
serverlistcount == 1 ? "" : "s"
);
}
}
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])
);
}
}
void M_DrawMPServerBrowser(void) void M_DrawMPServerBrowser(void)
{ {
patch_t *text1 = W_CachePatchName("MENUBGT1", PU_CACHE); patch_t *text1 = W_CachePatchName("MENUBGT1", PU_CACHE);
@ -3503,11 +3586,19 @@ void M_DrawMPServerBrowser(void)
V_DrawFill(0, 53, 320, 1, 31); V_DrawFill(0, 53, 320, 1, 31);
V_DrawFill(0, 55, 320, 1, 31); V_DrawFill(0, 55, 320, 1, 31);
V_DrawCenteredGamemodeString(160, 2, 0, 0, "Server Browser"); const char *headertext;
if (M_SecretUnlocked(SECRET_ADDONS, true))
headertext = va("%s Servers", mpmenu.room ? "Modded" : "Core");
else
headertext = "Server Browser";
V_DrawCenteredGamemodeString(160, 2, 0, 0, headertext);
// normal menu options // normal menu options
M_DrawGenericMenu(); M_DrawGenericMenu();
// And finally, the overlay bar!
M_DrawServerCountAndHorizontalBar();
M_DrawMasterServerReminder();
} }
// OPTIONS MENU // OPTIONS MENU

View file

@ -4,6 +4,7 @@
#include "../k_menu.h" #include "../k_menu.h"
#include "../m_cond.h" #include "../m_cond.h"
#include "../s_sound.h" #include "../s_sound.h"
#include "../mserv.h" // cv_masterserver
#if defined (TESTERS) #if defined (TESTERS)
#define IT_STRING_CALL_NOTESTERS IT_DISABLED #define IT_STRING_CALL_NOTESTERS IT_DISABLED
@ -11,13 +12,74 @@
#define IT_STRING_CALL_NOTESTERS (IT_STRING | IT_CALL) #define IT_STRING_CALL_NOTESTERS (IT_STRING | IT_CALL)
#endif // TESTERS #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[] = menuitem_t PLAY_MP_OptSelect[] =
{ {
{IT_STRING_CALL_NOTESTERS, "Host Game", "Start your own online game!", {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.", {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.", {IT_STRING | IT_CALL, "Join by IP", "Join an online game by its IP address.",
NULL, {.routine = M_MPJoinIPInit}, 0, 0}, NULL, {.routine = M_MPJoinIPInit}, 0, 0},

View file

@ -3,6 +3,8 @@
#include "../k_menu.h" #include "../k_menu.h"
#include "../s_sound.h" #include "../s_sound.h"
#include "../z_zone.h"
#include "../mserv.h"
// MULTIPLAYER HOST SCREEN -- see mhost_e // MULTIPLAYER HOST SCREEN -- see mhost_e
menuitem_t PLAY_MP_Host[] = menuitem_t PLAY_MP_Host[] =
@ -43,13 +45,41 @@ menu_t PLAY_MP_HostDef = {
NULL 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 M_MPHostInit(INT32 choice)
{ {
(void)choice; (void)choice;
mpmenu.modewinextend[0][0] = 1; mpmenu.modewinextend[0][0] = 1;
M_SetupNextMenu(&PLAY_MP_HostDef, true); M_SetupNextMenu(&PLAY_MP_HostDef, true);
itemOn = mhost_go; 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) void M_HandleHostMenuGametype(INT32 choice)

View file

@ -6,6 +6,7 @@
#include "../i_system.h" // I_OsPolling #include "../i_system.h" // I_OsPolling
#include "../i_video.h" // I_UpdateNoBlit #include "../i_video.h" // I_UpdateNoBlit
#include "../m_misc.h" // NUMLOGIP #include "../m_misc.h" // NUMLOGIP
#include "../f_finale.h" // g_wipeskiprender
menuitem_t PLAY_MP_JoinIP[] = menuitem_t PLAY_MP_JoinIP[] =
{ {
@ -56,6 +57,21 @@ void M_MPJoinIPInit(INT32 choice)
M_SetupNextMenu(&PLAY_MP_JoinIPDef, true); 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. // Attempts to join a given IP from the menu.
void M_JoinIP(const char *ipa) void M_JoinIP(const char *ipa)
{ {
@ -67,13 +83,7 @@ void M_JoinIP(const char *ipa)
COM_BufAddText(va("connect \"%s\"\n", ipa)); COM_BufAddText(va("connect \"%s\"\n", ipa));
// A little "please wait" message. M_PleaseWait();
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
} }
boolean M_JoinIPInputs(INT32 ch) boolean M_JoinIPInputs(INT32 ch)

View file

@ -42,8 +42,7 @@ void M_MPRoomSelect(INT32 choice)
M_ServersMenu(0); M_ServersMenu(0);
M_SetMenuDelay(pid); M_SetMenuDelay(pid);
} }
else if (mpmenu.roomforced == false else if (menucmd[pid].dpad_lr != 0)
&& menucmd[pid].dpad_lr != 0)
{ {
mpmenu.room ^= 1; mpmenu.room ^= 1;
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
@ -59,12 +58,28 @@ void M_MPRoomSelectTick(void)
void M_MPRoomSelectInit(INT32 choice) void M_MPRoomSelectInit(INT32 choice)
{ {
(void)choice; (void)choice;
if (modifiedgame)
{
M_StartMessage("Server Browser & Add-Ons", M_GetText("You have add-ons loaded.\nYou won't be able to join netgames!\n\nTo play online, restart the game\nand don't load any addons.\n\n\"Dr. Robotnik's Ring Racers\" will\nautomatically add everything\nyou need when you join.\n"), NULL, MM_NOTHING, NULL, NULL);
return;
}
// The following behaviour is affected by modifiedgame despite the above restriction.
// It's a sanity check were that to be removed, wheither by us or by a modified client.
// "wheither"? That typo rules, I'm keeping that ~toast 280823
mpmenu.room = (modifiedgame == true) ? 1 : 0; mpmenu.room = (modifiedgame == true) ? 1 : 0;
mpmenu.roomforced = ((modifiedgame == true) || (!M_SecretUnlocked(SECRET_ADDONS, true)));
mpmenu.ticker = 0; mpmenu.ticker = 0;
mpmenu.servernum = 0; mpmenu.servernum = 0;
mpmenu.scrolln = 0; mpmenu.scrolln = 0;
mpmenu.slide = 0; mpmenu.slide = 0;
if ((modifiedgame == true) || (M_SecretUnlocked(SECRET_ADDONS, true) == false))
{
M_ServersMenu(0);
return;
}
M_SetupNextMenu(&PLAY_MP_RoomSelectDef, false); M_SetupNextMenu(&PLAY_MP_RoomSelectDef, false);
} }

View file

@ -3,11 +3,14 @@
#include "../k_menu.h" #include "../k_menu.h"
#include "../v_video.h" #include "../v_video.h"
#include "../i_system.h" // I_OsPolling #include "../s_sound.h"
#include "../i_video.h" // I_UpdateNoBlit
//#define SERVERLISTDEBUG
#ifdef SERVERLISTDEBUG #ifdef SERVERLISTDEBUG
#include "../m_random.h" #include "../m_random.h"
void M_ServerListFillDebug(void);
#endif #endif
menuitem_t PLAY_MP_ServerBrowser[] = 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. {IT_STRING | IT_CVAR, "SORT BY", NULL, // tooltip MUST be null.
NULL, {.cvar = &cv_serversort}, 0, 0}, NULL, {.cvar = &cv_serversort}, 0, 0},
{IT_STRING, "REFRESH", NULL, {IT_STRING | IT_CALL, "REFRESH", NULL,
NULL, {NULL}, 0, 0}, NULL, {.routine = &M_RefreshServers}, 0, 0},
{IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0}, {IT_NOTHING, NULL, NULL, NULL, {NULL}, 0, 0},
}; };
@ -42,28 +45,6 @@ menu_t PLAY_MP_ServerBrowserDef = {
// for server fetch threads... // for server fetch threads...
M_waiting_mode_t m_waiting_mode = M_NOT_WAITING; 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 void
M_SetWaitingMode (int mode) M_SetWaitingMode (int mode)
{ {
@ -180,31 +161,19 @@ void M_RefreshServers(INT32 choice)
{ {
(void)choice; (void)choice;
// Display a little "please wait" message. CL_UpdateServerList();
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
#ifdef SERVERLISTDEBUG
M_ServerListFillDebug();
#else /*SERVERLISTDEBUG*/
#ifdef MASTERSERVER #ifdef MASTERSERVER
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
Spawn_masterserver_thread("fetch-servers", Fetch_servers_thread); Spawn_masterserver_thread("fetch-servers", Fetch_servers_thread);
#else/*HAVE_THREADS*/ #else/*HAVE_THREADS*/
Fetch_servers_thread(NULL); Fetch_servers_thread(NULL);
#endif/*HAVE_THREADS*/ #endif/*HAVE_THREADS*/
#else/*MASTERSERVER*/
CL_UpdateServerList();
#endif/*MASTERSERVER*/ #endif/*MASTERSERVER*/
#endif /*SERVERLISTDEBUG*/
#ifdef SERVERLISTDEBUG
M_ServerListFillDebug();
#endif
M_CleanServerList();
M_SortServerList();
} }
#ifdef UPDATE_ALERT #ifdef UPDATE_ALERT
@ -253,13 +222,21 @@ void M_ServersMenu(INT32 choice)
// modified game check: no longer handled // modified game check: no longer handled
// we don't request a restart unless the filelist differs // we don't request a restart unless the filelist differs
CL_UpdateServerList();
mpmenu.ticker = 0;
mpmenu.servernum = 0; mpmenu.servernum = 0;
mpmenu.scrolln = 0; mpmenu.scrolln = 0;
mpmenu.slide = 0; mpmenu.slide = 0;
PLAY_MP_ServerBrowserDef.prevMenu = currentMenu;
M_SetupNextMenu(&PLAY_MP_ServerBrowserDef, false); M_SetupNextMenu(&PLAY_MP_ServerBrowserDef, false);
itemOn = 0; itemOn = 0;
#ifdef SERVERLISTDEBUG
M_ServerListFillDebug();
#else /*SERVERLISTDEBUG*/
#if defined (MASTERSERVER) && defined (HAVE_THREADS) #if defined (MASTERSERVER) && defined (HAVE_THREADS)
I_lock_mutex(&ms_QueryId_mutex); I_lock_mutex(&ms_QueryId_mutex);
{ {
@ -289,12 +266,7 @@ void M_ServersMenu(INT32 choice)
M_RefreshServers(0); M_RefreshServers(0);
#endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/ #endif/*defined (MASTERSERVER) && defined (HAVE_THREADS)*/
#ifdef SERVERLISTDEBUG #endif /*SERVERLISTDEBUG*/
M_ServerListFillDebug();
#endif
M_CleanServerList();
M_SortServerList();
} }
#ifdef SERVERLISTDEBUG #ifdef SERVERLISTDEBUG
@ -304,29 +276,31 @@ void M_ServerListFillDebug(void)
{ {
UINT8 i = 0; UINT8 i = 0;
serverlistcount = 10; serverlistcount = 40;
memset(serverlist, 0, sizeof(serverlist)); // zero out the array for convenience... memset(serverlist, 0, sizeof(serverlist)); // zero out the array for convenience...
for (i = 0; i < serverlistcount; i++) 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... // 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 = M_RandomRange(8, 16);
serverlist[i].info.maxplayer = 8; 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.avgpwrlv = M_RandomRange(500, 1500);
serverlist[i].info.time = P_RandomRange(PR_UNDEFINED, 1, 8); // ping serverlist[i].info.time = M_RandomRange(1, 8); // ping
strcpy(serverlist[i].info.servername, va("Serv %d", i+1)); strcpy(serverlist[i].info.servername, va("Serv %d", i+1));
strcpy(serverlist[i].info.gametypename, i & 1 ? "Race" : "Battle"); strcpy(serverlist[i].info.gametypename, i & 1 ? "Race" : "Battle");
P_RandomRange(PR_UNDEFINED, 0, 5); // change results... serverlist[i].info.kartvars = M_RandomRange(0, 3) & SV_SPEEDMASK;
serverlist[i].info.kartvars = P_RandomRange(PR_UNDEFINED, 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); CONS_Printf("Serv %d | %d...\n", i, serverlist[i].info.modifiedgame);
} }
M_SortServerList();
} }
#endif // SERVERLISTDEBUG #endif // SERVERLISTDEBUG
@ -339,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; \ const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \
if (sa->info.key != sb->info.key) \ if (sa->info.key != sb->info.key) \
return 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. // This does descending instead of ascending.
@ -349,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; \ const serverelem_t *sa = (const serverelem_t*)entry1, *sb = (const serverelem_t*)entry2; \
if (sb->info.key != sa->info.key) \ if (sb->info.key != sa->info.key) \
return 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(numberofplayer)
SERVER_LIST_ENTRY_COMPARATOR_REVERSE(numberofplayer) SERVER_LIST_ENTRY_COMPARATOR_REVERSE(numberofplayer)
SERVER_LIST_ENTRY_COMPARATOR_REVERSE(maxplayer) SERVER_LIST_ENTRY_COMPARATOR_REVERSE(maxplayer)
SERVER_LIST_ENTRY_COMPARATOR(avgpwrlv) 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) static int ServerListEntryComparator_gametypename(const void *entry1, const void *entry2)
{ {
@ -365,13 +346,51 @@ static int ServerListEntryComparator_gametypename(const void *entry1, const void
int c; int c;
if (( c = strcasecmp(sa->info.gametypename, sb->info.gametypename) )) if (( c = strcasecmp(sa->info.gametypename, sb->info.gametypename) ))
return c; 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)
{
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) void M_SortServerList(void)
{ {
switch(cv_serversort.value) switch(cv_serversort.value)
{ {
case -1:
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_recommended);
break;
case 0: // Ping. case 0: // Ping.
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_time); qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_time);
break; break;
@ -397,89 +416,115 @@ void M_SortServerList(void)
// Server browser inputs & ticker // Server browser inputs & ticker
void M_MPServerBrowserTick(void) void M_MPServerBrowserTick(void)
{ {
mpmenu.ticker++;
mpmenu.slide /= 2; 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. // Input handler for server browser.
boolean M_ServerBrowserInputs(INT32 ch) boolean M_ServerBrowserInputs(INT32 ch)
{ {
UINT8 pid = 0; UINT8 pid = 0;
UINT8 maxscroll = serverlistcount-(SERVERSPERPAGE/2); INT16 maxscroll = serverlistcount - (SERVERSPERPAGE/2) - 2; // Why? Because
if (maxscroll < 0)
maxscroll = 0;
const INT16 serverbrowserOn = (currentMenu->numitems - 1);
(void) ch; (void) ch;
if (!itemOn && menucmd[pid].dpad_ud < 0) if (!itemOn && menucmd[pid].dpad_ud < 0)
{ {
M_PrevOpt(); // go to itemOn 2
if (serverlistcount) if (serverlistcount)
{ {
UINT8 prevscroll = mpmenu.scrolln; // Return the MS listing to the bottom.
INT32 prevscroll = mpmenu.scrolln;
mpmenu.servernum = serverlistcount; mpmenu.servernum = serverlistcount-1;
mpmenu.scrolln = maxscroll; mpmenu.scrolln = maxscroll;
mpmenu.slide = SERVERSPACE * (prevscroll - mpmenu.scrolln); mpmenu.slide = SERVERSPACE * (prevscroll - (INT32)mpmenu.scrolln);
} }
else else
{ {
itemOn = 1; // Sike! If there are no servers, go to refresh instead. M_PrevOpt(); // Double apply
} }
return true; // overwrite behaviour.
} }
else if (itemOn == 2) // server browser itself... else if (itemOn == (serverbrowserOn - 1) && menucmd[pid].dpad_ud > 0 && !serverlistcount)
{ {
// we have to manually do that here. M_NextOpt(); // Double apply
if (M_MenuBackPressed(pid)) }
else if (itemOn == serverbrowserOn) // server browser itself...
{
#ifndef SERVERLISTDEBUG
if (M_MenuConfirmPressed(pid))
{ {
M_GoBack(0);
M_SetMenuDelay(pid); M_SetMenuDelay(pid);
}
else if (menucmd[pid].dpad_ud > 0) // down COM_BufAddText(va("connect node %d\n", serverlist[mpmenu.servernum].node));
{
if (mpmenu.servernum >= serverlistcount-1)
{
UINT8 prevscroll = mpmenu.scrolln;
mpmenu.servernum = 0;
mpmenu.scrolln = 0;
mpmenu.slide = SERVERSPACE * (prevscroll - mpmenu.scrolln);
M_NextOpt(); // Go back to the top of the real menu. M_PleaseWait();
return true;
} }
else #endif
if (menucmd[pid].dpad_ud > 0) // down
{ {
if ((UINT32)(mpmenu.servernum+1) < serverlistcount)
{
// Listing scroll down
mpmenu.servernum++; mpmenu.servernum++;
if (mpmenu.scrolln < maxscroll && mpmenu.servernum > SERVERSPERPAGE/2) if (mpmenu.scrolln < maxscroll && mpmenu.servernum > SERVERSPERPAGE/2)
{ {
mpmenu.scrolln++; mpmenu.scrolln++;
mpmenu.slide += SERVERSPACE; mpmenu.slide += SERVERSPACE;
} }
}
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid); 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) else if (menucmd[pid].dpad_ud < 0)
{ {
if (mpmenu.servernum)
if (!mpmenu.servernum)
{ {
M_PrevOpt(); // Listing scroll up
} if (mpmenu.servernum <= (INT16)maxscroll && mpmenu.scrolln)
else
{
if (mpmenu.servernum <= serverlistcount-(SERVERSPERPAGE/2) && mpmenu.scrolln)
{ {
mpmenu.scrolln--; mpmenu.scrolln--;
mpmenu.slide -= SERVERSPACE; mpmenu.slide -= SERVERSPACE;
} }
mpmenu.servernum--; mpmenu.servernum--;
}
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid); M_SetMenuDelay(pid);
return true;
}
} }
return true; // Overwrite behaviour.
} }
return false; // use normal behaviour. return false; // use normal behaviour.
} }

View file

@ -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) 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; const UINT8 pid = 0;
static char *message = NULL;
Z_Free(message);
DEBFILE(string); DEBFILE(string);
message = V_ScaledWordWrap( char *message = V_ScaledWordWrap(
BASEVIDWIDTH << FRACBITS, (BASEVIDWIDTH - 8) << FRACBITS,
FRACUNIT, FRACUNIT, FRACUNIT, FRACUNIT, FRACUNIT, FRACUNIT,
0, 0,
HU_FONT, HU_FONT,
string string
); );
strncpy(menumessage.message, string, MAXMENUMESSAGE); strncpy(menumessage.message, message, MAXMENUMESSAGE);
Z_Free(message);
menumessage.header = header; menumessage.header = header;
menumessage.flags = itemtype; menumessage.flags = itemtype;
menumessage.routine = routine; 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 // oogh my god this was replaced in 2023
menumessage.x = (8 * MAXSTRINGLENGTH) - 1; 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. M_SetMenuDelay(pid); // Set menu delay to avoid setting off any of the handlers.
} }

View file

@ -17,6 +17,7 @@
#include "doomstat.h" #include "doomstat.h"
#include "doomdef.h" #include "doomdef.h"
#include "console.h" // con_startup
#include "command.h" #include "command.h"
#include "i_threads.h" #include "i_threads.h"
#include "mserv.h" #include "mserv.h"
@ -40,6 +41,8 @@ static boolean MSUpdateAgain;
static time_t MSLastPing; static time_t MSLastPing;
static char *MSRules;
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
static I_mutex MSMutex; static I_mutex MSMutex;
static I_cond MSCond; 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 static void
Finish_registration (void) Finish_registration (void)
{ {
@ -175,6 +215,17 @@ Finish_registration (void)
} }
Unlock_state(); 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) if (registered)
CONS_Printf("Master server registration successful.\n"); 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 #ifdef HAVE_THREADS
static int * static int *
Server_id (void) Server_id (void)
@ -350,7 +410,14 @@ Change_masterserver_thread (char *api)
} }
Unlock_state(); 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*/ #endif/*HAVE_THREADS*/
@ -397,6 +464,17 @@ void UnregisterServer(void)
#endif/*MASTERSERVER*/ #endif/*MASTERSERVER*/
} }
char *GetMasterServerRules(void)
{
char *rules;
Lock_state();
rules = MSRules ? Z_StrDup(MSRules) : NULL;
Unlock_state();
return rules;
}
static boolean static boolean
Online (void) Online (void)
{ {
@ -447,7 +525,21 @@ Set_api (const char *api)
strdup(api) strdup(api)
); );
#else #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 #endif
} }
@ -521,6 +613,8 @@ void Advertise_OnChange(void)
#ifdef HAVE_DISCORDRPC #ifdef HAVE_DISCORDRPC
DRPC_UpdatePresence(); DRPC_UpdatePresence();
#endif #endif
M_PopupMasterServerRules();
} }
#ifdef DEVELOP #ifdef DEVELOP

View file

@ -57,6 +57,7 @@ struct msg_ban_t
// ================================ GLOBALS =============================== // ================================ GLOBALS ===============================
extern consvar_t cv_masterserver, cv_servername; extern consvar_t cv_masterserver, cv_servername;
extern consvar_t cv_masterserver_nagattempts;
extern consvar_t cv_server_contact; extern consvar_t cv_server_contact;
extern consvar_t cv_masterserver_update_rate; extern consvar_t cv_masterserver_update_rate;
extern consvar_t cv_masterserver_timeout; extern consvar_t cv_masterserver_timeout;
@ -77,6 +78,8 @@ extern I_mutex ms_ServerList_mutex;
void RegisterServer(void); void RegisterServer(void);
void UnregisterServer(void); void UnregisterServer(void);
void Get_rules(void);
void MasterClient_Ticker(void); void MasterClient_Ticker(void);
msg_server_t *GetShortServersList(int id); msg_server_t *GetShortServersList(int id);
@ -84,6 +87,8 @@ msg_server_t *GetShortServersList(int id);
char *GetMODVersion(int id); char *GetMODVersion(int id);
#endif #endif
char *GetMasterServerRules(void);
void AddMServCommands(void); void AddMServCommands(void);
/* HTTP */ /* HTTP */
@ -94,6 +99,7 @@ int HMS_update (void);
void HMS_list_servers (void); void HMS_list_servers (void);
msg_server_t * HMS_fetch_servers (msg_server_t *list, int id); msg_server_t * HMS_fetch_servers (msg_server_t *list, int id);
int HMS_compare_mod_version (char *buffer, size_t size_of_buffer); 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 #ifdef __cplusplus
} // extern "C" } // extern "C"

View file

@ -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 ). // 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. // DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server.