Files
commandergenius/project/jni/application/lbreakout2-2.6.2/client/client_recv.c
2010-12-24 12:04:06 +00:00

358 lines
11 KiB
C

/***************************************************************************
client_recv.c - description
-------------------
begin : Sat Oct 26 12:02:57 CEST 2002
copyright : (C) 2002 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <stdarg.h>
#include "lbreakout.h"
#include "client_data.h"
#include "game.h"
#include "../game/game.h"
#include "../gui/gui.h"
/*
====================================================================
Externals
====================================================================
*/
#ifdef NETWORK_ENABLED
extern NetSocket client;
extern int client_is_connected;
#endif
extern GuiWidget *dlg_info;
extern GuiWidget *dlg_confirm;
extern GuiWidget *dlg_chatroom;
extern GuiWidget *label_channel;
extern GuiWidget *label_info;
extern GuiWidget *label_confirm;
extern GuiWidget *label_stats;
extern GuiWidget *label_winner;
extern GuiWidget *list_chatter;
extern GuiWidget *list_levels;
extern GuiWidget *list_users;
extern GuiWidget *list_games;
extern List *client_users;
extern List *client_channels;
extern List *client_levelsets;
extern int client_state;
extern List *levels;
extern int net_buffer_cur_size, msg_read_pos;
extern char net_buffer[MAX_MSG_SIZE + PACKET_HEADER_SIZE];
/* CHALLENGE */
extern char client_name[16];
extern int client_recv_limit;
extern char *mp_diff_names[];
extern char mp_levelset[16];
extern int mp_peer_id;
extern char mp_peer_name[16];
extern int mp_levelset_version;
extern int mp_levelset_update;
extern int mp_level_count;
extern int levelset_version, levelset_update;
extern int mp_diff, mp_rounds, mp_frags, mp_balls;
extern ClientUser *client_user;
extern void client_run_game( int challenger );
extern void client_disconnect(); /* from client.c */
extern int client_comm_delay;
/*
====================================================================
Popup info dialogue and set status to INFO.
====================================================================
*/
void client_popup_info( char *format, ... )
{
char buffer[256];
va_list args;
va_start( args, format );
vsnprintf( buffer, 256, format, args );
va_end( args );
gui_label_set_text( label_info, buffer );
gui_widget_show( dlg_info );
client_state = CLIENT_INFO;
}
/*
====================================================================
Popup confirm dialogue and _keep_ status.
====================================================================
*/
void client_popup_confirm( char *format, ... )
{
char buffer[256];
va_list args;
va_start( args, format );
vsnprintf( buffer, 256, format, args );
va_end( args );
gui_label_set_text( label_confirm, buffer );
gui_widget_show( dlg_confirm );
}
/*
====================================================================
Parse all messages in net_packet.
====================================================================
*/
#ifdef NETWORK_ENABLED
static void client_parse_packet()
{
int i, num;
char name[16];
unsigned char type;
int handled;
while ( 1 ) {
type = (unsigned)msg_read_int8(); handled = 0;
if ( msg_read_failed() ) break; /* no more messages */
switch ( type ) {
case MSG_PREPARE_FULL_UPDATE:
/* do only clear users as channels and
* levelsets are fixed */
list_clear( client_users ); client_user = 0;
handled = 1;
break;
case MSG_ERROR:
client_printf_chatter( 1, _("ERROR: %s"), msg_read_string() );
handled = 1;
break;
case MSG_BUSY:
if ( client_state == CLIENT_AWAIT_ANSWER ||
client_state == CLIENT_AWAIT_TRANSFER_CONFIRMATION )
client_popup_info(
_("%s is busy at the moment."),
mp_peer_name );
handled = 1;
break;
case MSG_DISCONNECT:
client_disconnect();
handled = 1;
break;
case MSG_SET_COMM_DELAY:
client_comm_delay = msg_read_int16();
printf( _("comm_delay set to %i\n"), client_comm_delay );
handled = 1;
break;
/* chatter */
case MSG_SERVER_INFO:
client_add_chatter( msg_read_string(), 1 );
handled = 1;
break;
case MSG_CHATTER:
client_add_chatter( msg_read_string(), 0 );
handled = 1;
break;
/* users */
case MSG_ADD_USER:
num = msg_read_int32();
snprintf( name, 16, "%s", msg_read_string() ); name[15] = 0;
if ( msg_read_failed() ) break;
client_add_user( num, name );
gui_list_update(
list_users,
client_users->count );
/* re-select current entry */
if ( client_user ) {
num = list_check( client_users, client_user );
if ( num != -1 )
gui_list_select( list_users, 0, num, 1 );
}
handled = 1;
break;
case MSG_REMOVE_USER:
num = msg_read_int32();
if ( msg_read_failed() ) break;
client_remove_user( num );
gui_list_update(
list_users,
client_users->count );
/* re-select current entry */
if ( client_user ) {
num = list_check( client_users, client_user );
if ( num != -1 )
gui_list_select( list_users, 0, num, 1 );
}
handled = 1;
break;
case MSG_CHANNEL_LIST:
list_clear( client_channels );
num = msg_read_int8();
for ( i = 0; i < num; i++ )
list_add( client_channels, strdup(msg_read_string()) );
handled = 1;
break;
case MSG_LEVELSET_LIST:
list_clear( client_levelsets );
num = msg_read_int8();
for ( i = 0; i < num; i++ )
list_add( client_levelsets, strdup(msg_read_string()) );
gui_list_update( list_levels, client_levelsets->count );
handled = 1;
break;
case MSG_ADD_LEVELSET:
list_add( client_levelsets, strdup(msg_read_string()) );
gui_list_update( list_levels, client_levelsets->count );
handled = 1;
break;
case MSG_SET_CHANNEL:
/* we only need to update the name */
gui_label_set_text( label_channel, msg_read_string() );
handled = 1;
break;
/* challenge */
case MSG_CHALLENGE:
/* the user may only be challenged if client state is NONE
because otherwise he is doing something that shouldn't be
interrupted */
if ( client_state != CLIENT_NONE ) {
msg_begin_writing( msgbuf, &msglen, 128 );
msg_write_int8( MSG_BUSY );
msg_write_int32( msg_read_int32() );
client_transmit( CODE_BLUE, msglen, msgbuf );
break;
}
snprintf( mp_peer_name, 15, "%s", msg_read_string() );
snprintf( mp_levelset, 16, "%s", msg_read_string() );
mp_diff = msg_read_int8();
mp_rounds = msg_read_int8();
mp_frags = msg_read_int8();
mp_balls = msg_read_int8();
if ( msg_read_failed() ) break;
client_popup_confirm( _(" You have been challenged!##"\
" Challenger: %13s#"\
" Levelset: %13s#"\
" Difficulty: %13s#"\
" Rounds: %13i#"\
" Frag Limit: %13i#"\
" Balls: %13i"),
mp_peer_name, mp_levelset, mp_diff_names[mp_diff],
mp_rounds, mp_frags, mp_balls );
client_state = CLIENT_ANSWER;
handled = 1;
break;
case MSG_REJECT_CHALLENGE:
handled = 1;
if ( client_state != CLIENT_AWAIT_ANSWER ) break;
client_popup_info(
_("%s is too scared to accept your challenge."),
mp_peer_name );
break;
case MSG_CANCEL_GAME:
handled = 1;
if ( client_state != CLIENT_ANSWER ) break;
gui_widget_hide( dlg_confirm );
client_popup_info( _("%s got cold feet."), mp_peer_name );
break;
case MSG_ACCEPT_CHALLENGE:
handled = 1;
if ( client_state != CLIENT_AWAIT_ANSWER ) break;
gui_widget_hide( dlg_info );
/* play */
gui_disable_event_filter();
if ( client_game_init_network( mp_peer_name, mp_diff ) )
client_game_run();
client_game_finalize();
gui_enable_event_filter();
gui_widget_draw( dlg_chatroom );
stk_display_fade( STK_FADE_IN, STK_FADE_DEFAULT_TIME );
break;
/* dummy parse game packets that may arrive after the QUIT_GAME
* message was sent because ADD_USER commands may be in the
* package and these we should get. */
case MSG_PADDLE_STATE:
comm_unpack_paddle_dummy( net_buffer, &msg_read_pos );
handled = 1;
break;
case MSG_SHOT_POSITIONS:
comm_unpack_shots_dummy( net_buffer, &msg_read_pos );
handled = 1;
break;
case MSG_BALL_POSITIONS:
comm_unpack_balls_dummy( net_buffer, &msg_read_pos );
handled = 1;
break;
case MSG_SCORES:
comm_unpack_scores_dummy( net_buffer, &msg_read_pos );
handled = 1;
break;
case MSG_BRICK_HITS:
comm_unpack_brick_hits_dummy( net_buffer, &msg_read_pos );
handled = 1;
break;
case MSG_NEW_EXTRAS:
comm_unpack_collected_extras_dummy( net_buffer, &msg_read_pos );
handled = 1;
break;
case MSG_ROUND_OVER:
i = msg_read_int8();
handled = 1;
break;
case MSG_LAST_ROUND_OVER:
i = msg_read_int8();
handled = 1;
break;
}
if ( !handled ) {
printf( _("chat: state %i: invalid message %x: skipping %i bytes\n"),
client_state, type, net_buffer_cur_size - msg_read_pos );
msg_read_pos = net_buffer_cur_size;
}
}
}
#endif
/*
====================================================================
Receive packets from server. Use the TIME_PASSED event therefore.
Send a heartbeat every three seconds as well.
====================================================================
*/
void client_recv_packet( GuiWidget *widget, GuiEvent *event )
{
#ifdef NETWORK_ENABLED
int recv_limit;
static int last_heartbeat = 0;
if ( !client_is_connected ) return;
if ( event->type != GUI_TIME_PASSED ) return;
/* heartbeat? */
if ( time(0) >= last_heartbeat + 10 ) {
last_heartbeat = time(0);
msgbuf[0] = MSG_HEARTBEAT;
client_transmit( CODE_BLUE, 1, msgbuf );
}
recv_limit = client_recv_limit; /* limited number of packets if not -1 */
while ( net_recv_packet() && ( recv_limit==-1 || recv_limit > 0) ) {
/* check if this is a valid packet and update the socket */
if ( msg_is_connectionless() )
msg_begin_connectionless_reading();
else
if ( !socket_process_header( &client ) )
continue;
client_parse_packet();
if ( recv_limit != -1 ) recv_limit--;
}
#endif
}