diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 53bbaf0b68443eaeca23eabc7194fb7d144c2dc4..0c8d736de94e2dc7e050c7ea21dea360ac06718d 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -163,6 +163,7 @@ static UINT8 localtextcmd[MAXSPLITSCREENPLAYERS][MAXTEXTCMD]; static tic_t neededtic; SINT8 servernode = 0; // the number of the server node char connectedservername[MAXSERVERNAME]; +char connectedservercontact[MAXSERVERCONTACT]; /// \brief do we accept new players? /// \todo WORK! boolean acceptnewnode = true; @@ -1283,6 +1284,9 @@ static boolean SV_SendServerConfig(INT32 node) memcpy(netbuffer->u.servercfg.server_context, server_context, 8); + strncpy(netbuffer->u.servercfg.server_name, cv_servername.string, MAXSERVERNAME); + strncpy(netbuffer->u.servercfg.server_contact, cv_server_contact.string, MAXSERVERCONTACT); + { const size_t len = sizeof (serverconfig_pak); @@ -3799,6 +3803,9 @@ void SV_ResetServer(void) // clear server_context memset(server_context, '-', 8); + strncpy(connectedservername, "\0", MAXSERVERNAME); + strncpy(connectedservercontact, "\0", MAXSERVERCONTACT); + CV_RevertNetVars(); // Copy our unlocks to a place where net material can grab at/overwrite them safely. @@ -3811,9 +3818,10 @@ void SV_ResetServer(void) DEBFILE("\n-=-=-=-=-=-=-= Server Reset =-=-=-=-=-=-=-\n\n"); } -static inline void SV_GenContext(void) +static void SV_GenContext(void) { UINT8 i; + // generate server_context, as exactly 8 bytes of randomly mixed A-Z and a-z // (hopefully M_Random is initialized!! if not this will be awfully silly!) for (i = 0; i < 8; i++) @@ -3824,6 +3832,9 @@ static inline void SV_GenContext(void) else // lowercase server_context[i] = 'a'+(a-26); } + + strncpy(connectedservername, cv_servername.string, MAXSERVERNAME); + strncpy(connectedservercontact, cv_server_contact.string, MAXSERVERCONTACT); } // @@ -4874,7 +4885,11 @@ static void HandlePacketFromAwayNode(SINT8 node) G_SetGametype(netbuffer->u.servercfg.gametype); modifiedgame = netbuffer->u.servercfg.modifiedgame; + memcpy(server_context, netbuffer->u.servercfg.server_context, 8); + + strncpy(connectedservername, netbuffer->u.servercfg.server_name, MAXSERVERNAME); + strncpy(connectedservercontact, netbuffer->u.servercfg.server_contact, MAXSERVERCONTACT); } #ifdef HAVE_DISCORDRPC diff --git a/src/d_clisrv.h b/src/d_clisrv.h index e2dd85bff8e22748425b7e50071b4f0a8dcf2f79..fdcf4d0fe521038283d73e864fb0b9edabad8c0a 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -43,6 +43,9 @@ applications may follow different packet versions. #define HU_MAXMSGLEN 223 +#define MAXSERVERNAME 32 +#define MAXSERVERCONTACT 1024 + // Networking and tick handling related. #define BACKUPTICS 512 // more than enough for most timeouts.... #define CLIENTBACKUPTICS 32 @@ -226,6 +229,9 @@ struct serverconfig_pak UINT8 maxplayer; boolean allownewplayer; boolean discordinvites; + + char server_name[MAXSERVERNAME]; + char server_contact[MAXSERVERCONTACT]; } ATTRPACK; struct filetx_pak @@ -276,7 +282,6 @@ struct clientconfig_pak #define SV_DEDICATED 0x40 // server is dedicated #define SV_LOTSOFADDONS 0x20 // flag used to ask for full file list in d_netfil -#define MAXSERVERNAME 32 #define MAXFILENEEDED 915 #define MAX_MIRROR_LENGTH 256 // This packet is too large @@ -509,6 +514,7 @@ extern UINT16 software_MAXPACKETLENGTH; extern boolean acceptnewnode; extern SINT8 servernode; extern char connectedservername[MAXSERVERNAME]; +extern char connectedservercontact[MAXSERVERCONTACT]; extern UINT32 ourIP; extern uint8_t lastReceivedKey[MAXNETNODES][MAXSPLITSCREENPLAYERS][PUBKEYLENGTH]; extern uint8_t lastSentChallenge[MAXNETNODES][CHALLENGELENGTH]; diff --git a/src/d_main.c b/src/d_main.c index fd05bc3cde549ac4b298041007fbc6a8a215d055..c177370602946612724191c2d041f91a4964fc4a 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1913,8 +1913,6 @@ void D_SRB2Main(void) COM_BufExecute(); // ensure the command buffer gets executed before the map starts (+skin) - strncpy(connectedservername, cv_servername.string, MAXSERVERNAME); - if (M_CheckParm("-gametype") && M_IsNextParm()) { // from Command_Map_f diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 6becfd0c3820b036ff675c2ab8f85eda7ab8c046..5694206267b03f94c5fe987ba86666ff75134351 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -3023,8 +3023,6 @@ static void Command_Map_f(void) multiplayer = true; netgame = false; - strncpy(connectedservername, cv_servername.string, MAXSERVERNAME); - if (cv_maxconnections.value < ssplayers+1) CV_SetValue(&cv_maxconnections, ssplayers+1); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index e97d411836a704d36bd22e0b9e789ba19c37c27c..fd9fa3c973b8cbc155be8db1c38e555e8444c4cb 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1952,7 +1952,7 @@ void HU_DrawSongCredits(void) } else { - y = (r_splitscreen ? (BASEVIDHEIGHT/2)-4 : 32) * FRACUNIT; + y = (r_splitscreen ? (BASEVIDHEIGHT/2)-4 : 40) * FRACUNIT; } INT32 bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans / 2); diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 23c989505d328423ff3b7730431b0b957c4b2f74..800ff3c6c53990f7d29f1df8cb2674e25a65fda8 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -825,6 +825,13 @@ void M_Drawer(void) } } + if (netgame && Playing()) + { + boolean mainpause_open = menuactive && currentMenu == &PAUSE_MainDef; + + ST_DrawServerSplash(!mainpause_open); + } + // focus lost notification goes on top of everything, even the former everything if (window_notinfocus && cv_showfocuslost.value) { diff --git a/src/st_stuff.c b/src/st_stuff.c index c7166c4144347a92c3748bb4ebb736334f0a77d9..748d6da1dda8192243a56a2d8cde685921d98e06 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1303,6 +1303,124 @@ void ST_AskToJoinEnvelope(void) } #endif +static INT32 ST_ServerSplash_OpacityFlag(INT32 opacity) +{ + if (opacity >= NUMTRANSMAPS) + { + return 0; + } + + opacity = max(opacity, 1); + return (NUMTRANSMAPS - opacity) << V_ALPHASHIFT; +} + +void ST_DrawServerSplash(boolean timelimited) +{ + static const fixed_t SPLASH_LEN = (FRACUNIT * TICRATE) * 3; + static const fixed_t SPLASH_WAIT = (FRACUNIT * TICRATE) / 2; + + static fixed_t splashTime = -SPLASH_WAIT; + static char prevContext[8] = {0}; + + if (memcmp(prevContext, server_context, 8) != 0) + { + // Context changed, we want to draw it again + splashTime = -SPLASH_WAIT; + memcpy(prevContext, server_context, 8); + } + + if (lt_ticker < lt_endtime) + { + // Level title is running rn + return; + } + + if (timelimited + && splashTime >= SPLASH_LEN) + { + // We finished drawing it + return; + } + + splashTime += renderdeltatics; + if (splashTime <= 0) + { + // We're waiting a tiny bit to draw it + return; + } + + const INT32 splashTic = splashTime >> FRACBITS; + INT32 opacity = NUMTRANSMAPS; + if (splashTic < NUMTRANSMAPS) + { + opacity = splashTic; + } + else if (timelimited + && splashTic > (SPLASH_LEN >> FRACBITS) - NUMTRANSMAPS) + { + opacity = (SPLASH_LEN >> FRACBITS) - splashTic; + } + + INT32 opacityFlag = ST_ServerSplash_OpacityFlag(opacity); + + patch_t *gridPatch = W_CachePatchName("MOTDBG", PU_CACHE); + + if (gridPatch && gridPatch->width) + { + fixed_t gridX = -(splashTime / 3) % (gridPatch->width * FRACUNIT); + fixed_t gridY = (gridPatch->height) * FRACUNIT; + INT32 gridOpacity = ST_ServerSplash_OpacityFlag(opacity / 2); + fixed_t maxX = (vid.width * FRACUNIT) / vid.dupx; + + while (gridX < maxX) + { + V_DrawFixedPatch( + gridX, gridY, + FRACUNIT, + (V_SNAPTOLEFT|V_SNAPTOBOTTOM) | V_SUBTRACT | V_VFLIP | gridOpacity, + gridPatch, + NULL + ); + + gridX += (gridPatch->width * FRACUNIT); + } + } + + // We're a bit crunched atm to do this but hopefully in the future + // the icon can be made a bmp file on the hard drive that the server + // sends on client join instead. + patch_t *iconPatch = W_CachePatchName("MOTDICON", PU_CACHE); + fixed_t iconX = (BASEVIDWIDTH - 16 - iconPatch->width) * FRACUNIT; + fixed_t iconY = (8) * FRACUNIT; + V_DrawFixedPatch( + iconX, iconY, + FRACUNIT, + (V_SNAPTORIGHT|V_SNAPTOBOTTOM) | opacityFlag, + iconPatch, + NULL + ); + + fixed_t textX = (BASEVIDWIDTH - 16 - 36) * FRACUNIT; + fixed_t textY = (24 - 8) * FRACUNIT; + + V_DrawRightAlignedStringAtFixed( + textX, textY, + (V_SNAPTORIGHT|V_SNAPTOBOTTOM) | opacityFlag, + connectedservername + ); + + textY += 10*FRACUNIT; + + if (connectedservercontact[0] != 0) + { + V_DrawRightAlignedThinStringAtFixed( + textX, textY, + (V_SNAPTORIGHT|V_SNAPTOBOTTOM) | opacityFlag, + va("Contact @ %c%s", '\x80' + cv_shoutcolor.value, connectedservercontact) + ); + } +} + void ST_Drawer(void) { boolean stagetitle = false; // Decide whether to draw the stage title or not diff --git a/src/st_stuff.h b/src/st_stuff.h index 44aa5f25188e916e3628bca127ef025998448e6a..c406bdcaf894e4b8e15b89a58e2069a68b689436 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -75,6 +75,8 @@ void ST_preLevelTitleCardDrawer(void); extern tic_t lt_ticker, lt_lasttic; extern tic_t lt_exitticker, lt_endtime; +void ST_DrawServerSplash(boolean timelimited); + // return if player a is in the same team as player b boolean ST_SameTeam(player_t *a, player_t *b); diff --git a/src/v_video.cpp b/src/v_video.cpp index 17519f8947961e38ae8c319ed371920625e4a042..351ff4d465b6e026704e81d3b7f0c1060edae846 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -2789,12 +2789,24 @@ void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *st V_DrawThinString(x, y, option, string); } -void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) +void V_DrawCenteredStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) { x -= (V_ThinStringWidth(string, option) / 2) * FRACUNIT; V_DrawThinStringAtFixed(x, y, option, string); } +void V_DrawRightAlignedStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) +{ + x -= V_StringWidth(string, option) * FRACUNIT; + V_DrawStringAtFixed(x, y, option, string); +} + +void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) +{ + x -= (V_StringWidth(string, option) / 2) * FRACUNIT; + V_DrawStringAtFixed(x, y, option, string); +} + void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) { x -= V_ThinStringWidth(string, option) * FRACUNIT; diff --git a/src/v_video.h b/src/v_video.h index 7a26591dc052d302d00a1c1334d65c4e793e5f26..f7c32505c8d2a356c7faa5ef66ea8e4d8dbf8012 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -334,16 +334,14 @@ void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *st #define V_DrawStringAtFixed( x,y,option,string ) \ V__DrawOneScaleString (x,y,FRACUNIT,option,NULL,HU_FONT,string) +void V_DrawCenteredStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); +void V_DrawRightAlignedStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); #define V_DrawThinStringAtFixed( x,y,option,string ) \ V__DrawOneScaleString (x,y,FRACUNIT,option,NULL,TINY_FONT,string) void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); - -void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); -void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); - // Draws a titlecard font string. // timer: when the letters start appearing (leave to 0 to disable) // threshold: when the letters start disappearing (leave to 0 to disable) (both are INT32 in case you supply negative values...)