Merge branch 'motd' into 'master'

Add server join splash (resolves #266)

Closes #266

See merge request KartKrew/Kart!1423
This commit is contained in:
toaster 2023-08-25 20:43:02 +00:00
commit 4abc0b2c5d
10 changed files with 166 additions and 12 deletions

View file

@ -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

View file

@ -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];

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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)
{

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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...)