Added initial LBreakout2 sources, already slightly modified - it does not work yet!
This commit is contained in:
616
project/jni/application/lbreakout2/server/server_game.c
Normal file
616
project/jni/application/lbreakout2/server/server_game.c
Normal file
@@ -0,0 +1,616 @@
|
||||
/***************************************************************************
|
||||
server_game.c - description
|
||||
-------------------
|
||||
begin : 03/03/19
|
||||
copyright : (C) 2003 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/***** INCLUDES ************************************************************/
|
||||
|
||||
#include "server.h"
|
||||
|
||||
/***** EXTERNAL VARIABLES **************************************************/
|
||||
|
||||
extern List *games;
|
||||
extern int global_id;
|
||||
extern char errbuf[128]; /* used to compile error messages */
|
||||
extern char msgbuf[MAX_MSG_SIZE]; /* used to compile messages */
|
||||
extern int msglen;
|
||||
extern List *levelsets;
|
||||
extern char net_buffer[MAX_MSG_SIZE + PACKET_HEADER_SIZE];
|
||||
extern int server_frame_delay;
|
||||
extern int msg_read_pos, net_buffer_cur_size;
|
||||
|
||||
extern void send_info( ServerUser *user, int type, char *format, ... );
|
||||
extern void channel_hide_user( ServerChannel *channel, ServerUser *user, int hide );
|
||||
extern void channel_remove_user( ServerChannel *channel, ServerUser *user );
|
||||
extern void send_full_update( ServerUser *user, ServerChannel *channel );
|
||||
|
||||
/***** EXPORTS *************************************************************/
|
||||
|
||||
/***** FORWARDED DECLARATIONS **********************************************/
|
||||
|
||||
/***** LOCAL TYPE DEFINITIONS **********************************************/
|
||||
|
||||
/***** LOCAL VARIABLES *****************************************************/
|
||||
|
||||
/***** LOCAL FUNCTIONS *****************************************************/
|
||||
|
||||
#ifdef NETWORK_ENABLED
|
||||
|
||||
/* update the position of top paddle */
|
||||
static void update_bot_paddle( Game *game, int ms )
|
||||
{
|
||||
int src_x, dest_x, dir;
|
||||
Ball *ball, *min_ball = 0;
|
||||
Extra *extra, *min_extra = 0;
|
||||
Paddle *paddle = game->paddles[PADDLE_TOP];
|
||||
int move = 0;
|
||||
static int entropy = 0;
|
||||
float change;
|
||||
|
||||
/* always fire */
|
||||
paddle->fire_left = 1;
|
||||
|
||||
/* get nearest ball */
|
||||
list_reset( game->balls );
|
||||
while ( ( ball = list_next( game->balls ) ) ) {
|
||||
if ( ball->attached ) continue;
|
||||
if ( min_ball == 0 || ball->y < min_ball->y )
|
||||
min_ball = ball;
|
||||
}
|
||||
/* get nearest extra */
|
||||
list_reset( game->extras );
|
||||
while ( ( extra = list_next( game->extras ) ) ) {
|
||||
if ( extra->dir != -1 ) continue;
|
||||
if ( min_extra == 0 || extra->y < min_extra->y )
|
||||
min_extra = extra;
|
||||
}
|
||||
|
||||
src_x = paddle->x + paddle->w/2;
|
||||
dest_x = paddle->x + paddle->w/2;
|
||||
if ( min_ball || min_extra ) {
|
||||
if ( min_ball && ( min_extra == 0 || min_ball->y < min_extra->y ) ) {
|
||||
dest_x = min_ball->x + 6;
|
||||
move = 1;
|
||||
}
|
||||
else
|
||||
if ( min_extra && ( min_ball == 0 || min_extra->y < min_ball->y ) ) {
|
||||
dest_x = min_extra->x + 20;
|
||||
move = 1;
|
||||
}
|
||||
}
|
||||
dir = (dest_x<src_x)?-1:(dest_x>src_x)?1:0;
|
||||
|
||||
entropy = (rand() % 17)-8;
|
||||
if ( move && dir != 0 ) {
|
||||
change = paddle->bot_vx * ms;
|
||||
/* due to high 'ms' the change might be so much that
|
||||
* the paddle would start to jump epileptically, so
|
||||
* set position to 'dest' then */
|
||||
if ( dir < 0 && src_x-change<dest_x+entropy )
|
||||
paddle->cur_x = dest_x+entropy - paddle->w/2;
|
||||
else
|
||||
if ( dir > 0 && src_x+change>dest_x-entropy )
|
||||
paddle->cur_x = dest_x-entropy - paddle->w/2;
|
||||
else
|
||||
paddle->cur_x += change * dir;
|
||||
if ( paddle->cur_x < BRICK_WIDTH )
|
||||
paddle->cur_x = BRICK_WIDTH;
|
||||
if ( paddle->cur_x + paddle->w >= 640 - BRICK_WIDTH )
|
||||
paddle->cur_x = 640 - BRICK_WIDTH - paddle->w;
|
||||
paddle->x = (int)paddle->cur_x;
|
||||
}
|
||||
}
|
||||
|
||||
static LevelSet *find_levelset( char *name )
|
||||
{
|
||||
LevelSet *set;
|
||||
|
||||
list_reset( levelsets );
|
||||
while ( (set = list_next( levelsets ) ) )
|
||||
if ( !strcmp( set->name, name ) )
|
||||
return set;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void send_level( Level *level, ServerUser *user, int l_pos )
|
||||
{
|
||||
if ( user->bot ) return;
|
||||
|
||||
msgbuf[0] = MSG_LEVEL_DATA;
|
||||
msgbuf[1] = l_pos;
|
||||
msglen = 2;
|
||||
comm_pack_level( level, msgbuf, &msglen );
|
||||
socket_transmit( &user->socket, CODE_BLUE, msglen, msgbuf );
|
||||
}
|
||||
|
||||
static void init_next_round( ServerGame *game )
|
||||
{
|
||||
game->cur_round++;
|
||||
game->cur_level = game->cur_round / game->rounds_per_level;
|
||||
game_init( game->game, game->set->levels[game->cur_level] );
|
||||
|
||||
/* send level and wait for ready */
|
||||
game->state = SERVER_AWAIT_READY;
|
||||
game->ready[0] = game->ready[1] = 0;
|
||||
send_level( game->set->levels[game->cur_level],
|
||||
game->users[0], PADDLE_BOTTOM );
|
||||
if ( !game->users[1]->bot )
|
||||
send_level( game->set->levels[game->cur_level],
|
||||
game->users[1], PADDLE_TOP );
|
||||
else
|
||||
game->ready[1] = 1; /* bot is always the challenged one */
|
||||
|
||||
/* set up bot top paddle if any */
|
||||
if ( game->users[1]->bot )
|
||||
game->game->paddles[PADDLE_TOP]->bot_vx =
|
||||
0.001 * game->users[1]->bot_level;
|
||||
|
||||
}
|
||||
|
||||
static void finalize_round( ServerGame *game )
|
||||
{
|
||||
/* update stats */
|
||||
game_update_stats( 0, &game->stats[0] );
|
||||
game_update_stats( 1, &game->stats[1] );
|
||||
|
||||
/* finalize */
|
||||
game_finalize( game->game );
|
||||
|
||||
/* tell clients that round is over */
|
||||
if ( game->cur_round == game->rounds-1 )
|
||||
msgbuf[0] = MSG_LAST_ROUND_OVER;
|
||||
else
|
||||
msgbuf[0] = MSG_ROUND_OVER;
|
||||
msgbuf[1] = game->game->winner;
|
||||
msglen = 2;
|
||||
socket_transmit( &game->users[0]->socket, CODE_BLUE, msglen, msgbuf );
|
||||
if ( !game->users[1]->bot )
|
||||
socket_transmit( &game->users[1]->socket, CODE_BLUE, msglen, msgbuf );
|
||||
|
||||
/* if this was the last round set game_over */
|
||||
if ( game->cur_round == game->rounds-1 )
|
||||
game->game_over = 1;
|
||||
}
|
||||
|
||||
/* send game statistics were the first stats is the user it is send
|
||||
* to and the second is the opponents stats */
|
||||
static void send_stats( ServerUser *user, GameStats *stats1, GameStats *stats2 )
|
||||
{
|
||||
int count;
|
||||
int kept[2] = {0,0}, bricks[2] = {0,0}, extras[2] = {0,0};
|
||||
|
||||
if ( user->bot ) return;
|
||||
|
||||
count = stats1->balls_reflected + stats1->balls_lost;
|
||||
if ( count > 0 )
|
||||
kept[0] = 100 * stats1->balls_reflected / count;
|
||||
count = stats2->balls_reflected + stats2->balls_lost;
|
||||
if ( count > 0 )
|
||||
kept[1] = 100 * stats2->balls_reflected / count;
|
||||
if ( stats1->total_brick_count > 0 )
|
||||
bricks[0] = 100 * stats1->bricks_cleared / stats1->total_brick_count;
|
||||
if ( stats2->total_brick_count > 0 )
|
||||
bricks[1] = 100 * stats2->bricks_cleared / stats2->total_brick_count;
|
||||
if ( stats1->total_extra_count > 0 )
|
||||
extras[0] = 100 * stats1->extras_collected / stats1->total_extra_count;
|
||||
if ( stats2->total_extra_count > 0 )
|
||||
extras[1] = 100 * stats2->extras_collected / stats2->total_extra_count;
|
||||
|
||||
msg_begin_writing( msgbuf, &msglen, MAX_MSG_SIZE );
|
||||
msg_write_int8( MSG_GAME_STATS );
|
||||
msg_write_int8( stats1->wins );
|
||||
msg_write_int8( stats2->wins );
|
||||
msg_write_int8( stats1->losses );
|
||||
msg_write_int8( stats2->losses );
|
||||
msg_write_int8( stats1->draws );
|
||||
msg_write_int8( stats2->draws );
|
||||
msg_write_int32( stats1->total_score );
|
||||
msg_write_int32( stats2->total_score );
|
||||
msg_write_int8( kept[0] );
|
||||
msg_write_int8( kept[1] );
|
||||
msg_write_int8( bricks[0] );
|
||||
msg_write_int8( bricks[1] );
|
||||
msg_write_int8( extras[0] );
|
||||
msg_write_int8( extras[1] );
|
||||
|
||||
socket_transmit( &user->socket, CODE_BLUE, msglen, msgbuf );
|
||||
}
|
||||
|
||||
/***** PUBLIC FUNCTIONS ****************************************************/
|
||||
|
||||
/* Add a new game by the context information, hide both users
|
||||
* and send a challenge message to the challenged user. */
|
||||
void server_game_add( ServerChannel *channel, ServerGameCtx *ctx )
|
||||
{
|
||||
ServerGame *game = salloc( 1, sizeof( ServerGame ) );
|
||||
|
||||
/* copy game data */
|
||||
game->state = SERVER_AWAIT_ACCEPT;
|
||||
game->id = global_id++;
|
||||
game->channel = channel;
|
||||
game->set = find_levelset( ctx->name );
|
||||
if ( game->set == 0 ) {
|
||||
/* should never happen... */
|
||||
sprintf( errbuf, "game_create_failed: no levelset '%s' found\n", ctx->name );
|
||||
send_info( ctx->challenger, MSG_ERROR, errbuf );
|
||||
free( game );
|
||||
return;
|
||||
}
|
||||
game->rounds_per_level = ctx->rounds;
|
||||
game->rounds = game->set->count * game->rounds_per_level;
|
||||
game->cur_round = -1; /* init_next_round will increase this to 0 */
|
||||
/* create game module */
|
||||
if ( (game->game = game_create( GT_NETWORK, ctx->diff, 100/*no rel warp*/ )) == 0 ) {
|
||||
/* send error to user */
|
||||
strncpy(errbuf,"game_create failed: out of memory",128);
|
||||
send_info( ctx->challenger, MSG_ERROR, errbuf );
|
||||
free( game );
|
||||
return;
|
||||
}
|
||||
game_set_current( game->game );
|
||||
game_set_ball_ammo( ctx->balls );
|
||||
game_set_frag_limit( ctx->frags );
|
||||
game_set_convex_paddle( 1 );
|
||||
game_set_ball_random_angle( 1 );
|
||||
|
||||
/* set game for both users and set both users for game */
|
||||
ctx->challenger->game = game;
|
||||
ctx->challenged->game = game;
|
||||
ctx->challenger->player_id = 0;
|
||||
ctx->challenged->player_id = 1;
|
||||
game->users[0] = ctx->challenger;
|
||||
game->users[1] = ctx->challenged;
|
||||
|
||||
/* hide both users */
|
||||
channel_hide_user( channel, ctx->challenger, 1 );
|
||||
channel_hide_user( channel, ctx->challenged, 1 );
|
||||
|
||||
/* inform challenged user */
|
||||
if ( !ctx->challenged->bot ) {
|
||||
msg_begin_writing( msgbuf, &msglen, MAX_MSG_SIZE );
|
||||
msg_write_int8( MSG_CHALLENGE );
|
||||
msg_write_string( ctx->challenger->name );
|
||||
msg_write_string( ctx->name );
|
||||
msg_write_int8( ctx->diff );
|
||||
msg_write_int8( ctx->rounds );
|
||||
msg_write_int8( ctx->frags );
|
||||
msg_write_int8( ctx->balls );
|
||||
socket_transmit( &ctx->challenged->socket, CODE_BLUE, msglen, msgbuf );
|
||||
}
|
||||
else {
|
||||
/* instantly accept as bot */
|
||||
msgbuf[0] = MSG_ACCEPT_CHALLENGE;
|
||||
socket_transmit( &game->users[0]->socket,
|
||||
CODE_BLUE, 1, msgbuf );
|
||||
init_next_round( game );
|
||||
}
|
||||
|
||||
list_add( games, game );
|
||||
printf( _("game added: %s (%i): %i rounds: %s vs. %s\n"),
|
||||
game->set->name, game->id, game->rounds,
|
||||
game->users[0]->name, game->users[1]->name );
|
||||
}
|
||||
|
||||
/* Free game memory. */
|
||||
void server_game_delete( void *ptr )
|
||||
{
|
||||
ServerGame *game = (ServerGame*)ptr;
|
||||
|
||||
if ( game ) {
|
||||
printf( _("game deleted: %s (%i)\n"), game->set->name, game->id );
|
||||
|
||||
if ( game->game )
|
||||
game_delete( &game->game );
|
||||
free( game );
|
||||
}
|
||||
}
|
||||
|
||||
/* unhide the users to their chat channel and delete the game.
|
||||
* if game was beyond state AWAIT_ACCEPT the game stats are send
|
||||
*/
|
||||
void server_game_remove( ServerGame *game )
|
||||
{
|
||||
int i;
|
||||
|
||||
/* users are not unhidden if the actual game has already started
|
||||
* as they need time to read the error messages (if any) then */
|
||||
if ( game->state == SERVER_AWAIT_ACCEPT )
|
||||
for ( i = 0; i < 2; i++ ) {
|
||||
if ( game->users[i]->hidden )
|
||||
channel_hide_user( game->channel, game->users[i], 0 );
|
||||
}
|
||||
else {
|
||||
/* send stats */
|
||||
send_stats( game->users[0], &game->stats[0], &game->stats[1] );
|
||||
send_stats( game->users[1], &game->stats[1], &game->stats[0] );
|
||||
|
||||
/* and unhide bot if any */
|
||||
if ( game->users[1]->bot )
|
||||
channel_hide_user( game->channel, game->users[1], 0 );
|
||||
}
|
||||
|
||||
/* clear user game pointer */
|
||||
game->users[0]->game = 0;
|
||||
game->users[1]->game = 0;
|
||||
|
||||
/* free memory */
|
||||
list_delete_item( games, game );
|
||||
}
|
||||
|
||||
/* void parse_packet_game
|
||||
* IN ServerGame *game
|
||||
* IN ServerUser *user
|
||||
*
|
||||
* Check all messages in packet from user who is currently within
|
||||
* a game. The header has already been successfully processed and
|
||||
* the read pointer is at the beginning of the first message.
|
||||
*/
|
||||
void parse_packet_game( ServerGame *game, ServerUser *user )
|
||||
{
|
||||
ServerUser *peer;
|
||||
unsigned char type;
|
||||
int handled, i;
|
||||
|
||||
game_set_current( game->game );
|
||||
|
||||
while ( 1 ) {
|
||||
type = (unsigned)msg_read_int8(); handled = 0;
|
||||
msglen = 0; /* the extract functions require a position pointer */
|
||||
|
||||
if ( msg_read_failed() ) break; /* no more messages */
|
||||
|
||||
/* general messages */
|
||||
switch ( type ) {
|
||||
case MSG_HEARTBEAT:
|
||||
/* updates the socket information automatically
|
||||
* so connection is not closed */
|
||||
handled = 1;
|
||||
break;
|
||||
case MSG_DISCONNECT:
|
||||
/* update stats and finalize context if playing */
|
||||
if ( game->state != SERVER_AWAIT_ACCEPT ) {
|
||||
game->game->winner = -1; /* count unfinished level as draw */
|
||||
game_update_stats( 0, &game->stats[0] );
|
||||
game_update_stats( 1, &game->stats[1] );
|
||||
game_finalize( game->game );
|
||||
}
|
||||
|
||||
if ( user == game->users[0] )
|
||||
peer = game->users[1];
|
||||
else
|
||||
peer = game->users[0];
|
||||
send_info( peer, MSG_ERROR, _("Remote player has disconnected...") );
|
||||
|
||||
server_game_remove( game );
|
||||
printf( _("%s (%i) disconnected\n"), user->name, user->id );
|
||||
channel_remove_user( game->channel, user );
|
||||
handled = 1;
|
||||
break;
|
||||
case MSG_QUIT_GAME:
|
||||
if ( user == game->users[0] )
|
||||
peer = game->users[1];
|
||||
else
|
||||
peer = game->users[0];
|
||||
send_info( peer, MSG_ERROR, _("Remote player has left the game...") );
|
||||
|
||||
/* update stats and finalize context */
|
||||
game->game->winner = -1; /* count unfinished level as draw */
|
||||
game_update_stats( 0, &game->stats[0] );
|
||||
game_update_stats( 1, &game->stats[1] );
|
||||
game_finalize( game->game );
|
||||
|
||||
server_game_remove( game );
|
||||
handled = 1;
|
||||
break;
|
||||
case MSG_UNHIDE:
|
||||
/* it's very unlikely that the user sends this
|
||||
* message while being in the game context but to be sure
|
||||
* he may unhide here */
|
||||
if ( user->hidden )
|
||||
channel_hide_user( game->channel, user, 0 );
|
||||
handled = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* challenge */
|
||||
if ( game->state == SERVER_AWAIT_ACCEPT )
|
||||
switch ( type ) {
|
||||
case MSG_ACCEPT_CHALLENGE:
|
||||
if ( user == game->users[1] ) {
|
||||
/* inform opponent */
|
||||
msgbuf[0] = MSG_ACCEPT_CHALLENGE;
|
||||
socket_transmit( &game->users[0]->socket,
|
||||
CODE_BLUE, 1, msgbuf );
|
||||
|
||||
init_next_round( game );
|
||||
handled = 1;
|
||||
}
|
||||
break;
|
||||
case MSG_REJECT_CHALLENGE:
|
||||
if ( user == game->users[1] ) {
|
||||
/* tell challenger that you refused the offer */
|
||||
msgbuf[0] = MSG_REJECT_CHALLENGE;
|
||||
socket_transmit( &game->users[0]->socket,
|
||||
CODE_BLUE, 1, msgbuf );
|
||||
|
||||
server_game_remove( game );
|
||||
handled = 1;
|
||||
}
|
||||
break;
|
||||
case MSG_CANCEL_GAME:
|
||||
if ( user == game->users[0] ) {
|
||||
/* tell challenged that you cancelled the offer */
|
||||
msgbuf[0] = MSG_CANCEL_GAME;
|
||||
socket_transmit( &game->users[1]->socket,
|
||||
CODE_BLUE, 1, msgbuf );
|
||||
|
||||
server_game_remove( game );
|
||||
handled = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* preparation */
|
||||
if ( game->state == SERVER_AWAIT_READY )
|
||||
if ( type == MSG_READY ) {
|
||||
game->ready[user->player_id] = 1;
|
||||
if ( game->ready[0] && game->ready[1] )
|
||||
game->state = SERVER_PLAY;
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
/* in-game messages */
|
||||
if ( game->state == SERVER_PLAY )
|
||||
switch ( type ) {
|
||||
case MSG_PADDLE_STATE:
|
||||
comm_unpack_paddle( game->game->paddles[user->player_id],
|
||||
net_buffer, &msg_read_pos );
|
||||
handled = 1;
|
||||
break;
|
||||
case MSG_PAUSE:
|
||||
game->state = SERVER_PAUSE;
|
||||
|
||||
msgbuf[0] = MSG_PAUSE; msglen = 1;
|
||||
if ( user == game->users[0] )
|
||||
peer = game->users[1];
|
||||
else
|
||||
peer = game->users[0];
|
||||
if ( !peer->bot )
|
||||
socket_transmit( &peer->socket, CODE_BLUE, msglen, msgbuf );
|
||||
handled = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* pause messages */
|
||||
if ( game->state == SERVER_PAUSE )
|
||||
switch ( type ) {
|
||||
case MSG_UNPAUSE:
|
||||
game->state = SERVER_PLAY;
|
||||
for ( i = 0; i < game->game->paddle_count; i++ )
|
||||
game->game->paddles[i]->last_ball_contact = SDL_GetTicks();
|
||||
|
||||
msgbuf[0] = MSG_UNPAUSE; msglen = 1;
|
||||
if ( user == game->users[0] )
|
||||
peer = game->users[1];
|
||||
else
|
||||
peer = game->users[0];
|
||||
if ( !peer->bot )
|
||||
socket_transmit( &peer->socket, CODE_BLUE, msglen, msgbuf );
|
||||
handled = 1;
|
||||
break;
|
||||
case MSG_CHATTER:
|
||||
/* client has added <user> prefix so simply pass it
|
||||
* to the remote user */
|
||||
msg_begin_writing( msgbuf, &msglen, MAX_MSG_SIZE );
|
||||
msg_write_int8( MSG_CHATTER );
|
||||
msg_write_string( msg_read_string() );
|
||||
if ( !msg_write_failed() ) {
|
||||
if ( user == game->users[0] )
|
||||
peer = game->users[1];
|
||||
else
|
||||
peer = game->users[0];
|
||||
if ( !peer->bot )
|
||||
socket_transmit( &peer->socket,
|
||||
CODE_BLUE, msglen, msgbuf );
|
||||
}
|
||||
handled = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !handled ) {
|
||||
printf( _("game %i: %s: state %i: invalid message %x: skipping %i bytes\n"),
|
||||
game->id, net_addr_to_string( &user->socket.remote_addr ),
|
||||
game->state, type, net_buffer_cur_size - msg_read_pos );
|
||||
msg_read_pos = net_buffer_cur_size;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* void update_games
|
||||
* IN int ms milliseconds passed since last call
|
||||
*
|
||||
* Update the objects of all games that are actually playing.
|
||||
*/
|
||||
void update_games( int ms )
|
||||
{
|
||||
int i;
|
||||
ServerGame *game;
|
||||
|
||||
list_reset( games );
|
||||
while ( (game = list_next( games ) ) ) {
|
||||
if ( game->state != SERVER_PLAY ) continue;
|
||||
|
||||
game_set_current( game->game );
|
||||
game_update( ms );
|
||||
|
||||
/* send updates to remote players */
|
||||
|
||||
if ( game->game->level_over ) {
|
||||
finalize_round( game );
|
||||
if ( game->game_over )
|
||||
server_game_remove( game );
|
||||
else
|
||||
init_next_round( game );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if playing against a bot update the top paddle */
|
||||
if ( game->users[1]->bot )
|
||||
update_bot_paddle( game->game, ms );
|
||||
|
||||
/* pack update */
|
||||
msglen = 0;
|
||||
|
||||
msgbuf[msglen++] = MSG_PADDLE_STATE;
|
||||
comm_pack_paddle( game->game->paddles[1], msgbuf, &msglen );
|
||||
|
||||
msgbuf[msglen++] = MSG_BALL_POSITIONS;
|
||||
comm_pack_balls( msgbuf, &msglen );
|
||||
|
||||
if ( game->game->shots->count > 0 ) {
|
||||
msgbuf[msglen++] = MSG_SHOT_POSITIONS;
|
||||
comm_pack_shots( msgbuf, &msglen );
|
||||
}
|
||||
|
||||
msgbuf[msglen++] = MSG_SCORES;
|
||||
comm_pack_scores( msgbuf, &msglen );
|
||||
|
||||
if ( game->game->mod.brick_hit_count > 0 ) {
|
||||
msgbuf[msglen++] = MSG_BRICK_HITS;
|
||||
comm_pack_brick_hits( msgbuf, &msglen );
|
||||
}
|
||||
|
||||
if ( game->game->mod.collected_extra_count[0] > 0 ||
|
||||
game->game->mod.collected_extra_count[1] > 0 ) {
|
||||
msgbuf[msglen++] = MSG_NEW_EXTRAS;
|
||||
comm_pack_collected_extras( msgbuf, &msglen );
|
||||
}
|
||||
|
||||
/* send packet */
|
||||
socket_transmit( &game->users[0]->socket, CODE_BLUE, msglen, msgbuf );
|
||||
|
||||
/* replace paddle which has a constant size */
|
||||
i = 1;
|
||||
comm_pack_paddle( game->game->paddles[0], msgbuf, &i );
|
||||
if ( !game->users[1]->bot )
|
||||
socket_transmit( &game->users[1]->socket, CODE_BLUE, msglen, msgbuf );
|
||||
|
||||
game_reset_mods();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user