q3rally/engine/code/q3_ui/ui_servers2.c

1847 lines
49 KiB
C
Raw Normal View History

2011-02-18 14:31:32 +00:00
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
2021-03-24 20:13:01 +00:00
Copyright (C) 2002-2021 Q3Rally Team (Per Thormann - q3rally@gmail.com)
2011-02-18 14:31:32 +00:00
This file is part of q3rally source code.
q3rally 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.
q3rally 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 q3rally; 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 16
#define MAX_ADDRESSLENGTH 64
// STONELANCE
#define MAX_HOSTNAMELENGTH 22
#define MAX_MAPNAMELENGTH 16
// END
#define MAX_LISTBOXITEMS 128
#define MAX_LOCALSERVERS 128
#define MAX_STATUSLENGTH 64
#define MAX_LEAGUELENGTH 28
// STONELANCE
//#define MAX_LISTBOXWIDTH 61
#define MAX_LISTBOXWIDTH 90
/*
#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"
*/
// END
#define ART_UNKNOWNMAP "menu/art/unknownmap"
#define ART_REMOVE0 "menu/art/delete_0"
#define ART_REMOVE1 "menu/art/delete_1"
#define GLOBALRANKINGS_LOGO "menu/art/gr/grlogo"
#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 GR_LOGO 30
#define GR_LETTERS 31
#define AS_LOCAL 0
#define AS_MPLAYER 1
#define AS_GLOBAL 2
#define AS_FAVORITES 3
ioquake3 resync to revision 2369 from 2317. Some revision messages: Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources. Play correct team sounds when in spectator mode and following a player. Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.) When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.) really fix the confusion with game entity and refentity numbers to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES Added Rend2, an alternate renderer. (Bug #4358) Fix restoring fs_game when default.cfg is missing. Fix restoring old fs_game upon leaving a server. Patch by Ensiform. Change more operator commands to require sv_running to be usable. Patch by Ensiform. Fix some "> MAX_*" to be ">= MAX_*". Fix follow command to find clients whose name begins with a number. Fix up "gc" command, make it more like "tell". Based on patch by Ensiform. Add usage messages for gc, tell, vtell, and votell commands. Check player names in gc, tell, vtell, and votell commands. #5799 - Change messagemode text box to display colors like in console input box. Improve "play" command, based on a patch from Ensiform. Check for invalid filename in OpenAL's RegisterSound function. Changed Base sound system to warn not error when sound filename is empty or too long. Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
#define UI_MAX_MASTER_SERVERS 5
2011-02-18 14:31:32 +00:00
#define SORT_HOST 0
#define SORT_MAP 1
#define SORT_CLIENTS 2
#define SORT_GAME 3
#define SORT_PING 4
#define GAMES_ALL 0
// STONELANCE
/*
#define GAMES_FFA 1
#define GAMES_TEAMPLAY 2
#define GAMES_TOURNEY 3
#define GAMES_CTF 4
*/
#define GAMES_RACING 1
#define GAMES_RACING_DM 2
#define GAMES_DERBY 3
#define GAMES_DEATHMATCH 4
#define GAMES_TEAM_RACING 5
#define GAMES_TEAM_RACING_DM 6
#define GAMES_TEAMPLAY 7
#define GAMES_CTF 8
#define GAMES_DOMINATION 9
2011-02-18 14:31:32 +00:00
// END
static const char *master_items[] = {
"Local",
"Mplayer",
"Internet",
"Favorites",
0
};
static const char *servertype_items[] = {
"All",
// STONELANCE
/*
"Free For All",
"Team Deathmatch",
"Tournament",
"Capture the Flag",
*/
"Racing",
"Racing Deathmatch",
"Demolition Derby",
"Deathmatch",
"Team Racing",
"Team Racing Deathmatch",
"Team Deathmatch",
"Capture the Flag",
"Domination",
2011-02-18 14:31:32 +00:00
// END
0
};
static const char *sortkey_items[] = {
"Server Name",
"Map Name",
"Open Player Spots",
"Game Type",
"Ping Time",
0
};
static char* gamenames[] = {
// STONELANCE
/*
"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
*/
"Race",
"Race DM",
"Derby",
"DM ",
"TRace",
"TRace DM",
"Team DM", // team deathmatch
"CTF", // capture the flag
"Domination", // domination
2011-02-18 14:31:32 +00:00
// END
"???", // unknown
0
};
static char* netnames[] = {
"???",
"UDP",
"IPX",
NULL
};
// STONELANCE
//static char quake3worldMessage[] = "Visit www.quake3world.com - News, Community, Events, Files";
static char quake3worldMessage[] = "Visit www.quake3rally.com - News, Message Boards, Files";
// END
static char globalRankingsMessage[] = "Visit www.globalrankings.com - you kick ass, we'll take names";
typedef struct {
char adrstr[MAX_ADDRESSLENGTH];
int start;
} pinglist_t;
typedef struct servernode_s {
char adrstr[MAX_ADDRESSLENGTH];
char hostname[MAX_HOSTNAMELENGTH];
char mapname[MAX_MAPNAMELENGTH];
int numclients;
int maxclients;
int pingtime;
int gametype;
char gamename[12];
int nettype;
int minPing;
int maxPing;
} 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;
// STONELANCE
/*
menubitmap_s arrows;
menubitmap_s up;
menubitmap_s down;
*/
// END
menutext_s status;
menutext_s statusbar;
menubitmap_s remove;
// STONELANCE
/*
menubitmap_s back;
menubitmap_s refresh;
menubitmap_s specify;
menubitmap_s create;
menubitmap_s go;
*/
menutext_s back;
menutext_s refresh;
menutext_s specify;
menutext_s create;
menutext_s go;
// END
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;
menubitmap_s grlogo;
menubitmap_s grletters;
menutext_s league;
menutext_s practice;
} arenaservers_t;
static arenaservers_t g_arenaservers;
ioquake3 resync to revision 2369 from 2317. Some revision messages: Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources. Play correct team sounds when in spectator mode and following a player. Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.) When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.) really fix the confusion with game entity and refentity numbers to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES Added Rend2, an alternate renderer. (Bug #4358) Fix restoring fs_game when default.cfg is missing. Fix restoring old fs_game upon leaving a server. Patch by Ensiform. Change more operator commands to require sv_running to be usable. Patch by Ensiform. Fix some "> MAX_*" to be ">= MAX_*". Fix follow command to find clients whose name begins with a number. Fix up "gc" command, make it more like "tell". Based on patch by Ensiform. Add usage messages for gc, tell, vtell, and votell commands. Check player names in gc, tell, vtell, and votell commands. #5799 - Change messagemode text box to display colors like in console input box. Improve "play" command, based on a patch from Ensiform. Check for invalid filename in OpenAL's RegisterSound function. Changed Base sound system to warn not error when sound filename is empty or too long. Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
static servernode_t g_globalserverlist[UI_MAX_MASTER_SERVERS][MAX_GLOBALSERVERS];
static int g_numglobalservers[UI_MAX_MASTER_SERVERS];
2011-02-18 14:31:32 +00:00
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;
// STONELANCE
// g_arenaservers.list.generic.flags &= ~QMF_GRAYED;
g_arenaservers.list.generic.flags &= ~QMF_SCROLL_ONLY;
// END
g_arenaservers.refresh.generic.flags &= ~QMF_GRAYED;
g_arenaservers.go.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 = "";
}
if (!(g_arenaservers.grlogo.generic.flags & QMF_HIDDEN)) {
g_arenaservers.statusbar.string = globalRankingsMessage;
}
}
}
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;
// STONELANCE
// g_arenaservers.list.generic.flags |= QMF_GRAYED;
g_arenaservers.list.generic.flags |= QMF_SCROLL_ONLY;
// END
g_arenaservers.refresh.generic.flags |= QMF_GRAYED;
g_arenaservers.go.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;
// STONELANCE
// g_arenaservers.list.generic.flags |= QMF_GRAYED;
g_arenaservers.list.generic.flags |= QMF_SCROLL_ONLY;
// END
g_arenaservers.refresh.generic.flags &= ~QMF_GRAYED;
g_arenaservers.go.generic.flags |= QMF_GRAYED;
}
// zero out list box
g_arenaservers.list.numitems = 0;
g_arenaservers.list.curvalue = 0;
// STONELANCE
// g_arenaservers.list.top = 0;
// END
// 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;
// STONELANCE
/*
case GAMES_FFA:
if( servernodeptr->gametype != GT_FFA ) {
continue;
}
break;
*/
case GAMES_RACING:
if( servernodeptr->gametype != GT_RACING ) {
continue;
}
break;
case GAMES_RACING_DM:
if( servernodeptr->gametype != GT_RACING_DM ) {
continue;
}
break;
case GAMES_DERBY:
if( servernodeptr->gametype != GT_DERBY ) {
continue;
}
break;
case GAMES_TEAM_RACING:
if( servernodeptr->gametype != GT_TEAM_RACING ) {
continue;
}
break;
case GAMES_TEAM_RACING_DM:
if( servernodeptr->gametype != GT_TEAM_RACING_DM ) {
continue;
}
break;
case GAMES_DEATHMATCH:
if( servernodeptr->gametype != GT_DEATHMATCH ) {
continue;
}
break;
// END
case GAMES_TEAMPLAY:
if( servernodeptr->gametype != GT_TEAM ) {
continue;
}
break;
// STONELANCE - removed gametype
/*
case GAMES_TOURNEY:
if( servernodeptr->gametype != GT_TOURNAMENT ) {
continue;
}
break;
*/
// END
case GAMES_CTF:
if( servernodeptr->gametype != GT_CTF ) {
continue;
}
break;
case GAMES_DOMINATION:
if( servernodeptr->gametype != GT_DOMINATION ) {
continue;
}
break;
2011-02-18 14:31:32 +00:00
}
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",
servernodeptr->hostname, servernodeptr->mapname, servernodeptr->numclients,
servernodeptr->maxclients, servernodeptr->gamename,
netnames[servernodeptr->nettype], pingColor, servernodeptr->pingtime );
j++;
}
// Com_sprintf( g_arenaservers.status.string, MAX_STATUSLENGTH, "%d of %d Arena Servers.", j, *g_arenaservers.numservers );
g_arenaservers.list.numitems = j;
g_arenaservers.list.curvalue = 0;
// STONELANCE
// g_arenaservers.list.top = 0;
// END
// 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;
}
//remove
//trap_Cmd_ExecuteText( EXEC_NOW, va( "echo infostring: %s\n", info ) );
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") );
/*
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;
}
// STONELANCE
else if( i >= GT_MAX_GAME_TYPE ) {
i = 0;
}
/*
else if( i > 11 ) {
i = 12;
}
if ( *s ) {
servernodeptr->gametype = -1;
Q_strncpyz( servernodeptr->gamename, s, sizeof(servernodeptr->gamename) );
}
else {
*/
servernodeptr->gametype = i;
Q_strncpyz( servernodeptr->gamename, gamenames[i], sizeof(servernodeptr->gamename) );
// }
// END
}
/*
=================
ArenaServers_InsertFavorites
Insert nonresponsive address book entries into display lists.
=================
*/
void ArenaServers_InsertFavorites( void )
{
int i;
int j;
char info[MAX_INFO_STRING];
// resync existing results with new or deleted cvars
info[0] = '\0';
Info_SetValueForKey( info, "hostname", "No Response" );
for (i=0; i<g_arenaservers.numfavoriteaddresses; i++)
{
// find favorite address in refresh list
for (j=0; j<g_numfavoriteservers; j++)
if (!Q_stricmp(g_arenaservers.favoriteaddresses[i],g_favoriteserverlist[j].adrstr))
break;
if ( j >= g_numfavoriteservers)
{
// not in list, add it
ArenaServers_Insert( g_arenaservers.favoriteaddresses[i], info, ArenaServers_MaxPing() );
}
}
}
/*
=================
ArenaServers_LoadFavorites
Load cvar address book entries into local lists.
=================
*/
void ArenaServers_LoadFavorites( void )
{
int i;
int j;
int numtempitems;
char adrstr[MAX_ADDRESSLENGTH];
servernode_t templist[MAX_FAVORITESERVERS];
qboolean found;
found = qfalse;
// copy the old
memcpy( templist, g_favoriteserverlist, sizeof(servernode_t)*MAX_FAVORITESERVERS );
numtempitems = g_numfavoriteservers;
// clear the current for sync
memset( g_favoriteserverlist, 0, sizeof(servernode_t)*MAX_FAVORITESERVERS );
g_numfavoriteservers = 0;
// resync existing results with new or deleted cvars
for (i=0; i<MAX_FAVORITESERVERS; i++)
{
trap_Cvar_VariableStringBuffer( va("server%d",i+1), adrstr, MAX_ADDRESSLENGTH );
if (!adrstr[0])
continue;
// quick sanity check to avoid slow domain name resolving
// first character must be numeric
if (adrstr[0] < '0' || adrstr[0] > '9')
continue;
// favorite server addresses must be maintained outside refresh list
// this mimics local and global netadr's stored in client
// these can be fetched to fill ping list
strcpy( g_arenaservers.favoriteaddresses[g_numfavoriteservers], adrstr );
// find this server in the old list
for (j=0; j<numtempitems; j++)
if (!Q_stricmp( templist[j].adrstr, adrstr ))
break;
if (j < numtempitems)
{
// found server - add exisiting results
memcpy( &g_favoriteserverlist[g_numfavoriteservers], &templist[j], sizeof(servernode_t) );
found = qtrue;
}
else
{
// add new server
Q_strncpyz( g_favoriteserverlist[g_numfavoriteservers].adrstr, adrstr, MAX_ADDRESSLENGTH );
g_favoriteserverlist[g_numfavoriteservers].pingtime = ArenaServers_MaxPing();
}
g_numfavoriteservers++;
}
g_arenaservers.numfavoriteaddresses = g_numfavoriteservers;
if (!found)
{
// no results were found, reset server list
// list will be automatically refreshed when selected
g_numfavoriteservers = 0;
}
}
/*
=================
ArenaServers_StopRefresh
=================
*/
static void ArenaServers_StopRefresh( void )
{
if (!g_arenaservers.refreshservers)
// not currently refreshing
return;
g_arenaservers.refreshservers = qfalse;
if (g_servertype == AS_FAVORITES)
{
// nonresponsive favorites must be shown
ArenaServers_InsertFavorites();
}
// final tally
if (g_arenaservers.numqueriedservers >= 0)
{
g_arenaservers.currentping = *g_arenaservers.numservers;
g_arenaservers.numqueriedservers = *g_arenaservers.numservers;
}
// sort
qsort( g_arenaservers.serverlist, *g_arenaservers.numservers, sizeof( servernode_t ), ArenaServers_Compare);
ArenaServers_UpdateMenu();
}
/*
=================
ArenaServers_DoRefresh
=================
*/
static void ArenaServers_DoRefresh( void )
{
int i;
int j;
int time;
int maxPing;
char adrstr[MAX_ADDRESSLENGTH];
char info[MAX_INFO_STRING];
if (uis.realtime < g_arenaservers.refreshtime)
{
if (g_servertype != AS_FAVORITES) {
if (g_servertype == AS_LOCAL) {
if (!trap_LAN_GetServerCount(g_servertype)) {
2011-02-18 14:31:32 +00:00
return;
}
}
if (trap_LAN_GetServerCount(g_servertype) < 0) {
2011-02-18 14:31:32 +00:00
// 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 + 50;
// process ping results
maxPing = ArenaServers_MaxPing();
for (i=0; i<MAX_PINGREQUESTS; i++)
{
trap_LAN_GetPing( i, adrstr, MAX_ADDRESSLENGTH, &time );
if (!adrstr[0])
{
// ignore empty or pending pings
continue;
}
// find ping result in our local list
for (j=0; j<MAX_PINGREQUESTS; j++)
if (!Q_stricmp( adrstr, g_arenaservers.pinglist[j].adrstr ))
break;
if (j < MAX_PINGREQUESTS)
{
// found it
if (!time)
{
time = uis.realtime - g_arenaservers.pinglist[j].start;
if (time < maxPing)
{
// still waiting
continue;
}
}
if (time > maxPing)
{
// stale it out
info[0] = '\0';
time = maxPing;
}
else
{
trap_LAN_GetPingInfo( i, info, MAX_INFO_STRING );
}
// 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);
2011-02-18 14:31:32 +00:00
}
// 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 );
2011-02-18 14:31:32 +00:00
}
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;
// STONELANCE
/*
case GAMES_FFA:
strcpy( myargs, " ffa" );
break;
*/
// END
case GAMES_TEAMPLAY:
strcpy( myargs, " team" );
break;
// STONELANCE
/*
case GAMES_TOURNEY:
strcpy( myargs, " tourney" );
break;
*/
case GAMES_RACING:
strcpy( myargs, " racing" );
break;
case GAMES_RACING_DM:
strcpy( myargs, " racing_dm" );
break;
case GAMES_DERBY:
strcpy( myargs, " derby" );
break;
case GAMES_TEAM_RACING:
strcpy( myargs, " team_racing" );
break;
case GAMES_TEAM_RACING_DM:
strcpy( myargs, " team_racing_dm" );
break;
case GAMES_DEATHMATCH:
strcpy( myargs, " dm" );
break;
// END
case GAMES_CTF:
strcpy( myargs, " ctf" );
break;
case GAMES_DOMINATION:
strcpy( myargs, " domination" );
break;
2011-02-18 14:31:32 +00:00
}
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);
ioquake3 resync to revision 2369 from 2317. Some revision messages: Cache servers for each master server in q3_ui, otherwise servers from last updated master for shown for all Internet# sources. Play correct team sounds when in spectator mode and following a player. Check last listener number instead of clc.clientNum in S_AL_HearingThroughEntity so sound work correctly when spectate following a client. (Related to bug 5741.) When in third person, don't play player's sounds as full volume in Base sound system. OpenAL already does this. (Related to bug 5741.) really fix the confusion with game entity and refentity numbers to further reduce confusion, rename constants like MAX_ENTITIES to MAX_REFENTITIES Added Rend2, an alternate renderer. (Bug #4358) Fix restoring fs_game when default.cfg is missing. Fix restoring old fs_game upon leaving a server. Patch by Ensiform. Change more operator commands to require sv_running to be usable. Patch by Ensiform. Fix some "> MAX_*" to be ">= MAX_*". Fix follow command to find clients whose name begins with a number. Fix up "gc" command, make it more like "tell". Based on patch by Ensiform. Add usage messages for gc, tell, vtell, and votell commands. Check player names in gc, tell, vtell, and votell commands. #5799 - Change messagemode text box to display colors like in console input box. Improve "play" command, based on a patch from Ensiform. Check for invalid filename in OpenAL's RegisterSound function. Changed Base sound system to warn not error when sound filename is empty or too long. Remove references to non-existent functions CM_MarkFragments and CM_LerpTag.
2012-12-06 07:07:19 +00:00
g_arenaservers.serverlist = g_globalserverlist[type-UIAS_GLOBAL1];
g_arenaservers.numservers = &g_numglobalservers[type-UIAS_GLOBAL1];
2011-02-18 14:31:32 +00:00
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");
2011-02-18 14:31:32 +00:00
}
}
/*
=================
ArenaServers_Event
=================
*/
static void ArenaServers_Event( void* ptr, int event ) {
int id;
id = ((menucommon_s*)ptr)->id;
if( event != QM_ACTIVATED && id != ID_LIST ) {
return;
}
switch( id ) {
case ID_MASTER:
trap_Cvar_SetValue( "ui_browserMaster", g_arenaservers.master.curvalue );
ArenaServers_SetType( g_arenaservers.master.curvalue );
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;
// STONELANCE - removed
/*
case ID_SCROLL_UP:
ScrollList_Key( &g_arenaservers.list, K_UPARROW );
break;
case ID_SCROLL_DOWN:
ScrollList_Key( &g_arenaservers.list, K_DOWNARROW );
break;
*/
// END
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;
}
}
/*
=================
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;
static char statusbuffer[MAX_STATUSLENGTH];
static char leaguebuffer[MAX_LEAGUELENGTH];
// 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;
// STONELANCE
// g_arenaservers.banner.color = color_white;
g_arenaservers.banner.color = text_color_normal;
// END
g_arenaservers.grlogo.generic.type = MTYPE_BITMAP;
g_arenaservers.grlogo.generic.name = GLOBALRANKINGS_LOGO;
g_arenaservers.grlogo.generic.flags = QMF_INACTIVE|QMF_HIDDEN;
g_arenaservers.grlogo.generic.x = 530;
g_arenaservers.grlogo.generic.y = 40;
g_arenaservers.grlogo.width = 32;
g_arenaservers.grlogo.height = 64;
g_arenaservers.league.generic.type = MTYPE_TEXT;
g_arenaservers.league.generic.flags = QMF_HIDDEN;
g_arenaservers.league.generic.x = g_arenaservers.grlogo.generic.x +
(g_arenaservers.grlogo.width / 2);
g_arenaservers.league.generic.y = g_arenaservers.grlogo.generic.y +
g_arenaservers.grlogo.height + 2;
g_arenaservers.league.string = leaguebuffer;
g_arenaservers.league.style = UI_CENTER|UI_SMALLFONT;
g_arenaservers.league.color = menu_text_color;
g_arenaservers.practice.generic.type = MTYPE_TEXT;
g_arenaservers.practice.generic.flags = QMF_HIDDEN;
g_arenaservers.practice.generic.x = g_arenaservers.grlogo.generic.x +
(g_arenaservers.grlogo.width / 2);
g_arenaservers.practice.generic.y = g_arenaservers.grlogo.generic.y + 6;
g_arenaservers.practice.string = "practice";
g_arenaservers.practice.style = UI_CENTER|UI_SMALLFONT;
g_arenaservers.practice.color = menu_text_color;
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;
// STONELANCE
// g_arenaservers.list.generic.type = MTYPE_SCROLLLIST;
g_arenaservers.list.generic.type = MTYPE_LISTBOX;
g_arenaservers.list.scrollbarAlignment = SB_RIGHT;
// END
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;
// STONELANCE
/*
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;
*/
// END
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;
// STONELANCE
/*
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.back.generic.type = MTYPE_PTEXT;
g_arenaservers.back.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
g_arenaservers.back.generic.x = 20;
g_arenaservers.back.generic.y = 480 - 50;
g_arenaservers.back.generic.id = ID_BACK;
g_arenaservers.back.generic.callback = ArenaServers_Event;
g_arenaservers.back.string = "< BACK";
g_arenaservers.back.color = text_color_normal;
g_arenaservers.back.style = UI_LEFT | UI_SMALLFONT;
g_arenaservers.specify.generic.type = MTYPE_PTEXT;
g_arenaservers.specify.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
g_arenaservers.specify.generic.x = 160 - 32;
g_arenaservers.specify.generic.y = 480-50;
g_arenaservers.specify.generic.id = ID_SPECIFY;
g_arenaservers.specify.generic.callback = ArenaServers_Event;
g_arenaservers.specify.string = "<SPECIFY>";
g_arenaservers.specify.color = text_color_normal;
g_arenaservers.specify.style = UI_LEFT | UI_SMALLFONT;
g_arenaservers.refresh.generic.type = MTYPE_PTEXT;
g_arenaservers.refresh.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
g_arenaservers.refresh.generic.x = 320 - 52;
g_arenaservers.refresh.generic.y = 480 - 50;
g_arenaservers.refresh.generic.id = ID_REFRESH;
g_arenaservers.refresh.generic.callback = ArenaServers_Event;
g_arenaservers.refresh.string = "<REFRESH>";
g_arenaservers.refresh.color = text_color_normal;
g_arenaservers.refresh.style = UI_LEFT | UI_SMALLFONT;
g_arenaservers.create.generic.type = MTYPE_PTEXT;
g_arenaservers.create.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS;
g_arenaservers.create.generic.x = 460 - 56;
g_arenaservers.create.generic.y = 480 - 50;
g_arenaservers.create.generic.id = ID_CREATE;
g_arenaservers.create.generic.callback = ArenaServers_Event;
g_arenaservers.create.string = "<CREATE>";
g_arenaservers.create.color = text_color_normal;
g_arenaservers.create.style = UI_LEFT | UI_SMALLFONT;
g_arenaservers.go.generic.type = MTYPE_PTEXT;
g_arenaservers.go.generic.flags = QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS;
g_arenaservers.go.generic.x = 640 - 20;
g_arenaservers.go.generic.y = 480 - 50;
g_arenaservers.go.generic.id = ID_CONNECT;
g_arenaservers.go.generic.callback = ArenaServers_Event;
g_arenaservers.go.string = "CONNECT >";
g_arenaservers.go.color = text_color_normal;
g_arenaservers.go.style = UI_RIGHT | UI_SMALLFONT;
// END
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.banner );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.grlogo );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.league );
Menu_AddItem( &g_arenaservers.menu, (void*) &g_arenaservers.practice );
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 );
// STONELANCE
/*
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 );
*/
// END
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 );
ArenaServers_LoadFavorites();
g_servertype = Com_Clamp( 0, 3, ui_browserMaster.integer );
g_arenaservers.master.curvalue = g_servertype;
// STONELANCE
// g_gametype = Com_Clamp( 0, 4, ui_browserGameType.integer );
g_gametype = Com_Clamp( 0, GT_MAX_GAME_TYPE, ui_browserGameType.integer );
// END
g_arenaservers.gametype.curvalue = g_gametype;
g_sortkey = Com_Clamp( 0, 4, ui_browserSortKey.integer );
g_arenaservers.sortkey.curvalue = g_sortkey;
g_fullservers = Com_Clamp( 0, 1, ui_browserShowFull.integer );
g_arenaservers.showfull.curvalue = g_fullservers;
g_emptyservers = Com_Clamp( 0, 1, ui_browserShowEmpty.integer );
g_arenaservers.showempty.curvalue = g_emptyservers;
// force to initial state and refresh
type = g_servertype;
g_servertype = -1;
ArenaServers_SetType( type );
trap_Cvar_Register(NULL, "debug_protocol", "", 0 );
}
/*
=================
ArenaServers_Cache
=================
*/
void ArenaServers_Cache( void ) {
// STOENLANCE
/*
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 );
*/
// END
trap_R_RegisterShaderNoMip( ART_UNKNOWNMAP );
trap_R_RegisterShaderNoMip( GLOBALRANKINGS_LOGO );
}
/*
=================
UI_ArenaServersMenu
=================
*/
void UI_ArenaServersMenu( void ) {
ArenaServers_MenuInit();
UI_PushMenu( &g_arenaservers.menu );
}