From f294db4ccf45f6274e65260dd6f9a2c5faa94313 Mon Sep 17 00:00:00 2001 From: Andrey Nazarov Date: Tue, 14 Aug 2007 20:18:08 +0000 Subject: Initial import of the new Q2PRO tree. --- source/ui_multiplayer.c | 462 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 462 insertions(+) create mode 100644 source/ui_multiplayer.c (limited to 'source/ui_multiplayer.c') diff --git a/source/ui_multiplayer.c b/source/ui_multiplayer.c new file mode 100644 index 0000000..a256ae6 --- /dev/null +++ b/source/ui_multiplayer.c @@ -0,0 +1,462 @@ +/* +Copyright (C) 2003-2006 Andrey Nazarov + +This program 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. + +This program 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 this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "ui_local.h" + +/* +============================================================================= + +JOIN SERVER MENU + +============================================================================= +*/ + +#define ID_LIST 101 + +#define MAX_STATUS_RULES 64 + +typedef struct serverSlot_s { + qboolean valid; + char *rules[MAX_STATUS_RULES+1]; + int numRules; + char *players[MAX_STATUS_PLAYERS+1]; + int numPlayers; + char address[MAX_QPATH]; + char realAddress[MAX_QPATH]; +} serverSlot_t; + +typedef struct m_joinServer_s { + menuFrameWork_t menu; + menuList_t list; + menuList_t info; + menuList_t players; + menuStatic_t banner; + qboolean active; + qboolean cursorSet; + + serverSlot_t servers[MAX_LOCAL_SERVERS]; + char *names[MAX_LOCAL_SERVERS+1]; +} m_joinServer_t; + +static m_joinServer_t m_join; + +static void UpdateSelection( void ) { + serverSlot_t *s; + + s = &m_join.servers[m_join.list.curvalue]; + + if( s->valid ) { + m_join.info.generic.flags &= ~QMF_HIDDEN; + m_join.info.itemnames = ( const char ** )s->rules; + m_join.info.numItems = s->numRules; + + if( s->numPlayers ) { + m_join.players.generic.flags &= ~QMF_HIDDEN; + m_join.players.itemnames = ( const char ** )s->players; + m_join.players.numItems = s->numPlayers; + } else { + m_join.players.generic.flags |= QMF_HIDDEN; + m_join.players.itemnames = NULL; + m_join.players.numItems = 0; + } + + m_join.menu.statusbar = "Press Enter to connect; Space to refresh"; + } else { + m_join.info.generic.flags |= QMF_HIDDEN; + m_join.info.itemnames = NULL; + m_join.info.numItems = 0; + + m_join.players.generic.flags |= QMF_HIDDEN; + m_join.players.itemnames = NULL; + m_join.players.numItems = 0; + + m_join.menu.statusbar = "Press Space to refresh"; + } +} + +void UI_AddToServerList( const serverStatus_t *status ) { + serverSlot_t *slot; + int i; + char *s; + const char *info; + char key[MAX_STRING_CHARS]; + char value[MAX_STRING_CHARS]; + const playerStatus_t *player; + + if( !m_join.active ) { + return; + } + + // see if already added + for( i = 0, slot = m_join.servers; i < m_join.list.numItems; i++, slot++ ) { + if( !strcmp( status->address, slot->realAddress ) ) { + break; + } + } + + if( i == m_join.list.numItems ) { + // create new slot + if( m_join.list.numItems == MAX_LOCAL_SERVERS ) { + return; + } + strcpy( slot->realAddress, status->address ); + strcpy( slot->address, status->address ); + if( !m_join.cursorSet ) { + m_join.list.curvalue = i; + m_join.cursorSet = qtrue; + } + m_join.list.numItems++; + m_join.names[m_join.list.numItems] = NULL; + } + + slot->valid = qtrue; + + s = UI_FormatColumns( 3, + Info_ValueForKey( status->infostring, "hostname" ), + Info_ValueForKey( status->infostring, "mapname" ), + va( "%i/%s", status->numPlayers, + Info_ValueForKey( status->infostring, "maxclients" ) ) ); + + if( m_join.names[i] ) { + com.Free( m_join.names[i] ); + } + m_join.names[i] = s; + + for( i = 0; i < slot->numRules; i++ ) { + com.Free( slot->rules[i] ); + slot->rules[i] = NULL; + } + for( i = 0; i < slot->numPlayers; i++ ) { + com.Free( slot->players[i] ); + slot->players[i] = NULL; + } + + slot->numRules = 0; + info = status->infostring; + do { + Info_NextPair( &info, key, value ); + + if( !key[0] ) { + break; + } + + s = UI_FormatColumns( 2, key, value ); + slot->rules[slot->numRules++] = s; + } while( info && slot->numRules < MAX_STATUS_RULES ); + slot->rules[slot->numRules] = NULL; + + for( i = 0, player = status->players ; i < status->numPlayers; i++, player++ ) { + s = UI_FormatColumns( 3, + va( "%i", player->score ), + va( "%i", player->ping ), + player->name ); + slot->players[i] = s; + } + slot->numPlayers = status->numPlayers; + slot->players[slot->numPlayers] = NULL; + + UpdateSelection(); + +} + +static void PingSelected( void ) { + serverSlot_t *slot; + char address[MAX_QPATH]; + int i; + char *s; + + slot = &m_join.servers[m_join.list.curvalue]; + slot->valid = qfalse; + + s = UI_FormatColumns( 3, + slot->address, "???", "?/?" ); + + if( m_join.names[m_join.list.curvalue] ) { + com.Free( m_join.names[m_join.list.curvalue] ); + } + m_join.names[m_join.list.curvalue] = s; + + for( i = 0; i < slot->numRules; i++ ) { + com.Free( slot->rules[i] ); + slot->rules[i] = NULL; + } + for( i = 0; i < slot->numPlayers; i++ ) { + com.Free( slot->players[i] ); + slot->players[i] = NULL; + } + + slot->numRules = 0; + slot->numPlayers = 0; + + UpdateSelection(); + m_join.menu.statusbar = "Pinging servers, please wait..."; + client.UpdateScreen(); + + strcpy( address, slot->realAddress ); + client.SendStatusRequest( address, sizeof( address ) ); + + UpdateSelection(); +} + +static void AddUnlistedServers( void ) { + char *s; + char address[MAX_QPATH]; + serverSlot_t *slot; + int i, j; + + m_join.active = qtrue; + + // ping broadcast + strcpy( address, "broadcast" ); + client.SendStatusRequest( address, sizeof( address ) ); + + for( i = 0; i < MAX_LOCAL_SERVERS; i++ ) { + cvar.VariableStringBuffer( va( "adr%i", i ), address, sizeof( address ) ); + if( !address[0] ) { + continue; + } + + // ignore if already listed + for( j = 0, slot = m_join.servers; j < m_join.list.numItems; j++, slot++ ) { + if( !Q_stricmp( address, slot->address ) ) { + break; + } + } + + if( j != m_join.list.numItems ) { + continue; + } + + if( m_join.list.numItems == MAX_LOCAL_SERVERS ) { + break; + } + + // save original address + strcpy( slot->address, address ); + + // resolve real ip + client.SendStatusRequest( address, sizeof( address ) ); + + // save real ip + strcpy( slot->realAddress, address ); + + s = UI_FormatColumns( 3, slot->address, "???", "?/?" ); + m_join.names[m_join.list.numItems++] = s; + m_join.names[m_join.list.numItems] = NULL; + + client.UpdateScreen(); + } +} + +static void FreeListedServers( void ) { + int i, j; + serverSlot_t *slot; + + for( i = 0, slot = m_join.servers; i < m_join.list.numItems; i++, slot++ ) { + for( j = 0; j < slot->numRules; j++ ) { + com.Free( slot->rules[j] ); + } + for( j = 0; j < slot->numPlayers; j++ ) { + com.Free( slot->players[j] ); + } + memset( slot, 0, sizeof( *slot ) ); + } + + + for( i=0 ; i