rpgxef/code/ui/ui_servers2.c
Walter Julius 'GSIO01' Hennecke f8eab147d4 Fixed some things ...
- fixed some insecure code
- fixed alot of warnings
2012-09-10 21:26:13 +02:00

2176 lines
59 KiB
C

// Copyright (C) 1999-2000 Id Software, Inc.
//
/*
=======================================================================
MULTIPLAYER MENU (SERVER BROWSER)
=======================================================================
*/
#include "ui_local.h"
static menubitmap_s s_find_server;
static menubitmap_s s_specific_server;
static menubitmap_s s_create_server;
#define RPGX_SERVERNAME "RPG-X2"
#define MAX_GLOBALSERVERS 256
#define MAX_PINGREQUESTS 16
#define MAX_ADDRESSLENGTH 64
#define MAX_HOSTNAMELENGTH 64
#define MAX_MAPNAMELENGTH 30
#define MAX_LISTBOXITEMS 256
#define MAX_LOCALSERVERS 256
#define MAX_STATUSLENGTH 64
#define MAX_LISTBOXWIDTH 67
#define ART_UNKNOWNMAP "levelshots/unknownmap"
#define ID_MASTER 10
#define ID_GAMETYPE 11
#define ID_SORTKEY 12
#define ID_SHOW_FULL 13
#define ID_SHOW_EMPTY 14
#define ID_LIST 15
#define ID_SCROLL_UP 16
#define ID_SCROLL_DOWN 17
#define ID_BACK 18
#define ID_REFRESH 19
#define ID_SPECIFY 20
#define ID_CREATE 21
#define ID_CONNECT 22
#define ID_REMOVE 23
#define ID_STOPREFRESH 24
#define ID_FINDSERVER 25
#define ID_FAVORITE 26
#define ID_MAINMENU 100
#define AS_LOCAL 0
//#define AS_MPLAYER 1
#define AS_GLOBAL1 1
#define AS_GLOBAL2 2
#define AS_GLOBAL3 3
#define AS_GLOBAL4 4
#define AS_GLOBAL5 5
#define AS_FAVORITES 6
#define SORT_HOST 0
#define SORT_MAP 1
#define SORT_CLIENTS 2
#define SORT_GAME 3
#define SORT_PING 4
/*#define GAMES_ALL 0
#define GAMES_FFA 1
#define GAMES_TEAMPLAY 2
#define GAMES_TOURNEY 3
#define GAMES_CTF 4
#define GAMES_EXCESSIVE 5
#define GAMES_FEDERATION 6
#define GAMES_GLADIATOR 7
#define GAMES_IN2TAGIB 8
#define GAMES_PINBALL 9
#define GAMES_Q32EF 10
#define GAMES_RPG 11
#define GAMES_TEAMELITE 12
#define GAMES_RPGX 13*/
#define GAMES_ALL 0
#define GAMES_RPGX 1
#define GAMES_FFA 2
#define GAMES_TEAMPLAY 3
#define GAMES_TOURNEY 4
#define GAMES_CTF 5
/*
static const char *master_items[] = {
"Local",
"Mplayer",
"Internet",
"Favorites",
0
};
static const char *servertype_items[] = {
"All",
"Free For All",
"Team Deathmatch",
"Tournament",
"Capture the Flag",
0
};
static const char *sortkey_items[] = {
"Server Name",
"Map Name",
"Open Player Spots",
"Game Type",
"Ping Time",
0
};
*/
static int master_items[] =
{
MNT_MASTER_ITEMS_LOCAL,
// MNT_MASTER_ITEMS_MPLAYER,
MNT_MASTER_ITEMS_INTERNET1,
MNT_MASTER_ITEMS_INTERNET2,
MNT_MASTER_ITEMS_INTERNET3,
MNT_MASTER_ITEMS_INTERNET4,
MNT_MASTER_ITEMS_INTERNET5,
MNT_MASTER_ITEMS_FAVORITES,
0
};
static int servertype_items[] =
{
MNT_SERVERTYPE_ALL,
MNT_SERVERTYPE_RPGX,
MNT_SERVERTYPE_FREE_FOR_ALL,
MNT_SERVERTYPE_TEAM_DEATHMATCH,
MNT_SERVERTYPE_TOURNAMENT,
MNT_SERVERTYPE_CAPTURETHEFLAG,
/*MNT_SERVERTYPE_EXCESSIVE,
MNT_SERVERTYPE_FEDERATION,
MNT_SERVERTYPE_GLADIATOR,
MNT_SERVERTYPE_IN2TAGIB,
MNT_SERVERTYPE_PINBALL,
MNT_SERVERTYPE_Q32EF,
MNT_SERVERTYPE_RPG,
MNT_SERVERTYPE_TEAMELITE,*/
0
};
static int sortkey_items[] =
{
MNT_SORTKEY_SERVER_NAME,
MNT_SORTKEY_MAP_NAME,
MNT_SORTKEY_OPENPLAYER,
MNT_SORTKEY_GAMETYPE,
MNT_SORTKEY_PINGTIME,
0
};
static int noyes_items[] =
{
MNT_NO,
MNT_YES,
0
};
static float server_buttons[5][2] =
{
{274, 72}, // Server type
{274, 92}, // Sort by
{274,112}, // Game Type
{274,132}, // All
{274,152}, // Empty
};
char* gamenames[] = {
"DM ", // deathmatch
"1v1", // tournament
"SP ", // single player
"TDM", // team deathmatch
"CTF", // capture the flag
/*"EXCESSIVE",
"FEDERATION",
"GLADIATOR",
"IN2TAGIB",
"PINBALL",
"Q32EF",
"RPG",
"TEAMELITE",
"RPG-X", //The best gametype of them all ;)*/
"???",
};
static char* netnames[] = {
"???",
"UDP",
"IPX",
NULL
};
static char quake3worldMessage[] = "For more information, please visit : www.rpg-x.net www.ravensoft.com/eliteforce www.startrek.com";
typedef struct {
char adrstr[MAX_ADDRESSLENGTH];
int start;
} pinglist_t;
typedef struct servernode_s {
char adrstr[MAX_ADDRESSLENGTH];
char hostname[MAX_HOSTNAMELENGTH];
char mapname[MAX_MAPNAMELENGTH];
int numclients;
int maxclients;
int pingtime;
int gametype;
char gamename[12];
int nettype;
int minPing;
int maxPing;
qboolean isPure;
qboolean isExpansion;
} servernode_t;
typedef struct {
char buff[MAX_LISTBOXWIDTH];
servernode_t* servernode;
} table_t;
typedef struct {
menuframework_s menu;
menubitmap_s mainmenu;
menubitmap_s back;
menulist_s master;
menulist_s gametype;
menulist_s sortkey;
menulist_s showfull;
menulist_s showempty;
menulist_s list;
menubitmap_s mappic;
menubitmap_s arrows;
menubitmap_s up;
menubitmap_s down;
menutext_s status;
menutext_s statusbar;
menubitmap_s remove;
menubitmap_s refresh;
menubitmap_s stoprefresh;
menubitmap_s go;
menubitmap_s favorite;
pinglist_t pinglist[MAX_PINGREQUESTS];
table_t table[MAX_LISTBOXITEMS];
char* items[MAX_LISTBOXITEMS];
int numqueriedservers;
int *numservers;
servernode_t *serverlist;
int currentping;
qboolean refreshservers;
int nextpingtime;
int maxservers;
int refreshtime;
char favoriteaddresses[MAX_FAVORITESERVERS][MAX_ADDRESSLENGTH];
int numfavoriteaddresses;
} arenaservers_t;
static arenaservers_t g_arenaservers;
typedef struct
{
menuframework_s menu;
menubitmap_s main;
} chooseservertype_t;
static chooseservertype_t g_chooseservertype;
static servernode_t g_globalserverlist[MAX_GLOBALSERVERS];
static int g_numglobalservers;
static servernode_t g_localserverlist[MAX_LOCALSERVERS];
static int g_numlocalservers;
static servernode_t g_favoriteserverlist[MAX_FAVORITESERVERS];
static int g_numfavoriteservers;
//static servernode_t g_mplayerserverlist[MAX_GLOBALSERVERS];
//static int g_nummplayerservers;
static int g_servertype;
static int g_gametype;
static int g_sortkey;
static int g_emptyservers;
static int g_fullservers;
/*
=================
ArenaServers_MaxPing
=================
*/
int ArenaServers_MaxPing( void ) { /*static*/
int maxPing;
maxPing = (int)trap_Cvar_VariableValue( "cl_maxPing" );
if( maxPing < 100 ) {
maxPing = 100;
}
return maxPing;
}
/*
=================
ArenaServers_Compare
=================
*/
static int QDECL ArenaServers_Compare( const void *arg1, const void *arg2 ) {
float f1;
float f2;
servernode_t* t1;
servernode_t* t2;
t1 = (servernode_t *)arg1;
t2 = (servernode_t *)arg2;
switch( g_sortkey ) {
case SORT_HOST:
return Q_stricmp( t1->hostname, t2->hostname );
case SORT_MAP:
return Q_stricmp( t1->mapname, t2->mapname );
case SORT_CLIENTS:
f1 = t1->maxclients - t1->numclients;
if( f1 < 0 ) {
f1 = 0;
}
f2 = t2->maxclients - t2->numclients;
if( f2 < 0 ) {
f2 = 0;
}
if( f1 < f2 ) {
return 1;
}
if( f1 == f2 ) {
return 0;
}
return -1;
case SORT_GAME:
if( t1->gametype < t2->gametype ) {
return -1;
}
if( t1->gametype == t2->gametype ) {
return 0;
}
return 1;
case SORT_PING:
if( t1->pingtime < t2->pingtime ) {
return -1;
}
if( t1->pingtime > t2->pingtime ) {
return 1;
}
return Q_stricmp( t1->hostname, t2->hostname );
}
return 0;
}
/*
=================
ArenaServers_Go
=================
*/
static void ArenaServers_Go( void ) {
servernode_t* servernode;
servernode = g_arenaservers.table[g_arenaservers.list.curvalue].servernode;
if( servernode ) {
trap_Cmd_ExecuteText( EXEC_APPEND, va( "connect %s\n", servernode->adrstr ) );
}
}
/*
=================
ArenaServers_UpdatePicture
=================
*/
static void ArenaServers_UpdatePicture( void ) {
static char picname[64];
servernode_t* servernodeptr;
qhandle_t hpic;
if( !g_arenaservers.list.numitems ) {
g_arenaservers.mappic.generic.name = NULL;
}
else {
servernodeptr = g_arenaservers.table[g_arenaservers.list.curvalue].servernode;
hpic = trap_R_RegisterShaderNoMip( va("levelshots/%s.tga", servernodeptr->mapname) );
if (!hpic)
{
Com_sprintf( picname, sizeof(picname), "levelshots/unknownmap.tga" );
}
else
{
Com_sprintf( picname, sizeof(picname), "levelshots/%s.tga", servernodeptr->mapname );
}
g_arenaservers.mappic.generic.name = picname;
}
// force shader update during draw
g_arenaservers.mappic.shader = 0;
}
/*
=================
ArenaServers_UpdateMenu
=================
*/
static void ArenaServers_UpdateMenu( void ) {
int i;
int j;
int count;
char* buff;
servernode_t* servernodeptr;
table_t* tableptr;
char *pingColor, *pongColor;
if( g_arenaservers.numqueriedservers > 0 ) {
// servers found
if( g_arenaservers.refreshservers && ( g_arenaservers.currentping <= g_arenaservers.numqueriedservers ) ) {
// show progress
Com_sprintf( g_arenaservers.status.string, MAX_STATUSLENGTH, menu_normal_text[MNT_CNT_SERVERS], g_arenaservers.currentping, g_arenaservers.numqueriedservers);
g_arenaservers.statusbar.string = (char*)menu_normal_text[MNT_SPACETOSTOP];
qsort( g_arenaservers.serverlist, *g_arenaservers.numservers, sizeof( servernode_t ), ArenaServers_Compare);
}
else {
// all servers pinged - enable controls
g_arenaservers.master.generic.flags &= ~QMF_GRAYED;
g_arenaservers.gametype.generic.flags &= ~QMF_GRAYED;
g_arenaservers.sortkey.generic.flags &= ~QMF_GRAYED;
g_arenaservers.showempty.generic.flags &= ~QMF_GRAYED;
g_arenaservers.showfull.generic.flags &= ~QMF_GRAYED;
g_arenaservers.list.generic.flags &= ~QMF_GRAYED;
g_arenaservers.refresh.generic.flags &= ~QMF_GRAYED;
g_arenaservers.go.generic.flags &= ~QMF_GRAYED;
// update status bar
if(( g_servertype >= AS_GLOBAL1) && ( g_servertype <= AS_GLOBAL5))
{
g_arenaservers.statusbar.string = quake3worldMessage;
}
else
{
g_arenaservers.statusbar.string = "";
}
}
}
else {
// no servers found
if( g_arenaservers.refreshservers )
{
strcpy( g_arenaservers.status.string,menu_normal_text[MNT_SCANNINGFORSERVERS] );
g_arenaservers.statusbar.string = (char*)menu_normal_text[MNT_SPACETOSTOP];
// disable controls during refresh
g_arenaservers.master.generic.flags |= QMF_GRAYED;
g_arenaservers.gametype.generic.flags |= QMF_GRAYED;
g_arenaservers.sortkey.generic.flags |= QMF_GRAYED;
g_arenaservers.showempty.generic.flags |= QMF_GRAYED;
g_arenaservers.showfull.generic.flags |= QMF_GRAYED;
g_arenaservers.list.generic.flags |= QMF_GRAYED;
g_arenaservers.refresh.generic.flags |= QMF_GRAYED;
g_arenaservers.go.generic.flags |= QMF_GRAYED;
g_arenaservers.statusbar.string = (char*)menu_normal_text[MNT_ACCESSING];
}
else {
if( g_arenaservers.numqueriedservers < 0 ) {
strcpy(g_arenaservers.status.string,menu_normal_text[MNT_NORESPONSE_MASTER] );
}
else {
strcpy(g_arenaservers.status.string,menu_normal_text[MNT_NO_SERVERS] );
}
// update status bar
if(( g_servertype >= AS_GLOBAL1) && ( g_servertype <= AS_GLOBAL5))
{
g_arenaservers.statusbar.string = quake3worldMessage;
}
else {
g_arenaservers.statusbar.string = "";
}
// end of refresh - set control state
g_arenaservers.master.generic.flags &= ~QMF_GRAYED;
g_arenaservers.gametype.generic.flags &= ~QMF_GRAYED;
g_arenaservers.sortkey.generic.flags &= ~QMF_GRAYED;
g_arenaservers.showempty.generic.flags &= ~QMF_GRAYED;
g_arenaservers.showfull.generic.flags &= ~QMF_GRAYED;
g_arenaservers.list.generic.flags |= QMF_GRAYED;
g_arenaservers.refresh.generic.flags &= ~QMF_GRAYED;
g_arenaservers.go.generic.flags |= QMF_GRAYED;
}
// zero out list box
g_arenaservers.list.numitems = 0;
g_arenaservers.list.curvalue = 0;
g_arenaservers.list.top = 0;
// update picture
ArenaServers_UpdatePicture();
return;
}
// build list box strings - apply culling filters
servernodeptr = g_arenaservers.serverlist;
count = *g_arenaservers.numservers;
for( i = 0, j = 0; i < count; i++, servernodeptr++ ) {
tableptr = &g_arenaservers.table[j];
tableptr->servernode = servernodeptr;
buff = tableptr->buff;
if( !g_emptyservers && !servernodeptr->numclients ) {
continue;
}
if( !g_fullservers && ( servernodeptr->numclients == servernodeptr->maxclients ) ) {
continue;
}
switch( g_gametype ) {
case GAMES_ALL:
break;
case GAMES_FFA:
if( servernodeptr->gametype != GT_FFA ) {
continue;
}
break;
case GAMES_TEAMPLAY:
if( servernodeptr->gametype != GT_TEAM ) {
continue;
}
break;
case GAMES_TOURNEY:
if( servernodeptr->gametype != GT_TOURNAMENT ) {
continue;
}
break;
case GAMES_CTF:
if( servernodeptr->gametype != GT_CTF ) {
continue;
}
break;
/*case GAMES_EXCESSIVE:
if( Q_stricmp(servernodeptr->gamename, "excessive") ) {
continue;
}
break;
case GAMES_FEDERATION:
if( Q_stricmp(servernodeptr->gamename, "federation") ) {
continue;
}
break;
case GAMES_GLADIATOR:
if( Q_stricmp(servernodeptr->gamename, "gladiator") ) {
continue;
}
break;
case GAMES_IN2TAGIB:
if( Q_stricmp(servernodeptr->gamename, "in2tagib") ) {
continue;
}
break;
case GAMES_PINBALL:
if( Q_stricmp(servernodeptr->gamename, "pinball") ) {
continue;
}
break;
case GAMES_Q32EF:
if( Q_stricmp(servernodeptr->gamename, "q32ef") ) {
continue;
}
break;
case GAMES_RPG:
if( Q_stricmp(servernodeptr->gamename, "rpg") ) {
continue;
}
break;
case GAMES_TEAMELITE:
if( Q_stricmp(servernodeptr->gamename, "teamelite") ) {
continue;
}
break;*/
case GAMES_RPGX:
if( Q_stricmp(servernodeptr->gamename, RPGX_SERVERNAME ) ) {
continue;
}
break;
}
if( servernodeptr->pingtime < servernodeptr->minPing ) {
pingColor = S_COLOR_BLUE;
}
else if( servernodeptr->maxPing && servernodeptr->pingtime > servernodeptr->maxPing ) {
pingColor = S_COLOR_BLUE;
}
else if( servernodeptr->pingtime < 50 ) {
pingColor = S_COLOR_WHITE;
}
else if( servernodeptr->pingtime < 200 ) {
pingColor = S_COLOR_GREEN;
}
else if( servernodeptr->pingtime < 400 ) {
pingColor = S_COLOR_YELLOW;
}
else {
pingColor = S_COLOR_RED;
}
pongColor = S_COLOR_WHITE;
Com_sprintf( buff, MAX_LISTBOXWIDTH, "%s%-31.31s %s%-11.11s %2d/%2d %-8.8s %3d", //31.31
pongColor, servernodeptr->hostname, pingColor, servernodeptr->mapname, servernodeptr->numclients,
servernodeptr->maxclients, servernodeptr->gamename, servernodeptr->pingtime);
if (!servernodeptr->isPure) { //prev length is 62, we can safely add 2 more chars.
strcat(buff, "*"); //mark this unpure server!
}
j++;
}
// Com_sprintf( g_arenaservers.status.string, MAX_STATUSLENGTH, "%d of %d Arena Servers.", j, *g_arenaservers.numservers );
g_arenaservers.list.numitems = j;
g_arenaservers.list.curvalue = 0;
g_arenaservers.list.top = 0;
if (!g_arenaservers.list.numitems)
{
g_arenaservers.go.generic.flags |= QMF_GRAYED;
}
// update picture
ArenaServers_UpdatePicture();
}
/*
=================
ArenaServers_Remove
=================
*/
static void ArenaServers_Remove( void )
{
int i;
servernode_t* servernodeptr;
table_t* tableptr;
if (!g_arenaservers.list.numitems)
return;
// remove selected item from display list
// items are in scattered order due to sort and cull
// perform delete on list box contents, resync all lists
tableptr = &g_arenaservers.table[g_arenaservers.list.curvalue];
servernodeptr = tableptr->servernode;
// find address in master list
for (i=0; i<g_arenaservers.numfavoriteaddresses; i++)
if (!Q_stricmp(g_arenaservers.favoriteaddresses[i],servernodeptr->adrstr))
break;
// delete address from master list
if (i <= g_arenaservers.numfavoriteaddresses-1)
{
if (i < g_arenaservers.numfavoriteaddresses-1)
{
// shift items up
memcpy( &g_arenaservers.favoriteaddresses[i], &g_arenaservers.favoriteaddresses[i+1], (g_arenaservers.numfavoriteaddresses - i - 1)*sizeof(MAX_ADDRESSLENGTH));
}
g_arenaservers.numfavoriteaddresses--;
}
// find address in server list
for (i=0; i<g_numfavoriteservers; i++)
if (&g_favoriteserverlist[i] == servernodeptr)
break;
// delete address from server list
if (i <= g_numfavoriteservers-1)
{
if (i < g_numfavoriteservers-1)
{
// shift items up
memcpy( &g_favoriteserverlist[i], &g_favoriteserverlist[i+1], (g_numfavoriteservers - i - 1)*sizeof(servernode_t));
}
g_numfavoriteservers--;
}
g_arenaservers.numqueriedservers = g_arenaservers.numfavoriteaddresses;
g_arenaservers.currentping = g_arenaservers.numfavoriteaddresses;
}
/*
=================
ArenaServers_Insert
=================
*/
static void ArenaServers_Insert( char* adrstr, char* info, int pingtime )
{
servernode_t* servernodeptr;
char* s;
int i;
if ((pingtime >= ArenaServers_MaxPing()) && (g_servertype != AS_FAVORITES))
{
// slow global or local servers do not get entered
return;
}
if (*g_arenaservers.numservers >= g_arenaservers.maxservers) {
// list full;
servernodeptr = g_arenaservers.serverlist+(*g_arenaservers.numservers)-1;
} else {
// next slot
servernodeptr = g_arenaservers.serverlist+(*g_arenaservers.numservers);
(*g_arenaservers.numservers)++;
}
Q_strncpyz( servernodeptr->adrstr, adrstr, MAX_ADDRESSLENGTH );
Q_strncpyz( servernodeptr->hostname, Info_ValueForKey( info, "hostname"), MAX_HOSTNAMELENGTH );
Q_CleanStr( servernodeptr->hostname );
Q_CleanStr( servernodeptr->hostname );
Q_CleanStr( servernodeptr->hostname );
Q_CleanStr( servernodeptr->hostname );
Q_strncpyz( servernodeptr->mapname, Info_ValueForKey( info, "mapname"), MAX_MAPNAMELENGTH );
Q_CleanStr( servernodeptr->mapname );
Q_strlwr( servernodeptr->mapname );
servernodeptr->numclients = atoi( Info_ValueForKey( info, "clients") );
servernodeptr->maxclients = atoi( Info_ValueForKey( info, "sv_maxclients") );
servernodeptr->pingtime = pingtime;
servernodeptr->minPing = atoi( Info_ValueForKey( info, "minPing") );
servernodeptr->maxPing = atoi( Info_ValueForKey( info, "maxPing") );
servernodeptr->isPure = atoi( Info_ValueForKey( info, "pure") );
servernodeptr->isExpansion= atoi( Info_ValueForKey( info, "vv") );
s = Info_ValueForKey( info, "nettype" );
for (i=0; ;i++)
{
if (!netnames[i])
{
servernodeptr->nettype = 0;
break;
}
else if (!Q_stricmp( netnames[i], s ))
{
servernodeptr->nettype = i;
break;
}
}
s = Info_ValueForKey( info, "game");
i = atoi( Info_ValueForKey( info, "gametype") );
if( i < 0 ) {
i = 0;
}
else if( i > 5 ) {
i = 5;
}
if( *s ) {
servernodeptr->gametype = -1;
Q_strncpyz( servernodeptr->gamename, s, sizeof(servernodeptr->gamename) );
}
else {
servernodeptr->gametype = i;
if (servernodeptr->isExpansion) {
Com_sprintf( servernodeptr->gamename, sizeof(servernodeptr->gamename), "vv-%s",gamenames[i]);
} else {
Q_strncpyz( servernodeptr->gamename, gamenames[i], sizeof(servernodeptr->gamename) );
}
}
}
/*
=================
ArenaServers_InsertFavorites
Insert nonresponsive address book entries into display lists.
=================
*/
void ArenaServers_InsertFavorites( void )
{
int i;
int j;
char info[MAX_INFO_STRING];
// resync existing results with new or deleted cvars
info[0] = '\0';
Info_SetValueForKey( info, "hostname", "No Response" );
for (i=0; i<g_arenaservers.numfavoriteaddresses; i++)
{
// find favorite address in refresh list
for (j=0; j<g_numfavoriteservers; j++)
if (!Q_stricmp(g_arenaservers.favoriteaddresses[i],g_favoriteserverlist[j].adrstr))
break;
if ( j >= g_numfavoriteservers)
{
// not in list, add it
ArenaServers_Insert( g_arenaservers.favoriteaddresses[i], info, ArenaServers_MaxPing() );
}
}
}
/*
=================
ArenaServers_LoadFavorites
Load cvar address book entries into local lists.
=================
*/
void ArenaServers_LoadFavorites( void )
{
int i;
int j;
int numtempitems;
char adrstr[MAX_ADDRESSLENGTH];
servernode_t templist[MAX_FAVORITESERVERS];
qboolean found;
found = qfalse;
// copy the old
memcpy( templist, g_favoriteserverlist, sizeof(servernode_t)*MAX_FAVORITESERVERS );
numtempitems = g_numfavoriteservers;
// clear the current for sync
memset( g_favoriteserverlist, 0, sizeof(servernode_t)*MAX_FAVORITESERVERS );
g_numfavoriteservers = 0;
// resync existing results with new or deleted cvars
for (i=0; i<MAX_FAVORITESERVERS; i++)
{
trap_Cvar_VariableStringBuffer( va("server%d",i+1), adrstr, MAX_ADDRESSLENGTH );
if (!adrstr[0])
continue;
// quick sanity check to avoid slow domain name resolving
// first character must be numeric
if (adrstr[0] < '0' || adrstr[0] > '9')
continue;
// favorite server addresses must be maintained outside refresh list
// this mimics local and global netadr's stored in client
// these can be fetched to fill ping list
strcpy( g_arenaservers.favoriteaddresses[g_numfavoriteservers], adrstr );
// find this server in the old list
for (j=0; j<numtempitems; j++)
if (!Q_stricmp( templist[j].adrstr, adrstr ))
break;
if (j < numtempitems)
{
// found server - add exisiting results
memcpy( &g_favoriteserverlist[g_numfavoriteservers], &templist[j], sizeof(servernode_t) );
found = qtrue;
}
else
{
// add new server
Q_strncpyz( g_favoriteserverlist[g_numfavoriteservers].adrstr, adrstr, MAX_ADDRESSLENGTH );
g_favoriteserverlist[g_numfavoriteservers].pingtime = ArenaServers_MaxPing();
}
g_numfavoriteservers++;
}
g_arenaservers.numfavoriteaddresses = g_numfavoriteservers;
if (!found)
{
// no results were found, reset server list
// list will be automatically refreshed when selected
g_numfavoriteservers = 0;
}
}
/*
=================
ArenaServers_StopRefresh
=================
*/
static void ArenaServers_StopRefresh( void )
{
if (!g_arenaservers.refreshservers)
// not currently refreshing
return;
g_arenaservers.refreshservers = qfalse;
if (g_servertype == AS_FAVORITES)
{
// nonresponsive favorites must be shown
ArenaServers_InsertFavorites();
}
// final tally
if (g_arenaservers.numqueriedservers >= 0)
{
g_arenaservers.currentping = *g_arenaservers.numservers;
g_arenaservers.numqueriedservers = *g_arenaservers.numservers;
}
// sort
qsort( g_arenaservers.serverlist, *g_arenaservers.numservers, sizeof( servernode_t ), ArenaServers_Compare);
ArenaServers_UpdateMenu();
}
/*
=================
ArenaServers_DoRefresh
=================
*/
static void ArenaServers_DoRefresh( void )
{
int i;
int j;
int time;
int maxPing;
char adrstr[MAX_ADDRESSLENGTH];
char info[MAX_INFO_STRING];
if (uis.realtime < g_arenaservers.refreshtime)
{
// wait for timeout or results
if (g_servertype == AS_LOCAL)
{
if (!trap_LAN_GetLocalServerCount())
{
// still waiting for response
return;
}
}
else if(( g_servertype >= AS_GLOBAL1) && ( g_servertype <= AS_GLOBAL5))
{
if (trap_LAN_GetGlobalServerCount() < 0)
{
// still waiting for master server response
return;
}
}
}
if (uis.realtime < g_arenaservers.nextpingtime)
{
// wait for time trigger
return;
}
// trigger at 10Hz intervals
g_arenaservers.nextpingtime = uis.realtime + 50;
// process ping results
maxPing = ArenaServers_MaxPing();
for (i=0; i<MAX_PINGREQUESTS; i++)
{
trap_LAN_GetPing( i, adrstr, MAX_ADDRESSLENGTH, &time );
if (!adrstr[0])
{
// ignore empty or pending pings
continue;
}
// find ping result in our local list
for (j=0; j<MAX_PINGREQUESTS; j++)
if (!Q_stricmp( adrstr, g_arenaservers.pinglist[j].adrstr ))
break;
if (j < MAX_PINGREQUESTS)
{
// found it
if (!time)
{
time = uis.realtime - g_arenaservers.pinglist[j].start;
if (time < maxPing)
{
// still waiting
continue;
}
}
if (time > maxPing)
{
// stale it out
info[0] = '\0';
time = maxPing;
}
else
{
trap_LAN_GetPingInfo( i, info, MAX_INFO_STRING ); //bookmark - TiM: This is where the info is received!
//TiM - testing the data output from this baby
//if ( !Q_stricmp( Info_ValueForKey( info, "game" ), "rpg-x" ) )
//Com_Printf( "%s", info );
}
// insert ping results
ArenaServers_Insert( adrstr, info, time );
// clear this query from internal list
g_arenaservers.pinglist[j].adrstr[0] = '\0';
}
// clear this query from external list
trap_LAN_ClearPing( i );
}
// get results of servers query
// counts can increase as servers respond
switch (g_servertype)
{
case AS_LOCAL:
g_arenaservers.numqueriedservers = trap_LAN_GetLocalServerCount();
break;
case AS_GLOBAL1:
case AS_GLOBAL2:
case AS_GLOBAL3:
case AS_GLOBAL4:
case AS_GLOBAL5:
g_arenaservers.numqueriedservers = trap_LAN_GetGlobalServerCount();
break;
case AS_FAVORITES:
g_arenaservers.numqueriedservers = g_arenaservers.numfavoriteaddresses;
break;
}
// if (g_arenaservers.numqueriedservers > g_arenaservers.maxservers)
// g_arenaservers.numqueriedservers = g_arenaservers.maxservers;
// send ping requests in reasonable bursts
// iterate ping through all found servers
for (i=0; i<MAX_PINGREQUESTS && g_arenaservers.currentping < g_arenaservers.numqueriedservers; i++)
{
if (trap_LAN_GetPingQueueCount() >= MAX_PINGREQUESTS)
{
// ping queue is full
break;
}
// find empty slot
for (j=0; j<MAX_PINGREQUESTS; j++)
if (!g_arenaservers.pinglist[j].adrstr[0])
break;
if (j >= MAX_PINGREQUESTS)
// no empty slots available yet - wait for timeout
break;
// get an address to ping
switch (g_servertype)
{
case AS_LOCAL:
trap_LAN_GetLocalServerAddressString( g_arenaservers.currentping, adrstr, MAX_ADDRESSLENGTH );
break;
case AS_GLOBAL1:
case AS_GLOBAL2:
case AS_GLOBAL3:
case AS_GLOBAL4:
case AS_GLOBAL5:
trap_LAN_GetGlobalServerAddressString( g_arenaservers.currentping, adrstr, MAX_ADDRESSLENGTH );
break;
case AS_FAVORITES:
strcpy( adrstr, g_arenaservers.favoriteaddresses[g_arenaservers.currentping] );
break;
}
strcpy( g_arenaservers.pinglist[j].adrstr, adrstr );
g_arenaservers.pinglist[j].start = uis.realtime;
trap_Cmd_ExecuteText( EXEC_NOW, va( "ping %s\n", adrstr ) );
// advance to next server
g_arenaservers.currentping++;
}
if (!trap_LAN_GetPingQueueCount())
{
// all pings completed
ArenaServers_StopRefresh();
return;
}
// update the user interface with ping status
ArenaServers_UpdateMenu();
}
/*
=================
ArenaServers_StartRefresh
=================
*/
static void ArenaServers_StartRefresh( void )
{
int i;
char myargs[32];
memset( g_arenaservers.serverlist, 0, g_arenaservers.maxservers*sizeof(table_t) );
for (i=0; i<MAX_PINGREQUESTS; i++)
{
g_arenaservers.pinglist[i].adrstr[0] = '\0';
trap_LAN_ClearPing( i );
}
g_arenaservers.refreshservers = qtrue;
g_arenaservers.currentping = 0;
g_arenaservers.nextpingtime = 0;
*g_arenaservers.numservers = 0;
g_arenaservers.numqueriedservers = 0;
// allow max 5 seconds for responses
g_arenaservers.refreshtime = uis.realtime + 5000;
// place menu in zeroed state
ArenaServers_UpdateMenu();
if( g_servertype == AS_LOCAL ) {
trap_Cmd_ExecuteText( EXEC_APPEND, "localservers\n" );
return;
}
if(( g_servertype >= AS_GLOBAL1) && ( g_servertype <= AS_GLOBAL5))
{
i = g_servertype - AS_GLOBAL1;
// if( g_servertype == AS_GLOBAL1 ) {
// i = 0;
// }
// else {
// i = 1;
// }
switch( g_arenaservers.gametype.curvalue ) {
default:
/*case GAMES_EXCESSIVE:
case GAMES_FEDERATION:
case GAMES_GLADIATOR:
case GAMES_IN2TAGIB:
case GAMES_PINBALL:
case GAMES_Q32EF:
case GAMES_RPG:
case GAMES_TEAMELITE:*/
case GAMES_RPGX:
case GAMES_ALL:
myargs[0] = 0;
break;
case GAMES_FFA:
strcpy( myargs, " ffa" );
break;
case GAMES_TEAMPLAY:
strcpy( myargs, " team" );
break;
case GAMES_TOURNEY:
strcpy( myargs, " tourney" );
break;
case GAMES_CTF:
strcpy( myargs, " ctf" );
break;
}
if (g_emptyservers) {
strcat(myargs, " empty");
}
if (g_fullservers) {
strcat(myargs, " full");
}
trap_Cmd_ExecuteText( EXEC_APPEND, va( "globalservers %d %d%s\n", i, (int)trap_Cvar_VariableValue( "protocol" ), myargs ) );
}
}
/*
=================
ArenaServers_SaveChanges
=================
*/
void ArenaServers_SaveChanges( void )
{
int i;
for (i=0; i<g_arenaservers.numfavoriteaddresses; i++)
trap_Cvar_Set( va("server%d",i+1), g_arenaservers.favoriteaddresses[i] );
for (; i<MAX_FAVORITESERVERS; i++)
trap_Cvar_Set( va("server%d",i+1), "" );
}
/*
=================
ArenaServers_Sort
=================
*/
void ArenaServers_Sort( int type ) {
if( g_sortkey == type ) {
return;
}
g_sortkey = type;
qsort( g_arenaservers.serverlist, *g_arenaservers.numservers, sizeof( servernode_t ), ArenaServers_Compare);
}
/*
=================
ArenaServers_SetType
=================
*/
void ArenaServers_SetType( int type )
{
char IP[128];
if (g_servertype == type)
return;
if (type == AS_GLOBAL1)
{
trap_Cvar_VariableStringBuffer( "sv_master1", IP, 128);
if (!IP[0])
{
type= AS_GLOBAL2;
}
if (g_arenaservers.numservers)
{
*g_arenaservers.numservers = 0;
}
}
if (type == AS_GLOBAL2)
{
trap_Cvar_VariableStringBuffer( "sv_master2", IP, 128);
if (!IP[0])
{
type= AS_GLOBAL3;
}
if (g_arenaservers.numservers)
{
*g_arenaservers.numservers = 0;
}
}
if (type == AS_GLOBAL3)
{
trap_Cvar_VariableStringBuffer( "sv_master3", IP, 128);
if (!IP[0])
{
type= AS_GLOBAL4;
}
if (g_arenaservers.numservers)
{
*g_arenaservers.numservers = 0;
}
}
if (type == AS_GLOBAL4)
{
trap_Cvar_VariableStringBuffer( "sv_master4", IP, 128);
if (!IP[0])
{
type= AS_GLOBAL5;
}
if (g_arenaservers.numservers)
{
*g_arenaservers.numservers = 0;
}
}
if (type == AS_GLOBAL5)
{
trap_Cvar_VariableStringBuffer( "sv_master5", IP, 128);
if (!IP[0])
{
type= AS_FAVORITES;
}
if (g_arenaservers.numservers)
{
*g_arenaservers.numservers = 0;
}
}
g_arenaservers.master.curvalue = type;
g_servertype = type;
switch( type ) {
default:
case AS_LOCAL:
g_arenaservers.remove.generic.flags |= (QMF_INACTIVE|QMF_HIDDEN);
g_arenaservers.serverlist = g_localserverlist;
g_arenaservers.numservers = &g_numlocalservers;
g_arenaservers.maxservers = MAX_LOCALSERVERS;
break;
case AS_GLOBAL1:
case AS_GLOBAL2:
case AS_GLOBAL3:
case AS_GLOBAL4:
case AS_GLOBAL5:
g_arenaservers.remove.generic.flags |= (QMF_INACTIVE|QMF_HIDDEN);
g_arenaservers.serverlist = g_globalserverlist;
g_arenaservers.numservers = &g_numglobalservers;
g_arenaservers.maxservers = MAX_GLOBALSERVERS;
break;
case AS_FAVORITES:
g_arenaservers.remove.generic.flags &= ~(QMF_INACTIVE|QMF_HIDDEN);
g_arenaservers.serverlist = g_favoriteserverlist;
g_arenaservers.numservers = &g_numfavoriteservers;
g_arenaservers.maxservers = MAX_FAVORITESERVERS;
break;
// case AS_MPLAYER:
// g_arenaservers.remove.generic.flags |= (QMF_INACTIVE|QMF_HIDDEN);
// g_arenaservers.serverlist = g_mplayerserverlist;
// g_arenaservers.numservers = &g_nummplayerservers;
// g_arenaservers.maxservers = MAX_GLOBALSERVERS;
// break;
}
if( !*g_arenaservers.numservers ) {
ArenaServers_StartRefresh();
}
else {
// avoid slow operation, use existing results
g_arenaservers.currentping = *g_arenaservers.numservers;
g_arenaservers.numqueriedservers = *g_arenaservers.numservers;
ArenaServers_UpdateMenu();
}
strcpy(g_arenaservers.status.string,menu_normal_text[MNT_HITREFRESH]);
}
/*
=================
ArenaServers_Favorites_Add
Add current server to favorites
=================
*/
void ArenaServers_Favorites_Add( void )
{
char adrstr[128];
int i;
int best;
if (!g_arenaservers.table[g_arenaservers.list.curvalue].servernode->adrstr)
return;
best = 0;
for (i=0; i<MAX_FAVORITESERVERS; i++)
{
trap_Cvar_VariableStringBuffer( va("server%d",i+1), adrstr, sizeof(adrstr) );
if (!Q_stricmp(g_arenaservers.table[g_arenaservers.list.curvalue].servernode->adrstr,adrstr))
{
// already in list
return;
}
// use first empty or non-numeric available slot
if ((adrstr[0] < '0' || adrstr[0] > '9' ) && !best)
best = i+1;
}
if (best)
trap_Cvar_Set( va("server%d",best), g_arenaservers.table[g_arenaservers.list.curvalue].servernode->adrstr);
}
/*
=================
ArenaServers_Event
=================
*/
static void ArenaServers_Event( void* ptr, int event ) {
int id;
id = ((menucommon_s*)ptr)->id;
if( event != QM_ACTIVATED && id != ID_LIST )
{
return;
}
switch( id )
{
case ID_MAINMENU:
UI_PopMenu();
UI_MainMenu();
break;
case ID_MASTER:
trap_Cvar_SetValue( "ui_browserMaster", g_arenaservers.master.curvalue );
ArenaServers_SetType( g_arenaservers.master.curvalue );
if (master_items[g_arenaservers.master.curvalue] == MNT_MASTER_ITEMS_FAVORITES)
{
g_arenaservers.favorite.generic.flags |= QMF_GRAYED;
}
else
{
g_arenaservers.favorite.generic.flags &= ~QMF_GRAYED;
}
break;
case ID_GAMETYPE:
trap_Cvar_SetValue( "ui_browserGameType", g_arenaservers.gametype.curvalue );
g_gametype = g_arenaservers.gametype.curvalue;
ArenaServers_UpdateMenu();
break;
case ID_SORTKEY:
trap_Cvar_SetValue( "ui_browserSortKey", g_arenaservers.sortkey.curvalue );
ArenaServers_Sort( g_arenaservers.sortkey.curvalue );
ArenaServers_UpdateMenu();
break;
case ID_SHOW_FULL:
trap_Cvar_SetValue( "ui_browserShowFull", g_arenaservers.showfull.curvalue );
g_fullservers = g_arenaservers.showfull.curvalue;
ArenaServers_UpdateMenu();
break;
case ID_SHOW_EMPTY:
trap_Cvar_SetValue( "ui_browserShowEmpty", g_arenaservers.showempty.curvalue );
g_emptyservers = g_arenaservers.showempty.curvalue;
ArenaServers_UpdateMenu();
break;
case ID_LIST:
if( event == QM_GOTFOCUS ) {
ArenaServers_UpdatePicture();
}
break;
case ID_SCROLL_UP:
ScrollList_Key( &g_arenaservers.list, K_UPARROW );
break;
case ID_SCROLL_DOWN:
ScrollList_Key( &g_arenaservers.list, K_DOWNARROW );
break;
case ID_FAVORITE:
ArenaServers_Favorites_Add();
ArenaServers_LoadFavorites();
break;
case ID_BACK:
ArenaServers_StopRefresh();
ArenaServers_SaveChanges();
UI_PopMenu();
break;
case ID_STOPREFRESH:
ArenaServers_StopRefresh();
break;
case ID_REFRESH:
ArenaServers_StartRefresh();
break;
case ID_SPECIFY:
UI_SpecifyServerMenu();
break;
case ID_CREATE:
UI_StartServerMenu( qtrue );
break;
case ID_FINDSERVER:
UI_ArenaServersMenu();
break;
case ID_CONNECT:
ArenaServers_Go();
break;
case ID_REMOVE:
ArenaServers_Remove();
ArenaServers_UpdateMenu();
break;
}
}
/*
=================
ArenaServers_Graphics
=================
*/
void ArenaServers_Graphics (void)
{
UI_MenuFrame2(&g_arenaservers.menu);
trap_R_SetColor( colorTable[CT_LTBROWN1]);
UI_DrawHandlePic( 30, 203, 47, 186, uis.whiteShader); // Left side of frame
// Frame map picture
trap_R_SetColor( colorTable[CT_DKPURPLE3]);
UI_DrawHandlePic( 87, 53, 158, 16, uis.whiteShader); // Top line
UI_DrawHandlePic( 232, 69, 13, 103, uis.whiteShader); // Side line
UI_DrawProportionalString( 90, 53, menu_normal_text[MNT_CURRENTMAP],UI_SMALLFONT, colorTable[CT_BLACK]);
// Frame sort options
trap_R_SetColor( colorTable[CT_DKPURPLE3]);
UI_DrawHandlePic( 252, 53, 359, 16, uis.whiteShader); // Top line
UI_DrawHandlePic( 252, 69, 13, 103, uis.whiteShader); // Side line
UI_DrawProportionalString( 272, 53, menu_normal_text[MNT_SORTPARMS],UI_SMALLFONT, colorTable[CT_BLACK]);
// Frame servers
trap_R_SetColor( colorTable[CT_DKORANGE]);
UI_DrawHandlePic( 87, 175, 523, 13, uis.whiteShader); // Top line
UI_DrawHandlePic( 87, 188, 16, 11, uis.whiteShader); // Side line
UI_DrawHandlePic( 87, 202, 16, 17, uis.whiteShader); // Side line
UI_DrawHandlePic( 87, 222, 16, 110, uis.whiteShader); // Side line
UI_DrawHandlePic( 87, 335, 16, 17, uis.whiteShader); // Side line
UI_DrawHandlePic( 87, 355, 16, 11, uis.whiteShader); // Side line
UI_DrawHandlePic( 87, 366, 268, 18, uis.whiteShader); // Bottom line
UI_DrawProportionalString( 105, 177, menu_normal_text[MNT_HOSTNAME],UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 360, 177, menu_normal_text[MNT_MAP],UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 466, 177, menu_normal_text[MNT_PLAYERS],UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 504, 177, menu_normal_text[MNT_TYPE],UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 583, 177, menu_normal_text[MNT_PING],UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 74, 27, "819",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 74, 149, "42",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 74, 205, "4363",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 74, 395, "6700",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
// Left rounded ends for buttons
trap_R_SetColor( colorTable[g_arenaservers.mainmenu.color]);
UI_DrawHandlePic(g_arenaservers.mainmenu.generic.x - 14, g_arenaservers.mainmenu.generic.y,
MENU_BUTTON_MED_HEIGHT, MENU_BUTTON_MED_HEIGHT, uis.graphicButtonLeftEnd);
trap_R_SetColor( colorTable[g_arenaservers.back.color]);
UI_DrawHandlePic(g_arenaservers.back.generic.x - 14, g_arenaservers.back.generic.y,
MENU_BUTTON_MED_HEIGHT, MENU_BUTTON_MED_HEIGHT, uis.graphicButtonLeftEnd);
}
/*
=================
ArenaServers_MenuDraw
=================
*/
static void ArenaServers_MenuDraw( void )
{
ArenaServers_Graphics();
if (g_arenaservers.refreshservers)
{
ArenaServers_DoRefresh();
}
trap_R_SetColor( colorTable[CT_WHITE]);
Menu_Draw( &g_arenaservers.menu );
}
/*
=================
ArenaServers_MenuKey
=================
*/
static sfxHandle_t ArenaServers_MenuKey( int key ) {
if( key == K_SPACE && g_arenaservers.refreshservers ) {
ArenaServers_StopRefresh();
return menu_move_sound;
}
if( ( key == K_DEL || key == K_KP_DEL ) && ( g_servertype == AS_FAVORITES ) &&
( Menu_ItemAtCursor( &g_arenaservers.menu) == &g_arenaservers.list ) ) {
ArenaServers_Remove();
ArenaServers_UpdateMenu();
return menu_move_sound;
}
if( key == K_MOUSE2 || key == K_ESCAPE ) {
ArenaServers_StopRefresh();
ArenaServers_SaveChanges();
}
return Menu_DefaultKey( &g_arenaservers.menu, key );
}
/*
=================
ArenaServers_MenuInit
=================
*/
static void ArenaServers_MenuInit( void )
{
int i;
int type;
static char statusbuffer[MAX_STATUSLENGTH];
// zero set all our globals
memset( &g_arenaservers, 0 ,sizeof(arenaservers_t) );
ArenaServers_Cache();
g_arenaservers.menu.fullscreen = qtrue;
g_arenaservers.menu.wrapAround = qtrue;
g_arenaservers.menu.draw = ArenaServers_MenuDraw;
g_arenaservers.menu.key = ArenaServers_MenuKey;
g_arenaservers.menu.descX = MENU_DESC_X;
g_arenaservers.menu.descY = MENU_DESC_Y;
g_arenaservers.menu.titleX = MENU_TITLE_X;
g_arenaservers.menu.titleY = MENU_TITLE_Y;
g_arenaservers.menu.titleI = MNT_MULTIPLAYER_TITLE;
g_arenaservers.menu.footNoteEnum = MNT_FINDSERVER;
g_arenaservers.mainmenu.generic.type = MTYPE_BITMAP;
g_arenaservers.mainmenu.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
g_arenaservers.mainmenu.generic.x = 110;
g_arenaservers.mainmenu.generic.y = 391;
g_arenaservers.mainmenu.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
g_arenaservers.mainmenu.generic.id = ID_MAINMENU;
g_arenaservers.mainmenu.generic.callback = ArenaServers_Event;
g_arenaservers.mainmenu.width = MENU_BUTTON_MED_WIDTH;
g_arenaservers.mainmenu.height = MENU_BUTTON_MED_HEIGHT;
g_arenaservers.mainmenu.color = CT_DKPURPLE1;
g_arenaservers.mainmenu.color2 = CT_LTPURPLE1;
g_arenaservers.mainmenu.textX = 5;
g_arenaservers.mainmenu.textY = 2;
g_arenaservers.mainmenu.textEnum = MBT_MAINMENU;
g_arenaservers.mainmenu.textcolor = CT_BLACK;
g_arenaservers.mainmenu.textcolor2 = CT_WHITE;
g_arenaservers.back.generic.type = MTYPE_BITMAP;
g_arenaservers.back.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
g_arenaservers.back.generic.x = 110;
g_arenaservers.back.generic.y = 415;
g_arenaservers.back.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
g_arenaservers.back.generic.id = ID_BACK;
g_arenaservers.back.generic.callback = ArenaServers_Event;
g_arenaservers.back.width = MENU_BUTTON_MED_WIDTH;
g_arenaservers.back.height = MENU_BUTTON_MED_HEIGHT;
g_arenaservers.back.color = CT_DKPURPLE1;
g_arenaservers.back.color2 = CT_LTPURPLE1;
g_arenaservers.back.textX = 5;
g_arenaservers.back.textY = 2;
g_arenaservers.back.textEnum = MBT_BACK;
g_arenaservers.back.textcolor = CT_BLACK;
g_arenaservers.back.textcolor2 = CT_WHITE;
g_arenaservers.master.generic.type = MTYPE_SPINCONTROL;
g_arenaservers.master.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
g_arenaservers.master.generic.callback = ArenaServers_Event;
g_arenaservers.master.generic.id = ID_MASTER;
g_arenaservers.master.generic.x = server_buttons[0][0];
g_arenaservers.master.generic.y = server_buttons[0][1];
g_arenaservers.master.textEnum = MBT_SERVERS;
g_arenaservers.master.textcolor = CT_BLACK;
g_arenaservers.master.textcolor2 = CT_WHITE;
g_arenaservers.master.color = CT_DKPURPLE1;
g_arenaservers.master.color2 = CT_LTPURPLE1;
g_arenaservers.master.width = 80;
g_arenaservers.master.textX = 5;
g_arenaservers.master.textY = 2;
g_arenaservers.master.listnames = master_items;
g_arenaservers.gametype.generic.type = MTYPE_SPINCONTROL;
g_arenaservers.gametype.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
g_arenaservers.gametype.generic.callback = ArenaServers_Event;
g_arenaservers.gametype.generic.id = ID_GAMETYPE;
g_arenaservers.gametype.generic.x = server_buttons[1][0];
g_arenaservers.gametype.generic.y = server_buttons[1][1];
g_arenaservers.gametype.textEnum = MBT_SERVERTYPE_GAMETYPE;
g_arenaservers.gametype.textcolor = CT_BLACK;
g_arenaservers.gametype.textcolor2 = CT_WHITE;
g_arenaservers.gametype.color = CT_DKPURPLE1;
g_arenaservers.gametype.color2 = CT_LTPURPLE1;
g_arenaservers.gametype.width = 80;
g_arenaservers.gametype.textX = 5;
g_arenaservers.gametype.textY = 2;
g_arenaservers.gametype.listnames = servertype_items;
g_arenaservers.sortkey.generic.type = MTYPE_SPINCONTROL;
g_arenaservers.sortkey.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
g_arenaservers.sortkey.generic.callback = ArenaServers_Event;
g_arenaservers.sortkey.generic.id = ID_SORTKEY;
g_arenaservers.sortkey.generic.x = server_buttons[2][0];
g_arenaservers.sortkey.generic.y = server_buttons[2][1];
g_arenaservers.sortkey.textEnum = MBT_SORTTYPE;
g_arenaservers.sortkey.textcolor = CT_BLACK;
g_arenaservers.sortkey.textcolor2 = CT_WHITE;
g_arenaservers.sortkey.color = CT_DKPURPLE1;
g_arenaservers.sortkey.color2 = CT_LTPURPLE1;
g_arenaservers.sortkey.width = 80;
g_arenaservers.sortkey.textX = 5;
g_arenaservers.sortkey.textY = 2;
g_arenaservers.sortkey.listnames = sortkey_items;
g_arenaservers.showfull.generic.type = MTYPE_SPINCONTROL;
g_arenaservers.showfull.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
g_arenaservers.showfull.generic.callback = ArenaServers_Event;
g_arenaservers.showfull.generic.id = ID_SHOW_FULL;
g_arenaservers.showfull.generic.x = server_buttons[3][0];
g_arenaservers.showfull.generic.y = server_buttons[3][1];
g_arenaservers.showfull.textEnum = MBT_SHOWFULL;
g_arenaservers.showfull.textcolor = CT_BLACK;
g_arenaservers.showfull.textcolor2 = CT_WHITE;
g_arenaservers.showfull.color = CT_DKPURPLE1;
g_arenaservers.showfull.color2 = CT_LTPURPLE1;
g_arenaservers.showfull.width = 80;
g_arenaservers.showfull.textX = 5;
g_arenaservers.showfull.textY = 2;
g_arenaservers.showfull.listnames = noyes_items;
g_arenaservers.showempty.generic.type = MTYPE_SPINCONTROL;
g_arenaservers.showempty.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
g_arenaservers.showempty.generic.callback = ArenaServers_Event;
g_arenaservers.showempty.generic.id = ID_SHOW_EMPTY;
g_arenaservers.showempty.generic.x = server_buttons[4][0];
g_arenaservers.showempty.generic.y = server_buttons[4][1];
g_arenaservers.showempty.textEnum = MBT_SHOWEMPTY;
g_arenaservers.showempty.textcolor = CT_BLACK;
g_arenaservers.showempty.textcolor2 = CT_WHITE;
g_arenaservers.showempty.color = CT_DKPURPLE1;
g_arenaservers.showempty.color2 = CT_LTPURPLE1;
g_arenaservers.showempty.width = 80;
g_arenaservers.showempty.textX = 5;
g_arenaservers.showempty.textY = 2;
g_arenaservers.showempty.listnames = noyes_items;
g_arenaservers.list.generic.type = MTYPE_SCROLLLIST;
g_arenaservers.list.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
g_arenaservers.list.generic.id = ID_LIST;
g_arenaservers.list.generic.callback = ArenaServers_Event;
g_arenaservers.list.generic.x = 103;
g_arenaservers.list.generic.y = 188;
g_arenaservers.list.width = MAX_LISTBOXWIDTH - 3;
g_arenaservers.list.height = 11;
g_arenaservers.list.itemnames = (const char **)g_arenaservers.items;
for( i = 0; i < MAX_LISTBOXITEMS; i++ )
{
g_arenaservers.items[i] = g_arenaservers.table[i].buff;
}
g_arenaservers.mappic.generic.type = MTYPE_BITMAP;
g_arenaservers.mappic.generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE;
g_arenaservers.mappic.generic.x = 95;
g_arenaservers.mappic.generic.y = 71;
g_arenaservers.mappic.width = 128;
g_arenaservers.mappic.height = 96;
g_arenaservers.mappic.errorpic = ART_UNKNOWNMAP;
g_arenaservers.up.generic.type = MTYPE_BITMAP;
g_arenaservers.up.generic.flags = QMF_HIGHLIGHT_IF_FOCUS|QMF_MOUSEONLY;
g_arenaservers.up.generic.callback = ArenaServers_Event;
g_arenaservers.up.generic.id = ID_SCROLL_UP;
g_arenaservers.up.generic.x = 87;
g_arenaservers.up.generic.y = 204;
g_arenaservers.up.width = 16;
g_arenaservers.up.height = 16;
g_arenaservers.up.color = CT_DKGOLD1;
g_arenaservers.up.color2 = CT_LTGOLD1;
g_arenaservers.up.generic.name = "menu/common/arrow_up_16.tga";
g_arenaservers.up.textEnum = MBT_ARROW_UP;
g_arenaservers.down.generic.type = MTYPE_BITMAP;
g_arenaservers.down.generic.flags = QMF_HIGHLIGHT_IF_FOCUS|QMF_MOUSEONLY;
g_arenaservers.down.generic.callback = ArenaServers_Event;
g_arenaservers.down.generic.id = ID_SCROLL_DOWN;
g_arenaservers.down.generic.x = 87;
g_arenaservers.down.generic.y = 337;
g_arenaservers.down.width = 16;
g_arenaservers.down.height = 16;
g_arenaservers.down.color = CT_DKGOLD1;
g_arenaservers.down.color2 = CT_LTGOLD1;
g_arenaservers.down.generic.name = "menu/common/arrow_dn_16.tga";
g_arenaservers.down.textEnum = MBT_ARROW_DOWN;
g_arenaservers.favorite.generic.type = MTYPE_BITMAP;
g_arenaservers.favorite.generic.flags = QMF_HIGHLIGHT_IF_FOCUS|QMF_MOUSEONLY;
g_arenaservers.favorite.generic.callback = ArenaServers_Event;
g_arenaservers.favorite.generic.id = ID_FAVORITE;
g_arenaservers.favorite.generic.x = 285;
g_arenaservers.favorite.generic.y = 415;
g_arenaservers.favorite.width = MENU_BUTTON_MED_WIDTH + 15;
g_arenaservers.favorite.height = MENU_BUTTON_MED_HEIGHT;
g_arenaservers.favorite.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
g_arenaservers.favorite.textEnum = MBT_ADDTOFAVS;
g_arenaservers.favorite.color = CT_DKPURPLE1;
g_arenaservers.favorite.color2 = CT_LTPURPLE1;
g_arenaservers.favorite.textX = 5;
g_arenaservers.favorite.textY = 2;
g_arenaservers.favorite.textcolor = CT_BLACK;
g_arenaservers.favorite.textcolor2 = CT_WHITE;
g_arenaservers.status.generic.type = MTYPE_TEXT;
g_arenaservers.status.generic.flags = QMF_INACTIVE;
g_arenaservers.status.generic.x = 129;
g_arenaservers.status.generic.y = 368;
g_arenaservers.status.string = statusbuffer;
g_arenaservers.status.style = UI_SMALLFONT;
g_arenaservers.status.color = menu_text_color;
g_arenaservers.refresh.generic.type = MTYPE_BITMAP;
g_arenaservers.refresh.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
g_arenaservers.refresh.generic.callback = ArenaServers_Event;
g_arenaservers.refresh.generic.id = ID_REFRESH;
g_arenaservers.refresh.generic.x = 358;
g_arenaservers.refresh.generic.y = 366;
g_arenaservers.refresh.generic.name = "menu/common/square.tga";
g_arenaservers.refresh.generic.callback = ArenaServers_Event;
g_arenaservers.refresh.width = 85;
g_arenaservers.refresh.height = MENU_BUTTON_MED_HEIGHT;
g_arenaservers.refresh.color = CT_DKPURPLE1;
g_arenaservers.refresh.color2 = CT_LTPURPLE1;
g_arenaservers.refresh.textX = 5;
g_arenaservers.refresh.textY = 2;
g_arenaservers.refresh.textEnum = MBT_REFRESH;
g_arenaservers.refresh.textcolor = CT_BLACK;
g_arenaservers.refresh.textcolor2 = CT_WHITE;
g_arenaservers.stoprefresh.generic.type = MTYPE_BITMAP;
g_arenaservers.stoprefresh.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
g_arenaservers.stoprefresh.generic.callback = ArenaServers_Event;
g_arenaservers.stoprefresh.generic.id = ID_STOPREFRESH;
g_arenaservers.stoprefresh.generic.x = 446;
g_arenaservers.stoprefresh.generic.y = 366;
g_arenaservers.stoprefresh.generic.name = "menu/common/square.tga";
g_arenaservers.stoprefresh.width = 85;
g_arenaservers.stoprefresh.height = MENU_BUTTON_MED_HEIGHT;
g_arenaservers.stoprefresh.color = CT_DKPURPLE1;
g_arenaservers.stoprefresh.color2 = CT_LTPURPLE1;
g_arenaservers.stoprefresh.textX = 5;
g_arenaservers.stoprefresh.textY = 2;
g_arenaservers.stoprefresh.textEnum = MBT_STOPREFRESH;
g_arenaservers.stoprefresh.textcolor = CT_BLACK;
g_arenaservers.stoprefresh.textcolor2 = CT_WHITE;
g_arenaservers.remove.generic.type = MTYPE_BITMAP;
g_arenaservers.remove.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
g_arenaservers.remove.generic.callback = ArenaServers_Event;
g_arenaservers.remove.generic.id = ID_REMOVE;
g_arenaservers.remove.generic.x = 534;
g_arenaservers.remove.generic.y = 366;
g_arenaservers.remove.generic.name = "menu/common/square.tga";
g_arenaservers.remove.width = 85;
g_arenaservers.remove.height = MENU_BUTTON_MED_HEIGHT;
g_arenaservers.remove.color = CT_DKPURPLE1;
g_arenaservers.remove.color2 = CT_LTPURPLE1;
g_arenaservers.remove.textX = 5;
g_arenaservers.remove.textY = 2;
g_arenaservers.remove.textEnum = MBT_REMOVE;
g_arenaservers.remove.textcolor = CT_BLACK;
g_arenaservers.remove.textcolor2 = CT_WHITE;
g_arenaservers.go.generic.type = MTYPE_BITMAP;
g_arenaservers.go.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
g_arenaservers.go.generic.x = 462;
g_arenaservers.go.generic.y = 391;
g_arenaservers.go.generic.name = "menu/common/square.tga";
g_arenaservers.go.generic.id = ID_CONNECT;
g_arenaservers.go.generic.callback = ArenaServers_Event;
g_arenaservers.go.width = 150;
g_arenaservers.go.height = 42;
g_arenaservers.go.color = CT_DKPURPLE1;
g_arenaservers.go.color2 = CT_LTPURPLE1;
g_arenaservers.go.textX = 5;
g_arenaservers.go.textY = 2;
g_arenaservers.go.textEnum = MBT_ENGAGEMULTIPLAYER;
g_arenaservers.go.textcolor = CT_BLACK;
g_arenaservers.go.textcolor2 = CT_WHITE;
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.mainmenu );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.back );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.master );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.gametype );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.sortkey );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.showfull);
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.showempty );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.mappic );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.list );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.status );
// Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.statusbar );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.up );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.down );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.refresh );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.stoprefresh );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.remove );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.favorite );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.go );
ArenaServers_LoadFavorites();
g_servertype = Com_Clamp( 0, 3, ui_browserMaster.integer );
g_arenaservers.master.curvalue = g_servertype;
g_gametype = Com_Clamp( 0, 13, ui_browserGameType.integer );
g_arenaservers.gametype.curvalue = g_gametype;
g_sortkey = Com_Clamp( 0, 4, ui_browserSortKey.integer );
g_arenaservers.sortkey.curvalue = g_sortkey;
g_fullservers = Com_Clamp( 0, 1, ui_browserShowFull.integer );
g_arenaservers.showfull.curvalue = g_fullservers;
g_emptyservers = Com_Clamp( 0, 1, ui_browserShowEmpty.integer );
g_arenaservers.showempty.curvalue = g_emptyservers;
// force to initial state and refresh
type = g_servertype;
g_servertype = -1;
ArenaServers_SetType( type );
if (master_items[g_arenaservers.master.curvalue] == MNT_MASTER_ITEMS_FAVORITES)
{
g_arenaservers.favorite.generic.flags |= QMF_GRAYED;
}
else
{
g_arenaservers.favorite.generic.flags &= ~QMF_GRAYED;
}
}
/*
=================
ArenaServers_Cache
=================
*/
void ArenaServers_Cache( void )
{
trap_R_RegisterShaderNoMip( ART_UNKNOWNMAP );
}
/*
=================
UI_ArenaServersMenu
=================
*/
void UI_ArenaServersMenu( void )
{
ArenaServers_MenuInit();
UI_PushMenu( &g_arenaservers.menu );
}
/*
=================
ChooseServerType_MenuKey
=================
*/
static sfxHandle_t ChooseServerType_MenuKey( int key )
{
return Menu_DefaultKey( &g_chooseservertype.menu, key );
}
/*
=================
ChooseServerType_Graphics
=================
*/
void ChooseServerType_Graphics (void)
{
UI_MenuFrame(&g_chooseservertype.menu);
trap_R_SetColor( colorTable[CT_LTPURPLE2]);
UI_DrawHandlePic( 30, 203, 47, 186, uis.whiteShader); // Frame Left side
UI_DrawProportionalString( 74, 27, "66809",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 74, 84, "809",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 74, 188, "991",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 74, 206, "6-513",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
UI_DrawProportionalString( 74, 395, "7814",UI_RIGHT|UI_TINYFONT, colorTable[CT_BLACK]);
// Left rounded ends for buttons
trap_R_SetColor( colorTable[s_find_server.color]);
UI_DrawHandlePic(s_find_server.generic.x - 14, s_find_server.generic.y,
MENU_BUTTON_MED_HEIGHT, MENU_BUTTON_MED_HEIGHT, uis.graphicButtonLeftEnd);
trap_R_SetColor( colorTable[s_create_server.color]);
UI_DrawHandlePic(s_create_server.generic.x - 14, s_create_server.generic.y,
MENU_BUTTON_MED_HEIGHT, MENU_BUTTON_MED_HEIGHT, uis.graphicButtonLeftEnd);
trap_R_SetColor( colorTable[s_specific_server.color]);
UI_DrawHandlePic(s_specific_server.generic.x - 14, s_specific_server.generic.y,
MENU_BUTTON_MED_HEIGHT, MENU_BUTTON_MED_HEIGHT, uis.graphicButtonLeftEnd);
}
/*
=================
ChooseServerType_MenuDraw
=================
*/
static void ChooseServerType_MenuDraw( void )
{
ChooseServerType_Graphics();
Menu_Draw( &g_chooseservertype.menu );
}
/*
=================
UI_ChooseServerTypeMenu_Cache
=================
*/
void UI_ChooseServerTypeMenu_Cache( void )
{
}
/*
=================
ChooseServerType_MenuInit
=================
*/
static void ChooseServerType_MenuInit( void )
{
// zero set all our globals
memset( &g_chooseservertype, 0 ,sizeof(chooseservertype_t) );
g_chooseservertype.menu.fullscreen = qtrue;
g_chooseservertype.menu.wrapAround = qtrue;
g_chooseservertype.menu.draw = ChooseServerType_MenuDraw;
g_chooseservertype.menu.key = ChooseServerType_MenuKey;
g_chooseservertype.menu.descX = MENU_DESC_X;
g_chooseservertype.menu.descY = MENU_DESC_Y;
g_chooseservertype.menu.titleX = MENU_TITLE_X;
g_chooseservertype.menu.titleY = MENU_TITLE_Y;
g_chooseservertype.menu.titleI = MNT_MULTIPLAYER_TITLE;
g_chooseservertype.menu.footNoteEnum = MNT_FINDSERVER;
g_chooseservertype.main.generic.type = MTYPE_BITMAP;
g_chooseservertype.main.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
g_chooseservertype.main.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
g_chooseservertype.main.generic.id = ID_BACK;
g_chooseservertype.main.generic.callback = ArenaServers_Event;
g_chooseservertype.main.generic.x = 482;
g_chooseservertype.main.generic.y = 136;
g_chooseservertype.main.width = MENU_BUTTON_MED_WIDTH;
g_chooseservertype.main.height = MENU_BUTTON_MED_HEIGHT;
g_chooseservertype.main.color = CT_DKPURPLE1;
g_chooseservertype.main.color2 = CT_LTPURPLE1;
g_chooseservertype.main.textX = MENU_BUTTON_TEXT_X;
g_chooseservertype.main.textY = MENU_BUTTON_TEXT_Y;
g_chooseservertype.main.textEnum = MBT_MAINMENU;
g_chooseservertype.main.textcolor = CT_BLACK;
g_chooseservertype.main.textcolor2 = CT_WHITE;
s_find_server.generic.type = MTYPE_BITMAP;
s_find_server.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
s_find_server.generic.x = 282;
s_find_server.generic.y = 229;
s_find_server.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
s_find_server.generic.id = ID_FINDSERVER;
s_find_server.generic.callback = ArenaServers_Event;
s_find_server.width = MENU_BUTTON_MED_WIDTH+16;
s_find_server.height = MENU_BUTTON_MED_HEIGHT;
s_find_server.color = CT_DKPURPLE1;
s_find_server.color2 = CT_LTPURPLE1;
s_find_server.textX = 5;
s_find_server.textY = 2;
s_find_server.textEnum = MBT_SEARCHSERVER;
s_find_server.textcolor = CT_BLACK;
s_find_server.textcolor2 = CT_WHITE;
s_create_server.generic.type = MTYPE_BITMAP;
s_create_server.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
s_create_server.generic.x = 282;
s_create_server.generic.y = 279;
s_create_server.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
s_create_server.generic.id = ID_CREATE;
s_create_server.generic.callback = ArenaServers_Event;
s_create_server.width = MENU_BUTTON_MED_WIDTH+16;
s_create_server.height = MENU_BUTTON_MED_HEIGHT;
s_create_server.color = CT_DKPURPLE1;
s_create_server.color2 = CT_LTPURPLE1;
s_create_server.textX = 5;
s_create_server.textY = 2;
s_create_server.textEnum = MBT_CREATE;
s_create_server.textcolor = CT_BLACK;
s_create_server.textcolor2 = CT_WHITE;
s_specific_server.generic.type = MTYPE_BITMAP;
s_specific_server.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
s_specific_server.generic.x = 282;
s_specific_server.generic.y = 329;
s_specific_server.generic.name = BUTTON_GRAPHIC_LONGRIGHT;
s_specific_server.generic.id = ID_SPECIFY;
s_specific_server.generic.callback = ArenaServers_Event;
s_specific_server.width = MENU_BUTTON_MED_WIDTH+16;
s_specific_server.height = MENU_BUTTON_MED_HEIGHT;
s_specific_server.color = CT_DKPURPLE1;
s_specific_server.color2 = CT_LTPURPLE1;
s_specific_server.textX = 5;
s_specific_server.textY = 2;
s_specific_server.textEnum = MBT_SPECIFY;
s_specific_server.textcolor = CT_BLACK;
s_specific_server.textcolor2 = CT_WHITE;
Menu_AddItem(&g_chooseservertype.menu, ( void * )&g_chooseservertype.main);
Menu_AddItem(&g_chooseservertype.menu, ( void * )&s_find_server);
Menu_AddItem(&g_chooseservertype.menu, ( void * )&s_create_server);
Menu_AddItem(&g_chooseservertype.menu, ( void * )&s_specific_server);
UI_ChooseServerTypeMenu_Cache();
}
/*
=================
UI_ChooseServerTypeMenu
=================
*/
void UI_ChooseServerTypeMenu( void )
{
ChooseServerType_MenuInit();
UI_PushMenu( &g_chooseservertype.menu );
}