diff options
author | zakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-08-26 17:39:27 +0000 |
---|---|---|
committer | zakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-08-26 17:39:27 +0000 |
commit | 6bf20c78f5b69d40bcc4931df93d29198435ab67 (patch) | |
tree | e3eda937a05d7db42de725b7013bd0344b987f34 /code/q3_ui/ui_servers2.c | |
parent | 872d4d7f55af706737ffb361bb76ad13e7496770 (diff) | |
download | ioquake3-aero-6bf20c78f5b69d40bcc4931df93d29198435ab67.tar.gz ioquake3-aero-6bf20c78f5b69d40bcc4931df93d29198435ab67.zip |
newlines fixed
git-svn-id: svn://svn.icculus.org/quake3/trunk@6 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'code/q3_ui/ui_servers2.c')
-rwxr-xr-x | code/q3_ui/ui_servers2.c | 3280 |
1 files changed, 1640 insertions, 1640 deletions
diff --git a/code/q3_ui/ui_servers2.c b/code/q3_ui/ui_servers2.c index d20fb6f..0804b5a 100755 --- a/code/q3_ui/ui_servers2.c +++ b/code/q3_ui/ui_servers2.c @@ -1,1640 +1,1640 @@ -/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Foobar; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-//
-/*
-=======================================================================
-
-MULTIPLAYER MENU (SERVER BROWSER)
-
-=======================================================================
-*/
-
-
-#include "ui_local.h"
-
-
-#define MAX_GLOBALSERVERS 128
-#define MAX_PINGREQUESTS 32
-#define MAX_ADDRESSLENGTH 64
-#define MAX_HOSTNAMELENGTH 22
-#define MAX_MAPNAMELENGTH 16
-#define MAX_LISTBOXITEMS 128
-#define MAX_LOCALSERVERS 128
-#define MAX_STATUSLENGTH 64
-#define MAX_LEAGUELENGTH 28
-#define MAX_LISTBOXWIDTH 68
-
-#define ART_BACK0 "menu/art/back_0"
-#define ART_BACK1 "menu/art/back_1"
-#define ART_CREATE0 "menu/art/create_0"
-#define ART_CREATE1 "menu/art/create_1"
-#define ART_SPECIFY0 "menu/art/specify_0"
-#define ART_SPECIFY1 "menu/art/specify_1"
-#define ART_REFRESH0 "menu/art/refresh_0"
-#define ART_REFRESH1 "menu/art/refresh_1"
-#define ART_CONNECT0 "menu/art/fight_0"
-#define ART_CONNECT1 "menu/art/fight_1"
-#define ART_ARROWS0 "menu/art/arrows_vert_0"
-#define ART_ARROWS_UP "menu/art/arrows_vert_top"
-#define ART_ARROWS_DOWN "menu/art/arrows_vert_bot"
-#define ART_UNKNOWNMAP "menu/art/unknownmap"
-#define ART_REMOVE0 "menu/art/delete_0"
-#define ART_REMOVE1 "menu/art/delete_1"
-#define ART_PUNKBUSTER "menu/art/pblogo"
-
-#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_PUNKBUSTER 24
-
-#define GR_LOGO 30
-#define GR_LETTERS 31
-
-#define AS_LOCAL 0
-#define AS_MPLAYER 1
-#define AS_GLOBAL 2
-#define AS_FAVORITES 3
-
-#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
-
-static const char *master_items[] = {
- "Local",
- "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 char* gamenames[] = {
- "DM ", // deathmatch
- "1v1", // tournament
- "SP ", // single player
- "Team DM", // team deathmatch
- "CTF", // capture the flag
- "One Flag CTF", // one flag ctf
- "OverLoad", // Overload
- "Harvester", // Harvester
- "Rocket Arena 3", // Rocket Arena 3
- "Q3F", // Q3F
- "Urban Terror", // Urban Terror
- "OSP", // Orange Smoothie Productions
- "???", // unknown
- 0
-};
-
-static char* netnames[] = {
- "???",
- "UDP",
- "IPX",
- NULL
-};
-
-static char quake3worldMessage[] = "Visit www.quake3world.com - News, Community, Events, Files";
-
-const char* punkbuster_items[] = {
- "Disabled",
- "Enabled",
- NULL
-};
-
-const char* punkbuster_msg[] = {
- "PunkBuster will be",
- "disabled the next time",
- "Quake III Arena",
- "is started.",
- NULL
-};
-
-typedef struct {
- char adrstr[MAX_ADDRESSLENGTH];
- int start;
-} pinglist_t;
-
-typedef struct servernode_s {
- char adrstr[MAX_ADDRESSLENGTH];
- char hostname[MAX_HOSTNAMELENGTH+3];
- char mapname[MAX_MAPNAMELENGTH];
- int numclients;
- int maxclients;
- int pingtime;
- int gametype;
- char gamename[12];
- int nettype;
- int minPing;
- int maxPing;
- qboolean bPB;
-
-} servernode_t;
-
-typedef struct {
- char buff[MAX_LISTBOXWIDTH];
- servernode_t* servernode;
-} table_t;
-
-typedef struct {
- menuframework_s menu;
-
- menutext_s banner;
-
- menulist_s master;
- menulist_s gametype;
- menulist_s sortkey;
- menuradiobutton_s showfull;
- menuradiobutton_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 back;
- menubitmap_s refresh;
- menubitmap_s specify;
- menubitmap_s create;
- menubitmap_s go;
-
- 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;
-
- menulist_s punkbuster;
- menubitmap_s pblogo;
-} arenaservers_t;
-
-static arenaservers_t g_arenaservers;
-
-
-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
-=================
-*/
-static int ArenaServers_MaxPing( void ) {
- 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;
-
- if( !g_arenaservers.list.numitems ) {
- g_arenaservers.mappic.generic.name = NULL;
- }
- else {
- servernodeptr = g_arenaservers.table[g_arenaservers.list.curvalue].servernode;
- 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;
-
- 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, "%d of %d Arena Servers.", g_arenaservers.currentping, g_arenaservers.numqueriedservers);
- g_arenaservers.statusbar.string = "Press SPACE to stop";
- 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;
- g_arenaservers.punkbuster.generic.flags &= ~QMF_GRAYED;
-
- // update status bar
- if( g_servertype == AS_GLOBAL || g_servertype == AS_MPLAYER ) {
- g_arenaservers.statusbar.string = quake3worldMessage;
- }
- else {
- g_arenaservers.statusbar.string = "";
- }
-
- }
- }
- else {
- // no servers found
- if( g_arenaservers.refreshservers ) {
- strcpy( g_arenaservers.status.string,"Scanning For Servers." );
- g_arenaservers.statusbar.string = "Press SPACE to stop";
-
- // 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.punkbuster.generic.flags |= QMF_GRAYED;
- }
- else {
- if( g_arenaservers.numqueriedservers < 0 ) {
- strcpy(g_arenaservers.status.string,"No Response From Master Server." );
- }
- else {
- strcpy(g_arenaservers.status.string,"No Servers Found." );
- }
-
- // update status bar
- if( g_servertype == AS_GLOBAL || g_servertype == AS_MPLAYER ) {
- 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;
- g_arenaservers.punkbuster.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;
-
- // can only cull valid results
- 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;
- }
-
- 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 < 200 ) {
- pingColor = S_COLOR_GREEN;
- }
- else if( servernodeptr->pingtime < 400 ) {
- pingColor = S_COLOR_YELLOW;
- }
- else {
- pingColor = S_COLOR_RED;
- }
-
- Com_sprintf( buff, MAX_LISTBOXWIDTH, "%-20.20s %-12.12s %2d/%2d %-8.8s %3s %s%3d " S_COLOR_YELLOW "%s",
- servernodeptr->hostname, servernodeptr->mapname, servernodeptr->numclients,
- servernodeptr->maxclients, servernodeptr->gamename,
- netnames[servernodeptr->nettype], pingColor, servernodeptr->pingtime, servernodeptr->bPB ? "Yes" : "No" );
- j++;
- }
-
- g_arenaservers.list.numitems = j;
- g_arenaservers.list.curvalue = 0;
- g_arenaservers.list.top = 0;
-
- // 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_strupr( servernodeptr->hostname );
-
- Q_strncpyz( servernodeptr->mapname, Info_ValueForKey( info, "mapname"), MAX_MAPNAMELENGTH );
- Q_CleanStr( servernodeptr->mapname );
- Q_strupr( 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->bPB = atoi( Info_ValueForKey( info, "punkbuster") );
-
- /*
- 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;
- }
- }
- */
- servernodeptr->nettype = atoi(Info_ValueForKey(info, "nettype"));
-
- s = Info_ValueForKey( info, "game");
- i = atoi( Info_ValueForKey( info, "gametype") );
- if( i < 0 ) {
- i = 0;
- }
- else if( i > 11 ) {
- i = 12;
- }
- if( *s ) {
- servernodeptr->gametype = i;//-1;
- Q_strncpyz( servernodeptr->gamename, s, sizeof(servernodeptr->gamename) );
- }
- else {
- servernodeptr->gametype = i;
- 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 emptyinfo[MAX_INFO_STRING];
- char adrstr[MAX_ADDRESSLENGTH];
- servernode_t templist[MAX_FAVORITESERVERS];
- qboolean found;
-
- found = qfalse;
- emptyinfo[0] = '\0';
-
- // 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)
- {
- if (g_servertype != AS_FAVORITES) {
- if (g_servertype == AS_LOCAL) {
- if (!trap_LAN_GetServerCount(g_servertype)) {
- return;
- }
- }
- if (trap_LAN_GetServerCount(g_servertype) < 0) {
- // still waiting for response
- return;
- }
- }
- }
-
- if (uis.realtime < g_arenaservers.nextpingtime)
- {
- // wait for time trigger
- return;
- }
-
- // trigger at 10Hz intervals
- g_arenaservers.nextpingtime = uis.realtime + 10;
-
- // 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 );
- }
-
- // 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
- if (g_servertype == AS_FAVORITES) {
- g_arenaservers.numqueriedservers = g_arenaservers.numfavoriteaddresses;
- } else {
- g_arenaservers.numqueriedservers = trap_LAN_GetServerCount(g_servertype);
- }
-
-// 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
-
- if (g_servertype == AS_FAVORITES) {
- strcpy( adrstr, g_arenaservers.favoriteaddresses[g_arenaservers.currentping] );
- } else {
- trap_LAN_GetServerAddressString(g_servertype, g_arenaservers.currentping, adrstr, MAX_ADDRESSLENGTH );
- }
-
- 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], protocol[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_GLOBAL || g_servertype == AS_MPLAYER ) {
- if( g_servertype == AS_GLOBAL ) {
- i = 0;
- }
- else {
- i = 1;
- }
-
- switch( g_arenaservers.gametype.curvalue ) {
- default:
- 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");
- }
-
- protocol[0] = '\0';
- trap_Cvar_VariableStringBuffer( "debug_protocol", protocol, sizeof(protocol) );
- if (strlen(protocol)) {
- trap_Cmd_ExecuteText( EXEC_APPEND, va( "globalservers %d %s%s\n", i, protocol, myargs ));
- }
- else {
- 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 )
-{
- if (g_servertype == type)
- return;
-
- 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_GLOBAL:
- 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,"hit refresh to update");
-}
-
-/*
-=================
-PunkBuster_Confirm
-=================
-*/
-static void Punkbuster_ConfirmEnable( qboolean result ) {
- if (result)
- {
- trap_SetPbClStatus(1);
- }
- g_arenaservers.punkbuster.curvalue = Com_Clamp( 0, 1, trap_Cvar_VariableValue( "cl_punkbuster" ) );
-}
-
-static void Punkbuster_ConfirmDisable( qboolean result ) {
- if (result)
- {
- trap_SetPbClStatus(0);
- UI_Message( punkbuster_msg );
- }
- g_arenaservers.punkbuster.curvalue = Com_Clamp( 0, 1, trap_Cvar_VariableValue( "cl_punkbuster" ) );
-}
-
-/*
-=================
-ArenaServers_Event
-=================
-*/
-static void ArenaServers_Event( void* ptr, int event ) {
- int id;
- int value;
-
- id = ((menucommon_s*)ptr)->id;
-
- if( event != QM_ACTIVATED && id != ID_LIST ) {
- return;
- }
-
- switch( id ) {
- case ID_MASTER:
- value = g_arenaservers.master.curvalue;
- if (value >= 1)
- {
- value++;
- }
- trap_Cvar_SetValue( "ui_browserMaster", value );
- ArenaServers_SetType( value );
- 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_BACK:
- ArenaServers_StopRefresh();
- ArenaServers_SaveChanges();
- UI_PopMenu();
- break;
-
- case ID_REFRESH:
- ArenaServers_StartRefresh();
- break;
-
- case ID_SPECIFY:
- UI_SpecifyServerMenu();
- break;
-
- case ID_CREATE:
- UI_StartServerMenu( qtrue );
- break;
-
- case ID_CONNECT:
- ArenaServers_Go();
- break;
-
- case ID_REMOVE:
- ArenaServers_Remove();
- ArenaServers_UpdateMenu();
- break;
-
- case ID_PUNKBUSTER:
- if (g_arenaservers.punkbuster.curvalue)
- {
- UI_ConfirmMenu_Style( "Enable Punkbuster?", UI_CENTER|UI_INVERSE|UI_SMALLFONT, (voidfunc_f)NULL, Punkbuster_ConfirmEnable );
- }
- else
- {
- UI_ConfirmMenu_Style( "Disable Punkbuster?", UI_CENTER|UI_INVERSE|UI_SMALLFONT, (voidfunc_f)NULL, Punkbuster_ConfirmDisable );
- }
- break;
- }
-}
-
-
-/*
-=================
-ArenaServers_MenuDraw
-=================
-*/
-static void ArenaServers_MenuDraw( void )
-{
- if (g_arenaservers.refreshservers)
- ArenaServers_DoRefresh();
-
- 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;
- int y;
- int value;
- 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.banner.generic.type = MTYPE_BTEXT;
- g_arenaservers.banner.generic.flags = QMF_CENTER_JUSTIFY;
- g_arenaservers.banner.generic.x = 320;
- g_arenaservers.banner.generic.y = 16;
- g_arenaservers.banner.string = "ARENA SERVERS";
- g_arenaservers.banner.style = UI_CENTER;
- g_arenaservers.banner.color = color_white;
-
- y = 80;
- g_arenaservers.master.generic.type = MTYPE_SPINCONTROL;
- g_arenaservers.master.generic.name = "Servers:";
- g_arenaservers.master.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
- g_arenaservers.master.generic.callback = ArenaServers_Event;
- g_arenaservers.master.generic.id = ID_MASTER;
- g_arenaservers.master.generic.x = 320;
- g_arenaservers.master.generic.y = y;
- g_arenaservers.master.itemnames = master_items;
-
- y += SMALLCHAR_HEIGHT;
- g_arenaservers.gametype.generic.type = MTYPE_SPINCONTROL;
- g_arenaservers.gametype.generic.name = "Game Type:";
- g_arenaservers.gametype.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
- g_arenaservers.gametype.generic.callback = ArenaServers_Event;
- g_arenaservers.gametype.generic.id = ID_GAMETYPE;
- g_arenaservers.gametype.generic.x = 320;
- g_arenaservers.gametype.generic.y = y;
- g_arenaservers.gametype.itemnames = servertype_items;
-
- y += SMALLCHAR_HEIGHT;
- g_arenaservers.sortkey.generic.type = MTYPE_SPINCONTROL;
- g_arenaservers.sortkey.generic.name = "Sort By:";
- g_arenaservers.sortkey.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
- g_arenaservers.sortkey.generic.callback = ArenaServers_Event;
- g_arenaservers.sortkey.generic.id = ID_SORTKEY;
- g_arenaservers.sortkey.generic.x = 320;
- g_arenaservers.sortkey.generic.y = y;
- g_arenaservers.sortkey.itemnames = sortkey_items;
-
- y += SMALLCHAR_HEIGHT;
- g_arenaservers.showfull.generic.type = MTYPE_RADIOBUTTON;
- g_arenaservers.showfull.generic.name = "Show Full:";
- g_arenaservers.showfull.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
- g_arenaservers.showfull.generic.callback = ArenaServers_Event;
- g_arenaservers.showfull.generic.id = ID_SHOW_FULL;
- g_arenaservers.showfull.generic.x = 320;
- g_arenaservers.showfull.generic.y = y;
-
- y += SMALLCHAR_HEIGHT;
- g_arenaservers.showempty.generic.type = MTYPE_RADIOBUTTON;
- g_arenaservers.showempty.generic.name = "Show Empty:";
- g_arenaservers.showempty.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
- g_arenaservers.showempty.generic.callback = ArenaServers_Event;
- g_arenaservers.showempty.generic.id = ID_SHOW_EMPTY;
- g_arenaservers.showempty.generic.x = 320;
- g_arenaservers.showempty.generic.y = y;
-
- y += 3 * SMALLCHAR_HEIGHT;
- 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 = 72;
- g_arenaservers.list.generic.y = y;
- g_arenaservers.list.width = MAX_LISTBOXWIDTH;
- 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 = 72;
- g_arenaservers.mappic.generic.y = 80;
- g_arenaservers.mappic.width = 128;
- g_arenaservers.mappic.height = 96;
- g_arenaservers.mappic.errorpic = ART_UNKNOWNMAP;
-
- g_arenaservers.arrows.generic.type = MTYPE_BITMAP;
- g_arenaservers.arrows.generic.name = ART_ARROWS0;
- g_arenaservers.arrows.generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE;
- g_arenaservers.arrows.generic.callback = ArenaServers_Event;
- g_arenaservers.arrows.generic.x = 512+48;
- g_arenaservers.arrows.generic.y = 240-64+16;
- g_arenaservers.arrows.width = 64;
- g_arenaservers.arrows.height = 128;
-
- g_arenaservers.up.generic.type = MTYPE_BITMAP;
- g_arenaservers.up.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_MOUSEONLY;
- g_arenaservers.up.generic.callback = ArenaServers_Event;
- g_arenaservers.up.generic.id = ID_SCROLL_UP;
- g_arenaservers.up.generic.x = 512+48;
- g_arenaservers.up.generic.y = 240-64+16;
- g_arenaservers.up.width = 64;
- g_arenaservers.up.height = 64;
- g_arenaservers.up.focuspic = ART_ARROWS_UP;
-
- g_arenaservers.down.generic.type = MTYPE_BITMAP;
- g_arenaservers.down.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_MOUSEONLY;
- g_arenaservers.down.generic.callback = ArenaServers_Event;
- g_arenaservers.down.generic.id = ID_SCROLL_DOWN;
- g_arenaservers.down.generic.x = 512+48;
- g_arenaservers.down.generic.y = 240+16;
- g_arenaservers.down.width = 64;
- g_arenaservers.down.height = 64;
- g_arenaservers.down.focuspic = ART_ARROWS_DOWN;
-
- y = 376;
- g_arenaservers.status.generic.type = MTYPE_TEXT;
- g_arenaservers.status.generic.x = 320;
- g_arenaservers.status.generic.y = y;
- g_arenaservers.status.string = statusbuffer;
- g_arenaservers.status.style = UI_CENTER|UI_SMALLFONT;
- g_arenaservers.status.color = menu_text_color;
-
- y += SMALLCHAR_HEIGHT;
- g_arenaservers.statusbar.generic.type = MTYPE_TEXT;
- g_arenaservers.statusbar.generic.x = 320;
- g_arenaservers.statusbar.generic.y = y;
- g_arenaservers.statusbar.string = "";
- g_arenaservers.statusbar.style = UI_CENTER|UI_SMALLFONT;
- g_arenaservers.statusbar.color = text_color_normal;
-
- g_arenaservers.remove.generic.type = MTYPE_BITMAP;
- g_arenaservers.remove.generic.name = ART_REMOVE0;
- g_arenaservers.remove.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
- g_arenaservers.remove.generic.callback = ArenaServers_Event;
- g_arenaservers.remove.generic.id = ID_REMOVE;
- g_arenaservers.remove.generic.x = 450;
- g_arenaservers.remove.generic.y = 86;
- g_arenaservers.remove.width = 96;
- g_arenaservers.remove.height = 48;
- g_arenaservers.remove.focuspic = ART_REMOVE1;
-
- g_arenaservers.back.generic.type = MTYPE_BITMAP;
- g_arenaservers.back.generic.name = ART_BACK0;
- g_arenaservers.back.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
- g_arenaservers.back.generic.callback = ArenaServers_Event;
- g_arenaservers.back.generic.id = ID_BACK;
- g_arenaservers.back.generic.x = 0;
- g_arenaservers.back.generic.y = 480-64;
- g_arenaservers.back.width = 128;
- g_arenaservers.back.height = 64;
- g_arenaservers.back.focuspic = ART_BACK1;
-
- g_arenaservers.specify.generic.type = MTYPE_BITMAP;
- g_arenaservers.specify.generic.name = ART_SPECIFY0;
- g_arenaservers.specify.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
- g_arenaservers.specify.generic.callback = ArenaServers_Event;
- g_arenaservers.specify.generic.id = ID_SPECIFY;
- g_arenaservers.specify.generic.x = 128;
- g_arenaservers.specify.generic.y = 480-64;
- g_arenaservers.specify.width = 128;
- g_arenaservers.specify.height = 64;
- g_arenaservers.specify.focuspic = ART_SPECIFY1;
-
- g_arenaservers.refresh.generic.type = MTYPE_BITMAP;
- g_arenaservers.refresh.generic.name = ART_REFRESH0;
- g_arenaservers.refresh.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
- g_arenaservers.refresh.generic.callback = ArenaServers_Event;
- g_arenaservers.refresh.generic.id = ID_REFRESH;
- g_arenaservers.refresh.generic.x = 256;
- g_arenaservers.refresh.generic.y = 480-64;
- g_arenaservers.refresh.width = 128;
- g_arenaservers.refresh.height = 64;
- g_arenaservers.refresh.focuspic = ART_REFRESH1;
-
- g_arenaservers.create.generic.type = MTYPE_BITMAP;
- g_arenaservers.create.generic.name = ART_CREATE0;
- g_arenaservers.create.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
- g_arenaservers.create.generic.callback = ArenaServers_Event;
- g_arenaservers.create.generic.id = ID_CREATE;
- g_arenaservers.create.generic.x = 384;
- g_arenaservers.create.generic.y = 480-64;
- g_arenaservers.create.width = 128;
- g_arenaservers.create.height = 64;
- g_arenaservers.create.focuspic = ART_CREATE1;
-
- g_arenaservers.go.generic.type = MTYPE_BITMAP;
- g_arenaservers.go.generic.name = ART_CONNECT0;
- g_arenaservers.go.generic.flags = QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS;
- g_arenaservers.go.generic.callback = ArenaServers_Event;
- g_arenaservers.go.generic.id = ID_CONNECT;
- g_arenaservers.go.generic.x = 640;
- g_arenaservers.go.generic.y = 480-64;
- g_arenaservers.go.width = 128;
- g_arenaservers.go.height = 64;
- g_arenaservers.go.focuspic = ART_CONNECT1;
-
- g_arenaservers.punkbuster.generic.type = MTYPE_SPINCONTROL;
- g_arenaservers.punkbuster.generic.name = "Punkbuster:";
- g_arenaservers.punkbuster.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT;
- g_arenaservers.punkbuster.generic.callback = ArenaServers_Event;
- g_arenaservers.punkbuster.generic.id = ID_PUNKBUSTER;
- g_arenaservers.punkbuster.generic.x = 480+32;
- g_arenaservers.punkbuster.generic.y = 144;
- g_arenaservers.punkbuster.itemnames = punkbuster_items;
-
- g_arenaservers.pblogo.generic.type = MTYPE_BITMAP;
- g_arenaservers.pblogo.generic.name = ART_PUNKBUSTER;
- g_arenaservers.pblogo.generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE;
- g_arenaservers.pblogo.generic.x = 526;
- g_arenaservers.pblogo.generic.y = 176;
- g_arenaservers.pblogo.width = 32;
- g_arenaservers.pblogo.height = 16;
- g_arenaservers.pblogo.errorpic = ART_UNKNOWNMAP;
-
- Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.banner );
-
- 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.arrows );
- 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.remove );
- Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.back );
- Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.specify );
- Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.refresh );
- Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.create );
- Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.go );
-
- Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.punkbuster );
- Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.pblogo );
-
- ArenaServers_LoadFavorites();
-
- g_servertype = Com_Clamp( 0, 3, ui_browserMaster.integer );
- // hack to get rid of MPlayer stuff
- value = g_servertype;
- if (value >= 1)
- value--;
- g_arenaservers.master.curvalue = value;
-
- g_gametype = Com_Clamp( 0, 4, 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;
-
- g_arenaservers.punkbuster.curvalue = Com_Clamp( 0, 1, trap_Cvar_VariableValue( "cl_punkbuster" ) );
-
- // force to initial state and refresh
- type = g_servertype;
- g_servertype = -1;
- ArenaServers_SetType( type );
-
- trap_Cvar_Register(NULL, "debug_protocol", "", 0 );
-}
-
-
-/*
-=================
-ArenaServers_Cache
-=================
-*/
-void ArenaServers_Cache( void ) {
- trap_R_RegisterShaderNoMip( ART_BACK0 );
- trap_R_RegisterShaderNoMip( ART_BACK1 );
- trap_R_RegisterShaderNoMip( ART_CREATE0 );
- trap_R_RegisterShaderNoMip( ART_CREATE1 );
- trap_R_RegisterShaderNoMip( ART_SPECIFY0 );
- trap_R_RegisterShaderNoMip( ART_SPECIFY1 );
- trap_R_RegisterShaderNoMip( ART_REFRESH0 );
- trap_R_RegisterShaderNoMip( ART_REFRESH1 );
- trap_R_RegisterShaderNoMip( ART_CONNECT0 );
- trap_R_RegisterShaderNoMip( ART_CONNECT1 );
- trap_R_RegisterShaderNoMip( ART_ARROWS0 );
- trap_R_RegisterShaderNoMip( ART_ARROWS_UP );
- trap_R_RegisterShaderNoMip( ART_ARROWS_DOWN );
- trap_R_RegisterShaderNoMip( ART_UNKNOWNMAP );
- trap_R_RegisterShaderNoMip( ART_PUNKBUSTER );
-}
-
-
-/*
-=================
-UI_ArenaServersMenu
-=================
-*/
-void UI_ArenaServersMenu( void ) {
- ArenaServers_MenuInit();
- UI_PushMenu( &g_arenaservers.menu );
-}
+/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +// +/* +======================================================================= + +MULTIPLAYER MENU (SERVER BROWSER) + +======================================================================= +*/ + + +#include "ui_local.h" + + +#define MAX_GLOBALSERVERS 128 +#define MAX_PINGREQUESTS 32 +#define MAX_ADDRESSLENGTH 64 +#define MAX_HOSTNAMELENGTH 22 +#define MAX_MAPNAMELENGTH 16 +#define MAX_LISTBOXITEMS 128 +#define MAX_LOCALSERVERS 128 +#define MAX_STATUSLENGTH 64 +#define MAX_LEAGUELENGTH 28 +#define MAX_LISTBOXWIDTH 68 + +#define ART_BACK0 "menu/art/back_0" +#define ART_BACK1 "menu/art/back_1" +#define ART_CREATE0 "menu/art/create_0" +#define ART_CREATE1 "menu/art/create_1" +#define ART_SPECIFY0 "menu/art/specify_0" +#define ART_SPECIFY1 "menu/art/specify_1" +#define ART_REFRESH0 "menu/art/refresh_0" +#define ART_REFRESH1 "menu/art/refresh_1" +#define ART_CONNECT0 "menu/art/fight_0" +#define ART_CONNECT1 "menu/art/fight_1" +#define ART_ARROWS0 "menu/art/arrows_vert_0" +#define ART_ARROWS_UP "menu/art/arrows_vert_top" +#define ART_ARROWS_DOWN "menu/art/arrows_vert_bot" +#define ART_UNKNOWNMAP "menu/art/unknownmap" +#define ART_REMOVE0 "menu/art/delete_0" +#define ART_REMOVE1 "menu/art/delete_1" +#define ART_PUNKBUSTER "menu/art/pblogo" + +#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_PUNKBUSTER 24 + +#define GR_LOGO 30 +#define GR_LETTERS 31 + +#define AS_LOCAL 0 +#define AS_MPLAYER 1 +#define AS_GLOBAL 2 +#define AS_FAVORITES 3 + +#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 + +static const char *master_items[] = { + "Local", + "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 char* gamenames[] = { + "DM ", // deathmatch + "1v1", // tournament + "SP ", // single player + "Team DM", // team deathmatch + "CTF", // capture the flag + "One Flag CTF", // one flag ctf + "OverLoad", // Overload + "Harvester", // Harvester + "Rocket Arena 3", // Rocket Arena 3 + "Q3F", // Q3F + "Urban Terror", // Urban Terror + "OSP", // Orange Smoothie Productions + "???", // unknown + 0 +}; + +static char* netnames[] = { + "???", + "UDP", + "IPX", + NULL +}; + +static char quake3worldMessage[] = "Visit www.quake3world.com - News, Community, Events, Files"; + +const char* punkbuster_items[] = { + "Disabled", + "Enabled", + NULL +}; + +const char* punkbuster_msg[] = { + "PunkBuster will be", + "disabled the next time", + "Quake III Arena", + "is started.", + NULL +}; + +typedef struct { + char adrstr[MAX_ADDRESSLENGTH]; + int start; +} pinglist_t; + +typedef struct servernode_s { + char adrstr[MAX_ADDRESSLENGTH]; + char hostname[MAX_HOSTNAMELENGTH+3]; + char mapname[MAX_MAPNAMELENGTH]; + int numclients; + int maxclients; + int pingtime; + int gametype; + char gamename[12]; + int nettype; + int minPing; + int maxPing; + qboolean bPB; + +} servernode_t; + +typedef struct { + char buff[MAX_LISTBOXWIDTH]; + servernode_t* servernode; +} table_t; + +typedef struct { + menuframework_s menu; + + menutext_s banner; + + menulist_s master; + menulist_s gametype; + menulist_s sortkey; + menuradiobutton_s showfull; + menuradiobutton_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 back; + menubitmap_s refresh; + menubitmap_s specify; + menubitmap_s create; + menubitmap_s go; + + 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; + + menulist_s punkbuster; + menubitmap_s pblogo; +} arenaservers_t; + +static arenaservers_t g_arenaservers; + + +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 +================= +*/ +static int ArenaServers_MaxPing( void ) { + 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; + + if( !g_arenaservers.list.numitems ) { + g_arenaservers.mappic.generic.name = NULL; + } + else { + servernodeptr = g_arenaservers.table[g_arenaservers.list.curvalue].servernode; + 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; + + 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, "%d of %d Arena Servers.", g_arenaservers.currentping, g_arenaservers.numqueriedservers); + g_arenaservers.statusbar.string = "Press SPACE to stop"; + 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; + g_arenaservers.punkbuster.generic.flags &= ~QMF_GRAYED; + + // update status bar + if( g_servertype == AS_GLOBAL || g_servertype == AS_MPLAYER ) { + g_arenaservers.statusbar.string = quake3worldMessage; + } + else { + g_arenaservers.statusbar.string = ""; + } + + } + } + else { + // no servers found + if( g_arenaservers.refreshservers ) { + strcpy( g_arenaservers.status.string,"Scanning For Servers." ); + g_arenaservers.statusbar.string = "Press SPACE to stop"; + + // 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.punkbuster.generic.flags |= QMF_GRAYED; + } + else { + if( g_arenaservers.numqueriedservers < 0 ) { + strcpy(g_arenaservers.status.string,"No Response From Master Server." ); + } + else { + strcpy(g_arenaservers.status.string,"No Servers Found." ); + } + + // update status bar + if( g_servertype == AS_GLOBAL || g_servertype == AS_MPLAYER ) { + 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; + g_arenaservers.punkbuster.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; + + // can only cull valid results + 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; + } + + 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 < 200 ) { + pingColor = S_COLOR_GREEN; + } + else if( servernodeptr->pingtime < 400 ) { + pingColor = S_COLOR_YELLOW; + } + else { + pingColor = S_COLOR_RED; + } + + Com_sprintf( buff, MAX_LISTBOXWIDTH, "%-20.20s %-12.12s %2d/%2d %-8.8s %3s %s%3d " S_COLOR_YELLOW "%s", + servernodeptr->hostname, servernodeptr->mapname, servernodeptr->numclients, + servernodeptr->maxclients, servernodeptr->gamename, + netnames[servernodeptr->nettype], pingColor, servernodeptr->pingtime, servernodeptr->bPB ? "Yes" : "No" ); + j++; + } + + g_arenaservers.list.numitems = j; + g_arenaservers.list.curvalue = 0; + g_arenaservers.list.top = 0; + + // 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_strupr( servernodeptr->hostname ); + + Q_strncpyz( servernodeptr->mapname, Info_ValueForKey( info, "mapname"), MAX_MAPNAMELENGTH ); + Q_CleanStr( servernodeptr->mapname ); + Q_strupr( 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->bPB = atoi( Info_ValueForKey( info, "punkbuster") ); + + /* + 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; + } + } + */ + servernodeptr->nettype = atoi(Info_ValueForKey(info, "nettype")); + + s = Info_ValueForKey( info, "game"); + i = atoi( Info_ValueForKey( info, "gametype") ); + if( i < 0 ) { + i = 0; + } + else if( i > 11 ) { + i = 12; + } + if( *s ) { + servernodeptr->gametype = i;//-1; + Q_strncpyz( servernodeptr->gamename, s, sizeof(servernodeptr->gamename) ); + } + else { + servernodeptr->gametype = i; + 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 emptyinfo[MAX_INFO_STRING]; + char adrstr[MAX_ADDRESSLENGTH]; + servernode_t templist[MAX_FAVORITESERVERS]; + qboolean found; + + found = qfalse; + emptyinfo[0] = '\0'; + + // 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) + { + if (g_servertype != AS_FAVORITES) { + if (g_servertype == AS_LOCAL) { + if (!trap_LAN_GetServerCount(g_servertype)) { + return; + } + } + if (trap_LAN_GetServerCount(g_servertype) < 0) { + // still waiting for response + return; + } + } + } + + if (uis.realtime < g_arenaservers.nextpingtime) + { + // wait for time trigger + return; + } + + // trigger at 10Hz intervals + g_arenaservers.nextpingtime = uis.realtime + 10; + + // 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 ); + } + + // 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 + if (g_servertype == AS_FAVORITES) { + g_arenaservers.numqueriedservers = g_arenaservers.numfavoriteaddresses; + } else { + g_arenaservers.numqueriedservers = trap_LAN_GetServerCount(g_servertype); + } + +// 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 + + if (g_servertype == AS_FAVORITES) { + strcpy( adrstr, g_arenaservers.favoriteaddresses[g_arenaservers.currentping] ); + } else { + trap_LAN_GetServerAddressString(g_servertype, g_arenaservers.currentping, adrstr, MAX_ADDRESSLENGTH ); + } + + 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], protocol[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_GLOBAL || g_servertype == AS_MPLAYER ) { + if( g_servertype == AS_GLOBAL ) { + i = 0; + } + else { + i = 1; + } + + switch( g_arenaservers.gametype.curvalue ) { + default: + 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"); + } + + protocol[0] = '\0'; + trap_Cvar_VariableStringBuffer( "debug_protocol", protocol, sizeof(protocol) ); + if (strlen(protocol)) { + trap_Cmd_ExecuteText( EXEC_APPEND, va( "globalservers %d %s%s\n", i, protocol, myargs )); + } + else { + 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 ) +{ + if (g_servertype == type) + return; + + 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_GLOBAL: + 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,"hit refresh to update"); +} + +/* +================= +PunkBuster_Confirm +================= +*/ +static void Punkbuster_ConfirmEnable( qboolean result ) { + if (result) + { + trap_SetPbClStatus(1); + } + g_arenaservers.punkbuster.curvalue = Com_Clamp( 0, 1, trap_Cvar_VariableValue( "cl_punkbuster" ) ); +} + +static void Punkbuster_ConfirmDisable( qboolean result ) { + if (result) + { + trap_SetPbClStatus(0); + UI_Message( punkbuster_msg ); + } + g_arenaservers.punkbuster.curvalue = Com_Clamp( 0, 1, trap_Cvar_VariableValue( "cl_punkbuster" ) ); +} + +/* +================= +ArenaServers_Event +================= +*/ +static void ArenaServers_Event( void* ptr, int event ) { + int id; + int value; + + id = ((menucommon_s*)ptr)->id; + + if( event != QM_ACTIVATED && id != ID_LIST ) { + return; + } + + switch( id ) { + case ID_MASTER: + value = g_arenaservers.master.curvalue; + if (value >= 1) + { + value++; + } + trap_Cvar_SetValue( "ui_browserMaster", value ); + ArenaServers_SetType( value ); + 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_BACK: + ArenaServers_StopRefresh(); + ArenaServers_SaveChanges(); + UI_PopMenu(); + break; + + case ID_REFRESH: + ArenaServers_StartRefresh(); + break; + + case ID_SPECIFY: + UI_SpecifyServerMenu(); + break; + + case ID_CREATE: + UI_StartServerMenu( qtrue ); + break; + + case ID_CONNECT: + ArenaServers_Go(); + break; + + case ID_REMOVE: + ArenaServers_Remove(); + ArenaServers_UpdateMenu(); + break; + + case ID_PUNKBUSTER: + if (g_arenaservers.punkbuster.curvalue) + { + UI_ConfirmMenu_Style( "Enable Punkbuster?", UI_CENTER|UI_INVERSE|UI_SMALLFONT, (voidfunc_f)NULL, Punkbuster_ConfirmEnable ); + } + else + { + UI_ConfirmMenu_Style( "Disable Punkbuster?", UI_CENTER|UI_INVERSE|UI_SMALLFONT, (voidfunc_f)NULL, Punkbuster_ConfirmDisable ); + } + break; + } +} + + +/* +================= +ArenaServers_MenuDraw +================= +*/ +static void ArenaServers_MenuDraw( void ) +{ + if (g_arenaservers.refreshservers) + ArenaServers_DoRefresh(); + + 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; + int y; + int value; + 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.banner.generic.type = MTYPE_BTEXT; + g_arenaservers.banner.generic.flags = QMF_CENTER_JUSTIFY; + g_arenaservers.banner.generic.x = 320; + g_arenaservers.banner.generic.y = 16; + g_arenaservers.banner.string = "ARENA SERVERS"; + g_arenaservers.banner.style = UI_CENTER; + g_arenaservers.banner.color = color_white; + + y = 80; + g_arenaservers.master.generic.type = MTYPE_SPINCONTROL; + g_arenaservers.master.generic.name = "Servers:"; + g_arenaservers.master.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + g_arenaservers.master.generic.callback = ArenaServers_Event; + g_arenaservers.master.generic.id = ID_MASTER; + g_arenaservers.master.generic.x = 320; + g_arenaservers.master.generic.y = y; + g_arenaservers.master.itemnames = master_items; + + y += SMALLCHAR_HEIGHT; + g_arenaservers.gametype.generic.type = MTYPE_SPINCONTROL; + g_arenaservers.gametype.generic.name = "Game Type:"; + g_arenaservers.gametype.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + g_arenaservers.gametype.generic.callback = ArenaServers_Event; + g_arenaservers.gametype.generic.id = ID_GAMETYPE; + g_arenaservers.gametype.generic.x = 320; + g_arenaservers.gametype.generic.y = y; + g_arenaservers.gametype.itemnames = servertype_items; + + y += SMALLCHAR_HEIGHT; + g_arenaservers.sortkey.generic.type = MTYPE_SPINCONTROL; + g_arenaservers.sortkey.generic.name = "Sort By:"; + g_arenaservers.sortkey.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + g_arenaservers.sortkey.generic.callback = ArenaServers_Event; + g_arenaservers.sortkey.generic.id = ID_SORTKEY; + g_arenaservers.sortkey.generic.x = 320; + g_arenaservers.sortkey.generic.y = y; + g_arenaservers.sortkey.itemnames = sortkey_items; + + y += SMALLCHAR_HEIGHT; + g_arenaservers.showfull.generic.type = MTYPE_RADIOBUTTON; + g_arenaservers.showfull.generic.name = "Show Full:"; + g_arenaservers.showfull.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + g_arenaservers.showfull.generic.callback = ArenaServers_Event; + g_arenaservers.showfull.generic.id = ID_SHOW_FULL; + g_arenaservers.showfull.generic.x = 320; + g_arenaservers.showfull.generic.y = y; + + y += SMALLCHAR_HEIGHT; + g_arenaservers.showempty.generic.type = MTYPE_RADIOBUTTON; + g_arenaservers.showempty.generic.name = "Show Empty:"; + g_arenaservers.showempty.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + g_arenaservers.showempty.generic.callback = ArenaServers_Event; + g_arenaservers.showempty.generic.id = ID_SHOW_EMPTY; + g_arenaservers.showempty.generic.x = 320; + g_arenaservers.showempty.generic.y = y; + + y += 3 * SMALLCHAR_HEIGHT; + 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 = 72; + g_arenaservers.list.generic.y = y; + g_arenaservers.list.width = MAX_LISTBOXWIDTH; + 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 = 72; + g_arenaservers.mappic.generic.y = 80; + g_arenaservers.mappic.width = 128; + g_arenaservers.mappic.height = 96; + g_arenaservers.mappic.errorpic = ART_UNKNOWNMAP; + + g_arenaservers.arrows.generic.type = MTYPE_BITMAP; + g_arenaservers.arrows.generic.name = ART_ARROWS0; + g_arenaservers.arrows.generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE; + g_arenaservers.arrows.generic.callback = ArenaServers_Event; + g_arenaservers.arrows.generic.x = 512+48; + g_arenaservers.arrows.generic.y = 240-64+16; + g_arenaservers.arrows.width = 64; + g_arenaservers.arrows.height = 128; + + g_arenaservers.up.generic.type = MTYPE_BITMAP; + g_arenaservers.up.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_MOUSEONLY; + g_arenaservers.up.generic.callback = ArenaServers_Event; + g_arenaservers.up.generic.id = ID_SCROLL_UP; + g_arenaservers.up.generic.x = 512+48; + g_arenaservers.up.generic.y = 240-64+16; + g_arenaservers.up.width = 64; + g_arenaservers.up.height = 64; + g_arenaservers.up.focuspic = ART_ARROWS_UP; + + g_arenaservers.down.generic.type = MTYPE_BITMAP; + g_arenaservers.down.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_MOUSEONLY; + g_arenaservers.down.generic.callback = ArenaServers_Event; + g_arenaservers.down.generic.id = ID_SCROLL_DOWN; + g_arenaservers.down.generic.x = 512+48; + g_arenaservers.down.generic.y = 240+16; + g_arenaservers.down.width = 64; + g_arenaservers.down.height = 64; + g_arenaservers.down.focuspic = ART_ARROWS_DOWN; + + y = 376; + g_arenaservers.status.generic.type = MTYPE_TEXT; + g_arenaservers.status.generic.x = 320; + g_arenaservers.status.generic.y = y; + g_arenaservers.status.string = statusbuffer; + g_arenaservers.status.style = UI_CENTER|UI_SMALLFONT; + g_arenaservers.status.color = menu_text_color; + + y += SMALLCHAR_HEIGHT; + g_arenaservers.statusbar.generic.type = MTYPE_TEXT; + g_arenaservers.statusbar.generic.x = 320; + g_arenaservers.statusbar.generic.y = y; + g_arenaservers.statusbar.string = ""; + g_arenaservers.statusbar.style = UI_CENTER|UI_SMALLFONT; + g_arenaservers.statusbar.color = text_color_normal; + + g_arenaservers.remove.generic.type = MTYPE_BITMAP; + g_arenaservers.remove.generic.name = ART_REMOVE0; + g_arenaservers.remove.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; + g_arenaservers.remove.generic.callback = ArenaServers_Event; + g_arenaservers.remove.generic.id = ID_REMOVE; + g_arenaservers.remove.generic.x = 450; + g_arenaservers.remove.generic.y = 86; + g_arenaservers.remove.width = 96; + g_arenaservers.remove.height = 48; + g_arenaservers.remove.focuspic = ART_REMOVE1; + + g_arenaservers.back.generic.type = MTYPE_BITMAP; + g_arenaservers.back.generic.name = ART_BACK0; + g_arenaservers.back.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; + g_arenaservers.back.generic.callback = ArenaServers_Event; + g_arenaservers.back.generic.id = ID_BACK; + g_arenaservers.back.generic.x = 0; + g_arenaservers.back.generic.y = 480-64; + g_arenaservers.back.width = 128; + g_arenaservers.back.height = 64; + g_arenaservers.back.focuspic = ART_BACK1; + + g_arenaservers.specify.generic.type = MTYPE_BITMAP; + g_arenaservers.specify.generic.name = ART_SPECIFY0; + g_arenaservers.specify.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; + g_arenaservers.specify.generic.callback = ArenaServers_Event; + g_arenaservers.specify.generic.id = ID_SPECIFY; + g_arenaservers.specify.generic.x = 128; + g_arenaservers.specify.generic.y = 480-64; + g_arenaservers.specify.width = 128; + g_arenaservers.specify.height = 64; + g_arenaservers.specify.focuspic = ART_SPECIFY1; + + g_arenaservers.refresh.generic.type = MTYPE_BITMAP; + g_arenaservers.refresh.generic.name = ART_REFRESH0; + g_arenaservers.refresh.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; + g_arenaservers.refresh.generic.callback = ArenaServers_Event; + g_arenaservers.refresh.generic.id = ID_REFRESH; + g_arenaservers.refresh.generic.x = 256; + g_arenaservers.refresh.generic.y = 480-64; + g_arenaservers.refresh.width = 128; + g_arenaservers.refresh.height = 64; + g_arenaservers.refresh.focuspic = ART_REFRESH1; + + g_arenaservers.create.generic.type = MTYPE_BITMAP; + g_arenaservers.create.generic.name = ART_CREATE0; + g_arenaservers.create.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; + g_arenaservers.create.generic.callback = ArenaServers_Event; + g_arenaservers.create.generic.id = ID_CREATE; + g_arenaservers.create.generic.x = 384; + g_arenaservers.create.generic.y = 480-64; + g_arenaservers.create.width = 128; + g_arenaservers.create.height = 64; + g_arenaservers.create.focuspic = ART_CREATE1; + + g_arenaservers.go.generic.type = MTYPE_BITMAP; + g_arenaservers.go.generic.name = ART_CONNECT0; + g_arenaservers.go.generic.flags = QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS; + g_arenaservers.go.generic.callback = ArenaServers_Event; + g_arenaservers.go.generic.id = ID_CONNECT; + g_arenaservers.go.generic.x = 640; + g_arenaservers.go.generic.y = 480-64; + g_arenaservers.go.width = 128; + g_arenaservers.go.height = 64; + g_arenaservers.go.focuspic = ART_CONNECT1; + + g_arenaservers.punkbuster.generic.type = MTYPE_SPINCONTROL; + g_arenaservers.punkbuster.generic.name = "Punkbuster:"; + g_arenaservers.punkbuster.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + g_arenaservers.punkbuster.generic.callback = ArenaServers_Event; + g_arenaservers.punkbuster.generic.id = ID_PUNKBUSTER; + g_arenaservers.punkbuster.generic.x = 480+32; + g_arenaservers.punkbuster.generic.y = 144; + g_arenaservers.punkbuster.itemnames = punkbuster_items; + + g_arenaservers.pblogo.generic.type = MTYPE_BITMAP; + g_arenaservers.pblogo.generic.name = ART_PUNKBUSTER; + g_arenaservers.pblogo.generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE; + g_arenaservers.pblogo.generic.x = 526; + g_arenaservers.pblogo.generic.y = 176; + g_arenaservers.pblogo.width = 32; + g_arenaservers.pblogo.height = 16; + g_arenaservers.pblogo.errorpic = ART_UNKNOWNMAP; + + Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.banner ); + + 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.arrows ); + 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.remove ); + Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.back ); + Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.specify ); + Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.refresh ); + Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.create ); + Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.go ); + + Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.punkbuster ); + Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.pblogo ); + + ArenaServers_LoadFavorites(); + + g_servertype = Com_Clamp( 0, 3, ui_browserMaster.integer ); + // hack to get rid of MPlayer stuff + value = g_servertype; + if (value >= 1) + value--; + g_arenaservers.master.curvalue = value; + + g_gametype = Com_Clamp( 0, 4, 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; + + g_arenaservers.punkbuster.curvalue = Com_Clamp( 0, 1, trap_Cvar_VariableValue( "cl_punkbuster" ) ); + + // force to initial state and refresh + type = g_servertype; + g_servertype = -1; + ArenaServers_SetType( type ); + + trap_Cvar_Register(NULL, "debug_protocol", "", 0 ); +} + + +/* +================= +ArenaServers_Cache +================= +*/ +void ArenaServers_Cache( void ) { + trap_R_RegisterShaderNoMip( ART_BACK0 ); + trap_R_RegisterShaderNoMip( ART_BACK1 ); + trap_R_RegisterShaderNoMip( ART_CREATE0 ); + trap_R_RegisterShaderNoMip( ART_CREATE1 ); + trap_R_RegisterShaderNoMip( ART_SPECIFY0 ); + trap_R_RegisterShaderNoMip( ART_SPECIFY1 ); + trap_R_RegisterShaderNoMip( ART_REFRESH0 ); + trap_R_RegisterShaderNoMip( ART_REFRESH1 ); + trap_R_RegisterShaderNoMip( ART_CONNECT0 ); + trap_R_RegisterShaderNoMip( ART_CONNECT1 ); + trap_R_RegisterShaderNoMip( ART_ARROWS0 ); + trap_R_RegisterShaderNoMip( ART_ARROWS_UP ); + trap_R_RegisterShaderNoMip( ART_ARROWS_DOWN ); + trap_R_RegisterShaderNoMip( ART_UNKNOWNMAP ); + trap_R_RegisterShaderNoMip( ART_PUNKBUSTER ); +} + + +/* +================= +UI_ArenaServersMenu +================= +*/ +void UI_ArenaServersMenu( void ) { + ArenaServers_MenuInit(); + UI_PushMenu( &g_arenaservers.menu ); +} |