Refactor and rework viewserver
Thanks to the srb2 classic team and luigi budd for the original version
This commit is contained in:
parent
56edab2480
commit
7c712836f3
10 changed files with 481 additions and 60 deletions
125
src/d_clisrv.c
125
src/d_clisrv.c
|
|
@ -154,6 +154,8 @@ static boolean cl_redownloadinggamestate = false;
|
|||
static UINT8 localtextcmd[MAXSPLITSCREENPLAYERS][MAXTEXTCMD];
|
||||
static tic_t neededtic;
|
||||
SINT8 servernode = 0; // the number of the server node
|
||||
SINT8 joinnode = 0; // used for CL_VIEWSERVER
|
||||
|
||||
char connectedservername[MAXSERVERNAME+1];
|
||||
/// \brief do we accept new players?
|
||||
/// \todo WORK!
|
||||
|
|
@ -541,27 +543,6 @@ void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum)
|
|||
|
||||
static INT16 Consistancy(void);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CL_SEARCHING,
|
||||
CL_CHECKFILES,
|
||||
CL_DOWNLOADFILES,
|
||||
CL_DOWNLOADFAILED,
|
||||
CL_ASKJOIN,
|
||||
CL_LOADFILES,
|
||||
CL_SETUPFILES,
|
||||
CL_WAITJOINRESPONSE,
|
||||
CL_DOWNLOADSAVEGAME,
|
||||
CL_CONNECTED,
|
||||
CL_ABORTED,
|
||||
CL_ASKFULLFILELIST,
|
||||
CL_CONFIRMCONNECT,
|
||||
#ifdef HAVE_CURL
|
||||
CL_PREPAREHTTPFILES,
|
||||
CL_DOWNLOADHTTPFILES,
|
||||
#endif
|
||||
} cl_mode_t;
|
||||
|
||||
static void GetPackets(void);
|
||||
|
||||
static cl_mode_t cl_mode = CL_SEARCHING;
|
||||
|
|
@ -572,6 +553,34 @@ char http_source[MAX_MIRROR_LENGTH];
|
|||
|
||||
static UINT16 cl_lastcheckedfilecount = 0; // used for full file list
|
||||
|
||||
static const char* servmus_1 = "SRVMS1";
|
||||
static const char* servmus_2 = "SRVMS2";
|
||||
// "SRVMS3" allows for the music position to be kept between servmus_1 and servmus_3
|
||||
// also takes priority over servmus_2
|
||||
static const char* servmus_3 = "SRVMS3";
|
||||
|
||||
static void ChangeServMusic(const char* musname, boolean fallback, boolean keepPos)
|
||||
{
|
||||
if (S_MusicExists(musname))
|
||||
if (keepPos)
|
||||
S_ChangeMusicEx(musname,0,true, S_GetMusicPosition(), 0,0);
|
||||
else
|
||||
S_ChangeMusicInternal(musname,true);
|
||||
else if (fallback)
|
||||
S_ChangeMusicInternal("BLANCD",true);
|
||||
}
|
||||
|
||||
// Let external code read and modify this stuff.
|
||||
INT32 GetClientMode(void)
|
||||
{
|
||||
return cl_mode;
|
||||
}
|
||||
|
||||
void ChangeClientMode(INT32 mode)
|
||||
{
|
||||
cl_mode = mode;
|
||||
}
|
||||
|
||||
//
|
||||
// CL_DrawConnectionStatus
|
||||
//
|
||||
|
|
@ -589,6 +598,7 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
#ifdef HAVE_CURL
|
||||
&& cl_mode != CL_DOWNLOADHTTPFILES
|
||||
#endif
|
||||
&& cl_mode != CL_VIEWSERVER
|
||||
)
|
||||
{
|
||||
INT32 i, animtime = ((ccstime / 4) & 15) + 16;
|
||||
|
|
@ -703,6 +713,14 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, MENUCAPS|V_20TRANS|V_MONOSPACE,
|
||||
va(" %2u/%2u Files",loadcompletednum,fileneedednum));
|
||||
}
|
||||
else if (cl_mode == CL_VIEWSERVER)
|
||||
{
|
||||
if (!menustack[0])
|
||||
{
|
||||
M_StartControlPanel();
|
||||
M_EnterMenu(MN_VIEWSERVER, true, 0);
|
||||
}
|
||||
}
|
||||
else if (lastfilenum != -1)
|
||||
{
|
||||
INT32 dldlength;
|
||||
|
|
@ -944,7 +962,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
|
|||
else
|
||||
netbuffer->u.serverinfo.refusereason = 0;
|
||||
|
||||
strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[prefgametype],
|
||||
strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype],
|
||||
sizeof netbuffer->u.serverinfo.gametypename);
|
||||
netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame;
|
||||
netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled();
|
||||
|
|
@ -1043,20 +1061,16 @@ static void SV_SendPlayerInfo(INT32 node)
|
|||
|
||||
for (i = 0; i < MSCOMPAT_MAXPLAYERS; i++)
|
||||
{
|
||||
if (i >= MAXPLAYERS)
|
||||
{
|
||||
netbuffer->u.playerinfo[i].num = 255; // Master Server compat
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!playeringame[i])
|
||||
if (i >= MAXPLAYERS || playernode[i] == UINT8_MAX || !playeringame[i])
|
||||
{
|
||||
netbuffer->u.playerinfo[i].num = 255; // This slot is empty.
|
||||
continue;
|
||||
}
|
||||
|
||||
netbuffer->u.playerinfo[i].num = i;
|
||||
strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1);
|
||||
memset(netbuffer->u.playerinfo[i].name, 0x00, sizeof(netbuffer->u.playerinfo[i].name));
|
||||
memcpy(netbuffer->u.playerinfo[i].name, player_names[i], sizeof(player_names[i]));
|
||||
|
||||
netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0';
|
||||
|
||||
//fetch IP address
|
||||
|
|
@ -1603,6 +1617,10 @@ static boolean CL_FinishedFileList(void)
|
|||
"Press ACCEL to continue or BRAKE to cancel.\n\n"
|
||||
), M_ConfirmConnect, MM_EVENTHANDLER);
|
||||
cl_mode = CL_CONFIRMCONNECT;
|
||||
if (S_MusicExists(servmus_3))
|
||||
ChangeServMusic(servmus_3, true,true);
|
||||
else
|
||||
ChangeServMusic(servmus_2, false,false);
|
||||
}
|
||||
else
|
||||
cl_mode = CL_LOADFILES;
|
||||
|
|
@ -1672,6 +1690,11 @@ static boolean CL_FinishedFileList(void)
|
|||
|
||||
Z_Free(downloadsize);
|
||||
cl_mode = CL_CONFIRMCONNECT;
|
||||
|
||||
if (S_MusicExists(servmus_3))
|
||||
ChangeServMusic(servmus_3, true,true);
|
||||
else
|
||||
ChangeServMusic(servmus_2, false,false);
|
||||
}
|
||||
#ifdef HAVE_CURL
|
||||
else
|
||||
|
|
@ -1771,7 +1794,8 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
|
|||
return true;
|
||||
}
|
||||
|
||||
cl_mode = CL_CHECKFILES;
|
||||
cl_mode = CL_VIEWSERVER; //cl_mode = CL_CHECKFILES;
|
||||
ChangeServMusic(servmus_1, true,false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1816,7 +1840,10 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
|||
|
||||
case CL_ASKFULLFILELIST:
|
||||
if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved
|
||||
cl_mode = CL_CHECKFILES;
|
||||
{
|
||||
cl_mode = CL_VIEWSERVER; //cl_mode = CL_CHECKFILES;
|
||||
ChangeServMusic(servmus_1, true,false);
|
||||
}
|
||||
else if (fileneedednum != cl_lastcheckedfilecount || I_GetTime() >= *asksent)
|
||||
{
|
||||
if (CL_AskFileList(fileneedednum))
|
||||
|
|
@ -2002,10 +2029,17 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
|||
else
|
||||
continue;
|
||||
|
||||
if (cl_mode == CL_VIEWSERVER && menustack[0])
|
||||
{
|
||||
M_Responder(ev);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (key == KEY_ESCAPE || G_ControlBoundToKey(0, gc_brake, key, true))
|
||||
cl_mode = CL_ABORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cl_mode == CL_ABORTED)
|
||||
{
|
||||
|
|
@ -4331,31 +4365,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
|
|||
switch (netbuffer->packettype)
|
||||
{
|
||||
case PT_ASKINFOVIAMS:
|
||||
#if 0
|
||||
if (server && serverrunning)
|
||||
{
|
||||
INT32 clientnode;
|
||||
if (ms_RoomId < 0) // ignore if we're not actually on the MS right now
|
||||
{
|
||||
Net_CloseConnection(node); // and yes, close connection
|
||||
return;
|
||||
}
|
||||
clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr);
|
||||
if (clientnode != -1)
|
||||
{
|
||||
SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time));
|
||||
SV_SendPlayerInfo(clientnode); // Send extra info
|
||||
Net_CloseConnection(clientnode);
|
||||
// Don't close connection to MS...
|
||||
}
|
||||
else
|
||||
Net_CloseConnection(node); // ...unless the IP address is not valid
|
||||
}
|
||||
else
|
||||
Net_CloseConnection(node); // you're not supposed to get it, so ignore it
|
||||
#else
|
||||
Net_CloseConnection(node);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PT_TELLFILESNEEDED:
|
||||
|
|
@ -4536,6 +4546,9 @@ static void HandlePacketFromAwayNode(SINT8 node)
|
|||
case PT_CLIENTCMD:
|
||||
break; // This is not an "unknown packet"
|
||||
|
||||
case PT_PLAYERINFO:
|
||||
break;
|
||||
|
||||
case PT_SERVERTICS:
|
||||
// Do not remove my own server (we have just get a out of order packet)
|
||||
if (node == servernode)
|
||||
|
|
|
|||
|
|
@ -471,6 +471,28 @@ void SendNetXCmdForPlayer(UINT8 playerid, netxcmd_t id, const void *param, size_
|
|||
#define SendNetXCmd(id, param, nparam) SendNetXCmdForPlayer(0, id, param, nparam) // Shortcut for P1
|
||||
void SendKick(UINT8 playernum, UINT8 msg);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CL_SEARCHING,
|
||||
CL_CHECKFILES,
|
||||
CL_DOWNLOADFILES,
|
||||
CL_DOWNLOADFAILED,
|
||||
CL_ASKJOIN,
|
||||
CL_LOADFILES,
|
||||
CL_SETUPFILES,
|
||||
CL_WAITJOINRESPONSE,
|
||||
CL_DOWNLOADSAVEGAME,
|
||||
CL_CONNECTED,
|
||||
CL_ABORTED,
|
||||
CL_ASKFULLFILELIST,
|
||||
CL_CONFIRMCONNECT,
|
||||
CL_VIEWSERVER,
|
||||
#ifdef HAVE_CURL
|
||||
CL_PREPAREHTTPFILES,
|
||||
CL_DOWNLOADHTTPFILES,
|
||||
#endif
|
||||
} cl_mode_t;
|
||||
|
||||
// Create any new ticcmds and broadcast to other players.
|
||||
void NetKeepAlive(void);
|
||||
void NetUpdate(void);
|
||||
|
|
@ -530,6 +552,10 @@ extern char motd[254], server_context[8];
|
|||
extern UINT8 playernode[MAXPLAYERS];
|
||||
/* consoleplayer of this player (splitscreen) */
|
||||
extern UINT8 playerconsole[MAXPLAYERS];
|
||||
extern SINT8 joinnode;
|
||||
|
||||
INT32 GetClientMode(void);
|
||||
void ChangeClientMode(INT32 mode);
|
||||
|
||||
INT32 D_NumPlayers(void);
|
||||
boolean D_IsPlayerHumanAndGaming(INT32 player_number);
|
||||
|
|
|
|||
|
|
@ -748,6 +748,8 @@ struct menu_routine_s const MENU_ROUTINES[] = {
|
|||
{ "ASSIGNJOYSTICK", &MR_AssignJoystick },
|
||||
{ "HANDLEMONITORTOGGLES", &MR_HandleMonitorToggles },
|
||||
{ "RESTARTAUDIO", &MR_RestartAudio },
|
||||
{ "QUITVIEWSERVER", &MR_QuitViewServer },
|
||||
{ "HANDLEVIEWSERVER", &MR_HandleViewServer },
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
{ "HANDLEDISCORDREQUESTS", &MR_HandleDiscordRequests },
|
||||
#endif
|
||||
|
|
@ -776,7 +778,7 @@ struct menu_drawer_s const MENU_DRAWERS[] = {
|
|||
{ "DRAWCONTROL", &M_DrawControl },
|
||||
{ "DRAWJOYSTICK", &M_DrawJoystick },
|
||||
{ "DRAWMONITORTOGGLES", &M_DrawMonitorToggles },
|
||||
{ "DRAWCONNECTMENU", &M_DrawConnectMenu },
|
||||
{ "DRAWVIEWSERVER", &M_DrawViewServer },
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
{ "DRAWDISCORDREQUESTS", &M_DrawDiscordRequests },
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ extern "C" {
|
|||
|
||||
// Special Hashing.
|
||||
//#define NOMD5
|
||||
//#define NOFILEHASH
|
||||
#define NOFILEHASH
|
||||
|
||||
// Uncheck this to compile debugging code
|
||||
//#define RANGECHECK
|
||||
|
|
|
|||
|
|
@ -919,6 +919,8 @@ static const char *blancredits[] = {
|
|||
"\"Lactozilla\"",
|
||||
"\"xyzzy\"",
|
||||
"\"SuperJustinBros\"",
|
||||
"SRB2Classic Team",
|
||||
"\"luigi budd\"",
|
||||
"",
|
||||
"\1Ring Racers Programming",
|
||||
"Kart Krew Dev",
|
||||
|
|
|
|||
25
src/g_game.c
25
src/g_game.c
|
|
@ -768,6 +768,31 @@ INT32 G_MapNumber(const char * name)
|
|||
#endif
|
||||
}
|
||||
|
||||
/** Returns the map number from level title.
|
||||
*
|
||||
* \param name Map name;
|
||||
* \return Map number.
|
||||
* \sa G_BuildMapName, nextmapspecial_t
|
||||
*/
|
||||
INT32 G_LevelTitleToMapNum(const char * leveltitle)
|
||||
{
|
||||
INT32 map;
|
||||
|
||||
for (map = 0; map < nummapheaders; ++map)
|
||||
{
|
||||
if (!strcasecmp(leveltitle, mapheaderinfo[map]->lvlttl))
|
||||
{
|
||||
return map;
|
||||
}
|
||||
|
||||
if (!strcasecmp(leveltitle, va("%s %s", mapheaderinfo[map]->lvlttl, mapheaderinfo[map]->actnum)))
|
||||
{
|
||||
return map;
|
||||
}
|
||||
}
|
||||
return INT32_MIN;
|
||||
}
|
||||
|
||||
// convert kart map number to native map number
|
||||
INT16 G_KartMapToNative(INT16 mapnum)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ void weaponPrefChange4(void);
|
|||
|
||||
const char *G_BuildMapName(INT32 map);
|
||||
INT32 G_MapNumber(const char *mapname);
|
||||
INT32 G_LevelTitleToMapNum(const char * leveltitle);
|
||||
INT16 G_KartMapToNative(INT16 mapnum);
|
||||
INT16 G_NativeMapToKart(INT16 mapnum);
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ _(MISC_REPLAYSTART)
|
|||
_(AD_MAIN)
|
||||
|
||||
// MISC
|
||||
_(VIEWSERVER)
|
||||
_(HELP)
|
||||
_(SPAUSE)
|
||||
_(MPAUSE)
|
||||
|
|
|
|||
348
src/m_menu.c
348
src/m_menu.c
|
|
@ -268,6 +268,8 @@ static INT16 M_GetMenuIndex(menutype_t type, const char *name)
|
|||
#define M_SetItemArgument(t, n, v) (M_GetMenuItem(t, n)->argument = v)
|
||||
#define M_SetItemX(t, n, v) (M_GetMenuItem(t, n)->x = v)
|
||||
#define M_SetItemY(t, n, v) (M_GetMenuItem(t, n)->y = v)
|
||||
#define M_SetItemText(t, n, s) (M_GetMenuItem(t, n)->text = s)
|
||||
#define M_GetItemX(t, n) (M_GetMenuItem(t, n)->x)
|
||||
#define M_GetItemY(t, n) (M_GetMenuItem(t, n)->y)
|
||||
|
||||
static void M_ChangeItemStatus(menutype_t type, const char *name, UINT16 flag, boolean cond)
|
||||
|
|
@ -7744,6 +7746,352 @@ INT32 MR_HandleMonitorToggles(INT32 choice)
|
|||
return true;
|
||||
}
|
||||
|
||||
INT32 MR_QuitViewServer(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean viewserver_showaddons = false;
|
||||
static INT32 viewserver_scroll = 0;
|
||||
static INT16 viewserver_animcount = 8;
|
||||
|
||||
INT32 MR_HandleViewServer(INT32 choice)
|
||||
{
|
||||
switch (choice)
|
||||
{
|
||||
case KEY_ENTER:
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
ChangeClientMode(CL_CHECKFILES);
|
||||
M_ClearMenus(false);
|
||||
return true;
|
||||
break;
|
||||
|
||||
case KEY_SPACE:
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
viewserver_showaddons = !viewserver_showaddons;
|
||||
return true;
|
||||
break;
|
||||
|
||||
case KEY_UPARROW:
|
||||
case KEY_DOWNARROW:
|
||||
if (viewserver_showaddons && fileneedednum > 22)
|
||||
{
|
||||
if (choice == KEY_UPARROW)
|
||||
viewserver_scroll -= 1;
|
||||
else if (choice == KEY_DOWNARROW)
|
||||
viewserver_scroll += 1;
|
||||
S_StartSound(NULL, sfx_menu1);
|
||||
if (viewserver_scroll < 0) viewserver_scroll = 0;
|
||||
if (viewserver_scroll >= fileneedednum - 22) viewserver_scroll = fileneedednum -22;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void M_DrawViewServer(void)
|
||||
{
|
||||
UINT32 ping = (UINT32)serverlist[joinnode].info.time;
|
||||
UINT8 kartvars = serverlist[joinnode].info.kartvars;
|
||||
const char *speedstring = "Auto";
|
||||
const char *serverstring = "Listen";
|
||||
const char *maptitle = serverlist[joinnode].info.maptitle;
|
||||
INT32 mapnum = G_LevelTitleToMapNum(maptitle);
|
||||
patch_t *current_map;
|
||||
|
||||
V_DrawFill(M_GetItemX(MN_VIEWSERVER, "TOPBOXXY"), M_GetItemY(MN_VIEWSERVER, "TOPBOXXY"), M_GetItemX(MN_VIEWSERVER, "TOPBOXWH"), M_GetItemY(MN_VIEWSERVER, "TOPBOXWH"), 159);
|
||||
|
||||
V_DrawThinString(M_GetItemX(MN_VIEWSERVER, "SERVERNAME"), M_GetItemY(MN_VIEWSERVER, "SERVERNAME"), V_ALLOWLOWERCASE, va("%s", serverlist[joinnode].info.servername));
|
||||
|
||||
if (mapnum == INT32_MIN)
|
||||
{
|
||||
V_DrawSmallScaledPatch(10, 18, 0, W_CachePatchName("RANDOMLV", PU_CACHE));
|
||||
}
|
||||
else
|
||||
{
|
||||
fixed_t scale = M_GetMapThumbnail(mapnum, ¤t_map)/4;
|
||||
V_DrawFixedPatch(10<<FRACBITS, 18<<FRACBITS, scale, 0, current_map, NULL);
|
||||
}
|
||||
|
||||
switch (kartvars & SV_SPEEDMASK)
|
||||
{
|
||||
case KARTSPEED_EASY:
|
||||
speedstring = "Easy";
|
||||
break;
|
||||
case KARTSPEED_NORMAL:
|
||||
speedstring = "Normal";
|
||||
break;
|
||||
case KARTSPEED_HARD:
|
||||
speedstring = "Hard";
|
||||
break;
|
||||
}
|
||||
|
||||
if (kartvars & SV_DEDICATED)
|
||||
{
|
||||
serverstring = "Dedicated";
|
||||
}
|
||||
|
||||
V_DrawThinString(M_GetItemX(MN_VIEWSERVER, "SERVERPING"), M_GetItemY(MN_VIEWSERVER, "SERVERPING"), V_ALLOWLOWERCASE, va("Ping: %s%ums", (ping < 128 ? "\x83" : (ping < 256 ? "\x82" : "\x85")), ping));
|
||||
V_DrawThinString(M_GetItemX(MN_VIEWSERVER, "SERVERMAP"), M_GetItemY(MN_VIEWSERVER, "SERVERMAP"), V_ALLOWLOWERCASE, va("%s", serverlist[joinnode].info.maptitle));
|
||||
V_DrawThinString(M_GetItemX(MN_VIEWSERVER, "SERVERGAMETYPE"), M_GetItemY(MN_VIEWSERVER, "SERVERGAMETYPE"), V_ALLOWLOWERCASE, va("%s: %s", serverlist[joinnode].info.gametypename, speedstring));
|
||||
|
||||
if (fileneedednum > 0)
|
||||
{
|
||||
V_DrawThinString(M_GetItemX(MN_VIEWSERVER, "SERVERADDON"), M_GetItemY(MN_VIEWSERVER, "SERVERADDON"), V_ALLOWLOWERCASE|warningflags, va("%i Addons", fileneedednum));
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawThinString(M_GetItemX(MN_VIEWSERVER, "SERVERADDON"), M_GetItemY(MN_VIEWSERVER, "SERVERADDON"), V_ALLOWLOWERCASE|highlightflags, "Vanilla");
|
||||
}
|
||||
|
||||
if (serverlist[joinnode].info.cheatsenabled)
|
||||
{
|
||||
V_DrawRightAlignedThinString(M_GetItemX(MN_VIEWSERVER, "SERVERCHEATS"), M_GetItemY(MN_VIEWSERVER, "SERVERCHEATS"), V_ALLOWLOWERCASE|recommendedflags, "Cheats");
|
||||
}
|
||||
|
||||
V_DrawRightAlignedThinString(M_GetItemX(MN_VIEWSERVER, "SERVERDEDICATED"), M_GetItemY(MN_VIEWSERVER, "SERVERDEDICATED"), V_ALLOWLOWERCASE|recommendedflags, va("%s Server", serverstring));
|
||||
|
||||
V_DrawFill(M_GetItemX(MN_VIEWSERVER, "MIDBOXXY"), M_GetItemY(MN_VIEWSERVER, "MIDBOXXY"), M_GetItemX(MN_VIEWSERVER, "MIDBOXWH"), M_GetItemY(MN_VIEWSERVER, "MIDBOXWH"), 159);
|
||||
|
||||
if (!viewserver_showaddons)
|
||||
{
|
||||
INT32 i;
|
||||
INT32 count = 0;
|
||||
INT32 x = 14;
|
||||
INT32 y = 84;
|
||||
char player_name[MAXPLAYERNAME+1];
|
||||
plrinfo *playerinfo = netbuffer->u.playerinfo;
|
||||
UINT8 playeramount = serverlist[joinnode].info.numberofplayer;
|
||||
UINT8 maxplayer = serverlist[joinnode].info.maxplayer;
|
||||
|
||||
V_DrawString(12, 74, V_ALLOWLOWERCASE|highlightflags, "Players");
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH - 12, 74, V_ALLOWLOWERCASE|highlightflags, va("%i / %i", playeramount, maxplayer));
|
||||
|
||||
if (playeramount > 0)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playerinfo[i].num < 255)
|
||||
{
|
||||
if (playeramount <= 16)
|
||||
{
|
||||
UINT8 skinum = playerinfo[i].skin;
|
||||
INT32 flags = 0;
|
||||
|
||||
if (R_SkinAvailable(skins[skinum].name) == -1)
|
||||
{
|
||||
INT32 statuscolor = 1;
|
||||
|
||||
if (playerinfo[i].team == 0) { statuscolor = 112; } // playing
|
||||
if (playerinfo[i].team == 1) { statuscolor = 35; } // ctf red team
|
||||
if (playerinfo[i].team == 2) { statuscolor = 152; } // ctf blue team
|
||||
if (playerinfo[i].team == 255) { statuscolor = 16; flags |= V_40TRANS; } // spectator or non-team
|
||||
|
||||
V_DrawFill(x, y+5, 16, 16, statuscolor);
|
||||
}
|
||||
else
|
||||
{
|
||||
patch_t *facerank = faceprefix[skinum][FACE_RANK];
|
||||
UINT8 *colormap = R_GetTranslationColormap(skinum, skins[skinum].prefcolor, GTC_MENUCACHE);
|
||||
|
||||
if (playerinfo[i].team == 255)
|
||||
{
|
||||
colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GREY, GTC_MENUCACHE);
|
||||
flags |= V_40TRANS;
|
||||
}
|
||||
|
||||
|
||||
V_DrawFixedPatch(x<<FRACBITS, (y+5)<<FRACBITS, FRACUNIT, flags, facerank, colormap);
|
||||
}
|
||||
|
||||
strlcpy(player_name, playerinfo[i].name, 12);
|
||||
V_DrawThinString(x + 20, y + 3 + 5, flags|V_ALLOWLOWERCASE|V_6WIDTHSPACE, player_name);
|
||||
|
||||
y += 22;
|
||||
count++;
|
||||
if ((count == 4) || (count == 8) || (count == 12))
|
||||
{
|
||||
x += 74;
|
||||
y = 84;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
INT32 statuscolor = 1;
|
||||
|
||||
strlcpy(player_name, playerinfo[i].name, 12);
|
||||
V_DrawThinString(x + 10, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE, player_name);
|
||||
|
||||
if (playerinfo[i].team == 0) { statuscolor = 112; } // playing
|
||||
if (playerinfo[i].team == 1) { statuscolor = 35; } // ctf red team
|
||||
if (playerinfo[i].team == 2) { statuscolor = 152; } // ctf blue team
|
||||
if (playerinfo[i].team == 255) { statuscolor = 16; } // spectator or non-team
|
||||
|
||||
V_DrawFill(x, y, 7, 7, 31);
|
||||
V_DrawFill(x, y, 6, 6, statuscolor);
|
||||
|
||||
y += 9;
|
||||
count++;
|
||||
if ((count == 11) || (count == 22))
|
||||
{
|
||||
x += 104;
|
||||
y = 84;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
INT32 i;
|
||||
INT32 count = 0;
|
||||
INT32 x = 14;
|
||||
INT32 y = 84;
|
||||
boolean small_mode = fileneedednum <= 11;
|
||||
char file_name[MAX_WADPATH+1];
|
||||
|
||||
V_DrawString(12, 74, V_ALLOWLOWERCASE|highlightflags, "Addons");
|
||||
|
||||
#define maxcharlen (20 + 3) // 3 for the 3 dots
|
||||
#define charsonside 10
|
||||
|
||||
for (i = viewserver_scroll; i < fileneedednum; i++)
|
||||
{
|
||||
if (i & 1)
|
||||
V_DrawFill(x,y-1,
|
||||
(small_mode) ? 292 : 146, 9,
|
||||
156
|
||||
);
|
||||
|
||||
fileneeded_t addon_file = fileneeded[i];
|
||||
strncpy(file_name, addon_file.filename, MAX_WADPATH);
|
||||
if ((UINT8)(strlen(file_name)+1) > maxcharlen && !small_mode)
|
||||
V_DrawThinString(x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE,
|
||||
va("\x82[#%d]\x80: %.*s...%s",i+1, charsonside, file_name, file_name+strlen(file_name)-((charsonside+1)))
|
||||
);
|
||||
else
|
||||
{
|
||||
V_DrawThinString(x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE,
|
||||
va("\x82[#%d]\x80: %s",i+1, file_name)
|
||||
);
|
||||
|
||||
// make sure we have the space
|
||||
if (small_mode)
|
||||
{
|
||||
float file_size = ((float)addon_file.totalsize);
|
||||
UINT8 size_mode = 0; // regular bytes
|
||||
//in megabytes
|
||||
if (file_size >= (1024.0f * 1024.0f))
|
||||
{
|
||||
size_mode = 1;
|
||||
file_size /= (1024.0f * 1024.0f);
|
||||
}
|
||||
// KB
|
||||
else if (file_size >= 1024.0f)
|
||||
{
|
||||
size_mode = 2;
|
||||
file_size /= 1024.0f;
|
||||
}
|
||||
|
||||
V_DrawRightAlignedThinString(x + 292,
|
||||
y, highlightflags|V_ALLOWLOWERCASE,
|
||||
// "~" since its approx this size, we mightve lost some
|
||||
// accuracy from only having 4 bytes carry the size
|
||||
va("(~%.1f%s)", file_size, size_mode == 0 ? "b" : (size_mode == 2 ? "kb" : "mb"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
y += 9;
|
||||
count++;
|
||||
if (count == 11)
|
||||
{
|
||||
x = BASEVIDWIDTH/2;
|
||||
y = 84;
|
||||
}
|
||||
// Cannot draw any more
|
||||
if (count == 22)
|
||||
break;
|
||||
}
|
||||
|
||||
// reiterate again!!! Yes!!! Yay!!!
|
||||
{
|
||||
UINT32 totalsize = 0;
|
||||
UINT8 size_mode = 0; // regular bytes
|
||||
|
||||
for (INT32 j = 0; j < fileneedednum; j++)
|
||||
totalsize += fileneeded[j].totalsize;
|
||||
totalsize = (float)totalsize;
|
||||
|
||||
//in megabytes
|
||||
if (totalsize >= (1024.0f * 1024.0f))
|
||||
{
|
||||
size_mode = 1;
|
||||
totalsize /= (1024.0f * 1024.0f);
|
||||
}
|
||||
// KB
|
||||
else if (totalsize >= 1024.0f)
|
||||
{
|
||||
size_mode = 2;
|
||||
totalsize /= 1024.0f;
|
||||
}
|
||||
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH - 22, 74,
|
||||
V_ALLOWLOWERCASE|highlightflags,
|
||||
va("~%.1f%s total", (float)totalsize, size_mode == 0 ? "b" : (size_mode == 2 ? "kb" : "mb"))
|
||||
);
|
||||
}
|
||||
|
||||
// draw the little arrows
|
||||
if (fileneedednum >= 22)
|
||||
{
|
||||
// up arrow
|
||||
if (viewserver_scroll)
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH - 12,
|
||||
74 - (viewserver_animcount/5), highlightflags,
|
||||
"\x1A"
|
||||
);
|
||||
|
||||
if (viewserver_scroll != fileneedednum-22)
|
||||
V_DrawRightAlignedThinString(BASEVIDWIDTH - 12,
|
||||
y-9 + (viewserver_animcount/5), highlightflags,
|
||||
"\x1B"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#undef maxcharlen
|
||||
#undef charsonside
|
||||
|
||||
// Buttons
|
||||
V_DrawFill(8, BASEVIDHEIGHT - 14, BASEVIDWIDTH - 16, 13, 159);
|
||||
V_DrawThinString(
|
||||
16, BASEVIDHEIGHT - 11,
|
||||
V_ALLOWLOWERCASE, "[""\x82""ESC""\x80""] = Return"
|
||||
);
|
||||
|
||||
V_DrawCenteredThinString(
|
||||
BASEVIDWIDTH/2, BASEVIDHEIGHT - 11,
|
||||
V_ALLOWLOWERCASE,
|
||||
va("[""\x82""SPACE""\x80""] = %s", (viewserver_showaddons ? "Players" : "Addons"))
|
||||
);
|
||||
|
||||
V_DrawRightAlignedThinString(
|
||||
BASEVIDWIDTH - 12, BASEVIDHEIGHT - 11,
|
||||
V_ALLOWLOWERCASE, "[""\x82""ENTER""\x80""] = Join"
|
||||
);
|
||||
}
|
||||
|
||||
// =========
|
||||
// Quit Game
|
||||
// =========
|
||||
|
|
|
|||
|
|
@ -312,6 +312,8 @@ INT32 MR_ChangeControl(INT32 arg);
|
|||
INT32 MR_AssignJoystick(INT32 arg);
|
||||
INT32 MR_HandleMonitorToggles(INT32 choice);
|
||||
INT32 MR_RestartAudio(INT32 choice);
|
||||
INT32 MR_QuitViewServer(INT32 choice);
|
||||
INT32 MR_HandleViewServer(INT32 choice);
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
INT32 MR_HandleDiscordRequests(INT32 choice);
|
||||
#endif
|
||||
|
|
@ -338,6 +340,7 @@ void M_DrawMusicTest(void);
|
|||
void M_DrawControl(void);
|
||||
void M_DrawJoystick(void);
|
||||
void M_DrawMonitorToggles(void);
|
||||
void M_DrawViewServer(void);
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
void M_DrawDiscordRequests(void);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue