Logo Search packages:      
Sourcecode: lbreakout2 version File versions  Download package

client_recv.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, 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, msg_read_string() );
                        snprintf( mp_levelset, 16, 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
}


Generated by  Doxygen 1.6.0   Back to index