📄 ui_servers2.c
字号:
/*
===========================================================================
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 = "";
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -