2
===========================================================================
3
Copyright (C) 1999-2005 Id Software, Inc.
5
This file is part of Quake III Arena source code.
7
Quake III Arena source code is free software; you can redistribute it
8
and/or modify it under the terms of the GNU General Public License as
9
published by the Free Software Foundation; either version 2 of the License,
10
or (at your option) any later version.
12
Quake III Arena source code is distributed in the hope that it will be
13
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with Quake III Arena source code; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
===========================================================================
24
=======================================================================
26
MULTIPLAYER MENU (SERVER BROWSER)
28
=======================================================================
35
#define MAX_GLOBALSERVERS 128
36
#define MAX_PINGREQUESTS 32
37
#define MAX_ADDRESSLENGTH 64
38
#define MAX_HOSTNAMELENGTH 22
39
#define MAX_MAPNAMELENGTH 16
40
#define MAX_LISTBOXITEMS 128
41
#define MAX_LOCALSERVERS 128
42
#define MAX_STATUSLENGTH 64
43
#define MAX_LEAGUELENGTH 28
44
#define MAX_LISTBOXWIDTH 68
46
#define ART_BACK0 "menu/art/back_0"
47
#define ART_BACK1 "menu/art/back_1"
48
#define ART_CREATE0 "menu/art/create_0"
49
#define ART_CREATE1 "menu/art/create_1"
50
#define ART_SPECIFY0 "menu/art/specify_0"
51
#define ART_SPECIFY1 "menu/art/specify_1"
52
#define ART_REFRESH0 "menu/art/refresh_0"
53
#define ART_REFRESH1 "menu/art/refresh_1"
54
#define ART_CONNECT0 "menu/art/fight_0"
55
#define ART_CONNECT1 "menu/art/fight_1"
56
#define ART_ARROWS0 "menu/art/arrows_vert_0"
57
#define ART_ARROWS_UP "menu/art/arrows_vert_top"
58
#define ART_ARROWS_DOWN "menu/art/arrows_vert_bot"
59
#define ART_UNKNOWNMAP "menu/art/unknownmap"
60
#define ART_REMOVE0 "menu/art/delete_0"
61
#define ART_REMOVE1 "menu/art/delete_1"
62
#define ART_PUNKBUSTER "menu/art/pblogo"
65
#define ID_GAMETYPE 11
67
#define ID_SHOW_FULL 13
68
#define ID_SHOW_EMPTY 14
70
#define ID_SCROLL_UP 16
71
#define ID_SCROLL_DOWN 17
78
#define ID_PUNKBUSTER 24
86
#define AS_FAVORITES 3
90
#define SORT_CLIENTS 2
96
#define GAMES_TEAMPLAY 2
97
#define GAMES_TOURNEY 3
100
static const char *master_items[] = {
107
static const char *servertype_items[] = {
116
static const char *sortkey_items[] = {
125
static char* gamenames[] = {
128
"SP ", // single player
129
"Team DM", // team deathmatch
130
"CTF", // capture the flag
131
"One Flag CTF", // one flag ctf
132
"OverLoad", // Overload
133
"Harvester", // Harvester
134
"Rocket Arena 3", // Rocket Arena 3
136
"Urban Terror", // Urban Terror
137
"OSP", // Orange Smoothie Productions
142
static char* netnames[] = {
149
static char quake3worldMessage[] = "Visit www.quake3world.com - News, Community, Events, Files";
151
const char* punkbuster_items[] = {
157
const char* punkbuster_msg[] = {
158
"PunkBuster will be",
159
"disabled the next time",
166
char adrstr[MAX_ADDRESSLENGTH];
170
typedef struct servernode_s {
171
char adrstr[MAX_ADDRESSLENGTH];
172
char hostname[MAX_HOSTNAMELENGTH+3];
173
char mapname[MAX_MAPNAMELENGTH];
187
char buff[MAX_LISTBOXWIDTH];
188
servernode_t* servernode;
192
menuframework_s menu;
199
menuradiobutton_s showfull;
200
menuradiobutton_s showempty;
208
menutext_s statusbar;
212
menubitmap_s refresh;
213
menubitmap_s specify;
217
pinglist_t pinglist[MAX_PINGREQUESTS];
218
table_t table[MAX_LISTBOXITEMS];
219
char* items[MAX_LISTBOXITEMS];
220
int numqueriedservers;
222
servernode_t *serverlist;
224
qboolean refreshservers;
228
char favoriteaddresses[MAX_FAVORITESERVERS][MAX_ADDRESSLENGTH];
229
int numfavoriteaddresses;
231
menulist_s punkbuster;
235
static arenaservers_t g_arenaservers;
238
static servernode_t g_globalserverlist[MAX_GLOBALSERVERS];
239
static int g_numglobalservers;
240
static servernode_t g_localserverlist[MAX_LOCALSERVERS];
241
static int g_numlocalservers;
242
static servernode_t g_favoriteserverlist[MAX_FAVORITESERVERS];
243
static int g_numfavoriteservers;
244
static servernode_t g_mplayerserverlist[MAX_GLOBALSERVERS];
245
static int g_nummplayerservers;
246
static int g_servertype;
247
static int g_gametype;
248
static int g_sortkey;
249
static int g_emptyservers;
250
static int g_fullservers;
258
static int ArenaServers_MaxPing( void ) {
261
maxPing = (int)trap_Cvar_VariableValue( "cl_maxPing" );
262
if( maxPing < 100 ) {
274
static int QDECL ArenaServers_Compare( const void *arg1, const void *arg2 ) {
280
t1 = (servernode_t *)arg1;
281
t2 = (servernode_t *)arg2;
283
switch( g_sortkey ) {
285
return Q_stricmp( t1->hostname, t2->hostname );
288
return Q_stricmp( t1->mapname, t2->mapname );
291
f1 = t1->maxclients - t1->numclients;
296
f2 = t2->maxclients - t2->numclients;
310
if( t1->gametype < t2->gametype ) {
313
if( t1->gametype == t2->gametype ) {
319
if( t1->pingtime < t2->pingtime ) {
322
if( t1->pingtime > t2->pingtime ) {
325
return Q_stricmp( t1->hostname, t2->hostname );
337
static void ArenaServers_Go( void ) {
338
servernode_t* servernode;
340
servernode = g_arenaservers.table[g_arenaservers.list.curvalue].servernode;
342
trap_Cmd_ExecuteText( EXEC_APPEND, va( "connect %s\n", servernode->adrstr ) );
349
ArenaServers_UpdatePicture
352
static void ArenaServers_UpdatePicture( void ) {
353
static char picname[64];
354
servernode_t* servernodeptr;
356
if( !g_arenaservers.list.numitems ) {
357
g_arenaservers.mappic.generic.name = NULL;
360
servernodeptr = g_arenaservers.table[g_arenaservers.list.curvalue].servernode;
361
Com_sprintf( picname, sizeof(picname), "levelshots/%s.tga", servernodeptr->mapname );
362
g_arenaservers.mappic.generic.name = picname;
366
// force shader update during draw
367
g_arenaservers.mappic.shader = 0;
373
ArenaServers_UpdateMenu
376
static void ArenaServers_UpdateMenu( void ) {
381
servernode_t* servernodeptr;
385
if( g_arenaservers.numqueriedservers > 0 ) {
387
if( g_arenaservers.refreshservers && ( g_arenaservers.currentping <= g_arenaservers.numqueriedservers ) ) {
389
Com_sprintf( g_arenaservers.status.string, MAX_STATUSLENGTH, "%d of %d Arena Servers.", g_arenaservers.currentping, g_arenaservers.numqueriedservers);
390
g_arenaservers.statusbar.string = "Press SPACE to stop";
391
qsort( g_arenaservers.serverlist, *g_arenaservers.numservers, sizeof( servernode_t ), ArenaServers_Compare);
394
// all servers pinged - enable controls
395
g_arenaservers.master.generic.flags &= ~QMF_GRAYED;
396
g_arenaservers.gametype.generic.flags &= ~QMF_GRAYED;
397
g_arenaservers.sortkey.generic.flags &= ~QMF_GRAYED;
398
g_arenaservers.showempty.generic.flags &= ~QMF_GRAYED;
399
g_arenaservers.showfull.generic.flags &= ~QMF_GRAYED;
400
g_arenaservers.list.generic.flags &= ~QMF_GRAYED;
401
g_arenaservers.refresh.generic.flags &= ~QMF_GRAYED;
402
g_arenaservers.go.generic.flags &= ~QMF_GRAYED;
403
g_arenaservers.punkbuster.generic.flags &= ~QMF_GRAYED;
406
if( g_servertype == AS_GLOBAL || g_servertype == AS_MPLAYER ) {
407
g_arenaservers.statusbar.string = quake3worldMessage;
410
g_arenaservers.statusbar.string = "";
417
if( g_arenaservers.refreshservers ) {
418
strcpy( g_arenaservers.status.string,"Scanning For Servers." );
419
g_arenaservers.statusbar.string = "Press SPACE to stop";
421
// disable controls during refresh
422
g_arenaservers.master.generic.flags |= QMF_GRAYED;
423
g_arenaservers.gametype.generic.flags |= QMF_GRAYED;
424
g_arenaservers.sortkey.generic.flags |= QMF_GRAYED;
425
g_arenaservers.showempty.generic.flags |= QMF_GRAYED;
426
g_arenaservers.showfull.generic.flags |= QMF_GRAYED;
427
g_arenaservers.list.generic.flags |= QMF_GRAYED;
428
g_arenaservers.refresh.generic.flags |= QMF_GRAYED;
429
g_arenaservers.go.generic.flags |= QMF_GRAYED;
430
g_arenaservers.punkbuster.generic.flags |= QMF_GRAYED;
433
if( g_arenaservers.numqueriedservers < 0 ) {
434
strcpy(g_arenaservers.status.string,"No Response From Master Server." );
437
strcpy(g_arenaservers.status.string,"No Servers Found." );
441
if( g_servertype == AS_GLOBAL || g_servertype == AS_MPLAYER ) {
442
g_arenaservers.statusbar.string = quake3worldMessage;
445
g_arenaservers.statusbar.string = "";
448
// end of refresh - set control state
449
g_arenaservers.master.generic.flags &= ~QMF_GRAYED;
450
g_arenaservers.gametype.generic.flags &= ~QMF_GRAYED;
451
g_arenaservers.sortkey.generic.flags &= ~QMF_GRAYED;
452
g_arenaservers.showempty.generic.flags &= ~QMF_GRAYED;
453
g_arenaservers.showfull.generic.flags &= ~QMF_GRAYED;
454
g_arenaservers.list.generic.flags |= QMF_GRAYED;
455
g_arenaservers.refresh.generic.flags &= ~QMF_GRAYED;
456
g_arenaservers.go.generic.flags |= QMF_GRAYED;
457
g_arenaservers.punkbuster.generic.flags &= ~QMF_GRAYED;
461
g_arenaservers.list.numitems = 0;
462
g_arenaservers.list.curvalue = 0;
463
g_arenaservers.list.top = 0;
466
ArenaServers_UpdatePicture();
470
// build list box strings - apply culling filters
471
servernodeptr = g_arenaservers.serverlist;
472
count = *g_arenaservers.numservers;
473
for( i = 0, j = 0; i < count; i++, servernodeptr++ ) {
474
tableptr = &g_arenaservers.table[j];
475
tableptr->servernode = servernodeptr;
476
buff = tableptr->buff;
478
// can only cull valid results
479
if( !g_emptyservers && !servernodeptr->numclients ) {
483
if( !g_fullservers && ( servernodeptr->numclients == servernodeptr->maxclients ) ) {
487
switch( g_gametype ) {
492
if( servernodeptr->gametype != GT_FFA ) {
498
if( servernodeptr->gametype != GT_TEAM ) {
504
if( servernodeptr->gametype != GT_TOURNAMENT ) {
510
if( servernodeptr->gametype != GT_CTF ) {
516
if( servernodeptr->pingtime < servernodeptr->minPing ) {
517
pingColor = S_COLOR_BLUE;
519
else if( servernodeptr->maxPing && servernodeptr->pingtime > servernodeptr->maxPing ) {
520
pingColor = S_COLOR_BLUE;
522
else if( servernodeptr->pingtime < 200 ) {
523
pingColor = S_COLOR_GREEN;
525
else if( servernodeptr->pingtime < 400 ) {
526
pingColor = S_COLOR_YELLOW;
529
pingColor = S_COLOR_RED;
532
Com_sprintf( buff, MAX_LISTBOXWIDTH, "%-20.20s %-12.12s %2d/%2d %-8.8s %3s %s%3d " S_COLOR_YELLOW "%s",
533
servernodeptr->hostname, servernodeptr->mapname, servernodeptr->numclients,
534
servernodeptr->maxclients, servernodeptr->gamename,
535
netnames[servernodeptr->nettype], pingColor, servernodeptr->pingtime, servernodeptr->bPB ? "Yes" : "No" );
539
g_arenaservers.list.numitems = j;
540
g_arenaservers.list.curvalue = 0;
541
g_arenaservers.list.top = 0;
544
ArenaServers_UpdatePicture();
553
static void ArenaServers_Remove( void )
556
servernode_t* servernodeptr;
559
if (!g_arenaservers.list.numitems)
562
// remove selected item from display list
563
// items are in scattered order due to sort and cull
564
// perform delete on list box contents, resync all lists
566
tableptr = &g_arenaservers.table[g_arenaservers.list.curvalue];
567
servernodeptr = tableptr->servernode;
569
// find address in master list
570
for (i=0; i<g_arenaservers.numfavoriteaddresses; i++)
571
if (!Q_stricmp(g_arenaservers.favoriteaddresses[i],servernodeptr->adrstr))
574
// delete address from master list
575
if (i <= g_arenaservers.numfavoriteaddresses-1)
577
if (i < g_arenaservers.numfavoriteaddresses-1)
580
memcpy( &g_arenaservers.favoriteaddresses[i], &g_arenaservers.favoriteaddresses[i+1], (g_arenaservers.numfavoriteaddresses - i - 1)*sizeof(MAX_ADDRESSLENGTH));
582
g_arenaservers.numfavoriteaddresses--;
585
// find address in server list
586
for (i=0; i<g_numfavoriteservers; i++)
587
if (&g_favoriteserverlist[i] == servernodeptr)
590
// delete address from server list
591
if (i <= g_numfavoriteservers-1)
593
if (i < g_numfavoriteservers-1)
596
memcpy( &g_favoriteserverlist[i], &g_favoriteserverlist[i+1], (g_numfavoriteservers - i - 1)*sizeof(servernode_t));
598
g_numfavoriteservers--;
601
g_arenaservers.numqueriedservers = g_arenaservers.numfavoriteaddresses;
602
g_arenaservers.currentping = g_arenaservers.numfavoriteaddresses;
611
static void ArenaServers_Insert( char* adrstr, char* info, int pingtime )
613
servernode_t* servernodeptr;
618
if ((pingtime >= ArenaServers_MaxPing()) && (g_servertype != AS_FAVORITES))
620
// slow global or local servers do not get entered
624
if (*g_arenaservers.numservers >= g_arenaservers.maxservers) {
626
servernodeptr = g_arenaservers.serverlist+(*g_arenaservers.numservers)-1;
629
servernodeptr = g_arenaservers.serverlist+(*g_arenaservers.numservers);
630
(*g_arenaservers.numservers)++;
633
Q_strncpyz( servernodeptr->adrstr, adrstr, MAX_ADDRESSLENGTH );
635
Q_strncpyz( servernodeptr->hostname, Info_ValueForKey( info, "hostname"), MAX_HOSTNAMELENGTH );
636
Q_CleanStr( servernodeptr->hostname );
637
Q_strupr( servernodeptr->hostname );
639
Q_strncpyz( servernodeptr->mapname, Info_ValueForKey( info, "mapname"), MAX_MAPNAMELENGTH );
640
Q_CleanStr( servernodeptr->mapname );
641
Q_strupr( servernodeptr->mapname );
643
servernodeptr->numclients = atoi( Info_ValueForKey( info, "clients") );
644
servernodeptr->maxclients = atoi( Info_ValueForKey( info, "sv_maxclients") );
645
servernodeptr->pingtime = pingtime;
646
servernodeptr->minPing = atoi( Info_ValueForKey( info, "minPing") );
647
servernodeptr->maxPing = atoi( Info_ValueForKey( info, "maxPing") );
648
servernodeptr->bPB = atoi( Info_ValueForKey( info, "punkbuster") );
651
s = Info_ValueForKey( info, "nettype" );
656
servernodeptr->nettype = 0;
659
else if (!Q_stricmp( netnames[i], s ))
661
servernodeptr->nettype = i;
666
servernodeptr->nettype = atoi(Info_ValueForKey(info, "nettype"));
668
s = Info_ValueForKey( info, "game");
669
i = atoi( Info_ValueForKey( info, "gametype") );
677
servernodeptr->gametype = i;//-1;
678
Q_strncpyz( servernodeptr->gamename, s, sizeof(servernodeptr->gamename) );
681
servernodeptr->gametype = i;
682
Q_strncpyz( servernodeptr->gamename, gamenames[i], sizeof(servernodeptr->gamename) );
689
ArenaServers_InsertFavorites
691
Insert nonresponsive address book entries into display lists.
694
void ArenaServers_InsertFavorites( void )
698
char info[MAX_INFO_STRING];
700
// resync existing results with new or deleted cvars
702
Info_SetValueForKey( info, "hostname", "No Response" );
703
for (i=0; i<g_arenaservers.numfavoriteaddresses; i++)
705
// find favorite address in refresh list
706
for (j=0; j<g_numfavoriteservers; j++)
707
if (!Q_stricmp(g_arenaservers.favoriteaddresses[i],g_favoriteserverlist[j].adrstr))
710
if ( j >= g_numfavoriteservers)
712
// not in list, add it
713
ArenaServers_Insert( g_arenaservers.favoriteaddresses[i], info, ArenaServers_MaxPing() );
721
ArenaServers_LoadFavorites
723
Load cvar address book entries into local lists.
726
void ArenaServers_LoadFavorites( void )
731
char emptyinfo[MAX_INFO_STRING];
732
char adrstr[MAX_ADDRESSLENGTH];
733
servernode_t templist[MAX_FAVORITESERVERS];
740
memcpy( templist, g_favoriteserverlist, sizeof(servernode_t)*MAX_FAVORITESERVERS );
741
numtempitems = g_numfavoriteservers;
743
// clear the current for sync
744
memset( g_favoriteserverlist, 0, sizeof(servernode_t)*MAX_FAVORITESERVERS );
745
g_numfavoriteservers = 0;
747
// resync existing results with new or deleted cvars
748
for (i=0; i<MAX_FAVORITESERVERS; i++)
750
trap_Cvar_VariableStringBuffer( va("server%d",i+1), adrstr, MAX_ADDRESSLENGTH );
754
// quick sanity check to avoid slow domain name resolving
755
// first character must be numeric
756
if (adrstr[0] < '0' || adrstr[0] > '9')
759
// favorite server addresses must be maintained outside refresh list
760
// this mimics local and global netadr's stored in client
761
// these can be fetched to fill ping list
762
strcpy( g_arenaservers.favoriteaddresses[g_numfavoriteservers], adrstr );
764
// find this server in the old list
765
for (j=0; j<numtempitems; j++)
766
if (!Q_stricmp( templist[j].adrstr, adrstr ))
769
if (j < numtempitems)
771
// found server - add exisiting results
772
memcpy( &g_favoriteserverlist[g_numfavoriteservers], &templist[j], sizeof(servernode_t) );
778
Q_strncpyz( g_favoriteserverlist[g_numfavoriteservers].adrstr, adrstr, MAX_ADDRESSLENGTH );
779
g_favoriteserverlist[g_numfavoriteservers].pingtime = ArenaServers_MaxPing();
782
g_numfavoriteservers++;
785
g_arenaservers.numfavoriteaddresses = g_numfavoriteservers;
789
// no results were found, reset server list
790
// list will be automatically refreshed when selected
791
g_numfavoriteservers = 0;
798
ArenaServers_StopRefresh
801
static void ArenaServers_StopRefresh( void )
803
if (!g_arenaservers.refreshservers)
804
// not currently refreshing
807
g_arenaservers.refreshservers = qfalse;
809
if (g_servertype == AS_FAVORITES)
811
// nonresponsive favorites must be shown
812
ArenaServers_InsertFavorites();
816
if (g_arenaservers.numqueriedservers >= 0)
818
g_arenaservers.currentping = *g_arenaservers.numservers;
819
g_arenaservers.numqueriedservers = *g_arenaservers.numservers;
823
qsort( g_arenaservers.serverlist, *g_arenaservers.numservers, sizeof( servernode_t ), ArenaServers_Compare);
825
ArenaServers_UpdateMenu();
831
ArenaServers_DoRefresh
834
static void ArenaServers_DoRefresh( void )
840
char adrstr[MAX_ADDRESSLENGTH];
841
char info[MAX_INFO_STRING];
843
if (uis.realtime < g_arenaservers.refreshtime)
845
if (g_servertype != AS_FAVORITES) {
846
if (g_servertype == AS_LOCAL) {
847
if (!trap_LAN_GetServerCount(g_servertype)) {
851
if (trap_LAN_GetServerCount(g_servertype) < 0) {
852
// still waiting for response
858
if (uis.realtime < g_arenaservers.nextpingtime)
860
// wait for time trigger
864
// trigger at 10Hz intervals
865
g_arenaservers.nextpingtime = uis.realtime + 10;
867
// process ping results
868
maxPing = ArenaServers_MaxPing();
869
for (i=0; i<MAX_PINGREQUESTS; i++)
871
trap_LAN_GetPing( i, adrstr, MAX_ADDRESSLENGTH, &time );
874
// ignore empty or pending pings
878
// find ping result in our local list
879
for (j=0; j<MAX_PINGREQUESTS; j++)
880
if (!Q_stricmp( adrstr, g_arenaservers.pinglist[j].adrstr ))
883
if (j < MAX_PINGREQUESTS)
888
time = uis.realtime - g_arenaservers.pinglist[j].start;
904
trap_LAN_GetPingInfo( i, info, MAX_INFO_STRING );
907
// insert ping results
908
ArenaServers_Insert( adrstr, info, time );
910
// clear this query from internal list
911
g_arenaservers.pinglist[j].adrstr[0] = '\0';
914
// clear this query from external list
915
trap_LAN_ClearPing( i );
918
// get results of servers query
919
// counts can increase as servers respond
920
if (g_servertype == AS_FAVORITES) {
921
g_arenaservers.numqueriedservers = g_arenaservers.numfavoriteaddresses;
923
g_arenaservers.numqueriedservers = trap_LAN_GetServerCount(g_servertype);
926
// if (g_arenaservers.numqueriedservers > g_arenaservers.maxservers)
927
// g_arenaservers.numqueriedservers = g_arenaservers.maxservers;
929
// send ping requests in reasonable bursts
930
// iterate ping through all found servers
931
for (i=0; i<MAX_PINGREQUESTS && g_arenaservers.currentping < g_arenaservers.numqueriedservers; i++)
933
if (trap_LAN_GetPingQueueCount() >= MAX_PINGREQUESTS)
935
// ping queue is full
940
for (j=0; j<MAX_PINGREQUESTS; j++)
941
if (!g_arenaservers.pinglist[j].adrstr[0])
944
if (j >= MAX_PINGREQUESTS)
945
// no empty slots available yet - wait for timeout
948
// get an address to ping
950
if (g_servertype == AS_FAVORITES) {
951
strcpy( adrstr, g_arenaservers.favoriteaddresses[g_arenaservers.currentping] );
953
trap_LAN_GetServerAddressString(g_servertype, g_arenaservers.currentping, adrstr, MAX_ADDRESSLENGTH );
956
strcpy( g_arenaservers.pinglist[j].adrstr, adrstr );
957
g_arenaservers.pinglist[j].start = uis.realtime;
959
trap_Cmd_ExecuteText( EXEC_NOW, va( "ping %s\n", adrstr ) );
961
// advance to next server
962
g_arenaservers.currentping++;
965
if (!trap_LAN_GetPingQueueCount())
967
// all pings completed
968
ArenaServers_StopRefresh();
972
// update the user interface with ping status
973
ArenaServers_UpdateMenu();
979
ArenaServers_StartRefresh
982
static void ArenaServers_StartRefresh( void )
985
char myargs[32], protocol[32];
987
memset( g_arenaservers.serverlist, 0, g_arenaservers.maxservers*sizeof(table_t) );
989
for (i=0; i<MAX_PINGREQUESTS; i++)
991
g_arenaservers.pinglist[i].adrstr[0] = '\0';
992
trap_LAN_ClearPing( i );
995
g_arenaservers.refreshservers = qtrue;
996
g_arenaservers.currentping = 0;
997
g_arenaservers.nextpingtime = 0;
998
*g_arenaservers.numservers = 0;
999
g_arenaservers.numqueriedservers = 0;
1001
// allow max 5 seconds for responses
1002
g_arenaservers.refreshtime = uis.realtime + 5000;
1004
// place menu in zeroed state
1005
ArenaServers_UpdateMenu();
1007
if( g_servertype == AS_LOCAL ) {
1008
trap_Cmd_ExecuteText( EXEC_APPEND, "localservers\n" );
1012
if( g_servertype == AS_GLOBAL || g_servertype == AS_MPLAYER ) {
1013
if( g_servertype == AS_GLOBAL ) {
1020
switch( g_arenaservers.gametype.curvalue ) {
1027
strcpy( myargs, " ffa" );
1030
case GAMES_TEAMPLAY:
1031
strcpy( myargs, " team" );
1035
strcpy( myargs, " tourney" );
1039
strcpy( myargs, " ctf" );
1044
if (g_emptyservers) {
1045
strcat(myargs, " empty");
1048
if (g_fullservers) {
1049
strcat(myargs, " full");
1053
trap_Cvar_VariableStringBuffer( "debug_protocol", protocol, sizeof(protocol) );
1054
if (strlen(protocol)) {
1055
trap_Cmd_ExecuteText( EXEC_APPEND, va( "globalservers %d %s%s\n", i, protocol, myargs ));
1058
trap_Cmd_ExecuteText( EXEC_APPEND, va( "globalservers %d %d%s\n", i, (int)trap_Cvar_VariableValue( "protocol" ), myargs ) );
1066
ArenaServers_SaveChanges
1069
void ArenaServers_SaveChanges( void )
1073
for (i=0; i<g_arenaservers.numfavoriteaddresses; i++)
1074
trap_Cvar_Set( va("server%d",i+1), g_arenaservers.favoriteaddresses[i] );
1076
for (; i<MAX_FAVORITESERVERS; i++)
1077
trap_Cvar_Set( va("server%d",i+1), "" );
1086
void ArenaServers_Sort( int type ) {
1087
if( g_sortkey == type ) {
1092
qsort( g_arenaservers.serverlist, *g_arenaservers.numservers, sizeof( servernode_t ), ArenaServers_Compare);
1098
ArenaServers_SetType
1101
void ArenaServers_SetType( int type )
1103
if (g_servertype == type)
1106
g_servertype = type;
1111
g_arenaservers.remove.generic.flags |= (QMF_INACTIVE|QMF_HIDDEN);
1112
g_arenaservers.serverlist = g_localserverlist;
1113
g_arenaservers.numservers = &g_numlocalservers;
1114
g_arenaservers.maxservers = MAX_LOCALSERVERS;
1118
g_arenaservers.remove.generic.flags |= (QMF_INACTIVE|QMF_HIDDEN);
1119
g_arenaservers.serverlist = g_globalserverlist;
1120
g_arenaservers.numservers = &g_numglobalservers;
1121
g_arenaservers.maxservers = MAX_GLOBALSERVERS;
1125
g_arenaservers.remove.generic.flags &= ~(QMF_INACTIVE|QMF_HIDDEN);
1126
g_arenaservers.serverlist = g_favoriteserverlist;
1127
g_arenaservers.numservers = &g_numfavoriteservers;
1128
g_arenaservers.maxservers = MAX_FAVORITESERVERS;
1132
g_arenaservers.remove.generic.flags |= (QMF_INACTIVE|QMF_HIDDEN);
1133
g_arenaservers.serverlist = g_mplayerserverlist;
1134
g_arenaservers.numservers = &g_nummplayerservers;
1135
g_arenaservers.maxservers = MAX_GLOBALSERVERS;
1140
if( !*g_arenaservers.numservers ) {
1141
ArenaServers_StartRefresh();
1144
// avoid slow operation, use existing results
1145
g_arenaservers.currentping = *g_arenaservers.numservers;
1146
g_arenaservers.numqueriedservers = *g_arenaservers.numservers;
1147
ArenaServers_UpdateMenu();
1149
strcpy(g_arenaservers.status.string,"hit refresh to update");
1157
static void Punkbuster_ConfirmEnable( qboolean result ) {
1160
trap_SetPbClStatus(1);
1162
g_arenaservers.punkbuster.curvalue = Com_Clamp( 0, 1, trap_Cvar_VariableValue( "cl_punkbuster" ) );
1165
static void Punkbuster_ConfirmDisable( qboolean result ) {
1168
trap_SetPbClStatus(0);
1169
UI_Message( punkbuster_msg );
1171
g_arenaservers.punkbuster.curvalue = Com_Clamp( 0, 1, trap_Cvar_VariableValue( "cl_punkbuster" ) );
1179
static void ArenaServers_Event( void* ptr, int event ) {
1183
id = ((menucommon_s*)ptr)->id;
1185
if( event != QM_ACTIVATED && id != ID_LIST ) {
1191
value = g_arenaservers.master.curvalue;
1196
trap_Cvar_SetValue( "ui_browserMaster", value );
1197
ArenaServers_SetType( value );
1201
trap_Cvar_SetValue( "ui_browserGameType", g_arenaservers.gametype.curvalue );
1202
g_gametype = g_arenaservers.gametype.curvalue;
1203
ArenaServers_UpdateMenu();
1207
trap_Cvar_SetValue( "ui_browserSortKey", g_arenaservers.sortkey.curvalue );
1208
ArenaServers_Sort( g_arenaservers.sortkey.curvalue );
1209
ArenaServers_UpdateMenu();
1213
trap_Cvar_SetValue( "ui_browserShowFull", g_arenaservers.showfull.curvalue );
1214
g_fullservers = g_arenaservers.showfull.curvalue;
1215
ArenaServers_UpdateMenu();
1219
trap_Cvar_SetValue( "ui_browserShowEmpty", g_arenaservers.showempty.curvalue );
1220
g_emptyservers = g_arenaservers.showempty.curvalue;
1221
ArenaServers_UpdateMenu();
1225
if( event == QM_GOTFOCUS ) {
1226
ArenaServers_UpdatePicture();
1231
ScrollList_Key( &g_arenaservers.list, K_UPARROW );
1234
case ID_SCROLL_DOWN:
1235
ScrollList_Key( &g_arenaservers.list, K_DOWNARROW );
1239
ArenaServers_StopRefresh();
1240
ArenaServers_SaveChanges();
1245
ArenaServers_StartRefresh();
1249
UI_SpecifyServerMenu();
1253
UI_StartServerMenu( qtrue );
1261
ArenaServers_Remove();
1262
ArenaServers_UpdateMenu();
1266
if (g_arenaservers.punkbuster.curvalue)
1268
UI_ConfirmMenu_Style( "Enable Punkbuster?", UI_CENTER|UI_INVERSE|UI_SMALLFONT, 0, Punkbuster_ConfirmEnable );
1272
UI_ConfirmMenu_Style( "Disable Punkbuster?", UI_CENTER|UI_INVERSE|UI_SMALLFONT, 0, Punkbuster_ConfirmDisable );
1281
ArenaServers_MenuDraw
1284
static void ArenaServers_MenuDraw( void )
1286
if (g_arenaservers.refreshservers)
1287
ArenaServers_DoRefresh();
1289
Menu_Draw( &g_arenaservers.menu );
1295
ArenaServers_MenuKey
1298
static sfxHandle_t ArenaServers_MenuKey( int key ) {
1299
if( key == K_SPACE && g_arenaservers.refreshservers ) {
1300
ArenaServers_StopRefresh();
1301
return menu_move_sound;
1304
if( ( key == K_DEL || key == K_KP_DEL ) && ( g_servertype == AS_FAVORITES ) &&
1305
( Menu_ItemAtCursor( &g_arenaservers.menu) == &g_arenaservers.list ) ) {
1306
ArenaServers_Remove();
1307
ArenaServers_UpdateMenu();
1308
return menu_move_sound;
1311
if( key == K_MOUSE2 || key == K_ESCAPE ) {
1312
ArenaServers_StopRefresh();
1313
ArenaServers_SaveChanges();
1317
return Menu_DefaultKey( &g_arenaservers.menu, key );
1323
ArenaServers_MenuInit
1326
static void ArenaServers_MenuInit( void ) {
1331
static char statusbuffer[MAX_STATUSLENGTH];
1333
// zero set all our globals
1334
memset( &g_arenaservers, 0 ,sizeof(arenaservers_t) );
1336
ArenaServers_Cache();
1338
g_arenaservers.menu.fullscreen = qtrue;
1339
g_arenaservers.menu.wrapAround = qtrue;
1340
g_arenaservers.menu.draw = ArenaServers_MenuDraw;
1341
g_arenaservers.menu.key = ArenaServers_MenuKey;
1343
g_arenaservers.banner.generic.type = MTYPE_BTEXT;
1344
g_arenaservers.banner.generic.flags = QMF_CENTER_JUSTIFY;
1345
g_arenaservers.banner.generic.x = 320;
1346
g_arenaservers.banner.generic.y = 16;
1347
g_arenaservers.banner.string = "ARENA SERVERS";
1348
g_arenaservers.banner.style = UI_CENTER;
1349
g_arenaservers.banner.color = color_white;
1352
g_arenaservers.master.generic.type = MTYPE_SPINCONTROL;
1353
g_arenaservers.master.generic.name = "Servers:";
1354
g_arenaservers.master.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
1355
g_arenaservers.master.generic.callback = ArenaServers_Event;
1356
g_arenaservers.master.generic.id = ID_MASTER;
1357
g_arenaservers.master.generic.x = 320;
1358
g_arenaservers.master.generic.y = y;
1359
g_arenaservers.master.itemnames = master_items;
1361
y += SMALLCHAR_HEIGHT;
1362
g_arenaservers.gametype.generic.type = MTYPE_SPINCONTROL;
1363
g_arenaservers.gametype.generic.name = "Game Type:";
1364
g_arenaservers.gametype.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
1365
g_arenaservers.gametype.generic.callback = ArenaServers_Event;
1366
g_arenaservers.gametype.generic.id = ID_GAMETYPE;
1367
g_arenaservers.gametype.generic.x = 320;
1368
g_arenaservers.gametype.generic.y = y;
1369
g_arenaservers.gametype.itemnames = servertype_items;
1371
y += SMALLCHAR_HEIGHT;
1372
g_arenaservers.sortkey.generic.type = MTYPE_SPINCONTROL;
1373
g_arenaservers.sortkey.generic.name = "Sort By:";
1374
g_arenaservers.sortkey.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
1375
g_arenaservers.sortkey.generic.callback = ArenaServers_Event;
1376
g_arenaservers.sortkey.generic.id = ID_SORTKEY;
1377
g_arenaservers.sortkey.generic.x = 320;
1378
g_arenaservers.sortkey.generic.y = y;
1379
g_arenaservers.sortkey.itemnames = sortkey_items;
1381
y += SMALLCHAR_HEIGHT;
1382
g_arenaservers.showfull.generic.type = MTYPE_RADIOBUTTON;
1383
g_arenaservers.showfull.generic.name = "Show Full:";
1384
g_arenaservers.showfull.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
1385
g_arenaservers.showfull.generic.callback = ArenaServers_Event;
1386
g_arenaservers.showfull.generic.id = ID_SHOW_FULL;
1387
g_arenaservers.showfull.generic.x = 320;
1388
g_arenaservers.showfull.generic.y = y;
1390
y += SMALLCHAR_HEIGHT;
1391
g_arenaservers.showempty.generic.type = MTYPE_RADIOBUTTON;
1392
g_arenaservers.showempty.generic.name = "Show Empty:";
1393
g_arenaservers.showempty.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
1394
g_arenaservers.showempty.generic.callback = ArenaServers_Event;
1395
g_arenaservers.showempty.generic.id = ID_SHOW_EMPTY;
1396
g_arenaservers.showempty.generic.x = 320;
1397
g_arenaservers.showempty.generic.y = y;
1399
y += 3 * SMALLCHAR_HEIGHT;
1400
g_arenaservers.list.generic.type = MTYPE_SCROLLLIST;
1401
g_arenaservers.list.generic.flags = QMF_HIGHLIGHT_IF_FOCUS;
1402
g_arenaservers.list.generic.id = ID_LIST;
1403
g_arenaservers.list.generic.callback = ArenaServers_Event;
1404
g_arenaservers.list.generic.x = 72;
1405
g_arenaservers.list.generic.y = y;
1406
g_arenaservers.list.width = MAX_LISTBOXWIDTH;
1407
g_arenaservers.list.height = 11;
1408
g_arenaservers.list.itemnames = (const char **)g_arenaservers.items;
1409
for( i = 0; i < MAX_LISTBOXITEMS; i++ ) {
1410
g_arenaservers.items[i] = g_arenaservers.table[i].buff;
1413
g_arenaservers.mappic.generic.type = MTYPE_BITMAP;
1414
g_arenaservers.mappic.generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE;
1415
g_arenaservers.mappic.generic.x = 72;
1416
g_arenaservers.mappic.generic.y = 80;
1417
g_arenaservers.mappic.width = 128;
1418
g_arenaservers.mappic.height = 96;
1419
g_arenaservers.mappic.errorpic = ART_UNKNOWNMAP;
1421
g_arenaservers.arrows.generic.type = MTYPE_BITMAP;
1422
g_arenaservers.arrows.generic.name = ART_ARROWS0;
1423
g_arenaservers.arrows.generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE;
1424
g_arenaservers.arrows.generic.callback = ArenaServers_Event;
1425
g_arenaservers.arrows.generic.x = 512+48;
1426
g_arenaservers.arrows.generic.y = 240-64+16;
1427
g_arenaservers.arrows.width = 64;
1428
g_arenaservers.arrows.height = 128;
1430
g_arenaservers.up.generic.type = MTYPE_BITMAP;
1431
g_arenaservers.up.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_MOUSEONLY;
1432
g_arenaservers.up.generic.callback = ArenaServers_Event;
1433
g_arenaservers.up.generic.id = ID_SCROLL_UP;
1434
g_arenaservers.up.generic.x = 512+48;
1435
g_arenaservers.up.generic.y = 240-64+16;
1436
g_arenaservers.up.width = 64;
1437
g_arenaservers.up.height = 64;
1438
g_arenaservers.up.focuspic = ART_ARROWS_UP;
1440
g_arenaservers.down.generic.type = MTYPE_BITMAP;
1441
g_arenaservers.down.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_MOUSEONLY;
1442
g_arenaservers.down.generic.callback = ArenaServers_Event;
1443
g_arenaservers.down.generic.id = ID_SCROLL_DOWN;
1444
g_arenaservers.down.generic.x = 512+48;
1445
g_arenaservers.down.generic.y = 240+16;
1446
g_arenaservers.down.width = 64;
1447
g_arenaservers.down.height = 64;
1448
g_arenaservers.down.focuspic = ART_ARROWS_DOWN;
1451
g_arenaservers.status.generic.type = MTYPE_TEXT;
1452
g_arenaservers.status.generic.x = 320;
1453
g_arenaservers.status.generic.y = y;
1454
g_arenaservers.status.string = statusbuffer;
1455
g_arenaservers.status.style = UI_CENTER|UI_SMALLFONT;
1456
g_arenaservers.status.color = menu_text_color;
1458
y += SMALLCHAR_HEIGHT;
1459
g_arenaservers.statusbar.generic.type = MTYPE_TEXT;
1460
g_arenaservers.statusbar.generic.x = 320;
1461
g_arenaservers.statusbar.generic.y = y;
1462
g_arenaservers.statusbar.string = "";
1463
g_arenaservers.statusbar.style = UI_CENTER|UI_SMALLFONT;
1464
g_arenaservers.statusbar.color = text_color_normal;
1466
g_arenaservers.remove.generic.type = MTYPE_BITMAP;
1467
g_arenaservers.remove.generic.name = ART_REMOVE0;
1468
g_arenaservers.remove.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
1469
g_arenaservers.remove.generic.callback = ArenaServers_Event;
1470
g_arenaservers.remove.generic.id = ID_REMOVE;
1471
g_arenaservers.remove.generic.x = 450;
1472
g_arenaservers.remove.generic.y = 86;
1473
g_arenaservers.remove.width = 96;
1474
g_arenaservers.remove.height = 48;
1475
g_arenaservers.remove.focuspic = ART_REMOVE1;
1477
g_arenaservers.back.generic.type = MTYPE_BITMAP;
1478
g_arenaservers.back.generic.name = ART_BACK0;
1479
g_arenaservers.back.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
1480
g_arenaservers.back.generic.callback = ArenaServers_Event;
1481
g_arenaservers.back.generic.id = ID_BACK;
1482
g_arenaservers.back.generic.x = 0;
1483
g_arenaservers.back.generic.y = 480-64;
1484
g_arenaservers.back.width = 128;
1485
g_arenaservers.back.height = 64;
1486
g_arenaservers.back.focuspic = ART_BACK1;
1488
g_arenaservers.specify.generic.type = MTYPE_BITMAP;
1489
g_arenaservers.specify.generic.name = ART_SPECIFY0;
1490
g_arenaservers.specify.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
1491
g_arenaservers.specify.generic.callback = ArenaServers_Event;
1492
g_arenaservers.specify.generic.id = ID_SPECIFY;
1493
g_arenaservers.specify.generic.x = 128;
1494
g_arenaservers.specify.generic.y = 480-64;
1495
g_arenaservers.specify.width = 128;
1496
g_arenaservers.specify.height = 64;
1497
g_arenaservers.specify.focuspic = ART_SPECIFY1;
1499
g_arenaservers.refresh.generic.type = MTYPE_BITMAP;
1500
g_arenaservers.refresh.generic.name = ART_REFRESH0;
1501
g_arenaservers.refresh.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
1502
g_arenaservers.refresh.generic.callback = ArenaServers_Event;
1503
g_arenaservers.refresh.generic.id = ID_REFRESH;
1504
g_arenaservers.refresh.generic.x = 256;
1505
g_arenaservers.refresh.generic.y = 480-64;
1506
g_arenaservers.refresh.width = 128;
1507
g_arenaservers.refresh.height = 64;
1508
g_arenaservers.refresh.focuspic = ART_REFRESH1;
1510
g_arenaservers.create.generic.type = MTYPE_BITMAP;
1511
g_arenaservers.create.generic.name = ART_CREATE0;
1512
g_arenaservers.create.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
1513
g_arenaservers.create.generic.callback = ArenaServers_Event;
1514
g_arenaservers.create.generic.id = ID_CREATE;
1515
g_arenaservers.create.generic.x = 384;
1516
g_arenaservers.create.generic.y = 480-64;
1517
g_arenaservers.create.width = 128;
1518
g_arenaservers.create.height = 64;
1519
g_arenaservers.create.focuspic = ART_CREATE1;
1521
g_arenaservers.go.generic.type = MTYPE_BITMAP;
1522
g_arenaservers.go.generic.name = ART_CONNECT0;
1523
g_arenaservers.go.generic.flags = QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS;
1524
g_arenaservers.go.generic.callback = ArenaServers_Event;
1525
g_arenaservers.go.generic.id = ID_CONNECT;
1526
g_arenaservers.go.generic.x = 640;
1527
g_arenaservers.go.generic.y = 480-64;
1528
g_arenaservers.go.width = 128;
1529
g_arenaservers.go.height = 64;
1530
g_arenaservers.go.focuspic = ART_CONNECT1;
1532
g_arenaservers.punkbuster.generic.type = MTYPE_SPINCONTROL;
1533
g_arenaservers.punkbuster.generic.name = "Punkbuster:";
1534
g_arenaservers.punkbuster.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
1535
g_arenaservers.punkbuster.generic.callback = ArenaServers_Event;
1536
g_arenaservers.punkbuster.generic.id = ID_PUNKBUSTER;
1537
g_arenaservers.punkbuster.generic.x = 480+32;
1538
g_arenaservers.punkbuster.generic.y = 144;
1539
g_arenaservers.punkbuster.itemnames = punkbuster_items;
1541
g_arenaservers.pblogo.generic.type = MTYPE_BITMAP;
1542
g_arenaservers.pblogo.generic.name = ART_PUNKBUSTER;
1543
g_arenaservers.pblogo.generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE;
1544
g_arenaservers.pblogo.generic.x = 526;
1545
g_arenaservers.pblogo.generic.y = 176;
1546
g_arenaservers.pblogo.width = 32;
1547
g_arenaservers.pblogo.height = 16;
1548
g_arenaservers.pblogo.errorpic = ART_UNKNOWNMAP;
1550
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.banner );
1552
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.master );
1553
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.gametype );
1554
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.sortkey );
1555
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.showfull);
1556
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.showempty );
1558
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.mappic );
1559
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.list );
1560
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.status );
1561
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.statusbar );
1562
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.arrows );
1563
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.up );
1564
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.down );
1566
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.remove );
1567
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.back );
1568
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.specify );
1569
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.refresh );
1570
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.create );
1571
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.go );
1573
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.punkbuster );
1574
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.pblogo );
1576
ArenaServers_LoadFavorites();
1578
g_servertype = Com_Clamp( 0, 3, ui_browserMaster.integer );
1579
// hack to get rid of MPlayer stuff
1580
value = g_servertype;
1583
g_arenaservers.master.curvalue = value;
1585
g_gametype = Com_Clamp( 0, 4, ui_browserGameType.integer );
1586
g_arenaservers.gametype.curvalue = g_gametype;
1588
g_sortkey = Com_Clamp( 0, 4, ui_browserSortKey.integer );
1589
g_arenaservers.sortkey.curvalue = g_sortkey;
1591
g_fullservers = Com_Clamp( 0, 1, ui_browserShowFull.integer );
1592
g_arenaservers.showfull.curvalue = g_fullservers;
1594
g_emptyservers = Com_Clamp( 0, 1, ui_browserShowEmpty.integer );
1595
g_arenaservers.showempty.curvalue = g_emptyservers;
1597
g_arenaservers.punkbuster.curvalue = Com_Clamp( 0, 1, trap_Cvar_VariableValue( "cl_punkbuster" ) );
1599
// force to initial state and refresh
1600
type = g_servertype;
1602
ArenaServers_SetType( type );
1604
trap_Cvar_Register(NULL, "debug_protocol", "", 0 );
1613
void ArenaServers_Cache( void ) {
1614
trap_R_RegisterShaderNoMip( ART_BACK0 );
1615
trap_R_RegisterShaderNoMip( ART_BACK1 );
1616
trap_R_RegisterShaderNoMip( ART_CREATE0 );
1617
trap_R_RegisterShaderNoMip( ART_CREATE1 );
1618
trap_R_RegisterShaderNoMip( ART_SPECIFY0 );
1619
trap_R_RegisterShaderNoMip( ART_SPECIFY1 );
1620
trap_R_RegisterShaderNoMip( ART_REFRESH0 );
1621
trap_R_RegisterShaderNoMip( ART_REFRESH1 );
1622
trap_R_RegisterShaderNoMip( ART_CONNECT0 );
1623
trap_R_RegisterShaderNoMip( ART_CONNECT1 );
1624
trap_R_RegisterShaderNoMip( ART_ARROWS0 );
1625
trap_R_RegisterShaderNoMip( ART_ARROWS_UP );
1626
trap_R_RegisterShaderNoMip( ART_ARROWS_DOWN );
1627
trap_R_RegisterShaderNoMip( ART_UNKNOWNMAP );
1628
trap_R_RegisterShaderNoMip( ART_PUNKBUSTER );
1637
void UI_ArenaServersMenu( void ) {
1638
ArenaServers_MenuInit();
1639
UI_PushMenu( &g_arenaservers.menu );