diff --git a/ChangeLog b/ChangeLog index 793ed4b..3cfc879 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,13 @@ -- Added: loadable maps. (ob1kenewb) +- Changed: You can now change the map settings even in the Player + selection menu. (kitutou) +- Added: tileset support with random tileset selection + thanks to (thaphool) for the jungle tileset + +- Added: loadable maps. (ob1kenewb) + with random map selection (kitutou) + - Changed: now the send packet option will be set for every player directly, so if a slow player joinsit should not anymore slow down the whole network game. diff --git a/TechDoc.txt b/TechDoc.txt index de607b6..74eb25d 100644 --- a/TechDoc.txt +++ b/TechDoc.txt @@ -3,7 +3,6 @@ This file will hold some Details about the Game. A list of files and what every file is used for: field.c: - selecting a tileset loading maps generating maps drawing the field @@ -130,4 +129,23 @@ udp.c: dns names start/stop udp server - \ No newline at end of file +mapmenu.c: + map option menu + map initializing + - selects random maps + - loads random tilesets + +keypinput.c: + loop for keyboard text fields + +sysfunc.c: + s_delay + - waiting for some milliseconds + s_random + - returns a random number + s_gethomedir + - returns the name of the homedir used for the config file + s_getdir + - list of files and directorys + s_filterdir + - filters the list diff --git a/src/basic.h b/src/basic.h index 9bc4869..4a63528 100644 --- a/src/basic.h +++ b/src/basic.h @@ -1,146 +1,146 @@ -/* basic types which we need everywhere */ - -#ifndef _BC_BASIC_H_ - -#define _BC_BASIC_H_ - -#define GAME_SPECIAL_ITEMBOMB 10 -#define GAME_SPECIAL_ITEMFIRE 10 -#define GAME_SPECIAL_ITEMSHOE 15 -#define GAME_SPECIAL_ITEMDEATH 25 - -#define START_BOMBS 1 -#define START_RANGE 2 -#define START_SPEED 16 -#define SPEEDMUL 1.2 - -#define MAX_PLAYERS 8 -#define MAX_BOMBS 12 -#define MAX_RANGE 10 -#define MAX_SPEED 40 -#define MAX_UPDATERECTS 2048 -#define MAX_CONNECTS 16 /* maximal number of connection data */ -#define MAX_SERVERENTRYS 8 /* number of entrys in the server tab */ -#define MAX_GAMESRVENTRYS 255 /* number of entry which can be get */ -#define MAX_FIELDSIZE_X 51 -#define MAX_FIELDSIZE_Y 31 -#define MIN_FIELDSIZE_X 15 -#define MIN_FIELDSIZE_Y 9 - - -#define EXPLOSIONTIMEOUT 20 -#define ANI_FIRETIMEOUT 2 -#define ANI_BOMBTIMEOUT 1 -#define ANI_PLAYERTIMEOUT 1 -#define ANI_PLAYERILLTIMEOUT 1 -#define ANI_STONETIMEOUT 10 - -#define TIME_FACTOR 50 -#define BOMB_TIMEOUT 5 -#define IL_TIMEOUT 20 - -#define LEN_PLAYERNAME 10 -#define LEN_SERVERNAME 41 -#define LEN_PORT 6 -#define LEN_GAMENAME 32 -#define LEN_PATHFILENAME 512 -#define LEN_FILENAME 256 -#define LEN_TILESETNAME 32 - -#define DEFAULT_UDPPORT 11000 -#define DEFAULT_GMUDPPORT "11100" -#define DEFAULT_GAMEMASTER "x.yz.to:11100" -#define GAMESRV_TIMEOUT 2000 /* Timeout of the GameSrv_GetEntry */ - -#define UDP_TIMEOUT 15000 -#define BUF_SIZE 1024 - - -enum _backgound { // to load some diffrent logos.. - BG_start = 0, - BG_net, - BG_conf -}; - - -enum _gametype { - GT_single = 0, - GT_multi -}; - - -enum _multitype { - MT_ptpm, // udp ptp master - MT_ptps // udp ptp client -}; - - -enum _gamestate { - GS_startup = 0, - GS_quit, - GS_wait, // waiting for players to join - GS_update, - GS_ready, - GS_running -}; - - -enum _fieldtype { - FT_nothing = 0, // Nothing in here - FT_stone, // Stones you can bomb away - FT_block, // Stones which can't bomb away - FT_death, // The bad Powerup - FT_fire, // Special Field for the fire - FT_bomb, - FT_shoe, - - FT_max // just to know how many types there are -}; - - -enum _playerillnestype { - PI_keys = 0, - PI_range, - PI_slow, - PI_bomb, - - PI_max // just to know what is the last number -}; - - -enum _bombstate { - BS_off = 0, - BS_ticking, - BS_exploding -}; - - -enum _playerstateflags { - PSF_used = 1, // Player Unused | Player Used - PSF_net = 2, // Local Player | AI / Network Player - PSF_alife = 4, // Player is Dead | Player is Alife - PSF_playing = 8, // Watching Player | Playing Player -- as long as one don't delete -}; - -#define PSFM_used (PSF_used + PSF_playing) -#define PSFM_alife (PSF_used + PSF_alife + PSF_playing) -#define PS_IS_dead(__ps) (((__ps) & (PSFM_alife)) == (PSFM_used)) -#define PS_IS_alife(__ps) (((__ps) & (PSFM_alife)) == (PSFM_alife)) -#define PS_IS_netplayer(__ps) (((__ps) & (PSFM_alife + PSF_net)) == (PSF_net + PSFM_alife)) -#define PS_IS_playing(__ps) (((__ps) & (PSFM_used)) == (PSFM_used)) -#define PS_IS_used(__ps) (((__ps) & (PSFM_used)) != 0) - -enum _direction { // to handle directions better - left = 0, - right, - up, - down -}; - - -struct __point { - short int x; - short int y; -} typedef _point; - -#endif +/* basic types which we need everywhere */ + +#ifndef _BC_BASIC_H_ + +#define _BC_BASIC_H_ + +#define GAME_SPECIAL_ITEMBOMB 10 +#define GAME_SPECIAL_ITEMFIRE 10 +#define GAME_SPECIAL_ITEMSHOE 15 +#define GAME_SPECIAL_ITEMDEATH 25 + +#define START_BOMBS 1 +#define START_RANGE 2 +#define START_SPEED 16 +#define SPEEDMUL 1.2 + +#define MAX_PLAYERS 8 +#define MAX_BOMBS 12 +#define MAX_RANGE 10 +#define MAX_SPEED 40 +#define MAX_UPDATERECTS 2048 +#define MAX_CONNECTS 16 /* maximal number of connection data */ +#define MAX_SERVERENTRYS 8 /* number of entrys in the server tab */ +#define MAX_GAMESRVENTRYS 255 /* number of entry which can be get */ +#define MAX_FIELDSIZE_X 51 +#define MAX_FIELDSIZE_Y 31 +#define MIN_FIELDSIZE_X 15 +#define MIN_FIELDSIZE_Y 9 + + +#define EXPLOSIONTIMEOUT 20 +#define ANI_FIRETIMEOUT 2 +#define ANI_BOMBTIMEOUT 1 +#define ANI_PLAYERTIMEOUT 1 +#define ANI_PLAYERILLTIMEOUT 1 +#define ANI_STONETIMEOUT 10 + +#define TIME_FACTOR 50 +#define BOMB_TIMEOUT 5 +#define IL_TIMEOUT 20 + +#define LEN_PLAYERNAME 10 +#define LEN_SERVERNAME 41 +#define LEN_PORT 6 +#define LEN_GAMENAME 32 +#define LEN_PATHFILENAME 512 +#define LEN_FILENAME 256 +#define LEN_TILESETNAME 32 + +#define DEFAULT_UDPPORT 11000 +#define DEFAULT_GMUDPPORT "11100" +#define DEFAULT_GAMEMASTER "x.yz.to:11100" +#define GAMESRV_TIMEOUT 2000 /* Timeout of the GameSrv_GetEntry */ + +#define UDP_TIMEOUT 15000 +#define BUF_SIZE 1024 + + +enum _backgound { // to load some diffrent logos.. + BG_start = 0, + BG_net, + BG_conf +}; + + +enum _gametype { + GT_single = 0, + GT_multi +}; + + +enum _multitype { + MT_ptpm, // udp ptp master + MT_ptps // udp ptp client +}; + + +enum _gamestate { + GS_startup = 0, + GS_quit, + GS_wait, // waiting for players to join + GS_update, + GS_ready, + GS_running +}; + + +enum _fieldtype { + FT_nothing = 0, // Nothing in here + FT_stone, // Stones you can bomb away + FT_block, // Stones which can't bomb away + FT_death, // The bad Powerup + FT_fire, // Special Field for the fire + FT_bomb, + FT_shoe, + + FT_max // just to know how many types there are +}; + + +enum _playerillnestype { + PI_keys = 0, + PI_range, + PI_slow, + PI_bomb, + + PI_max // just to know what is the last number +}; + + +enum _bombstate { + BS_off = 0, + BS_ticking, + BS_exploding +}; + + +enum _playerstateflags { + PSF_used = 1, // Player Unused | Player Used + PSF_net = 2, // Local Player | AI / Network Player + PSF_alife = 4, // Player is Dead | Player is Alife + PSF_playing = 8, // Watching Player | Playing Player -- as long as one don't delete +}; + +#define PSFM_used (PSF_used + PSF_playing) +#define PSFM_alife (PSF_used + PSF_alife + PSF_playing) +#define PS_IS_dead(__ps) (((__ps) & (PSFM_alife)) == (PSFM_used)) +#define PS_IS_alife(__ps) (((__ps) & (PSFM_alife)) == (PSFM_alife)) +#define PS_IS_netplayer(__ps) (((__ps) & (PSFM_alife + PSF_net)) == (PSF_net + PSFM_alife)) +#define PS_IS_playing(__ps) (((__ps) & (PSFM_used)) == (PSFM_used)) +#define PS_IS_used(__ps) (((__ps) & (PSFM_used)) != 0) + +enum _direction { // to handle directions better + left = 0, + right, + up, + down +}; + + +struct __point { + short int x; + short int y; +} typedef _point; + +#endif diff --git a/src/bomb.c b/src/bomb.c index 295b33b..67b537c 100644 --- a/src/bomb.c +++ b/src/bomb.c @@ -1,400 +1,400 @@ -/* everything what have to do with the bombs */ - -#include "bomberclone.h" -#include "network.h" -#include "gfx.h" - -void -restore_bomb_screen () -{ - int p, - i; - _bomb *bomb; - - for (p = 0; p < MAX_PLAYERS; p++) - for (i = 0; i < MAX_BOMBS; i++) { - bomb = &bman.players[p].bombs[i]; - if (bomb->state == BS_ticking) { - draw_stone (bomb->pos.x, bomb->pos.y); - if (bomb->pos.x > 1) - draw_stone (bomb->pos.x - 1, bomb->pos.y); - if (bomb->pos.y > 1) - draw_stone (bomb->pos.x, bomb->pos.y - 1); - if (bomb->pos.x < bman.fieldsize.x) - draw_stone (bomb->pos.x + 1, bomb->pos.y); - if (bomb->pos.y < bman.fieldsize.y) - draw_stone (bomb->pos.x, bomb->pos.y + 1); - } - } -}; - - -void -draw_bomb (_bomb * bomb) -{ - SDL_Rect src, - dest; - - /* check the framenumber */ - if (bomb->frameto-- == 0) { - bomb->frameto = ANI_BOMBTIMEOUT; - bomb->frame++; - }; - if (bomb->frame < 0 || bomb->frame >= gfx.bomb.frames || bomb->frameto > ANI_BOMBTIMEOUT) { - bomb->frame = 0; - bomb->frameto = ANI_BOMBTIMEOUT; - } - - src.w = src.w = gfx.bomb.image->w; - dest.h = src.h = gfx.block.y; - - dest.x = gfx.offset.x + (bomb->pos.x * gfx.block.x); - dest.y = gfx.offset.y + (bomb->pos.y * gfx.block.y); - - src.x = 0; - src.y = src.h * bomb->frame; - - SDL_BlitSurface (gfx.bomb.image, &src, gfx.screen, &dest); - - gfx_AddUpdateRect (dest.x, dest.y, dest.w, dest.h); -}; - - -void -bomb_explode (int p, int b) -{ - int d; - _bomb *bomb = &bman.players[p].bombs[b]; - - d_printf ("Bomb Explode p:%d, b:%d [%d,%d]\n", p, b, bomb->pos.x, bomb->pos.y); - - if (bomb->ex_nr == -1) - bomb->ex_nr = bman.last_ex_nr++; // set bomb explosion id - - bomb->to = EXPLOSIONTIMEOUT; /* set the timeout for the fireexplosion */ - bomb->state = BS_exploding; - for (d = 0; d < 4; d++) { - bomb->firer[d] = 0; - bomb->firerst[d] = -1; - } - - if (GT_MP_PTPM) /* from now on only the server let the bomb explode */ - net_game_send_bomb (p, b); -}; - - -void -bomb_loop () -{ - int p, - i; - _player *player; - _bomb *bomb; - - for (p = 0; p < MAX_PLAYERS; p++) { - player = &bman.players[p]; - if ((bman.players[p].state & PSFM_used) != 0) { - for (i = 0; i < MAX_BOMBS; i++) { - bomb = &player->bombs[i]; - if (bomb->state == BS_ticking) { - if (GT_MP_PTPM || bman.gametype == GT_single) { - if (--bomb->to == 0) // bomb will have to explode in the next loop - bomb_explode (p, i); - else - draw_bomb (bomb); - } - else { - if (--bomb->to == 0) { // bomb did not explode -> resend bombdata - bomb->to = BOMB_TIMEOUT * TIME_FACTOR; - net_game_send_bomb (bman.p_nr, i); - bomb->to = bomb->to + ((2 * RESENDCACHE_RETRY) / TIME_FACTOR); - } - draw_bomb (bomb); - } - } - else if (bomb->state == BS_exploding) { - if (bomb->to > 0) { - do_explosion (p, i); - } - if (bomb->to == 0) { // explosion done - restore_explosion (bomb); - bomb->to = 0; - bomb->state = BS_off; - } - bomb->to--; - } - } - } - } -}; - -void -get_bomb_on (int x, int y, _point bombs[]) -{ - int p, - b, - i; - _bomb *bomb; - - for (i = 0, p = 0; p < MAX_PLAYERS; p++) - if ((bman.players[p].state & PSFM_used) != 0) { - for (b = 0; b < MAX_BOMBS; b++) { - bomb = &bman.players[p].bombs[b]; - if (bomb->state == BS_ticking) { - if (bomb->pos.x == x && bomb->pos.y == y) { - bombs[i].x = p; - bombs[i].y = b; - i++; - } - } - } - } - bombs[i].x = bombs[i].y = -1; -}; - -/* if frame == -1 we will draw the framenumber in - the field.ex data */ -void -draw_fire (int x, int y, int d, int frame) -{ - SDL_Rect src, - dest; - - if (frame == -1) // no giving frame - frame = bman.field[x][y].ex[d].frame; - - src.w = src.w = gfx.block.x; - dest.h = src.h = gfx.block.y; - - dest.x = gfx.offset.x + x * gfx.block.x; - dest.y = gfx.offset.y + y * gfx.block.y; - - src.y = frame * src.w; - src.x = d * src.w; - - SDL_BlitSurface (gfx.fire.image, &src, gfx.screen, &dest); - gfx_AddUpdateRect (dest.x, dest.y, dest.w, dest.h); -}; - - -void -restore_explosion (_bomb * bomb) -{ - int i, - d; - int dx = 0, - dy = 0; - int _x, - _y; - - for (d = 0; d < 4; d++) { - switch (d) { - case (left): - dx = -1; - dy = 0; - break; - case (right): - dx = 1; - dy = 0; - break; - case (up): - dx = 0; - dy = -1; - break; - case (down): - dx = 0; - dy = 1; - break; - } - - _x = bomb->pos.x; - _y = bomb->pos.y; - - for (i = 0; i < bomb->firer[d]; i++) { - if (--bman.field[_x][_y].ex[d].count == 0) // there was only one explosion so - bman.field[_x][_y].ex[d].frame = 0; // reset the framenumber - - if (i == 0 && d == 3) - draw_stone (_x, _y); - if (i > 0) - draw_stone (_x, _y); - _x = _x + dx; - _y = _y + dy; - } - - // delete the stone completly if there was any in the way - if (bomb->firer[d] <= bomb->r && bman.field[_x][_y].type != FT_block - && bomb->ex_nr != bman.field[_x][_y].ex_nr) { - - bman.field[_x][_y].ex_nr = bomb->ex_nr; - bman.field[_x][_y].frame = 0; - bman.field[_x][_y].frameto = 0; - if (bman.field[_x][_y].special != FT_nothing) { - bman.field[_x][_y].type = bman.field[_x][_y].special; - bman.field[_x][_y].special = FT_nothing; - d_printf ("field_explode (%d,%d) ex_nr = %d\n", _x, _y, bman.field[_x][_y].ex_nr); - } - else - bman.field[_x][_y].type = FT_nothing; - - draw_stone (_x, _y); - - if (GT_MP_PTPM) /* send only if we are the master */ - net_game_send_field (_x, _y); - } - } -}; - - - -/* - check the field on which the explosion is -*/ -int -explosion_check_field (int x, int y, int p, int b) -{ - _bomb *bomb = &bman.players[p].bombs[b]; - int pl[MAX_PLAYERS]; - int i; - _point bo[MAX_PLAYERS * MAX_BOMBS]; - _bomb *tmpbomb; - _player *tmpplayer; - - if (x < 0 || x >= bman.fieldsize.x || y < 0 || y >= bman.fieldsize.y) - return FT_block; - - get_player_on (x << 8, y << 8, pl); - get_bomb_on (x, y, bo); - - // check if any bomb have to explode.. - for (i = 0; bo[i].x != -1; i++) { - tmpbomb = &bman.players[bo[i].x].bombs[bo[i].y]; - if (tmpbomb != bomb && tmpbomb->state != BS_exploding) { - tmpbomb->ex_nr = bomb->ex_nr; // set the ex_nr to identify explosions - bomb_explode (bo[i].x, bo[i].y); - } - } - - // check if any player is in the explosion - for (i = 0; pl[i] != -1; i++) { - tmpplayer = &bman.players[pl[i]]; - if (((tmpplayer->state & PSF_alife) != 0) - && (bman.gametype == GT_single - || (GT_MP_PTP && (&bman.players[bman.p_nr] == tmpplayer)))) - player_died (tmpplayer, p); - } - - // let the stones right beside explode - if (bman.field[x][y].type != FT_nothing - && bman.field[x][y].type != FT_block && bomb->ex_nr != bman.field[x][y].ex_nr) { - if (bman.field[x][y].frame == 0) { - bman.field[x][y].frameto = ANI_STONETIMEOUT; - bman.field[x][y].frame = 1; - } - draw_stone (x, y); - } - - return bman.field[x][y].type; -}; - - -/* draw the explosion as far as she got */ -void -draw_explosion (_bomb * bomb) -{ - int d, - r, - dx, - dy; - _point p; - - bomb->frameto--; - if (bomb->frameto < 0 || bomb->frameto > ANI_FIRETIMEOUT) - bomb->frameto = ANI_FIRETIMEOUT; - - for (d = 0; d < 4; d++) { - switch (d) { - case (left): - dx = -1; - dy = 0; - break; - case (right): - dx = 1; - dy = 0; - break; - case (up): - dx = 0; - dy = -1; - break; - default: - dx = 0; - dy = 1; - break; - } - p.x = bomb->pos.x; - p.y = bomb->pos.y; - - for (r = 0; r < bomb->firer[d]; r++) { - if (bomb->frameto == 0) { - bman.field[p.x][p.y].ex[d].frame++; - if (bman.field[p.x][p.y].ex[d].frame >= gfx.fire.frames) - bman.field[p.x][p.y].ex[d].frame = 0; - } - draw_fire (p.x, p.y, d, -1); - p.x += dx; - p.y += dy; - } - } -} - -/* check the fields and all this */ -void -do_explosion (int p, int b) -{ - _bomb *bomb = &bman.players[p].bombs[b]; - int dx = 0, - dy = 0, - d; - - for (d = 0; d < 4; d++) { - switch (d) { - case (left): - dx = -1; - dy = 0; - break; - case (right): - dx = 1; - dy = 0; - break; - case (up): - dx = 0; - dy = -1; - break; - case (down): - dx = 0; - dy = 1; - break; - } - - if (bomb->firer[d] <= bomb->r) { - dx = bomb->firer[d] * dx; - dy = bomb->firer[d] * dy; - - if (explosion_check_field (bomb->pos.x + dx, bomb->pos.y + dy, p, b) == - BS_off && bomb->firerst[d] == -1) { - bomb->firer[d]++; - bman.field[bomb->pos.x + dx][bomb->pos.y + dy].ex[d].count++; - bman.field[bomb->pos.x + dx][bomb->pos.y + dy].ex[d].frame = bomb->firer[d]; - /* if we have a slow pc we can enable this and disable the drawing animation */ - // draw_fire (bomb->pos.x + dx, bomb->pos.y + dy, d, gfx.fire.frames>>1); - } - else { - bomb->firerst[d] = bomb->firer[d]; - draw_stone (bomb->pos.x + dx, bomb->pos.y + dy); - } - } - } - /* with a slow pc disable this --- maybe option over a config menu */ - if (bomb->state == BS_exploding) - draw_explosion (bomb); -}; +/* everything what have to do with the bombs */ + +#include "bomberclone.h" +#include "network.h" +#include "gfx.h" + +void +restore_bomb_screen () +{ + int p, + i; + _bomb *bomb; + + for (p = 0; p < MAX_PLAYERS; p++) + for (i = 0; i < MAX_BOMBS; i++) { + bomb = &bman.players[p].bombs[i]; + if (bomb->state == BS_ticking) { + draw_stone (bomb->pos.x, bomb->pos.y); + if (bomb->pos.x > 1) + draw_stone (bomb->pos.x - 1, bomb->pos.y); + if (bomb->pos.y > 1) + draw_stone (bomb->pos.x, bomb->pos.y - 1); + if (bomb->pos.x < bman.fieldsize.x) + draw_stone (bomb->pos.x + 1, bomb->pos.y); + if (bomb->pos.y < bman.fieldsize.y) + draw_stone (bomb->pos.x, bomb->pos.y + 1); + } + } +}; + + +void +draw_bomb (_bomb * bomb) +{ + SDL_Rect src, + dest; + + /* check the framenumber */ + if (bomb->frameto-- == 0) { + bomb->frameto = ANI_BOMBTIMEOUT; + bomb->frame++; + }; + if (bomb->frame < 0 || bomb->frame >= gfx.bomb.frames || bomb->frameto > ANI_BOMBTIMEOUT) { + bomb->frame = 0; + bomb->frameto = ANI_BOMBTIMEOUT; + } + + src.w = src.w = gfx.bomb.image->w; + dest.h = src.h = gfx.block.y; + + dest.x = gfx.offset.x + (bomb->pos.x * gfx.block.x); + dest.y = gfx.offset.y + (bomb->pos.y * gfx.block.y); + + src.x = 0; + src.y = src.h * bomb->frame; + + SDL_BlitSurface (gfx.bomb.image, &src, gfx.screen, &dest); + + gfx_AddUpdateRect (dest.x, dest.y, dest.w, dest.h); +}; + + +void +bomb_explode (int p, int b) +{ + int d; + _bomb *bomb = &bman.players[p].bombs[b]; + + d_printf ("Bomb Explode p:%d, b:%d [%d,%d]\n", p, b, bomb->pos.x, bomb->pos.y); + + if (bomb->ex_nr == -1) + bomb->ex_nr = bman.last_ex_nr++; // set bomb explosion id + + bomb->to = EXPLOSIONTIMEOUT; /* set the timeout for the fireexplosion */ + bomb->state = BS_exploding; + for (d = 0; d < 4; d++) { + bomb->firer[d] = 0; + bomb->firerst[d] = -1; + } + + if (GT_MP_PTPM) /* from now on only the server let the bomb explode */ + net_game_send_bomb (p, b); +}; + + +void +bomb_loop () +{ + int p, + i; + _player *player; + _bomb *bomb; + + for (p = 0; p < MAX_PLAYERS; p++) { + player = &bman.players[p]; + if ((bman.players[p].state & PSFM_used) != 0) { + for (i = 0; i < MAX_BOMBS; i++) { + bomb = &player->bombs[i]; + if (bomb->state == BS_ticking) { + if (GT_MP_PTPM || bman.gametype == GT_single) { + if (--bomb->to == 0) // bomb will have to explode in the next loop + bomb_explode (p, i); + else + draw_bomb (bomb); + } + else { + if (--bomb->to == 0) { // bomb did not explode -> resend bombdata + bomb->to = BOMB_TIMEOUT * TIME_FACTOR; + net_game_send_bomb (bman.p_nr, i); + bomb->to = bomb->to + ((2 * RESENDCACHE_RETRY) / TIME_FACTOR); + } + draw_bomb (bomb); + } + } + else if (bomb->state == BS_exploding) { + if (bomb->to > 0) { + do_explosion (p, i); + } + if (bomb->to == 0) { // explosion done + restore_explosion (bomb); + bomb->to = 0; + bomb->state = BS_off; + } + bomb->to--; + } + } + } + } +}; + +void +get_bomb_on (int x, int y, _point bombs[]) +{ + int p, + b, + i; + _bomb *bomb; + + for (i = 0, p = 0; p < MAX_PLAYERS; p++) + if ((bman.players[p].state & PSFM_used) != 0) { + for (b = 0; b < MAX_BOMBS; b++) { + bomb = &bman.players[p].bombs[b]; + if (bomb->state == BS_ticking) { + if (bomb->pos.x == x && bomb->pos.y == y) { + bombs[i].x = p; + bombs[i].y = b; + i++; + } + } + } + } + bombs[i].x = bombs[i].y = -1; +}; + +/* if frame == -1 we will draw the framenumber in + the field.ex data */ +void +draw_fire (int x, int y, int d, int frame) +{ + SDL_Rect src, + dest; + + if (frame == -1) // no giving frame + frame = bman.field[x][y].ex[d].frame; + + src.w = src.w = gfx.block.x; + dest.h = src.h = gfx.block.y; + + dest.x = gfx.offset.x + x * gfx.block.x; + dest.y = gfx.offset.y + y * gfx.block.y; + + src.y = frame * src.w; + src.x = d * src.w; + + SDL_BlitSurface (gfx.fire.image, &src, gfx.screen, &dest); + gfx_AddUpdateRect (dest.x, dest.y, dest.w, dest.h); +}; + + +void +restore_explosion (_bomb * bomb) +{ + int i, + d; + int dx = 0, + dy = 0; + int _x, + _y; + + for (d = 0; d < 4; d++) { + switch (d) { + case (left): + dx = -1; + dy = 0; + break; + case (right): + dx = 1; + dy = 0; + break; + case (up): + dx = 0; + dy = -1; + break; + case (down): + dx = 0; + dy = 1; + break; + } + + _x = bomb->pos.x; + _y = bomb->pos.y; + + for (i = 0; i < bomb->firer[d]; i++) { + if (--bman.field[_x][_y].ex[d].count == 0) // there was only one explosion so + bman.field[_x][_y].ex[d].frame = 0; // reset the framenumber + + if (i == 0 && d == 3) + draw_stone (_x, _y); + if (i > 0) + draw_stone (_x, _y); + _x = _x + dx; + _y = _y + dy; + } + + // delete the stone completly if there was any in the way + if (bomb->firer[d] <= bomb->r && bman.field[_x][_y].type != FT_block + && bomb->ex_nr != bman.field[_x][_y].ex_nr) { + + bman.field[_x][_y].ex_nr = bomb->ex_nr; + bman.field[_x][_y].frame = 0; + bman.field[_x][_y].frameto = 0; + if (bman.field[_x][_y].special != FT_nothing) { + bman.field[_x][_y].type = bman.field[_x][_y].special; + bman.field[_x][_y].special = FT_nothing; + d_printf ("field_explode (%d,%d) ex_nr = %d\n", _x, _y, bman.field[_x][_y].ex_nr); + } + else + bman.field[_x][_y].type = FT_nothing; + + draw_stone (_x, _y); + + if (GT_MP_PTPM) /* send only if we are the master */ + net_game_send_field (_x, _y); + } + } +}; + + + +/* + check the field on which the explosion is +*/ +int +explosion_check_field (int x, int y, int p, int b) +{ + _bomb *bomb = &bman.players[p].bombs[b]; + int pl[MAX_PLAYERS]; + int i; + _point bo[MAX_PLAYERS * MAX_BOMBS]; + _bomb *tmpbomb; + _player *tmpplayer; + + if (x < 0 || x >= bman.fieldsize.x || y < 0 || y >= bman.fieldsize.y) + return FT_block; + + get_player_on (x << 8, y << 8, pl); + get_bomb_on (x, y, bo); + + // check if any bomb have to explode.. + for (i = 0; bo[i].x != -1; i++) { + tmpbomb = &bman.players[bo[i].x].bombs[bo[i].y]; + if (tmpbomb != bomb && tmpbomb->state != BS_exploding) { + tmpbomb->ex_nr = bomb->ex_nr; // set the ex_nr to identify explosions + bomb_explode (bo[i].x, bo[i].y); + } + } + + // check if any player is in the explosion + for (i = 0; pl[i] != -1; i++) { + tmpplayer = &bman.players[pl[i]]; + if (((tmpplayer->state & PSF_alife) != 0) + && (bman.gametype == GT_single + || (GT_MP_PTP && (&bman.players[bman.p_nr] == tmpplayer)))) + player_died (tmpplayer, p); + } + + // let the stones right beside explode + if (bman.field[x][y].type != FT_nothing + && bman.field[x][y].type != FT_block && bomb->ex_nr != bman.field[x][y].ex_nr) { + if (bman.field[x][y].frame == 0) { + bman.field[x][y].frameto = ANI_STONETIMEOUT; + bman.field[x][y].frame = 1; + } + draw_stone (x, y); + } + + return bman.field[x][y].type; +}; + + +/* draw the explosion as far as she got */ +void +draw_explosion (_bomb * bomb) +{ + int d, + r, + dx, + dy; + _point p; + + bomb->frameto--; + if (bomb->frameto < 0 || bomb->frameto > ANI_FIRETIMEOUT) + bomb->frameto = ANI_FIRETIMEOUT; + + for (d = 0; d < 4; d++) { + switch (d) { + case (left): + dx = -1; + dy = 0; + break; + case (right): + dx = 1; + dy = 0; + break; + case (up): + dx = 0; + dy = -1; + break; + default: + dx = 0; + dy = 1; + break; + } + p.x = bomb->pos.x; + p.y = bomb->pos.y; + + for (r = 0; r < bomb->firer[d]; r++) { + if (bomb->frameto == 0) { + bman.field[p.x][p.y].ex[d].frame++; + if (bman.field[p.x][p.y].ex[d].frame >= gfx.fire.frames) + bman.field[p.x][p.y].ex[d].frame = 0; + } + draw_fire (p.x, p.y, d, -1); + p.x += dx; + p.y += dy; + } + } +} + +/* check the fields and all this */ +void +do_explosion (int p, int b) +{ + _bomb *bomb = &bman.players[p].bombs[b]; + int dx = 0, + dy = 0, + d; + + for (d = 0; d < 4; d++) { + switch (d) { + case (left): + dx = -1; + dy = 0; + break; + case (right): + dx = 1; + dy = 0; + break; + case (up): + dx = 0; + dy = -1; + break; + case (down): + dx = 0; + dy = 1; + break; + } + + if (bomb->firer[d] <= bomb->r) { + dx = bomb->firer[d] * dx; + dy = bomb->firer[d] * dy; + + if (explosion_check_field (bomb->pos.x + dx, bomb->pos.y + dy, p, b) == + BS_off && bomb->firerst[d] == -1) { + bomb->firer[d]++; + bman.field[bomb->pos.x + dx][bomb->pos.y + dy].ex[d].count++; + bman.field[bomb->pos.x + dx][bomb->pos.y + dy].ex[d].frame = bomb->firer[d]; + /* if we have a slow pc we can enable this and disable the drawing animation */ + // draw_fire (bomb->pos.x + dx, bomb->pos.y + dy, d, gfx.fire.frames>>1); + } + else { + bomb->firerst[d] = bomb->firer[d]; + draw_stone (bomb->pos.x + dx, bomb->pos.y + dy); + } + } + } + /* with a slow pc disable this --- maybe option over a config menu */ + if (bomb->state == BS_exploding) + draw_explosion (bomb); +}; diff --git a/src/bomberclone.h b/src/bomberclone.h index 558fc8d..6cea591 100644 --- a/src/bomberclone.h +++ b/src/bomberclone.h @@ -1,245 +1,245 @@ -/* $Id: bomberclone.h,v 1.16 2003/05/07 21:28:12 stpohle Exp $ */ -/* bomberclone.h */ - -#ifndef _BOMBERCLONE_H_ -#define _BOMBERCLONE_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef _WIN32 - #include - #include - #include - #ifndef S_ISDIR - #define S_ISDIR(a) ((a & _S_IFDIR) == _S_IFDIR) - #endif - #ifndef S_ISREG - #define S_ISREG(a) ((a & _S_IFREG) == _S_IFREG) - #endif -#else - #include - #include - #include - #include - #include - #include - #include - #include -#endif -#include -#include "../config.h" -#include "gfx.h" -#include "network.h" -#include "sysfunc.h" - - -struct __playerilness { - int to; // if (to > 0) the ilness is still working - int data; -} typedef _playerilness; - - -struct __bomb { - _point pos; // lower byte = _X Higher Byte = FX - int firer[4]; // range of the fire for the fire for each direction - int firerst[4]; /* just save here where the direction was going to stop (-1) - if the exp is still growing */ - int to; // timeout in ms after dropping the bomb. (loops * 0.0005sec) - int frame; // frame of the animation - int frameto; // timeout for the frame - unsigned char r; // range of the bomb - unsigned char state; // state of the bomb - int ex_nr; // explosion number -} typedef _bomb; - - -struct __player { - _gfxplayer *gfx; // pointer to the gfx information - int gfx_nr; // number of the player GFX - - int frame; // step of the animation - int frameto; // timeout for the animation - - int illframe; - int illframeto; - - _point pos; /* position (without the offset) - _x = pos.x & 255; fx = pos.x >> 8; */ - _point old; // the old position - signed char d; // direction - signed char m; // player is moving ? - signed char old_m; // to save the old state.. - - int bombs_n; // maximal number of bombs for the player - _bomb bombs[MAX_BOMBS]; // number of bombs who are ticking. - int range; // range of the bombs - int speed; // how fast we can go (0 = slow, 1 = normal... 3 = fastest) - int speeddat; // some data i need to do the speed thing - _playerilness ill[PI_max]; // all possible types - - char name[LEN_PLAYERNAME]; // name oder name[0] == 0 - unsigned char state; // status of the player - signed char in_nr; // number of the connected player entry - - int points; // points - int wins; // wins - signed char dead_by; // player who killed this player - - _net_player net; // holds all important network data -} typedef _player; - - -struct __ex_field { - unsigned char count; - unsigned char frame; -} typedef _ex_field; - - -struct __field { - unsigned char type; - int frame; // frame (frame > 0 && FS_stone) - int frameto; // frame to - unsigned char special; // to save special stones - _ex_field ex[4]; // count up every explosion there is on this field for ever direction - int ex_nr; // number to identify the explosion. -} typedef _field; - - -struct __serverlist { - char name[255]; -} typedef _serverlist; - - -struct __bomberclone { - _point fieldsize; // dimension of the field - char datapath[512]; - - _player players[MAX_PLAYERS]; - int p_nr; // Playernumber 0 if you host a game or the number of the one you are. - - _field field[MAX_FIELDSIZE_X][MAX_FIELDSIZE_Y]; - - int random_map; // random selecting of a map - char fieldpath[512]; // path of the field file - - int last_ex_nr; // number of the last explosion - - unsigned char gametype; - unsigned char multitype; - unsigned char state; - char playername[LEN_PLAYERNAME]; - int players_nr_s; // number of players at the beginning - int players_nr; // number of player who are alife - signed char lastwinner; // number of the last winnet - - int maxplayer; // number of max players for the server - - int sock; // the server socket - unsigned char net_ai_family; - char port[LEN_PORT]; // what port we're using - char servername[LEN_SERVERNAME + LEN_PORT + 2]; // holds the name of the current server - _serverlist serverlist[MAX_SERVERENTRYS]; // ** CONFIG name of the server we are connected to - char gamename[LEN_GAMENAME]; // this will hold the game name - char gamemaster[LEN_SERVERNAME + LEN_PORT + 2]; // ** CONFIG ... GameMaster Address - unsigned char notifygamemaster; - unsigned char askplayername; // ask player for name at startup - signed char debug; // 0 = off 1 = on -} typedef _bomberclone; - - -struct __menu { - int index; - char text[255]; - // int type; // could be visible / disabled / grayed ?? should avoid -2 trick -} typedef _menu; - -extern _bomberclone bman; -extern Uint32 timestamp; -extern int debug; - -// Game routines.. -extern void game_draw_info (); -extern void game_loop (); -extern void game_end (); -extern void game_set_playerposition(); - -// everything is declared in field.c -extern void draw_field (); -extern void draw_stone (int x, int y); -extern void field_new (char *filename); -extern void field_set_playerposition (int usermap); -extern void tileset_random (); - -// everything what is declared in players.c -extern void dead_playerani (); -extern void draw_player (_player * player); -extern void restore_players_screen (); -extern void move_player (); -extern int stepmove_player (); -extern void player_drop_bomb (); -extern void get_player_on (short int x, short int y, int pl_nr[]); -extern void player_died (_player * player, signed char dead_by); -extern void draw_players (); -extern void player_animation (_player * player); -extern int check_field (short int fx, short int fy, _player * p); -extern void player_calcstep (_player * pl); -extern void player_calcpos (); -extern void player_set_ilness (_player *p, int t); -extern void player_clear_ilness (_player *p, int type); -extern void player_ilness_loop (); -extern void player_check_powerup (_player * p); -extern void player_set_gfx (_player *p, signed char gfx_nr); - -// for the bomb.. -extern void bomb_loop (); -extern void restore_bomb_screen (); -extern void get_bomb_on (int x, int y, _point bombs[]); -extern void draw_fire (int x, int y, int d, int frame); -extern void do_explosion (int p, int b); -extern void restore_explosion (_bomb * bomb); -extern int explosion_check_field (int x, int y, int p, int b); -extern void bomb_explode (int p, int b); - -// menus -extern void draw_select (int select, _menu menu[], int x, int y); -extern int menu_loop (char *menutitle, _menu menu[], int lastselect); -extern void draw_menu (char *text, _menu menu[], int *x, int *y); -extern void menu_get_text (char *title, char *text, int len); -extern void menu_displaymessage (char *title, char *text); -extern void menu_displaytext (char *title, char *text, Uint8 r, Uint8 g, Uint8 b); -extern char *menu_dir_select (char *title, char *path, signed char dirflags); - -// configuration -extern void configuration (); -extern void game_init (); -extern int ReadConfig(); -extern int WriteConfig(); -extern void ReadPrgArgs (int argc, char **argv); - -// debug.c -extern void d_in_pl_detail (char *head); -extern void d_playerdetail (char *head); -extern void d_gamedetail (char *head); -extern void d_printf (char *fmt,...); - - -// single.c -extern void single_game_new (); -extern void single_create_ai (); -extern void single_loop(); - -// mapmenu.c -extern void map_random (); -extern void tileset_random (); -extern void mapmenu (); -extern char* getfilename(char* path); -extern void init_map_tileset(); - -#endif - +/* $Id: bomberclone.h,v 1.17 2003/05/08 14:35:48 stpohle Exp $ */ +/* bomberclone.h */ + +#ifndef _BOMBERCLONE_H_ +#define _BOMBERCLONE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 + #include + #include + #include + #ifndef S_ISDIR + #define S_ISDIR(a) ((a & _S_IFDIR) == _S_IFDIR) + #endif + #ifndef S_ISREG + #define S_ISREG(a) ((a & _S_IFREG) == _S_IFREG) + #endif +#else + #include + #include + #include + #include + #include + #include + #include + #include +#endif +#include +#include "../config.h" +#include "gfx.h" +#include "network.h" +#include "sysfunc.h" + + +struct __playerilness { + int to; // if (to > 0) the ilness is still working + int data; +} typedef _playerilness; + + +struct __bomb { + _point pos; // lower byte = _X Higher Byte = FX + int firer[4]; // range of the fire for the fire for each direction + int firerst[4]; /* just save here where the direction was going to stop (-1) + if the exp is still growing */ + int to; // timeout in ms after dropping the bomb. (loops * 0.0005sec) + int frame; // frame of the animation + int frameto; // timeout for the frame + unsigned char r; // range of the bomb + unsigned char state; // state of the bomb + int ex_nr; // explosion number +} typedef _bomb; + + +struct __player { + _gfxplayer *gfx; // pointer to the gfx information + int gfx_nr; // number of the player GFX + + int frame; // step of the animation + int frameto; // timeout for the animation + + int illframe; + int illframeto; + + _point pos; /* position (without the offset) + _x = pos.x & 255; fx = pos.x >> 8; */ + _point old; // the old position + signed char d; // direction + signed char m; // player is moving ? + signed char old_m; // to save the old state.. + + int bombs_n; // maximal number of bombs for the player + _bomb bombs[MAX_BOMBS]; // number of bombs who are ticking. + int range; // range of the bombs + int speed; // how fast we can go (0 = slow, 1 = normal... 3 = fastest) + int speeddat; // some data i need to do the speed thing + _playerilness ill[PI_max]; // all possible types + + char name[LEN_PLAYERNAME]; // name oder name[0] == 0 + unsigned char state; // status of the player + signed char in_nr; // number of the connected player entry + + int points; // points + int wins; // wins + signed char dead_by; // player who killed this player + + _net_player net; // holds all important network data +} typedef _player; + + +struct __ex_field { + unsigned char count; + unsigned char frame; +} typedef _ex_field; + + +struct __field { + unsigned char type; + int frame; // frame (frame > 0 && FS_stone) + int frameto; // frame to + unsigned char special; // to save special stones + _ex_field ex[4]; // count up every explosion there is on this field for ever direction + int ex_nr; // number to identify the explosion. +} typedef _field; + + +struct __serverlist { + char name[255]; +} typedef _serverlist; + + +struct __bomberclone { + _point fieldsize; // dimension of the field + char datapath[512]; + + _player players[MAX_PLAYERS]; + int p_nr; // Playernumber 0 if you host a game or the number of the one you are. + + _field field[MAX_FIELDSIZE_X][MAX_FIELDSIZE_Y]; + + int random_map; // random selecting of a map + char fieldpath[512]; // path of the field file + + int last_ex_nr; // number of the last explosion + + unsigned char gametype; + unsigned char multitype; + unsigned char state; + char playername[LEN_PLAYERNAME]; + int players_nr_s; // number of players at the beginning + int players_nr; // number of player who are alife + signed char lastwinner; // number of the last winnet + + int maxplayer; // number of max players for the server + + int sock; // the server socket + unsigned char net_ai_family; + char port[LEN_PORT]; // what port we're using + char servername[LEN_SERVERNAME + LEN_PORT + 2]; // holds the name of the current server + _serverlist serverlist[MAX_SERVERENTRYS]; // ** CONFIG name of the server we are connected to + char gamename[LEN_GAMENAME]; // this will hold the game name + char gamemaster[LEN_SERVERNAME + LEN_PORT + 2]; // ** CONFIG ... GameMaster Address + unsigned char notifygamemaster; + unsigned char askplayername; // ask player for name at startup + signed char debug; // 0 = off 1 = on +} typedef _bomberclone; + + +struct __menu { + int index; + char text[255]; + // int type; // could be visible / disabled / grayed ?? should avoid -2 trick +} typedef _menu; + +extern _bomberclone bman; +extern Uint32 timestamp; +extern int debug; + +// Game routines.. +extern void game_draw_info (); +extern void game_loop (); +extern void game_end (); +extern void game_set_playerposition(); + +// everything is declared in field.c +extern void draw_field (); +extern void draw_stone (int x, int y); +extern void field_new (char *filename); +extern void field_set_playerposition (int usermap); +extern void tileset_random (); + +// everything what is declared in players.c +extern void dead_playerani (); +extern void draw_player (_player * player); +extern void restore_players_screen (); +extern void move_player (); +extern int stepmove_player (); +extern void player_drop_bomb (); +extern void get_player_on (short int x, short int y, int pl_nr[]); +extern void player_died (_player * player, signed char dead_by); +extern void draw_players (); +extern void player_animation (_player * player); +extern int check_field (short int fx, short int fy, _player * p); +extern void player_calcstep (_player * pl); +extern void player_calcpos (); +extern void player_set_ilness (_player *p, int t); +extern void player_clear_ilness (_player *p, int type); +extern void player_ilness_loop (); +extern void player_check_powerup (_player * p); +extern void player_set_gfx (_player *p, signed char gfx_nr); + +// for the bomb.. +extern void bomb_loop (); +extern void restore_bomb_screen (); +extern void get_bomb_on (int x, int y, _point bombs[]); +extern void draw_fire (int x, int y, int d, int frame); +extern void do_explosion (int p, int b); +extern void restore_explosion (_bomb * bomb); +extern int explosion_check_field (int x, int y, int p, int b); +extern void bomb_explode (int p, int b); + +// menus +extern void draw_select (int select, _menu menu[], int x, int y); +extern int menu_loop (char *menutitle, _menu menu[], int lastselect); +extern void draw_menu (char *text, _menu menu[], int *x, int *y); +extern void menu_get_text (char *title, char *text, int len); +extern void menu_displaymessage (char *title, char *text); +extern void menu_displaytext (char *title, char *text, Uint8 r, Uint8 g, Uint8 b); +extern char *menu_dir_select (char *title, char *path, signed char dirflags); + +// configuration +extern void configuration (); +extern void game_init (); +extern int ReadConfig(); +extern int WriteConfig(); +extern void ReadPrgArgs (int argc, char **argv); + +// debug.c +extern void d_in_pl_detail (char *head); +extern void d_playerdetail (char *head); +extern void d_gamedetail (char *head); +extern void d_printf (char *fmt,...); + + +// single.c +extern void single_game_new (); +extern void single_create_ai (); +extern void single_loop(); + +// mapmenu.c +extern void map_random (); +extern void tileset_random (); +extern void mapmenu (); +extern char* getfilename(char* path); +extern void init_map_tileset(); + +#endif + diff --git a/src/chat.c b/src/chat.c index a6922fa..ea25574 100644 --- a/src/chat.c +++ b/src/chat.c @@ -1,233 +1,233 @@ -/* - chat.c - this file will do everything what have to do with the chat.. -*/ - -#include "bomberclone.h" -#include "network.h" -#include "packets.h" -#include "gfx.h" -#include "keybinput.h" -#include "chat.h" - -_chat chat; - -/* find a free line or delete the oldest one */ -int -chat_findfreeline () -{ - int i; - - for (i = 0; (i < CHAT_MAX_LINES && chat.lines[i][0] != 0); i++); - - if (i >= CHAT_MAX_LINES) { - memcpy (chat.lines[1], chat.lines[0], 255); - i = 255; - } - - chat.changed = 1; - - return i; -} - -void -chat_addline (char *text) -{ - int l; - - l = chat_findfreeline (); - - strncpy (chat.lines[l], text, 255); - chat.lineschanged = 1; -} - -void -chat_drawbox () -{ - SDL_Rect src; - int i; - - if (chat.visible == 0) - chat.oldscreen = gfx_copyscreen (&chat.window); - - chat.visible = 1; - - if (gfx_locksurface (gfx.screen)) - return; - - for (i = 0; i < 2; i++) { - src.x = chat.window.x + i; - src.w = src.x + chat.window.w - 2; - src.y = chat.window.y + i; - src.h = src.y + chat.window.h - 2; - draw_shadefield (gfx.screen, &src, CHAT_BG_SHADE_BRIGHT); - } - - gfx_unlocksurface (gfx.screen); - - src.x = chat.window.x + 2; - src.y = chat.window.y + 2; - src.w = src.x + chat.window.w - 4; - src.h = src.y + chat.window.h - 4 - 16; - draw_shadefield (gfx.screen, &src, CHAT_BG_SHADE_DARK); - src.x = chat.window.x + 2; - src.y = chat.window.y + chat.window.h - 18; - src.w = src.x + chat.window.w - 4; - src.h = src.y + 16; - draw_shadefield (gfx.screen, &src, CHAT_BG_SHADE_DARK >> 1); -}; - - -void -chat_deletebox () -{ - SDL_Rect src, - dest; - - src.x = 0; - src.y = 0; - src.w = dest.w = chat.oldscreen->w; - src.h = dest.h = chat.oldscreen->h; - - dest.x = chat.window.x; - dest.y = chat.window.y; - - SDL_BlitSurface (chat.oldscreen, &src, gfx.screen, &dest); - gfx_AddUpdateRect (chat.window.x, chat.window.y, chat.window.w, chat.window.h); - - chat.visible = 0; - SDL_FreeSurface (chat.oldscreen); - chat.oldscreen = NULL; -}; - - -void -chat_show (int x1, int y1, int x2, int y2) -{ - if (chat.visible != 0) - chat_deletebox (); - - if (x1 == -1 || x2 == -1 || y1 == -1 || y2 == -1 || x2 <= x1 || y2 <= y1) - chat.visible = 0; - else { - chat.window.x = x1; - chat.window.y = y1; - chat.window.w = x2 - x1; - chat.window.h = y2 - y1; - chat_drawbox (); - keybinput_new (&chat.input); - gfx_AddUpdateRect (chat.window.x, chat.window.y, chat.window.w, chat.window.h); - chat.changed = 1; - chat.lineschanged = 1; - } -}; - - -void -chat_clearscreen (signed char all) -{ - SDL_Rect src, - dest; - - if (all == 1) { - dest.x = chat.window.x + 2; - dest.y = chat.window.y + 2; - dest.w = dest.x + chat.window.w - 4; - dest.h = dest.y + chat.window.h - 4; - - src.x = 2; - src.y = 2; - src.w = chat.window.w - 4; - src.h = chat.window.h - 4; - } - else { - /* redraw only the textline of out input box */ - dest.x = chat.window.x + 2; - dest.y = chat.window.y + chat.window.h - 18; - dest.w = src.w = chat.window.w - 4; - dest.h = src.h = 16; - - src.x = 2; - src.y = chat.window.h - 18; - } - SDL_BlitSurface (chat.oldscreen, &src, gfx.screen, &dest); - - if (all == 1) { - dest.w = dest.x + chat.window.w - 4; - dest.h = dest.y + chat.window.h - 4 - 16; - draw_shadefield (gfx.screen, &dest, CHAT_BG_SHADE_DARK); - } - - src.x = chat.window.x + 2; - src.y = chat.window.y + chat.window.h - 18; - src.w = src.x + chat.window.w - 4; - src.h = src.y + 16; - draw_shadefield (gfx.screen, &src, CHAT_BG_SHADE_DARK >> 1); - - gfx_AddUpdateRect (chat.window.x, chat.window.y, chat.window.w, chat.window.h); -}; - - -void -chat_loop (SDL_Event * event) -{ - int i, - y, - l, - p1, - p2, - maxchar; - char text[255]; - - i = keybinput_loop (&chat.input, event); - - if (i == 1 && chat.input.text[0] != 0) { - sprintf (text, "%s: %s", bman.playername, chat.input.text); - net_send_chat (text, 1); - chat_addline (text); - keybinput_new (&chat.input); - i = 0; - } - - if (((i == 0 && chat.input.changed == 1) || chat.changed == 1) && chat.visible == 1) { - /* draw the new field */ - chat_clearscreen (chat.lineschanged); - p1 = p2 = 0; - maxchar = (chat.window.w - 4) / (gfx.font.size.x - 4); - if (chat.lineschanged) { - y = chat.window.y + 4; - l = chat.startline; - while (y < (chat.window.y + chat.window.h - 32) && chat.lines[l][0] != 0) { - for (p1 = 0; (p1 < maxchar && chat.lines[l][p2] != 0); p1++) - text[p1] = chat.lines[l][p2++]; - text[p1] = 0; - draw_text (chat.window.x + 4, y, text, 1); - if (chat.lines[l][p2] == 0) { // the end of the line - l++; - p2 = 0; - } - y = y + gfx.font.size.y; - } - if (chat.lines[l][0] != 0) { - chat.startline++; - chat.changed = 1; - chat.lineschanged = 1; - } - else { - chat.changed = 0; - chat.lineschanged = 0; - } - } - if (chat.startline >= CHAT_MAX_LINES) - chat.startline = CHAT_MAX_LINES - 5; - - /* draw the input line */ - if (chat.input.len > maxchar) - p2 = chat.input.len - maxchar; - - for (p1 = 0; (p1 < maxchar && chat.input.text[p2] != 0); p1++) - text[p1] = chat.input.text[p2++]; - text[p1] = 0; - draw_text (chat.window.x + 4, (chat.window.y + chat.window.h) - 4 - gfx.font.size.y, text, - 1); - } -}; +/* + chat.c - this file will do everything what have to do with the chat.. +*/ + +#include "bomberclone.h" +#include "network.h" +#include "packets.h" +#include "gfx.h" +#include "keybinput.h" +#include "chat.h" + +_chat chat; + +/* find a free line or delete the oldest one */ +int +chat_findfreeline () +{ + int i; + + for (i = 0; (i < CHAT_MAX_LINES && chat.lines[i][0] != 0); i++); + + if (i >= CHAT_MAX_LINES) { + memcpy (chat.lines[1], chat.lines[0], 255); + i = 255; + } + + chat.changed = 1; + + return i; +} + +void +chat_addline (char *text) +{ + int l; + + l = chat_findfreeline (); + + strncpy (chat.lines[l], text, 255); + chat.lineschanged = 1; +} + +void +chat_drawbox () +{ + SDL_Rect src; + int i; + + if (chat.visible == 0) + chat.oldscreen = gfx_copyscreen (&chat.window); + + chat.visible = 1; + + if (gfx_locksurface (gfx.screen)) + return; + + for (i = 0; i < 2; i++) { + src.x = chat.window.x + i; + src.w = src.x + chat.window.w - 2; + src.y = chat.window.y + i; + src.h = src.y + chat.window.h - 2; + draw_shadefield (gfx.screen, &src, CHAT_BG_SHADE_BRIGHT); + } + + gfx_unlocksurface (gfx.screen); + + src.x = chat.window.x + 2; + src.y = chat.window.y + 2; + src.w = src.x + chat.window.w - 4; + src.h = src.y + chat.window.h - 4 - 16; + draw_shadefield (gfx.screen, &src, CHAT_BG_SHADE_DARK); + src.x = chat.window.x + 2; + src.y = chat.window.y + chat.window.h - 18; + src.w = src.x + chat.window.w - 4; + src.h = src.y + 16; + draw_shadefield (gfx.screen, &src, CHAT_BG_SHADE_DARK >> 1); +}; + + +void +chat_deletebox () +{ + SDL_Rect src, + dest; + + src.x = 0; + src.y = 0; + src.w = dest.w = chat.oldscreen->w; + src.h = dest.h = chat.oldscreen->h; + + dest.x = chat.window.x; + dest.y = chat.window.y; + + SDL_BlitSurface (chat.oldscreen, &src, gfx.screen, &dest); + gfx_AddUpdateRect (chat.window.x, chat.window.y, chat.window.w, chat.window.h); + + chat.visible = 0; + SDL_FreeSurface (chat.oldscreen); + chat.oldscreen = NULL; +}; + + +void +chat_show (int x1, int y1, int x2, int y2) +{ + if (chat.visible != 0) + chat_deletebox (); + + if (x1 == -1 || x2 == -1 || y1 == -1 || y2 == -1 || x2 <= x1 || y2 <= y1) + chat.visible = 0; + else { + chat.window.x = x1; + chat.window.y = y1; + chat.window.w = x2 - x1; + chat.window.h = y2 - y1; + chat_drawbox (); + keybinput_new (&chat.input); + gfx_AddUpdateRect (chat.window.x, chat.window.y, chat.window.w, chat.window.h); + chat.changed = 1; + chat.lineschanged = 1; + } +}; + + +void +chat_clearscreen (signed char all) +{ + SDL_Rect src, + dest; + + if (all == 1) { + dest.x = chat.window.x + 2; + dest.y = chat.window.y + 2; + dest.w = dest.x + chat.window.w - 4; + dest.h = dest.y + chat.window.h - 4; + + src.x = 2; + src.y = 2; + src.w = chat.window.w - 4; + src.h = chat.window.h - 4; + } + else { + /* redraw only the textline of out input box */ + dest.x = chat.window.x + 2; + dest.y = chat.window.y + chat.window.h - 18; + dest.w = src.w = chat.window.w - 4; + dest.h = src.h = 16; + + src.x = 2; + src.y = chat.window.h - 18; + } + SDL_BlitSurface (chat.oldscreen, &src, gfx.screen, &dest); + + if (all == 1) { + dest.w = dest.x + chat.window.w - 4; + dest.h = dest.y + chat.window.h - 4 - 16; + draw_shadefield (gfx.screen, &dest, CHAT_BG_SHADE_DARK); + } + + src.x = chat.window.x + 2; + src.y = chat.window.y + chat.window.h - 18; + src.w = src.x + chat.window.w - 4; + src.h = src.y + 16; + draw_shadefield (gfx.screen, &src, CHAT_BG_SHADE_DARK >> 1); + + gfx_AddUpdateRect (chat.window.x, chat.window.y, chat.window.w, chat.window.h); +}; + + +void +chat_loop (SDL_Event * event) +{ + int i, + y, + l, + p1, + p2, + maxchar; + char text[255]; + + i = keybinput_loop (&chat.input, event); + + if (i == 1 && chat.input.text[0] != 0) { + sprintf (text, "%s: %s", bman.playername, chat.input.text); + net_send_chat (text, 1); + chat_addline (text); + keybinput_new (&chat.input); + i = 0; + } + + if (((i == 0 && chat.input.changed == 1) || chat.changed == 1) && chat.visible == 1) { + /* draw the new field */ + chat_clearscreen (chat.lineschanged); + p1 = p2 = 0; + maxchar = (chat.window.w - 4) / (gfx.font.size.x - 4); + if (chat.lineschanged) { + y = chat.window.y + 4; + l = chat.startline; + while (y < (chat.window.y + chat.window.h - 32) && chat.lines[l][0] != 0) { + for (p1 = 0; (p1 < maxchar && chat.lines[l][p2] != 0); p1++) + text[p1] = chat.lines[l][p2++]; + text[p1] = 0; + draw_text (chat.window.x + 4, y, text, 1); + if (chat.lines[l][p2] == 0) { // the end of the line + l++; + p2 = 0; + } + y = y + gfx.font.size.y; + } + if (chat.lines[l][0] != 0) { + chat.startline++; + chat.changed = 1; + chat.lineschanged = 1; + } + else { + chat.changed = 0; + chat.lineschanged = 0; + } + } + if (chat.startline >= CHAT_MAX_LINES) + chat.startline = CHAT_MAX_LINES - 5; + + /* draw the input line */ + if (chat.input.len > maxchar) + p2 = chat.input.len - maxchar; + + for (p1 = 0; (p1 < maxchar && chat.input.text[p2] != 0); p1++) + text[p1] = chat.input.text[p2++]; + text[p1] = 0; + draw_text (chat.window.x + 4, (chat.window.y + chat.window.h) - 4 - gfx.font.size.y, text, + 1); + } +}; diff --git a/src/chat.h b/src/chat.h index 1d69ee4..6c0335e 100644 --- a/src/chat.h +++ b/src/chat.h @@ -1,29 +1,29 @@ - -#ifndef _CHAT_H_ -#define _CHAT_H_ - -#include "keybinput.h" - -#define CHAT_MAX_LINES 255 -#define CHAT_BG_SHADE_DARK -64 -#define CHAT_BG_SHADE_BRIGHT 64 - -struct __chat { - SDL_Rect window; - signed char visible; - signed char changed; - SDL_Surface *oldscreen; - short int startline; - char lines[CHAT_MAX_LINES][255]; - signed char lineschanged; - _keybinput input; -} typedef _chat; - -extern _chat chat; - -extern void chat_show (int x1, int y1, int x2, int y2); -extern void chat_addline (char *text); -extern void chat_loop (SDL_Event *event); -extern void chat_drawbox (); - -#endif + +#ifndef _CHAT_H_ +#define _CHAT_H_ + +#include "keybinput.h" + +#define CHAT_MAX_LINES 255 +#define CHAT_BG_SHADE_DARK -64 +#define CHAT_BG_SHADE_BRIGHT 64 + +struct __chat { + SDL_Rect window; + signed char visible; + signed char changed; + SDL_Surface *oldscreen; + short int startline; + char lines[CHAT_MAX_LINES][255]; + signed char lineschanged; + _keybinput input; +} typedef _chat; + +extern _chat chat; + +extern void chat_show (int x1, int y1, int x2, int y2); +extern void chat_addline (char *text); +extern void chat_loop (SDL_Event *event); +extern void chat_drawbox (); + +#endif diff --git a/src/configuration.c b/src/configuration.c index dc14570..5dddf51 100644 --- a/src/configuration.c +++ b/src/configuration.c @@ -1,394 +1,394 @@ -/* configuration */ - -#include - -#include "basic.h" -#include "bomberclone.h" -#include "network.h" -#include "packets.h" -#include "gfx.h" -#include "chat.h" - -void -game_init () -{ - int i; - - srand (((int) time (NULL))); // initialize randomgenerator - - // do some init stuff - for (i = 0; i < MAX_SERVERENTRYS; i++) - bman.serverlist[i].name[0] = 0; - - for (i = 0; i < MAX_PLAYERS; i++) { - bman.players[i].gfx = NULL; /* we will select them in the wait_for_players loop */ - bman.players[i].gfx_nr = -1; /* and even now in the singleplayer menu */ - } - - chat.visible = 0; - chat.startline = 0; - for (i = 0; i < CHAT_MAX_LINES; i++) - chat.lines[i][0] = 0; - - bman.maxplayer = MAX_PLAYERS; - bman.net_ai_family = PF_INET; - bman.sock = -1; - bman.gamename[0] = 0; - sprintf (bman.port, "%d", DEFAULT_UDPPORT); - sprintf (bman.gamemaster, DEFAULT_GAMEMASTER); - resend_cache.data = NULL; - resend_cache.fill = -1; - bman.notifygamemaster = 1; - bman.askplayername = 1; - debug = 0; - gfx.res.x = 640; - gfx.res.y = 480; - gfx.bpp = 16; - gfx.tileset[0] = 0; - gfx.random_tileset = 1; - bman.fieldsize.x = 25; - bman.fieldsize.y = 17; - sprintf (bman.datapath, "data"); - bman.fieldpath[0] = 0; - bman.random_map = 1; - init_map_tileset(); -}; - -int -ReadConfig () -{ - FILE *config; - char buf[1024], - key2[1024]; - char *findit, - *keyword, - *value; - int i; - char filename[512]; - -#ifdef _WIN32 - sprintf (filename, "%sbomberclone.cfg", s_gethomedir ()); -#else - sprintf (filename, "%s.bomberclone.cfg", s_gethomedir ()); -#endif - - config = fopen (filename, "r"); - if (config == NULL) { - d_printf ("Error: Config file not found!\n"); - return -1; - } - d_printf ("Reading Config-file: %s", filename); - - while (fgets (buf, sizeof (buf), config) != NULL) { - findit = strchr (buf, '\n'); - if (findit) - findit[0] = '\0'; - if (buf[0] == '\0') - continue; - - keyword = buf; - while (isspace (*keyword)) - keyword++; - - value = strchr (buf, '='); - if (value == NULL) - continue; - *value = 0; - value++; - while (*value == ' ') - value++; - while (keyword[strlen (keyword) - 1] == ' ') - keyword[strlen (keyword) - 1] = 0; - while (value[strlen (value) - 1] == ' ') - value[strlen (value) - 1] = 0; - if (strlen (value) == 0) - continue; - for (i = 0; i < (int) strlen (keyword); i++) - keyword[i] = tolower (keyword[i]); - - if (!strcmp (keyword, "playername")) { - if (strlen (value) > LEN_PLAYERNAME) { - d_printf - ("*** Error - playername too long (maximum size permitted is %d characters)!\n\n", - LEN_PLAYERNAME); - } - value[LEN_PLAYERNAME - 1] = 0; - strcpy (bman.playername, value); - } - - if (!strcmp (keyword, "gamename")) { - if (strlen (value) > LEN_GAMENAME) { - d_printf - ("*** Error - servername too long (maximum size permitted is %d characters)!\n\n", - LEN_GAMENAME); - } - value[LEN_GAMENAME - 1] = 0; - strcpy (bman.gamename, value); - } - - if (!strcmp (keyword, "askplayername")) { - bman.askplayername = atoi (value); - } - if (!strcmp (keyword, "resolutionx")) { - gfx.res.x = atoi (value); - } - if (!strcmp (keyword, "resolutiony")) { - gfx.res.y = atoi (value); - } - if (!strcmp (keyword, "fieldpath")) { - if (strlen (value) > 510) { - d_printf - ("*** Error - fieldpath too long (maximum size permitted is %d characters)!\n\n", - 510); - } - value[511] = 0; - strcpy(bman.fieldpath,value); - } - if (!strcmp (keyword, "fieldsizex")) { - bman.fieldsize.x = atoi (value); - } - if (!strcmp (keyword, "fieldsizey")) { - bman.fieldsize.y = atoi (value); - } - if (!strcmp (keyword, "fullscreen")) { - gfx.fullscreen = atoi (value); - } - if (!strcmp (keyword, "bitsperpixel")) { - gfx.bpp = atoi (value); - } - if (!strcmp (keyword, "ai_family")) { - bman.net_ai_family = atoi (value); - } - if (!strcmp (keyword, "debug")) { - debug = atoi (value); - } - if (!strcmp (keyword, "notify")) { - bman.notifygamemaster = atoi (value); - } - if (!strcmp (keyword, "masterserver")) { - strcpy (bman.gamemaster, value); - } - if (!strcmp (keyword, "maxplayer")) { - bman.maxplayer = atoi (value); - } - for (i = 0; i < MAX_SERVERENTRYS; i++) { - sprintf (key2, "ip%d", i); - if (!strcmp (keyword, key2)) { - strcpy (bman.serverlist[i].name, value); - } - } - } - fclose (config); - return 0; -} - -int -WriteConfig () -{ - FILE *config; - int i; - char filename[512]; -#ifdef _WIN32 - sprintf (filename, "%sbomberclone.cfg", s_gethomedir ()); -#else - sprintf (filename, "%s.bomberclone.cfg", s_gethomedir ()); -#endif - if ((config = fopen (filename, "w")) == NULL) - return -1; - fprintf (config, "resolutionx=%d\n", gfx.res.x); - fprintf (config, "resolutiony=%d\n", gfx.res.y); - fprintf (config, "fullscreen=%d\n", gfx.fullscreen); - fprintf (config, "fieldpath=%s\n", bman.fieldpath); - fprintf (config, "fieldsizex=%d\n", bman.fieldsize.x); - fprintf (config, "fieldsizey=%d\n", bman.fieldsize.y); - fprintf (config, "notify=%d\n", bman.notifygamemaster); - fprintf (config, "ai_family=%d\n", bman.net_ai_family); - fprintf (config, "masterserver=%s\n", bman.gamemaster); - fprintf (config, "gamename=%s\n", bman.gamename); - fprintf (config, "maxplayer=%d\n", bman.maxplayer); - for (i = 0; i < MAX_SERVERENTRYS; i++) - fprintf (config, "ip%d=%s\n", i, bman.serverlist[i].name); - fprintf (config, "debug=%d\n", debug); - fprintf (config, "askplayername=%d\n", bman.askplayername); - fprintf (config, "playername=%s\n", bman.playername); - fprintf (config, "bitsperpixel=%d\n", gfx.bpp); - - fclose (config); - return 0; -} - - - -void -change_res () -{ - int menuselect = 0; - _menu menu[] = { - {0, "Full Screen"}, - {1, "640x480"}, - {2, "800x600"}, - {3, "1024x768"}, - {4, "1280x1024"}, - {5, "BPP"}, - {6, "Return To Configuration Menu"}, - {-1, ""} - }; - while (1) { - if (gfx.fullscreen) - sprintf (menu[0].text, "Disable Fullscreen"); - else - sprintf (menu[0].text, "Enable Full Screen"); - - if (gfx.bpp == 16) - sprintf (menu[5].text, "16 Bit Per Pixel"); - else if (gfx.bpp == 24) - sprintf (menu[5].text, "24 Bit Per Pixel"); - else - sprintf (menu[5].text, "32 Bit Per Pixel"); - - menuselect = menu_loop ("Video Options", menu, menuselect); - - switch (menuselect) { - case (0): // Fullscreen - if (gfx.fullscreen) - gfx.fullscreen = 0; - else - gfx.fullscreen = 1; - break; - - case (1): // 640x480 - gfx.res.x = 640; - gfx.res.y = 480; - break; - case (2): // 800x600 - gfx.res.x = 800; - gfx.res.y = 600; - break; - case (3): // 1024x768 - gfx.res.x = 1024; - gfx.res.y = 768; - break; - case (4): // 1280x1024 - gfx.res.x = 1280; - gfx.res.y = 1024; - break; - case (5): - if (gfx.bpp == 16) - gfx.bpp = 24; - else if (gfx.bpp == 24) - gfx.bpp = 32; - else - gfx.bpp = 16; - break; - case (6): // Return - menuselect = -1; - break; - } - if (menuselect != -1) { - gfx_shutdown (); - gfx_init (); - } - else - return; - - } -}; - - - - - - -void -configuration () -{ - int menuselect = 0; - - _menu menu[] = { - {0, "Player Name:"}, - {1, "Video Options"}, - {2, "Sound Options"}, - {3, "Map Options"}, - {4, "Customize Keyboard"}, - {5, "Prompt For Player Name"}, - {6, "Debug"}, - {7, "Save Config"}, - {8, "Return To Main Manu"}, - {-1, ""} - }; - - while (menuselect != -1) { - - sprintf (menu[0].text, "Player Name: %s", bman.playername); - - if (bman.askplayername == 1) - sprintf (menu[5].text, "Prompt For Name: YES"); - else - sprintf (menu[5].text, "Prompt For Name: NO"); - - if (debug == 1) - sprintf (menu[6].text, "Debug Messages ON"); - else - sprintf (menu[6].text, "Debug Messages OFF"); - - - menuselect = menu_loop ("Configuration", menu, menuselect); - - - switch (menuselect) { - case (0): // Playername - menu_get_text ("Enter Playername", bman.playername, LEN_PLAYERNAME - 1); - bman.playername[LEN_PLAYERNAME - 1] = 0; - break; - - case (1): // Screen Options - change_res (); - break; - - case (2): // Sound Options - break; - - case (3): // Map Options - mapmenu(); - break; - - case (4): // Customize Keyboard - break; - - case (5): // Prompt For Player Name - if (bman.askplayername == 1) - bman.askplayername = 0; - else - bman.askplayername = 1; - break; - - case (6): // Debugging On / Off - if (debug == 1) - debug = 0; - else { - debug = 1; - d_printf ("BomberClone ver.%s\n", VERSION); - } - break; - - case (7): // Save Configuration - WriteConfig (); - break; - - case (8): // Return to main menu - menuselect = -1; - break; - } - } -}; - -void -ReadPrgArgs (int argc, char **argv) -{ - int i = 0; - - while (argv[++i] != NULL) { - if (!strcmp (argv[i], "-port")) - strncpy (bman.port, argv[++i], LEN_PORT); - } -}; +/* configuration */ + +#include + +#include "basic.h" +#include "bomberclone.h" +#include "network.h" +#include "packets.h" +#include "gfx.h" +#include "chat.h" + +void +game_init () +{ + int i; + + srand (((int) time (NULL))); // initialize randomgenerator + + // do some init stuff + for (i = 0; i < MAX_SERVERENTRYS; i++) + bman.serverlist[i].name[0] = 0; + + for (i = 0; i < MAX_PLAYERS; i++) { + bman.players[i].gfx = NULL; /* we will select them in the wait_for_players loop */ + bman.players[i].gfx_nr = -1; /* and even now in the singleplayer menu */ + } + + chat.visible = 0; + chat.startline = 0; + for (i = 0; i < CHAT_MAX_LINES; i++) + chat.lines[i][0] = 0; + + bman.maxplayer = MAX_PLAYERS; + bman.net_ai_family = PF_INET; + bman.sock = -1; + bman.gamename[0] = 0; + sprintf (bman.port, "%d", DEFAULT_UDPPORT); + sprintf (bman.gamemaster, DEFAULT_GAMEMASTER); + resend_cache.data = NULL; + resend_cache.fill = -1; + bman.notifygamemaster = 1; + bman.askplayername = 1; + debug = 0; + gfx.res.x = 640; + gfx.res.y = 480; + gfx.bpp = 16; + gfx.tileset[0] = 0; + gfx.random_tileset = 1; + bman.fieldsize.x = 25; + bman.fieldsize.y = 17; + sprintf (bman.datapath, "data"); + bman.fieldpath[0] = 0; + bman.random_map = 1; + init_map_tileset(); +}; + +int +ReadConfig () +{ + FILE *config; + char buf[1024], + key2[1024]; + char *findit, + *keyword, + *value; + int i; + char filename[512]; + +#ifdef _WIN32 + sprintf (filename, "%sbomberclone.cfg", s_gethomedir ()); +#else + sprintf (filename, "%s.bomberclone.cfg", s_gethomedir ()); +#endif + + config = fopen (filename, "r"); + if (config == NULL) { + d_printf ("Error: Config file not found!\n"); + return -1; + } + d_printf ("Reading Config-file: %s", filename); + + while (fgets (buf, sizeof (buf), config) != NULL) { + findit = strchr (buf, '\n'); + if (findit) + findit[0] = '\0'; + if (buf[0] == '\0') + continue; + + keyword = buf; + while (isspace (*keyword)) + keyword++; + + value = strchr (buf, '='); + if (value == NULL) + continue; + *value = 0; + value++; + while (*value == ' ') + value++; + while (keyword[strlen (keyword) - 1] == ' ') + keyword[strlen (keyword) - 1] = 0; + while (value[strlen (value) - 1] == ' ') + value[strlen (value) - 1] = 0; + if (strlen (value) == 0) + continue; + for (i = 0; i < (int) strlen (keyword); i++) + keyword[i] = tolower (keyword[i]); + + if (!strcmp (keyword, "playername")) { + if (strlen (value) > LEN_PLAYERNAME) { + d_printf + ("*** Error - playername too long (maximum size permitted is %d characters)!\n\n", + LEN_PLAYERNAME); + } + value[LEN_PLAYERNAME - 1] = 0; + strcpy (bman.playername, value); + } + + if (!strcmp (keyword, "gamename")) { + if (strlen (value) > LEN_GAMENAME) { + d_printf + ("*** Error - servername too long (maximum size permitted is %d characters)!\n\n", + LEN_GAMENAME); + } + value[LEN_GAMENAME - 1] = 0; + strcpy (bman.gamename, value); + } + + if (!strcmp (keyword, "askplayername")) { + bman.askplayername = atoi (value); + } + if (!strcmp (keyword, "resolutionx")) { + gfx.res.x = atoi (value); + } + if (!strcmp (keyword, "resolutiony")) { + gfx.res.y = atoi (value); + } + if (!strcmp (keyword, "fieldpath")) { + if (strlen (value) > 510) { + d_printf + ("*** Error - fieldpath too long (maximum size permitted is %d characters)!\n\n", + 510); + } + value[511] = 0; + strcpy(bman.fieldpath,value); + } + if (!strcmp (keyword, "fieldsizex")) { + bman.fieldsize.x = atoi (value); + } + if (!strcmp (keyword, "fieldsizey")) { + bman.fieldsize.y = atoi (value); + } + if (!strcmp (keyword, "fullscreen")) { + gfx.fullscreen = atoi (value); + } + if (!strcmp (keyword, "bitsperpixel")) { + gfx.bpp = atoi (value); + } + if (!strcmp (keyword, "ai_family")) { + bman.net_ai_family = atoi (value); + } + if (!strcmp (keyword, "debug")) { + debug = atoi (value); + } + if (!strcmp (keyword, "notify")) { + bman.notifygamemaster = atoi (value); + } + if (!strcmp (keyword, "masterserver")) { + strcpy (bman.gamemaster, value); + } + if (!strcmp (keyword, "maxplayer")) { + bman.maxplayer = atoi (value); + } + for (i = 0; i < MAX_SERVERENTRYS; i++) { + sprintf (key2, "ip%d", i); + if (!strcmp (keyword, key2)) { + strcpy (bman.serverlist[i].name, value); + } + } + } + fclose (config); + return 0; +} + +int +WriteConfig () +{ + FILE *config; + int i; + char filename[512]; +#ifdef _WIN32 + sprintf (filename, "%sbomberclone.cfg", s_gethomedir ()); +#else + sprintf (filename, "%s.bomberclone.cfg", s_gethomedir ()); +#endif + if ((config = fopen (filename, "w")) == NULL) + return -1; + fprintf (config, "resolutionx=%d\n", gfx.res.x); + fprintf (config, "resolutiony=%d\n", gfx.res.y); + fprintf (config, "fullscreen=%d\n", gfx.fullscreen); + fprintf (config, "fieldpath=%s\n", bman.fieldpath); + fprintf (config, "fieldsizex=%d\n", bman.fieldsize.x); + fprintf (config, "fieldsizey=%d\n", bman.fieldsize.y); + fprintf (config, "notify=%d\n", bman.notifygamemaster); + fprintf (config, "ai_family=%d\n", bman.net_ai_family); + fprintf (config, "masterserver=%s\n", bman.gamemaster); + fprintf (config, "gamename=%s\n", bman.gamename); + fprintf (config, "maxplayer=%d\n", bman.maxplayer); + for (i = 0; i < MAX_SERVERENTRYS; i++) + fprintf (config, "ip%d=%s\n", i, bman.serverlist[i].name); + fprintf (config, "debug=%d\n", debug); + fprintf (config, "askplayername=%d\n", bman.askplayername); + fprintf (config, "playername=%s\n", bman.playername); + fprintf (config, "bitsperpixel=%d\n", gfx.bpp); + + fclose (config); + return 0; +} + + + +void +change_res () +{ + int menuselect = 0; + _menu menu[] = { + {0, "Full Screen"}, + {1, "640x480"}, + {2, "800x600"}, + {3, "1024x768"}, + {4, "1280x1024"}, + {5, "BPP"}, + {6, "Return To Configuration Menu"}, + {-1, ""} + }; + while (1) { + if (gfx.fullscreen) + sprintf (menu[0].text, "Disable Fullscreen"); + else + sprintf (menu[0].text, "Enable Full Screen"); + + if (gfx.bpp == 16) + sprintf (menu[5].text, "16 Bit Per Pixel"); + else if (gfx.bpp == 24) + sprintf (menu[5].text, "24 Bit Per Pixel"); + else + sprintf (menu[5].text, "32 Bit Per Pixel"); + + menuselect = menu_loop ("Video Options", menu, menuselect); + + switch (menuselect) { + case (0): // Fullscreen + if (gfx.fullscreen) + gfx.fullscreen = 0; + else + gfx.fullscreen = 1; + break; + + case (1): // 640x480 + gfx.res.x = 640; + gfx.res.y = 480; + break; + case (2): // 800x600 + gfx.res.x = 800; + gfx.res.y = 600; + break; + case (3): // 1024x768 + gfx.res.x = 1024; + gfx.res.y = 768; + break; + case (4): // 1280x1024 + gfx.res.x = 1280; + gfx.res.y = 1024; + break; + case (5): + if (gfx.bpp == 16) + gfx.bpp = 24; + else if (gfx.bpp == 24) + gfx.bpp = 32; + else + gfx.bpp = 16; + break; + case (6): // Return + menuselect = -1; + break; + } + if (menuselect != -1) { + gfx_shutdown (); + gfx_init (); + } + else + return; + + } +}; + + + + + + +void +configuration () +{ + int menuselect = 0; + + _menu menu[] = { + {0, "Player Name:"}, + {1, "Video Options"}, + {2, "Sound Options"}, + {3, "Map Options"}, + {4, "Customize Keyboard"}, + {5, "Prompt For Player Name"}, + {6, "Debug"}, + {7, "Save Config"}, + {8, "Return To Main Manu"}, + {-1, ""} + }; + + while (menuselect != -1) { + + sprintf (menu[0].text, "Player Name: %s", bman.playername); + + if (bman.askplayername == 1) + sprintf (menu[5].text, "Prompt For Name: YES"); + else + sprintf (menu[5].text, "Prompt For Name: NO"); + + if (debug == 1) + sprintf (menu[6].text, "Debug Messages ON"); + else + sprintf (menu[6].text, "Debug Messages OFF"); + + + menuselect = menu_loop ("Configuration", menu, menuselect); + + + switch (menuselect) { + case (0): // Playername + menu_get_text ("Enter Playername", bman.playername, LEN_PLAYERNAME - 1); + bman.playername[LEN_PLAYERNAME - 1] = 0; + break; + + case (1): // Screen Options + change_res (); + break; + + case (2): // Sound Options + break; + + case (3): // Map Options + mapmenu(); + break; + + case (4): // Customize Keyboard + break; + + case (5): // Prompt For Player Name + if (bman.askplayername == 1) + bman.askplayername = 0; + else + bman.askplayername = 1; + break; + + case (6): // Debugging On / Off + if (debug == 1) + debug = 0; + else { + debug = 1; + d_printf ("BomberClone ver.%s\n", VERSION); + } + break; + + case (7): // Save Configuration + WriteConfig (); + break; + + case (8): // Return to main menu + menuselect = -1; + break; + } + } +}; + +void +ReadPrgArgs (int argc, char **argv) +{ + int i = 0; + + while (argv[++i] != NULL) { + if (!strcmp (argv[i], "-port")) + strncpy (bman.port, argv[++i], LEN_PORT); + } +}; diff --git a/src/debug.c b/src/debug.c index a155708..379462c 100644 --- a/src/debug.c +++ b/src/debug.c @@ -1,39 +1,39 @@ - -#include "bomberclone.h" -#include "network.h" -#include "packets.h" - -int debug; - -void d_gamedetail (char *head) { - d_playerdetail (head); - - d_printf ("bman.players_nr = %d\n", bman.players_nr); - d_printf ("bman.players_nr_s = %d\n", bman.players_nr_s); - d_printf ("bman.gametype = %d\n", bman.gametype); - d_printf ("bman.multitype = %d\n", bman.multitype); - d_printf ("bman.state = %d\n", bman.state); -}; - - -void d_printf (char *fmt,...) { - va_list args; - - if (debug == 0) - return; - - va_start (args, fmt); - fprintf (stdout, "[%8d] :", timestamp); - vfprintf (stdout, fmt, args); - va_end (args); -}; - - -void d_playerdetail (char *head) { - int i; - - d_printf ("---------------> %s\n", head); - d_printf ("Nr Name GFX Sta Pkt Win [Addr]\n"); - for (i = 0; i < MAX_PLAYERS; i++) - d_printf ("%2d %16s %3d %3d %3d %3d [%s:%s]\n",i, bman.players[i].name, bman.players[i].gfx_nr, bman.players[i].state, bman.players[i].points, bman.players[i].wins, bman.players[i].net.addr.host, bman.players[i].net.addr.port); -}; + +#include "bomberclone.h" +#include "network.h" +#include "packets.h" + +int debug; + +void d_gamedetail (char *head) { + d_playerdetail (head); + + d_printf ("bman.players_nr = %d\n", bman.players_nr); + d_printf ("bman.players_nr_s = %d\n", bman.players_nr_s); + d_printf ("bman.gametype = %d\n", bman.gametype); + d_printf ("bman.multitype = %d\n", bman.multitype); + d_printf ("bman.state = %d\n", bman.state); +}; + + +void d_printf (char *fmt,...) { + va_list args; + + if (debug == 0) + return; + + va_start (args, fmt); + fprintf (stdout, "[%8d] :", timestamp); + vfprintf (stdout, fmt, args); + va_end (args); +}; + + +void d_playerdetail (char *head) { + int i; + + d_printf ("---------------> %s\n", head); + d_printf ("Nr Name GFX Sta Pkt Win [Addr]\n"); + for (i = 0; i < MAX_PLAYERS; i++) + d_printf ("%2d %16s %3d %3d %3d %3d [%s:%s]\n",i, bman.players[i].name, bman.players[i].gfx_nr, bman.players[i].state, bman.players[i].points, bman.players[i].wins, bman.players[i].net.addr.host, bman.players[i].net.addr.port); +}; diff --git a/src/field.c b/src/field.c index eaedf27..f565fff 100644 --- a/src/field.c +++ b/src/field.c @@ -1,384 +1,393 @@ -/* $Id: field.c,v 1.14 2003/05/07 21:28:12 stpohle Exp $ */ -/* field.c - procedures which are needed to control the field */ - -#include -#include - -#include "bomberclone.h" -#include "gfx.h" - -void -draw_stone (int x, int y) -{ - _field *stone = &bman.field[x][y]; - SDL_Rect dest, - src; - SDL_Surface *srcimg; - int i, - d; - - src.w = dest.w = gfx.block.x; - src.h = dest.h = gfx.block.y; - - dest.x = x * gfx.block.x + gfx.offset.x; - dest.y = y * gfx.block.y + gfx.offset.y; - - src.x = 0; - - if (stone->frame == 0 || stone->type != FT_stone) { - srcimg = gfx.field[stone->type].image; - src.y = 0; - } - else { - if (stone->frameto == 0) { - if (stone->frame < gfx.field[stone->type].frames) { - stone->frame++; - stone->frameto = ANI_STONETIMEOUT; - } - } - if (stone->frameto > 0) - stone->frameto--; - if (stone->frame < gfx.field[stone->type].frames) { - src.y = stone->frame * gfx.block.y; - srcimg = gfx.field[stone->type].image; - } - else { - src.y = 0; - srcimg = gfx.field[FT_nothing].image; - } - - } - - if (stone->frame > 0) - SDL_BlitSurface (gfx.field[FT_nothing].image, NULL, gfx.screen, &dest); - - SDL_BlitSurface (srcimg, &src, gfx.screen, &dest); - - // draw explosions if there is any - for (d = 0, i = 0; d < 4; d++) - if (stone->ex[d].count > 0) { - i = 1; // mark that there is already an explosion - draw_fire (x, y, d, -1); - } - - if (i == 0) // we don't have to do this anymore because this was happend in draw_fire - gfx_AddUpdateRect (dest.x, dest.y, dest.w, dest.h); - - return; -}; - - -void -draw_field () -{ - int x, - y; - - for (x = 0; x < bman.fieldsize.x; x++) - for (y = 0; y < bman.fieldsize.y; y++) - draw_stone (x, y); -}; - -/* read from an open file map, determine field.x and field.y - and fill the field. - (# correspond to a bloc and @ correspond to a stone, - an espace is nothing ' ' - % are commentary at the beginning of the map */ -void -field_load (FILE * map) -{ - size_t length; - char *currentline; - char tmp[MAX_FIELDSIZE_X]; - int sizex = 0; - int sizey = 0; - int i; - int d; - - while ((currentline = fgets (tmp, MAX_FIELDSIZE_X, map))) { - length = strlen (currentline); - if (currentline[0] == '%') - continue; - /* now each line correspond to the field */ - else { - for (i = 0; i < length; i++) { - switch (currentline[i]) { - case '#': - bman.field[i][sizey].type = FT_block; - break; - case '@': - bman.field[i][sizey].type = FT_stone; - break; - case ' ': - bman.field[i][sizey].type = FT_nothing; - default: - break; - } - for (d = 0; d < 4; d++) - bman.field[i][sizey].ex[d].frame = bman.field[i][sizey].ex[d].count = 0; - bman.field[i][sizey].ex_nr = -1; - bman.field[i][sizey].frame = 0; - bman.field[i][sizey].frameto = 0; - bman.field[i][sizey].special = FT_nothing; - } - sizey++; - if (sizex < length) - sizex = length; - } - } - - bman.fieldsize.x = sizex - 1; - bman.fieldsize.y = sizey; - - /* darw the border so we know everything is right */ - for (i = 0; i < bman.fieldsize.x; i++) - bman.field[i][0].type = bman.field[i][bman.fieldsize.y-1].type = FT_block; - for (i = 0; i < bman.fieldsize.y; i++) - bman.field[0][i].type = bman.field[bman.fieldsize.x-1][i].type = FT_block; -} - -/* will set the playerposition but in a way that we won't start on a block */ -/* i am just too lazy to write this all again and again */ -#define PLX bman.players[i].pos.x -#define PLY bman.players[i].pos.y -void field_set_playerposition (int usermap) { - int p, dist, i,j , mx, my, dx = 0, dy = 0; - char txt[255]; - - p = 50; - dist = 8; - while (p == 50) { - p = 0; - dist--; - for (i = 0; (p < 50 && i < MAX_PLAYERS);) { - if (usermap) { - int maxloop = 0; - while (maxloop < 200 && (PLX == -1 || PLY == -1)) { - maxloop++; - PLX = s_random (bman.fieldsize.x - 2) + 1; - PLY = s_random (bman.fieldsize.y - 2) + 1; - - for (dx = 10, dy = 10, j = 0; (j < i && j < MAX_PLAYERS && (dx > 1 || dy > 1)); j++) { /* is ther any other player */ - dx = PLX - bman.players[j].pos.x; - if (dx < 0) dx = - dx; - dy = PLY - bman.players[j].pos.y; - if (dy < 0) dy = - dy; - } - - /* check if there is no block */ - if ((dx > 1 || dy > 1) && ((bman.field[PLX][PLY].type != FT_block && maxloop > 100) || - bman.field[PLX][PLY].type == FT_nothing)) { - /* get (up or down) dx and (left or right) dy */ - dx = s_random (2); - if (dx == 0) - dx = -1; - dy = s_random (2); - if (dy == 0) - dy = -1; - - /* first check if there is and free place for us */ - if (!((bman.field[PLX+dx][PLY].type != FT_block && maxloop > 100) || - bman.field[PLX+dx][PLY].type == FT_nothing)) - dx = -dx; - if (!((bman.field[PLX+dx][PLY].type != FT_block && maxloop > 100) || - bman.field[PLX+dx][PLY].type == FT_nothing)) - PLX = -1; - - if (!((bman.field[PLX][PLY+dy].type != FT_block && maxloop > 100) || - bman.field[PLX][PLY+dy].type == FT_nothing)) - dy = -dy; - if (!((bman.field[PLX][PLY+dy].type != FT_block && maxloop > 100) || - bman.field[PLX][PLY+dy].type == FT_nothing)) - PLY = -1; - } - else { - PLX = -1; - PLY = -1; - } - - /* make some space */ - if (PLX != -1 && PLY != -1) { - bman.field[PLX][PLY].type = FT_nothing; - bman.field[PLX+dx][PLY].type = FT_nothing; - bman.field[PLX][PLY+dy].type = FT_nothing; - } - } - } - if (PLX == -1 || PLY == -1) { - /* we could not set all fields or we don't run on a usermap */ - if (usermap) { - sprintf (txt,"Not all players could be set (Pl:%d)", i); - menu_displaymessage ("MAP - ERROR",txt); - } - - /* now there will be some fields deleted */ - PLX = 2 * (s_random ((bman.fieldsize.x - 1) / 2)) + 1; - PLY = 2 * (s_random ((bman.fieldsize.y - 1) / 2)) + 1; - - bman.field[PLX][PLY].type = FT_nothing; - - dx = s_random (4); // bit 1 = up/down bit 2 = left/right - /* up and down */ - if (((dx & 1) == 0 && PLX > 1) || PLX >= bman.fieldsize.x - 2) - bman.field[PLX-1][PLY].type = FT_nothing; - else - bman.field[PLX+1][PLY].type = FT_nothing; - /* left and right */ - if (((dx & 2) == 0 && PLY > 1) || PLY >= bman.fieldsize.y - 2) - bman.field[PLX][PLY-1].type = FT_nothing; - else - bman.field[PLX][PLY+1].type = FT_nothing; - } - mx = my = 100; - for (j = 0; j <= i; j++) { /* search smalest distance */ - dy = PLY - bman.players[j].pos.y; - dx = PLX - bman.players[j].pos.x; - if (dy < 0) - dy = -dy; - if (dx < 0) - dx = -dx; - - if (mx > dx && i != j) - mx = dx; - if (my > dy && i != j) - my = dy; - } - - if (mx > dist || my > dist) - i++; - else - p++; - } - } - - for (i = 0; i < MAX_PLAYERS; i++) { - PLX = PLX << 8; - PLY = PLY << 8; - } -}; -#undef PLX -#undef PLY - - -void -field_new (char *filename) -{ - int x, - y, - d; - FILE *fmap; - float fkt; - int nb_try; - - if(filename) - { - fmap = fopen (filename, "r"); - - /* if we can't open the given filename for any reason, reverting - to default value else, load the file */ - if (fmap) - field_load (fmap); - } - else - { - fmap = NULL; - } - - /* this is the item factor we multiply it with this so we know - how much items we want in the game */ - fkt = ((float)(bman.fieldsize.x * bman.fieldsize.y))/(25.0 * 17.0); - - // Clean and create the field // - if (fmap == NULL) { - /* if we can't load the map check first the fieldsize settings */ - if (bman.fieldsize.x < MIN_FIELDSIZE_X) - bman.fieldsize.x = MIN_FIELDSIZE_X; - if (bman.fieldsize.x > MAX_FIELDSIZE_X) - bman.fieldsize.x = MAX_FIELDSIZE_X; - - for (x = 0; x < bman.fieldsize.x; x++) - for (y = 0; y < bman.fieldsize.y; y++) { - if ((y == 0) || (y == bman.fieldsize.y - 1)) - bman.field[x][y].type = FT_block; - else if ((x == 0) || (x == bman.fieldsize.x - 1)) - bman.field[x][y].type = FT_block; - else if (((x & 1) == 0) && ((y & 1) == 0)) - bman.field[x][y].type = FT_block; - else { - // create random field - if ((s_random (256) & 3) == 0) - bman.field[x][y].type = FT_nothing; - else - bman.field[x][y].type = FT_stone; - } - - for (d = 0; d < 4; d++) - bman.field[x][y].ex[d].frame = bman.field[x][y].ex[d].count = 0; - bman.field[x][y].ex_nr = -1; - bman.field[x][y].frame = 0; - bman.field[x][y].frameto = 0; - bman.field[x][y].special = FT_nothing; - } - } - - /* Set the Playerinformation */ - field_set_playerposition (fmap != NULL); - - nb_try = 100; // to prevent infinite loops (maybe there are no stones) - /* put the fire powerups in the field */ - for (d = 0, x = 0, y = 0; d < GAME_SPECIAL_ITEMFIRE * fkt; d++) { - while (bman.field[x][y].type != FT_stone || bman.field[x][y].special != FT_nothing) { - x = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.x - 1); - y = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.y - 1); - nb_try--; - if (nb_try < 0) - break; - } - bman.field[x][y].special = FT_fire; - x = y = 0; - } - - nb_try = 100; - /* put the bomb powerups in the field */ - for (d = 0, x = 0, y = 0; d < GAME_SPECIAL_ITEMBOMB * fkt; d++) { - while (bman.field[x][y].type != FT_stone || bman.field[x][y].special != FT_nothing) { - x = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.x - 1); - y = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.y - 1); - nb_try--; - if (nb_try < 0) - break; - } - bman.field[x][y].special = FT_bomb; - x = y = 0; - } - - nb_try = 100; - /* put the shoe powerup in the field */ - for (d = 0, x = 0, y = 0; d < GAME_SPECIAL_ITEMSHOE * fkt; d++) { - while (bman.field[x][y].type != FT_stone || bman.field[x][y].special != FT_nothing) { - x = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.x - 1); - y = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.y - 1); - nb_try--; - if (nb_try < 0) - break; - } - bman.field[x][y].special = FT_shoe; - x = y = 0; - } - - nb_try = 100; - /* put the death ?powerups? in the field */ - for (d = 0, x = 0, y = 0; d < GAME_SPECIAL_ITEMDEATH * fkt; d++) { - while (bman.field[x][y].type != FT_stone || bman.field[x][y].special != FT_nothing) { - x = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.x - 1); - y = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.y - 1); - nb_try--; - if (nb_try < 0) - break; - } - bman.field[x][y].special = FT_death; - x = y = 0; - } -} - - +/* $Id: field.c,v 1.15 2003/05/08 14:35:49 stpohle Exp $ */ +/* field.c - procedures which are needed to control the field */ + +#include +#include + +#include "bomberclone.h" +#include "gfx.h" + +void +draw_stone (int x, int y) +{ + _field *stone = &bman.field[x][y]; + SDL_Rect dest, + src; + SDL_Surface *srcimg; + int i, + d; + + src.w = dest.w = gfx.block.x; + src.h = dest.h = gfx.block.y; + + dest.x = x * gfx.block.x + gfx.offset.x; + dest.y = y * gfx.block.y + gfx.offset.y; + + src.x = 0; + + if (stone->frame == 0 || stone->type != FT_stone) { + srcimg = gfx.field[stone->type].image; + src.y = 0; + } + else { + if (stone->frameto == 0) { + if (stone->frame < gfx.field[stone->type].frames) { + stone->frame++; + stone->frameto = ANI_STONETIMEOUT; + } + } + if (stone->frameto > 0) + stone->frameto--; + if (stone->frame < gfx.field[stone->type].frames) { + src.y = stone->frame * gfx.block.y; + srcimg = gfx.field[stone->type].image; + } + else { + src.y = 0; + srcimg = gfx.field[FT_nothing].image; + } + + } + + if (stone->frame > 0 || stone->type == FT_nothing) { + SDL_Rect srcbg; + + srcbg.w = dest.w; + srcbg.h = dest.h; + srcbg.x = (x % gfx.field[FT_nothing].frames) * gfx.block.x; + srcbg.y = (y % gfx.field[FT_nothing].frames) * gfx.block.y; + + SDL_BlitSurface (gfx.field[FT_nothing].image, &srcbg, gfx.screen, &dest); + } + + if (stone->type != FT_nothing) + SDL_BlitSurface (srcimg, &src, gfx.screen, &dest); + + // draw explosions if there is any + for (d = 0, i = 0; d < 4; d++) + if (stone->ex[d].count > 0) { + i = 1; // mark that there is already an explosion + draw_fire (x, y, d, -1); + } + + if (i == 0) // we don't have to do this anymore because this was happend in draw_fire + gfx_AddUpdateRect (dest.x, dest.y, dest.w, dest.h); + + return; +}; + + +void +draw_field () +{ + int x, + y; + + for (x = 0; x < bman.fieldsize.x; x++) + for (y = 0; y < bman.fieldsize.y; y++) + draw_stone (x, y); +}; + +/* read from an open file map, determine field.x and field.y + and fill the field. + (# correspond to a bloc and @ correspond to a stone, + an espace is nothing ' ' + % are commentary at the beginning of the map */ +void +field_load (FILE * map) +{ + size_t length; + char *currentline; + char tmp[MAX_FIELDSIZE_X]; + int sizex = 0; + int sizey = 0; + int i; + int d; + + while ((currentline = fgets (tmp, MAX_FIELDSIZE_X, map))) { + length = strlen (currentline); + if (currentline[0] == '%') + continue; + /* now each line correspond to the field */ + else { + for (i = 0; i < length; i++) { + switch (currentline[i]) { + case '#': + bman.field[i][sizey].type = FT_block; + break; + case '@': + bman.field[i][sizey].type = FT_stone; + break; + case ' ': + bman.field[i][sizey].type = FT_nothing; + default: + break; + } + for (d = 0; d < 4; d++) + bman.field[i][sizey].ex[d].frame = bman.field[i][sizey].ex[d].count = 0; + bman.field[i][sizey].ex_nr = -1; + bman.field[i][sizey].frame = 0; + bman.field[i][sizey].frameto = 0; + bman.field[i][sizey].special = FT_nothing; + } + sizey++; + if (sizex < length) + sizex = length; + } + } + + bman.fieldsize.x = sizex - 1; + bman.fieldsize.y = sizey; + + /* darw the border so we know everything is right */ + for (i = 0; i < bman.fieldsize.x; i++) + bman.field[i][0].type = bman.field[i][bman.fieldsize.y-1].type = FT_block; + for (i = 0; i < bman.fieldsize.y; i++) + bman.field[0][i].type = bman.field[bman.fieldsize.x-1][i].type = FT_block; +} + +/* will set the playerposition but in a way that we won't start on a block */ +/* i am just too lazy to write this all again and again */ +#define PLX bman.players[i].pos.x +#define PLY bman.players[i].pos.y +void field_set_playerposition (int usermap) { + int p, dist, i,j , mx, my, dx = 0, dy = 0; + char txt[255]; + + p = 50; + dist = 8; + while (p == 50) { + p = 0; + dist--; + for (i = 0; (p < 50 && i < MAX_PLAYERS);) { + if (usermap) { + int maxloop = 0; + while (maxloop < 200 && (PLX == -1 || PLY == -1)) { + maxloop++; + PLX = s_random (bman.fieldsize.x - 2) + 1; + PLY = s_random (bman.fieldsize.y - 2) + 1; + + for (dx = 10, dy = 10, j = 0; (j < i && j < MAX_PLAYERS && (dx > 1 || dy > 1)); j++) { /* is ther any other player */ + dx = PLX - bman.players[j].pos.x; + if (dx < 0) dx = - dx; + dy = PLY - bman.players[j].pos.y; + if (dy < 0) dy = - dy; + } + + /* check if there is no block */ + if ((dx > 1 || dy > 1) && ((bman.field[PLX][PLY].type != FT_block && maxloop > 100) || + bman.field[PLX][PLY].type == FT_nothing)) { + /* get (up or down) dx and (left or right) dy */ + dx = s_random (2); + if (dx == 0) + dx = -1; + dy = s_random (2); + if (dy == 0) + dy = -1; + + /* first check if there is and free place for us */ + if (!((bman.field[PLX+dx][PLY].type != FT_block && maxloop > 100) || + bman.field[PLX+dx][PLY].type == FT_nothing)) + dx = -dx; + if (!((bman.field[PLX+dx][PLY].type != FT_block && maxloop > 100) || + bman.field[PLX+dx][PLY].type == FT_nothing)) + PLX = -1; + + if (!((bman.field[PLX][PLY+dy].type != FT_block && maxloop > 100) || + bman.field[PLX][PLY+dy].type == FT_nothing)) + dy = -dy; + if (!((bman.field[PLX][PLY+dy].type != FT_block && maxloop > 100) || + bman.field[PLX][PLY+dy].type == FT_nothing)) + PLY = -1; + } + else { + PLX = -1; + PLY = -1; + } + + /* make some space */ + if (PLX != -1 && PLY != -1) { + bman.field[PLX][PLY].type = FT_nothing; + bman.field[PLX+dx][PLY].type = FT_nothing; + bman.field[PLX][PLY+dy].type = FT_nothing; + } + } + } + if (PLX == -1 || PLY == -1) { + /* we could not set all fields or we don't run on a usermap */ + if (usermap) { + sprintf (txt,"Not all players could be set (Pl:%d)", i); + menu_displaymessage ("MAP - ERROR",txt); + } + + /* now there will be some fields deleted */ + PLX = 2 * (s_random ((bman.fieldsize.x - 1) / 2)) + 1; + PLY = 2 * (s_random ((bman.fieldsize.y - 1) / 2)) + 1; + + bman.field[PLX][PLY].type = FT_nothing; + + dx = s_random (4); // bit 1 = up/down bit 2 = left/right + /* up and down */ + if (((dx & 1) == 0 && PLX > 1) || PLX >= bman.fieldsize.x - 2) + bman.field[PLX-1][PLY].type = FT_nothing; + else + bman.field[PLX+1][PLY].type = FT_nothing; + /* left and right */ + if (((dx & 2) == 0 && PLY > 1) || PLY >= bman.fieldsize.y - 2) + bman.field[PLX][PLY-1].type = FT_nothing; + else + bman.field[PLX][PLY+1].type = FT_nothing; + } + mx = my = 100; + for (j = 0; j <= i; j++) { /* search smalest distance */ + dy = PLY - bman.players[j].pos.y; + dx = PLX - bman.players[j].pos.x; + if (dy < 0) + dy = -dy; + if (dx < 0) + dx = -dx; + + if (mx > dx && i != j) + mx = dx; + if (my > dy && i != j) + my = dy; + } + + if (mx > dist || my > dist) + i++; + else + p++; + } + } + + for (i = 0; i < MAX_PLAYERS; i++) { + PLX = PLX << 8; + PLY = PLY << 8; + } +}; +#undef PLX +#undef PLY + + +void +field_new (char *filename) +{ + int x, + y, + d; + FILE *fmap; + float fkt; + int nb_try; + + if(filename) + { + fmap = fopen (filename, "r"); + + /* if we can't open the given filename for any reason, reverting + to default value else, load the file */ + if (fmap) + field_load (fmap); + } + else + { + fmap = NULL; + } + + /* this is the item factor we multiply it with this so we know + how much items we want in the game */ + fkt = ((float)(bman.fieldsize.x * bman.fieldsize.y))/(25.0 * 17.0); + + // Clean and create the field // + if (fmap == NULL) { + /* if we can't load the map check first the fieldsize settings */ + if (bman.fieldsize.x < MIN_FIELDSIZE_X) + bman.fieldsize.x = MIN_FIELDSIZE_X; + if (bman.fieldsize.x > MAX_FIELDSIZE_X) + bman.fieldsize.x = MAX_FIELDSIZE_X; + + for (x = 0; x < bman.fieldsize.x; x++) + for (y = 0; y < bman.fieldsize.y; y++) { + if ((y == 0) || (y == bman.fieldsize.y - 1)) + bman.field[x][y].type = FT_block; + else if ((x == 0) || (x == bman.fieldsize.x - 1)) + bman.field[x][y].type = FT_block; + else if (((x & 1) == 0) && ((y & 1) == 0)) + bman.field[x][y].type = FT_block; + else { + // create random field + if ((s_random (256) & 3) == 0) + bman.field[x][y].type = FT_nothing; + else + bman.field[x][y].type = FT_stone; + } + + for (d = 0; d < 4; d++) + bman.field[x][y].ex[d].frame = bman.field[x][y].ex[d].count = 0; + bman.field[x][y].ex_nr = -1; + bman.field[x][y].frame = 0; + bman.field[x][y].frameto = 0; + bman.field[x][y].special = FT_nothing; + } + } + + /* Set the Playerinformation */ + field_set_playerposition (fmap != NULL); + + nb_try = 100; // to prevent infinite loops (maybe there are no stones) + /* put the fire powerups in the field */ + for (d = 0, x = 0, y = 0; d < GAME_SPECIAL_ITEMFIRE * fkt; d++) { + while (bman.field[x][y].type != FT_stone || bman.field[x][y].special != FT_nothing) { + x = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.x - 1); + y = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.y - 1); + nb_try--; + if (nb_try < 0) + break; + } + bman.field[x][y].special = FT_fire; + x = y = 0; + } + + nb_try = 100; + /* put the bomb powerups in the field */ + for (d = 0, x = 0, y = 0; d < GAME_SPECIAL_ITEMBOMB * fkt; d++) { + while (bman.field[x][y].type != FT_stone || bman.field[x][y].special != FT_nothing) { + x = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.x - 1); + y = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.y - 1); + nb_try--; + if (nb_try < 0) + break; + } + bman.field[x][y].special = FT_bomb; + x = y = 0; + } + + nb_try = 100; + /* put the shoe powerup in the field */ + for (d = 0, x = 0, y = 0; d < GAME_SPECIAL_ITEMSHOE * fkt; d++) { + while (bman.field[x][y].type != FT_stone || bman.field[x][y].special != FT_nothing) { + x = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.x - 1); + y = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.y - 1); + nb_try--; + if (nb_try < 0) + break; + } + bman.field[x][y].special = FT_shoe; + x = y = 0; + } + + nb_try = 100; + /* put the death ?powerups? in the field */ + for (d = 0, x = 0, y = 0; d < GAME_SPECIAL_ITEMDEATH * fkt; d++) { + while (bman.field[x][y].type != FT_stone || bman.field[x][y].special != FT_nothing) { + x = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.x - 1); + y = ((float) rand () / (float) RAND_MAX) * (bman.fieldsize.y - 1); + nb_try--; + if (nb_try < 0) + break; + } + bman.field[x][y].special = FT_death; + x = y = 0; + } +} + + diff --git a/src/font.c b/src/font.c index 23c4bc5..ea091fd 100644 --- a/src/font.c +++ b/src/font.c @@ -1,36 +1,36 @@ -// Using Fonts in SDL - -#include -#include - -#include "bomberclone.h" -#include "gfx.h" - -void -draw_text (int x, int y, char *text, int white) -{ - int i, - c; - SDL_Rect src, - dest; - - src.y = 0; - dest.w = src.w = gfx.font.size.x; - dest.h = src.h = gfx.font.size.y; - dest.x = x; - dest.y = y; - - for (i = 0; text[i] != 0; i++) { - c = text[i]; - src.x = gfx.font.size.x * (c & 15); - src.y = gfx.font.size.y * ((c & 240) >> 4); - if (white) - SDL_BlitSurface (gfx.font.image, &src, gfx.screen, &dest); - else - SDL_BlitSurface (gfx.font1.image, &src, gfx.screen, &dest); - dest.x += gfx.font.size.x-4; - } - - gfx_AddUpdateRect (x, y, dest.x - x, dest.h); -}; - +// Using Fonts in SDL + +#include +#include + +#include "bomberclone.h" +#include "gfx.h" + +void +draw_text (int x, int y, char *text, int white) +{ + int i, + c; + SDL_Rect src, + dest; + + src.y = 0; + dest.w = src.w = gfx.font.size.x; + dest.h = src.h = gfx.font.size.y; + dest.x = x; + dest.y = y; + + for (i = 0; text[i] != 0; i++) { + c = text[i]; + src.x = gfx.font.size.x * (c & 15); + src.y = gfx.font.size.y * ((c & 240) >> 4); + if (white) + SDL_BlitSurface (gfx.font.image, &src, gfx.screen, &dest); + else + SDL_BlitSurface (gfx.font1.image, &src, gfx.screen, &dest); + dest.x += gfx.font.size.x-4; + } + + gfx_AddUpdateRect (x, y, dest.x - x, dest.h); +}; + diff --git a/src/game.c b/src/game.c index 285f199..780376c 100644 --- a/src/game.c +++ b/src/game.c @@ -1,260 +1,260 @@ -/* game.c - procedures for the game. */ - -#include -#include - -#include "bomberclone.h" -#include "gfx.h" -#include "network.h" -#include "packets.h" -#include "chat.h" - -extern int UpdateRects_nr; - -static Uint32 timediff; - -void -game_draw_info () -{ - int i, - x, - j, - gfx_oldRects; - char text[255]; - char scrtext[255]; - SDL_Rect src, dest; - - redraw_logo (0, 0, gfx.res.x, 3*16); - gfx_AddUpdateRect (0,0, gfx.res.x, 3*16); - gfx_oldRects = UpdateRects_nr; - bman.players_nr = 0; - - /* draw Player names */ - if (GT_MP_PTP) { - for (x = 0, j = 0, i = 0; i < MAX_PLAYERS; i++) - if ((bman.players[i].state & PSFM_used) != 0) { - - if (bman.players[i].gfx_nr != -1 && PS_IS_used (bman.players[i].state)) { - src.x = 3 * bman.players[i].gfx->smal_size.x; - src.y = 0; - src.w = dest.w = bman.players[i].gfx->smal_size.x; - src.h = dest.h = bman.players[i].gfx->smal_size.y; - - dest.x = x; - dest.y = j - 4; - - SDL_BlitSurface (bman.players[i].gfx->smal_image, &src, gfx.screen, &dest); - } - - - sprintf (scrtext, "%10s:%2d", bman.players[i].name, bman.players[i].points); - if ((bman.players[i].state & PSFM_alife) != PSFM_alife) { // Player is dead - draw_text (x, j, scrtext, 0); - if ((bman.players[i].state & PSF_used) != PSF_used) - draw_text (x, j, "-------------", 1); - } - else { // players is alife - draw_text (x, j, scrtext, 1); - bman.players_nr++; - } - - x = x + 170; - if (x >= gfx.res.x - (120 + 170)) { - x = 0; - j = j + 14; - } - } - } - - x = gfx.res.x - 120; - sprintf (text, "Bombs: %2d", bman.players[bman.p_nr].bombs_n); - draw_text (x, 0, text, 1); - sprintf (text, "Range: %2d", bman.players[bman.p_nr].range); - draw_text (x, 16, text, 1); - sprintf (text, "Speed: %2d", bman.players[bman.p_nr].speed); - draw_text (x, 32, text, 1); - - if (bman.state == GS_ready && GT_MP_PTPM) - draw_text (100, 32, "Press F4 to start the game", 1); - else if (bman.state == GS_ready) - draw_text (100, 32, "Waiting for the Server to Start", 1); - gfx_AddUpdateRect (100, 32, gfx.res.x - 100, 16); - - redraw_logo (0, gfx.res.y - gfx.font.size.y, gfx.res.x, gfx.res.y); - for (x = 0; x < bman.fieldsize.x; x++) - draw_stone (x, bman.fieldsize.y-1); - - if (debug) { /* do some debug informations on the screen */ - sprintf (text, "NET_STAT: ["); - for (i = 0 ; i < MAX_PLAYERS; i++) - sprintf (text, "%s%3d ", text, bman.players[i].net.pkgopt.send_set); - text[strlen(text)+1] = 0; - text[strlen(text)] = ']'; - sprintf (text, "%s GFX_RECTS:%d", text, UpdateRects_nr); - draw_text (0, gfx.res.y - (gfx.font.size.y << 1), text, 1); - sprintf (text, "TILESET: %s Timediff: %d", gfx.tileset, timediff); - draw_text (0, gfx.res.y - gfx.font.size.y, text, 1); - gfx_AddUpdateRect (0, gfx.res.y - (gfx.font.size.y << 1), gfx.res.x, gfx.font.size.y << 1); - - } - - if (chat.visible == 0) { - SDL_Flip (gfx.screen); - chat_show (4, 3*16, gfx.res.x - 4, gfx.offset.y); - } -}; - - -void -game_loop () -{ - SDL_Event event; - Uint8 *keys; - int done = 0; - Uint32 timeloop1; - int gameovertimeout = TIME_FACTOR * 5; // gameovertimeout - unsigned char key_bomb = 0; // last state of the bomb key - - draw_logo (); - draw_field (); - if (GT_MP_PTP) - net_game_fillsockaddr (); - - SDL_Flip (gfx.screen); - - timestamp = SDL_GetTicks (); // needed for time sync. - - d_gamedetail ("GAME START"); - - while (!done && (bman.state == GS_running || bman.state == GS_ready)) { - if (SDL_PollEvent (&event) != 0) - switch (event.type) { - case (SDL_QUIT): - done = 1; - bman.state = GS_quit; - } - - /* keyboard handling */ - keys = SDL_GetKeyState (NULL); - - /* only do movements if we're alife and GS_running */ - if ((bman.players[bman.p_nr].state & PSFM_alife) == PSFM_alife && bman.state == GS_running) { - if (keys[SDLK_UP]) { - bman.players[bman.p_nr].d = up; - bman.players[bman.p_nr].m = 1; - } - if (keys[SDLK_DOWN]) { - bman.players[bman.p_nr].d = down; - bman.players[bman.p_nr].m = 1; - } - if (keys[SDLK_RIGHT]) { - bman.players[bman.p_nr].d = right; - bman.players[bman.p_nr].m = 1; - } - if (keys[SDLK_LEFT]) { - bman.players[bman.p_nr].d = left; - bman.players[bman.p_nr].m = 1; - } - if (keys[SDLK_LCTRL] || keys[SDLK_RCTRL]) { - if (key_bomb == 0) - player_drop_bomb (); - key_bomb = 1; - } - else - key_bomb = 0; - if (keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]) { - d_printf ("not in use yet\n"); - } - } - else if (GT_MP_PTPM && keys[SDLK_F4] && event.type == SDL_KEYDOWN) { - /* Server is starting the game */ - bman.state = GS_running; - net_send_servermode (); - } - - if (event.key.keysym.sym == SDLK_ESCAPE && event.type == SDL_KEYDOWN) { - bman.state = GS_startup; - done = 1; - } - - chat_loop (&event); - - restore_players_screen (); - restore_bomb_screen (); - player_ilness_loop (); - if ((bman.players[bman.p_nr].state & PSFM_alife) == PSFM_alife) - move_player (); - - player_calcpos (); - dead_playerani (); /* we need it to draw dead players */ - - if (bman.gametype != GT_single) - network_loop (); - else - single_loop (); - - /* this will even set the variable "bman.player_nr" - to let us know how much Players are still left */ - game_draw_info (); - - bomb_loop (); - draw_players (); - - gfx_UpdateRects (); - - /* check if there is only one player left and the game is in multiplayer mode - and if there the last dieing animation is done */ - if ((GT_MP_PTPM) && bman.players_nr < 2) - gameovertimeout--; - - /* check if we died and we are in single mode and the animation is done */ - if (bman.gametype == GT_single && !PS_IS_alife(bman.players[bman.p_nr].state)) - gameovertimeout--; - - if (gameovertimeout <= 0) { - d_printf ("GAME: Game Over 'Cause only one or noone anymore alife\n"); - done = 1; - } - - // calculate time sync. - timeloop1 = SDL_GetTicks (); - timediff = timeloop1 - timestamp; // only for debugging needed - - while (timeloop1 - timestamp >= 0 && timeloop1 - timestamp < 20) { - s_delay (20 - (timeloop1 - timestamp) - 1); - timeloop1 = SDL_GetTicks (); - } - - timestamp = timeloop1; - } - - chat_show (-1, -1, -1, -1); - - d_gamedetail ("GAME END"); - d_printf ("done = %d\n", done); -}; - - -/* check which player won */ -void -game_end () -{ - int i; - - /* count the points */ - for (i = 0; i < MAX_PLAYERS; i++) - if (PS_IS_used (bman.players[i].state)) { - if (PS_IS_alife (bman.players[i].state)) { - bman.lastwinner = i; - bman.players[i].wins++; - bman.players[i].points += bman.players_nr_s; - } - } - - /* check which player is now free ,i.e. disconnected during the game and was playing */ - for (i = 0; i < MAX_PLAYERS; i++) - if ((bman.players[i].state & PSF_used ) == 0) - bman.players[i].state = 0; -} - - +/* game.c - procedures for the game. */ + +#include +#include + +#include "bomberclone.h" +#include "gfx.h" +#include "network.h" +#include "packets.h" +#include "chat.h" + +extern int UpdateRects_nr; + +static Uint32 timediff; + +void +game_draw_info () +{ + int i, + x, + j, + gfx_oldRects; + char text[255]; + char scrtext[255]; + SDL_Rect src, dest; + + redraw_logo (0, 0, gfx.res.x, 3*16); + gfx_AddUpdateRect (0,0, gfx.res.x, 3*16); + gfx_oldRects = UpdateRects_nr; + bman.players_nr = 0; + + /* draw Player names */ + if (GT_MP_PTP) { + for (x = 0, j = 0, i = 0; i < MAX_PLAYERS; i++) + if ((bman.players[i].state & PSFM_used) != 0) { + + if (bman.players[i].gfx_nr != -1 && PS_IS_used (bman.players[i].state)) { + src.x = 3 * bman.players[i].gfx->smal_size.x; + src.y = 0; + src.w = dest.w = bman.players[i].gfx->smal_size.x; + src.h = dest.h = bman.players[i].gfx->smal_size.y; + + dest.x = x; + dest.y = j - 4; + + SDL_BlitSurface (bman.players[i].gfx->smal_image, &src, gfx.screen, &dest); + } + + + sprintf (scrtext, "%10s:%2d", bman.players[i].name, bman.players[i].points); + if ((bman.players[i].state & PSFM_alife) != PSFM_alife) { // Player is dead + draw_text (x, j, scrtext, 0); + if ((bman.players[i].state & PSF_used) != PSF_used) + draw_text (x, j, "-------------", 1); + } + else { // players is alife + draw_text (x, j, scrtext, 1); + bman.players_nr++; + } + + x = x + 170; + if (x >= gfx.res.x - (120 + 170)) { + x = 0; + j = j + 14; + } + } + } + + x = gfx.res.x - 120; + sprintf (text, "Bombs: %2d", bman.players[bman.p_nr].bombs_n); + draw_text (x, 0, text, 1); + sprintf (text, "Range: %2d", bman.players[bman.p_nr].range); + draw_text (x, 16, text, 1); + sprintf (text, "Speed: %2d", bman.players[bman.p_nr].speed); + draw_text (x, 32, text, 1); + + if (bman.state == GS_ready && GT_MP_PTPM) + draw_text (100, 32, "Press F4 to start the game", 1); + else if (bman.state == GS_ready) + draw_text (100, 32, "Waiting for the Server to Start", 1); + gfx_AddUpdateRect (100, 32, gfx.res.x - 100, 16); + + redraw_logo (0, gfx.res.y - gfx.font.size.y, gfx.res.x, gfx.res.y); + for (x = 0; x < bman.fieldsize.x; x++) + draw_stone (x, bman.fieldsize.y-1); + + if (debug) { /* do some debug informations on the screen */ + sprintf (text, "NET_STAT: ["); + for (i = 0 ; i < MAX_PLAYERS; i++) + sprintf (text, "%s%3d ", text, bman.players[i].net.pkgopt.send_set); + text[strlen(text)+1] = 0; + text[strlen(text)] = ']'; + sprintf (text, "%s GFX_RECTS:%d", text, UpdateRects_nr); + draw_text (0, gfx.res.y - (gfx.font.size.y << 1), text, 1); + sprintf (text, "TILESET: %s Timediff: %d", gfx.tileset, timediff); + draw_text (0, gfx.res.y - gfx.font.size.y, text, 1); + gfx_AddUpdateRect (0, gfx.res.y - (gfx.font.size.y << 1), gfx.res.x, gfx.font.size.y << 1); + + } + + if (chat.visible == 0) { + SDL_Flip (gfx.screen); + chat_show (4, 3*16, gfx.res.x - 4, gfx.offset.y); + } +}; + + +void +game_loop () +{ + SDL_Event event; + Uint8 *keys; + int done = 0; + Uint32 timeloop1; + int gameovertimeout = TIME_FACTOR * 5; // gameovertimeout + unsigned char key_bomb = 0; // last state of the bomb key + + draw_logo (); + draw_field (); + if (GT_MP_PTP) + net_game_fillsockaddr (); + + SDL_Flip (gfx.screen); + + timestamp = SDL_GetTicks (); // needed for time sync. + + d_gamedetail ("GAME START"); + + while (!done && (bman.state == GS_running || bman.state == GS_ready)) { + if (SDL_PollEvent (&event) != 0) + switch (event.type) { + case (SDL_QUIT): + done = 1; + bman.state = GS_quit; + } + + /* keyboard handling */ + keys = SDL_GetKeyState (NULL); + + /* only do movements if we're alife and GS_running */ + if ((bman.players[bman.p_nr].state & PSFM_alife) == PSFM_alife && bman.state == GS_running) { + if (keys[SDLK_UP]) { + bman.players[bman.p_nr].d = up; + bman.players[bman.p_nr].m = 1; + } + if (keys[SDLK_DOWN]) { + bman.players[bman.p_nr].d = down; + bman.players[bman.p_nr].m = 1; + } + if (keys[SDLK_RIGHT]) { + bman.players[bman.p_nr].d = right; + bman.players[bman.p_nr].m = 1; + } + if (keys[SDLK_LEFT]) { + bman.players[bman.p_nr].d = left; + bman.players[bman.p_nr].m = 1; + } + if (keys[SDLK_LCTRL] || keys[SDLK_RCTRL]) { + if (key_bomb == 0) + player_drop_bomb (); + key_bomb = 1; + } + else + key_bomb = 0; + if (keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]) { + d_printf ("not in use yet\n"); + } + } + else if (GT_MP_PTPM && keys[SDLK_F4] && event.type == SDL_KEYDOWN) { + /* Server is starting the game */ + bman.state = GS_running; + net_send_servermode (); + } + + if (event.key.keysym.sym == SDLK_ESCAPE && event.type == SDL_KEYDOWN) { + bman.state = GS_startup; + done = 1; + } + + chat_loop (&event); + + restore_players_screen (); + restore_bomb_screen (); + player_ilness_loop (); + if ((bman.players[bman.p_nr].state & PSFM_alife) == PSFM_alife) + move_player (); + + player_calcpos (); + dead_playerani (); /* we need it to draw dead players */ + + if (bman.gametype != GT_single) + network_loop (); + else + single_loop (); + + /* this will even set the variable "bman.player_nr" + to let us know how much Players are still left */ + game_draw_info (); + + bomb_loop (); + draw_players (); + + gfx_UpdateRects (); + + /* check if there is only one player left and the game is in multiplayer mode + and if there the last dieing animation is done */ + if ((GT_MP_PTPM) && bman.players_nr < 2) + gameovertimeout--; + + /* check if we died and we are in single mode and the animation is done */ + if (bman.gametype == GT_single && !PS_IS_alife(bman.players[bman.p_nr].state)) + gameovertimeout--; + + if (gameovertimeout <= 0) { + d_printf ("GAME: Game Over 'Cause only one or noone anymore alife\n"); + done = 1; + } + + // calculate time sync. + timeloop1 = SDL_GetTicks (); + timediff = timeloop1 - timestamp; // only for debugging needed + + while (timeloop1 - timestamp >= 0 && timeloop1 - timestamp < 20) { + s_delay (20 - (timeloop1 - timestamp) - 1); + timeloop1 = SDL_GetTicks (); + } + + timestamp = timeloop1; + } + + chat_show (-1, -1, -1, -1); + + d_gamedetail ("GAME END"); + d_printf ("done = %d\n", done); +}; + + +/* check which player won */ +void +game_end () +{ + int i; + + /* count the points */ + for (i = 0; i < MAX_PLAYERS; i++) + if (PS_IS_used (bman.players[i].state)) { + if (PS_IS_alife (bman.players[i].state)) { + bman.lastwinner = i; + bman.players[i].wins++; + bman.players[i].points += bman.players_nr_s; + } + } + + /* check which player is now free ,i.e. disconnected during the game and was playing */ + for (i = 0; i < MAX_PLAYERS; i++) + if ((bman.players[i].state & PSF_used ) == 0) + bman.players[i].state = 0; +} + + diff --git a/src/gamesrv.c b/src/gamesrv.c index f58c42b..329dd52 100644 --- a/src/gamesrv.c +++ b/src/gamesrv.c @@ -1,469 +1,469 @@ -/* - GameServer: this file will hold the protocol for the gameserver communication -*/ -#include "bomberclone.h" -#include "network.h" -#include "gamesrv.h" - -static int sock = -1; -struct game_entry gse[MAX_GAMESRVENTRYS]; -_menu menu[22]; -int menuselect = 0; - -/* - We want to get a server -*/ -void -gamesrv_getserver () -{ - int i, - keypressed = 0, - done = 0, - ds = 0, - gserv = bman.notifygamemaster, - bx, - by; - SDL_Event event; - Uint8 *keys; - - menuselect = 0; - for (i = 0; i < MAX_GAMESRVENTRYS; i++) { - gse[i].name[0] = 0; - gse[i].host[0] = 0; - gse[i].port[0] = 0; - } - for (i = 0; i < 21; i++) { - menu[i].index = 0; - menu[i].text[0] = 0; - } - if (!gserv) { - menu[0].index = 1; - sprintf (menu[0].text, "Scan for Games on the MasterServer"); - } - sprintf (menu[10].text, "User defined Server List"); - menu[20].index = 1; - sprintf (menu[20].text, "Enter an IP-Address"); - menu[21].index = -1; - for (i = 1; i <= MAX_SERVERENTRYS; i++) { - menu[i + 10].index = 1; - sprintf (menu[i + 10].text, "%d) %s", i, bman.serverlist[i - 1].name); - } - - draw_logo (); - draw_menu ("Select Server", menu, &bx, &by); - if (gserv) { - if (gamesrv_startudp () == -1) - return; - gamesrv_browse (1); - } - draw_select (menuselect, menu, bx, by); - - SDL_Flip (gfx.screen); - - while (menuselect != -1 && done == 0) { - - if (gserv) - i = gamesrv_getglist (); - /*keyboard */ - if (SDL_PollEvent (&event) != 0) - switch (event.type) { - case (SDL_QUIT): - bman.state = GS_quit; - menuselect = -1; - done = 1; - } - - keys = SDL_GetKeyState (NULL); - - if (keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { - /* we want to quit */ - done = 1; - keypressed = 1; - menuselect = -1; - } - - if (keys[SDLK_DOWN] && (!keypressed)) { - d_printf ("down:%d\n", menu[menuselect].index); - menuselect++; - while (menu[menuselect].index == 0) - menuselect++; - if (menu[menuselect].index == -1) { - menuselect = 0; - while (menu[menuselect].index == 0) - menuselect++; - } - keypressed = 1; - ds = 1; - } - - if (keys[SDLK_UP] && (!keypressed)) { - d_printf ("up\n"); - menuselect--; - while (menu[menuselect].index == 0 && menuselect >= 0) - menuselect--; - if (menuselect == -1) - menuselect = 20; - keypressed = 1; - ds = 1; - } - if (keys[SDLK_RETURN] && (!keypressed)) { - if (menuselect == 0 && !gserv) { - gserv = 1; - if (gamesrv_startudp () == -1) - return; - gamesrv_browse (1); - } else done=1; - - - keypressed = 1; - } - - if (event.type == SDL_KEYUP) - keypressed = 0; - else if (event.type == SDL_KEYDOWN) - keypressed = 1; - - if (i) { - draw_logo (); - draw_menu ("Select Server", menu, &bx, &by); - draw_select (menuselect, menu, bx, by); - ds = 0; - SDL_Flip (gfx.screen); - } - else if (ds) { - draw_select (menuselect, menu, bx, by); - ds = 0; - SDL_Flip (gfx.screen); - } - s_delay (25); - } - - - if (menuselect > 0 && menuselect < 10) { - i = (menuselect - 1); - if (gse[i].name[0] != 0 && gse[i].host[0] != 0 && gse[i].port[0] != 0 && - (gse[i].state == GS_wait || gse[i].state == GS_running - || gse[i].state == GS_ready)) { - /* add if we are on Linux + and Windows and ai_family == PF_INET */ -#ifdef _WIN32 - if (gse[i].ai_family == PF_INET) { - sprintf (bman.servername, "%s:%s", gse[i].host, gse[i].port); - bman.net_ai_family = gse[i].ai_family; - } -#else - sprintf (bman.servername, "%s:%s", gse[i].host, gse[i].port); - d_printf("%s xxx %s xxx %s",gse[i].host,gse[i].port,bman.servername); - bman.net_ai_family = gse[i].ai_family; -#endif - } - } else if (menuselect >= 11 && menuselect < 19) - /* User defined Servers */ - strncpy (bman.servername, bman.serverlist[menuselect - 11].name, - LEN_SERVERNAME + LEN_PORT + 2); - else if (menuselect == 20) { - /* enter address */ - menu_get_text ("Enter Address", bman.servername, LEN_SERVERNAME + LEN_PORT + 2);} - - - if (gserv) { - gamesrv_browse (0); - udp_close (sock); - sock = -1; - -#ifdef _WIN32 - WSACleanup (); -#endif - } -}; - - -int -gamesrv_getglist () -{ - int i, - i1, - i2, - i3, - y, - nr, - rebuild = 0; - char buf[BUF_SIZE]; - char *pos; - char txt[255]; - struct _sockaddr addr; - struct game_entry entry; - - while (udp_get (sock, buf, BUF_SIZE, &addr, PF_INET) > 0) { - d_printf ("GOT:\n%s\n", buf); - - if (buf[0] == 'E') { - for (i = 0; i < MAX_GAMESRVENTRYS; i++) { - gse[i].name[0] = 0; - gse[i].host[0] = 0; - gse[i].port[0] = 0; - } - for (i = 0; i < 10; i++ ) { - menu[i].index = 0; - menu[i].text[0] = 0; - } - sprintf (menu[0].text, "No Games found on Masterserver"); - menu[0].index = 1; - rebuild = 1; - if (menuselect<10) menuselect=0; - } - else { - for (pos = buf; pos != 0;) { - // go throught the incoming data - switch (pos[0]) { - case ('P'): - sscanf (pos + 1, "%d,%d", &i1, &i2); - entry.curplayers = i1; - entry.maxplayers = i2; - break; - case ('V'): - sscanf (pos + 1, "%d.%d.%d", &i1, &i2, &i3); - entry.version.major = i1; - entry.version.minor = i2; - entry.version.sub = i3; - break; - case ('S'): - sscanf (pos + 1, "%d,%d,%d", &i1, &i2, &i3); - entry.state = i1; - entry.multitype = i2; - entry.gametype = i3; - break; - case ('I'): - if (pos[1] == '4') - entry.ai_family = PF_INET; - else if (pos[1] == '6') -#ifndef _WIN32 - entry.ai_family = PF_INET6; -#else - entry.ai_family = 0; -#endif - break; - case ('N'): - for (i = 1; (i - 1 < LEN_GAMENAME) && (pos[i] != 0) - && (pos[i] != '\n'); i++) - entry.name[i - 1] = pos[i]; - entry.name[i-1]=0; - break; - case ('H'): - for (i = 1; (i - 1 < LEN_SERVERNAME) && (pos[i] != 0) - && (pos[i] != '\n'); i++) - entry.host[i - 1] = pos[i]; - entry.host[i-1]=0; - break; - case ('O'): - for (i = 1; (i - 1 < LEN_PORT) && (pos[i] != 0) - && (pos[i] != '\n'); i++) - entry.port[i - 1] = pos[i]; - entry.port[i-1]=0; - break; - } - pos = strchr (pos, '\n'); - if (pos != 0) - pos++; - if (pos != 0 && pos[0] == 0) - pos = 0; - } - nr = gamesrv_findentry (entry.host, entry.port); - if (nr == -1) { - nr = gamesrv_findfree (); - if (nr == -1) - return -1; - } - gse[nr] = entry; - - - sprintf (txt, "%16s ", gse[nr].name); - - if (gse[nr].state == GS_wait) - sprintf (txt, "%s Wait ", txt); - else if (gse[nr].state == GS_running || gse[nr].state == GS_ready) - sprintf (txt, "%sRunning ", txt); - else if (gse[nr].state == GS_update) - sprintf (txt, "%s Update ", txt); - - sprintf (txt, "%s%d/%d ", txt, gse[nr].curplayers, gse[nr].maxplayers); - - if (gse[nr].ai_family == PF_INET) - sprintf (txt, "%s %d.%d.%d IPv4", txt, gse[nr].version.major, gse[nr].version.minor, - gse[nr].version.sub); - else - sprintf (txt, "%s %d.%d.%d IPv6", txt, gse[nr].version.major, gse[nr].version.minor, - gse[nr].version.sub); - - for (y = 0; y < 255; y++) - menu[nr + 1].text[y] = 0; - strncpy (menu[nr + 1].text, txt, 40); - rebuild = 1; - sprintf (menu[0].text, "Games on the Masterserver"); - menu[0].index = 0; - if (menuselect == 0) - menuselect = 1; - menu[nr + 1].index = 1; - } - } - return rebuild; -} - -int -gamesrv_startudp () -{ -#ifdef _WIN32 - WSADATA wsaData; - - if (WSAStartup (MAKEWORD (1, 1), &wsaData) != 0) { - d_printf ("WSAStartup failed.\n"); - exit (1); - } -#endif - - sock = udp_server (DEFAULT_GMUDPPORT, bman.net_ai_family); - if (sock == -1) { -#ifdef _WIN32 - WSACleanup (); -#endif - } - return sock; -} - - - -/* find the entry */ -int -gamesrv_findentry (char *host, char *port) -{ - int i, - y; - - for (i = 0, y = -1; (i < MAX_GAMESRVENTRYS) && (y == -1); i++) { - if (strcmp (gse[i].host, host) == 0 && strcmp (gse[i].port, port) == 0) - y = i; - } - return y; -}; - -/* Find first free entry */ -int -gamesrv_findfree () -{ - int i, - y; - - for (i = 0, y = -1; (y == -1) && (i < MAX_GAMESRVENTRYS); i++) - if (gse[i].host[0] == 0) - y = i; - - return y; -}; - - - -/* - Add and Delete Browsers from Serverbrowselist -*/ - - -void -gamesrv_browse (int i) -{ - char data[255]; - struct _sockaddr addr; - char host[LEN_SERVERNAME]; - char port[LEN_PORT]; - - d_printf ("** Notify Browser Master Server\n"); - if (i) - sprintf (data, "B\n"); - else - sprintf (data, "E\n"); - - network_server_port (bman.gamemaster, host, LEN_SERVERNAME, port, LEN_PORT); - dns_filladdr (host, LEN_SERVERNAME, port, LEN_PORT, bman.net_ai_family, &addr); - udp_send (sock, data, strlen (data), &addr, bman.net_ai_family); - d_printf ("Send: %s\n", data); -}; - -/* - The Server should know that we quit. - Delete every entry from our client. -*/ - - -void -gamesrv_quit () -{ - char data[255]; - struct _sockaddr addr; - char host[LEN_SERVERNAME]; - char port[LEN_PORT]; - int len; - - d_printf ("** Notify GameMaster Server\n"); - sprintf (data, "D\n"); - - len = 4; - - network_server_port (bman.gamemaster, host, LEN_SERVERNAME, port, LEN_PORT); - dns_filladdr (host, LEN_SERVERNAME, port, LEN_PORT, bman.net_ai_family, &addr); - - udp_send (bman.sock, data, len, &addr, bman.net_ai_family); - d_printf ("** Send \n\n%s\n\n", data); -}; - - -/* - send the mode of the game from the current bman.state and bman.gamename - parameter -*/ -void -gamesrv_sendmode (int maxplayer, int curplayers) -{ - char data[255]; - int len = 0; - struct _sockaddr addr; - char host[LEN_SERVERNAME]; - char port[LEN_PORT]; - - d_printf ("** Notify GameMaster Server\n"); - - sprintf (data, "AV%s\n", VERSION); - sprintf (data, "%sP%d,%d\n", data, curplayers, maxplayer); - sprintf (data, "%sS%d,%d,%d\n", data, bman.state, bman.multitype, bman.gametype); - if (bman.net_ai_family == PF_INET) - sprintf (data, "%sI4\n", data); - else - sprintf (data, "%sI6\n", data); - sprintf (data, "%sN%s\n", data, bman.gamename); - - len = strlen (data); - - network_server_port (bman.gamemaster, host, LEN_SERVERNAME, port, LEN_PORT); - dns_filladdr (host, LEN_SERVERNAME, port, LEN_PORT, bman.net_ai_family, &addr); - - host[0] = 0; - port[0] = 0; - dns_filladdr (host, LEN_SERVERNAME, port, LEN_PORT, bman.net_ai_family, &addr); - - udp_send (bman.sock, data, len, &addr, bman.net_ai_family); - d_printf ("** Send To (%s[:%s])\n\n%s\n\n", host, port, data); -}; - - -void -gamesrv_sendchat (char *text) -{ - char data[255]; - struct _sockaddr addr; - char host[LEN_SERVERNAME]; - char port[LEN_PORT]; - - network_server_port (bman.gamemaster, host, LEN_SERVERNAME, port, LEN_PORT); - dns_filladdr (host, LEN_SERVERNAME, port, LEN_PORT, bman.net_ai_family, &addr); - - sprintf (data, "C%s", text); - - udp_send (bman.sock, data, strlen (data), &addr, bman.net_ai_family); -}; +/* + GameServer: this file will hold the protocol for the gameserver communication +*/ +#include "bomberclone.h" +#include "network.h" +#include "gamesrv.h" + +static int sock = -1; +struct game_entry gse[MAX_GAMESRVENTRYS]; +_menu menu[22]; +int menuselect = 0; + +/* + We want to get a server +*/ +void +gamesrv_getserver () +{ + int i, + keypressed = 0, + done = 0, + ds = 0, + gserv = bman.notifygamemaster, + bx, + by; + SDL_Event event; + Uint8 *keys; + + menuselect = 0; + for (i = 0; i < MAX_GAMESRVENTRYS; i++) { + gse[i].name[0] = 0; + gse[i].host[0] = 0; + gse[i].port[0] = 0; + } + for (i = 0; i < 21; i++) { + menu[i].index = 0; + menu[i].text[0] = 0; + } + if (!gserv) { + menu[0].index = 1; + sprintf (menu[0].text, "Scan for Games on the MasterServer"); + } + sprintf (menu[10].text, "User defined Server List"); + menu[20].index = 1; + sprintf (menu[20].text, "Enter an IP-Address"); + menu[21].index = -1; + for (i = 1; i <= MAX_SERVERENTRYS; i++) { + menu[i + 10].index = 1; + sprintf (menu[i + 10].text, "%d) %s", i, bman.serverlist[i - 1].name); + } + + draw_logo (); + draw_menu ("Select Server", menu, &bx, &by); + if (gserv) { + if (gamesrv_startudp () == -1) + return; + gamesrv_browse (1); + } + draw_select (menuselect, menu, bx, by); + + SDL_Flip (gfx.screen); + + while (menuselect != -1 && done == 0) { + + if (gserv) + i = gamesrv_getglist (); + /*keyboard */ + if (SDL_PollEvent (&event) != 0) + switch (event.type) { + case (SDL_QUIT): + bman.state = GS_quit; + menuselect = -1; + done = 1; + } + + keys = SDL_GetKeyState (NULL); + + if (keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { + /* we want to quit */ + done = 1; + keypressed = 1; + menuselect = -1; + } + + if (keys[SDLK_DOWN] && (!keypressed)) { + d_printf ("down:%d\n", menu[menuselect].index); + menuselect++; + while (menu[menuselect].index == 0) + menuselect++; + if (menu[menuselect].index == -1) { + menuselect = 0; + while (menu[menuselect].index == 0) + menuselect++; + } + keypressed = 1; + ds = 1; + } + + if (keys[SDLK_UP] && (!keypressed)) { + d_printf ("up\n"); + menuselect--; + while (menu[menuselect].index == 0 && menuselect >= 0) + menuselect--; + if (menuselect == -1) + menuselect = 20; + keypressed = 1; + ds = 1; + } + if (keys[SDLK_RETURN] && (!keypressed)) { + if (menuselect == 0 && !gserv) { + gserv = 1; + if (gamesrv_startudp () == -1) + return; + gamesrv_browse (1); + } else done=1; + + + keypressed = 1; + } + + if (event.type == SDL_KEYUP) + keypressed = 0; + else if (event.type == SDL_KEYDOWN) + keypressed = 1; + + if (i) { + draw_logo (); + draw_menu ("Select Server", menu, &bx, &by); + draw_select (menuselect, menu, bx, by); + ds = 0; + SDL_Flip (gfx.screen); + } + else if (ds) { + draw_select (menuselect, menu, bx, by); + ds = 0; + SDL_Flip (gfx.screen); + } + s_delay (25); + } + + + if (menuselect > 0 && menuselect < 10) { + i = (menuselect - 1); + if (gse[i].name[0] != 0 && gse[i].host[0] != 0 && gse[i].port[0] != 0 && + (gse[i].state == GS_wait || gse[i].state == GS_running + || gse[i].state == GS_ready)) { + /* add if we are on Linux + and Windows and ai_family == PF_INET */ +#ifdef _WIN32 + if (gse[i].ai_family == PF_INET) { + sprintf (bman.servername, "%s:%s", gse[i].host, gse[i].port); + bman.net_ai_family = gse[i].ai_family; + } +#else + sprintf (bman.servername, "%s:%s", gse[i].host, gse[i].port); + d_printf("%s xxx %s xxx %s",gse[i].host,gse[i].port,bman.servername); + bman.net_ai_family = gse[i].ai_family; +#endif + } + } else if (menuselect >= 11 && menuselect < 19) + /* User defined Servers */ + strncpy (bman.servername, bman.serverlist[menuselect - 11].name, + LEN_SERVERNAME + LEN_PORT + 2); + else if (menuselect == 20) { + /* enter address */ + menu_get_text ("Enter Address", bman.servername, LEN_SERVERNAME + LEN_PORT + 2);} + + + if (gserv) { + gamesrv_browse (0); + udp_close (sock); + sock = -1; + +#ifdef _WIN32 + WSACleanup (); +#endif + } +}; + + +int +gamesrv_getglist () +{ + int i, + i1, + i2, + i3, + y, + nr, + rebuild = 0; + char buf[BUF_SIZE]; + char *pos; + char txt[255]; + struct _sockaddr addr; + struct game_entry entry; + + while (udp_get (sock, buf, BUF_SIZE, &addr, PF_INET) > 0) { + d_printf ("GOT:\n%s\n", buf); + + if (buf[0] == 'E') { + for (i = 0; i < MAX_GAMESRVENTRYS; i++) { + gse[i].name[0] = 0; + gse[i].host[0] = 0; + gse[i].port[0] = 0; + } + for (i = 0; i < 10; i++ ) { + menu[i].index = 0; + menu[i].text[0] = 0; + } + sprintf (menu[0].text, "No Games found on Masterserver"); + menu[0].index = 1; + rebuild = 1; + if (menuselect<10) menuselect=0; + } + else { + for (pos = buf; pos != 0;) { + // go throught the incoming data + switch (pos[0]) { + case ('P'): + sscanf (pos + 1, "%d,%d", &i1, &i2); + entry.curplayers = i1; + entry.maxplayers = i2; + break; + case ('V'): + sscanf (pos + 1, "%d.%d.%d", &i1, &i2, &i3); + entry.version.major = i1; + entry.version.minor = i2; + entry.version.sub = i3; + break; + case ('S'): + sscanf (pos + 1, "%d,%d,%d", &i1, &i2, &i3); + entry.state = i1; + entry.multitype = i2; + entry.gametype = i3; + break; + case ('I'): + if (pos[1] == '4') + entry.ai_family = PF_INET; + else if (pos[1] == '6') +#ifndef _WIN32 + entry.ai_family = PF_INET6; +#else + entry.ai_family = 0; +#endif + break; + case ('N'): + for (i = 1; (i - 1 < LEN_GAMENAME) && (pos[i] != 0) + && (pos[i] != '\n'); i++) + entry.name[i - 1] = pos[i]; + entry.name[i-1]=0; + break; + case ('H'): + for (i = 1; (i - 1 < LEN_SERVERNAME) && (pos[i] != 0) + && (pos[i] != '\n'); i++) + entry.host[i - 1] = pos[i]; + entry.host[i-1]=0; + break; + case ('O'): + for (i = 1; (i - 1 < LEN_PORT) && (pos[i] != 0) + && (pos[i] != '\n'); i++) + entry.port[i - 1] = pos[i]; + entry.port[i-1]=0; + break; + } + pos = strchr (pos, '\n'); + if (pos != 0) + pos++; + if (pos != 0 && pos[0] == 0) + pos = 0; + } + nr = gamesrv_findentry (entry.host, entry.port); + if (nr == -1) { + nr = gamesrv_findfree (); + if (nr == -1) + return -1; + } + gse[nr] = entry; + + + sprintf (txt, "%16s ", gse[nr].name); + + if (gse[nr].state == GS_wait) + sprintf (txt, "%s Wait ", txt); + else if (gse[nr].state == GS_running || gse[nr].state == GS_ready) + sprintf (txt, "%sRunning ", txt); + else if (gse[nr].state == GS_update) + sprintf (txt, "%s Update ", txt); + + sprintf (txt, "%s%d/%d ", txt, gse[nr].curplayers, gse[nr].maxplayers); + + if (gse[nr].ai_family == PF_INET) + sprintf (txt, "%s %d.%d.%d IPv4", txt, gse[nr].version.major, gse[nr].version.minor, + gse[nr].version.sub); + else + sprintf (txt, "%s %d.%d.%d IPv6", txt, gse[nr].version.major, gse[nr].version.minor, + gse[nr].version.sub); + + for (y = 0; y < 255; y++) + menu[nr + 1].text[y] = 0; + strncpy (menu[nr + 1].text, txt, 40); + rebuild = 1; + sprintf (menu[0].text, "Games on the Masterserver"); + menu[0].index = 0; + if (menuselect == 0) + menuselect = 1; + menu[nr + 1].index = 1; + } + } + return rebuild; +} + +int +gamesrv_startudp () +{ +#ifdef _WIN32 + WSADATA wsaData; + + if (WSAStartup (MAKEWORD (1, 1), &wsaData) != 0) { + d_printf ("WSAStartup failed.\n"); + exit (1); + } +#endif + + sock = udp_server (DEFAULT_GMUDPPORT, bman.net_ai_family); + if (sock == -1) { +#ifdef _WIN32 + WSACleanup (); +#endif + } + return sock; +} + + + +/* find the entry */ +int +gamesrv_findentry (char *host, char *port) +{ + int i, + y; + + for (i = 0, y = -1; (i < MAX_GAMESRVENTRYS) && (y == -1); i++) { + if (strcmp (gse[i].host, host) == 0 && strcmp (gse[i].port, port) == 0) + y = i; + } + return y; +}; + +/* Find first free entry */ +int +gamesrv_findfree () +{ + int i, + y; + + for (i = 0, y = -1; (y == -1) && (i < MAX_GAMESRVENTRYS); i++) + if (gse[i].host[0] == 0) + y = i; + + return y; +}; + + + +/* + Add and Delete Browsers from Serverbrowselist +*/ + + +void +gamesrv_browse (int i) +{ + char data[255]; + struct _sockaddr addr; + char host[LEN_SERVERNAME]; + char port[LEN_PORT]; + + d_printf ("** Notify Browser Master Server\n"); + if (i) + sprintf (data, "B\n"); + else + sprintf (data, "E\n"); + + network_server_port (bman.gamemaster, host, LEN_SERVERNAME, port, LEN_PORT); + dns_filladdr (host, LEN_SERVERNAME, port, LEN_PORT, bman.net_ai_family, &addr); + udp_send (sock, data, strlen (data), &addr, bman.net_ai_family); + d_printf ("Send: %s\n", data); +}; + +/* + The Server should know that we quit. + Delete every entry from our client. +*/ + + +void +gamesrv_quit () +{ + char data[255]; + struct _sockaddr addr; + char host[LEN_SERVERNAME]; + char port[LEN_PORT]; + int len; + + d_printf ("** Notify GameMaster Server\n"); + sprintf (data, "D\n"); + + len = 4; + + network_server_port (bman.gamemaster, host, LEN_SERVERNAME, port, LEN_PORT); + dns_filladdr (host, LEN_SERVERNAME, port, LEN_PORT, bman.net_ai_family, &addr); + + udp_send (bman.sock, data, len, &addr, bman.net_ai_family); + d_printf ("** Send \n\n%s\n\n", data); +}; + + +/* + send the mode of the game from the current bman.state and bman.gamename + parameter +*/ +void +gamesrv_sendmode (int maxplayer, int curplayers) +{ + char data[255]; + int len = 0; + struct _sockaddr addr; + char host[LEN_SERVERNAME]; + char port[LEN_PORT]; + + d_printf ("** Notify GameMaster Server\n"); + + sprintf (data, "AV%s\n", VERSION); + sprintf (data, "%sP%d,%d\n", data, curplayers, maxplayer); + sprintf (data, "%sS%d,%d,%d\n", data, bman.state, bman.multitype, bman.gametype); + if (bman.net_ai_family == PF_INET) + sprintf (data, "%sI4\n", data); + else + sprintf (data, "%sI6\n", data); + sprintf (data, "%sN%s\n", data, bman.gamename); + + len = strlen (data); + + network_server_port (bman.gamemaster, host, LEN_SERVERNAME, port, LEN_PORT); + dns_filladdr (host, LEN_SERVERNAME, port, LEN_PORT, bman.net_ai_family, &addr); + + host[0] = 0; + port[0] = 0; + dns_filladdr (host, LEN_SERVERNAME, port, LEN_PORT, bman.net_ai_family, &addr); + + udp_send (bman.sock, data, len, &addr, bman.net_ai_family); + d_printf ("** Send To (%s[:%s])\n\n%s\n\n", host, port, data); +}; + + +void +gamesrv_sendchat (char *text) +{ + char data[255]; + struct _sockaddr addr; + char host[LEN_SERVERNAME]; + char port[LEN_PORT]; + + network_server_port (bman.gamemaster, host, LEN_SERVERNAME, port, LEN_PORT); + dns_filladdr (host, LEN_SERVERNAME, port, LEN_PORT, bman.net_ai_family, &addr); + + sprintf (data, "C%s", text); + + udp_send (bman.sock, data, strlen (data), &addr, bman.net_ai_family); +}; diff --git a/src/gamesrv.h b/src/gamesrv.h index 3057c18..a711708 100644 --- a/src/gamesrv.h +++ b/src/gamesrv.h @@ -1,30 +1,30 @@ -/* - include file for the gamesrv.c file -*/ - -struct game_entry { - char host[LEN_SERVERNAME]; - char port[LEN_PORT]; - char name[LEN_GAMENAME]; - struct _version { - unsigned char major; - unsigned char minor; - unsigned char sub; - } version; - signed char curplayers; - signed char maxplayers; - signed char ai_family; - unsigned char state; - unsigned char multitype; - unsigned char gametype; -}; - -extern int gamesrv_findentry (char *host, char *port); -extern int gamesrv_findfree (); -extern int gamesrv_startudp (); -extern int gamesrv_getglist (); -extern void gamesrv_getserver (); -extern void gamesrv_quit (); -extern void gamesrv_browse (); -extern void gamesrv_sendmode (int maxplayer, int curplayers); -extern void gamesrv_sendchat (char *text); +/* + include file for the gamesrv.c file +*/ + +struct game_entry { + char host[LEN_SERVERNAME]; + char port[LEN_PORT]; + char name[LEN_GAMENAME]; + struct _version { + unsigned char major; + unsigned char minor; + unsigned char sub; + } version; + signed char curplayers; + signed char maxplayers; + signed char ai_family; + unsigned char state; + unsigned char multitype; + unsigned char gametype; +}; + +extern int gamesrv_findentry (char *host, char *port); +extern int gamesrv_findfree (); +extern int gamesrv_startudp (); +extern int gamesrv_getglist (); +extern void gamesrv_getserver (); +extern void gamesrv_quit (); +extern void gamesrv_browse (); +extern void gamesrv_sendmode (int maxplayer, int curplayers); +extern void gamesrv_sendchat (char *text); diff --git a/src/gfx.c b/src/gfx.c index bfdaa9b..da08c0c 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -1,787 +1,822 @@ -/* gfx.c */ - -#include -#include "bomberclone.h" -#include "gfx.h" - -int UpdateRects_nr = 0; -SDL_Rect UpdateRects[MAX_UPDATERECTS]; - -_gfx gfx; - - -void getRGBpixel (SDL_Surface *surface, int x, int y, int *R, int *G, int *B) { - - Uint32 pixel = 0; - Uint8 r,g,b; - - /* Lock the screen for direct access to the pixels */ - if ( SDL_MUSTLOCK(surface) ) - if ( SDL_LockSurface(surface) < 0 ) { - fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError()); - return; - } - - pixel = getpixel (surface, x, y); - - if ( SDL_MUSTLOCK(surface) ) { - SDL_UnlockSurface(surface); - } - - SDL_GetRGB(pixel, surface->format, &r, &g, &b); - *R = r; - *G = g; - *B = b; -}; - - -Uint32 getpixel(SDL_Surface *surface, int x, int y) -{ - int bpp = surface->format->BytesPerPixel; - /* Here p is the address to the pixel we want to retrieve */ - Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; - - switch(bpp) { - case 1: - return *p; - - case 2: - return *(Uint16 *)p; - - case 3: - if(SDL_BYTEORDER == SDL_BIG_ENDIAN) - return p[0] << 16 | p[1] << 8 | p[2]; - else - return p[0] | p[1] << 8 | p[2] << 16; - - case 4: - return *(Uint32 *)p; - - default: - return 0; /* shouldn't happen, but avoids warnings */ - } -} - - -void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) -{ - int bpp = surface->format->BytesPerPixel; - /* Here p is the address to the pixel we want to set */ - Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; - - switch(bpp) { - case 1: - *p = pixel; - break; - - case 2: - *(Uint16 *)p = pixel; - break; - - case 3: - if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { - p[0] = (pixel >> 16) & 0xff; - p[1] = (pixel >> 8) & 0xff; - p[2] = pixel & 0xff; - } else { - p[0] = pixel & 0xff; - p[1] = (pixel >> 8) & 0xff; - p[2] = (pixel >> 16) & 0xff; - } - break; - - case 4: - *(Uint32 *)p = pixel; - break; - } -} - - -void scale (short int *dpattern, short int x, short int y) { - int a, dx, dy; - - if (x >= SCALE_MAXRES || y >= SCALE_MAXRES) { - for (x = 0; x < SCALE_MAXRES; x++) - dpattern[x] = 0; - return; - } - - if (x > y) { - dy = 2 * y; - dx = a = 2 * x - dy; - do { - if ( a <= 0) { - dpattern[(y--)-1] = x; - a = a + dx; - } - else - a = a - dy; - } while (x--); - } - else { - dy = 2 * x; - dx = a = 2 * y - dy; - do { - dpattern[y] = x; - if (a <= 0) { - x--; - a = a + dx; - } - else - a = a - dy; - } while (y--); - } -} - - -SDL_Surface * -scale_image (SDL_Surface * orginal, int newx, int newy) -{ - Uint32 rmask, - gmask, - bmask, - amask; - SDL_Surface *surface; - - int y, x; - short int xpattern[SCALE_MAXRES]; - short int ypattern[SCALE_MAXRES]; - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - rmask = 0xff000000; - gmask = 0x00ff0000; - bmask = 0x0000ff00; - amask = 0x000000ff; -#else - rmask = 0x00ff0000; - gmask = 0x0000ff00; - bmask = 0x000000ff; - amask = 0xff000000; -#endif - - surface = SDL_CreateRGBSurface (SDL_SWSURFACE, newx, newy, 32, rmask, gmask, bmask, amask); - if (surface == NULL) { - fprintf (stderr, "CreateRGBSurface failed: %s\n", SDL_GetError ()); - return NULL; - } - - /* Lock the screen for direct access to the pixels */ - if ( SDL_MUSTLOCK(surface) ) - if ( SDL_LockSurface(surface) < 0 ) { - fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError()); - return NULL; - } - if ( SDL_MUSTLOCK(orginal) ) - if ( SDL_LockSurface(orginal) < 0 ) { - fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError()); - if ( SDL_MUSTLOCK(surface) ) { - SDL_UnlockSurface(surface); - } - return NULL; - } - - /* do the scaling work */ - scale (xpattern, orginal->w -1, newx); - scale (ypattern, orginal->h -1, newy); - - for (x = newx-1; x >= 0; x--) - for (y = newy - 1; y >= 0; y--) - putpixel (surface, x, y, getpixel (orginal, xpattern[x], ypattern[y])); - if ( SDL_MUSTLOCK(orginal) ) { - SDL_UnlockSurface(orginal); - } - - if ( SDL_MUSTLOCK(surface) ) { - SDL_UnlockSurface(surface); - } - - return surface; -}; - - -SDL_Surface *makegray_image (SDL_Surface *org) { - Uint32 rmask, - gmask, - bmask, - amask; - Uint32 pixel, transpixel = 0; - SDL_Surface *dest; - int y, x; - Uint8 r,g,b,gray; - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - rmask = 0xff000000; - gmask = 0x00ff0000; - bmask = 0x0000ff00; - amask = 0x000000ff; -#else - rmask = 0x00ff0000; - gmask = 0x0000ff00; - bmask = 0x000000ff; - amask = 0xff000000; -#endif - - dest = SDL_CreateRGBSurface (SDL_SWSURFACE, org->w, org->h, 32, rmask, gmask, bmask, amask); - if (dest == NULL) { - fprintf (stderr, "CreateRGBSurface failed: %s\n", SDL_GetError ()); - return NULL; - } - - /* Lock the screen for direct access to the pixels */ - if ( SDL_MUSTLOCK(dest) ) - if ( SDL_LockSurface(dest) < 0 ) { - fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError()); - return NULL; - } - - if ( SDL_MUSTLOCK(org) ) - if ( SDL_LockSurface(org) < 0 ) { - fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError()); - if ( SDL_MUSTLOCK(dest) ) { - SDL_UnlockSurface(dest); - } - return NULL; - } - - for (x = 0; x < org->w; x++) - for (y = 0; y < org->h; y++) { - pixel = getpixel (org, x, y); - if (x == 0 && y == 0) - transpixel = pixel; - - if (pixel != transpixel) { - SDL_GetRGB(pixel, org->format, &r, &g, &b); - gray = (r/3 + g/3 + b/3); - pixel = SDL_MapRGB(dest->format, gray, gray, gray); - } - - putpixel (dest, x, y, pixel); - } - - if ( SDL_MUSTLOCK(org) ) { - SDL_UnlockSurface(org); - } - - if ( SDL_MUSTLOCK(dest) ) { - SDL_UnlockSurface(dest); - } - - SDL_SetColorKey (dest, SDL_SRCCOLORKEY,transpixel); - - return dest; -}; - - - -#define __smalsizeX 12 -void gfx_load_players (int sx, int sy) { - float sfkt, ssfkt; - char filename[255]; - int i, - j, - r, - g, - b; - SDL_Surface *tmpimage, *tmpimage1; - - sfkt = ((float) sx) / ((float) GFX_IMGSIZE); - ssfkt = ((float) __smalsizeX) / ((float) GFX_IMGSIZE); - - /* loading the player images */ - for (j = i = 0; i < MAX_PLAYERS; i++) { - sprintf (filename, "%s/player/player%d.bmp", bman.datapath, j); - j++; - tmpimage = SDL_LoadBMP (filename); - if (tmpimage == NULL) { - if (j == 0) { // try again with the first image, if this don't work give up. - printf ("Can't load image: %s\n", SDL_GetError ()); - exit (1); - } - i--; // load the this image again - j = 0; - } - else { - /* load the game player image */ - gfx.players[i].size.y = sy * 2; - gfx.players[i].size.x = (tmpimage->w / 4) * sfkt; - gfx.players[i].ani.frames = tmpimage->h / GFX_PLAYERIMGSIZE_Y; - tmpimage1 = scale_image (tmpimage, gfx.players[i].size.x * 4 , gfx.players[i].ani.frames * gfx.players[i].size.y); - getRGBpixel (tmpimage1, 0, 0, &r, &g, &b); - SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY,SDL_MapRGB (tmpimage1->format, r, g, b)); - gfx.players[i].ani.image = SDL_DisplayFormat (tmpimage1); - SDL_FreeSurface (tmpimage1); - /* calculate the numbers of images for the animation */ - gfx.players[i].offset.x = (sx - gfx.players[i].size.x) / 2; - gfx.players[i].offset.y = - sy; - - /* load the smal image */ - gfx.players[i].smal_size.y = __smalsizeX * 2; - gfx.players[i].smal_size.x = (tmpimage->w / 4) * ssfkt; - tmpimage1 = scale_image (tmpimage, gfx.players[i].smal_size.x * 4 , gfx.players[i].ani.frames * gfx.players[i].smal_size.y); - getRGBpixel (tmpimage1, 0, 0, &r, &g, &b); - SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY,SDL_MapRGB (tmpimage1->format, r, g, b)); - gfx.players[i].smal_image = SDL_DisplayFormat (tmpimage1); - SDL_FreeSurface (tmpimage1); - SDL_FreeSurface (tmpimage); - } - } - - /* load the illnessthing */ - sprintf (filename, "%s/player/playersick.bmp", bman.datapath); - tmpimage = SDL_LoadBMP (filename); - if (tmpimage == NULL) { - printf ("Can't load image: %s\n", SDL_GetError ()); - exit (1); - } - gfx.ill.frames = tmpimage->h / (2*GFX_IMGSIZE); - tmpimage1 = scale_image (tmpimage, (tmpimage->w / (2*GFX_IMGSIZE)) * (2 * sx), gfx.ill.frames * (2*sy)); - getRGBpixel (tmpimage1, 0, 0, &r, &g, &b); - SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY,SDL_MapRGB (tmpimage1->format, r, g, b)); - gfx.ill.image = SDL_DisplayFormat (tmpimage1); - SDL_FreeSurface (tmpimage); - SDL_FreeSurface (tmpimage1); - - -} - -/* frees the player images */ -void gfx_free_players () { - int i; - - for (i = 0; i < MAX_PLAYERS; i++) { - if (gfx.players[i].ani.image != NULL) - SDL_FreeSurface (gfx.players[i].ani.image); - gfx.players[i].ani.image = NULL; - if (gfx.players[i].smal_image != NULL) - SDL_FreeSurface (gfx.players[i].smal_image); - gfx.players[i].smal_image = NULL; - } - - SDL_FreeSurface (gfx.ill.image); -} - - -/* load the images with the right scaleing */ -void gfx_game_init () { - menu_displaytext ("Loading..", "Please Wait", 32, 128, 32); - - gfx_load_tileset (gfx.tileset); - gfx_load_players (gfx.block.x,gfx.block.y); -} - - -void gfx_game_shutdown () { - menu_displaytext ("Freeing..", "Please Wait", 32, 128, 32); - - gfx_free_players (); - gfx_free_tileset (); -}; - - -/* init the whole GFX Part */ -void gfx_init () { - if (gfx.fullscreen) - gfx.screen = SDL_SetVideoMode (gfx.res.x, gfx.res.y, gfx.bpp, - SDL_SWSURFACE | SDL_DOUBLEBUF | SDL_HWACCEL | SDL_FULLSCREEN); - else - gfx.screen = SDL_SetVideoMode (gfx.res.x, gfx.res.y, gfx.bpp, - SDL_SWSURFACE | SDL_DOUBLEBUF | SDL_HWACCEL); - - if (gfx.screen == NULL) { - d_printf ("Unable to set video mode: %s\n", SDL_GetError ()); - return; - } - - SDL_ShowCursor(SDL_DISABLE); - - gfx_loaddata (); -}; - - -void -gfx_loaddata () -{ - int r, - g, - b; - - char filename[255]; - SDL_Surface *tmpimage, *tmpimage1; - - /* load the font */ - sprintf (filename, "%s/gfx/font.bmp", bman.datapath); - tmpimage = SDL_LoadBMP (filename); - if (tmpimage == NULL) { - printf ("Can't load image: %s\n", SDL_GetError ()); - exit (1); - } - SDL_SetColorKey (tmpimage, SDL_SRCCOLORKEY, - SDL_MapRGB (tmpimage->format, 0, 0, 0)); - gfx.font.image = SDL_DisplayFormat (tmpimage); - gfx.font.size.x = 16; - gfx.font.size.y = 16; - SDL_FreeSurface (tmpimage); - - /* load the font */ - sprintf (filename, "%s/gfx/font1.bmp", bman.datapath); - tmpimage = SDL_LoadBMP (filename); - if (tmpimage == NULL) { - printf ("Can't load image: %s\n", SDL_GetError ()); - exit (1); - } - SDL_SetColorKey (tmpimage, SDL_SRCCOLORKEY, - SDL_MapRGB (tmpimage->format, 0, 0, 0)); - gfx.font1.image = SDL_DisplayFormat (tmpimage); - gfx.font1.size.x = 16; - gfx.font1.size.y = 16; - SDL_FreeSurface (tmpimage); - - /* load the logo */ - sprintf (filename, "%s/gfx/logo.bmp", bman.datapath); - tmpimage = SDL_LoadBMP (filename); - if (tmpimage == NULL) { - printf ("Can't load image: %s\n", SDL_GetError ()); - exit (1); - } - tmpimage1 = scale_image (tmpimage, gfx.res.x, gfx.res.y); - SDL_FreeSurface (tmpimage); - SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY, - SDL_MapRGB (tmpimage1->format, 255, 255, 0)); - gfx.logo = SDL_DisplayFormat (tmpimage1); - SDL_FreeSurface (tmpimage1); - - /* load the menuselector */ - sprintf (filename, "%s/gfx/menuselect.bmp", bman.datapath); - tmpimage = SDL_LoadBMP (filename); - if (tmpimage == NULL) { - printf ("Can't load image: %s\n", SDL_GetError ()); - exit (1); - } - gfx.menuselect.frames = tmpimage->h / GFX_IMGSIZE; - tmpimage1 = scale_image (tmpimage, gfx.font.size.x, gfx.menuselect.frames * gfx.font.size.y); - getRGBpixel (tmpimage1, 0, 0, &r, &g, &b); - SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY,SDL_MapRGB (tmpimage1->format, r, g, b)); - gfx.menuselect.image = SDL_DisplayFormat (tmpimage1); - SDL_FreeSurface (tmpimage); - SDL_FreeSurface (tmpimage1); -}; - -void -gfx_shutdown () -{ - int i; - - for (i = 0; i < FT_max; i++) - SDL_FreeSurface (gfx.field[i].image); - - for (i = 0; i < MAX_PLAYERS; i++) - SDL_FreeSurface (gfx.players[i].ani.image); - - SDL_FreeSurface (gfx.font.image); - SDL_FreeSurface (gfx.font1.image); - SDL_FreeSurface (gfx.logo); - SDL_FreeSurface (gfx.bomb.image); - SDL_FreeSurface (gfx.fire.image); - SDL_FreeSurface (gfx.menuselect.image); - - gfx.screen = SDL_SetVideoMode (gfx.res.x, gfx.res.y, 16, - SDL_HWSURFACE | SDL_DOUBLEBUF); - - SDL_FreeSurface (gfx.screen); -} - -void -gfx_AddUpdateRect (int x, int y, int w, int h) -{ - if (UpdateRects_nr >= MAX_UPDATERECTS) - return; - - UpdateRects[UpdateRects_nr].x = x; - UpdateRects[UpdateRects_nr].y = y; - UpdateRects[UpdateRects_nr].w = w; - UpdateRects[UpdateRects_nr].h = h; - - UpdateRects_nr++; -} - - -void -gfx_UpdateRects () -{ - if (UpdateRects_nr > 0) - SDL_UpdateRects (gfx.screen, UpdateRects_nr, UpdateRects); - UpdateRects_nr = 0; - -} - -void draw_logo () { - - SDL_BlitSurface (gfx.logo, NULL, gfx.screen, NULL); - - UpdateRects_nr = 0; - gfx_AddUpdateRect (0,0,gfx.screen->w, gfx.screen->h); -} - - -void redraw_logo_shaded (int x, int y, int w, int h, int c) { - - SDL_Rect dest; - - dest.w = w; - dest.h = h; - dest.x = x; - dest.y = y; - - redraw_logo (x, y, w+1, h+1); - - if (gfx_locksurface (gfx.screen)) - return; - - dest.h += dest.y; - dest.w += dest.x; - - draw_shadefield (gfx.screen, &dest, c); - - gfx_unlocksurface (gfx.screen); -}; - - -void redraw_logo (int x, int y, int w, int h) { - - SDL_Rect src, dest; - - dest.w = src.w = w; - dest.h = src.h = h; - - dest.x = x; - dest.y = y; - - src.x = x; - src.y = y; - - SDL_BlitSurface (gfx.logo, &src, gfx.screen, &dest); - -// gfx_AddUpdateRect (); -}; - -void -shade_pixel(SDL_Surface *s, int x, int y, int c) { - Uint32 p; - Uint8 r,g,b; - - p = getpixel(s,x,y); - - SDL_GetRGB(p, s->format, &r, &g, &b); - - if (c > 0) { - if (((Sint16) r) + c < 256) {r += c;} else r = 255; - if (((Sint16) g) + c < 256) {g += c;} else g = 255; - if (((Sint16) b) + c < 256) {b += c;} else b = 255; - } - else { - if (((Sint16) r) + c > 0) {r += c;} else r = 0; - if (((Sint16) g) + c > 0) {g += c;} else g = 0; - if (((Sint16) b) + c > 0) {b += c;} else b = 0; - } - - p = SDL_MapRGB(s->format, r, g, b); - - putpixel(s,x,y,p); -} - -int gfx_locksurface (SDL_Surface *surface) { - if ( SDL_MUSTLOCK(surface) ) - if ( SDL_LockSurface(surface) < 0 ) { - fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError()); - return -1; - } - return 0; -}; - - -void gfx_unlocksurface (SDL_Surface *surface) { - if ( SDL_MUSTLOCK(surface) ) { - SDL_UnlockSurface(surface); - } -}; - - -void -draw_shadefield (SDL_Surface *s, SDL_Rect *rec, int c) { - int x1, x, x2, y1, y; - - if (rec->x > rec->w) { - x1 = rec->w; - x2 = rec->x; - } - else { - x2 = rec->w; - x1 = rec->x; - } - - if (rec->y > rec->h) { - y = rec->h; - y1 = rec->y; - } - else { - y1 = rec->h; - y = rec->y; - } - - for (;y <= y1;y++) - for (x = x1 ;x <= x2;x++) - shade_pixel(s, x, y, c); -}; - - -SDL_Surface *gfx_copyscreen (SDL_Rect *wnd) { - SDL_Surface *res; - SDL_Rect dest; - - res = SDL_CreateRGBSurface(SDL_HWSURFACE, wnd->w, wnd->h, gfx.screen->format->BitsPerPixel, gfx.screen->format->Rmask, gfx.screen->format->Gmask, gfx.screen->format->Bmask, gfx.screen->format->Amask); - - dest.x = 0; - dest.y = 0; - dest.w = wnd->w; - dest.h = wnd->h; - - SDL_BlitSurface (gfx.screen, wnd, res, &dest); - return res; -}; - - -void gfx_load_tileset (char *tilesetname) { - int i, - r, - g, - b; - - char filename[LEN_PATHFILENAME]; - char tileset[LEN_TILESETNAME]; - SDL_Surface *tmpimage, *tmpimage1; - float sfkt; - - d_printf ("Loading Tileset: %s\n", tilesetname); - strncpy (tileset, tilesetname, LEN_TILESETNAME); - - /* Calculate the Best Size of the Images */ - gfx.block.x = gfx.res.x / (bman.fieldsize.x+1); - gfx.block.y = (gfx.res.y - 80) / (bman.fieldsize.y+1); - - if (gfx.block.x < gfx.block.y) - gfx.block.y = gfx.block.x; - else - gfx.block.x = gfx.block.y; - - /* create Table of points */ - scale (gfx.postab, gfx.block.x, 256); - sfkt = ((float) gfx.block.x) / ((float) GFX_IMGSIZE); - - /* calculating the best offset for the field on the screen */ - gfx.offset.x = (gfx.res.x - (gfx.block.x * bman.fieldsize.x)) / 2; - gfx.offset.y = gfx.res.y - (gfx.block.y * bman.fieldsize.y); - - /* load the fire */ - sprintf (filename, "%s/tileset/%s/fire.bmp", bman.datapath,tileset); - tmpimage = SDL_LoadBMP (filename); - if (tmpimage == NULL) { - /* file could not be load, so load teh default tileset */ - printf ("Can't load tileset: %s\n", SDL_GetError ()); - if (strcmp (tileset, "default") != 0) { - strcpy (tileset, "default"); - sprintf (filename, "%s/tileset/%s/fire.bmp", bman.datapath,tileset); - tmpimage = SDL_LoadBMP (filename); - if (tmpimage == NULL) { - printf ("default tileset could not be loaded.\n"); - exit (1); - } - else - printf ("switching to default tileset.\n"); - } - else exit (1); - } - gfx.fire.frames = tmpimage->h / GFX_IMGSIZE; - tmpimage1 = scale_image (tmpimage, (tmpimage->w / GFX_IMGSIZE) * gfx.block.x, gfx.fire.frames * gfx.block.y); - getRGBpixel (tmpimage1, 0, 0, &r, &g, &b); - SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY,SDL_MapRGB (tmpimage1->format, r, g, b)); - gfx.fire.image = SDL_DisplayFormat (tmpimage1); - SDL_FreeSurface (tmpimage); - SDL_FreeSurface (tmpimage1); - - /* load the bomb */ - sprintf (filename, "%s/tileset/%s/bomb.bmp", bman.datapath, tileset); - tmpimage = SDL_LoadBMP (filename); - if (tmpimage == NULL) { - printf ("Can't load image: %s\n", SDL_GetError ()); - exit (1); - } - gfx.bomb.frames = tmpimage->h / GFX_IMGSIZE; - tmpimage1 = scale_image (tmpimage, (tmpimage->w / GFX_IMGSIZE) * gfx.block.x, gfx.bomb.frames * gfx.block.y); - getRGBpixel (tmpimage1, 0, 0, &r, &g, &b); - SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY,SDL_MapRGB (tmpimage1->format, r, g, b)); - gfx.bomb.image = SDL_DisplayFormat (tmpimage1); - SDL_FreeSurface (tmpimage); - SDL_FreeSurface (tmpimage1); - - /* loading the field images */ - for (i = 0; i < FT_max; i++) { - switch (i) { - case (FT_nothing): - sprintf (filename, "%s/tileset/%s/background.bmp", bman.datapath, tileset); - break; - case (FT_stone): - sprintf (filename, "%s/tileset/%s/stone.bmp", bman.datapath, tileset); - break; - case (FT_block): - sprintf (filename, "%s/tileset/%s/block.bmp", bman.datapath, tileset); - break; - case (FT_death): - sprintf (filename, "%s/tileset/%s/fielddeath.bmp", bman.datapath, tileset); - break; - case (FT_bomb): - sprintf (filename, "%s/tileset/%s/fieldbomb.bmp", bman.datapath, tileset); - break; - case (FT_fire): - sprintf (filename, "%s/tileset/%s/fieldfire.bmp", bman.datapath, tileset); - break; - case (FT_shoe): - sprintf (filename, "%s/tileset/%s/fieldshoe.bmp", bman.datapath, tileset); - break; - } - - tmpimage = SDL_LoadBMP (filename); - if (tmpimage == NULL) { - printf ("Can't load image: %s\n", SDL_GetError ()); - exit (1); - } - gfx.field[i].frames = tmpimage->h / GFX_IMGSIZE; - tmpimage1 = scale_image (tmpimage, (tmpimage->w / GFX_IMGSIZE) * gfx.block.x, gfx.field[i].frames * gfx.block.y); - SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY,SDL_MapRGB (tmpimage1->format, 255, 255, 255)); - gfx.field[i].image = SDL_DisplayFormat (tmpimage1); - SDL_FreeSurface (tmpimage); - SDL_FreeSurface (tmpimage1); - } - - UpdateRects_nr = 0; -}; - - -void gfx_free_tileset () { - int i; - - for (i = 0; i < FT_max; i++) { - if (gfx.field[i].image != NULL) - SDL_FreeSurface (gfx.field[i].image); - gfx.field[i].image = NULL; - } - - if (gfx.bomb.image != NULL) - SDL_FreeSurface (gfx.bomb.image); - - if (gfx.fire.image != NULL) - SDL_FreeSurface (gfx.fire.image); - - gfx.bomb.image = NULL; - gfx.fire.image = NULL; -}; - +/* gfx.c */ + +#include +#include "bomberclone.h" +#include "gfx.h" + +int UpdateRects_nr = 0; +SDL_Rect UpdateRects[MAX_UPDATERECTS]; + +_gfx gfx; +void +getRGBpixel (SDL_Surface * surface, int x, int y, int *R, int *G, int *B) +{ + Uint32 pixel = 0; + Uint8 r, + g, + b; + + /* Lock the screen for direct access to the pixels */ + if (SDL_MUSTLOCK (surface)) + if (SDL_LockSurface (surface) < 0) { + fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ()); + return; + } + pixel = getpixel (surface, x, y); + if (SDL_MUSTLOCK (surface)) { + SDL_UnlockSurface (surface); + } + SDL_GetRGB (pixel, surface->format, &r, &g, &b); + *R = r; + *G = g; + *B = b; +}; + + +Uint32 +getpixel (SDL_Surface * surface, int x, int y) +{ + int bpp = surface->format->BytesPerPixel; + + /* Here p is the address to the pixel we want to retrieve */ + Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * bpp; + switch (bpp) { + case 1: + return *p; + case 2: + return *(Uint16 *) p; + case 3: + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) + return p[0] << 16 | p[1] << 8 | p[2]; + + else + return p[0] | p[1] << 8 | p[2] << 16; + case 4: + return *(Uint32 *) p; + default: + return 0; /* shouldn't happen, but avoids warnings */ + } +}; + + +void +putpixel (SDL_Surface * surface, int x, int y, Uint32 pixel) +{ + int bpp = surface->format->BytesPerPixel; + + /* Here p is the address to the pixel we want to set */ + Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * bpp; + switch (bpp) { + case 1: + *p = pixel; + break; + case 2: + *(Uint16 *) p = pixel; + break; + case 3: + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { + p[0] = (pixel >> 16) & 0xff; + p[1] = (pixel >> 8) & 0xff; + p[2] = pixel & 0xff; + } + else { + p[0] = pixel & 0xff; + p[1] = (pixel >> 8) & 0xff; + p[2] = (pixel >> 16) & 0xff; + } + break; + case 4: + *(Uint32 *) p = pixel; + break; + } +}; + + +void +scale (short int *dpattern, short int x, short int y) +{ + int a, + dx, + dy; + if (x >= SCALE_MAXRES || y >= SCALE_MAXRES) { + for (x = 0; x < SCALE_MAXRES; x++) + dpattern[x] = 0; + return; + } + if (x > y) { + dy = 2 * y; + dx = a = 2 * x - dy; + + do { + if (a <= 0) { + dpattern[(y--) - 1] = x; + a = a + dx; + } + + else + a = a - dy; + } while (x--); + } + + else { + dy = 2 * x; + dx = a = 2 * y - dy; + + do { + dpattern[y] = x; + if (a <= 0) { + x--; + a = a + dx; + } + + else + a = a - dy; + } while (y--); + } +}; + + +SDL_Surface * +scale_image (SDL_Surface * orginal, int newx, int newy) +{ + Uint32 rmask, + gmask, + bmask, + amask; + SDL_Surface *surface; + int y, + x; + short int xpattern[SCALE_MAXRES]; + short int ypattern[SCALE_MAXRES]; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + rmask = 0xff000000; + gmask = 0x00ff0000; + bmask = 0x0000ff00; + amask = 0x000000ff; + +#else /* */ + rmask = 0x00ff0000; + gmask = 0x0000ff00; + bmask = 0x000000ff; + amask = 0xff000000; + +#endif /* */ + surface = SDL_CreateRGBSurface (SDL_SWSURFACE, newx, newy, 32, rmask, gmask, bmask, amask); + if (surface == NULL) { + fprintf (stderr, "CreateRGBSurface failed: %s\n", SDL_GetError ()); + return NULL; + } + + /* Lock the screen for direct access to the pixels */ + if (SDL_MUSTLOCK (surface)) + if (SDL_LockSurface (surface) < 0) { + fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ()); + return NULL; + } + if (SDL_MUSTLOCK (orginal)) + if (SDL_LockSurface (orginal) < 0) { + fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ()); + if (SDL_MUSTLOCK (surface)) { + SDL_UnlockSurface (surface); + } + return NULL; + } + + /* do the scaling work */ + scale (xpattern, orginal->w - 1, newx); + scale (ypattern, orginal->h - 1, newy); + for (x = newx - 1; x >= 0; x--) + for (y = newy - 1; y >= 0; y--) + putpixel (surface, x, y, getpixel (orginal, xpattern[x], ypattern[y])); + if (SDL_MUSTLOCK (orginal)) { + SDL_UnlockSurface (orginal); + } + if (SDL_MUSTLOCK (surface)) { + SDL_UnlockSurface (surface); + } + return surface; +}; + +SDL_Surface * +makegray_image (SDL_Surface * org) +{ + Uint32 rmask, + gmask, + bmask, + amask; + Uint32 pixel, + transpixel = 0; + SDL_Surface *dest; + int y, + x; + Uint8 r, + g, + b, + gray; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + rmask = 0xff000000; + gmask = 0x00ff0000; + bmask = 0x0000ff00; + amask = 0x000000ff; + +#else /* */ + rmask = 0x00ff0000; + gmask = 0x0000ff00; + bmask = 0x000000ff; + amask = 0xff000000; + +#endif /* */ + dest = SDL_CreateRGBSurface (SDL_SWSURFACE, org->w, org->h, 32, rmask, gmask, bmask, amask); + if (dest == NULL) { + fprintf (stderr, "CreateRGBSurface failed: %s\n", SDL_GetError ()); + return NULL; + } + + /* Lock the screen for direct access to the pixels */ + if (SDL_MUSTLOCK (dest)) + if (SDL_LockSurface (dest) < 0) { + fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ()); + return NULL; + } + if (SDL_MUSTLOCK (org)) + if (SDL_LockSurface (org) < 0) { + fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ()); + if (SDL_MUSTLOCK (dest)) { + SDL_UnlockSurface (dest); + } + return NULL; + } + for (x = 0; x < org->w; x++) + for (y = 0; y < org->h; y++) { + pixel = getpixel (org, x, y); + if (x == 0 && y == 0) + transpixel = pixel; + if (pixel != transpixel) { + SDL_GetRGB (pixel, org->format, &r, &g, &b); + gray = (r / 3 + g / 3 + b / 3); + pixel = SDL_MapRGB (dest->format, gray, gray, gray); + } + putpixel (dest, x, y, pixel); + } + if (SDL_MUSTLOCK (org)) { + SDL_UnlockSurface (org); + } + if (SDL_MUSTLOCK (dest)) { + SDL_UnlockSurface (dest); + } + SDL_SetColorKey (dest, SDL_SRCCOLORKEY, transpixel); + return dest; +}; + + +#define __smalsizeX 12 +void +gfx_load_players (int sx, int sy) +{ + float sfkt, + ssfkt; + char filename[255]; + int i, + j, + r, + g, + b; + SDL_Surface *tmpimage, + *tmpimage1; + sfkt = ((float) sx) / ((float) GFX_IMGSIZE); + ssfkt = ((float) __smalsizeX) / ((float) GFX_IMGSIZE); + + /* loading the player images */ + for (j = i = 0; i < MAX_PLAYERS; i++) { + sprintf (filename, "%s/player/player%d.bmp", bman.datapath, j); + j++; + tmpimage = SDL_LoadBMP (filename); + if (tmpimage == NULL) { + if (j == 0) { // try again with the first image, if this don't work give up. + printf ("Can't load image: %s\n", SDL_GetError ()); + exit (1); + } + i--; // load the this image again + j = 0; + } + + else { + + /* load the game player image */ + gfx.players[i].size.y = sy * 2; + gfx.players[i].size.x = (tmpimage->w / 4) * sfkt; + gfx.players[i].ani.frames = tmpimage->h / GFX_PLAYERIMGSIZE_Y; + tmpimage1 = + scale_image (tmpimage, gfx.players[i].size.x * 4, + gfx.players[i].ani.frames * gfx.players[i].size.y); + getRGBpixel (tmpimage1, 0, 0, &r, &g, &b); + SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY, SDL_MapRGB (tmpimage1->format, r, g, b)); + gfx.players[i].ani.image = SDL_DisplayFormat (tmpimage1); + SDL_FreeSurface (tmpimage1); + + /* calculate the numbers of images for the animation */ + gfx.players[i].offset.x = (sx - gfx.players[i].size.x) / 2; + gfx.players[i].offset.y = -sy; + + /* load the smal image */ + gfx.players[i].smal_size.y = __smalsizeX * 2; + gfx.players[i].smal_size.x = (tmpimage->w / 4) * ssfkt; + tmpimage1 = + scale_image (tmpimage, gfx.players[i].smal_size.x * 4, + gfx.players[i].ani.frames * gfx.players[i].smal_size.y); + getRGBpixel (tmpimage1, 0, 0, &r, &g, &b); + SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY, SDL_MapRGB (tmpimage1->format, r, g, b)); + gfx.players[i].smal_image = SDL_DisplayFormat (tmpimage1); + SDL_FreeSurface (tmpimage1); + SDL_FreeSurface (tmpimage); + } + } + + /* load the illnessthing */ + sprintf (filename, "%s/player/playersick.bmp", bman.datapath); + tmpimage = SDL_LoadBMP (filename); + if (tmpimage == NULL) { + printf ("Can't load image: %s\n", SDL_GetError ()); + exit (1); + } + gfx.ill.frames = tmpimage->h / (2 * GFX_IMGSIZE); + tmpimage1 = + scale_image (tmpimage, (tmpimage->w / (2 * GFX_IMGSIZE)) * (2 * sx), + gfx.ill.frames * (2 * sy)); + getRGBpixel (tmpimage1, 0, 0, &r, &g, &b); + SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY, SDL_MapRGB (tmpimage1->format, r, g, b)); + gfx.ill.image = SDL_DisplayFormat (tmpimage1); + SDL_FreeSurface (tmpimage); + SDL_FreeSurface (tmpimage1); +}; + + +/* frees the player images */ +void +gfx_free_players () +{ + int i; + for (i = 0; i < MAX_PLAYERS; i++) { + if (gfx.players[i].ani.image != NULL) + SDL_FreeSurface (gfx.players[i].ani.image); + gfx.players[i].ani.image = NULL; + if (gfx.players[i].smal_image != NULL) + SDL_FreeSurface (gfx.players[i].smal_image); + gfx.players[i].smal_image = NULL; + } + SDL_FreeSurface (gfx.ill.image); +} + + +/* load the images with the right scaleing */ +void +gfx_game_init () +{ + menu_displaytext ("Loading..", "Please Wait", 32, 128, 32); + gfx_load_tileset (gfx.tileset); + gfx_load_players (gfx.block.x, gfx.block.y); +}; + +void +gfx_game_shutdown () +{ + menu_displaytext ("Freeing..", "Please Wait", 32, 128, 32); + gfx_free_players (); + gfx_free_tileset (); +}; + + +/* init the whole GFX Part */ +void +gfx_init () +{ + if (gfx.fullscreen) + gfx.screen = + SDL_SetVideoMode (gfx.res.x, gfx.res.y, gfx.bpp, + SDL_SWSURFACE | SDL_DOUBLEBUF | SDL_HWACCEL | SDL_FULLSCREEN); + + else + gfx.screen = + SDL_SetVideoMode (gfx.res.x, gfx.res.y, gfx.bpp, + SDL_SWSURFACE | SDL_DOUBLEBUF | SDL_HWACCEL); + if (gfx.screen == NULL) { + d_printf ("Unable to set video mode: %s\n", SDL_GetError ()); + return; + } + SDL_ShowCursor (SDL_DISABLE); + gfx_loaddata (); +}; + + + +void +gfx_loaddata () +{ + int r, + g, + b; + char filename[255]; + SDL_Surface *tmpimage, + *tmpimage1; + + /* load the font */ + sprintf (filename, "%s/gfx/font.bmp", bman.datapath); + tmpimage = SDL_LoadBMP (filename); + if (tmpimage == NULL) { + printf ("Can't load image: %s\n", SDL_GetError ()); + exit (1); + } + SDL_SetColorKey (tmpimage, SDL_SRCCOLORKEY, SDL_MapRGB (tmpimage->format, 0, 0, 0)); + gfx.font.image = SDL_DisplayFormat (tmpimage); + gfx.font.size.x = 16; + gfx.font.size.y = 16; + SDL_FreeSurface (tmpimage); + + /* load the font */ + sprintf (filename, "%s/gfx/font1.bmp", bman.datapath); + tmpimage = SDL_LoadBMP (filename); + if (tmpimage == NULL) { + printf ("Can't load image: %s\n", SDL_GetError ()); + exit (1); + } + SDL_SetColorKey (tmpimage, SDL_SRCCOLORKEY, SDL_MapRGB (tmpimage->format, 0, 0, 0)); + gfx.font1.image = SDL_DisplayFormat (tmpimage); + gfx.font1.size.x = 16; + gfx.font1.size.y = 16; + SDL_FreeSurface (tmpimage); + + /* load the logo */ + sprintf (filename, "%s/gfx/logo.bmp", bman.datapath); + tmpimage = SDL_LoadBMP (filename); + if (tmpimage == NULL) { + printf ("Can't load image: %s\n", SDL_GetError ()); + exit (1); + } + tmpimage1 = scale_image (tmpimage, gfx.res.x, gfx.res.y); + SDL_FreeSurface (tmpimage); + SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY, SDL_MapRGB (tmpimage1->format, 255, 255, 0)); + gfx.logo = SDL_DisplayFormat (tmpimage1); + SDL_FreeSurface (tmpimage1); + + /* load the menuselector */ + sprintf (filename, "%s/gfx/menuselect.bmp", bman.datapath); + tmpimage = SDL_LoadBMP (filename); + if (tmpimage == NULL) { + printf ("Can't load image: %s\n", SDL_GetError ()); + exit (1); + } + gfx.menuselect.frames = tmpimage->h / GFX_IMGSIZE; + tmpimage1 = scale_image (tmpimage, gfx.font.size.x, gfx.menuselect.frames * gfx.font.size.y); + getRGBpixel (tmpimage1, 0, 0, &r, &g, &b); + SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY, SDL_MapRGB (tmpimage1->format, r, g, b)); + gfx.menuselect.image = SDL_DisplayFormat (tmpimage1); + SDL_FreeSurface (tmpimage); + SDL_FreeSurface (tmpimage1); +}; + + +void +gfx_shutdown () +{ + int i; + for (i = 0; i < FT_max; i++) + SDL_FreeSurface (gfx.field[i].image); + for (i = 0; i < MAX_PLAYERS; i++) + SDL_FreeSurface (gfx.players[i].ani.image); + SDL_FreeSurface (gfx.font.image); + SDL_FreeSurface (gfx.font1.image); + SDL_FreeSurface (gfx.logo); + SDL_FreeSurface (gfx.bomb.image); + SDL_FreeSurface (gfx.fire.image); + SDL_FreeSurface (gfx.menuselect.image); + gfx.screen = SDL_SetVideoMode (gfx.res.x, gfx.res.y, 16, SDL_HWSURFACE | SDL_DOUBLEBUF); + SDL_FreeSurface (gfx.screen); +}; + + +void +gfx_AddUpdateRect (int x, int y, int w, int h) +{ + if (UpdateRects_nr >= MAX_UPDATERECTS) + return; + UpdateRects[UpdateRects_nr].x = x; + UpdateRects[UpdateRects_nr].y = y; + UpdateRects[UpdateRects_nr].w = w; + UpdateRects[UpdateRects_nr].h = h; + UpdateRects_nr++; +}; + + +void +gfx_UpdateRects () +{ + if (UpdateRects_nr > 0) + SDL_UpdateRects (gfx.screen, UpdateRects_nr, UpdateRects); + UpdateRects_nr = 0; +}; + + +void +draw_logo () +{ + SDL_BlitSurface (gfx.logo, NULL, gfx.screen, NULL); + UpdateRects_nr = 0; + gfx_AddUpdateRect (0, 0, gfx.screen->w, gfx.screen->h); +}; + + +void +redraw_logo_shaded (int x, int y, int w, int h, int c) +{ + SDL_Rect dest; + dest.w = w; + dest.h = h; + dest.x = x; + dest.y = y; + redraw_logo (x, y, w + 1, h + 1); + if (gfx_locksurface (gfx.screen)) + return; + dest.h += dest.y; + dest.w += dest.x; + draw_shadefield (gfx.screen, &dest, c); + gfx_unlocksurface (gfx.screen); +}; + + +void +redraw_logo (int x, int y, int w, int h) +{ + SDL_Rect src, + dest; + dest.w = src.w = w; + dest.h = src.h = h; + dest.x = x; + dest.y = y; + src.x = x; + src.y = y; + SDL_BlitSurface (gfx.logo, &src, gfx.screen, &dest); +}; + + + +void +shade_pixel (SDL_Surface * s, int x, int y, int c) +{ + Uint32 p; + Uint8 r, + g, + b; + p = getpixel (s, x, y); + SDL_GetRGB (p, s->format, &r, &g, &b); + if (c > 0) { + if (((Sint16) r) + c < 256) { + r += c; + } + else + r = 255; + if (((Sint16) g) + c < 256) { + g += c; + } + else + g = 255; + if (((Sint16) b) + c < 256) { + b += c; + } + else + b = 255; + } + + else { + if (((Sint16) r) + c > 0) { + r += c; + } + else + r = 0; + if (((Sint16) g) + c > 0) { + g += c; + } + else + g = 0; + if (((Sint16) b) + c > 0) { + b += c; + } + else + b = 0; + } + p = SDL_MapRGB (s->format, r, g, b); + putpixel (s, x, y, p); +}; + + +int +gfx_locksurface (SDL_Surface * surface) +{ + if (SDL_MUSTLOCK (surface)) + if (SDL_LockSurface (surface) < 0) { + fprintf (stderr, "Can't lock screen: %s\n", SDL_GetError ()); + return -1; + } + return 0; +}; + + + +void +gfx_unlocksurface (SDL_Surface * surface) +{ + if (SDL_MUSTLOCK (surface)) { + SDL_UnlockSurface (surface); + } +}; + + +void +draw_shadefield (SDL_Surface * s, SDL_Rect * rec, int c) +{ + int x1, + x, + x2, + y1, + y; + if (rec->x > rec->w) { + x1 = rec->w; + x2 = rec->x; + } + + else { + x2 = rec->w; + x1 = rec->x; + } + if (rec->y > rec->h) { + y = rec->h; + y1 = rec->y; + } + + else { + y1 = rec->h; + y = rec->y; + } + for (; y <= y1; y++) + for (x = x1; x <= x2; x++) + shade_pixel (s, x, y, c); +}; + + +SDL_Surface * +gfx_copyscreen (SDL_Rect * wnd) +{ + SDL_Surface *res; + SDL_Rect dest; + res = + SDL_CreateRGBSurface (SDL_HWSURFACE, wnd->w, wnd->h, gfx.screen->format->BitsPerPixel, + gfx.screen->format->Rmask, gfx.screen->format->Gmask, + gfx.screen->format->Bmask, gfx.screen->format->Amask); + dest.x = 0; + dest.y = 0; + dest.w = wnd->w; + dest.h = wnd->h; + SDL_BlitSurface (gfx.screen, wnd, res, &dest); + return res; +}; +void +gfx_load_tileset (char *tilesetname) +{ + int i, + r, + g, + b; + char filename[LEN_PATHFILENAME]; + char tileset[LEN_TILESETNAME]; + SDL_Surface *tmpimage, + *tmpimage1; + float sfkt; + d_printf ("Loading Tileset: %s\n", tilesetname); + strncpy (tileset, tilesetname, LEN_TILESETNAME); + + /* Calculate the Best Size of the Images */ + gfx.block.x = gfx.res.x / (bman.fieldsize.x + 1); + gfx.block.y = (gfx.res.y - 80) / (bman.fieldsize.y + 1); + if (gfx.block.x < gfx.block.y) + gfx.block.y = gfx.block.x; + + else + gfx.block.x = gfx.block.y; + + /* create Table of points */ + scale (gfx.postab, gfx.block.x, 256); + sfkt = ((float) gfx.block.x) / ((float) GFX_IMGSIZE); + + /* calculating the best offset for the field on the screen */ + gfx.offset.x = (gfx.res.x - (gfx.block.x * bman.fieldsize.x)) / 2; + gfx.offset.y = gfx.res.y - (gfx.block.y * bman.fieldsize.y); + + /* load the fire */ + sprintf (filename, "%s/tileset/%s/fire.bmp", bman.datapath, tileset); + tmpimage = SDL_LoadBMP (filename); + if (tmpimage == NULL) { + + /* file could not be load, so load teh default tileset */ + printf ("Can't load tileset: %s\n", SDL_GetError ()); + if (strcmp (tileset, "default") != 0) { + strcpy (tileset, "default"); + sprintf (filename, "%s/tileset/%s/fire.bmp", bman.datapath, tileset); + tmpimage = SDL_LoadBMP (filename); + if (tmpimage == NULL) { + printf ("default tileset could not be loaded.\n"); + exit (1); + } + + else + printf ("switching to default tileset.\n"); + } + + else + exit (1); + } + gfx.fire.frames = tmpimage->h / GFX_IMGSIZE; + tmpimage1 = + scale_image (tmpimage, (tmpimage->w / GFX_IMGSIZE) * gfx.block.x, + gfx.fire.frames * gfx.block.y); + getRGBpixel (tmpimage1, 0, 0, &r, &g, &b); + SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY, SDL_MapRGB (tmpimage1->format, r, g, b)); + gfx.fire.image = SDL_DisplayFormat (tmpimage1); + SDL_FreeSurface (tmpimage); + SDL_FreeSurface (tmpimage1); + + /* load the bomb */ + sprintf (filename, "%s/tileset/%s/bomb.bmp", bman.datapath, tileset); + tmpimage = SDL_LoadBMP (filename); + if (tmpimage == NULL) { + printf ("Can't load image: %s\n", SDL_GetError ()); + exit (1); + } + gfx.bomb.frames = tmpimage->h / GFX_IMGSIZE; + tmpimage1 = + scale_image (tmpimage, (tmpimage->w / GFX_IMGSIZE) * gfx.block.x, + gfx.bomb.frames * gfx.block.y); + getRGBpixel (tmpimage1, 0, 0, &r, &g, &b); + SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY, SDL_MapRGB (tmpimage1->format, r, g, b)); + gfx.bomb.image = SDL_DisplayFormat (tmpimage1); + SDL_FreeSurface (tmpimage); + SDL_FreeSurface (tmpimage1); + + /* loading the field images */ + for (i = 0; i < FT_max; i++) { + switch (i) { + case (FT_nothing): + sprintf (filename, "%s/tileset/%s/background.bmp", bman.datapath, tileset); + break; + case (FT_stone): + sprintf (filename, "%s/tileset/%s/stone.bmp", bman.datapath, tileset); + break; + case (FT_block): + sprintf (filename, "%s/tileset/%s/block.bmp", bman.datapath, tileset); + break; + case (FT_death): + sprintf (filename, "%s/tileset/%s/fielddeath.bmp", bman.datapath, tileset); + break; + case (FT_bomb): + sprintf (filename, "%s/tileset/%s/fieldbomb.bmp", bman.datapath, tileset); + break; + case (FT_fire): + sprintf (filename, "%s/tileset/%s/fieldfire.bmp", bman.datapath, tileset); + break; + case (FT_shoe): + sprintf (filename, "%s/tileset/%s/fieldshoe.bmp", bman.datapath, tileset); + break; + } + tmpimage = SDL_LoadBMP (filename); + if (tmpimage == NULL) { + printf ("Can't load image: %s\n", SDL_GetError ()); + exit (1); + } + gfx.field[i].frames = tmpimage->h / GFX_IMGSIZE; + tmpimage1 = scale_image (tmpimage, (tmpimage->w / GFX_IMGSIZE) * gfx.block.x, + gfx.field[i].frames * gfx.block.y); + SDL_SetColorKey (tmpimage1, SDL_SRCCOLORKEY, SDL_MapRGB (tmpimage1->format, 255, 255, 255)); + gfx.field[i].image = SDL_DisplayFormat (tmpimage1); + SDL_FreeSurface (tmpimage); + SDL_FreeSurface (tmpimage1); + } + UpdateRects_nr = 0; +}; + + +void +gfx_free_tileset () +{ + int i; + for (i = 0; i < FT_max; i++) { + if (gfx.field[i].image != NULL) + SDL_FreeSurface (gfx.field[i].image); + gfx.field[i].image = NULL; + } + if (gfx.bomb.image != NULL) + SDL_FreeSurface (gfx.bomb.image); + if (gfx.fire.image != NULL) + SDL_FreeSurface (gfx.fire.image); + gfx.bomb.image = NULL; + gfx.fire.image = NULL; +}; diff --git a/src/gfx.h b/src/gfx.h index cd5160c..508ad11 100644 --- a/src/gfx.h +++ b/src/gfx.h @@ -1,95 +1,95 @@ -#ifndef _GFX_H_ - -#define _GFX_H_ - -#define SCALE_MAXRES 10000 -#define GFX_IMGSIZE 64 -#define GFX_PLAYERIMGSIZE_Y 128 - -#include "basic.h" - -struct __gfxani { - SDL_Surface *image; - int frames; // how many single frames (image -> heigh / (1.5 * gamestyle.height)) -} typedef _gfxani; - - -struct __gfxplayer { - _gfxani ani; - _point offset; - _point size; // height of the image.. needed for faster access. - _point smal_size; // smal size of the image - SDL_Surface *smal_image; // smal size of the animation -} typedef _gfxplayer; - - -struct __gfxfont { - SDL_Surface *image; - _point size; -} typedef _gfxfont; - - -struct __gfx { - SDL_Surface *screen; - _point res; // resolution - _point block; // block size - short int bpp; // bits per pixel - - unsigned char fullscreen; - - _point offset; // where the game field starts - - _gfxfont font; - _gfxfont font1; - - _gfxplayer players[MAX_PLAYERS]; - short int postab[256]; // table of points where we need to go to. - - _gfxani field[FT_max]; // the field animations - _gfxani fire; // fire (explostion) - _gfxani bomb; // bomb animation - _gfxani ill; // sick animation above the player - - _gfxani menuselect; // The Menu Select GFX (the bomb ?) - - int random_tileset; // random selecting of a tileset - char tileset[LEN_TILESETNAME]; // name of the tileset - - SDL_Surface *logo; -} typedef _gfx; - -extern _gfx gfx; - - -// everything what is in gfx.c -extern void gfx_loaddata (); -extern void gfx_UpdateRects (); -extern void gfx_AddUpdateRect (int x, int y, int w, int h); -extern void redraw_logo (int x, int y, int w, int h); -extern void draw_logo (); -extern void gfx_init (); // Load Base Image Data -extern void gfx_game_init (); // Load Game Data -extern void gfx_game_shutdown (); // Free Image Data -extern void gfx_shutdown (); // -extern void getRGBpixel (SDL_Surface *surface, int x, int y, int *R, int *G, int *B); -extern Uint32 getpixel(SDL_Surface *surface, int x, int y); -extern void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel); -extern void scale (short int *dpattern, short int x, short int y); -extern SDL_Surface *scale_image (SDL_Surface * orginal, int newx, int newy); -extern void shade_pixel(SDL_Surface *s, int x, int y, int c); -extern void draw_shadefield (SDL_Surface *s, SDL_Rect *rec, int c); -extern int gfx_locksurface (SDL_Surface *surface); -extern void gfx_unlocksurface (SDL_Surface *surface); -extern void redraw_logo_shaded (int x, int y, int w, int h, int c); -extern void gfx_load_players (int sx, int sy); -extern void gfx_free_players (); -extern void gfx_load_tileset (char *tileset); -extern void gfx_free_tileset (); -extern SDL_Surface *makegray_image (SDL_Surface *org); -extern SDL_Surface *gfx_copyscreen (SDL_Rect *wnd); - -// declared functions in font.c -extern void draw_text (int x, int y, char *text, int white); - -#endif - +#ifndef _GFX_H_ + +#define _GFX_H_ + +#define SCALE_MAXRES 10000 +#define GFX_IMGSIZE 64 +#define GFX_PLAYERIMGSIZE_Y 128 + +#include "basic.h" + +struct __gfxani { + SDL_Surface *image; + int frames; // how many single frames (image -> heigh / (1.5 * gamestyle.height)) +} typedef _gfxani; + + +struct __gfxplayer { + _gfxani ani; + _point offset; + _point size; // height of the image.. needed for faster access. + _point smal_size; // smal size of the image + SDL_Surface *smal_image; // smal size of the animation +} typedef _gfxplayer; + + +struct __gfxfont { + SDL_Surface *image; + _point size; +} typedef _gfxfont; + + +struct __gfx { + SDL_Surface *screen; + _point res; // resolution + _point block; // block size + short int bpp; // bits per pixel + + unsigned char fullscreen; + + _point offset; // where the game field starts + + _gfxfont font; + _gfxfont font1; + + _gfxplayer players[MAX_PLAYERS]; + short int postab[256]; // table of points where we need to go to. + + _gfxani field[FT_max]; // the field animations + _gfxani fire; // fire (explostion) + _gfxani bomb; // bomb animation + _gfxani ill; // sick animation above the player + + _gfxani menuselect; // The Menu Select GFX (the bomb ?) + + int random_tileset; // random selecting of a tileset + char tileset[LEN_TILESETNAME]; // name of the tileset + + SDL_Surface *logo; +} typedef _gfx; + +extern _gfx gfx; + + +// everything what is in gfx.c +extern void gfx_loaddata (); +extern void gfx_UpdateRects (); +extern void gfx_AddUpdateRect (int x, int y, int w, int h); +extern void redraw_logo (int x, int y, int w, int h); +extern void draw_logo (); +extern void gfx_init (); // Load Base Image Data +extern void gfx_game_init (); // Load Game Data +extern void gfx_game_shutdown (); // Free Image Data +extern void gfx_shutdown (); // +extern void getRGBpixel (SDL_Surface *surface, int x, int y, int *R, int *G, int *B); +extern Uint32 getpixel(SDL_Surface *surface, int x, int y); +extern void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel); +extern void scale (short int *dpattern, short int x, short int y); +extern SDL_Surface *scale_image (SDL_Surface * orginal, int newx, int newy); +extern void shade_pixel(SDL_Surface *s, int x, int y, int c); +extern void draw_shadefield (SDL_Surface *s, SDL_Rect *rec, int c); +extern int gfx_locksurface (SDL_Surface *surface); +extern void gfx_unlocksurface (SDL_Surface *surface); +extern void redraw_logo_shaded (int x, int y, int w, int h, int c); +extern void gfx_load_players (int sx, int sy); +extern void gfx_free_players (); +extern void gfx_load_tileset (char *tileset); +extern void gfx_free_tileset (); +extern SDL_Surface *makegray_image (SDL_Surface *org); +extern SDL_Surface *gfx_copyscreen (SDL_Rect *wnd); + +// declared functions in font.c +extern void draw_text (int x, int y, char *text, int white); + +#endif + diff --git a/src/keybinput.c b/src/keybinput.c index b12269f..e3eec6f 100644 --- a/src/keybinput.c +++ b/src/keybinput.c @@ -1,55 +1,55 @@ -/* keyborad handling for text fields */ - -#include -#include "keybinput.h" - -static int keybinput_oldkey = 0; - -void keybinput_new (_keybinput *ki) { - int i; - - for (i = 0; i < 255; i++) - ki->text[i] = 0; - ki->curpos = 0; - ki->len = 0; -} - - -int keybinput_loop (_keybinput *ki, SDL_Event *event) { - int key = 0, keyu = 0; - - ki->changed = 0; - - if (event->type == SDL_KEYUP) - keybinput_oldkey = 0; - - if (event->type == SDL_KEYDOWN && keybinput_oldkey != event->key.keysym.sym) { - key = keybinput_oldkey = event->key.keysym.sym; - keyu = event->key.keysym.unicode; - - if (key == 8) { // BACKSPACE - if (ki->curpos > 0) { - ki->curpos--; - ki->text[ki->curpos] = 0; - ki->changed = 1; - } - } - else if ((keyu >= 32 && keyu <= 126) || (keyu >= 128 && keyu <= 255)) { // International keyboard support - if (ki->curpos < 255) { - ki->text[ki->curpos++] = event->key.keysym.unicode; - ki->text[ki->curpos] = 0; - ki->changed = 1; - } - } - ki->len = strlen (ki->text); - } - - if (key == SDLK_RETURN) - return 1; - - if (key == SDLK_ESCAPE) - return -1; - - return 0; -} - +/* keyborad handling for text fields */ + +#include +#include "keybinput.h" + +static int keybinput_oldkey = 0; + +void keybinput_new (_keybinput *ki) { + int i; + + for (i = 0; i < 255; i++) + ki->text[i] = 0; + ki->curpos = 0; + ki->len = 0; +} + + +int keybinput_loop (_keybinput *ki, SDL_Event *event) { + int key = 0, keyu = 0; + + ki->changed = 0; + + if (event->type == SDL_KEYUP) + keybinput_oldkey = 0; + + if (event->type == SDL_KEYDOWN && keybinput_oldkey != event->key.keysym.sym) { + key = keybinput_oldkey = event->key.keysym.sym; + keyu = event->key.keysym.unicode; + + if (key == 8) { // BACKSPACE + if (ki->curpos > 0) { + ki->curpos--; + ki->text[ki->curpos] = 0; + ki->changed = 1; + } + } + else if ((keyu >= 32 && keyu <= 126) || (keyu >= 128 && keyu <= 255)) { // International keyboard support + if (ki->curpos < 255) { + ki->text[ki->curpos++] = event->key.keysym.unicode; + ki->text[ki->curpos] = 0; + ki->changed = 1; + } + } + ki->len = strlen (ki->text); + } + + if (key == SDLK_RETURN) + return 1; + + if (key == SDLK_ESCAPE) + return -1; + + return 0; +} + diff --git a/src/keybinput.h b/src/keybinput.h index 58f4687..c9358e3 100644 --- a/src/keybinput.h +++ b/src/keybinput.h @@ -1,15 +1,15 @@ - -#ifndef _KEYBINPUT_H_ -#define _KEYBINPUT_H_ - -struct __keybinput { - char text[255]; - short int curpos; - short int len; - char changed; -} typedef _keybinput; - -extern void keybinput_new (_keybinput *ki); -extern int keybinput_loop (_keybinput *ki, SDL_Event *event); - -#endif + +#ifndef _KEYBINPUT_H_ +#define _KEYBINPUT_H_ + +struct __keybinput { + char text[255]; + short int curpos; + short int len; + char changed; +} typedef _keybinput; + +extern void keybinput_new (_keybinput *ki); +extern int keybinput_loop (_keybinput *ki, SDL_Event *event); + +#endif diff --git a/src/main.c b/src/main.c index e49bba3..da9be3a 100644 --- a/src/main.c +++ b/src/main.c @@ -1,75 +1,75 @@ - -#include "bomberclone.h" -#include "network.h" -#include "gfx.h" -#ifndef _WIN32 - #include "../config.h" -#endif - -_bomberclone bman; // Holds GameData -Uint32 timestamp; // timestamp - -int -main (int argc, char **argv) -{ - int menuselect = 0; - _menu menu[] = { - {0, "Singleplayer"}, - {1, "Multiplayer"}, - {2, "Configuration"}, - {3, "Quit Game"}, - {-1, ""} - }; - char text[255]; - - if (SDL_Init (SDL_INIT_VIDEO) != 0) { - d_printf ("Unable to init SDL: %s\n", SDL_GetError ()); - return (1); - } - - sprintf (text,"Bomberclone %s", VERSION); - SDL_WM_SetCaption(text , NULL); - SDL_EnableUNICODE(1); - - game_init (argv); - d_printf ("\n\n ***** Bomberclone Version %s \n\n",VERSION); - if (ReadConfig()) { - gfx_init (); - menu_get_text ("Please You Playername", bman.playername, LEN_PLAYERNAME-1); - bman.playername[LEN_PLAYERNAME-1] = 0; - } else { - gfx_init (); - if (bman.askplayername) - menu_get_text ("Please You Playername", bman.playername, LEN_PLAYERNAME); - } - ReadPrgArgs (argc, argv); - - sprintf(text,"Welcome to BomberClone"); - while (menuselect != -1 && bman.state != GS_quit) { - - menuselect = menu_loop (text , menu, menuselect); - - switch (menuselect) { - case (0) : // Singleplayer - single_game_new (); - single_create_ai (); - gfx_game_init (); - game_loop (); - gfx_game_shutdown (); - break; - case (1) : // Multiplayer - netmenu(); - break; - case (2) : // Options - configuration (); - break; - case (3) : // Quit - bman.state = GS_quit; - break; - } - } - - gfx_shutdown (); - - return 0; -}; + +#include "bomberclone.h" +#include "network.h" +#include "gfx.h" +#ifndef _WIN32 + #include "../config.h" +#endif + +_bomberclone bman; // Holds GameData +Uint32 timestamp; // timestamp + +int +main (int argc, char **argv) +{ + int menuselect = 0; + _menu menu[] = { + {0, "Singleplayer"}, + {1, "Multiplayer"}, + {2, "Configuration"}, + {3, "Quit Game"}, + {-1, ""} + }; + char text[255]; + + if (SDL_Init (SDL_INIT_VIDEO) != 0) { + d_printf ("Unable to init SDL: %s\n", SDL_GetError ()); + return (1); + } + + sprintf (text,"Bomberclone %s", VERSION); + SDL_WM_SetCaption(text , NULL); + SDL_EnableUNICODE(1); + + game_init (argv); + d_printf ("\n\n ***** Bomberclone Version %s \n\n",VERSION); + if (ReadConfig()) { + gfx_init (); + menu_get_text ("Please You Playername", bman.playername, LEN_PLAYERNAME-1); + bman.playername[LEN_PLAYERNAME-1] = 0; + } else { + gfx_init (); + if (bman.askplayername) + menu_get_text ("Please You Playername", bman.playername, LEN_PLAYERNAME); + } + ReadPrgArgs (argc, argv); + + sprintf(text,"Welcome to BomberClone"); + while (menuselect != -1 && bman.state != GS_quit) { + + menuselect = menu_loop (text , menu, menuselect); + + switch (menuselect) { + case (0) : // Singleplayer + single_game_new (); + single_create_ai (); + gfx_game_init (); + game_loop (); + gfx_game_shutdown (); + break; + case (1) : // Multiplayer + netmenu(); + break; + case (2) : // Options + configuration (); + break; + case (3) : // Quit + bman.state = GS_quit; + break; + } + } + + gfx_shutdown (); + + return 0; +}; diff --git a/src/mapmenu.c b/src/mapmenu.c index 0b8f6d9..efe1c02 100644 --- a/src/mapmenu.c +++ b/src/mapmenu.c @@ -1,233 +1,233 @@ - -/* map/tileset selection menu */ - -#include "bomberclone.h" -#include "gfx.h" - -/* load a random map */ -void map_random () { - _direntry *destart, *de, *desel; - char path[LEN_PATHFILENAME]; - int max, sel; - - sprintf (path, "%s/maps", bman.datapath); - desel = destart = s_getdir (path); - - for (max = 0, de = destart; de != NULL; de = de->next) - if ((de->flags & DF_file) == DF_file) - max++; - - sel = s_random (max); - for (max = 0, de = destart; max <= sel && de != NULL; de = de->next) - if ((de->flags & DF_file) == DF_file) { - desel = de; - max++; - } - - d_printf ("Random Map %s (%d on %d)\n", desel->name, sel, max); - - if (desel != NULL) - sprintf (bman.fieldpath, "%s/maps/%s", bman.datapath, desel->name); -} - - -/* load a random tileset */ -void tileset_random () { - _direntry *destart, *de, *desel; - char path[LEN_PATHFILENAME]; - int max, sel; - - sprintf (path, "%s/tileset", bman.datapath); - desel = destart = s_getdir (path); - - for (max = 0, de = destart; de != NULL; de = de->next) - if (de->name[0] != '.' && (de->flags & DF_dir) == DF_dir) - max++; - - sel = s_random (max); - for (max = 0, de = destart; max <= sel && de != NULL; de = de->next) - if (de->name[0] != '.' && (de->flags & DF_dir) == DF_dir) { - desel = de; - max++; - } - - d_printf ("Random Tileset %s (%d on %d)\n", desel->name, sel, max); - - if (desel != NULL) - strncpy (gfx.tileset, desel->name, LEN_TILESETNAME); - gfx.tileset[LEN_TILESETNAME-1] = 0; -} - - -/* launch the map options menu */ -void mapmenu () -{ - int menuselect = 0; - char text[255], *map, pathname[LEN_PATHFILENAME], size[4]; - - _menu menu[] = { - {0, "Random Map:"}, - {1, "Selected Map:"}, - {2, " Size X:"}, - {3, " Size Y:"}, - {4, "Random Tileset:"}, - {5, "Selected Tileset:"}, - {-2, ""}, - {6, "Return To Previous Manu"}, - {-1, ""} - }; - - while (menuselect != -1) { - - - switch (bman.random_map) { - case (0): - if(bman.fieldpath[0]==0) - sprintf (menu[1].text, "Selected Map: < undefined >"); - else - sprintf (menu[1].text, "Selected Map: %s", getfilename(bman.fieldpath)); - menu[1].index = 1; - sprintf (menu[0].text, "Random Map: OFF"); - menu[2].text[0] = 0; - menu[2].index = -2; - menu[3].text[0] = 0; - menu[3].index = -2; - break; - - case (1): - menu[1].text[0] = 0; - menu[1].index = -2; - sprintf (menu[0].text, "Random Map: random file"); - menu[2].text[0] = 0; - menu[2].index = -2; - menu[3].text[0] = 0; - menu[3].index = -2; - break; - - case (2): - menu[1].text[0] = 0; - menu[1].index = -2; - sprintf (menu[0].text, "Random Map: auto-generated"); - sprintf (menu[2].text, " Size X: %d", bman.fieldsize.x); - menu[2].index = 2; - sprintf (menu[3].text, " Size Y: %d", bman.fieldsize.y); - menu[3].index = 3; - break; - } - - if(gfx.random_tileset) - { - menu[5].text[0] = 0; - menu[5].index = -2; - } - else - { - if(gfx.tileset[0]==0) - sprintf (menu[5].text, "Selected Tileset: < undefined >"); - else - sprintf (menu[5].text, "Selected Tileset: %s", gfx.tileset); - menu[5].index = 5; - } - - if(gfx.random_tileset) - sprintf (menu[4].text, "Random Tileset: random file"); - else - sprintf (menu[4].text, "Random Tileset: OFF"); - - menuselect = menu_loop ("Map Options", menu, menuselect); - - switch (menuselect) { - case (0): // Random Map - bman.random_map = (bman.random_map+2)%3; - break; - - case (1): // Selected Map - sprintf (pathname , "%s/maps", bman.datapath); - map = menu_dir_select ("Select Map", pathname, DF_file); - if (map == NULL) - { - bman.fieldpath[0] = 0; - bman.random_map = 2; - } - else - sprintf (bman.fieldpath, "%s/maps/%s", bman.datapath, map); - break; - - case (2): // Size X - sprintf (text, "Field Size X (%d - %d)", MIN_FIELDSIZE_X, MAX_FIELDSIZE_X); - sprintf (size, "%d", bman.fieldsize.x); - menu_get_text (text, size, 3); - bman.fieldsize.x = atoi (size) | 1; - if (bman.fieldsize.x < MIN_FIELDSIZE_X) - bman.fieldsize.x = MIN_FIELDSIZE_X; - if (bman.fieldsize.x > MAX_FIELDSIZE_X) - bman.fieldsize.x = MAX_FIELDSIZE_X; - break; - - case (3): // Size Y - sprintf (text, "Field Size Y (%d - %d)", MIN_FIELDSIZE_Y, MAX_FIELDSIZE_Y); - sprintf (size, "%d", bman.fieldsize.y); - menu_get_text (text, size, 3); - bman.fieldsize.y = atoi (size) | 1; - if (bman.fieldsize.y < MIN_FIELDSIZE_Y) - bman.fieldsize.y = MIN_FIELDSIZE_Y; - if (bman.fieldsize.y > MAX_FIELDSIZE_Y) - bman.fieldsize.y = MAX_FIELDSIZE_Y; - break; - - case (4): // Random Tileset - if (gfx.random_tileset == 1) - gfx.random_tileset = 0; - else - gfx.random_tileset = 1; - break; - - case (5): // Selected Tileset - sprintf (pathname , "%s/tileset", bman.datapath); - map = menu_dir_select ("Select Tileset", pathname, DF_dir); - if (map == NULL) - { - gfx.tileset[0] = 0; - gfx.random_tileset = 1; - } - else - strcpy (gfx.tileset, map); - break; - - case (6): // Return to previous menu - menuselect = -1; - break; - } - } -} - - -// Return only the file name -char* getfilename(char* path) -{ - int i; - for(i=strlen(path);i>=0;i--) - if(path[i] == '\\' || path[i] == '/') - return path+i+1; - return path; -} - -// Init the game according to options -void init_map_tileset() -{ - switch (bman.random_map) { - case (0): - field_new (bman.fieldpath); - break; - case (1): - map_random (); - field_new (bman.fieldpath); - break; - case (2): - field_new (NULL); - break; - } - - if (gfx.random_tileset) - tileset_random (); -} + +/* map/tileset selection menu */ + +#include "bomberclone.h" +#include "gfx.h" + +/* load a random map */ +void map_random () { + _direntry *destart, *de, *desel; + char path[LEN_PATHFILENAME]; + int max, sel; + + sprintf (path, "%s/maps", bman.datapath); + desel = destart = s_getdir (path); + + for (max = 0, de = destart; de != NULL; de = de->next) + if ((de->flags & DF_file) == DF_file) + max++; + + sel = s_random (max); + for (max = 0, de = destart; max <= sel && de != NULL; de = de->next) + if ((de->flags & DF_file) == DF_file) { + desel = de; + max++; + } + + d_printf ("Random Map %s (%d on %d)\n", desel->name, sel, max); + + if (desel != NULL) + sprintf (bman.fieldpath, "%s/maps/%s", bman.datapath, desel->name); +} + + +/* load a random tileset */ +void tileset_random () { + _direntry *destart, *de, *desel; + char path[LEN_PATHFILENAME]; + int max, sel; + + sprintf (path, "%s/tileset", bman.datapath); + desel = destart = s_getdir (path); + + for (max = 0, de = destart; de != NULL; de = de->next) + if (de->name[0] != '.' && (de->flags & DF_dir) == DF_dir) + max++; + + sel = s_random (max); + for (max = 0, de = destart; max <= sel && de != NULL; de = de->next) + if (de->name[0] != '.' && (de->flags & DF_dir) == DF_dir) { + desel = de; + max++; + } + + d_printf ("Random Tileset %s (%d on %d)\n", desel->name, sel, max); + + if (desel != NULL) + strncpy (gfx.tileset, desel->name, LEN_TILESETNAME); + gfx.tileset[LEN_TILESETNAME-1] = 0; +} + + +/* launch the map options menu */ +void mapmenu () +{ + int menuselect = 0; + char text[255], *map, pathname[LEN_PATHFILENAME], size[4]; + + _menu menu[] = { + {0, "Random Map:"}, + {1, "Selected Map:"}, + {2, " Size X:"}, + {3, " Size Y:"}, + {4, "Random Tileset:"}, + {5, "Selected Tileset:"}, + {-2, ""}, + {6, "Return To Previous Manu"}, + {-1, ""} + }; + + while (menuselect != -1) { + + + switch (bman.random_map) { + case (0): + if(bman.fieldpath[0]==0) + sprintf (menu[1].text, "Selected Map: < undefined >"); + else + sprintf (menu[1].text, "Selected Map: %s", getfilename(bman.fieldpath)); + menu[1].index = 1; + sprintf (menu[0].text, "Random Map: OFF"); + menu[2].text[0] = 0; + menu[2].index = -2; + menu[3].text[0] = 0; + menu[3].index = -2; + break; + + case (1): + menu[1].text[0] = 0; + menu[1].index = -2; + sprintf (menu[0].text, "Random Map: random file"); + menu[2].text[0] = 0; + menu[2].index = -2; + menu[3].text[0] = 0; + menu[3].index = -2; + break; + + case (2): + menu[1].text[0] = 0; + menu[1].index = -2; + sprintf (menu[0].text, "Random Map: auto-generated"); + sprintf (menu[2].text, " Size X: %d", bman.fieldsize.x); + menu[2].index = 2; + sprintf (menu[3].text, " Size Y: %d", bman.fieldsize.y); + menu[3].index = 3; + break; + } + + if(gfx.random_tileset) + { + menu[5].text[0] = 0; + menu[5].index = -2; + } + else + { + if(gfx.tileset[0]==0) + sprintf (menu[5].text, "Selected Tileset: < undefined >"); + else + sprintf (menu[5].text, "Selected Tileset: %s", gfx.tileset); + menu[5].index = 5; + } + + if(gfx.random_tileset) + sprintf (menu[4].text, "Random Tileset: random file"); + else + sprintf (menu[4].text, "Random Tileset: OFF"); + + menuselect = menu_loop ("Map Options", menu, menuselect); + + switch (menuselect) { + case (0): // Random Map + bman.random_map = (bman.random_map+2)%3; + break; + + case (1): // Selected Map + sprintf (pathname , "%s/maps", bman.datapath); + map = menu_dir_select ("Select Map", pathname, DF_file); + if (map == NULL) + { + bman.fieldpath[0] = 0; + bman.random_map = 2; + } + else + sprintf (bman.fieldpath, "%s/maps/%s", bman.datapath, map); + break; + + case (2): // Size X + sprintf (text, "Field Size X (%d - %d)", MIN_FIELDSIZE_X, MAX_FIELDSIZE_X); + sprintf (size, "%d", bman.fieldsize.x); + menu_get_text (text, size, 3); + bman.fieldsize.x = atoi (size) | 1; + if (bman.fieldsize.x < MIN_FIELDSIZE_X) + bman.fieldsize.x = MIN_FIELDSIZE_X; + if (bman.fieldsize.x > MAX_FIELDSIZE_X) + bman.fieldsize.x = MAX_FIELDSIZE_X; + break; + + case (3): // Size Y + sprintf (text, "Field Size Y (%d - %d)", MIN_FIELDSIZE_Y, MAX_FIELDSIZE_Y); + sprintf (size, "%d", bman.fieldsize.y); + menu_get_text (text, size, 3); + bman.fieldsize.y = atoi (size) | 1; + if (bman.fieldsize.y < MIN_FIELDSIZE_Y) + bman.fieldsize.y = MIN_FIELDSIZE_Y; + if (bman.fieldsize.y > MAX_FIELDSIZE_Y) + bman.fieldsize.y = MAX_FIELDSIZE_Y; + break; + + case (4): // Random Tileset + if (gfx.random_tileset == 1) + gfx.random_tileset = 0; + else + gfx.random_tileset = 1; + break; + + case (5): // Selected Tileset + sprintf (pathname , "%s/tileset", bman.datapath); + map = menu_dir_select ("Select Tileset", pathname, DF_dir); + if (map == NULL) + { + gfx.tileset[0] = 0; + gfx.random_tileset = 1; + } + else + strcpy (gfx.tileset, map); + break; + + case (6): // Return to previous menu + menuselect = -1; + break; + } + } +} + + +// Return only the file name +char* getfilename(char* path) +{ + int i; + for(i=strlen(path);i>=0;i--) + if(path[i] == '\\' || path[i] == '/') + return path+i+1; + return path; +} + +// Init the game according to options +void init_map_tileset() +{ + switch (bman.random_map) { + case (0): + field_new (bman.fieldpath); + break; + case (1): + map_random (); + field_new (bman.fieldpath); + break; + case (2): + field_new (NULL); + break; + } + + if (gfx.random_tileset) + tileset_random (); +} diff --git a/src/menu.c b/src/menu.c index 9bf0da0..64d5112 100644 --- a/src/menu.c +++ b/src/menu.c @@ -1,109 +1,109 @@ -/* $Id: menu.c,v 1.17 2003/05/07 21:30:36 stpohle Exp $ */ -/* menu's for the game */ - -#include -#include "bomberclone.h" -#include "gfx.h" - -#define MENU_BG_SHADE_DARK -64 -#define MENU_BG_SHADE_BRIGHT 64 - -/* draws a box size (x,y) */ -void -draw_menubox (int x, int y) -{ - int x1, - x2, - y1, - y2, - i; - SDL_Rect src, - dest; - - x1 = gfx.res.x / 2 - x / 2; - x2 = gfx.res.x / 2 + x / 2; - y1 = gfx.res.y / 2 - y / 2; - y2 = gfx.res.y / 2 + y / 2; - - if (gfx_locksurface (gfx.screen)) - return; - - for (i = 0; i < 2; i++) { - src.x = x1 + i; - src.w = x2 + i; - src.y = y1 + i; - src.h = y2 + i; - draw_shadefield (gfx.screen, &src, MENU_BG_SHADE_BRIGHT); - } - - gfx_unlocksurface (gfx.screen); - - dest.w = src.w = x - 2; - dest.h = src.h = y - 2; - dest.x = src.x = x1 + 2; - dest.y = src.y = y1 + 2; - - redraw_logo_shaded (x1 + 2, y1 + 2, x - 2, y - 2, MENU_BG_SHADE_DARK); -} - -void -draw_menu (char *text, _menu menu[], int *x, int *y) -{ - int last, - maxlen, - x1, - y1, - i; - char vers[20]; - - // count the number of entrys - for (last = 0, maxlen = 0; menu[last].index != -1; last++) - if (strlen (menu[last].text) > maxlen) - maxlen = strlen (menu[last].text); - if (strlen (text) > maxlen) - maxlen = strlen (text); - *x = x1 = gfx.res.x / 2 - ((gfx.font.size.x + (maxlen * (gfx.font.size.x - 2))) / 2); - y1 = gfx.res.y / 2 - ((last + 2) * gfx.font.size.y / 2); - x1 = x1 + gfx.font.size.x; - draw_menubox (maxlen * gfx.font.size.x, (last + 3) * gfx.font.size.y); - draw_text (x1, y1, text, 1); - - *y = y1 = y1 + (gfx.font.size.y * 2); - - for (i = 0; i < last; i++) { - draw_text (x1, y1, menu[i].text, 1); - y1 = y1 + gfx.font.size.y; - } - sprintf (vers, "v%s", VERSION); - draw_text (gfx.res.x - gfx.font.size.x * strlen (vers), gfx.res.y - gfx.font.size.y, vers, 1); -}; - - -void -draw_select (int select, _menu menu[], int x, int y) -{ - SDL_Rect dest, - src; - int last; - - for (last = 0; menu[last].index != -1; last++) - redraw_logo_shaded (x, y + last * gfx.font.size.y, gfx.menuselect.image->w, gfx.menuselect.image->h , MENU_BG_SHADE_DARK); - - dest.x = x; - dest.y = y + select * gfx.font.size.y; - - src.x = 0; - src.y = 0; - src.w = gfx.font.size.x; - src.h = gfx.font.size.y; - - SDL_BlitSurface (gfx.menuselect.image, &src, gfx.screen, &dest); -}; - - -int -menu_loop (char *menutitle, _menu menu[], int lastselect) -{ +/* $Id: menu.c,v 1.18 2003/05/08 14:35:49 stpohle Exp $ */ +/* menu's for the game */ + +#include +#include "bomberclone.h" +#include "gfx.h" + +#define MENU_BG_SHADE_DARK -64 +#define MENU_BG_SHADE_BRIGHT 64 + +/* draws a box size (x,y) */ +void +draw_menubox (int x, int y) +{ + int x1, + x2, + y1, + y2, + i; + SDL_Rect src, + dest; + + x1 = gfx.res.x / 2 - x / 2; + x2 = gfx.res.x / 2 + x / 2; + y1 = gfx.res.y / 2 - y / 2; + y2 = gfx.res.y / 2 + y / 2; + + if (gfx_locksurface (gfx.screen)) + return; + + for (i = 0; i < 2; i++) { + src.x = x1 + i; + src.w = x2 + i; + src.y = y1 + i; + src.h = y2 + i; + draw_shadefield (gfx.screen, &src, MENU_BG_SHADE_BRIGHT); + } + + gfx_unlocksurface (gfx.screen); + + dest.w = src.w = x - 2; + dest.h = src.h = y - 2; + dest.x = src.x = x1 + 2; + dest.y = src.y = y1 + 2; + + redraw_logo_shaded (x1 + 2, y1 + 2, x - 2, y - 2, MENU_BG_SHADE_DARK); +} + +void +draw_menu (char *text, _menu menu[], int *x, int *y) +{ + int last, + maxlen, + x1, + y1, + i; + char vers[20]; + + // count the number of entrys + for (last = 0, maxlen = 0; menu[last].index != -1; last++) + if (strlen (menu[last].text) > maxlen) + maxlen = strlen (menu[last].text); + if (strlen (text) > maxlen) + maxlen = strlen (text); + *x = x1 = gfx.res.x / 2 - ((gfx.font.size.x + (maxlen * (gfx.font.size.x - 2))) / 2); + y1 = gfx.res.y / 2 - ((last + 2) * gfx.font.size.y / 2); + x1 = x1 + gfx.font.size.x; + draw_menubox (maxlen * gfx.font.size.x, (last + 3) * gfx.font.size.y); + draw_text (x1, y1, text, 1); + + *y = y1 = y1 + (gfx.font.size.y * 2); + + for (i = 0; i < last; i++) { + draw_text (x1, y1, menu[i].text, 1); + y1 = y1 + gfx.font.size.y; + } + sprintf (vers, "v%s", VERSION); + draw_text (gfx.res.x - gfx.font.size.x * strlen (vers), gfx.res.y - gfx.font.size.y, vers, 1); +}; + + +void +draw_select (int select, _menu menu[], int x, int y) +{ + SDL_Rect dest, + src; + int last; + + for (last = 0; menu[last].index != -1; last++) + redraw_logo_shaded (x, y + last * gfx.font.size.y, gfx.menuselect.image->w, gfx.menuselect.image->h , MENU_BG_SHADE_DARK); + + dest.x = x; + dest.y = y + select * gfx.font.size.y; + + src.x = 0; + src.y = 0; + src.w = gfx.font.size.x; + src.h = gfx.font.size.y; + + SDL_BlitSurface (gfx.menuselect.image, &src, gfx.screen, &dest); +}; + + +int +menu_loop (char *menutitle, _menu menu[], int lastselect) +{ int menuselect = lastselect, done = 0, ds=0, @@ -175,309 +175,309 @@ menu_loop (char *menutitle, _menu menu[], int lastselect) s_delay (25); }; return menuselect; -}; - -void -menu_get_text (char *title, char *text, int len) -{ - char t[255]; - int done = 0, - keypressed = 0, - curpos, - x, - y, - i, - len_; - SDL_Event event; - Uint8 *keys; - - text[len]=0; - curpos = strlen (text); - if(curpos>=len) curpos=len-1; - strcpy (t, text); - if (len > strlen (title)) { - len_ = len; - } - else { - len_ = strlen (title); - } - draw_logo (); - y = (gfx.res.y - 2 * gfx.font.size.y) / 2; - x = (gfx.res.x - (gfx.font.size.x - 4) * len_) / 2; - draw_menubox ((gfx.font.size.x - 1) * len_, 4 * gfx.font.size.y); - draw_text (x, y, title, 1); - y = y + gfx.font.size.y; - x = (gfx.res.x - (gfx.font.size.x - 4) * len) / 2; - - if ((len - 1) * (gfx.font.size.x - 4) > gfx.res.x) - len_ = 40; - else - len_ = len; - - while (!done || keypressed == 1) { - - redraw_logo_shaded (x, y, (gfx.font.size.x - 4) * len_, gfx.font.size.y, MENU_BG_SHADE_DARK); - draw_text (x, y, t, 1); - draw_text (x + (gfx.font.size.x - 4) * curpos, y, "_", 1); - SDL_Flip (gfx.screen); - - /* do the network loop if we have to */ - if (bman.gametype == GT_multi && bman.sock != -1) - network_loop (); - - if (SDL_PollEvent (&event) != 0) - switch (event.type) { - case (SDL_QUIT): - bman.state = GS_quit; - done = 1; - } - - keys = SDL_GetKeyState (NULL); - if (!keypressed && keys[SDLK_LEFT] && event.type == SDL_KEYDOWN) { - if (curpos > 0) - curpos--; - keypressed = 1; - } - if (!keypressed && keys[SDLK_RIGHT] && event.type == SDL_KEYDOWN) { - if (curpos < strlen (text) && curpos < len - 1) - curpos++; - keypressed = 1; - } - - if (!keypressed && keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { - done = 1; - keypressed = 1; - } - - if (!keypressed && keys[SDLK_RETURN] && event.type == SDL_KEYDOWN) { - done = 1; - keypressed = 1; - strcpy (text, t); - } - - if (!keypressed && keys[8] && event.type == SDL_KEYDOWN) - if (curpos > 0) { - curpos--; - t[curpos] = t[curpos + 1]; - t[curpos + 1] = t[curpos + 2]; - keypressed = 1; - } - - for (i = ' '; i <= 255; i++) - if (i != 127 && !keypressed && keys[i] && event.type == SDL_KEYDOWN) { - if (t[curpos] == 0) - t[curpos + 1] = 0; - t[curpos] = event.key.keysym.unicode; - if (curpos < strlen (t) && curpos < len - 1) - curpos++; - keypressed = 1; - } - - if (event.type == SDL_KEYUP) - keypressed = 0; - - s_delay (25); - } -}; - - -void -menu_displaytext (char *title, char *text, Uint8 r, Uint8 g, Uint8 b) -{ - int x, - x1, - y, - y1, - len; - SDL_Rect dest; - - len = strlen (title); - if (len < strlen (text)) - len = strlen (text); - - y = (gfx.res.y - 2 * gfx.block.y) / 2; - x = (gfx.res.x - (gfx.font.size.x - 4) * len) / 2; - - y1 = gfx.font.size.y * 3; - x1 = ((gfx.font.size.x - 4) * len); - - dest.x = x; - dest.y = y - 4; - dest.h = y1; - dest.w = x1; - SDL_FillRect (gfx.screen, &dest, SDL_MapRGB (gfx.screen->format, r, g, b)); - - y = (gfx.res.y - 2 * gfx.block.y) / 2; - draw_text ((gfx.res.x - (gfx.font.size.x - 4) * strlen (title)) / 2, y, title, 1); - draw_text ((gfx.res.x - (gfx.font.size.x - 4) * strlen (text)) / 2, y + gfx.font.size.y, text, - 0); - - SDL_Flip (gfx.screen); -}; - - -void -menu_displaymessage (char *title, char *text) -{ - SDL_Event event; - Uint8 *keys; - int done = 0, - keypressed = 0; - - menu_displaytext (title, text, 64, 0, 0); - - while (done == 0 || (done == 1 && keypressed == 1)) { - /* do the network loop if we have to */ - if (bman.gametype == GT_multi && bman.sock != -1) - network_loop (); - - if (SDL_PollEvent (&event) != 0) - switch (event.type) { - case (SDL_QUIT): - done = 1; - bman.state = GS_quit; - } - keys = SDL_GetKeyState (NULL); - - if (!keypressed && keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { - done = 1; - keypressed = 1; - } - - if (!keypressed && keys[SDLK_RETURN] && event.type == SDL_KEYDOWN) { - done = 1; - keypressed = 1; - } - - if (event.type == SDL_KEYUP) - keypressed = 0; - - s_delay (100); - } -}; - -/*** - *** Menu Selection of a file ior a directory - ***/ -#define DIRSCRMAX 10 -/* draws the selection on the screen.. - dirstart - first entry do display - flags - flags what should be shown directorys or files - selected - Selected file in the list -*/ -int menu_dir_draw (char *title, _direntry *dirstart, int start, int selected) { - _direntry *de = dirstart; - int maxlen = 0, pos = 0; - SDL_Rect wnd; - - /* look for the longest name */ - for (; de != NULL; de = de->next) - if (maxlen < strlen (de->name)) - maxlen = strlen (de->name); - - if (maxlen < strlen (title)) - maxlen = strlen (title); - - if (maxlen * gfx.font.size.x > gfx.res.x - 32) - maxlen = (gfx.res.x - 40) /gfx.font.size.x; - - wnd.h = DIRSCRMAX * gfx.font.size.y * 2; - wnd.w = maxlen * gfx.font.size.x; - wnd.x = (gfx.res.x - wnd.w) / 2; - wnd.y = (gfx.res.y - wnd.h) / 2; - - draw_menubox (wnd.w, wnd.h); - draw_text ((gfx.res.x - (gfx.font.size.x/1.17) * strlen (title)) / 2, wnd.y + 4, title, 1); - - for (de = dirstart, pos = 0; de != NULL && pos < start + DIRSCRMAX - 1; de=de->next, pos++) { - if (pos >= start && pos < (start + DIRSCRMAX - 1)) - draw_text (wnd.x + gfx.menuselect.image->w + 2, 8 + wnd.y + (1+pos-start) * gfx.font.size.y * 2, de->name, (pos == selected)); - } - - return (de == NULL); -} - -char *menu_dir_select (char *title, char *path, signed char dirflags) { - _direntry *destart, *de; - SDL_Event event; - Uint8 *keys; - int max = 0, sel = 0, keypressed = 0, done = 0, listend = 0, liststart = 0, oldsel = -1; - - /* get the directory list and count the numbers */ - destart = s_getdir (path); - destart = s_dirfilter (destart, dirflags); - for (max = 0, de = destart; de != NULL; de = de->next) - max++; - if (max <= 0) - return NULL; - - while (done == 0 || (done == 1 && keypressed == 1)) { - if (sel != oldsel) { - listend = menu_dir_draw (title, destart, liststart, sel); - SDL_Flip (gfx.screen); - oldsel = sel; - } - - /* do the network loop if we have to */ - if (bman.gametype == GT_multi && bman.sock != -1) - network_loop (); - - if (SDL_PollEvent (&event) != 0) - switch (event.type) { - case (SDL_QUIT): - sel = -1; - bman.state = GS_quit; - done = 1; - } - - /* keyboard handling */ - keys = SDL_GetKeyState (NULL); - if (keys[SDLK_DOWN] && event.type == SDL_KEYDOWN && keypressed == 0) { - keypressed = 1; - sel++; - if (!(listend)) /* if we can move this list down */ - liststart++; - if (sel >= max) { - liststart = 0; - sel = 0; - } - } - - if (keys[SDLK_UP] && event.type == SDL_KEYDOWN && keypressed == 0) { - keypressed = 1; - sel--; - if (liststart > 0) - liststart--; - if (sel < 0) { - sel = max - 1; - if (sel > (DIRSCRMAX/2)) - liststart = sel - (DIRSCRMAX/2); - } - } - - if (keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { - keypressed = 1; - return NULL; - } - if (!keys[SDLK_ESCAPE] && event.type == SDL_KEYUP) - keypressed = 0; - - if (keys[SDLK_RETURN] && event.type == SDL_KEYDOWN) { - done = 1; - keypressed = 1; - } - if (!keys[SDLK_RETURN] && event.type == SDL_KEYUP) - keypressed = 0; - - s_delay (25); - } - - for (max = 0, de = destart; max != sel && de != NULL; de = de->next) - max++; - - if (de == NULL) - return NULL; - - return de->name; -}; -#undef DIRSCRMAX +}; + +void +menu_get_text (char *title, char *text, int len) +{ + char t[255]; + int done = 0, + keypressed = 0, + curpos, + x, + y, + i, + len_; + SDL_Event event; + Uint8 *keys; + + text[len]=0; + curpos = strlen (text); + if(curpos>=len) curpos=len-1; + strcpy (t, text); + if (len > strlen (title)) { + len_ = len; + } + else { + len_ = strlen (title); + } + draw_logo (); + y = (gfx.res.y - 2 * gfx.font.size.y) / 2; + x = (gfx.res.x - (gfx.font.size.x - 4) * len_) / 2; + draw_menubox ((gfx.font.size.x - 1) * len_, 4 * gfx.font.size.y); + draw_text (x, y, title, 1); + y = y + gfx.font.size.y; + x = (gfx.res.x - (gfx.font.size.x - 4) * len) / 2; + + if ((len - 1) * (gfx.font.size.x - 4) > gfx.res.x) + len_ = 40; + else + len_ = len; + + while (!done || keypressed == 1) { + + redraw_logo_shaded (x, y, (gfx.font.size.x - 4) * len_, gfx.font.size.y, MENU_BG_SHADE_DARK); + draw_text (x, y, t, 1); + draw_text (x + (gfx.font.size.x - 4) * curpos, y, "_", 1); + SDL_Flip (gfx.screen); + + /* do the network loop if we have to */ + if (bman.gametype == GT_multi && bman.sock != -1) + network_loop (); + + if (SDL_PollEvent (&event) != 0) + switch (event.type) { + case (SDL_QUIT): + bman.state = GS_quit; + done = 1; + } + + keys = SDL_GetKeyState (NULL); + if (!keypressed && keys[SDLK_LEFT] && event.type == SDL_KEYDOWN) { + if (curpos > 0) + curpos--; + keypressed = 1; + } + if (!keypressed && keys[SDLK_RIGHT] && event.type == SDL_KEYDOWN) { + if (curpos < strlen (text) && curpos < len - 1) + curpos++; + keypressed = 1; + } + + if (!keypressed && keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { + done = 1; + keypressed = 1; + } + + if (!keypressed && keys[SDLK_RETURN] && event.type == SDL_KEYDOWN) { + done = 1; + keypressed = 1; + strcpy (text, t); + } + + if (!keypressed && keys[8] && event.type == SDL_KEYDOWN) + if (curpos > 0) { + curpos--; + t[curpos] = t[curpos + 1]; + t[curpos + 1] = t[curpos + 2]; + keypressed = 1; + } + + for (i = ' '; i <= 255; i++) + if (i != 127 && !keypressed && keys[i] && event.type == SDL_KEYDOWN) { + if (t[curpos] == 0) + t[curpos + 1] = 0; + t[curpos] = event.key.keysym.unicode; + if (curpos < strlen (t) && curpos < len - 1) + curpos++; + keypressed = 1; + } + + if (event.type == SDL_KEYUP) + keypressed = 0; + + s_delay (25); + } +}; + + +void +menu_displaytext (char *title, char *text, Uint8 r, Uint8 g, Uint8 b) +{ + int x, + x1, + y, + y1, + len; + SDL_Rect dest; + + len = strlen (title); + if (len < strlen (text)) + len = strlen (text); + + y = (gfx.res.y - 2 * gfx.block.y) / 2; + x = (gfx.res.x - (gfx.font.size.x - 4) * len) / 2; + + y1 = gfx.font.size.y * 3; + x1 = ((gfx.font.size.x - 4) * len); + + dest.x = x; + dest.y = y - 4; + dest.h = y1; + dest.w = x1; + SDL_FillRect (gfx.screen, &dest, SDL_MapRGB (gfx.screen->format, r, g, b)); + + y = (gfx.res.y - 2 * gfx.block.y) / 2; + draw_text ((gfx.res.x - (gfx.font.size.x - 4) * strlen (title)) / 2, y, title, 1); + draw_text ((gfx.res.x - (gfx.font.size.x - 4) * strlen (text)) / 2, y + gfx.font.size.y, text, + 0); + + SDL_Flip (gfx.screen); +}; + + +void +menu_displaymessage (char *title, char *text) +{ + SDL_Event event; + Uint8 *keys; + int done = 0, + keypressed = 0; + + menu_displaytext (title, text, 64, 0, 0); + + while (done == 0 || (done == 1 && keypressed == 1)) { + /* do the network loop if we have to */ + if (bman.gametype == GT_multi && bman.sock != -1) + network_loop (); + + if (SDL_PollEvent (&event) != 0) + switch (event.type) { + case (SDL_QUIT): + done = 1; + bman.state = GS_quit; + } + keys = SDL_GetKeyState (NULL); + + if (!keypressed && keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { + done = 1; + keypressed = 1; + } + + if (!keypressed && keys[SDLK_RETURN] && event.type == SDL_KEYDOWN) { + done = 1; + keypressed = 1; + } + + if (event.type == SDL_KEYUP) + keypressed = 0; + + s_delay (100); + } +}; + +/*** + *** Menu Selection of a file ior a directory + ***/ +#define DIRSCRMAX 10 +/* draws the selection on the screen.. + dirstart - first entry do display + flags - flags what should be shown directorys or files + selected - Selected file in the list +*/ +int menu_dir_draw (char *title, _direntry *dirstart, int start, int selected) { + _direntry *de = dirstart; + int maxlen = 0, pos = 0; + SDL_Rect wnd; + + /* look for the longest name */ + for (; de != NULL; de = de->next) + if (maxlen < strlen (de->name)) + maxlen = strlen (de->name); + + if (maxlen < strlen (title)) + maxlen = strlen (title); + + if (maxlen * gfx.font.size.x > gfx.res.x - 32) + maxlen = (gfx.res.x - 40) /gfx.font.size.x; + + wnd.h = DIRSCRMAX * gfx.font.size.y * 2; + wnd.w = maxlen * gfx.font.size.x; + wnd.x = (gfx.res.x - wnd.w) / 2; + wnd.y = (gfx.res.y - wnd.h) / 2; + + draw_menubox (wnd.w, wnd.h); + draw_text ((gfx.res.x - (gfx.font.size.x/1.17) * strlen (title)) / 2, wnd.y + 4, title, 1); + + for (de = dirstart, pos = 0; de != NULL && pos < start + DIRSCRMAX - 1; de=de->next, pos++) { + if (pos >= start && pos < (start + DIRSCRMAX - 1)) + draw_text (wnd.x + gfx.menuselect.image->w + 2, 8 + wnd.y + (1+pos-start) * gfx.font.size.y * 2, de->name, (pos == selected)); + } + + return (de == NULL); +} + +char *menu_dir_select (char *title, char *path, signed char dirflags) { + _direntry *destart, *de; + SDL_Event event; + Uint8 *keys; + int max = 0, sel = 0, keypressed = 0, done = 0, listend = 0, liststart = 0, oldsel = -1; + + /* get the directory list and count the numbers */ + destart = s_getdir (path); + destart = s_dirfilter (destart, dirflags); + for (max = 0, de = destart; de != NULL; de = de->next) + max++; + if (max <= 0) + return NULL; + + while (done == 0 || (done == 1 && keypressed == 1)) { + if (sel != oldsel) { + listend = menu_dir_draw (title, destart, liststart, sel); + SDL_Flip (gfx.screen); + oldsel = sel; + } + + /* do the network loop if we have to */ + if (bman.gametype == GT_multi && bman.sock != -1) + network_loop (); + + if (SDL_PollEvent (&event) != 0) + switch (event.type) { + case (SDL_QUIT): + sel = -1; + bman.state = GS_quit; + done = 1; + } + + /* keyboard handling */ + keys = SDL_GetKeyState (NULL); + if (keys[SDLK_DOWN] && event.type == SDL_KEYDOWN && keypressed == 0) { + keypressed = 1; + sel++; + if (!(listend)) /* if we can move this list down */ + liststart++; + if (sel >= max) { + liststart = 0; + sel = 0; + } + } + + if (keys[SDLK_UP] && event.type == SDL_KEYDOWN && keypressed == 0) { + keypressed = 1; + sel--; + if (liststart > 0) + liststart--; + if (sel < 0) { + sel = max - 1; + if (sel > (DIRSCRMAX/2)) + liststart = sel - (DIRSCRMAX/2); + } + } + + if (keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { + keypressed = 1; + return NULL; + } + if (!keys[SDLK_ESCAPE] && event.type == SDL_KEYUP) + keypressed = 0; + + if (keys[SDLK_RETURN] && event.type == SDL_KEYDOWN) { + done = 1; + keypressed = 1; + } + if (!keys[SDLK_RETURN] && event.type == SDL_KEYUP) + keypressed = 0; + + s_delay (25); + } + + for (max = 0, de = destart; max != sel && de != NULL; de = de->next) + max++; + + if (de == NULL) + return NULL; + + return de->name; +}; +#undef DIRSCRMAX diff --git a/src/multiwait.c b/src/multiwait.c index 928d3f3..7c5b044 100644 --- a/src/multiwait.c +++ b/src/multiwait.c @@ -1,366 +1,366 @@ -/* - multiwait.c - this manages only the network screen where - everyone have to select it's players and where even the basic chat is inside -*/ - -#include "bomberclone.h" -#include "network.h" -#include "packets.h" -#include "gamesrv.h" -#include "gfx.h" -#include "chat.h" - -#define MW_IS_GFX_SELECT(__gfx_nr,__result) for (__result = (MAX_PLAYERS-1); (bman.players[__result].gfx_nr != __gfx_nr) && (__result >= 0); __result--); - -extern int UpdateRects_nr; - -static int mw_y = 0, - mw_frame = 0, - mw_frameto = 0; -static SDL_Surface *mw_plgfx[MAX_PLAYERS]; - - -/* this will load some graphics and so other stuff */ -void -mw_init () -{ - int i; - SDL_Surface *tmp; - draw_logo (); - - menu_displaytext ("Please Wait", "Loading GFX Data", 64, 128, 64); - - gfx_load_players (32, 32); - network_loop (); - for (i = 0; i < MAX_PLAYERS; i++) { - network_loop (); - tmp = makegray_image (gfx.players[i].ani.image); - network_loop (); - mw_plgfx[i] = SDL_DisplayFormat (tmp); - network_loop (); - SDL_FreeSurface (tmp); - network_loop (); - } -}; - - -/* free all grafics */ -void -mw_shutdown () -{ - int i; - - chat_show (-1, -1, -1, -1); - - menu_displaytext ("Please Wait", "Freeing GFX Data", 64, 128, 64); - - gfx_free_players (); - for (i = 0; i < MAX_PLAYERS; i++) - SDL_FreeSurface (mw_plgfx[i]); -}; - - -void -mw_wait_for_connect () -{ - menu_displaytext ("Please Wait", "Wait For connection", 64, 128, 64); -}; - - -void -mw_draw_status () -{ - int pnr, - x, - x1, - y, - px; - char text[255]; - SDL_Rect src, - dest; - - /* Draw Player List */ - /* 1. the head */ - px = gfx.res.x / 320; - x = (gfx.res.x - px * 320) / 2; - - for (pnr = 0; pnr < px; pnr++) - draw_text (pnr * 320 + x, 24, " Wins Points", 1); - - /* 2. the names with points */ - for (x1 = pnr = 0, y = 48; pnr < MAX_PLAYERS; pnr++) { - redraw_logo (x1 * 320, y - 4, 320, 32); - if (bman.players[pnr].gfx_nr != -1 && PS_IS_used (bman.players[pnr].state)) { - src.x = 3 * bman.players[pnr].gfx->smal_size.x; - src.y = 0; - src.w = dest.w = bman.players[pnr].gfx->smal_size.x; - src.h = dest.h = bman.players[pnr].gfx->smal_size.y; - - dest.x = x1 * 320; - dest.y = y - 4; - - SDL_BlitSurface (bman.players[pnr].gfx->smal_image, &src, gfx.screen, &dest); - } - - sprintf (text, " %10s %2d %2d", bman.players[pnr].name, bman.players[pnr].wins, - bman.players[pnr].points); - if (PS_IS_used (bman.players[pnr].state)) { - - if (bman.lastwinner == pnr) - draw_text (x + x1 * 320, y, text, 1); - else - draw_text (x + x1 * 320, y, text, 0); - } - x1++; - if (x1 >= px) { - y += 32; - x1 = 0; - } - if (pnr == MAX_PLAYERS - 1 && x1 != 0) - y += 32; - } - - mw_y = y; -}; - - -void -mw_draw_gfxselect (int selgfx) -{ - int i, - select, - xstep; - SDL_Rect src, - dest; - - xstep = gfx.res.x / MAX_PLAYERS; - - if (bman.players[bman.p_nr].gfx_nr == -1) { - /* draw selection */ - for (i = 0; i < MAX_PLAYERS; i++) { - dest.w = src.w = gfx.players[i].size.x; - dest.h = src.h = gfx.players[i].size.y; - - dest.x = i * xstep + (xstep >> 1) - (gfx.players[i].size.x >> 1); - dest.y = mw_y + 8; - - redraw_logo (dest.x, dest.y, dest.w, dest.h); - - src.x = 3 * gfx.players[i].size.x; - if (i == selgfx) - src.y = mw_frame * gfx.players[i].size.y; - else - src.y = 0; - - MW_IS_GFX_SELECT (i, select); - - if (select >= MAX_PLAYERS || select < 0) { - /* this player have not been selected */ - if (selgfx == i) { - mw_frameto--; - - if (mw_frameto <= 0 || mw_frameto > ANI_PLAYERTIMEOUT) { - mw_frameto = ANI_PLAYERTIMEOUT; - mw_frame++; - } - - if (mw_frame >= gfx.players[i].ani.frames || mw_frame < 0) { - mw_frameto = ANI_PLAYERTIMEOUT; - mw_frame = 0; - } - - SDL_BlitSurface (gfx.players[i].ani.image, &src, gfx.screen, &dest); - } - else - SDL_BlitSurface (mw_plgfx[i], &src, gfx.screen, &dest); - } - } - } - else { - /* draw selected players */ - for (i = 0; i < MAX_PLAYERS; i++) { - dest.w = src.w = gfx.players[i].size.x; - dest.h = src.h = gfx.players[i].size.y; - - dest.x = i * xstep + (xstep >> 1) - (gfx.players[i].size.x >> 1); - dest.y = mw_y + 8; - - redraw_logo (dest.x, dest.y, dest.w, dest.h); - - src.x = 3 * gfx.players[i].size.x; - if (i == selgfx) - src.y = mw_frame * gfx.players[i].size.y; - else - src.y = 0; - - MW_IS_GFX_SELECT (i, select); - - if (select < MAX_PLAYERS && select >= 0) { - /* this player have been selected */ - if (bman.players[bman.p_nr].gfx_nr == i) - SDL_BlitSurface (gfx.players[i].ani.image, &src, gfx.screen, &dest); - else - SDL_BlitSurface (mw_plgfx[i], &src, gfx.screen, &dest); - } - } - } - - mw_y += 8 + gfx.players[0].size.y; -} - - -void -mw_draw_chat () -{ - if (chat.visible == 0) { - chat_show (16, mw_y + 16, gfx.res.x - 16, gfx.res.y - 32); - chat_addline ("Press [STRG] or [CTRL] - to select a player"); - if (GT_MP_PTPM) - chat_addline ("F4 - to start the game"); - } -}; - - -/* the loop itself */ -void -wait_for_players () -{ - SDL_Event event; - Uint8 *keys; - int done = 0, - ready = 0, - keypressed = 0, - i, - selgfx = 0; - - mw_init (); - draw_logo (); - - while (!done && bman.state == GS_wait) { - - i = bman.p_nr; - if (network_loop () < 0) { - done = 1; - bman.p_nr = -1; - } - if (i != bman.p_nr) /* clean the screen after we got our playernumber */ - draw_logo (); - - /* check if all players are ready, and more as one player is connected */ - if (GT_MP_PTPM) - for (ready = 0, i = 0; i < MAX_PLAYERS; i++) - if (PS_IS_playing (bman.players[i].state)) - ready++; - if (ready > 1) - ready = 1; - else - ready = 0; - - /* draw the screeninformations */ - if (bman.p_nr == -1) { /* we have no connect yet */ - mw_wait_for_connect (); - SDL_Flip (gfx.screen); - } - else { /* we have a connect so draw status */ - mw_draw_status (); - mw_draw_gfxselect (selgfx); - gfx_AddUpdateRect (0, 0, gfx.res.x, mw_y); - mw_draw_chat (); - } - - gfx_UpdateRects (); - - /* do the keyboard handling */ - if (SDL_PollEvent (&event) != 0) - switch (event.type) { - case (SDL_QUIT): - bman.state = GS_quit; - bman.p_nr = -1; - done = 1; - } - - keys = SDL_GetKeyState (NULL); - - if (keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { - /* we want to quit */ - done = 1; - bman.p_nr = -1; - keypressed = 1; - bman.state = GS_startup; - } - - if (bman.p_nr != -1) { - - if (keys[SDLK_LEFT] && (!keypressed) && bman.players[bman.p_nr].gfx_nr == -1) { - i = 0; - while (selgfx < 0 || selgfx >= MAX_PLAYERS || i != -1) { - selgfx--; - if (selgfx < 0) - selgfx = MAX_PLAYERS - 1; - MW_IS_GFX_SELECT (selgfx, i); - } - } - - if (keys[SDLK_RIGHT] && (!keypressed) && bman.players[bman.p_nr].gfx_nr == -1) { - i = 0; - while (selgfx < 0 || selgfx >= MAX_PLAYERS || i != -1) { - selgfx++; - if (selgfx >= MAX_PLAYERS) - selgfx = 0; - MW_IS_GFX_SELECT (selgfx, i); - } - } - - /* just make sure this player is not selected twice */ - if (bman.players[bman.p_nr].gfx_nr == -1) { - MW_IS_GFX_SELECT (selgfx, i); - while (selgfx < 0 || selgfx >= MAX_PLAYERS || i != -1) { - selgfx++; - if (selgfx >= MAX_PLAYERS) - selgfx = 0; - MW_IS_GFX_SELECT (selgfx, i); - } - } - - if ((keys[SDLK_LCTRL] || keys[SDLK_RCTRL]) && (!keypressed)) { - if (bman.players[bman.p_nr].gfx_nr == -1) { - /* select player */ - bman.players[bman.p_nr].gfx_nr = selgfx; - } - else { - /* deselect player */ - bman.players[bman.p_nr].gfx_nr = -1; - } - net_change_playerid (bman.p_nr, 1); - } - - if ((GT_MP_PTPM) && ready && keys[SDLK_F4] && (!keypressed)) { - done = 1; - } - - if ((GT_MP_PTPM) && keys[SDLK_F5] && (!keypressed)) { - /* Map modification */ - mapmenu (); - mw_draw_status (); - mw_draw_gfxselect (selgfx); - UpdateRects_nr = 0; - gfx_AddUpdateRect (0, 0, gfx.res.x, mw_y); - chat.changed = 1; - chat.lineschanged = 1; - chat_drawbox (); - mw_draw_chat (); - gfx_UpdateRects (); - } - chat_loop (&event); - } - - if (event.type == SDL_KEYUP) - keypressed = 0; - else if (event.type == SDL_KEYDOWN) - keypressed = 1; - - s_delay (25); - } - - mw_shutdown (); -}; +/* + multiwait.c - this manages only the network screen where + everyone have to select it's players and where even the basic chat is inside +*/ + +#include "bomberclone.h" +#include "network.h" +#include "packets.h" +#include "gamesrv.h" +#include "gfx.h" +#include "chat.h" + +#define MW_IS_GFX_SELECT(__gfx_nr,__result) for (__result = (MAX_PLAYERS-1); (bman.players[__result].gfx_nr != __gfx_nr) && (__result >= 0); __result--); + +extern int UpdateRects_nr; + +static int mw_y = 0, + mw_frame = 0, + mw_frameto = 0; +static SDL_Surface *mw_plgfx[MAX_PLAYERS]; + + +/* this will load some graphics and so other stuff */ +void +mw_init () +{ + int i; + SDL_Surface *tmp; + draw_logo (); + + menu_displaytext ("Please Wait", "Loading GFX Data", 64, 128, 64); + + gfx_load_players (32, 32); + network_loop (); + for (i = 0; i < MAX_PLAYERS; i++) { + network_loop (); + tmp = makegray_image (gfx.players[i].ani.image); + network_loop (); + mw_plgfx[i] = SDL_DisplayFormat (tmp); + network_loop (); + SDL_FreeSurface (tmp); + network_loop (); + } +}; + + +/* free all grafics */ +void +mw_shutdown () +{ + int i; + + chat_show (-1, -1, -1, -1); + + menu_displaytext ("Please Wait", "Freeing GFX Data", 64, 128, 64); + + gfx_free_players (); + for (i = 0; i < MAX_PLAYERS; i++) + SDL_FreeSurface (mw_plgfx[i]); +}; + + +void +mw_wait_for_connect () +{ + menu_displaytext ("Please Wait", "Wait For connection", 64, 128, 64); +}; + + +void +mw_draw_status () +{ + int pnr, + x, + x1, + y, + px; + char text[255]; + SDL_Rect src, + dest; + + /* Draw Player List */ + /* 1. the head */ + px = gfx.res.x / 320; + x = (gfx.res.x - px * 320) / 2; + + for (pnr = 0; pnr < px; pnr++) + draw_text (pnr * 320 + x, 24, " Wins Points", 1); + + /* 2. the names with points */ + for (x1 = pnr = 0, y = 48; pnr < MAX_PLAYERS; pnr++) { + redraw_logo (x1 * 320, y - 4, 320, 32); + if (bman.players[pnr].gfx_nr != -1 && PS_IS_used (bman.players[pnr].state)) { + src.x = 3 * bman.players[pnr].gfx->smal_size.x; + src.y = 0; + src.w = dest.w = bman.players[pnr].gfx->smal_size.x; + src.h = dest.h = bman.players[pnr].gfx->smal_size.y; + + dest.x = x1 * 320; + dest.y = y - 4; + + SDL_BlitSurface (bman.players[pnr].gfx->smal_image, &src, gfx.screen, &dest); + } + + sprintf (text, " %10s %2d %2d", bman.players[pnr].name, bman.players[pnr].wins, + bman.players[pnr].points); + if (PS_IS_used (bman.players[pnr].state)) { + + if (bman.lastwinner == pnr) + draw_text (x + x1 * 320, y, text, 1); + else + draw_text (x + x1 * 320, y, text, 0); + } + x1++; + if (x1 >= px) { + y += 32; + x1 = 0; + } + if (pnr == MAX_PLAYERS - 1 && x1 != 0) + y += 32; + } + + mw_y = y; +}; + + +void +mw_draw_gfxselect (int selgfx) +{ + int i, + select, + xstep; + SDL_Rect src, + dest; + + xstep = gfx.res.x / MAX_PLAYERS; + + if (bman.players[bman.p_nr].gfx_nr == -1) { + /* draw selection */ + for (i = 0; i < MAX_PLAYERS; i++) { + dest.w = src.w = gfx.players[i].size.x; + dest.h = src.h = gfx.players[i].size.y; + + dest.x = i * xstep + (xstep >> 1) - (gfx.players[i].size.x >> 1); + dest.y = mw_y + 8; + + redraw_logo (dest.x, dest.y, dest.w, dest.h); + + src.x = 3 * gfx.players[i].size.x; + if (i == selgfx) + src.y = mw_frame * gfx.players[i].size.y; + else + src.y = 0; + + MW_IS_GFX_SELECT (i, select); + + if (select >= MAX_PLAYERS || select < 0) { + /* this player have not been selected */ + if (selgfx == i) { + mw_frameto--; + + if (mw_frameto <= 0 || mw_frameto > ANI_PLAYERTIMEOUT) { + mw_frameto = ANI_PLAYERTIMEOUT; + mw_frame++; + } + + if (mw_frame >= gfx.players[i].ani.frames || mw_frame < 0) { + mw_frameto = ANI_PLAYERTIMEOUT; + mw_frame = 0; + } + + SDL_BlitSurface (gfx.players[i].ani.image, &src, gfx.screen, &dest); + } + else + SDL_BlitSurface (mw_plgfx[i], &src, gfx.screen, &dest); + } + } + } + else { + /* draw selected players */ + for (i = 0; i < MAX_PLAYERS; i++) { + dest.w = src.w = gfx.players[i].size.x; + dest.h = src.h = gfx.players[i].size.y; + + dest.x = i * xstep + (xstep >> 1) - (gfx.players[i].size.x >> 1); + dest.y = mw_y + 8; + + redraw_logo (dest.x, dest.y, dest.w, dest.h); + + src.x = 3 * gfx.players[i].size.x; + if (i == selgfx) + src.y = mw_frame * gfx.players[i].size.y; + else + src.y = 0; + + MW_IS_GFX_SELECT (i, select); + + if (select < MAX_PLAYERS && select >= 0) { + /* this player have been selected */ + if (bman.players[bman.p_nr].gfx_nr == i) + SDL_BlitSurface (gfx.players[i].ani.image, &src, gfx.screen, &dest); + else + SDL_BlitSurface (mw_plgfx[i], &src, gfx.screen, &dest); + } + } + } + + mw_y += 8 + gfx.players[0].size.y; +} + + +void +mw_draw_chat () +{ + if (chat.visible == 0) { + chat_show (16, mw_y + 16, gfx.res.x - 16, gfx.res.y - 32); + chat_addline ("Press [STRG] or [CTRL] - to select a player"); + if (GT_MP_PTPM) + chat_addline ("F4 - to start the game"); + } +}; + + +/* the loop itself */ +void +wait_for_players () +{ + SDL_Event event; + Uint8 *keys; + int done = 0, + ready = 0, + keypressed = 0, + i, + selgfx = 0; + + mw_init (); + draw_logo (); + + while (!done && bman.state == GS_wait) { + + i = bman.p_nr; + if (network_loop () < 0) { + done = 1; + bman.p_nr = -1; + } + if (i != bman.p_nr) /* clean the screen after we got our playernumber */ + draw_logo (); + + /* check if all players are ready, and more as one player is connected */ + if (GT_MP_PTPM) + for (ready = 0, i = 0; i < MAX_PLAYERS; i++) + if (PS_IS_playing (bman.players[i].state)) + ready++; + if (ready > 1) + ready = 1; + else + ready = 0; + + /* draw the screeninformations */ + if (bman.p_nr == -1) { /* we have no connect yet */ + mw_wait_for_connect (); + SDL_Flip (gfx.screen); + } + else { /* we have a connect so draw status */ + mw_draw_status (); + mw_draw_gfxselect (selgfx); + gfx_AddUpdateRect (0, 0, gfx.res.x, mw_y); + mw_draw_chat (); + } + + gfx_UpdateRects (); + + /* do the keyboard handling */ + if (SDL_PollEvent (&event) != 0) + switch (event.type) { + case (SDL_QUIT): + bman.state = GS_quit; + bman.p_nr = -1; + done = 1; + } + + keys = SDL_GetKeyState (NULL); + + if (keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { + /* we want to quit */ + done = 1; + bman.p_nr = -1; + keypressed = 1; + bman.state = GS_startup; + } + + if (bman.p_nr != -1) { + + if (keys[SDLK_LEFT] && (!keypressed) && bman.players[bman.p_nr].gfx_nr == -1) { + i = 0; + while (selgfx < 0 || selgfx >= MAX_PLAYERS || i != -1) { + selgfx--; + if (selgfx < 0) + selgfx = MAX_PLAYERS - 1; + MW_IS_GFX_SELECT (selgfx, i); + } + } + + if (keys[SDLK_RIGHT] && (!keypressed) && bman.players[bman.p_nr].gfx_nr == -1) { + i = 0; + while (selgfx < 0 || selgfx >= MAX_PLAYERS || i != -1) { + selgfx++; + if (selgfx >= MAX_PLAYERS) + selgfx = 0; + MW_IS_GFX_SELECT (selgfx, i); + } + } + + /* just make sure this player is not selected twice */ + if (bman.players[bman.p_nr].gfx_nr == -1) { + MW_IS_GFX_SELECT (selgfx, i); + while (selgfx < 0 || selgfx >= MAX_PLAYERS || i != -1) { + selgfx++; + if (selgfx >= MAX_PLAYERS) + selgfx = 0; + MW_IS_GFX_SELECT (selgfx, i); + } + } + + if ((keys[SDLK_LCTRL] || keys[SDLK_RCTRL]) && (!keypressed)) { + if (bman.players[bman.p_nr].gfx_nr == -1) { + /* select player */ + bman.players[bman.p_nr].gfx_nr = selgfx; + } + else { + /* deselect player */ + bman.players[bman.p_nr].gfx_nr = -1; + } + net_change_playerid (bman.p_nr, 1); + } + + if ((GT_MP_PTPM) && ready && keys[SDLK_F4] && (!keypressed)) { + done = 1; + } + + if ((GT_MP_PTPM) && keys[SDLK_F5] && (!keypressed)) { + /* Map modification */ + mapmenu (); + mw_draw_status (); + mw_draw_gfxselect (selgfx); + UpdateRects_nr = 0; + gfx_AddUpdateRect (0, 0, gfx.res.x, mw_y); + chat.changed = 1; + chat.lineschanged = 1; + chat_drawbox (); + mw_draw_chat (); + gfx_UpdateRects (); + } + chat_loop (&event); + } + + if (event.type == SDL_KEYUP) + keypressed = 0; + else if (event.type == SDL_KEYDOWN) + keypressed = 1; + + s_delay (25); + } + + mw_shutdown (); +}; diff --git a/src/netmenu.c b/src/netmenu.c index 98f7c02..c72cb07 100644 --- a/src/netmenu.c +++ b/src/netmenu.c @@ -1,247 +1,247 @@ -/* network menu */ - -#include "bomberclone.h" -#include "network.h" -#include "packets.h" -#include "gamesrv.h" -#include "gfx.h" - -extern int UpdateRects_nr; - - -void -networkmenu_joingame () -{ - int i; - - gamesrv_getserver (); - - for (i = 0; bman.servername[i] != 0; i++) - if (bman.servername[i] == ' ') - bman.servername[i] = ':'; - - - /* connect if we have an Servername */ - if (bman.servername[0] != 0) { - bman.sock = -1; - bman.gametype = GT_multi; - bman.multitype = MT_ptps; - join_multiplayer_game (); - bman.servername[0] = 0; - } -}; - -void -netmenu () -{ - int menuselect = 0; - _menu menu[] = { - {0, "Join A Netgame"}, - {1, "Create A New Netgame"}, - {2, "Options"}, - {3, "Return To Main Menu"}, - {-1, ""} - }; - - if (bman.gamename[0] == 0) - sprintf (bman.gamename, "%s's Game", bman.playername); - - while (menuselect != -1 && bman.state != GS_quit) { - menuselect = menu_loop ("Multiplayer", menu, menuselect); - switch (menuselect) { - case (0): // Join a Game - networkmenu_joingame (); - break; - case (1): // Create a new Game - bman.sock = -1; - bman.gametype = GT_multi; - bman.multitype = MT_ptpm; - host_multiplayer_game (); - break; - case (2): // Options - networkmenu_options (); - break; - case (3): - menuselect = -1; - break; - } - } -} - -void -networkmenu_options () -{ - int menuselect = 0; - char text[255]; - _menu menu[] = { - {0, "Game Name:"}, - {1, "Max Players:"}, - {2, "Network"}, - {3, "Notify Masterserver"}, - {4, "Masterserver"}, - {5, "Return To Multiplayer Menu"}, - {-1, ""} - }; - - - while (menuselect != -1 && bman.state != GS_quit) { - - sprintf (menu[0].text, "Gamename: %s", bman.gamename); - sprintf (menu[1].text, "Max Players: %d/%d", bman.maxplayer, MAX_PLAYERS); - - if (bman.net_ai_family == PF_INET) - sprintf (menu[2].text, "Network: IPv4"); - else - sprintf (menu[2].text, "Network: IPv6"); - - if (bman.notifygamemaster) - sprintf (menu[3].text, "Notify MasterServer: Yes"); - else - sprintf (menu[3].text, "Notify MasterServer: No"); - - sprintf (menu[4].text, "MasterServer %s", bman.gamemaster); - - menuselect = menu_loop ("Multiplayer Options", menu, menuselect); - - switch (menuselect) { - - case (0): // change the game name - menu_get_text ("Name of the Game:", bman.gamename, 32); - break; - - case (1): // Max Number of Players - sprintf (text, "%d", bman.maxplayer); - menu_get_text ("Max Players", text, 2); - bman.maxplayer = atoi (text); - if (bman.maxplayer > MAX_PLAYERS) - bman.maxplayer = MAX_PLAYERS; - if (bman.maxplayer < 2) - bman.maxplayer = 2; - break; - - case (2): -#ifndef _WIN32 - if (bman.net_ai_family == PF_INET) - bman.net_ai_family = PF_INET6; - else - bman.net_ai_family = PF_INET; -#endif - break; - - case (3): // Change the Notification - if (bman.notifygamemaster) - bman.notifygamemaster = 0; - else - bman.notifygamemaster = 1; - break; - - case (4): // Masterserver Address - menu_get_text ("Address of the MasterServer", bman.gamemaster, - LEN_SERVERNAME + LEN_PORT + 2); - break; - - case (5): - menuselect = -1; - break; - } - } -}; - - -void -multiplayer_firstrun () -{ - int i; - /* - reset some gamedata - */ - bman.p_nr = -1; - bman.state = GS_wait; - - for (i = 0; i < MAX_PLAYERS; i++) { - bman.players[i].name[0] = 0; - bman.players[i].gfx_nr = -1; - bman.players[i].gfx = NULL; - } - - /* - init the network - */ - if (network_init () < 0) { - d_printf ("network_init () FAILED\n"); - return; - } -}; - - -/* - We will host a network game -*/ -void -host_multiplayer_game () -{ - multiplayer_firstrun (); - - while (bman.state != GS_startup && bman.state != GS_quit) { - /* check players and in_pl lists */ - wait_for_players (); - - if (bman.p_nr != -1) { - bman.state = GS_update; - net_new_game (); - init_map_tileset(); - net_send_servermode (); - gfx_game_init (); - net_new_gamedata (); - - if (bman.state == GS_ready || bman.state == GS_running) { - net_send_servermode (); - - game_loop (); - if (bman.state == GS_running) - bman.state = GS_wait; - - bman.lastwinner = -1; - - game_end (); - - net_send_servermode (); - net_send_players (); - } - gfx_game_shutdown (); - } - } - - network_shutdown (); -}; - - - -/* - We will join a network game -*/ -void -join_multiplayer_game () -{ - multiplayer_firstrun (); - - while (bman.state != GS_startup && bman.state != GS_quit) { - wait_for_players (); - - if (bman.p_nr != -1 && (GS_WAITRUNNING || bman.state == GS_update)) { - gfx_game_init (); - bman.state = GS_update; - net_new_game (); - net_new_gamedata (); - - if (bman.state == GS_ready || bman.state == GS_running) - game_loop (); - - gfx_game_shutdown (); - } - else - bman.state = GS_startup; - } - - network_shutdown (); -}; +/* network menu */ + +#include "bomberclone.h" +#include "network.h" +#include "packets.h" +#include "gamesrv.h" +#include "gfx.h" + +extern int UpdateRects_nr; + + +void +networkmenu_joingame () +{ + int i; + + gamesrv_getserver (); + + for (i = 0; bman.servername[i] != 0; i++) + if (bman.servername[i] == ' ') + bman.servername[i] = ':'; + + + /* connect if we have an Servername */ + if (bman.servername[0] != 0) { + bman.sock = -1; + bman.gametype = GT_multi; + bman.multitype = MT_ptps; + join_multiplayer_game (); + bman.servername[0] = 0; + } +}; + +void +netmenu () +{ + int menuselect = 0; + _menu menu[] = { + {0, "Join A Netgame"}, + {1, "Create A New Netgame"}, + {2, "Options"}, + {3, "Return To Main Menu"}, + {-1, ""} + }; + + if (bman.gamename[0] == 0) + sprintf (bman.gamename, "%s's Game", bman.playername); + + while (menuselect != -1 && bman.state != GS_quit) { + menuselect = menu_loop ("Multiplayer", menu, menuselect); + switch (menuselect) { + case (0): // Join a Game + networkmenu_joingame (); + break; + case (1): // Create a new Game + bman.sock = -1; + bman.gametype = GT_multi; + bman.multitype = MT_ptpm; + host_multiplayer_game (); + break; + case (2): // Options + networkmenu_options (); + break; + case (3): + menuselect = -1; + break; + } + } +} + +void +networkmenu_options () +{ + int menuselect = 0; + char text[255]; + _menu menu[] = { + {0, "Game Name:"}, + {1, "Max Players:"}, + {2, "Network"}, + {3, "Notify Masterserver"}, + {4, "Masterserver"}, + {5, "Return To Multiplayer Menu"}, + {-1, ""} + }; + + + while (menuselect != -1 && bman.state != GS_quit) { + + sprintf (menu[0].text, "Gamename: %s", bman.gamename); + sprintf (menu[1].text, "Max Players: %d/%d", bman.maxplayer, MAX_PLAYERS); + + if (bman.net_ai_family == PF_INET) + sprintf (menu[2].text, "Network: IPv4"); + else + sprintf (menu[2].text, "Network: IPv6"); + + if (bman.notifygamemaster) + sprintf (menu[3].text, "Notify MasterServer: Yes"); + else + sprintf (menu[3].text, "Notify MasterServer: No"); + + sprintf (menu[4].text, "MasterServer %s", bman.gamemaster); + + menuselect = menu_loop ("Multiplayer Options", menu, menuselect); + + switch (menuselect) { + + case (0): // change the game name + menu_get_text ("Name of the Game:", bman.gamename, 32); + break; + + case (1): // Max Number of Players + sprintf (text, "%d", bman.maxplayer); + menu_get_text ("Max Players", text, 2); + bman.maxplayer = atoi (text); + if (bman.maxplayer > MAX_PLAYERS) + bman.maxplayer = MAX_PLAYERS; + if (bman.maxplayer < 2) + bman.maxplayer = 2; + break; + + case (2): +#ifndef _WIN32 + if (bman.net_ai_family == PF_INET) + bman.net_ai_family = PF_INET6; + else + bman.net_ai_family = PF_INET; +#endif + break; + + case (3): // Change the Notification + if (bman.notifygamemaster) + bman.notifygamemaster = 0; + else + bman.notifygamemaster = 1; + break; + + case (4): // Masterserver Address + menu_get_text ("Address of the MasterServer", bman.gamemaster, + LEN_SERVERNAME + LEN_PORT + 2); + break; + + case (5): + menuselect = -1; + break; + } + } +}; + + +void +multiplayer_firstrun () +{ + int i; + /* + reset some gamedata + */ + bman.p_nr = -1; + bman.state = GS_wait; + + for (i = 0; i < MAX_PLAYERS; i++) { + bman.players[i].name[0] = 0; + bman.players[i].gfx_nr = -1; + bman.players[i].gfx = NULL; + } + + /* + init the network + */ + if (network_init () < 0) { + d_printf ("network_init () FAILED\n"); + return; + } +}; + + +/* + We will host a network game +*/ +void +host_multiplayer_game () +{ + multiplayer_firstrun (); + + while (bman.state != GS_startup && bman.state != GS_quit) { + /* check players and in_pl lists */ + wait_for_players (); + + if (bman.p_nr != -1) { + bman.state = GS_update; + net_new_game (); + init_map_tileset(); + net_send_servermode (); + gfx_game_init (); + net_new_gamedata (); + + if (bman.state == GS_ready || bman.state == GS_running) { + net_send_servermode (); + + game_loop (); + if (bman.state == GS_running) + bman.state = GS_wait; + + bman.lastwinner = -1; + + game_end (); + + net_send_servermode (); + net_send_players (); + } + gfx_game_shutdown (); + } + } + + network_shutdown (); +}; + + + +/* + We will join a network game +*/ +void +join_multiplayer_game () +{ + multiplayer_firstrun (); + + while (bman.state != GS_startup && bman.state != GS_quit) { + wait_for_players (); + + if (bman.p_nr != -1 && (GS_WAITRUNNING || bman.state == GS_update)) { + gfx_game_init (); + bman.state = GS_update; + net_new_game (); + net_new_gamedata (); + + if (bman.state == GS_ready || bman.state == GS_running) + game_loop (); + + gfx_game_shutdown (); + } + else + bman.state = GS_startup; + } + + network_shutdown (); +}; diff --git a/src/network.c b/src/network.c index 2e9c01e..6a9f194 100644 --- a/src/network.c +++ b/src/network.c @@ -1,777 +1,777 @@ -/* $Id: network.c,v 1.15 2003/05/07 21:28:12 stpohle Exp $ */ -/* - network routines. -*/ - -#include "bomberclone.h" -#include "network.h" -#include "gamesrv.h" -#include "packets.h" -#include "gfx.h" - -int -network_server_port (char *server, char *host, int hostlen, char *port, int portlen) -{ - char *pos, - *pos2; - - if (host == NULL) - return -1; - - pos2 = pos = strchr (server, ':'); - - if (pos != NULL) - while (pos2 != NULL) { - pos = pos2; - pos2 = strchr (pos + 1, ':'); - } - - if (pos != NULL) { - // : für Portangabe gefunden - if (pos - server < hostlen) { - strncpy (host, server, pos - server); - host[pos - server] = 0; - if (pos[1] == 0) - sprintf (port, "11000"); - else - strcpy (port, pos + 1); - } - else { - return -1; - } - } - else { - // Portangabe wurde nicht gefunden und wird auf 0 gesetzt - strncpy (host, server, hostlen); - sprintf (port, "11000"); - } - - return 0; -}; - - -/* - try to work better with the network packet option -*/ -void -net_dyn_pkgoption () -{ - int p; - _net_pkgopt *npkg; - - for (p = 0; p < MAX_PLAYERS; p++) - if (PS_IS_netplayer (bman.players[p].state)) { - npkg = &bman.players[p].net.pkgopt; - - if (npkg->to_2sec > DYN_PKG_MAX_MISSING) { - if (npkg->send_set < 10) - npkg->send_set++; - npkg->to_2sec = 0; - npkg->to_timestamp = timestamp; - } - - if ((timestamp - npkg->to_timestamp > 2000) && npkg->to_2sec <= DYN_PKG_MIN_MISSING) { - if (npkg->send_set > PKG_SENDSETOPT) - npkg->send_set--; - npkg->to_2sec = 0; - npkg->to_timestamp = timestamp; - } - } -}; - - - - -/* - setup everything for the network loop -*/ -int -network_init () -{ - int i; -/* - we need it for the windows winsock -*/ -#ifdef _WIN32 - WSADATA wsaData; - - if (WSAStartup (MAKEWORD (1, 1), &wsaData) != 0) { - d_printf ("WSAStartup failed.\n"); - exit (1); - } -#endif - - bman.sock = -1; - bman.p_nr = -1; - - timestamp = SDL_GetTicks (); - - // reset playernumber and number of connected players - for (i = 0; i < MAX_PLAYERS; i++) { - bman.players[i].net.addr.host[0] = 0; - bman.players[i].net.addr.port[0] = 0; - bman.players[i].name[0] = 0; - bman.players[i].gfx_nr = -1; - bman.players[i].net.timestamp = timestamp; - bman.players[i].points = 0; - bman.players[i].wins = 0; - bman.players[i].net.pingreq = 20; - bman.players[i].net.pingack = 22; - bman.players[i].state = 0; - } - - bman.lastwinner = -1; - bman.players_nr_s = 1; - - // start the udp server - bman.sock = udp_server (bman.port, bman.net_ai_family); - - if (bman.sock < 0) { -#ifdef _WIN32 - WSACleanup (); -#endif - return -1; - } - - // we have got out socket.. so now allocate the memory for the resend_cache - resend_cache.data = (char *) malloc (PKG_RESENDCACHE_SIZE); - resend_cache.fill = 0; - - // if we are the server set up my data - if (GT_MP_PTPM) { - strncpy (bman.players[0].name, bman.playername, LEN_PLAYERNAME); - bman.p_nr = 0; - bman.players[0].state = PSF_used; - if (bman.notifygamemaster) - gamesrv_sendmode (bman.maxplayer, 1); - } - - // if client send Data to the server - if (GT_MP_PTPS) { - network_server_port (bman.servername, bman.players[0].net.addr.host, - LEN_SERVERNAME, bman.players[0].net.addr.port, LEN_PORT); - - d_printf ("Connect To: %s[:%s]\n", bman.players[0].net.addr.host, - bman.players[0].net.addr.port); - - dns_filladdr (bman.players[0].net.addr.host, LEN_SERVERNAME, bman.players[0].net.addr.port, - LEN_PORT, bman.net_ai_family, &bman.players[0].net.addr.sAddr); - bman.players[0].net.addr.port[0] = bman.players[0].net.addr.host[0] = 0; - dns_filladdr (bman.players[0].net.addr.host, LEN_SERVERNAME, bman.players[0].net.addr.port, - LEN_PORT, bman.net_ai_family, &bman.players[0].net.addr.sAddr); - send_playerid (&bman.players[0].net.addr, bman.playername, NULL, NULL, -1, -1); - } - - return 0; -}; - - -/* -shutdown the network part -*/ -void -network_shutdown () -{ - int i; - - if (GT_MP_PTPM) { - for (i = 1; i < MAX_PLAYERS; i++) - if (bman.players[i].net.addr.host[0] != 0) - send_quit (&bman.players[i].net.addr, NULL, NULL); - if (bman.notifygamemaster) - gamesrv_quit (); - } - else if (bman.players[0].net.addr.host[0] != 0) - send_quit (&bman.players[0].net.addr, NULL, NULL); - - udp_close (bman.sock); - - if (resend_cache.data != NULL) - free (resend_cache.data); - - resend_cache.data = NULL; - resend_cache.fill = -1; - - bman.p_nr = -1; - bman.sock = -1; -#ifdef _WIN32 - WSACleanup (); -#endif -}; - - -int -net_check_timeout (int pl_nr) -{ - int timeout = UDP_TIMEOUT; - - if ((bman.players[pl_nr].state & (PSF_net + PSF_used)) == (PSF_used + PSF_net) - && timestamp - bman.players[pl_nr].net.timestamp > timeout - && bman.players[pl_nr].net.pingreq != bman.players[pl_nr].net.pingack) { - d_printf ("net_check_timeout pl_nr=%d, ack=%d, req=%d, timediff=%d\n", pl_nr, - bman.players[pl_nr].net.pingack, bman.players[pl_nr].net.pingreq, - timestamp - bman.players[pl_nr].net.timestamp); - bman.players[pl_nr].net.timestamp = timestamp; - bman.players[pl_nr].net.pingack = bman.players[pl_nr].net.pingreq; - send_ping (&bman.players[pl_nr].net.addr, bman.players[pl_nr].net.pingack + 100, - PKG_pingreq); - } - if ((bman.players[pl_nr].state & (PSF_net + PSF_used)) == (PSF_used + PSF_net) - && timestamp - bman.players[pl_nr].net.timestamp > timeout - && bman.players[pl_nr].net.pingreq == bman.players[pl_nr].net.pingack) { - d_printf ("net_check_timeout pl_nr=%d, ack=%d, req=%d, timediff=%d\n", pl_nr, - bman.players[pl_nr].net.pingack, bman.players[pl_nr].net.pingreq, - timestamp - bman.players[pl_nr].net.timestamp); - return 1; - } - return 0; -}; - - - -/* - Read data from the network and work with it -*/ -int -network_loop () -{ - char data[MAX_UDPDATA]; - struct pkg *packet = (struct pkg *) data; - int inlen, - i; - - _net_addr addr; - - if (bman.state != GS_running && bman.state != GS_ready) - timestamp = SDL_GetTicks (); - - /* - as long as we get any new data, work with them - */ - inlen = udp_get (bman.sock, data, MAX_UDPDATA, &addr.sAddr, bman.net_ai_family); - addr.port[0] = addr.host[0] = 0; - if (inlen > 0) - dns_filladdr (addr.host, LEN_SERVERNAME, addr.port, LEN_PORT, bman.net_ai_family, - &addr.sAddr); - - while (inlen > 0) { - - do_pkg (packet, &addr); - - // printf ("Network : inlen (%d) typ (%d) Size (%d)\n", inlen, packet->typ, pkglen); - inlen = udp_get (bman.sock, data, MAX_UDPDATA, &addr.sAddr, bman.net_ai_family); - addr.port[0] = addr.host[0] = 0; - if (inlen > 0) - dns_filladdr (addr.host, LEN_SERVERNAME, addr.port, LEN_PORT, bman.net_ai_family, - &addr.sAddr); - } - - /* - check here for old connections who aren't answering - */ - if (bman.state == GS_wait || bman.state == GS_ready || bman.state == GS_running) { - if (GT_MP_PTPS) { - if (net_check_timeout (0)) { - d_printf ("Server Timed Out\n"); - bman.state = GS_startup; - } - } - else if (GT_MP_PTPM) { - for (i = 1; i < MAX_PLAYERS; i++) - if (net_check_timeout (i)) { - d_printf ("Player %d Timed Out\n", i); - net_delplayer (i); - } - } - } - - /* - resend_cache.... - */ - rscache_loop (); - - /* - dynamic calibration of the network traffic option - */ - net_dyn_pkgoption (); - - return 0; -}; - - -/* - this is needed to draw the whole uppdate of everything -*/ -void -draw_netupdatestate () -{ - char text[255]; - int y = 0, - i; - SDL_Rect src, - dest; - - for (i = 0; i < MAX_PLAYERS; i++) - if (PS_IS_used (bman.players[i].state)) { - y += 48; - redraw_logo (0, y, gfx.res.x, y + 48); - - if (bman.players[i].gfx_nr != -1) { - dest.w = src.w = bman.players[i].gfx->smal_size.x; - dest.h = src.h = bman.players[i].gfx->smal_size.y; - src.x = bman.players[i].gfx->smal_size.x * down; - src.y = 0; - - dest.x = 50; - dest.y = y; - - SDL_BlitSurface (bman.players[i].gfx->smal_image, &src, gfx.screen, &dest); - gfx_AddUpdateRect (dest.x, dest.y, gfx.res.x - dest.x, dest.h); - } - - if (bman.players[i].net.net_istep == 0) - sprintf (text, "%s - State : READY", bman.players[i].name); - else - sprintf (text, "%s - State : DOWNLOAD", bman.players[i].name); - draw_text (70, y, text, 1); - - text[0] = 0; - if (bman.players[i].net.net_istep == 2) - sprintf (text, "Getting Field Data %d of %d.", bman.players[i].net.net_status, - bman.fieldsize.x); - - if (bman.players[i].net.net_istep == 1) - sprintf (text, "Getting Player Data %d of %d.", bman.players[i].net.net_status, - MAX_PLAYERS); - - draw_text (70, y + 16, text, 1); - } - return; -} - -/* - used to update settings at startup -*/ -void -net_change_playerid (int pl_nr, unsigned char senddata) -{ - int i; - - if (GT_MP_PTPM) { - /* - Send to all connected clients the update - */ - for (i = 1; i < MAX_PLAYERS; i++) - if (bman.players[i].net.addr.host[0] != 0) - send_playerid (&bman.players[i].net.addr, bman.players[pl_nr].name, - bman.players[pl_nr].net.addr.host, bman.players[pl_nr].net.addr.port, - pl_nr, bman.players[pl_nr].gfx_nr); - } - else { - /* - Send only to the Server the update and only if in_nr == bman.in_nr - */ - if (pl_nr == bman.p_nr && senddata) - send_playerid (&bman.players[0].net.addr, bman.players[pl_nr].name, - bman.players[pl_nr].net.addr.host, bman.players[pl_nr].net.addr.port, - pl_nr, bman.players[pl_nr].gfx_nr); - } - - player_set_gfx (&bman.players[pl_nr], bman.players[pl_nr].gfx_nr); -}; - - -/* - sets up everything for the network game.. - on servers the game field will be created and the clients will wait for the game data - within the network loop -*/ -void -net_new_gamedata () -{ - int done = 0, - keypressed = 0, - x, - y, - p, - i, - net_istep; // network init step - SDL_Event event; - Uint8 *keys; - Uint32 downtimestamp = 0; - - draw_logo (); - - if (GT_MP_PTPM) - draw_text (100, 0, "Waiting for the Clients", 1); - else - draw_text (100, 0, "Downloading Data", 1); - - SDL_Flip (gfx.screen); - - /* - prepare everything for the loop - */ - for (x = 0; x < MAX_PLAYERS; x++) { - bman.players[x].net.timestamp = 0; - bman.players[x].net.net_status = -1; - bman.players[x].net.net_istep = 2; - } - - y = -1; - if (GT_MP_PTPM) - net_istep = 0; - else - net_istep = 2; - - while (!done && bman.state == GS_update) { - /* the network thing */ - - network_loop (); - - /* if PTPM check if all players are ready */ - if (GT_MP_PTPM) { - for (p = 1, i = 1; p < MAX_PLAYERS; p++) - if (PS_IS_playing (bman.players[p].state) && bman.players[p].net.net_istep != 0) - i = 0; - if (i == 1) { /* all players are ready */ - done = 1; - bman.state = GS_ready; - } - } - - /* if PTPS get all data */ - if (GT_MP_PTPS) { - if (net_istep == 2) { - if ((y < bman.fieldsize.y - 1 && y == bman.players[bman.p_nr].net.net_status) - || y == -1) { - /* send field data req */ - y++; - downtimestamp = timestamp; - send_getfield (&bman.players[0].net.addr, y); - } - else if (y < bman.fieldsize.y && y != bman.players[bman.p_nr].net.net_status - && y >= 0 && timestamp - downtimestamp > DOWNLOAD_TIMEOUT) { - /* we have got no field data */ - y--; - } - else if (y == bman.fieldsize.y - 1 && bman.players[bman.p_nr].net.net_status == y) { - /* we have got all field data */ - y = -1; - bman.players[bman.p_nr].net.net_istep = --net_istep; - bman.players[bman.p_nr].net.net_status = -1; - } - } - - if (net_istep == 1) { - if ((y < MAX_PLAYERS - 1 && y == bman.players[bman.p_nr].net.net_status) || y == -1) { - /* send player date req */ - y++; - downtimestamp = timestamp; - send_getplayerdata (&bman.players[0].net.addr, y); - } - if (y < MAX_PLAYERS && y != bman.players[bman.p_nr].net.net_status && y >= 0 - && timestamp - downtimestamp > DOWNLOAD_TIMEOUT) { - /* we have got no player data */ - y--; - } - if (y == MAX_PLAYERS - 1 && bman.players[bman.p_nr].net.net_status == y) { - /* we have got all playerdata */ - y = -1; - bman.players[bman.p_nr].net.net_istep = --net_istep; - bman.players[bman.p_nr].net.net_status = -1; - downtimestamp = timestamp; - send_playerstatus (&bman.players[0].net.addr, bman.p_nr, 0, 0); - } - } - if (net_istep == 0 && bman.players[bman.p_nr].net.net_status == -1 - && timestamp - downtimestamp > DOWNLOAD_TIMEOUT) { - /* server did not send informations back */ - downtimestamp = timestamp; - send_playerstatus (&bman.players[0].net.addr, bman.p_nr, 0, 0); - } - } - - /* do the grafik work */ - draw_netupdatestate (); - SDL_Flip (gfx.screen); - - if (SDL_PollEvent (&event) != 0) - switch (event.type) { - case (SDL_QUIT): - bman.state = GS_quit; - bman.p_nr = -1; - done = 1; - } - - keys = SDL_GetKeyState (NULL); - - if (keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { - done = 1; - bman.p_nr = -1; - keypressed = 1; - bman.state = GS_startup; - } - - if (event.type == SDL_KEYUP) - keypressed = 0; - - timestamp = SDL_GetTicks (); // needed for time sync. - SDL_Delay (1); // we don't need here anything better - - /* player is only watching so just go after we have got everything - go to show the field */ - if (GT_MP_PTPS && bman.state == GS_update && net_istep == 0 - && bman.players[bman.p_nr].gfx_nr == -1) { - done = 1; - bman.state = GS_running; - } - } -}; - - -void -net_game_send_player (int p_nr) -{ - int p; - - if (GT_MP_PTPM) { - for (p = 0; p < MAX_PLAYERS; p++) - if (PS_IS_used (bman.players[p].state) && p != bman.p_nr) - send_playerdata (&bman.players[p].net.addr, p_nr, &bman.players[p_nr]); - } - else if (p_nr == bman.p_nr) { - for (p = 0; p < MAX_PLAYERS; p++) - if (PS_IS_used (bman.players[p].state) && p != bman.p_nr) - send_playerdata (&bman.players[p].net.addr, p_nr, &bman.players[p_nr]); - } -}; - - -void -net_game_send_playermove (int p_nr, int mustsend) -{ - int p; - _player *pl; - - for (p = 0; p < MAX_PLAYERS; p++) - if (PS_IS_used (bman.players[p].state) && p != bman.p_nr) { - pl = &bman.players[p_nr]; - - pl->net.pkgopt.send_to--; - if (pl->net.pkgopt.send_to <= 0 || mustsend) - send_playermove (&bman.players[p].net.addr, p_nr, pl); - - /* network packet send control */ - if (pl->net.pkgopt.send_to <= 0 || pl->net.pkgopt.send_to > pl->net.pkgopt.send_set) - pl->net.pkgopt.send_to = pl->net.pkgopt.send_set; - } -}; - -void -net_game_send_bomb (int p, int b) -{ - int pl; - - /* check if we are slave and send something else as dropping a bomb */ - if (GT_MP_PTPS && bman.players[p].bombs[b].state != BS_ticking) - return; - - d_printf ("Send BombData %d, %d\n", p, b); - - if (p < 0 || p >= MAX_PLAYERS || b < 0 || b >= MAX_BOMBS) - return; - - for (pl = 0; pl < MAX_PLAYERS; pl++) - if (PS_IS_used (bman.players[pl].state) && pl != bman.p_nr) - send_bombdata (&bman.players[pl].net.addr, p, b, &bman.players[p].bombs[b]); -}; - - -void -net_game_send_field (int x, int y) -{ - int pl; - - d_printf ("Send FieldData %d, %d\n", x, y); - - if (x < 0 || x >= MAX_FIELDSIZE_X || y < 0 || y >= MAX_FIELDSIZE_Y) - return; - - for (pl = 0; pl < MAX_PLAYERS; pl++) - if (PS_IS_used (bman.players[pl].state) && pl != bman.p_nr) - send_field (&bman.players[pl].net.addr, x, y, &bman.field[x][y]); -}; - - - -void -net_delplayer (int pl_nr) -{ - char host[LEN_SERVERNAME]; - char port[LEN_PORT]; - int i, - j = 1; - - d_printf ("net_delplayer (%d)\n", pl_nr); - - if (pl_nr == bman.p_nr) { - /* we're not wanted */ - network_shutdown (); - bman.state = GS_startup; - } - else { - strncpy (host, bman.players[pl_nr].net.addr.host, LEN_SERVERNAME); - strncpy (port, bman.players[pl_nr].net.addr.port, LEN_PORT); - - bman.players[pl_nr].state &= (0xFF - (PSF_used + PSF_alife)); // Delete the used flag - bman.players[pl_nr].net.net_istep = 0; // needed for disconnect during the update - bman.players_nr_s--; - bman.players[pl_nr].gfx_nr = -1; - - if (GT_MP_PTPM && (GS_WAITRUNNING || bman.state == GS_update)) { - for (i = 1; i < MAX_PLAYERS; i++) - if (PS_IS_used (bman.players[i].state)) { - send_quit (&bman.players[i].net.addr, host, port); - j++; - } - if (bman.notifygamemaster) - gamesrv_sendmode (bman.maxplayer, j); - } - } - - if (GT_MP_PTPS && pl_nr == 0) /* masterserver quit */ - bman.state = GS_startup; - - if (GT_MP_PTPM && bman.notifygamemaster) - gamesrv_sendmode (bman.maxplayer, bman.players_nr_s); -}; - - -void -net_game_fillsockaddr () -{ - /* Update all sockaddr before the game starts */ - int i; - - for (i = 0; i < MAX_PLAYERS; i++) - if (bman.players[i].net.addr.host[0] != 0 && bman.players[i].net.addr.host[0] != 0) - dns_filladdr (bman.players[i].net.addr.host, LEN_SERVERNAME, - bman.players[i].net.addr.port, LEN_PORT, bman.net_ai_family, - &bman.players[i].net.addr.sAddr); -}; - - -void -net_send_servermode () -{ - int i; - - for (i = 0; i < MAX_PLAYERS; i++) - if (PS_IS_used (bman.players[i].state) && i != bman.p_nr) - send_servermode (&bman.players[i].net.addr, i); - - if (GT_MP_PTPM && bman.notifygamemaster) /* send notification the the gamemaster */ - gamesrv_sendmode (bman.maxplayer, bman.players_nr_s); - -}; - - -/* sends to everyone an up to date playerlist*/ -void -net_send_players () -{ - int i, - j; - - for (j = 0; j < MAX_PLAYERS; j++) - if (PS_IS_used (bman.players[j].state) && j != bman.p_nr) - for (i = 0; i < MAX_PLAYERS; i++) - send_playerid (&bman.players[j].net.addr, bman.players[i].name, - bman.players[i].net.addr.host, bman.players[i].net.addr.port, i, - bman.players[i].gfx_nr); - -}; - - - -void -net_send_chat (char *text, signed char notigamesrv) -{ - int i; - - for (i = 0; i < MAX_PLAYERS; i++) - if (PS_IS_used (bman.players[i].state) && i != bman.p_nr) - send_chat (&bman.players[i].net.addr, text); - - if (GT_MP_PTPM && bman.notifygamemaster && notigamesrv == 1) /* send notification the the gamemaster */ - gamesrv_sendchat (text); -}; - - -void -net_game_send_ill (int p_nr) -{ - int i; - - d_printf ("net_game_send_ill (%d)\n", p_nr); - - for (i = 0; i < MAX_PLAYERS; i++) - if (PS_IS_used (bman.players[i].state) && i != bman.p_nr) - send_ill (&bman.players[i].net.addr, p_nr, &bman.players[p_nr]); -}; - - -/* - this routine will set up some things for the network game - after this the data should be transfered to the other clients. -*/ -void -net_new_game () -{ - int p, - i; - - // reset playerposition - for (i = 0; i < MAX_PLAYERS; i++) - bman.players[i].pos.y = bman.players[i].pos.x = -1; - - bman.players_nr = 0; - bman.players_nr_s = 0; - for (p = 0; p < MAX_PLAYERS; p++) { - bman.players[p].frame = 0; - bman.players[p].frameto = 0; - - if (PS_IS_used (bman.players[p].state)) { - bman.players_nr_s++; - if (bman.players[p].gfx_nr == -1) { - bman.players[p].gfx = NULL; - bman.players[p].state &= (0xff - (PSF_alife + PSF_playing)); - } - else { - bman.players[p].state |= PSF_alife + PSF_playing; - bman.players[p].gfx = &gfx.players[bman.players[p].gfx_nr]; - } - } - else - bman.players[p].state = 0; - - bman.players[p].bombs_n = START_BOMBS; - bman.players[p].range = START_RANGE; - bman.players[p].speed = START_SPEED; - for (i = 0; i < PI_max; i++) /* all types of illnes turn them off */ - bman.players[p].ill[i].to = 0; - bman.players[p].frame = 0; - bman.players[p].frameto = 0; - bman.players[p].d = 0; - - // reset bombs - for (i = 0; i < MAX_BOMBS; i++) { - bman.players[p].bombs[i].state = BS_off; - bman.players[p].bombs[i].ex_nr = -1; - } - } - - bman.players[bman.p_nr].state &= (0xFF - PSF_net); // we are the local player - bman.last_ex_nr = 1; -}; +/* $Id: network.c,v 1.16 2003/05/08 14:35:49 stpohle Exp $ */ +/* + network routines. +*/ + +#include "bomberclone.h" +#include "network.h" +#include "gamesrv.h" +#include "packets.h" +#include "gfx.h" + +int +network_server_port (char *server, char *host, int hostlen, char *port, int portlen) +{ + char *pos, + *pos2; + + if (host == NULL) + return -1; + + pos2 = pos = strchr (server, ':'); + + if (pos != NULL) + while (pos2 != NULL) { + pos = pos2; + pos2 = strchr (pos + 1, ':'); + } + + if (pos != NULL) { + // : für Portangabe gefunden + if (pos - server < hostlen) { + strncpy (host, server, pos - server); + host[pos - server] = 0; + if (pos[1] == 0) + sprintf (port, "11000"); + else + strcpy (port, pos + 1); + } + else { + return -1; + } + } + else { + // Portangabe wurde nicht gefunden und wird auf 0 gesetzt + strncpy (host, server, hostlen); + sprintf (port, "11000"); + } + + return 0; +}; + + +/* + try to work better with the network packet option +*/ +void +net_dyn_pkgoption () +{ + int p; + _net_pkgopt *npkg; + + for (p = 0; p < MAX_PLAYERS; p++) + if (PS_IS_netplayer (bman.players[p].state)) { + npkg = &bman.players[p].net.pkgopt; + + if (npkg->to_2sec > DYN_PKG_MAX_MISSING) { + if (npkg->send_set < 10) + npkg->send_set++; + npkg->to_2sec = 0; + npkg->to_timestamp = timestamp; + } + + if ((timestamp - npkg->to_timestamp > 2000) && npkg->to_2sec <= DYN_PKG_MIN_MISSING) { + if (npkg->send_set > PKG_SENDSETOPT) + npkg->send_set--; + npkg->to_2sec = 0; + npkg->to_timestamp = timestamp; + } + } +}; + + + + +/* + setup everything for the network loop +*/ +int +network_init () +{ + int i; +/* + we need it for the windows winsock +*/ +#ifdef _WIN32 + WSADATA wsaData; + + if (WSAStartup (MAKEWORD (1, 1), &wsaData) != 0) { + d_printf ("WSAStartup failed.\n"); + exit (1); + } +#endif + + bman.sock = -1; + bman.p_nr = -1; + + timestamp = SDL_GetTicks (); + + // reset playernumber and number of connected players + for (i = 0; i < MAX_PLAYERS; i++) { + bman.players[i].net.addr.host[0] = 0; + bman.players[i].net.addr.port[0] = 0; + bman.players[i].name[0] = 0; + bman.players[i].gfx_nr = -1; + bman.players[i].net.timestamp = timestamp; + bman.players[i].points = 0; + bman.players[i].wins = 0; + bman.players[i].net.pingreq = 20; + bman.players[i].net.pingack = 22; + bman.players[i].state = 0; + } + + bman.lastwinner = -1; + bman.players_nr_s = 1; + + // start the udp server + bman.sock = udp_server (bman.port, bman.net_ai_family); + + if (bman.sock < 0) { +#ifdef _WIN32 + WSACleanup (); +#endif + return -1; + } + + // we have got out socket.. so now allocate the memory for the resend_cache + resend_cache.data = (char *) malloc (PKG_RESENDCACHE_SIZE); + resend_cache.fill = 0; + + // if we are the server set up my data + if (GT_MP_PTPM) { + strncpy (bman.players[0].name, bman.playername, LEN_PLAYERNAME); + bman.p_nr = 0; + bman.players[0].state = PSF_used; + if (bman.notifygamemaster) + gamesrv_sendmode (bman.maxplayer, 1); + } + + // if client send Data to the server + if (GT_MP_PTPS) { + network_server_port (bman.servername, bman.players[0].net.addr.host, + LEN_SERVERNAME, bman.players[0].net.addr.port, LEN_PORT); + + d_printf ("Connect To: %s[:%s]\n", bman.players[0].net.addr.host, + bman.players[0].net.addr.port); + + dns_filladdr (bman.players[0].net.addr.host, LEN_SERVERNAME, bman.players[0].net.addr.port, + LEN_PORT, bman.net_ai_family, &bman.players[0].net.addr.sAddr); + bman.players[0].net.addr.port[0] = bman.players[0].net.addr.host[0] = 0; + dns_filladdr (bman.players[0].net.addr.host, LEN_SERVERNAME, bman.players[0].net.addr.port, + LEN_PORT, bman.net_ai_family, &bman.players[0].net.addr.sAddr); + send_playerid (&bman.players[0].net.addr, bman.playername, NULL, NULL, -1, -1); + } + + return 0; +}; + + +/* +shutdown the network part +*/ +void +network_shutdown () +{ + int i; + + if (GT_MP_PTPM) { + for (i = 1; i < MAX_PLAYERS; i++) + if (bman.players[i].net.addr.host[0] != 0) + send_quit (&bman.players[i].net.addr, NULL, NULL); + if (bman.notifygamemaster) + gamesrv_quit (); + } + else if (bman.players[0].net.addr.host[0] != 0) + send_quit (&bman.players[0].net.addr, NULL, NULL); + + udp_close (bman.sock); + + if (resend_cache.data != NULL) + free (resend_cache.data); + + resend_cache.data = NULL; + resend_cache.fill = -1; + + bman.p_nr = -1; + bman.sock = -1; +#ifdef _WIN32 + WSACleanup (); +#endif +}; + + +int +net_check_timeout (int pl_nr) +{ + int timeout = UDP_TIMEOUT; + + if ((bman.players[pl_nr].state & (PSF_net + PSF_used)) == (PSF_used + PSF_net) + && timestamp - bman.players[pl_nr].net.timestamp > timeout + && bman.players[pl_nr].net.pingreq != bman.players[pl_nr].net.pingack) { + d_printf ("net_check_timeout pl_nr=%d, ack=%d, req=%d, timediff=%d\n", pl_nr, + bman.players[pl_nr].net.pingack, bman.players[pl_nr].net.pingreq, + timestamp - bman.players[pl_nr].net.timestamp); + bman.players[pl_nr].net.timestamp = timestamp; + bman.players[pl_nr].net.pingack = bman.players[pl_nr].net.pingreq; + send_ping (&bman.players[pl_nr].net.addr, bman.players[pl_nr].net.pingack + 100, + PKG_pingreq); + } + if ((bman.players[pl_nr].state & (PSF_net + PSF_used)) == (PSF_used + PSF_net) + && timestamp - bman.players[pl_nr].net.timestamp > timeout + && bman.players[pl_nr].net.pingreq == bman.players[pl_nr].net.pingack) { + d_printf ("net_check_timeout pl_nr=%d, ack=%d, req=%d, timediff=%d\n", pl_nr, + bman.players[pl_nr].net.pingack, bman.players[pl_nr].net.pingreq, + timestamp - bman.players[pl_nr].net.timestamp); + return 1; + } + return 0; +}; + + + +/* + Read data from the network and work with it +*/ +int +network_loop () +{ + char data[MAX_UDPDATA]; + struct pkg *packet = (struct pkg *) data; + int inlen, + i; + + _net_addr addr; + + if (bman.state != GS_running && bman.state != GS_ready) + timestamp = SDL_GetTicks (); + + /* + as long as we get any new data, work with them + */ + inlen = udp_get (bman.sock, data, MAX_UDPDATA, &addr.sAddr, bman.net_ai_family); + addr.port[0] = addr.host[0] = 0; + if (inlen > 0) + dns_filladdr (addr.host, LEN_SERVERNAME, addr.port, LEN_PORT, bman.net_ai_family, + &addr.sAddr); + + while (inlen > 0) { + + do_pkg (packet, &addr); + + // printf ("Network : inlen (%d) typ (%d) Size (%d)\n", inlen, packet->typ, pkglen); + inlen = udp_get (bman.sock, data, MAX_UDPDATA, &addr.sAddr, bman.net_ai_family); + addr.port[0] = addr.host[0] = 0; + if (inlen > 0) + dns_filladdr (addr.host, LEN_SERVERNAME, addr.port, LEN_PORT, bman.net_ai_family, + &addr.sAddr); + } + + /* + check here for old connections who aren't answering + */ + if (bman.state == GS_wait || bman.state == GS_ready || bman.state == GS_running) { + if (GT_MP_PTPS) { + if (net_check_timeout (0)) { + d_printf ("Server Timed Out\n"); + bman.state = GS_startup; + } + } + else if (GT_MP_PTPM) { + for (i = 1; i < MAX_PLAYERS; i++) + if (net_check_timeout (i)) { + d_printf ("Player %d Timed Out\n", i); + net_delplayer (i); + } + } + } + + /* + resend_cache.... + */ + rscache_loop (); + + /* + dynamic calibration of the network traffic option + */ + net_dyn_pkgoption (); + + return 0; +}; + + +/* + this is needed to draw the whole uppdate of everything +*/ +void +draw_netupdatestate () +{ + char text[255]; + int y = 0, + i; + SDL_Rect src, + dest; + + for (i = 0; i < MAX_PLAYERS; i++) + if (PS_IS_used (bman.players[i].state)) { + y += 48; + redraw_logo (0, y, gfx.res.x, y + 48); + + if (bman.players[i].gfx_nr != -1) { + dest.w = src.w = bman.players[i].gfx->smal_size.x; + dest.h = src.h = bman.players[i].gfx->smal_size.y; + src.x = bman.players[i].gfx->smal_size.x * down; + src.y = 0; + + dest.x = 50; + dest.y = y; + + SDL_BlitSurface (bman.players[i].gfx->smal_image, &src, gfx.screen, &dest); + gfx_AddUpdateRect (dest.x, dest.y, gfx.res.x - dest.x, dest.h); + } + + if (bman.players[i].net.net_istep == 0) + sprintf (text, "%s - State : READY", bman.players[i].name); + else + sprintf (text, "%s - State : DOWNLOAD", bman.players[i].name); + draw_text (70, y, text, 1); + + text[0] = 0; + if (bman.players[i].net.net_istep == 2) + sprintf (text, "Getting Field Data %d of %d.", bman.players[i].net.net_status, + bman.fieldsize.x); + + if (bman.players[i].net.net_istep == 1) + sprintf (text, "Getting Player Data %d of %d.", bman.players[i].net.net_status, + MAX_PLAYERS); + + draw_text (70, y + 16, text, 1); + } + return; +} + +/* + used to update settings at startup +*/ +void +net_change_playerid (int pl_nr, unsigned char senddata) +{ + int i; + + if (GT_MP_PTPM) { + /* + Send to all connected clients the update + */ + for (i = 1; i < MAX_PLAYERS; i++) + if (bman.players[i].net.addr.host[0] != 0) + send_playerid (&bman.players[i].net.addr, bman.players[pl_nr].name, + bman.players[pl_nr].net.addr.host, bman.players[pl_nr].net.addr.port, + pl_nr, bman.players[pl_nr].gfx_nr); + } + else { + /* + Send only to the Server the update and only if in_nr == bman.in_nr + */ + if (pl_nr == bman.p_nr && senddata) + send_playerid (&bman.players[0].net.addr, bman.players[pl_nr].name, + bman.players[pl_nr].net.addr.host, bman.players[pl_nr].net.addr.port, + pl_nr, bman.players[pl_nr].gfx_nr); + } + + player_set_gfx (&bman.players[pl_nr], bman.players[pl_nr].gfx_nr); +}; + + +/* + sets up everything for the network game.. + on servers the game field will be created and the clients will wait for the game data + within the network loop +*/ +void +net_new_gamedata () +{ + int done = 0, + keypressed = 0, + x, + y, + p, + i, + net_istep; // network init step + SDL_Event event; + Uint8 *keys; + Uint32 downtimestamp = 0; + + draw_logo (); + + if (GT_MP_PTPM) + draw_text (100, 0, "Waiting for the Clients", 1); + else + draw_text (100, 0, "Downloading Data", 1); + + SDL_Flip (gfx.screen); + + /* + prepare everything for the loop + */ + for (x = 0; x < MAX_PLAYERS; x++) { + bman.players[x].net.timestamp = 0; + bman.players[x].net.net_status = -1; + bman.players[x].net.net_istep = 2; + } + + y = -1; + if (GT_MP_PTPM) + net_istep = 0; + else + net_istep = 2; + + while (!done && bman.state == GS_update) { + /* the network thing */ + + network_loop (); + + /* if PTPM check if all players are ready */ + if (GT_MP_PTPM) { + for (p = 1, i = 1; p < MAX_PLAYERS; p++) + if (PS_IS_playing (bman.players[p].state) && bman.players[p].net.net_istep != 0) + i = 0; + if (i == 1) { /* all players are ready */ + done = 1; + bman.state = GS_ready; + } + } + + /* if PTPS get all data */ + if (GT_MP_PTPS) { + if (net_istep == 2) { + if ((y < bman.fieldsize.y - 1 && y == bman.players[bman.p_nr].net.net_status) + || y == -1) { + /* send field data req */ + y++; + downtimestamp = timestamp; + send_getfield (&bman.players[0].net.addr, y); + } + else if (y < bman.fieldsize.y && y != bman.players[bman.p_nr].net.net_status + && y >= 0 && timestamp - downtimestamp > DOWNLOAD_TIMEOUT) { + /* we have got no field data */ + y--; + } + else if (y == bman.fieldsize.y - 1 && bman.players[bman.p_nr].net.net_status == y) { + /* we have got all field data */ + y = -1; + bman.players[bman.p_nr].net.net_istep = --net_istep; + bman.players[bman.p_nr].net.net_status = -1; + } + } + + if (net_istep == 1) { + if ((y < MAX_PLAYERS - 1 && y == bman.players[bman.p_nr].net.net_status) || y == -1) { + /* send player date req */ + y++; + downtimestamp = timestamp; + send_getplayerdata (&bman.players[0].net.addr, y); + } + if (y < MAX_PLAYERS && y != bman.players[bman.p_nr].net.net_status && y >= 0 + && timestamp - downtimestamp > DOWNLOAD_TIMEOUT) { + /* we have got no player data */ + y--; + } + if (y == MAX_PLAYERS - 1 && bman.players[bman.p_nr].net.net_status == y) { + /* we have got all playerdata */ + y = -1; + bman.players[bman.p_nr].net.net_istep = --net_istep; + bman.players[bman.p_nr].net.net_status = -1; + downtimestamp = timestamp; + send_playerstatus (&bman.players[0].net.addr, bman.p_nr, 0, 0); + } + } + if (net_istep == 0 && bman.players[bman.p_nr].net.net_status == -1 + && timestamp - downtimestamp > DOWNLOAD_TIMEOUT) { + /* server did not send informations back */ + downtimestamp = timestamp; + send_playerstatus (&bman.players[0].net.addr, bman.p_nr, 0, 0); + } + } + + /* do the grafik work */ + draw_netupdatestate (); + SDL_Flip (gfx.screen); + + if (SDL_PollEvent (&event) != 0) + switch (event.type) { + case (SDL_QUIT): + bman.state = GS_quit; + bman.p_nr = -1; + done = 1; + } + + keys = SDL_GetKeyState (NULL); + + if (keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { + done = 1; + bman.p_nr = -1; + keypressed = 1; + bman.state = GS_startup; + } + + if (event.type == SDL_KEYUP) + keypressed = 0; + + timestamp = SDL_GetTicks (); // needed for time sync. + SDL_Delay (1); // we don't need here anything better + + /* player is only watching so just go after we have got everything + go to show the field */ + if (GT_MP_PTPS && bman.state == GS_update && net_istep == 0 + && bman.players[bman.p_nr].gfx_nr == -1) { + done = 1; + bman.state = GS_running; + } + } +}; + + +void +net_game_send_player (int p_nr) +{ + int p; + + if (GT_MP_PTPM) { + for (p = 0; p < MAX_PLAYERS; p++) + if (PS_IS_used (bman.players[p].state) && p != bman.p_nr) + send_playerdata (&bman.players[p].net.addr, p_nr, &bman.players[p_nr]); + } + else if (p_nr == bman.p_nr) { + for (p = 0; p < MAX_PLAYERS; p++) + if (PS_IS_used (bman.players[p].state) && p != bman.p_nr) + send_playerdata (&bman.players[p].net.addr, p_nr, &bman.players[p_nr]); + } +}; + + +void +net_game_send_playermove (int p_nr, int mustsend) +{ + int p; + _player *pl; + + for (p = 0; p < MAX_PLAYERS; p++) + if (PS_IS_used (bman.players[p].state) && p != bman.p_nr) { + pl = &bman.players[p_nr]; + + pl->net.pkgopt.send_to--; + if (pl->net.pkgopt.send_to <= 0 || mustsend) + send_playermove (&bman.players[p].net.addr, p_nr, pl); + + /* network packet send control */ + if (pl->net.pkgopt.send_to <= 0 || pl->net.pkgopt.send_to > pl->net.pkgopt.send_set) + pl->net.pkgopt.send_to = pl->net.pkgopt.send_set; + } +}; + +void +net_game_send_bomb (int p, int b) +{ + int pl; + + /* check if we are slave and send something else as dropping a bomb */ + if (GT_MP_PTPS && bman.players[p].bombs[b].state != BS_ticking) + return; + + d_printf ("Send BombData %d, %d\n", p, b); + + if (p < 0 || p >= MAX_PLAYERS || b < 0 || b >= MAX_BOMBS) + return; + + for (pl = 0; pl < MAX_PLAYERS; pl++) + if (PS_IS_used (bman.players[pl].state) && pl != bman.p_nr) + send_bombdata (&bman.players[pl].net.addr, p, b, &bman.players[p].bombs[b]); +}; + + +void +net_game_send_field (int x, int y) +{ + int pl; + + d_printf ("Send FieldData %d, %d\n", x, y); + + if (x < 0 || x >= MAX_FIELDSIZE_X || y < 0 || y >= MAX_FIELDSIZE_Y) + return; + + for (pl = 0; pl < MAX_PLAYERS; pl++) + if (PS_IS_used (bman.players[pl].state) && pl != bman.p_nr) + send_field (&bman.players[pl].net.addr, x, y, &bman.field[x][y]); +}; + + + +void +net_delplayer (int pl_nr) +{ + char host[LEN_SERVERNAME]; + char port[LEN_PORT]; + int i, + j = 1; + + d_printf ("net_delplayer (%d)\n", pl_nr); + + if (pl_nr == bman.p_nr) { + /* we're not wanted */ + network_shutdown (); + bman.state = GS_startup; + } + else { + strncpy (host, bman.players[pl_nr].net.addr.host, LEN_SERVERNAME); + strncpy (port, bman.players[pl_nr].net.addr.port, LEN_PORT); + + bman.players[pl_nr].state &= (0xFF - (PSF_used + PSF_alife)); // Delete the used flag + bman.players[pl_nr].net.net_istep = 0; // needed for disconnect during the update + bman.players_nr_s--; + bman.players[pl_nr].gfx_nr = -1; + + if (GT_MP_PTPM && (GS_WAITRUNNING || bman.state == GS_update)) { + for (i = 1; i < MAX_PLAYERS; i++) + if (PS_IS_used (bman.players[i].state)) { + send_quit (&bman.players[i].net.addr, host, port); + j++; + } + if (bman.notifygamemaster) + gamesrv_sendmode (bman.maxplayer, j); + } + } + + if (GT_MP_PTPS && pl_nr == 0) /* masterserver quit */ + bman.state = GS_startup; + + if (GT_MP_PTPM && bman.notifygamemaster) + gamesrv_sendmode (bman.maxplayer, bman.players_nr_s); +}; + + +void +net_game_fillsockaddr () +{ + /* Update all sockaddr before the game starts */ + int i; + + for (i = 0; i < MAX_PLAYERS; i++) + if (bman.players[i].net.addr.host[0] != 0 && bman.players[i].net.addr.host[0] != 0) + dns_filladdr (bman.players[i].net.addr.host, LEN_SERVERNAME, + bman.players[i].net.addr.port, LEN_PORT, bman.net_ai_family, + &bman.players[i].net.addr.sAddr); +}; + + +void +net_send_servermode () +{ + int i; + + for (i = 0; i < MAX_PLAYERS; i++) + if (PS_IS_used (bman.players[i].state) && i != bman.p_nr) + send_servermode (&bman.players[i].net.addr, i); + + if (GT_MP_PTPM && bman.notifygamemaster) /* send notification the the gamemaster */ + gamesrv_sendmode (bman.maxplayer, bman.players_nr_s); + +}; + + +/* sends to everyone an up to date playerlist*/ +void +net_send_players () +{ + int i, + j; + + for (j = 0; j < MAX_PLAYERS; j++) + if (PS_IS_used (bman.players[j].state) && j != bman.p_nr) + for (i = 0; i < MAX_PLAYERS; i++) + send_playerid (&bman.players[j].net.addr, bman.players[i].name, + bman.players[i].net.addr.host, bman.players[i].net.addr.port, i, + bman.players[i].gfx_nr); + +}; + + + +void +net_send_chat (char *text, signed char notigamesrv) +{ + int i; + + for (i = 0; i < MAX_PLAYERS; i++) + if (PS_IS_used (bman.players[i].state) && i != bman.p_nr) + send_chat (&bman.players[i].net.addr, text); + + if (GT_MP_PTPM && bman.notifygamemaster && notigamesrv == 1) /* send notification the the gamemaster */ + gamesrv_sendchat (text); +}; + + +void +net_game_send_ill (int p_nr) +{ + int i; + + d_printf ("net_game_send_ill (%d)\n", p_nr); + + for (i = 0; i < MAX_PLAYERS; i++) + if (PS_IS_used (bman.players[i].state) && i != bman.p_nr) + send_ill (&bman.players[i].net.addr, p_nr, &bman.players[p_nr]); +}; + + +/* + this routine will set up some things for the network game + after this the data should be transfered to the other clients. +*/ +void +net_new_game () +{ + int p, + i; + + // reset playerposition + for (i = 0; i < MAX_PLAYERS; i++) + bman.players[i].pos.y = bman.players[i].pos.x = -1; + + bman.players_nr = 0; + bman.players_nr_s = 0; + for (p = 0; p < MAX_PLAYERS; p++) { + bman.players[p].frame = 0; + bman.players[p].frameto = 0; + + if (PS_IS_used (bman.players[p].state)) { + bman.players_nr_s++; + if (bman.players[p].gfx_nr == -1) { + bman.players[p].gfx = NULL; + bman.players[p].state &= (0xff - (PSF_alife + PSF_playing)); + } + else { + bman.players[p].state |= PSF_alife + PSF_playing; + bman.players[p].gfx = &gfx.players[bman.players[p].gfx_nr]; + } + } + else + bman.players[p].state = 0; + + bman.players[p].bombs_n = START_BOMBS; + bman.players[p].range = START_RANGE; + bman.players[p].speed = START_SPEED; + for (i = 0; i < PI_max; i++) /* all types of illnes turn them off */ + bman.players[p].ill[i].to = 0; + bman.players[p].frame = 0; + bman.players[p].frameto = 0; + bman.players[p].d = 0; + + // reset bombs + for (i = 0; i < MAX_BOMBS; i++) { + bman.players[p].bombs[i].state = BS_off; + bman.players[p].bombs[i].ex_nr = -1; + } + } + + bman.players[bman.p_nr].state &= (0xFF - PSF_net); // we are the local player + bman.last_ex_nr = 1; +}; diff --git a/src/network.h b/src/network.h index 3095956..4ba7201 100644 --- a/src/network.h +++ b/src/network.h @@ -1,104 +1,104 @@ -/* -network.h file... for everything what have to do with the network stuff -*/ - -#ifndef _NETWORK_H_ -#define _NETWORK_H_ - -#define MAX_UDPDATA 1024 -#define PKG_RESENDCACHE_SIZE (64*1024) -#define PKG_IN_INDEX_NUM 256 -#define RESENDCACHE_TIMEOUT 500 -#define RESENDCACHE_RETRY 10 -#define DOWNLOAD_TIMEOUT 2000 -#define DYN_PKG_MAX_MISSING 4 -#define DYN_PKG_MIN_MISSING 1 -#define PKG_SENDSETOPT 2 - -#define GT_MP_PTPM (bman.multitype == MT_ptpm && bman.gametype == GT_multi) -#define GT_MP_PTPS (bman.multitype == MT_ptps && bman.gametype == GT_multi) -#define GT_MP_PTP ((bman.multitype == MT_ptps || bman.multitype == MT_ptpm) && bman.gametype == GT_multi) - -#define GS_WAITRUNNING (bman.state == GS_wait || bman.state == GS_ready || bman.state == GS_running) - -#ifdef _WIN32 -#define _sockaddr sockaddr -#else -#define _sockaddr sockaddr_in6 -#endif - -struct __net_addr { // this holds the network data - char host[LEN_SERVERNAME]; - char port[LEN_PORT]; - struct _sockaddr sAddr; - signed char pl_nr; // pl_nr so we know it in the pkgcahce. -} typedef _net_addr; - - -struct __net_pkgopt { /* this will hold all needed data for the packet - timeout function */ - signed char send_to; // sending packet data (playermove) on 0 it will be send - signed char send_set; // start value for the packet data option (dynamic set) - int to_2sec; // how many unreached packets was send - Uint32 to_timestamp; -} typedef _net_pkgopt; - -struct __net_player { - _net_addr addr; // holds the address - int pingreq; // just to send a ping and to save the number in here - int pingack; // just to wait for an ping reply.. it will show up here - Uint32 timestamp; // time of the last incoming package - signed char net_istep; - signed char net_status; - _net_pkgopt pkgopt; // packet and network controll data -} typedef _net_player; - - -// network menu -extern void netmenu(); -extern void networkmenu_joingame (); -extern void networkmenu_options (); -extern void join_multiplayer_game (); -extern void host_multiplayer_game (); -extern void multiplayer_firstrun (); - -// network.c -extern int network_server_port (char *server, char *host, int hostlen, char *port, int portlen); -extern void network_shutdown (); -extern int network_init (); -extern int network_loop (); -extern void net_change_playerid (int pl_nr, unsigned char senddata); -extern void net_new_game (); -extern void net_new_gamedata (); -extern void net_game_send_player (int p_nr); -extern void net_game_send_playermove (int p_nr, int mustsend); -extern void net_game_send_bomb (int p, int b); -extern void net_game_send_field (int x, int y); -extern void net_game_fillsockaddr (); -extern void net_game_send_ill (int p_nr); -extern void net_delplayer (int pl_nr); -extern void draw_netupdatestate (); -extern void net_send_servermode (); -extern void net_send_players (); -extern int net_check_timeout (int pl_nr); -extern void net_dyn_pkgoption (); -extern void net_send_chat (char *text, signed char notigamesrv); - -// multiwait.c -extern void wait_for_players (); -extern void mw_init (); -extern void mw_shutdown (); -extern void mw_draw_gfxselect (int selgfx); -extern void mw_draw_status (); -extern void mw_wait_for_connect (); -extern void mw_draw_chat (); - -// udp.c -extern char *dns_net_getip (char *host); -extern int dns_filladdr (char *host, int hostlen, char *port, int portlen, int ai_family, struct _sockaddr *sAddr); -extern int udp_get (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family); -extern int udp_server (char *port, int ai_family); -extern void udp_send (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family); -extern void udp_close (int sock); - -#endif +/* +network.h file... for everything what have to do with the network stuff +*/ + +#ifndef _NETWORK_H_ +#define _NETWORK_H_ + +#define MAX_UDPDATA 1024 +#define PKG_RESENDCACHE_SIZE (64*1024) +#define PKG_IN_INDEX_NUM 256 +#define RESENDCACHE_TIMEOUT 500 +#define RESENDCACHE_RETRY 10 +#define DOWNLOAD_TIMEOUT 2000 +#define DYN_PKG_MAX_MISSING 4 +#define DYN_PKG_MIN_MISSING 1 +#define PKG_SENDSETOPT 2 + +#define GT_MP_PTPM (bman.multitype == MT_ptpm && bman.gametype == GT_multi) +#define GT_MP_PTPS (bman.multitype == MT_ptps && bman.gametype == GT_multi) +#define GT_MP_PTP ((bman.multitype == MT_ptps || bman.multitype == MT_ptpm) && bman.gametype == GT_multi) + +#define GS_WAITRUNNING (bman.state == GS_wait || bman.state == GS_ready || bman.state == GS_running) + +#ifdef _WIN32 +#define _sockaddr sockaddr +#else +#define _sockaddr sockaddr_in6 +#endif + +struct __net_addr { // this holds the network data + char host[LEN_SERVERNAME]; + char port[LEN_PORT]; + struct _sockaddr sAddr; + signed char pl_nr; // pl_nr so we know it in the pkgcahce. +} typedef _net_addr; + + +struct __net_pkgopt { /* this will hold all needed data for the packet + timeout function */ + signed char send_to; // sending packet data (playermove) on 0 it will be send + signed char send_set; // start value for the packet data option (dynamic set) + int to_2sec; // how many unreached packets was send + Uint32 to_timestamp; +} typedef _net_pkgopt; + +struct __net_player { + _net_addr addr; // holds the address + int pingreq; // just to send a ping and to save the number in here + int pingack; // just to wait for an ping reply.. it will show up here + Uint32 timestamp; // time of the last incoming package + signed char net_istep; + signed char net_status; + _net_pkgopt pkgopt; // packet and network controll data +} typedef _net_player; + + +// network menu +extern void netmenu(); +extern void networkmenu_joingame (); +extern void networkmenu_options (); +extern void join_multiplayer_game (); +extern void host_multiplayer_game (); +extern void multiplayer_firstrun (); + +// network.c +extern int network_server_port (char *server, char *host, int hostlen, char *port, int portlen); +extern void network_shutdown (); +extern int network_init (); +extern int network_loop (); +extern void net_change_playerid (int pl_nr, unsigned char senddata); +extern void net_new_game (); +extern void net_new_gamedata (); +extern void net_game_send_player (int p_nr); +extern void net_game_send_playermove (int p_nr, int mustsend); +extern void net_game_send_bomb (int p, int b); +extern void net_game_send_field (int x, int y); +extern void net_game_fillsockaddr (); +extern void net_game_send_ill (int p_nr); +extern void net_delplayer (int pl_nr); +extern void draw_netupdatestate (); +extern void net_send_servermode (); +extern void net_send_players (); +extern int net_check_timeout (int pl_nr); +extern void net_dyn_pkgoption (); +extern void net_send_chat (char *text, signed char notigamesrv); + +// multiwait.c +extern void wait_for_players (); +extern void mw_init (); +extern void mw_shutdown (); +extern void mw_draw_gfxselect (int selgfx); +extern void mw_draw_status (); +extern void mw_wait_for_connect (); +extern void mw_draw_chat (); + +// udp.c +extern char *dns_net_getip (char *host); +extern int dns_filladdr (char *host, int hostlen, char *port, int portlen, int ai_family, struct _sockaddr *sAddr); +extern int udp_get (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family); +extern int udp_server (char *port, int ai_family); +extern void udp_send (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family); +extern void udp_close (int sock); + +#endif diff --git a/src/packets.c b/src/packets.c index a711a63..eb4611a 100644 --- a/src/packets.c +++ b/src/packets.c @@ -1,1049 +1,1049 @@ -/* network commands and data */ - -#include "basic.h" -#include "bomberclone.h" -#include "network.h" -#include "gamesrv.h" -#include "packets.h" -#include "chat.h" - -extern _point debug_field; -extern int debug_lastping; - -static short int pkg_lastid; /* the packet id, this will only counted - up nothing more.. if we are at 0x10000 - we will start at 0 */ - -struct _resend_cache resend_cache; -struct _inpkg_index inpkg_index[PKG_IN_INDEX_NUM]; -int inpkg_index_pos = 0; - - -int -get_player_nr (char *host, char *port) -{ - int i, - res; - - for (i = 0, res = -1; (i < MAX_PLAYERS && res == -1); i++) { - if (bman.players[i].net.addr.host[0] != 0) - if ((strcmp (bman.players[i].net.addr.host, host) == 0) && - (strcmp (bman.players[i].net.addr.port, port) == 0)) - res = i; - } - return res; -} - - -void -send_error (_net_addr * addr, char *text) -{ - struct pkg_error p_err; - - d_printf ("Send Network Error : %s\n", text); - strncpy (p_err.text, text, 127); - p_err.h.typ = PKG_error; - p_err.h.flags = 0; - p_err.h.len = sizeof (struct pkg_error); - p_err.nr = 0; - - send_pkg ((struct pkg *) &p_err, addr); -}; - - -int -do_error (struct pkg_error *data, _net_addr * addr) -{ - d_printf ("Network Error : '%s'\n", data->text); - menu_displaymessage ("Network Error", data->text); - if (data->nr == 1) - return -1; - else - return 0; -}; - - -/* -update the playerinformations in the game -*/ -void -do_playerid (struct pkg_playerid *p_id, _net_addr * addr) -{ - _player *pl; - int i, - j, - vma, - vmi, - vsu; - char text[255]; - - sscanf (VERSION, "%d.%d.%d", &vma, &vmi, &vsu); - - if (p_id->ver_sub != vsu || p_id->ver_major != vma || p_id->ver_minor != vmi) { - sprintf (text, "Version Error - Host/Server Version: %s", VERSION); - send_error (addr, text); - return; - } - d_printf ("do_playerid (From:%s:%s pl_nr=%d) Player(name:%s [%s:%s], pl_nr:%d)\n", addr->host, - addr->port, addr->pl_nr, p_id->name, p_id->host, p_id->port, p_id->pl_nr); - - /* As Server/Master Only change settings, or do ignore them if we are not in GS_wait */ - if (((GT_MP_PTPM && (bman.state == GS_wait && addr->pl_nr != -1)) || // PTPM change setting - (GT_MP_PTPS && addr->pl_nr == 0)) && p_id->pl_nr >= 0 && p_id->pl_nr < MAX_PLAYERS) { // PTPS and information send by PTPM - - pl = &bman.players[p_id->pl_nr]; - - pl->state = p_id->state; - if (p_id->pl_nr != bman.p_nr && PS_IS_used (pl->state)) - pl->state |= PSF_net; - else - pl->state &= (0xff - PSF_net); - - player_set_gfx (pl, p_id->gfx_nr); - strncpy (pl->name, p_id->name, LEN_PLAYERNAME); - pl->net.timestamp = timestamp; - pl->net.pingreq = pl->net.pingack + 5; - - if (p_id->host[0] != 0) { - pl->net.addr.pl_nr = addr->pl_nr; - strncpy (pl->net.addr.host, p_id->host, LEN_SERVERNAME); - strncpy (pl->net.addr.port, p_id->port, LEN_PORT); - dns_filladdr (pl->net.addr.host, LEN_SERVERNAME, - pl->net.addr.port, LEN_PORT, bman.net_ai_family, &pl->net.addr.sAddr); - } - - if (GT_MP_PTPS) { - pl->points = p_id->points; - pl->wins = p_id->wins; - } - } - - /* add player into the list if there is something free */ - else if ((addr->pl_nr == -1 || p_id->pl_nr == -1) && GS_WAITRUNNING && GT_MP_PTPM) { - - /* find free player slot */ - if (addr->pl_nr == -1) - for (i = 0; (i < MAX_PLAYERS && PS_IS_used (bman.players[i].state)); i++); - else - i = addr->pl_nr; - - if ((i < MAX_PLAYERS) && (i < bman.maxplayer)) { - /* free in_pl slot ... fill in data */ - pl = &bman.players[i]; - - pl->state = PSF_used + PSF_net; - if (strncmp (pl->name, p_id->name, LEN_PLAYERNAME) == 0) - d_printf ("***** Player ReJoined : Nr:[%d] Name:%10s\n", i, p_id->name); - else { - d_printf ("***** Player Added : Nr:[%d] Name:%10s\n", i, p_id->name); - pl->points = 0; - pl->wins = 0; - } - strncpy (pl->name, p_id->name, LEN_PLAYERNAME); - player_set_gfx (pl, p_id->gfx_nr); - - /* Reset the network data */ - pl->net.timestamp = timestamp; - pl->net.pkgopt.to_timestamp = timestamp; - pl->net.pkgopt.to_2sec = 0; - pl->net.pkgopt.send_to = 0; - pl->net.pkgopt.send_set = PKG_SENDSETOPT; - - strncpy (pl->net.addr.host, addr->host, LEN_SERVERNAME); - strncpy (pl->net.addr.port, addr->port, LEN_PORT); - dns_filladdr (pl->net.addr.host, LEN_SERVERNAME, pl->net.addr.port, LEN_PORT, - bman.net_ai_family, &pl->net.addr.sAddr); - pl->net.addr.pl_nr = i; - bman.players_nr_s++; - - /* send to the new client the servermode and the complete playerlist */ - send_servermode (addr, i); - for (j = 0; j < MAX_PLAYERS; j++) - if (bman.players[j].net.addr.host[0] != 0 || bman.players[j].name[0] != 0) - send_playerid (addr, bman.players[j].name, bman.players[j].net.addr.host, - bman.players[j].net.addr.port, j, bman.players[j].gfx_nr); - - addr->pl_nr = i; - for (j = 0, i = 0; i < bman.maxplayer; i++) - if (PS_IS_used (bman.players[i].state)) - j++; - if (bman.notifygamemaster) - gamesrv_sendmode (bman.maxplayer, j); - } - - else if (GS_WAITRUNNING) { - send_error (addr, "No Free Playerslot found\n"); - return; - } - - else if (!GS_WAITRUNNING) { - send_error (addr, "Game is in the wrong mode.\n"); - return; - } - } - - /* Send all connected players the new PlayerID */ - if (GS_WAITRUNNING && addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS) - net_change_playerid (addr->pl_nr, (GT_MP_PTPM)); - - d_playerdetail ("*** PLAYER List ***"); -}; - - -void -send_playerid (_net_addr * addr, char *name, char *pladdr, char *plport, int pl_nr, int gfx_nr) -{ - struct pkg_playerid p_id; - int vmi, - vma, vsu; - - d_printf ("send_playerid SendTo: %s:%s (Name:%16s p_nr:%d)\n", addr->host, addr->port, name, - pl_nr); - sscanf (VERSION, "%d.%d.%d", &vma, &vmi, &vsu); - - p_id.h.typ = PKG_playerid; - p_id.h.flags = PKGF_ackreq; - p_id.h.len = sizeof (struct pkg_playerid); - p_id.ver_sub = vsu; - p_id.ver_major = vma; - p_id.ver_minor = vmi; - - strncpy (p_id.name, name, LEN_PLAYERNAME); - if (pladdr == NULL) - p_id.host[0] = 0; - else - strncpy (p_id.host, pladdr, LEN_SERVERNAME); - - if (plport == NULL) - p_id.port[0] = 0; - - else - strncpy (p_id.port, plport, LEN_PORT); - - p_id.pl_nr = pl_nr; - p_id.gfx_nr = gfx_nr; - if (pl_nr != -1) { - p_id.points = bman.players[pl_nr].points; - p_id.wins = bman.players[pl_nr].wins; - p_id.state = bman.players[pl_nr].state; - } - else { - p_id.points = 0; - p_id.wins = 0; - p_id.state = 0; - } - - send_pkg ((struct pkg *) &p_id, addr); -}; - - -void -do_servermode (struct pkg_servermode *s_mod, _net_addr * addr) -{ - if (addr->pl_nr == -1) - return; - - d_printf ("do_servermode (%s:%s) state = %d\n", addr->host, addr->port, s_mod->state); - - if (s_mod->pl_nr >= 0 && s_mod->pl_nr < MAX_PLAYERS) { - bman.p_nr = s_mod->pl_nr; - bman.players[bman.p_nr].state &= (0xFF - PSF_net); - strncpy (bman.players[s_mod->pl_nr].name, bman.playername, LEN_PLAYERNAME); - } - - if (s_mod->type == GT_multi) - bman.gametype = GT_multi; - else - bman.gametype = GT_single; - - bman.state = s_mod->state; - if (s_mod->multitype == MT_ptpm) - bman.multitype = MT_ptps; - - bman.players_nr_s = s_mod->players; - bman.lastwinner = s_mod->last_winner; - - if (GT_MP_PTPS) { - bman.fieldsize.x = s_mod->fieldsize_x; - bman.fieldsize.y = s_mod->fieldsize_y; - } - strncpy (gfx.tileset, s_mod->tileset, LEN_TILESETNAME); -}; - - -void -send_servermode (_net_addr * addr, int pl_nr) -{ - struct pkg_servermode s_mod; - d_printf ("Send ServerMode\n"); - - s_mod.h.typ = PKG_servermode; - s_mod.h.len = sizeof (struct pkg_servermode); - s_mod.h.flags = PKGF_ackreq; - s_mod.type = bman.gametype; - s_mod.state = bman.state; - s_mod.multitype = bman.multitype; - s_mod.players = bman.players_nr_s; - s_mod.maxplayer = bman.maxplayer; - s_mod.pl_nr = pl_nr; - s_mod.last_winner = bman.lastwinner; - s_mod.fieldsize_x = bman.fieldsize.x; - s_mod.fieldsize_y = bman.fieldsize.y; - strncpy (s_mod.tileset, gfx.tileset, LEN_TILESETNAME); - send_pkg ((struct pkg *) &s_mod, addr); -}; - - -void -send_field (_net_addr * addr, int x, int y, _field * field) -{ - struct pkg_field f_dat; - - d_printf ("send_field [%d,%d]\n", x, y); - - f_dat.h.typ = PKG_field; - f_dat.h.len = sizeof (struct pkg_field); - f_dat.h.flags = PKGF_ackreq; - - f_dat.x = x; - f_dat.y = y; - - if (x < 0 || x >= bman.fieldsize.x || y < 0 || y >= bman.fieldsize.y) - return; - memcpy (&f_dat.field, &bman.field[x][y], sizeof (_field)); - - send_pkg ((struct pkg *) &f_dat, addr); -}; - - -void -do_field (struct pkg_field *f_dat, _net_addr * addr) -{ - if (addr->pl_nr == -1) - return; - - if (f_dat->x < bman.fieldsize.x && f_dat->y < bman.fieldsize.y) { - memcpy (&bman.field[f_dat->x][f_dat->y], &f_dat->field, sizeof (_field)); - } - if (bman.state == GS_running) - draw_stone (f_dat->x, f_dat->y); - - if (f_dat->field.ex_nr > bman.last_ex_nr) - bman.last_ex_nr = f_dat->field.ex_nr; - - d_printf ("do_field (%d,%d) ex_nr = %d, special = %d, type = %d\n", f_dat->x, f_dat->y, - f_dat->field.ex_nr, f_dat->field.special, f_dat->field.type); -}; - - -void -do_ping (struct pkg_ping *p_dat, _net_addr * addr) -{ - if (addr->pl_nr == -1) - return; - - if (p_dat->h.typ == PKG_pingack) - /* ping was an answer */ - bman.players[addr->pl_nr].net.pingack = p_dat->data; - - else - /* send the answer */ - send_ping (addr, p_dat->data, PKG_pingack); - - d_printf ("do_ping pl_nr[%d] (%s:%s) req=%d, ack=%d\n", addr->pl_nr, addr->host, - addr->port, bman.players[addr->pl_nr].net.pingreq, bman.players[addr->pl_nr].net.pingack); -}; - - -void -send_ping (_net_addr * addr, int data, unsigned char typ) -{ - struct pkg_ping p_dat; - - if (addr->pl_nr == -1) - return; - - p_dat.h.len = sizeof (struct pkg_ping); - p_dat.h.flags = 0; - - if (typ == PKG_pingack) { - p_dat.h.typ = typ; - p_dat.data = data; - send_pkg ((struct pkg *) &p_dat, addr); - } - - else if (typ == PKG_pingreq) { - p_dat.h.typ = typ; - p_dat.data = data; - send_pkg ((struct pkg *) &p_dat, addr); - } - - d_printf ("send_ping Player[%d] (%s:%s) req=%d, ack=%d\n", addr->pl_nr, addr->host, addr->port, - bman.players[addr->pl_nr].net.pingreq, bman.players[addr->pl_nr].net.pingack); - - bman.players[addr->pl_nr].net.timestamp = timestamp; /* we need to set it here, so we can check - for the timeout again */ -}; - - -void -send_playerdata (_net_addr * addr, int p_nr, _player * pl) -{ - struct pkg_playerdata p_dat; - - p_dat.h.typ = PKG_playerdata; - p_dat.h.len = sizeof (struct pkg_playerdata); - - if (bman.state == GS_update) - p_dat.h.flags = 0; - else - p_dat.h.flags = PKGF_ackreq; - - p_dat.pos.x = pl->pos.x; - p_dat.pos.y = pl->pos.y; - p_dat.bombs_n = pl->bombs_n; - p_dat.d = pl->d; - p_dat.range = pl->range; - p_dat.gfx_nr = pl->gfx_nr; - p_dat.state = pl->state; - p_dat.wins = pl->wins; - p_dat.points = pl->points; - p_dat.dead_by = pl->dead_by; - p_dat.frame = pl->frame; - p_dat.p_nr = p_nr; - - send_pkg ((struct pkg *) &p_dat, addr); -}; - - -void -do_playerdata (struct pkg_playerdata *p_dat, _net_addr * addr) -{ - _player *pl; - - if (addr->pl_nr == -1) - return; - - if (p_dat->p_nr < 0 || p_dat->p_nr >= MAX_PLAYERS) - return; - - d_printf ("do_playerdata (From: %d) p_nr: %d\n", addr->pl_nr, p_dat->p_nr); - - pl = &bman.players[p_dat->p_nr]; - player_set_gfx (pl, p_dat->gfx_nr); - - if (bman.state == GS_running && bman.p_nr != p_dat->p_nr) { - pl->points = p_dat->points; - pl->dead_by = p_dat->dead_by; - } - else if (bman.state != GS_running || bman.p_nr != p_dat->p_nr) { - pl->pos.x = p_dat->pos.x; - pl->pos.y = p_dat->pos.y; - pl->dead_by = p_dat->dead_by; - pl->points = p_dat->points; - pl->d = p_dat->d; - pl->bombs_n = p_dat->bombs_n; - pl->range = p_dat->range; - pl->frame = p_dat->frame; - pl->state = p_dat->state; - } - - if (p_dat->dead_by < 0 || p_dat->dead_by >= MAX_PLAYERS) /* set player state no matter what */ - pl->state = p_dat->state; - else { /* player died in the game */ - /* check if the player just died */ - if (PS_IS_alife (pl->state) && PS_IS_dead (p_dat->state)) { - /* player just died */ - if (p_dat->p_nr != p_dat->dead_by) { - bman.players[p_dat->dead_by].points++; - net_game_send_player (p_dat->dead_by); - } - } - pl->state = p_dat->state; - } - - /* set the state of the player */ - if (p_dat->p_nr != bman.p_nr && PS_IS_used (pl->state)) - pl->state |= PSF_net; - else - pl->state &= (0xff - PSF_net); - - if (p_dat->gfx_nr == -1) - pl->state &= (0xff - PSF_alife); - - if (bman.state == GS_update && PS_IS_used (p_dat->state)) - bman.players_nr_s++; - - if (bman.state == GS_update && bman.players[bman.p_nr].net.net_istep == 1) - bman.players[bman.p_nr].net.net_status = p_dat->p_nr; -} - - -void -send_playermove (_net_addr * addr, int p_nr, _player * pl) -{ - struct pkg_playermove p_dat; - - p_dat.h.typ = PKG_playermove; - p_dat.h.len = sizeof (struct pkg_playermove); - p_dat.h.flags = 0; - - p_dat.pos.x = pl->pos.x; - p_dat.pos.y = pl->pos.y; - p_dat.m = pl->m; - p_dat.d = pl->d; - p_dat.p_nr = p_nr; - p_dat.speed = pl->speed; - - send_pkg ((struct pkg *) &p_dat, addr); -}; - - -void -do_ill (struct pkg_ill *ill, _net_addr * addr) -{ - int i; - - if (addr->pl_nr == -1) - return; - - d_printf ("do_ill (From: %d) For Player %d\n", addr->pl_nr, ill->pl_nr); - if (ill->pl_nr < 0 || ill->pl_nr >= MAX_PLAYERS || ill->pl_nr == bman.p_nr) - return; - - for (i = 0; i < PI_max; i++) - bman.players[ill->pl_nr].ill[i].to = ill->to[i]; -}; - - - -void -send_ill (_net_addr * addr, int p_nr, _player * pl) -{ - struct pkg_ill ill; - int i; - - ill.h.typ = PKG_ill; - ill.h.len = sizeof (struct pkg_ill); - ill.h.flags = PKGF_ackreq; - - ill.pl_nr = p_nr; - for (i = 0; i < PI_max; i++) - ill.to[i] = pl->ill[i].to; - - send_pkg ((struct pkg *) &ill, addr); -}; - - -void -do_playermove (struct pkg_playermove *p_dat, _net_addr * addr) -{ - _player *pl; - - if (addr->pl_nr == -1) - return; - - if (p_dat->p_nr == -1) - return; - - /* check if the right player is sending the information */ - pl = &bman.players[p_dat->p_nr]; - if (addr->pl_nr != 0 && addr->pl_nr != p_dat->p_nr) - return; - - pl->m = p_dat->m; - pl->d = p_dat->d; - pl->speed = p_dat->speed; - pl->pos.x = p_dat->pos.x; - pl->pos.y = p_dat->pos.y; -} - - -void -do_bombdata (struct pkg_bombdata *b_dat, _net_addr * addr) -{ - _bomb *bomb; - - if (addr->pl_nr == -1) - return; - - if (b_dat->p_nr >= MAX_PLAYERS || b_dat->b_nr >= MAX_BOMBS) { - d_printf ("Bomb Error\n"); - return; - } - - if (b_dat->state == BS_off) - return; // if there was a bomb let it explose don't delete the bomb - - d_printf ("do_bombdata [%d,%d] Player: %d Bomb: %d, ex_nr:%d\n", b_dat->x, b_dat->y, - b_dat->p_nr, b_dat->b_nr, b_dat->ex_nr); - - bomb = &bman.players[b_dat->p_nr].bombs[b_dat->b_nr]; - if (bomb->state == BS_exploding) { - d_printf ("do_bombdata ---> bomb is already exploding\n"); - return; - } - - if ((bomb->pos.x != b_dat->x || bomb->pos.y != b_dat->y) && bomb->state == BS_exploding - && b_dat->state != BS_exploding) - d_printf ("do_bombdata WARNING : bomb explosion haven't finished\n"); - - bomb->pos.x = b_dat->x; - bomb->pos.y = b_dat->y; - if (bomb->state != BS_ticking) - bomb->to = b_dat->to; - bomb->r = b_dat->r; - bomb->ex_nr = b_dat->ex_nr; - bomb->state = b_dat->state; - if (bomb->state == BS_exploding) - bomb_explode (b_dat->p_nr, b_dat->b_nr); - - if (bomb->ex_nr > bman.last_ex_nr) - bman.last_ex_nr = bomb->ex_nr; -}; - - -void -send_bombdata (_net_addr * addr, int p, int b, _bomb * bomb) -{ - struct pkg_bombdata b_dat; - - b_dat.h.typ = PKG_bombdata; - b_dat.h.len = sizeof (struct pkg_bombdata); - b_dat.x = bomb->pos.x; - b_dat.y = bomb->pos.y; - b_dat.to = bomb->to; - b_dat.r = bomb->r; - b_dat.ex_nr = bomb->ex_nr; - b_dat.state = bomb->state; - b_dat.b_nr = b; - b_dat.p_nr = p; - b_dat.h.flags = PKGF_ackreq; - - send_pkg ((struct pkg *) &b_dat, addr); -}; - - -void -send_quit (_net_addr * addr, char *plhost, char *plport) -{ - struct pkg_quit q_dat; - - d_printf ("send_quit (%s:%s) plhost (%s:%s)\n", addr->host, addr->port, plhost, plport); - - q_dat.h.typ = PKG_quit; - q_dat.h.flags = 0; - q_dat.h.len = sizeof (struct pkg_quit); - - if (plhost == NULL) { - q_dat.host[0] = 0; - q_dat.port[0] = 0; - } - - else { - strncpy (q_dat.host, plhost, LEN_SERVERNAME); - strncpy (q_dat.port, plport, LEN_PORT); - } - - send_pkg ((struct pkg *) &q_dat, addr); -}; - - -void -do_quit (struct pkg_quit *q_dat, _net_addr * addr) -{ - d_printf ("do_quit (%s:%s) pl_nr = %d\n", addr->host, addr->port, addr->pl_nr); - if (addr->pl_nr == -1) - return; - - if (q_dat->host[0] == 0) - /* the player who send this quit */ - net_delplayer (addr->pl_nr); - else { - /* delete the player with the giving address */ - int pl_nr = get_player_nr (q_dat->host, q_dat->port); - if (pl_nr == -1) - return; - - net_delplayer (pl_nr); - } -}; - - -void -send_getfield (_net_addr * addr, int line) -{ - struct pkg_getfield gf_dat; - - gf_dat.h.typ = PKG_getfield; - gf_dat.h.len = sizeof (struct pkg_getfield); - gf_dat.h.flags = 0; - gf_dat.line = line; - send_pkg ((struct pkg *) &gf_dat, addr); -}; - - -void -do_getfield (struct pkg_getfield *gf_dat, _net_addr * addr) -{ - if (addr->pl_nr == -1) - return; - - if (gf_dat->line < 0 || gf_dat->line >= MAX_FIELDSIZE_Y) - return; - - if (addr->pl_nr != -1 && bman.state == GS_update && GT_MP_PTPM) { - if (addr->pl_nr > 0 && addr->pl_nr < MAX_PLAYERS) { - bman.players[addr->pl_nr].net.net_status = gf_dat->line; - bman.players[addr->pl_nr].net.net_istep = 2; - } - } - - send_fieldline (addr, gf_dat->line); -}; - - -void -send_fieldline (_net_addr * addr, int line) -{ - int i, - j; - struct pkg_fieldline f_dat; - - f_dat.h.typ = PKG_fieldline; - f_dat.h.len = sizeof (struct pkg_fieldline); - f_dat.h.flags = 0; - f_dat.line = line; - - if (line < 0 || line >= MAX_FIELDSIZE_Y) - return; - - for (i = 0; i < MAX_FIELDSIZE_X; i++) { - f_dat.type[i] = bman.field[i][line].type; - f_dat.special[i] = bman.field[i][line].special; - bman.field[i][line].frame = 0; - bman.field[i][line].frameto = 0; - bman.field[i][line].ex_nr = 0; - for (j = 0; j < 4; j++) - bman.field[i][line].ex[j].frame = bman.field[i][line].ex[j].count = 0; - } - send_pkg ((struct pkg *) &f_dat, addr); -}; - - -void -do_fieldline (struct pkg_fieldline *f_dat, _net_addr * addr) -{ - int i, d; - - if (addr->pl_nr == -1) - return; - - if (addr->pl_nr != 0) { - /* the data we have got are not from the server */ - d_printf ("do_fieldline: the data we have got are not from the server\n"); - return; - } - - if (f_dat->line < 0 || f_dat->line >= MAX_FIELDSIZE_Y) { - /* the line number is wrong */ - d_printf ("do_fieldline: the line number is not correct\n"); - return; - } - - if (bman.state == GS_update && bman.players[bman.p_nr].net.net_istep == 2) - bman.players[bman.p_nr].net.net_status = f_dat->line; - - for (i = 0; i < MAX_FIELDSIZE_X; i++) { - bman.field[i][f_dat->line].type = f_dat->type[i]; - bman.field[i][f_dat->line].special = f_dat->special[i]; - for (d = 0; d < 4; d++) - bman.field[i][f_dat->line].ex[d].frame = bman.field[i][f_dat->line].ex[d].count = 0; - } -}; - - -void -send_getplayerdata (_net_addr * addr, int pl) -{ - struct pkg_getplayerdata gp_dat; - gp_dat.h.typ = PKG_getplayerdata; - gp_dat.h.len = sizeof (struct pkg_getplayerdata); - gp_dat.pl_nr = pl; - gp_dat.h.flags = 0; - send_pkg ((struct pkg *) &gp_dat, addr); -}; - - -void -do_getplayerdata (struct pkg_getplayerdata *gp_dat, _net_addr * addr) -{ - if (addr->pl_nr == -1) - return; - - if (gp_dat->pl_nr < 0 || gp_dat->pl_nr >= MAX_PLAYERS) - return; - - if (addr->pl_nr != -1 && bman.state == GS_update && GT_MP_PTPM) { - if (addr->pl_nr > 0 && addr->pl_nr < MAX_PLAYERS) { - bman.players[addr->pl_nr].net.net_status = gp_dat->pl_nr; - bman.players[addr->pl_nr].net.net_istep = 1; - } - } - send_playerdata (addr, gp_dat->pl_nr, &bman.players[gp_dat->pl_nr]); -}; - - -void -do_playerstatus (struct pkg_playerstatus *stat, _net_addr * addr) -{ - int i; - - d_printf ("do_playerstatus (%s,%s)\n", addr->host, addr->port); - - if (addr->pl_nr != 0 && !(GT_MP_PTPM)) { - /* the data we have got are not from the server */ - d_printf ("do_playerstatus: the data we have got are not from the server\n"); - return; - } - - if (stat->pl_nr < 0 || stat->pl_nr >= MAX_PLAYERS) { - /* the line number is wrong */ - d_printf ("do_playerstatus: playernumber not correct\n"); - return; - } - - bman.players[addr->pl_nr].net.net_status = stat->status; - bman.players[addr->pl_nr].net.net_istep = stat->net_istep; - if (GT_MP_PTPM) - for (i = 0; i < MAX_PLAYERS; i++) - if (bman.players[i].net.addr.host[0] != 0) - send_playerstatus (&bman.players[i].net.addr, stat->pl_nr, stat->net_istep, - stat->status); -}; - - -void -send_playerstatus (_net_addr * addr, int pl_nr, int net_istep, int status) -{ - struct pkg_playerstatus stat; - - d_printf ("send_playerstatus (%s,%s) %d, %d, %d\n", addr->host, addr->port, pl_nr, net_istep, - status); - - stat.h.typ = PKG_playerstatus; - stat.h.flags = 0; - stat.h.len = sizeof (struct pkg_playerstatus); - stat.pl_nr = pl_nr; - stat.net_istep = net_istep; - stat.status = status; - - send_pkg ((struct pkg *) &stat, addr); -}; - - -void -do_chat (struct pkg_chat *chat_pkg, _net_addr * addr) -{ - chat_addline (chat_pkg->text); - - if (GT_MP_PTPM && bman.notifygamemaster) /* send notification the the gamemaster */ - gamesrv_sendchat (chat_pkg->text); -}; - - -void -send_chat (_net_addr * addr, char *text) -{ - struct pkg_chat chat_pkg; - int i; - - chat_pkg.h.typ = PKG_chat; - chat_pkg.h.flags = 0; - chat_pkg.h.len = sizeof (struct pkg_chat); - - for (i = 0; i < sizeof (chat_pkg.text); i++) - chat_pkg.text[i] = 0; - strncpy (chat_pkg.text, text, sizeof (struct pkg_chat) - sizeof (struct pkg)); - - send_pkg ((struct pkg *) &chat_pkg, addr); -}; - - -void -send_pkgack (_net_addr * addr, unsigned char typ, short int id) -{ - struct pkg_pkgack p_ack; - - p_ack.h.typ = PKG_pkgack; - p_ack.h.flags = 0; - p_ack.h.len = sizeof (struct pkg_pkgack); - p_ack.id = id; - p_ack.typ = typ; - - send_pkg ((struct pkg *) &p_ack, addr); -}; - - -void -do_pkgack (struct pkg_pkgack *p_ack, _net_addr * addr) -{ - d_printf ("do_pkgack (%s:%s)\n", addr->host, addr->port); - if (rscache_getpos (addr, p_ack->typ, p_ack->id) == -1) - return; - - rscache_del (); -}; - - -void -do_bcmservchat (struct pkg_bcmservchat *packet, _net_addr * addr) -{ - packet->data[127] = 0; - if (strstr (packet->data,"BC:BC:") == packet->data) - return; // ignore packet - chat_addline (packet->data); - net_send_chat (packet->data, 0); -}; - - -int -inpkg_check (unsigned char typ, short int id, _net_addr * addr) -{ - int i, - pos; - - /* find packet */ - for (i = 0, pos = -1; (i < PKG_IN_INDEX_NUM && pos == -1); i++) - if (inpkg_index[i].pl_nr == addr->pl_nr && - inpkg_index[i].typ == typ && inpkg_index[i].id == id) { - printf ("typ: %d, id: %d\n", typ, id); - pos = i; - } - if (pos == -1) { - /* packet unknown ... add to index */ - if (++inpkg_index_pos >= PKG_IN_INDEX_NUM) - inpkg_index_pos = 0; - - inpkg_index[inpkg_index_pos].pl_nr = addr->pl_nr; - inpkg_index[inpkg_index_pos].typ = typ; - inpkg_index[inpkg_index_pos].id = id; - } - - return pos; -}; - - - -void -send_pkg (struct pkg *packet, _net_addr * addr) -{ - packet->h.id = pkg_lastid++; - if (bman.net_ai_family != PF_INET) - packet->h.flags = packet->h.flags | PKGF_ipv6; - udp_send (bman.sock, (char *) packet, packet->h.len, &addr->sAddr, bman.net_ai_family); - - /* test if we have any important packet if so put it in the resend_cache */ - if (packet->h.flags & PKGF_ackreq) { - if (rscache_add (addr, packet) == -1) - d_printf ("resend_cache overrun.... packet throw away.\n"); - } -}; - - - -int -do_pkg (struct pkg *packet, _net_addr * addr) -{ - if ((((packet->h.flags & PKGF_ipv6) == 0 && bman.net_ai_family != PF_INET) || - ((packet->h.flags & PKGF_ipv6) != 0 && bman.net_ai_family == PF_INET)) && - packet->h.typ != PKG_bcmservchat) { - d_printf ("-----packet comes from the wrong network type\n"); - return 0; - } - - /* get the addr and set the ping timeout value */ - addr->pl_nr = get_player_nr (addr->host, addr->port); - bman.players[addr->pl_nr].net.timestamp = timestamp; - bman.players[addr->pl_nr].net.pingreq = bman.players[addr->pl_nr].net.pingack + 5; - - /* test if we have any important packet */ - if (packet->h.flags & PKGF_ackreq && packet->h.typ != PKG_bcmservchat) - send_pkgack (addr, packet->h.typ, packet->h.id); - - /* check the packet with the index */ - if (packet->h.typ != PKG_bcmservchat && inpkg_check (packet->h.typ, packet->h.id, addr) != -1) { - /* we have got this packet already */ - d_printf ("-----packet ignored\n"); - if (addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS) - bman.players[addr->pl_nr].net.pkgopt.to_2sec++; - return 0; - } - - /* check if the incoming packet have the right size */ - if (packet->h.typ == PKG_servermode && packet->h.len != sizeof (struct pkg_servermode)) - send_error (addr, "pkg_servermode: packetsize incorrect."); - - switch (packet->h.typ) { - case (PKG_error): - if (do_error ((struct pkg_error *) packet, addr) < 0) - return -1; - break; - case (PKG_playerid): - do_playerid ((struct pkg_playerid *) packet, addr); - break; - case (PKG_servermode): - do_servermode ((struct pkg_servermode *) packet, addr); - break; - case (PKG_field): - do_field ((struct pkg_field *) packet, addr); - break; - case (PKG_pingreq): - do_ping ((struct pkg_ping *) packet, addr); - break; - case (PKG_pingack): - do_ping ((struct pkg_ping *) packet, addr); - break; - case (PKG_bombdata): - do_bombdata ((struct pkg_bombdata *) packet, addr); - break; - case (PKG_playerdata): - do_playerdata ((struct pkg_playerdata *) packet, addr); - break; - case (PKG_quit): - do_quit ((struct pkg_quit *) packet, addr); - break; - case (PKG_getfield): - do_getfield ((struct pkg_getfield *) packet, addr); - break; - case (PKG_getplayerdata): - do_getplayerdata ((struct pkg_getplayerdata *) packet, addr); - break; - case (PKG_fieldline): - do_fieldline ((struct pkg_fieldline *) packet, addr); - break; - case (PKG_playerstatus): - do_playerstatus ((struct pkg_playerstatus *) packet, addr); - break; - case (PKG_pkgack): - do_pkgack ((struct pkg_pkgack *) packet, addr); - break; - case (PKG_chat): - do_chat ((struct pkg_chat *) packet, addr); - break; - case (PKG_playermove): - do_playermove ((struct pkg_playermove *) packet, addr); - break; - case (PKG_bcmservchat): - do_bcmservchat ((struct pkg_bcmservchat *) packet, addr); - break; - case (PKG_ill): - do_ill ((struct pkg_ill *) packet, addr); - break; - default: - send_error (addr, "BomberClone: unknown data packet"); - break; - } - - return 0; -}; +/* network commands and data */ + +#include "basic.h" +#include "bomberclone.h" +#include "network.h" +#include "gamesrv.h" +#include "packets.h" +#include "chat.h" + +extern _point debug_field; +extern int debug_lastping; + +static short int pkg_lastid; /* the packet id, this will only counted + up nothing more.. if we are at 0x10000 + we will start at 0 */ + +struct _resend_cache resend_cache; +struct _inpkg_index inpkg_index[PKG_IN_INDEX_NUM]; +int inpkg_index_pos = 0; + + +int +get_player_nr (char *host, char *port) +{ + int i, + res; + + for (i = 0, res = -1; (i < MAX_PLAYERS && res == -1); i++) { + if (bman.players[i].net.addr.host[0] != 0) + if ((strcmp (bman.players[i].net.addr.host, host) == 0) && + (strcmp (bman.players[i].net.addr.port, port) == 0)) + res = i; + } + return res; +} + + +void +send_error (_net_addr * addr, char *text) +{ + struct pkg_error p_err; + + d_printf ("Send Network Error : %s\n", text); + strncpy (p_err.text, text, 127); + p_err.h.typ = PKG_error; + p_err.h.flags = 0; + p_err.h.len = sizeof (struct pkg_error); + p_err.nr = 0; + + send_pkg ((struct pkg *) &p_err, addr); +}; + + +int +do_error (struct pkg_error *data, _net_addr * addr) +{ + d_printf ("Network Error : '%s'\n", data->text); + menu_displaymessage ("Network Error", data->text); + if (data->nr == 1) + return -1; + else + return 0; +}; + + +/* +update the playerinformations in the game +*/ +void +do_playerid (struct pkg_playerid *p_id, _net_addr * addr) +{ + _player *pl; + int i, + j, + vma, + vmi, + vsu; + char text[255]; + + sscanf (VERSION, "%d.%d.%d", &vma, &vmi, &vsu); + + if (p_id->ver_sub != vsu || p_id->ver_major != vma || p_id->ver_minor != vmi) { + sprintf (text, "Version Error - Host/Server Version: %s", VERSION); + send_error (addr, text); + return; + } + d_printf ("do_playerid (From:%s:%s pl_nr=%d) Player(name:%s [%s:%s], pl_nr:%d)\n", addr->host, + addr->port, addr->pl_nr, p_id->name, p_id->host, p_id->port, p_id->pl_nr); + + /* As Server/Master Only change settings, or do ignore them if we are not in GS_wait */ + if (((GT_MP_PTPM && (bman.state == GS_wait && addr->pl_nr != -1)) || // PTPM change setting + (GT_MP_PTPS && addr->pl_nr == 0)) && p_id->pl_nr >= 0 && p_id->pl_nr < MAX_PLAYERS) { // PTPS and information send by PTPM + + pl = &bman.players[p_id->pl_nr]; + + pl->state = p_id->state; + if (p_id->pl_nr != bman.p_nr && PS_IS_used (pl->state)) + pl->state |= PSF_net; + else + pl->state &= (0xff - PSF_net); + + player_set_gfx (pl, p_id->gfx_nr); + strncpy (pl->name, p_id->name, LEN_PLAYERNAME); + pl->net.timestamp = timestamp; + pl->net.pingreq = pl->net.pingack + 5; + + if (p_id->host[0] != 0) { + pl->net.addr.pl_nr = addr->pl_nr; + strncpy (pl->net.addr.host, p_id->host, LEN_SERVERNAME); + strncpy (pl->net.addr.port, p_id->port, LEN_PORT); + dns_filladdr (pl->net.addr.host, LEN_SERVERNAME, + pl->net.addr.port, LEN_PORT, bman.net_ai_family, &pl->net.addr.sAddr); + } + + if (GT_MP_PTPS) { + pl->points = p_id->points; + pl->wins = p_id->wins; + } + } + + /* add player into the list if there is something free */ + else if ((addr->pl_nr == -1 || p_id->pl_nr == -1) && GS_WAITRUNNING && GT_MP_PTPM) { + + /* find free player slot */ + if (addr->pl_nr == -1) + for (i = 0; (i < MAX_PLAYERS && PS_IS_used (bman.players[i].state)); i++); + else + i = addr->pl_nr; + + if ((i < MAX_PLAYERS) && (i < bman.maxplayer)) { + /* free in_pl slot ... fill in data */ + pl = &bman.players[i]; + + pl->state = PSF_used + PSF_net; + if (strncmp (pl->name, p_id->name, LEN_PLAYERNAME) == 0) + d_printf ("***** Player ReJoined : Nr:[%d] Name:%10s\n", i, p_id->name); + else { + d_printf ("***** Player Added : Nr:[%d] Name:%10s\n", i, p_id->name); + pl->points = 0; + pl->wins = 0; + } + strncpy (pl->name, p_id->name, LEN_PLAYERNAME); + player_set_gfx (pl, p_id->gfx_nr); + + /* Reset the network data */ + pl->net.timestamp = timestamp; + pl->net.pkgopt.to_timestamp = timestamp; + pl->net.pkgopt.to_2sec = 0; + pl->net.pkgopt.send_to = 0; + pl->net.pkgopt.send_set = PKG_SENDSETOPT; + + strncpy (pl->net.addr.host, addr->host, LEN_SERVERNAME); + strncpy (pl->net.addr.port, addr->port, LEN_PORT); + dns_filladdr (pl->net.addr.host, LEN_SERVERNAME, pl->net.addr.port, LEN_PORT, + bman.net_ai_family, &pl->net.addr.sAddr); + pl->net.addr.pl_nr = i; + bman.players_nr_s++; + + /* send to the new client the servermode and the complete playerlist */ + send_servermode (addr, i); + for (j = 0; j < MAX_PLAYERS; j++) + if (bman.players[j].net.addr.host[0] != 0 || bman.players[j].name[0] != 0) + send_playerid (addr, bman.players[j].name, bman.players[j].net.addr.host, + bman.players[j].net.addr.port, j, bman.players[j].gfx_nr); + + addr->pl_nr = i; + for (j = 0, i = 0; i < bman.maxplayer; i++) + if (PS_IS_used (bman.players[i].state)) + j++; + if (bman.notifygamemaster) + gamesrv_sendmode (bman.maxplayer, j); + } + + else if (GS_WAITRUNNING) { + send_error (addr, "No Free Playerslot found\n"); + return; + } + + else if (!GS_WAITRUNNING) { + send_error (addr, "Game is in the wrong mode.\n"); + return; + } + } + + /* Send all connected players the new PlayerID */ + if (GS_WAITRUNNING && addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS) + net_change_playerid (addr->pl_nr, (GT_MP_PTPM)); + + d_playerdetail ("*** PLAYER List ***"); +}; + + +void +send_playerid (_net_addr * addr, char *name, char *pladdr, char *plport, int pl_nr, int gfx_nr) +{ + struct pkg_playerid p_id; + int vmi, + vma, vsu; + + d_printf ("send_playerid SendTo: %s:%s (Name:%16s p_nr:%d)\n", addr->host, addr->port, name, + pl_nr); + sscanf (VERSION, "%d.%d.%d", &vma, &vmi, &vsu); + + p_id.h.typ = PKG_playerid; + p_id.h.flags = PKGF_ackreq; + p_id.h.len = sizeof (struct pkg_playerid); + p_id.ver_sub = vsu; + p_id.ver_major = vma; + p_id.ver_minor = vmi; + + strncpy (p_id.name, name, LEN_PLAYERNAME); + if (pladdr == NULL) + p_id.host[0] = 0; + else + strncpy (p_id.host, pladdr, LEN_SERVERNAME); + + if (plport == NULL) + p_id.port[0] = 0; + + else + strncpy (p_id.port, plport, LEN_PORT); + + p_id.pl_nr = pl_nr; + p_id.gfx_nr = gfx_nr; + if (pl_nr != -1) { + p_id.points = bman.players[pl_nr].points; + p_id.wins = bman.players[pl_nr].wins; + p_id.state = bman.players[pl_nr].state; + } + else { + p_id.points = 0; + p_id.wins = 0; + p_id.state = 0; + } + + send_pkg ((struct pkg *) &p_id, addr); +}; + + +void +do_servermode (struct pkg_servermode *s_mod, _net_addr * addr) +{ + if (addr->pl_nr == -1) + return; + + d_printf ("do_servermode (%s:%s) state = %d\n", addr->host, addr->port, s_mod->state); + + if (s_mod->pl_nr >= 0 && s_mod->pl_nr < MAX_PLAYERS) { + bman.p_nr = s_mod->pl_nr; + bman.players[bman.p_nr].state &= (0xFF - PSF_net); + strncpy (bman.players[s_mod->pl_nr].name, bman.playername, LEN_PLAYERNAME); + } + + if (s_mod->type == GT_multi) + bman.gametype = GT_multi; + else + bman.gametype = GT_single; + + bman.state = s_mod->state; + if (s_mod->multitype == MT_ptpm) + bman.multitype = MT_ptps; + + bman.players_nr_s = s_mod->players; + bman.lastwinner = s_mod->last_winner; + + if (GT_MP_PTPS) { + bman.fieldsize.x = s_mod->fieldsize_x; + bman.fieldsize.y = s_mod->fieldsize_y; + } + strncpy (gfx.tileset, s_mod->tileset, LEN_TILESETNAME); +}; + + +void +send_servermode (_net_addr * addr, int pl_nr) +{ + struct pkg_servermode s_mod; + d_printf ("Send ServerMode\n"); + + s_mod.h.typ = PKG_servermode; + s_mod.h.len = sizeof (struct pkg_servermode); + s_mod.h.flags = PKGF_ackreq; + s_mod.type = bman.gametype; + s_mod.state = bman.state; + s_mod.multitype = bman.multitype; + s_mod.players = bman.players_nr_s; + s_mod.maxplayer = bman.maxplayer; + s_mod.pl_nr = pl_nr; + s_mod.last_winner = bman.lastwinner; + s_mod.fieldsize_x = bman.fieldsize.x; + s_mod.fieldsize_y = bman.fieldsize.y; + strncpy (s_mod.tileset, gfx.tileset, LEN_TILESETNAME); + send_pkg ((struct pkg *) &s_mod, addr); +}; + + +void +send_field (_net_addr * addr, int x, int y, _field * field) +{ + struct pkg_field f_dat; + + d_printf ("send_field [%d,%d]\n", x, y); + + f_dat.h.typ = PKG_field; + f_dat.h.len = sizeof (struct pkg_field); + f_dat.h.flags = PKGF_ackreq; + + f_dat.x = x; + f_dat.y = y; + + if (x < 0 || x >= bman.fieldsize.x || y < 0 || y >= bman.fieldsize.y) + return; + memcpy (&f_dat.field, &bman.field[x][y], sizeof (_field)); + + send_pkg ((struct pkg *) &f_dat, addr); +}; + + +void +do_field (struct pkg_field *f_dat, _net_addr * addr) +{ + if (addr->pl_nr == -1) + return; + + if (f_dat->x < bman.fieldsize.x && f_dat->y < bman.fieldsize.y) { + memcpy (&bman.field[f_dat->x][f_dat->y], &f_dat->field, sizeof (_field)); + } + if (bman.state == GS_running) + draw_stone (f_dat->x, f_dat->y); + + if (f_dat->field.ex_nr > bman.last_ex_nr) + bman.last_ex_nr = f_dat->field.ex_nr; + + d_printf ("do_field (%d,%d) ex_nr = %d, special = %d, type = %d\n", f_dat->x, f_dat->y, + f_dat->field.ex_nr, f_dat->field.special, f_dat->field.type); +}; + + +void +do_ping (struct pkg_ping *p_dat, _net_addr * addr) +{ + if (addr->pl_nr == -1) + return; + + if (p_dat->h.typ == PKG_pingack) + /* ping was an answer */ + bman.players[addr->pl_nr].net.pingack = p_dat->data; + + else + /* send the answer */ + send_ping (addr, p_dat->data, PKG_pingack); + + d_printf ("do_ping pl_nr[%d] (%s:%s) req=%d, ack=%d\n", addr->pl_nr, addr->host, + addr->port, bman.players[addr->pl_nr].net.pingreq, bman.players[addr->pl_nr].net.pingack); +}; + + +void +send_ping (_net_addr * addr, int data, unsigned char typ) +{ + struct pkg_ping p_dat; + + if (addr->pl_nr == -1) + return; + + p_dat.h.len = sizeof (struct pkg_ping); + p_dat.h.flags = 0; + + if (typ == PKG_pingack) { + p_dat.h.typ = typ; + p_dat.data = data; + send_pkg ((struct pkg *) &p_dat, addr); + } + + else if (typ == PKG_pingreq) { + p_dat.h.typ = typ; + p_dat.data = data; + send_pkg ((struct pkg *) &p_dat, addr); + } + + d_printf ("send_ping Player[%d] (%s:%s) req=%d, ack=%d\n", addr->pl_nr, addr->host, addr->port, + bman.players[addr->pl_nr].net.pingreq, bman.players[addr->pl_nr].net.pingack); + + bman.players[addr->pl_nr].net.timestamp = timestamp; /* we need to set it here, so we can check + for the timeout again */ +}; + + +void +send_playerdata (_net_addr * addr, int p_nr, _player * pl) +{ + struct pkg_playerdata p_dat; + + p_dat.h.typ = PKG_playerdata; + p_dat.h.len = sizeof (struct pkg_playerdata); + + if (bman.state == GS_update) + p_dat.h.flags = 0; + else + p_dat.h.flags = PKGF_ackreq; + + p_dat.pos.x = pl->pos.x; + p_dat.pos.y = pl->pos.y; + p_dat.bombs_n = pl->bombs_n; + p_dat.d = pl->d; + p_dat.range = pl->range; + p_dat.gfx_nr = pl->gfx_nr; + p_dat.state = pl->state; + p_dat.wins = pl->wins; + p_dat.points = pl->points; + p_dat.dead_by = pl->dead_by; + p_dat.frame = pl->frame; + p_dat.p_nr = p_nr; + + send_pkg ((struct pkg *) &p_dat, addr); +}; + + +void +do_playerdata (struct pkg_playerdata *p_dat, _net_addr * addr) +{ + _player *pl; + + if (addr->pl_nr == -1) + return; + + if (p_dat->p_nr < 0 || p_dat->p_nr >= MAX_PLAYERS) + return; + + d_printf ("do_playerdata (From: %d) p_nr: %d\n", addr->pl_nr, p_dat->p_nr); + + pl = &bman.players[p_dat->p_nr]; + player_set_gfx (pl, p_dat->gfx_nr); + + if (bman.state == GS_running && bman.p_nr != p_dat->p_nr) { + pl->points = p_dat->points; + pl->dead_by = p_dat->dead_by; + } + else if (bman.state != GS_running || bman.p_nr != p_dat->p_nr) { + pl->pos.x = p_dat->pos.x; + pl->pos.y = p_dat->pos.y; + pl->dead_by = p_dat->dead_by; + pl->points = p_dat->points; + pl->d = p_dat->d; + pl->bombs_n = p_dat->bombs_n; + pl->range = p_dat->range; + pl->frame = p_dat->frame; + pl->state = p_dat->state; + } + + if (p_dat->dead_by < 0 || p_dat->dead_by >= MAX_PLAYERS) /* set player state no matter what */ + pl->state = p_dat->state; + else { /* player died in the game */ + /* check if the player just died */ + if (PS_IS_alife (pl->state) && PS_IS_dead (p_dat->state)) { + /* player just died */ + if (p_dat->p_nr != p_dat->dead_by) { + bman.players[p_dat->dead_by].points++; + net_game_send_player (p_dat->dead_by); + } + } + pl->state = p_dat->state; + } + + /* set the state of the player */ + if (p_dat->p_nr != bman.p_nr && PS_IS_used (pl->state)) + pl->state |= PSF_net; + else + pl->state &= (0xff - PSF_net); + + if (p_dat->gfx_nr == -1) + pl->state &= (0xff - PSF_alife); + + if (bman.state == GS_update && PS_IS_used (p_dat->state)) + bman.players_nr_s++; + + if (bman.state == GS_update && bman.players[bman.p_nr].net.net_istep == 1) + bman.players[bman.p_nr].net.net_status = p_dat->p_nr; +} + + +void +send_playermove (_net_addr * addr, int p_nr, _player * pl) +{ + struct pkg_playermove p_dat; + + p_dat.h.typ = PKG_playermove; + p_dat.h.len = sizeof (struct pkg_playermove); + p_dat.h.flags = 0; + + p_dat.pos.x = pl->pos.x; + p_dat.pos.y = pl->pos.y; + p_dat.m = pl->m; + p_dat.d = pl->d; + p_dat.p_nr = p_nr; + p_dat.speed = pl->speed; + + send_pkg ((struct pkg *) &p_dat, addr); +}; + + +void +do_ill (struct pkg_ill *ill, _net_addr * addr) +{ + int i; + + if (addr->pl_nr == -1) + return; + + d_printf ("do_ill (From: %d) For Player %d\n", addr->pl_nr, ill->pl_nr); + if (ill->pl_nr < 0 || ill->pl_nr >= MAX_PLAYERS || ill->pl_nr == bman.p_nr) + return; + + for (i = 0; i < PI_max; i++) + bman.players[ill->pl_nr].ill[i].to = ill->to[i]; +}; + + + +void +send_ill (_net_addr * addr, int p_nr, _player * pl) +{ + struct pkg_ill ill; + int i; + + ill.h.typ = PKG_ill; + ill.h.len = sizeof (struct pkg_ill); + ill.h.flags = PKGF_ackreq; + + ill.pl_nr = p_nr; + for (i = 0; i < PI_max; i++) + ill.to[i] = pl->ill[i].to; + + send_pkg ((struct pkg *) &ill, addr); +}; + + +void +do_playermove (struct pkg_playermove *p_dat, _net_addr * addr) +{ + _player *pl; + + if (addr->pl_nr == -1) + return; + + if (p_dat->p_nr == -1) + return; + + /* check if the right player is sending the information */ + pl = &bman.players[p_dat->p_nr]; + if (addr->pl_nr != 0 && addr->pl_nr != p_dat->p_nr) + return; + + pl->m = p_dat->m; + pl->d = p_dat->d; + pl->speed = p_dat->speed; + pl->pos.x = p_dat->pos.x; + pl->pos.y = p_dat->pos.y; +} + + +void +do_bombdata (struct pkg_bombdata *b_dat, _net_addr * addr) +{ + _bomb *bomb; + + if (addr->pl_nr == -1) + return; + + if (b_dat->p_nr >= MAX_PLAYERS || b_dat->b_nr >= MAX_BOMBS) { + d_printf ("Bomb Error\n"); + return; + } + + if (b_dat->state == BS_off) + return; // if there was a bomb let it explose don't delete the bomb + + d_printf ("do_bombdata [%d,%d] Player: %d Bomb: %d, ex_nr:%d\n", b_dat->x, b_dat->y, + b_dat->p_nr, b_dat->b_nr, b_dat->ex_nr); + + bomb = &bman.players[b_dat->p_nr].bombs[b_dat->b_nr]; + if (bomb->state == BS_exploding) { + d_printf ("do_bombdata ---> bomb is already exploding\n"); + return; + } + + if ((bomb->pos.x != b_dat->x || bomb->pos.y != b_dat->y) && bomb->state == BS_exploding + && b_dat->state != BS_exploding) + d_printf ("do_bombdata WARNING : bomb explosion haven't finished\n"); + + bomb->pos.x = b_dat->x; + bomb->pos.y = b_dat->y; + if (bomb->state != BS_ticking) + bomb->to = b_dat->to; + bomb->r = b_dat->r; + bomb->ex_nr = b_dat->ex_nr; + bomb->state = b_dat->state; + if (bomb->state == BS_exploding) + bomb_explode (b_dat->p_nr, b_dat->b_nr); + + if (bomb->ex_nr > bman.last_ex_nr) + bman.last_ex_nr = bomb->ex_nr; +}; + + +void +send_bombdata (_net_addr * addr, int p, int b, _bomb * bomb) +{ + struct pkg_bombdata b_dat; + + b_dat.h.typ = PKG_bombdata; + b_dat.h.len = sizeof (struct pkg_bombdata); + b_dat.x = bomb->pos.x; + b_dat.y = bomb->pos.y; + b_dat.to = bomb->to; + b_dat.r = bomb->r; + b_dat.ex_nr = bomb->ex_nr; + b_dat.state = bomb->state; + b_dat.b_nr = b; + b_dat.p_nr = p; + b_dat.h.flags = PKGF_ackreq; + + send_pkg ((struct pkg *) &b_dat, addr); +}; + + +void +send_quit (_net_addr * addr, char *plhost, char *plport) +{ + struct pkg_quit q_dat; + + d_printf ("send_quit (%s:%s) plhost (%s:%s)\n", addr->host, addr->port, plhost, plport); + + q_dat.h.typ = PKG_quit; + q_dat.h.flags = 0; + q_dat.h.len = sizeof (struct pkg_quit); + + if (plhost == NULL) { + q_dat.host[0] = 0; + q_dat.port[0] = 0; + } + + else { + strncpy (q_dat.host, plhost, LEN_SERVERNAME); + strncpy (q_dat.port, plport, LEN_PORT); + } + + send_pkg ((struct pkg *) &q_dat, addr); +}; + + +void +do_quit (struct pkg_quit *q_dat, _net_addr * addr) +{ + d_printf ("do_quit (%s:%s) pl_nr = %d\n", addr->host, addr->port, addr->pl_nr); + if (addr->pl_nr == -1) + return; + + if (q_dat->host[0] == 0) + /* the player who send this quit */ + net_delplayer (addr->pl_nr); + else { + /* delete the player with the giving address */ + int pl_nr = get_player_nr (q_dat->host, q_dat->port); + if (pl_nr == -1) + return; + + net_delplayer (pl_nr); + } +}; + + +void +send_getfield (_net_addr * addr, int line) +{ + struct pkg_getfield gf_dat; + + gf_dat.h.typ = PKG_getfield; + gf_dat.h.len = sizeof (struct pkg_getfield); + gf_dat.h.flags = 0; + gf_dat.line = line; + send_pkg ((struct pkg *) &gf_dat, addr); +}; + + +void +do_getfield (struct pkg_getfield *gf_dat, _net_addr * addr) +{ + if (addr->pl_nr == -1) + return; + + if (gf_dat->line < 0 || gf_dat->line >= MAX_FIELDSIZE_Y) + return; + + if (addr->pl_nr != -1 && bman.state == GS_update && GT_MP_PTPM) { + if (addr->pl_nr > 0 && addr->pl_nr < MAX_PLAYERS) { + bman.players[addr->pl_nr].net.net_status = gf_dat->line; + bman.players[addr->pl_nr].net.net_istep = 2; + } + } + + send_fieldline (addr, gf_dat->line); +}; + + +void +send_fieldline (_net_addr * addr, int line) +{ + int i, + j; + struct pkg_fieldline f_dat; + + f_dat.h.typ = PKG_fieldline; + f_dat.h.len = sizeof (struct pkg_fieldline); + f_dat.h.flags = 0; + f_dat.line = line; + + if (line < 0 || line >= MAX_FIELDSIZE_Y) + return; + + for (i = 0; i < MAX_FIELDSIZE_X; i++) { + f_dat.type[i] = bman.field[i][line].type; + f_dat.special[i] = bman.field[i][line].special; + bman.field[i][line].frame = 0; + bman.field[i][line].frameto = 0; + bman.field[i][line].ex_nr = 0; + for (j = 0; j < 4; j++) + bman.field[i][line].ex[j].frame = bman.field[i][line].ex[j].count = 0; + } + send_pkg ((struct pkg *) &f_dat, addr); +}; + + +void +do_fieldline (struct pkg_fieldline *f_dat, _net_addr * addr) +{ + int i, d; + + if (addr->pl_nr == -1) + return; + + if (addr->pl_nr != 0) { + /* the data we have got are not from the server */ + d_printf ("do_fieldline: the data we have got are not from the server\n"); + return; + } + + if (f_dat->line < 0 || f_dat->line >= MAX_FIELDSIZE_Y) { + /* the line number is wrong */ + d_printf ("do_fieldline: the line number is not correct\n"); + return; + } + + if (bman.state == GS_update && bman.players[bman.p_nr].net.net_istep == 2) + bman.players[bman.p_nr].net.net_status = f_dat->line; + + for (i = 0; i < MAX_FIELDSIZE_X; i++) { + bman.field[i][f_dat->line].type = f_dat->type[i]; + bman.field[i][f_dat->line].special = f_dat->special[i]; + for (d = 0; d < 4; d++) + bman.field[i][f_dat->line].ex[d].frame = bman.field[i][f_dat->line].ex[d].count = 0; + } +}; + + +void +send_getplayerdata (_net_addr * addr, int pl) +{ + struct pkg_getplayerdata gp_dat; + gp_dat.h.typ = PKG_getplayerdata; + gp_dat.h.len = sizeof (struct pkg_getplayerdata); + gp_dat.pl_nr = pl; + gp_dat.h.flags = 0; + send_pkg ((struct pkg *) &gp_dat, addr); +}; + + +void +do_getplayerdata (struct pkg_getplayerdata *gp_dat, _net_addr * addr) +{ + if (addr->pl_nr == -1) + return; + + if (gp_dat->pl_nr < 0 || gp_dat->pl_nr >= MAX_PLAYERS) + return; + + if (addr->pl_nr != -1 && bman.state == GS_update && GT_MP_PTPM) { + if (addr->pl_nr > 0 && addr->pl_nr < MAX_PLAYERS) { + bman.players[addr->pl_nr].net.net_status = gp_dat->pl_nr; + bman.players[addr->pl_nr].net.net_istep = 1; + } + } + send_playerdata (addr, gp_dat->pl_nr, &bman.players[gp_dat->pl_nr]); +}; + + +void +do_playerstatus (struct pkg_playerstatus *stat, _net_addr * addr) +{ + int i; + + d_printf ("do_playerstatus (%s,%s)\n", addr->host, addr->port); + + if (addr->pl_nr != 0 && !(GT_MP_PTPM)) { + /* the data we have got are not from the server */ + d_printf ("do_playerstatus: the data we have got are not from the server\n"); + return; + } + + if (stat->pl_nr < 0 || stat->pl_nr >= MAX_PLAYERS) { + /* the line number is wrong */ + d_printf ("do_playerstatus: playernumber not correct\n"); + return; + } + + bman.players[addr->pl_nr].net.net_status = stat->status; + bman.players[addr->pl_nr].net.net_istep = stat->net_istep; + if (GT_MP_PTPM) + for (i = 0; i < MAX_PLAYERS; i++) + if (bman.players[i].net.addr.host[0] != 0) + send_playerstatus (&bman.players[i].net.addr, stat->pl_nr, stat->net_istep, + stat->status); +}; + + +void +send_playerstatus (_net_addr * addr, int pl_nr, int net_istep, int status) +{ + struct pkg_playerstatus stat; + + d_printf ("send_playerstatus (%s,%s) %d, %d, %d\n", addr->host, addr->port, pl_nr, net_istep, + status); + + stat.h.typ = PKG_playerstatus; + stat.h.flags = 0; + stat.h.len = sizeof (struct pkg_playerstatus); + stat.pl_nr = pl_nr; + stat.net_istep = net_istep; + stat.status = status; + + send_pkg ((struct pkg *) &stat, addr); +}; + + +void +do_chat (struct pkg_chat *chat_pkg, _net_addr * addr) +{ + chat_addline (chat_pkg->text); + + if (GT_MP_PTPM && bman.notifygamemaster) /* send notification the the gamemaster */ + gamesrv_sendchat (chat_pkg->text); +}; + + +void +send_chat (_net_addr * addr, char *text) +{ + struct pkg_chat chat_pkg; + int i; + + chat_pkg.h.typ = PKG_chat; + chat_pkg.h.flags = 0; + chat_pkg.h.len = sizeof (struct pkg_chat); + + for (i = 0; i < sizeof (chat_pkg.text); i++) + chat_pkg.text[i] = 0; + strncpy (chat_pkg.text, text, sizeof (struct pkg_chat) - sizeof (struct pkg)); + + send_pkg ((struct pkg *) &chat_pkg, addr); +}; + + +void +send_pkgack (_net_addr * addr, unsigned char typ, short int id) +{ + struct pkg_pkgack p_ack; + + p_ack.h.typ = PKG_pkgack; + p_ack.h.flags = 0; + p_ack.h.len = sizeof (struct pkg_pkgack); + p_ack.id = id; + p_ack.typ = typ; + + send_pkg ((struct pkg *) &p_ack, addr); +}; + + +void +do_pkgack (struct pkg_pkgack *p_ack, _net_addr * addr) +{ + d_printf ("do_pkgack (%s:%s)\n", addr->host, addr->port); + if (rscache_getpos (addr, p_ack->typ, p_ack->id) == -1) + return; + + rscache_del (); +}; + + +void +do_bcmservchat (struct pkg_bcmservchat *packet, _net_addr * addr) +{ + packet->data[127] = 0; + if (strstr (packet->data,"BC:BC:") == packet->data) + return; // ignore packet + chat_addline (packet->data); + net_send_chat (packet->data, 0); +}; + + +int +inpkg_check (unsigned char typ, short int id, _net_addr * addr) +{ + int i, + pos; + + /* find packet */ + for (i = 0, pos = -1; (i < PKG_IN_INDEX_NUM && pos == -1); i++) + if (inpkg_index[i].pl_nr == addr->pl_nr && + inpkg_index[i].typ == typ && inpkg_index[i].id == id) { + printf ("typ: %d, id: %d\n", typ, id); + pos = i; + } + if (pos == -1) { + /* packet unknown ... add to index */ + if (++inpkg_index_pos >= PKG_IN_INDEX_NUM) + inpkg_index_pos = 0; + + inpkg_index[inpkg_index_pos].pl_nr = addr->pl_nr; + inpkg_index[inpkg_index_pos].typ = typ; + inpkg_index[inpkg_index_pos].id = id; + } + + return pos; +}; + + + +void +send_pkg (struct pkg *packet, _net_addr * addr) +{ + packet->h.id = pkg_lastid++; + if (bman.net_ai_family != PF_INET) + packet->h.flags = packet->h.flags | PKGF_ipv6; + udp_send (bman.sock, (char *) packet, packet->h.len, &addr->sAddr, bman.net_ai_family); + + /* test if we have any important packet if so put it in the resend_cache */ + if (packet->h.flags & PKGF_ackreq) { + if (rscache_add (addr, packet) == -1) + d_printf ("resend_cache overrun.... packet throw away.\n"); + } +}; + + + +int +do_pkg (struct pkg *packet, _net_addr * addr) +{ + if ((((packet->h.flags & PKGF_ipv6) == 0 && bman.net_ai_family != PF_INET) || + ((packet->h.flags & PKGF_ipv6) != 0 && bman.net_ai_family == PF_INET)) && + packet->h.typ != PKG_bcmservchat) { + d_printf ("-----packet comes from the wrong network type\n"); + return 0; + } + + /* get the addr and set the ping timeout value */ + addr->pl_nr = get_player_nr (addr->host, addr->port); + bman.players[addr->pl_nr].net.timestamp = timestamp; + bman.players[addr->pl_nr].net.pingreq = bman.players[addr->pl_nr].net.pingack + 5; + + /* test if we have any important packet */ + if (packet->h.flags & PKGF_ackreq && packet->h.typ != PKG_bcmservchat) + send_pkgack (addr, packet->h.typ, packet->h.id); + + /* check the packet with the index */ + if (packet->h.typ != PKG_bcmservchat && inpkg_check (packet->h.typ, packet->h.id, addr) != -1) { + /* we have got this packet already */ + d_printf ("-----packet ignored\n"); + if (addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS) + bman.players[addr->pl_nr].net.pkgopt.to_2sec++; + return 0; + } + + /* check if the incoming packet have the right size */ + if (packet->h.typ == PKG_servermode && packet->h.len != sizeof (struct pkg_servermode)) + send_error (addr, "pkg_servermode: packetsize incorrect."); + + switch (packet->h.typ) { + case (PKG_error): + if (do_error ((struct pkg_error *) packet, addr) < 0) + return -1; + break; + case (PKG_playerid): + do_playerid ((struct pkg_playerid *) packet, addr); + break; + case (PKG_servermode): + do_servermode ((struct pkg_servermode *) packet, addr); + break; + case (PKG_field): + do_field ((struct pkg_field *) packet, addr); + break; + case (PKG_pingreq): + do_ping ((struct pkg_ping *) packet, addr); + break; + case (PKG_pingack): + do_ping ((struct pkg_ping *) packet, addr); + break; + case (PKG_bombdata): + do_bombdata ((struct pkg_bombdata *) packet, addr); + break; + case (PKG_playerdata): + do_playerdata ((struct pkg_playerdata *) packet, addr); + break; + case (PKG_quit): + do_quit ((struct pkg_quit *) packet, addr); + break; + case (PKG_getfield): + do_getfield ((struct pkg_getfield *) packet, addr); + break; + case (PKG_getplayerdata): + do_getplayerdata ((struct pkg_getplayerdata *) packet, addr); + break; + case (PKG_fieldline): + do_fieldline ((struct pkg_fieldline *) packet, addr); + break; + case (PKG_playerstatus): + do_playerstatus ((struct pkg_playerstatus *) packet, addr); + break; + case (PKG_pkgack): + do_pkgack ((struct pkg_pkgack *) packet, addr); + break; + case (PKG_chat): + do_chat ((struct pkg_chat *) packet, addr); + break; + case (PKG_playermove): + do_playermove ((struct pkg_playermove *) packet, addr); + break; + case (PKG_bcmservchat): + do_bcmservchat ((struct pkg_bcmservchat *) packet, addr); + break; + case (PKG_ill): + do_ill ((struct pkg_ill *) packet, addr); + break; + default: + send_error (addr, "BomberClone: unknown data packet"); + break; + } + + return 0; +}; diff --git a/src/packets.h b/src/packets.h index 0de1505..241ba23 100644 --- a/src/packets.h +++ b/src/packets.h @@ -1,275 +1,275 @@ -/* network packets.. */ - - -enum _network_data { - PKG_error = 0, - PKG_pingreq, - PKG_pingack, - PKG_playerid, - PKG_servermode, - PKG_quit, - PKG_field, - PKG_playerdata, - PKG_bombdata, - PKG_getfield, - PKG_getplayerdata, - PKG_fieldline, - PKG_playerstatus, - PKG_pkgack, - PKG_playermove, - PKG_chat, - PKG_ill, - - PKG_bcmservchat = 90 -}; - - -enum _pkgflags { - PKGF_ackreq = 1, - PKGF_ipv6 = 2 -}; - - -struct pkgheader { - unsigned char typ; - unsigned char flags; - short int id; - short int len; -}; - - -struct pkg { - struct pkgheader h; - char data[0]; -}; - - -struct pkg_bcmservchat { - char typ; - char data[128]; -}; - - -struct pkg_pkgack { - struct pkgheader h; - char typ; - short int id; -}; - - -struct pkg_ping { - struct pkgheader h; - int data; -}; - - -struct pkg_field { - struct pkgheader h; - unsigned char x; - unsigned char y; - _field field; -}; - - -struct pkg_error { - struct pkgheader h; - unsigned char nr; - char text[128]; -}; - - -struct pkg_servermode { - struct pkgheader h; - unsigned char type; - unsigned char state; - unsigned char multitype; - unsigned char players; - unsigned char maxplayer; - signed char last_winner; - signed char fieldsize_x; - signed char fieldsize_y; - char tileset [LEN_TILESETNAME]; - signed char pl_nr; /* if the server sends this to a client... - it will be the clients in_nr number - (-1) for not set */ - -}; - - -struct pkg_playerid { - struct pkgheader h; - char name[LEN_PLAYERNAME]; - char host[LEN_SERVERNAME]; - char port[LEN_PORT]; - signed char ver_major; // Version - signed char ver_minor; // Version - signed char ver_sub; // Version - signed char pl_nr; // Player Nummer - signed char gfx_nr; // number of the graphic - signed char state; - short int points; - short int wins; -}; - - -struct pkg_playerdata { - struct pkgheader h; - signed char p_nr; // Playernumber - short int points; // points - short int wins; // how many times we win - signed char gfx_nr; // the gfx number we want to use - _point pos; - unsigned char bombs_n; - unsigned char range; - unsigned char state; - unsigned char d; - unsigned char frame; - signed char dead_by; -}; - - -struct pkg_playermove { - struct pkgheader h; - signed char p_nr; - signed char m; - signed char d; - signed char speed; - _point pos; -}; - - -struct pkg_bombdata { - struct pkgheader h; - unsigned char p_nr; - unsigned char b_nr; - unsigned char x; - unsigned char y; - unsigned char state; - unsigned char r; - int ex_nr; - int to; -}; - - -struct pkg_quit { - struct pkgheader h; - char host[LEN_SERVERNAME]; - char port[LEN_PORT]; -}; - - -struct pkg_getfield { - struct pkgheader h; - signed char line; -}; - - -struct pkg_playerstatus { - struct pkgheader h; - signed char pl_nr; - signed char net_istep; - signed char status; -}; - - -struct pkg_fieldline { - struct pkgheader h; - signed char line; - unsigned char type[MAX_FIELDSIZE_X]; - unsigned char special[MAX_FIELDSIZE_X]; -}; - - -struct pkg_ill { - struct pkgheader h; - signed char pl_nr; - short int to[PI_max]; -}; - - -struct pkg_getplayerdata { - struct pkgheader h; - signed char pl_nr; -}; - - -struct pkg_chat { - struct pkgheader h; - char text[128]; -}; - - -struct _rscache_entry { - signed char pl_nr; // playernumber to whom this data should go - short int len; // size of the entry - Uint32 timestamp; // pointer to the timestamp - signed char retry; // retry's how many times we tryed this - _net_addr addr; // pointer to the address - struct pkg packet; // pointer to the packet -}; - - -struct _resend_cache { - char *data; // will hold the pointer to out cache - struct _rscache_entry *entry; // pointer to our data - int fill; // how much we have used -}; - - -struct _inpkg_index { - signed char pl_nr; - unsigned char typ; - short int id; -}; - - -extern int do_error (struct pkg_error *data, _net_addr *addr); -extern void do_playerid (struct pkg_playerid *p_id, _net_addr *addr); -extern void do_servermode (struct pkg_servermode *s_mod, _net_addr *addr); -extern void do_field (struct pkg_field *f_dat, _net_addr *addr); -extern void do_ping (struct pkg_ping *p_dat, _net_addr *addr); -extern void do_playerdata (struct pkg_playerdata *p_dat, _net_addr *addr); -extern void do_playermove (struct pkg_playermove *p_dat, _net_addr *addr); -extern void do_bombdata (struct pkg_bombdata *b_dat, _net_addr *addr); -extern void do_quit (struct pkg_quit *q_dat, _net_addr *addr); -extern void do_getfield (struct pkg_getfield *gf_dat, _net_addr *addr); -extern void do_fieldline (struct pkg_fieldline *f_dat, _net_addr *addr); -extern void do_getplayerdata (struct pkg_getplayerdata *gp_dat, _net_addr *addr); -extern void do_playerstatus (struct pkg_playerstatus *gp_dat, _net_addr *addr); -extern void do_pkgack (struct pkg_pkgack *p_ack, _net_addr *addr); -extern void do_chat (struct pkg_chat *chat_pkg, _net_addr *addr); -extern int do_pkg (struct pkg *packet, _net_addr *addr); -extern void do_bcmservchat (struct pkg_bcmservchat *packet, _net_addr *addr); -extern void do_ill (struct pkg_ill *ill_pkg, _net_addr *addr); - - -extern void send_pkg (struct pkg *packet, _net_addr *addr); -extern void send_playerid (_net_addr *addr, char *name, char *pladdr, char *plport, int p_nr, int gfx_nr); -extern void send_servermode (_net_addr *addr, int pl_nr); -extern void send_error (_net_addr *addr, char *text); -extern void send_field (_net_addr *addr, int x, int y, _field * field); -extern void send_ping (_net_addr *addr, int data, unsigned char typ); -extern void send_playerdata (_net_addr *addr, int p_nr, _player * pl); -extern void send_playermove (_net_addr *addr, int p_nr, _player * pl); -extern void send_bombdata (_net_addr *addr, int p, int b, _bomb * bomb); -extern void send_quit (_net_addr *addr, char *plhost, char *plport); -extern void send_getfield (_net_addr *addr, int line); -extern void send_fieldline (_net_addr *addr, int line); -extern void send_getplayerdata (_net_addr *addr, int pl); -extern void send_playerstatus (_net_addr *addr, int pl_nr, int net_istep, int status); -extern void send_pkgack (_net_addr *addr, unsigned char typ, short int id); -extern void send_chat (_net_addr *addr, char *text); -extern void send_ill (_net_addr *addr, int p_nr, _player *pl); - -extern int get_player_nr (char *host, char *port); -extern int inpkg_check (unsigned char typ, short int id, _net_addr *addr); - - -/* this functions will be defined in pkgcache.c */ -extern int rscache_add (_net_addr *addr, struct pkg *packet); -extern void rscache_del (); -extern int rscache_getpos (_net_addr *addr, unsigned char typ, short int id); -extern int rscache_getcurlen (); -extern void rscache_loop (); - -extern struct _resend_cache resend_cache; +/* network packets.. */ + + +enum _network_data { + PKG_error = 0, + PKG_pingreq, + PKG_pingack, + PKG_playerid, + PKG_servermode, + PKG_quit, + PKG_field, + PKG_playerdata, + PKG_bombdata, + PKG_getfield, + PKG_getplayerdata, + PKG_fieldline, + PKG_playerstatus, + PKG_pkgack, + PKG_playermove, + PKG_chat, + PKG_ill, + + PKG_bcmservchat = 90 +}; + + +enum _pkgflags { + PKGF_ackreq = 1, + PKGF_ipv6 = 2 +}; + + +struct pkgheader { + unsigned char typ; + unsigned char flags; + short int id; + short int len; +}; + + +struct pkg { + struct pkgheader h; + char data[0]; +}; + + +struct pkg_bcmservchat { + char typ; + char data[128]; +}; + + +struct pkg_pkgack { + struct pkgheader h; + char typ; + short int id; +}; + + +struct pkg_ping { + struct pkgheader h; + int data; +}; + + +struct pkg_field { + struct pkgheader h; + unsigned char x; + unsigned char y; + _field field; +}; + + +struct pkg_error { + struct pkgheader h; + unsigned char nr; + char text[128]; +}; + + +struct pkg_servermode { + struct pkgheader h; + unsigned char type; + unsigned char state; + unsigned char multitype; + unsigned char players; + unsigned char maxplayer; + signed char last_winner; + signed char fieldsize_x; + signed char fieldsize_y; + char tileset [LEN_TILESETNAME]; + signed char pl_nr; /* if the server sends this to a client... + it will be the clients in_nr number + (-1) for not set */ + +}; + + +struct pkg_playerid { + struct pkgheader h; + char name[LEN_PLAYERNAME]; + char host[LEN_SERVERNAME]; + char port[LEN_PORT]; + signed char ver_major; // Version + signed char ver_minor; // Version + signed char ver_sub; // Version + signed char pl_nr; // Player Nummer + signed char gfx_nr; // number of the graphic + signed char state; + short int points; + short int wins; +}; + + +struct pkg_playerdata { + struct pkgheader h; + signed char p_nr; // Playernumber + short int points; // points + short int wins; // how many times we win + signed char gfx_nr; // the gfx number we want to use + _point pos; + unsigned char bombs_n; + unsigned char range; + unsigned char state; + unsigned char d; + unsigned char frame; + signed char dead_by; +}; + + +struct pkg_playermove { + struct pkgheader h; + signed char p_nr; + signed char m; + signed char d; + signed char speed; + _point pos; +}; + + +struct pkg_bombdata { + struct pkgheader h; + unsigned char p_nr; + unsigned char b_nr; + unsigned char x; + unsigned char y; + unsigned char state; + unsigned char r; + int ex_nr; + int to; +}; + + +struct pkg_quit { + struct pkgheader h; + char host[LEN_SERVERNAME]; + char port[LEN_PORT]; +}; + + +struct pkg_getfield { + struct pkgheader h; + signed char line; +}; + + +struct pkg_playerstatus { + struct pkgheader h; + signed char pl_nr; + signed char net_istep; + signed char status; +}; + + +struct pkg_fieldline { + struct pkgheader h; + signed char line; + unsigned char type[MAX_FIELDSIZE_X]; + unsigned char special[MAX_FIELDSIZE_X]; +}; + + +struct pkg_ill { + struct pkgheader h; + signed char pl_nr; + short int to[PI_max]; +}; + + +struct pkg_getplayerdata { + struct pkgheader h; + signed char pl_nr; +}; + + +struct pkg_chat { + struct pkgheader h; + char text[128]; +}; + + +struct _rscache_entry { + signed char pl_nr; // playernumber to whom this data should go + short int len; // size of the entry + Uint32 timestamp; // pointer to the timestamp + signed char retry; // retry's how many times we tryed this + _net_addr addr; // pointer to the address + struct pkg packet; // pointer to the packet +}; + + +struct _resend_cache { + char *data; // will hold the pointer to out cache + struct _rscache_entry *entry; // pointer to our data + int fill; // how much we have used +}; + + +struct _inpkg_index { + signed char pl_nr; + unsigned char typ; + short int id; +}; + + +extern int do_error (struct pkg_error *data, _net_addr *addr); +extern void do_playerid (struct pkg_playerid *p_id, _net_addr *addr); +extern void do_servermode (struct pkg_servermode *s_mod, _net_addr *addr); +extern void do_field (struct pkg_field *f_dat, _net_addr *addr); +extern void do_ping (struct pkg_ping *p_dat, _net_addr *addr); +extern void do_playerdata (struct pkg_playerdata *p_dat, _net_addr *addr); +extern void do_playermove (struct pkg_playermove *p_dat, _net_addr *addr); +extern void do_bombdata (struct pkg_bombdata *b_dat, _net_addr *addr); +extern void do_quit (struct pkg_quit *q_dat, _net_addr *addr); +extern void do_getfield (struct pkg_getfield *gf_dat, _net_addr *addr); +extern void do_fieldline (struct pkg_fieldline *f_dat, _net_addr *addr); +extern void do_getplayerdata (struct pkg_getplayerdata *gp_dat, _net_addr *addr); +extern void do_playerstatus (struct pkg_playerstatus *gp_dat, _net_addr *addr); +extern void do_pkgack (struct pkg_pkgack *p_ack, _net_addr *addr); +extern void do_chat (struct pkg_chat *chat_pkg, _net_addr *addr); +extern int do_pkg (struct pkg *packet, _net_addr *addr); +extern void do_bcmservchat (struct pkg_bcmservchat *packet, _net_addr *addr); +extern void do_ill (struct pkg_ill *ill_pkg, _net_addr *addr); + + +extern void send_pkg (struct pkg *packet, _net_addr *addr); +extern void send_playerid (_net_addr *addr, char *name, char *pladdr, char *plport, int p_nr, int gfx_nr); +extern void send_servermode (_net_addr *addr, int pl_nr); +extern void send_error (_net_addr *addr, char *text); +extern void send_field (_net_addr *addr, int x, int y, _field * field); +extern void send_ping (_net_addr *addr, int data, unsigned char typ); +extern void send_playerdata (_net_addr *addr, int p_nr, _player * pl); +extern void send_playermove (_net_addr *addr, int p_nr, _player * pl); +extern void send_bombdata (_net_addr *addr, int p, int b, _bomb * bomb); +extern void send_quit (_net_addr *addr, char *plhost, char *plport); +extern void send_getfield (_net_addr *addr, int line); +extern void send_fieldline (_net_addr *addr, int line); +extern void send_getplayerdata (_net_addr *addr, int pl); +extern void send_playerstatus (_net_addr *addr, int pl_nr, int net_istep, int status); +extern void send_pkgack (_net_addr *addr, unsigned char typ, short int id); +extern void send_chat (_net_addr *addr, char *text); +extern void send_ill (_net_addr *addr, int p_nr, _player *pl); + +extern int get_player_nr (char *host, char *port); +extern int inpkg_check (unsigned char typ, short int id, _net_addr *addr); + + +/* this functions will be defined in pkgcache.c */ +extern int rscache_add (_net_addr *addr, struct pkg *packet); +extern void rscache_del (); +extern int rscache_getpos (_net_addr *addr, unsigned char typ, short int id); +extern int rscache_getcurlen (); +extern void rscache_loop (); + +extern struct _resend_cache resend_cache; diff --git a/src/pkgcache.c b/src/pkgcache.c index a9b2981..a65d9da 100644 --- a/src/pkgcache.c +++ b/src/pkgcache.c @@ -1,161 +1,161 @@ -#include "bomberclone.h" -#include "network.h" -#include "packets.h" - -/* - set pointers at the giving pos -*/ -void -rscache_setpointer (int pos) -{ - resend_cache.entry = (struct _rscache_entry *) (((char *) resend_cache.data) + pos); -}; - - -/* - add a packet to the cache and sets the timestamp -*/ -int -rscache_add (_net_addr * addr, struct pkg *packet) -{ - int newlen; - - if (resend_cache.fill + sizeof (struct _rscache_entry) > PKG_RESENDCACHE_SIZE) - return -1; - - rscache_setpointer (resend_cache.fill); - resend_cache.entry->retry = 0; - resend_cache.entry->timestamp = timestamp; - memcpy (&resend_cache.entry->addr, addr, sizeof (_net_addr)); - memcpy (&resend_cache.entry->packet, packet, packet->h.len); - - newlen = resend_cache.fill + rscache_getcurlen (); - - resend_cache.fill = newlen; - - return 0; -}; - -/* - deletes the packet at current pointer in the cache -*/ -void -rscache_del () -{ - int len, - size; - char *pos1; - - /* check if we are able to delete */ - if ((char *) resend_cache.data > (char *) resend_cache.entry || - (char *) resend_cache.entry > (char *) resend_cache.data + resend_cache.fill || - resend_cache.fill == -1 || resend_cache.data == NULL) { - d_printf ("rscache_del: something wrong with the cache\n"); - exit (1); - return; - } - - /* newlen = size of the cacheentry we are going to delete */ - len = rscache_getcurlen (); - - if (resend_cache.fill <= len) /* something went wrong, fill is smaler as the cacheentry, delete the cache */ - resend_cache.fill = 0; - else { - pos1 = (char *) resend_cache.entry + len; - size = PKG_RESENDCACHE_SIZE - (pos1 - resend_cache.data); - - if (resend_cache.fill < PKG_RESENDCACHE_SIZE) { - memmove (resend_cache.entry, pos1, size); - resend_cache.fill = resend_cache.fill - len; - } - } -}; - -/* - get the position in the cache where our needed packet is -*/ -int -rscache_getpos (_net_addr * addr, unsigned char typ, short int id) -{ - int len, - pos, - done = 0; - - for (pos = 0; (pos < resend_cache.fill && done == 0);) { - - rscache_setpointer (pos); - - /* get size of the cacheentry */ - len = rscache_getcurlen (); - - if (strcmp (addr->host, resend_cache.entry->addr.host) == 0 && - strcmp (addr->port, resend_cache.entry->addr.port) == 0 && - typ == resend_cache.entry->packet.h.typ && id == resend_cache.entry->packet.h.id) - done = 1; /* we have found the old packet */ - else - pos = pos + len; - } - - if (done == 0) /* we have found nothing */ - return -1; - - return pos; -}; - -/* get the len of the current entry */ -int -rscache_getcurlen () -{ - int len; - - len = sizeof (struct _rscache_entry) - sizeof (struct pkg) + resend_cache.entry->packet.h.len; - - return len; -}; - - -/* - the loop for the cache.. to see what will have to be resend -*/ -void -rscache_loop () -{ - int len, - pos, - timeout = RESENDCACHE_TIMEOUT; - - for (pos = 0; pos < resend_cache.fill && pos < PKG_RESENDCACHE_SIZE && pos >= 0;) { - - rscache_setpointer (pos); - len = rscache_getcurlen (); - - if (timestamp - resend_cache.entry->timestamp >= timeout - && resend_cache.entry->retry < RESENDCACHE_RETRY) { - /* send it again */ - d_printf - ("Data Send Timeout (%s:%s) Resend now Package Fill %d, Pos %d\n", - resend_cache.entry->addr.host, resend_cache.entry->addr.port, resend_cache.fill, - pos); - udp_send (bman.sock, (char *) &resend_cache.entry->packet, - resend_cache.entry->packet.h.len, &resend_cache.entry->addr.sAddr, - bman.net_ai_family); - resend_cache.entry->timestamp = timestamp; - resend_cache.entry->retry++; - if (resend_cache.entry->addr.pl_nr >= 0 && resend_cache.entry->addr.pl_nr < MAX_PLAYERS) - bman.players[resend_cache.entry->addr.pl_nr].net.pkgopt.to_2sec++; - } - - if (timestamp - resend_cache.entry->timestamp >= timeout - && resend_cache.entry->retry >= RESENDCACHE_RETRY) { - d_printf ("Data Send Timeout (%s:%s) Delete now Package Fill %d, Pos %d\n", - resend_cache.entry->addr.host, resend_cache.entry->addr.port, - resend_cache.fill, pos); - if (resend_cache.entry->addr.pl_nr >= 0 && resend_cache.entry->addr.pl_nr < MAX_PLAYERS) - bman.players[resend_cache.entry->addr.pl_nr].net.pkgopt.to_2sec++; - - rscache_del (); - } - else - pos = pos + len; - } -}; +#include "bomberclone.h" +#include "network.h" +#include "packets.h" + +/* + set pointers at the giving pos +*/ +void +rscache_setpointer (int pos) +{ + resend_cache.entry = (struct _rscache_entry *) (((char *) resend_cache.data) + pos); +}; + + +/* + add a packet to the cache and sets the timestamp +*/ +int +rscache_add (_net_addr * addr, struct pkg *packet) +{ + int newlen; + + if (resend_cache.fill + sizeof (struct _rscache_entry) > PKG_RESENDCACHE_SIZE) + return -1; + + rscache_setpointer (resend_cache.fill); + resend_cache.entry->retry = 0; + resend_cache.entry->timestamp = timestamp; + memcpy (&resend_cache.entry->addr, addr, sizeof (_net_addr)); + memcpy (&resend_cache.entry->packet, packet, packet->h.len); + + newlen = resend_cache.fill + rscache_getcurlen (); + + resend_cache.fill = newlen; + + return 0; +}; + +/* + deletes the packet at current pointer in the cache +*/ +void +rscache_del () +{ + int len, + size; + char *pos1; + + /* check if we are able to delete */ + if ((char *) resend_cache.data > (char *) resend_cache.entry || + (char *) resend_cache.entry > (char *) resend_cache.data + resend_cache.fill || + resend_cache.fill == -1 || resend_cache.data == NULL) { + d_printf ("rscache_del: something wrong with the cache\n"); + exit (1); + return; + } + + /* newlen = size of the cacheentry we are going to delete */ + len = rscache_getcurlen (); + + if (resend_cache.fill <= len) /* something went wrong, fill is smaler as the cacheentry, delete the cache */ + resend_cache.fill = 0; + else { + pos1 = (char *) resend_cache.entry + len; + size = PKG_RESENDCACHE_SIZE - (pos1 - resend_cache.data); + + if (resend_cache.fill < PKG_RESENDCACHE_SIZE) { + memmove (resend_cache.entry, pos1, size); + resend_cache.fill = resend_cache.fill - len; + } + } +}; + +/* + get the position in the cache where our needed packet is +*/ +int +rscache_getpos (_net_addr * addr, unsigned char typ, short int id) +{ + int len, + pos, + done = 0; + + for (pos = 0; (pos < resend_cache.fill && done == 0);) { + + rscache_setpointer (pos); + + /* get size of the cacheentry */ + len = rscache_getcurlen (); + + if (strcmp (addr->host, resend_cache.entry->addr.host) == 0 && + strcmp (addr->port, resend_cache.entry->addr.port) == 0 && + typ == resend_cache.entry->packet.h.typ && id == resend_cache.entry->packet.h.id) + done = 1; /* we have found the old packet */ + else + pos = pos + len; + } + + if (done == 0) /* we have found nothing */ + return -1; + + return pos; +}; + +/* get the len of the current entry */ +int +rscache_getcurlen () +{ + int len; + + len = sizeof (struct _rscache_entry) - sizeof (struct pkg) + resend_cache.entry->packet.h.len; + + return len; +}; + + +/* + the loop for the cache.. to see what will have to be resend +*/ +void +rscache_loop () +{ + int len, + pos, + timeout = RESENDCACHE_TIMEOUT; + + for (pos = 0; pos < resend_cache.fill && pos < PKG_RESENDCACHE_SIZE && pos >= 0;) { + + rscache_setpointer (pos); + len = rscache_getcurlen (); + + if (timestamp - resend_cache.entry->timestamp >= timeout + && resend_cache.entry->retry < RESENDCACHE_RETRY) { + /* send it again */ + d_printf + ("Data Send Timeout (%s:%s) Resend now Package Fill %d, Pos %d\n", + resend_cache.entry->addr.host, resend_cache.entry->addr.port, resend_cache.fill, + pos); + udp_send (bman.sock, (char *) &resend_cache.entry->packet, + resend_cache.entry->packet.h.len, &resend_cache.entry->addr.sAddr, + bman.net_ai_family); + resend_cache.entry->timestamp = timestamp; + resend_cache.entry->retry++; + if (resend_cache.entry->addr.pl_nr >= 0 && resend_cache.entry->addr.pl_nr < MAX_PLAYERS) + bman.players[resend_cache.entry->addr.pl_nr].net.pkgopt.to_2sec++; + } + + if (timestamp - resend_cache.entry->timestamp >= timeout + && resend_cache.entry->retry >= RESENDCACHE_RETRY) { + d_printf ("Data Send Timeout (%s:%s) Delete now Package Fill %d, Pos %d\n", + resend_cache.entry->addr.host, resend_cache.entry->addr.port, + resend_cache.fill, pos); + if (resend_cache.entry->addr.pl_nr >= 0 && resend_cache.entry->addr.pl_nr < MAX_PLAYERS) + bman.players[resend_cache.entry->addr.pl_nr].net.pkgopt.to_2sec++; + + rscache_del (); + } + else + pos = pos + len; + } +}; diff --git a/src/player.c b/src/player.c index a88cf1c..d95fbce 100644 --- a/src/player.c +++ b/src/player.c @@ -1,637 +1,637 @@ -/* player.c - everything what have to do with the player */ - -#include -#include "bomberclone.h" -#include "network.h" - - -void -draw_player (_player * player) -{ - SDL_Rect src, - dest; - int i; - - dest.w = src.w = player->gfx->size.x; - dest.h = src.h = player->gfx->size.y; - - dest.x = - gfx.offset.x + player->gfx->offset.x + (player->pos.x >> 8) * gfx.block.x + - gfx.postab[player->pos.x & 255]; - dest.y = - gfx.offset.y + player->gfx->offset.y + (player->pos.y >> 8) * gfx.block.y + - gfx.postab[player->pos.y & 255]; - - src.x = player->d * player->gfx->size.x; - src.y = player->frame * player->gfx->size.y; - - SDL_BlitSurface (player->gfx->ani.image, &src, gfx.screen, &dest); - - /* if the player is ill, draw this image above him */ - if (PS_IS_alife (player->state)) { - for (i = PI_max - 1; (i >= 0) && (player->ill[i].to == 0); i--); - if (i >= 0) { - dest.w = src.w = gfx.block.x * 2; - dest.h = src.h = gfx.block.y * 2; - - src.x = 0; - src.y = (2 * gfx.block.y) * player->illframe; - - dest.x = - (-(gfx.block.x >> 1)) + gfx.offset.x + (player->pos.x >> 8) * gfx.block.x + - gfx.postab[player->pos.x & 255]; - dest.y = - gfx.offset.y + ((player->pos.y >> 8) - 1) * gfx.block.y + - gfx.postab[player->pos.y & 255]; - - SDL_BlitSurface (gfx.ill.image, &src, gfx.screen, &dest); - - } - } - gfx_AddUpdateRect (dest.x, dest.y, dest.w, dest.h); - player->old = player->pos; // save this position -}; - - -void -restore_players_screen () -{ - int i, - x, - xe, - y, - ys, - ye; - - for (i = 0; i < MAX_PLAYERS; i++) - if ((PS_IS_used (bman.players[i].state)) && bman.players[i].old.x != -1) { - if ((bman.players[i].old.x & 0xFF) > 128) { - x = (bman.players[i].old.x >> 8); - xe = (bman.players[i].old.x >> 8) + 2; - } - else { - x = (bman.players[i].old.x >> 8) - 1; - xe = (bman.players[i].old.x >> 8) +1; - } - if (x < 0) - x = 0; - if (xe >= bman.fieldsize.x) - xe = bman.fieldsize.x - 1; - - ys = (bman.players[i].old.y >> 8) - 1; - ye = (bman.players[i].old.y >> 8) + 1; - if (ys < 0) - ys = 0; - if (ye >= bman.fieldsize.y) - ye = bman.fieldsize.y - 1; - - for (; x <= xe; x++) - for (y = ys; y <= ye; y++) - draw_stone (x, y); - } -}; - - -void -player_check_powerup (_player * p) -{ - int fx = p->pos.x >> 8; - int fy = p->pos.y >> 8; - int _x = p->pos.x & 255; - int _y = p->pos.y & 255; - - /* Get the right field position */ - if (_x > 128) - fx = fx + 1; - - if (_y > 128) - fy = fy + 1; - - /* we found a bomb powerup */ - if (bman.field[fx][fy].type == FT_bomb) { - if (p->bombs_n < MAX_BOMBS) - p->bombs_n++; - bman.field[fx][fy].type = FT_nothing; - if (bman.gametype != GT_single) - net_game_send_field (fx, fy); - } - - /* we found a fire powerup */ - if (bman.field[fx][fy].type == FT_fire) { - if (p->range < MAX_RANGE && p->ill[PI_range].to <= 0) - p->range++; - bman.field[fx][fy].type = FT_nothing; - if (bman.gametype != GT_single) - net_game_send_field (fx, fy); - } - - /* we found a shoe powerup */ - if (bman.field[fx][fy].type == FT_shoe) { - if (p->speed < MAX_SPEED && p->ill[PI_slow].to <= 0) - p->speed *= SPEEDMUL; - bman.field[fx][fy].type = FT_nothing; - if (bman.gametype != GT_single) - net_game_send_field (fx, fy); - } - - /* we found a death ?powerup? */ - if (bman.field[fx][fy].type == FT_death) { - player_set_ilness (p, -1); - net_game_send_ill (bman.p_nr); - - bman.field[fx][fy].type = FT_nothing; - if (bman.gametype != GT_single) - net_game_send_field (fx, fy); - } -}; - - -/* - check the givin field. if we are able to move on it - fx,fy = position on the field -*/ -int -check_field (short int fx, short int fy, _player * p) -{ - _point bombs[MAX_PLAYERS * MAX_BOMBS]; - int res = 0; - - if (bman.field[fx][fy].type != FT_stone && bman.field[fx][fy].type != FT_block) - res = 1; - - get_bomb_on (fx, fy, bombs); - if (bombs[0].x != -1) - res = 0; - - return res; -} - - -int -stepmove_player () -{ - _player *p = &bman.players[bman.p_nr]; - int _x, - _y, - dx = 0, - dy = 0, - fx, - fy, - speed = 0; - - if (p->m == 1) { - - fx = p->pos.x >> 8; - fy = p->pos.y >> 8; - - _x = p->pos.x & 255; - _y = p->pos.y & 255; - - // do direction correction for going up/down - if (_x > 0 && _x <= 128 && (p->d == up || p->d == down)) - p->d = left; - if (_x > 128 && _x < 256 && (p->d == up || p->d == down)) - p->d = right; - - // do direction correction for left/right - if (_y > 0 && _y <= 128 && (p->d == left || p->d == right)) - p->d = up; - if (_y > 128 && _y < 256 && (p->d == left || p->d == right)) - p->d = down; - - /* get the pos to the next field */ - if (p->d == left) - speed = _x; - else if (p->d == right) - speed = 256 - _x; - else if (p->d == up) - speed = _y; - else - speed = 256 - _y; - - if (speed > p->speed || speed == 0) - speed = p->speed; - - // go left - if (p->d == left && _y == 0 && ((_x == 0 && check_field (fx - 1, fy, p)) || (_x > 0))) - dx = -speed; - - // go right - if (p->d == right && _y == 0 && ((_x == 0 && check_field (fx + 1, fy, p)) || (_x > 0))) - dx = speed; - - // go up - if (p->d == up && _x == 0 && ((_y == 0 && check_field (fx, fy - 1, p)) || (_y > 0))) - dy = -speed; - - // go down - if (p->d == down && _x == 0 && ((_y == 0 && check_field (fx, fy + 1, p)) || (_y > 0))) - dy = speed; - - p->pos.x = p->pos.x + dx; - p->pos.y = p->pos.y + dy; - - player_check_powerup (p); - } - - if (dx == 0 && dy == 0) - return 0; - return (p->speed - speed); -}; - - -void -move_player () -{ - int oldd, - stepsleft, - speed; - _player *p = &bman.players[bman.p_nr]; - - oldd = p->d; - if (p->m) { - player_animation (p); - - if ((stepsleft = stepmove_player ()) > 0) { - /* save the speed and go the rest of the step */ - p->d = oldd; - speed = p->speed; - p->speed = stepsleft; - stepmove_player (); - p->speed = speed; - } - - /* network packet send control - send data if it's time to send or if we need to */ - if (bman.gametype != GT_single) - net_game_send_playermove (bman.p_nr, (p->old_m == 0)); - } - - /* the player just stopt moving so send data */ - if (bman.gametype != GT_single && p->m == 0 && p->old_m != 0) - net_game_send_playermove (bman.p_nr, 1); - - p->old_m = p->m; // save the old state - p->m = 0; -}; - - -void -player_drop_bomb () -{ - _player *player = &bman.players[bman.p_nr]; - _bomb *bomb = NULL; - int i, - _x, - _y; - _point bombs[MAX_PLAYERS * MAX_BOMBS]; - - for (i = 0; ((i < player->bombs_n) && (player->bombs[i].state != BS_off)); i++); - - if (i < player->bombs_n) { // free bomb found - // get the best position for the bomb. - bomb = &player->bombs[i]; - - bomb->pos.x = player->pos.x >> 8; - bomb->pos.y = player->pos.y >> 8; - _x = player->pos.x & 255; - _y = player->pos.y & 255; - - if (_x > 0 && _x <= 128) - _x = 0; - else if (_x > 128) { - bomb->pos.x += 1; - _x = 0; - } - - if (_y > 0 && _y <= 128) - _y = 0; - else if (_y > 12) { - bomb->pos.y += 1; - _y = 0; - } - - get_bomb_on (bomb->pos.x, bomb->pos.y, bombs); - if (bombs[0].x != -1) // is there already a bomb - return; - - d_printf ("Player %d Dropped Bomb %d\n", bman.p_nr, i); - bomb->r = player->range; - bomb->state = BS_ticking; - bomb->ex_nr = -1; - - bomb->to = BOMB_TIMEOUT * TIME_FACTOR; // 5 Secs * 200 - - if (bman.gametype != GT_single) { - net_game_send_bomb (bman.p_nr, i); - if (GT_MP_PTPS) - bomb->to = bomb->to + ((2 * RESENDCACHE_RETRY) / TIME_FACTOR); - } - } -}; - - -/* -check the field - 4 pixels from every side.. so it's not anymore that tricky to get -away from bombs.. */ -void -get_player_on (short int x, short int y, int pl_nr[]) -{ - int i, - p; - - for (i = 0, p = 0; p < MAX_PLAYERS; p++) - if (PS_IS_alife (bman.players[p].state)) { - if (bman.players[p].pos.x - 42 > x - 256 - && bman.players[p].pos.x + 42 < x + 256 - && bman.players[p].pos.y - 42 > y - 256 && bman.players[p].pos.y + 42 < y + 256) { - pl_nr[i] = p; - i++; - } - } - pl_nr[i] = -1; -}; - - -void -player_died (_player * player, signed char dead_by) -{ - // player die ! - - d_printf ("player_died (%10s)\n", player->name); - - if (PS_IS_alife (player->state) && dead_by >= 0 && dead_by < MAX_PLAYERS) - if (bman.p_nr != dead_by) - bman.players[dead_by].points++; - - player->state &= (0xFF - PSF_alife); - player->dead_by = dead_by; - - net_game_send_player (bman.p_nr); -}; - - -void -draw_players () -{ - int p; - - for (p = 0; p < MAX_PLAYERS; p++) { - if (PS_IS_playing (bman.players[p].state)) - draw_player (&bman.players[p]); - } -}; - - -void -player_animation (_player * player) -{ - if (player->gfx == NULL) - return; - - if (player->frame < player->gfx->ani.frames - && (player->frameto <= 0 || player->frameto > ANI_PLAYERTIMEOUT)) { - player->frameto = ANI_PLAYERTIMEOUT; - player->frame++; - } - - if (player->frame >= player->gfx->ani.frames && PS_IS_alife (player->state)) - player->frame = 0; - - if (player->frameto > 0) - player->frameto--; -}; - - -void -dead_playerani () -{ - int i; - - for (i = 0; i < MAX_PLAYERS; i++) - if (PS_IS_dead (bman.players[i].state)) - player_animation (&bman.players[i]); -}; - - -void -player_calcstep (_player * pl) -{ - _point d; - int fx, - fy; - - player_animation (pl); - - fx = pl->pos.x >> 8; - fy = pl->pos.y >> 8; - - if (bman.field[fx][fy].type != FT_block && bman.field[fx][fy].type != FT_stone) { - d.x = 0; - d.y = 0; - if (pl->d == left) - d.x = -16; - else if (pl->d == right) - d.x = 16; - else if (pl->d == up) - d.y = -16; - else if (pl->d == down) - d.y = 16; - - pl->pos.x += d.x; - pl->pos.y += d.y; - } -}; - - -/* - calc the position on the screen for moving network players -*/ -void -player_calcpos () -{ - _player *pl; - int oldm, - oldd, - p; - - for (p = 0; p < MAX_PLAYERS; p++) { - pl = &bman.players[p]; - if (PS_IS_netplayer (pl->state) && pl->m != 0) { - - if (pl->speeddat == 0 || pl->speed == 1 || pl->speed == 3) - pl->speeddat = 1; - else - pl->speeddat = 0; - - oldm = pl->m; - oldd = pl->d; - - if (pl->speed > 1) - stepmove_player (); - - if (pl->speeddat) { - pl->m = oldm; - pl->d = oldd; - player_calcstep (pl); - } - } - } - -}; - - -void -player_ilness_loop () -{ - _player *p; - int type, - pnr, - i, - tmp, - send; - int pl[MAX_PLAYERS + 1]; - - /* do the illness for the network players */ - for (pnr = 0; pnr < MAX_PLAYERS; pnr++) - if (pnr != bman.p_nr && PS_IS_alife (bman.players[pnr].state)) { - p = &bman.players[pnr]; - for (type = 0; type < PI_max; type++) - if (p->ill[type].to > 0) { - p->ill[type].to--; - p->illframeto--; - if (p->illframeto <= 0 || p->illframeto > ANI_PLAYERILLTIMEOUT) { - p->illframeto = ANI_PLAYERILLTIMEOUT; - p->illframe++; - if (p->illframe < 0 || p->illframe >= gfx.ill.frames) - p->illframe = 0; - } - } - } - - /* check if we have contact with an other ill player */ - p = &bman.players[bman.p_nr]; - - get_player_on (p->pos.x, p->pos.y, pl); - for (i = 0; (pl[i] != -1 && i < MAX_PLAYERS); i++) - if (pl[i] != bman.p_nr) { - send = 0; - for (type = 0; type < PI_max; type++) { - if (bman.players[pl[i]].ill[type].to > p->ill[type].to) { - tmp = p->ill[type].to; - player_set_ilness (p, type); - p->ill[type].to = bman.players[pl[i]].ill[type].to; - if (tmp <= 0) - send = 1; - } - } - if (send != 0) - net_game_send_ill (bman.p_nr); - } - - /* do the illness for our own player */ - for (type = 0; type < PI_max; type++) - if (p->ill[type].to > 0) { - p->ill[type].to--; - if (p->ill[type].to == 0) - player_clear_ilness (p, type); - else { - p->illframeto--; - if (p->illframeto <= 0 || p->illframeto > ANI_PLAYERILLTIMEOUT) { - p->illframeto = ANI_PLAYERILLTIMEOUT; - p->illframe++; - if (p->illframe < 0 || p->illframe >= gfx.ill.frames) - p->illframe = 0; - } - - if (type == PI_keys) { - /* switch direction for player key illness */ - if (p->m > 0) - switch (p->d) { - case (left): - p->d = right; - break; - case (right): - p->d = left; - break; - case (up): - p->d = down; - break; - case (down): - p->d = up; - break; - } - } - else if (type == PI_bomb) - /* player is dropping bombs */ - player_drop_bomb (); - } - } -} - - -/* player picked up the death powerup, add timeout for -this illness to the maybe excisting timeout */ -void -player_set_ilness (_player * p, int t) -{ - int type; - - if (t == -1) - type = s_random (PI_max); - else - type = t; - - d_printf ("Ilness : %d\n", type); - - if (type == PI_slow) { - if (p->ill[type].to == 0) - p->ill[type].data = p->speed; - p->speed = 6; - } - - else if (type == PI_range) { - if (p->ill[type].to == 0) - p->ill[type].data = p->range; - p->range = 1; - } - - p->ill[type].to += TIME_FACTOR * IL_TIMEOUT; -}; - - -/* players ilness is over now */ -void -player_clear_ilness (_player * p, int type) -{ - if (type < 0 || type >= PI_max) - return; - - if (type == PI_slow) - p->speed = p->ill[type].data; - - if (type == PI_range) - p->range = p->ill[type].data; - - p->ill[type].to = 0; - - net_game_send_ill (bman.p_nr); -}; - - -void -player_set_gfx (_player * p, signed char gfx_nr) -{ - p->gfx_nr = gfx_nr; - - if (p->gfx_nr < 0 || p->gfx_nr >= MAX_PLAYERS) - p->gfx_nr = -1; - - if (p->gfx_nr == -1) { - p->gfx = NULL; - p->state &= (0xFF - (PSF_alife + PSF_playing)); - } - else { - p->gfx = &gfx.players[gfx_nr]; - p->state |= PSF_playing; - } -}; +/* player.c - everything what have to do with the player */ + +#include +#include "bomberclone.h" +#include "network.h" + + +void +draw_player (_player * player) +{ + SDL_Rect src, + dest; + int i; + + dest.w = src.w = player->gfx->size.x; + dest.h = src.h = player->gfx->size.y; + + dest.x = + gfx.offset.x + player->gfx->offset.x + (player->pos.x >> 8) * gfx.block.x + + gfx.postab[player->pos.x & 255]; + dest.y = + gfx.offset.y + player->gfx->offset.y + (player->pos.y >> 8) * gfx.block.y + + gfx.postab[player->pos.y & 255]; + + src.x = player->d * player->gfx->size.x; + src.y = player->frame * player->gfx->size.y; + + SDL_BlitSurface (player->gfx->ani.image, &src, gfx.screen, &dest); + + /* if the player is ill, draw this image above him */ + if (PS_IS_alife (player->state)) { + for (i = PI_max - 1; (i >= 0) && (player->ill[i].to == 0); i--); + if (i >= 0) { + dest.w = src.w = gfx.block.x * 2; + dest.h = src.h = gfx.block.y * 2; + + src.x = 0; + src.y = (2 * gfx.block.y) * player->illframe; + + dest.x = + (-(gfx.block.x >> 1)) + gfx.offset.x + (player->pos.x >> 8) * gfx.block.x + + gfx.postab[player->pos.x & 255]; + dest.y = + gfx.offset.y + ((player->pos.y >> 8) - 1) * gfx.block.y + + gfx.postab[player->pos.y & 255]; + + SDL_BlitSurface (gfx.ill.image, &src, gfx.screen, &dest); + + } + } + gfx_AddUpdateRect (dest.x, dest.y, dest.w, dest.h); + player->old = player->pos; // save this position +}; + + +void +restore_players_screen () +{ + int i, + x, + xe, + y, + ys, + ye; + + for (i = 0; i < MAX_PLAYERS; i++) + if ((PS_IS_used (bman.players[i].state)) && bman.players[i].old.x != -1) { + if ((bman.players[i].old.x & 0xFF) > 128) { + x = (bman.players[i].old.x >> 8); + xe = (bman.players[i].old.x >> 8) + 2; + } + else { + x = (bman.players[i].old.x >> 8) - 1; + xe = (bman.players[i].old.x >> 8) +1; + } + if (x < 0) + x = 0; + if (xe >= bman.fieldsize.x) + xe = bman.fieldsize.x - 1; + + ys = (bman.players[i].old.y >> 8) - 1; + ye = (bman.players[i].old.y >> 8) + 1; + if (ys < 0) + ys = 0; + if (ye >= bman.fieldsize.y) + ye = bman.fieldsize.y - 1; + + for (; x <= xe; x++) + for (y = ys; y <= ye; y++) + draw_stone (x, y); + } +}; + + +void +player_check_powerup (_player * p) +{ + int fx = p->pos.x >> 8; + int fy = p->pos.y >> 8; + int _x = p->pos.x & 255; + int _y = p->pos.y & 255; + + /* Get the right field position */ + if (_x > 128) + fx = fx + 1; + + if (_y > 128) + fy = fy + 1; + + /* we found a bomb powerup */ + if (bman.field[fx][fy].type == FT_bomb) { + if (p->bombs_n < MAX_BOMBS) + p->bombs_n++; + bman.field[fx][fy].type = FT_nothing; + if (bman.gametype != GT_single) + net_game_send_field (fx, fy); + } + + /* we found a fire powerup */ + if (bman.field[fx][fy].type == FT_fire) { + if (p->range < MAX_RANGE && p->ill[PI_range].to <= 0) + p->range++; + bman.field[fx][fy].type = FT_nothing; + if (bman.gametype != GT_single) + net_game_send_field (fx, fy); + } + + /* we found a shoe powerup */ + if (bman.field[fx][fy].type == FT_shoe) { + if (p->speed < MAX_SPEED && p->ill[PI_slow].to <= 0) + p->speed *= SPEEDMUL; + bman.field[fx][fy].type = FT_nothing; + if (bman.gametype != GT_single) + net_game_send_field (fx, fy); + } + + /* we found a death ?powerup? */ + if (bman.field[fx][fy].type == FT_death) { + player_set_ilness (p, -1); + net_game_send_ill (bman.p_nr); + + bman.field[fx][fy].type = FT_nothing; + if (bman.gametype != GT_single) + net_game_send_field (fx, fy); + } +}; + + +/* + check the givin field. if we are able to move on it + fx,fy = position on the field +*/ +int +check_field (short int fx, short int fy, _player * p) +{ + _point bombs[MAX_PLAYERS * MAX_BOMBS]; + int res = 0; + + if (bman.field[fx][fy].type != FT_stone && bman.field[fx][fy].type != FT_block) + res = 1; + + get_bomb_on (fx, fy, bombs); + if (bombs[0].x != -1) + res = 0; + + return res; +} + + +int +stepmove_player () +{ + _player *p = &bman.players[bman.p_nr]; + int _x, + _y, + dx = 0, + dy = 0, + fx, + fy, + speed = 0; + + if (p->m == 1) { + + fx = p->pos.x >> 8; + fy = p->pos.y >> 8; + + _x = p->pos.x & 255; + _y = p->pos.y & 255; + + // do direction correction for going up/down + if (_x > 0 && _x <= 128 && (p->d == up || p->d == down)) + p->d = left; + if (_x > 128 && _x < 256 && (p->d == up || p->d == down)) + p->d = right; + + // do direction correction for left/right + if (_y > 0 && _y <= 128 && (p->d == left || p->d == right)) + p->d = up; + if (_y > 128 && _y < 256 && (p->d == left || p->d == right)) + p->d = down; + + /* get the pos to the next field */ + if (p->d == left) + speed = _x; + else if (p->d == right) + speed = 256 - _x; + else if (p->d == up) + speed = _y; + else + speed = 256 - _y; + + if (speed > p->speed || speed == 0) + speed = p->speed; + + // go left + if (p->d == left && _y == 0 && ((_x == 0 && check_field (fx - 1, fy, p)) || (_x > 0))) + dx = -speed; + + // go right + if (p->d == right && _y == 0 && ((_x == 0 && check_field (fx + 1, fy, p)) || (_x > 0))) + dx = speed; + + // go up + if (p->d == up && _x == 0 && ((_y == 0 && check_field (fx, fy - 1, p)) || (_y > 0))) + dy = -speed; + + // go down + if (p->d == down && _x == 0 && ((_y == 0 && check_field (fx, fy + 1, p)) || (_y > 0))) + dy = speed; + + p->pos.x = p->pos.x + dx; + p->pos.y = p->pos.y + dy; + + player_check_powerup (p); + } + + if (dx == 0 && dy == 0) + return 0; + return (p->speed - speed); +}; + + +void +move_player () +{ + int oldd, + stepsleft, + speed; + _player *p = &bman.players[bman.p_nr]; + + oldd = p->d; + if (p->m) { + player_animation (p); + + if ((stepsleft = stepmove_player ()) > 0) { + /* save the speed and go the rest of the step */ + p->d = oldd; + speed = p->speed; + p->speed = stepsleft; + stepmove_player (); + p->speed = speed; + } + + /* network packet send control - send data if it's time to send or if we need to */ + if (bman.gametype != GT_single) + net_game_send_playermove (bman.p_nr, (p->old_m == 0)); + } + + /* the player just stopt moving so send data */ + if (bman.gametype != GT_single && p->m == 0 && p->old_m != 0) + net_game_send_playermove (bman.p_nr, 1); + + p->old_m = p->m; // save the old state + p->m = 0; +}; + + +void +player_drop_bomb () +{ + _player *player = &bman.players[bman.p_nr]; + _bomb *bomb = NULL; + int i, + _x, + _y; + _point bombs[MAX_PLAYERS * MAX_BOMBS]; + + for (i = 0; ((i < player->bombs_n) && (player->bombs[i].state != BS_off)); i++); + + if (i < player->bombs_n) { // free bomb found + // get the best position for the bomb. + bomb = &player->bombs[i]; + + bomb->pos.x = player->pos.x >> 8; + bomb->pos.y = player->pos.y >> 8; + _x = player->pos.x & 255; + _y = player->pos.y & 255; + + if (_x > 0 && _x <= 128) + _x = 0; + else if (_x > 128) { + bomb->pos.x += 1; + _x = 0; + } + + if (_y > 0 && _y <= 128) + _y = 0; + else if (_y > 12) { + bomb->pos.y += 1; + _y = 0; + } + + get_bomb_on (bomb->pos.x, bomb->pos.y, bombs); + if (bombs[0].x != -1) // is there already a bomb + return; + + d_printf ("Player %d Dropped Bomb %d\n", bman.p_nr, i); + bomb->r = player->range; + bomb->state = BS_ticking; + bomb->ex_nr = -1; + + bomb->to = BOMB_TIMEOUT * TIME_FACTOR; // 5 Secs * 200 + + if (bman.gametype != GT_single) { + net_game_send_bomb (bman.p_nr, i); + if (GT_MP_PTPS) + bomb->to = bomb->to + ((2 * RESENDCACHE_RETRY) / TIME_FACTOR); + } + } +}; + + +/* +check the field - 4 pixels from every side.. so it's not anymore that tricky to get +away from bombs.. */ +void +get_player_on (short int x, short int y, int pl_nr[]) +{ + int i, + p; + + for (i = 0, p = 0; p < MAX_PLAYERS; p++) + if (PS_IS_alife (bman.players[p].state)) { + if (bman.players[p].pos.x - 42 > x - 256 + && bman.players[p].pos.x + 42 < x + 256 + && bman.players[p].pos.y - 42 > y - 256 && bman.players[p].pos.y + 42 < y + 256) { + pl_nr[i] = p; + i++; + } + } + pl_nr[i] = -1; +}; + + +void +player_died (_player * player, signed char dead_by) +{ + // player die ! + + d_printf ("player_died (%10s)\n", player->name); + + if (PS_IS_alife (player->state) && dead_by >= 0 && dead_by < MAX_PLAYERS) + if (bman.p_nr != dead_by) + bman.players[dead_by].points++; + + player->state &= (0xFF - PSF_alife); + player->dead_by = dead_by; + + net_game_send_player (bman.p_nr); +}; + + +void +draw_players () +{ + int p; + + for (p = 0; p < MAX_PLAYERS; p++) { + if (PS_IS_playing (bman.players[p].state)) + draw_player (&bman.players[p]); + } +}; + + +void +player_animation (_player * player) +{ + if (player->gfx == NULL) + return; + + if (player->frame < player->gfx->ani.frames + && (player->frameto <= 0 || player->frameto > ANI_PLAYERTIMEOUT)) { + player->frameto = ANI_PLAYERTIMEOUT; + player->frame++; + } + + if (player->frame >= player->gfx->ani.frames && PS_IS_alife (player->state)) + player->frame = 0; + + if (player->frameto > 0) + player->frameto--; +}; + + +void +dead_playerani () +{ + int i; + + for (i = 0; i < MAX_PLAYERS; i++) + if (PS_IS_dead (bman.players[i].state)) + player_animation (&bman.players[i]); +}; + + +void +player_calcstep (_player * pl) +{ + _point d; + int fx, + fy; + + player_animation (pl); + + fx = pl->pos.x >> 8; + fy = pl->pos.y >> 8; + + if (bman.field[fx][fy].type != FT_block && bman.field[fx][fy].type != FT_stone) { + d.x = 0; + d.y = 0; + if (pl->d == left) + d.x = -16; + else if (pl->d == right) + d.x = 16; + else if (pl->d == up) + d.y = -16; + else if (pl->d == down) + d.y = 16; + + pl->pos.x += d.x; + pl->pos.y += d.y; + } +}; + + +/* + calc the position on the screen for moving network players +*/ +void +player_calcpos () +{ + _player *pl; + int oldm, + oldd, + p; + + for (p = 0; p < MAX_PLAYERS; p++) { + pl = &bman.players[p]; + if (PS_IS_netplayer (pl->state) && pl->m != 0) { + + if (pl->speeddat == 0 || pl->speed == 1 || pl->speed == 3) + pl->speeddat = 1; + else + pl->speeddat = 0; + + oldm = pl->m; + oldd = pl->d; + + if (pl->speed > 1) + stepmove_player (); + + if (pl->speeddat) { + pl->m = oldm; + pl->d = oldd; + player_calcstep (pl); + } + } + } + +}; + + +void +player_ilness_loop () +{ + _player *p; + int type, + pnr, + i, + tmp, + send; + int pl[MAX_PLAYERS + 1]; + + /* do the illness for the network players */ + for (pnr = 0; pnr < MAX_PLAYERS; pnr++) + if (pnr != bman.p_nr && PS_IS_alife (bman.players[pnr].state)) { + p = &bman.players[pnr]; + for (type = 0; type < PI_max; type++) + if (p->ill[type].to > 0) { + p->ill[type].to--; + p->illframeto--; + if (p->illframeto <= 0 || p->illframeto > ANI_PLAYERILLTIMEOUT) { + p->illframeto = ANI_PLAYERILLTIMEOUT; + p->illframe++; + if (p->illframe < 0 || p->illframe >= gfx.ill.frames) + p->illframe = 0; + } + } + } + + /* check if we have contact with an other ill player */ + p = &bman.players[bman.p_nr]; + + get_player_on (p->pos.x, p->pos.y, pl); + for (i = 0; (pl[i] != -1 && i < MAX_PLAYERS); i++) + if (pl[i] != bman.p_nr) { + send = 0; + for (type = 0; type < PI_max; type++) { + if (bman.players[pl[i]].ill[type].to > p->ill[type].to) { + tmp = p->ill[type].to; + player_set_ilness (p, type); + p->ill[type].to = bman.players[pl[i]].ill[type].to; + if (tmp <= 0) + send = 1; + } + } + if (send != 0) + net_game_send_ill (bman.p_nr); + } + + /* do the illness for our own player */ + for (type = 0; type < PI_max; type++) + if (p->ill[type].to > 0) { + p->ill[type].to--; + if (p->ill[type].to == 0) + player_clear_ilness (p, type); + else { + p->illframeto--; + if (p->illframeto <= 0 || p->illframeto > ANI_PLAYERILLTIMEOUT) { + p->illframeto = ANI_PLAYERILLTIMEOUT; + p->illframe++; + if (p->illframe < 0 || p->illframe >= gfx.ill.frames) + p->illframe = 0; + } + + if (type == PI_keys) { + /* switch direction for player key illness */ + if (p->m > 0) + switch (p->d) { + case (left): + p->d = right; + break; + case (right): + p->d = left; + break; + case (up): + p->d = down; + break; + case (down): + p->d = up; + break; + } + } + else if (type == PI_bomb) + /* player is dropping bombs */ + player_drop_bomb (); + } + } +} + + +/* player picked up the death powerup, add timeout for +this illness to the maybe excisting timeout */ +void +player_set_ilness (_player * p, int t) +{ + int type; + + if (t == -1) + type = s_random (PI_max); + else + type = t; + + d_printf ("Ilness : %d\n", type); + + if (type == PI_slow) { + if (p->ill[type].to == 0) + p->ill[type].data = p->speed; + p->speed = 6; + } + + else if (type == PI_range) { + if (p->ill[type].to == 0) + p->ill[type].data = p->range; + p->range = 1; + } + + p->ill[type].to += TIME_FACTOR * IL_TIMEOUT; +}; + + +/* players ilness is over now */ +void +player_clear_ilness (_player * p, int type) +{ + if (type < 0 || type >= PI_max) + return; + + if (type == PI_slow) + p->speed = p->ill[type].data; + + if (type == PI_range) + p->range = p->ill[type].data; + + p->ill[type].to = 0; + + net_game_send_ill (bman.p_nr); +}; + + +void +player_set_gfx (_player * p, signed char gfx_nr) +{ + p->gfx_nr = gfx_nr; + + if (p->gfx_nr < 0 || p->gfx_nr >= MAX_PLAYERS) + p->gfx_nr = -1; + + if (p->gfx_nr == -1) { + p->gfx = NULL; + p->state &= (0xFF - (PSF_alife + PSF_playing)); + } + else { + p->gfx = &gfx.players[gfx_nr]; + p->state |= PSF_playing; + } +}; diff --git a/src/single.c b/src/single.c index 591cab0..7b45111 100644 --- a/src/single.c +++ b/src/single.c @@ -1,66 +1,66 @@ -/* $Id: single.c,v 1.9 2003/05/07 21:28:13 stpohle Exp $ */ -/* single player */ - -#include "basic.h" -#include "bomberclone.h" - -void -single_game_new (int ai_players) -{ - int p, - i; - - // set players on field 1,1 - for (p = 0; p < MAX_PLAYERS; p++) { - bman.players[p].pos.x = -1; - bman.players[p].pos.y = -1; - bman.players[p].state = 0; - - // reset bombs - bman.players[p].bombs_n = START_BOMBS; - bman.players[p].range = START_RANGE; - bman.players[p].speed = START_SPEED; - for (i = 0; i < MAX_BOMBS; i++) { - bman.players[p].bombs[i].state = BS_off; - bman.players[p].bombs[i].ex_nr = -1; - } - - for (i = 0; i < PI_max; i++) - bman.players[p].ill[i].to = 0; - bman.players[p].frame = 0; - bman.players[p].frameto = 0; - bman.players[p].d = 0; - } - - bman.p_nr = 0; - bman.players[bman.p_nr].state = PSFM_alife; - player_set_gfx (&bman.players[bman.p_nr], 0); - bman.last_ex_nr = 1; - - init_map_tileset(); - - bman.players_nr_s = 1; - bman.players_nr = 1; - bman.gametype = GT_single; - bman.state = GS_running; -}; - - -void single_loop () { - -}; - - -void single_create_ai () { - int p; - _player *pl; - - /* find free players */ - for (pl = NULL, p = 0; (pl == NULL && p < MAX_PLAYERS); p++) - if (!(PS_IS_used (bman.players[p].state))) - pl = &bman.players[p]; - - if (pl == NULL) - return; - -}; +/* $Id: single.c,v 1.10 2003/05/08 14:35:49 stpohle Exp $ */ +/* single player */ + +#include "basic.h" +#include "bomberclone.h" + +void +single_game_new (int ai_players) +{ + int p, + i; + + // set players on field 1,1 + for (p = 0; p < MAX_PLAYERS; p++) { + bman.players[p].pos.x = -1; + bman.players[p].pos.y = -1; + bman.players[p].state = 0; + + // reset bombs + bman.players[p].bombs_n = START_BOMBS; + bman.players[p].range = START_RANGE; + bman.players[p].speed = START_SPEED; + for (i = 0; i < MAX_BOMBS; i++) { + bman.players[p].bombs[i].state = BS_off; + bman.players[p].bombs[i].ex_nr = -1; + } + + for (i = 0; i < PI_max; i++) + bman.players[p].ill[i].to = 0; + bman.players[p].frame = 0; + bman.players[p].frameto = 0; + bman.players[p].d = 0; + } + + bman.p_nr = 0; + bman.players[bman.p_nr].state = PSFM_alife; + player_set_gfx (&bman.players[bman.p_nr], 0); + bman.last_ex_nr = 1; + + init_map_tileset(); + + bman.players_nr_s = 1; + bman.players_nr = 1; + bman.gametype = GT_single; + bman.state = GS_running; +}; + + +void single_loop () { + +}; + + +void single_create_ai () { + int p; + _player *pl; + + /* find free players */ + for (pl = NULL, p = 0; (pl == NULL && p < MAX_PLAYERS); p++) + if (!(PS_IS_used (bman.players[p].state))) + pl = &bman.players[p]; + + if (pl == NULL) + return; + +}; diff --git a/src/sysfunc.h b/src/sysfunc.h index 0737be4..2ef14f9 100644 --- a/src/sysfunc.h +++ b/src/sysfunc.h @@ -1,27 +1,27 @@ -/* $Id: sysfunc.h,v 1.4 2003/05/07 21:28:13 stpohle Exp $ */ -/* include some system near functions */ - -#ifndef _SYSFUNC_H_ -#define _SYSFUNC_H_ - -#define MAX_DIRENTRYS 1024 - -enum _dirflags { - DF_dir = 1, - DF_file = 2 -}; - -struct __direntry { - unsigned char flags; - char name[LEN_FILENAME]; - struct __direntry *next; -} typedef _direntry; - -extern void s_delay (int ms); -extern int s_random (int maxnr); -extern char *s_gethomedir (); - -extern _direntry *s_getdir (char *path); -extern _direntry *s_dirfilter (_direntry *dirstart, signed char dirflags); - -#endif +/* $Id: sysfunc.h,v 1.5 2003/05/08 14:35:49 stpohle Exp $ */ +/* include some system near functions */ + +#ifndef _SYSFUNC_H_ +#define _SYSFUNC_H_ + +#define MAX_DIRENTRYS 1024 + +enum _dirflags { + DF_dir = 1, + DF_file = 2 +}; + +struct __direntry { + unsigned char flags; + char name[LEN_FILENAME]; + struct __direntry *next; +} typedef _direntry; + +extern void s_delay (int ms); +extern int s_random (int maxnr); +extern char *s_gethomedir (); + +extern _direntry *s_getdir (char *path); +extern _direntry *s_dirfilter (_direntry *dirstart, signed char dirflags); + +#endif diff --git a/src/udp.c b/src/udp.c index b667b2e..1e3c23e 100644 --- a/src/udp.c +++ b/src/udp.c @@ -1,300 +1,300 @@ -/* $Id: udp.c,v 1.6 2003/05/07 21:28:13 stpohle Exp $ */ -/* udp.c code for the network - File Version 0.2 -*/ - -#define UDP_LEN_HOSTNAME 128 -#include -#include -#include -#include -#include -#include -#ifdef _WIN32 - #include - #include -#else - #include - #include - #include - #include - #include - #include -#endif - -#ifdef _WIN32 -#define _sockaddr sockaddr -#define bzero(a,b) memset(a,'\0',b) -#else -#define _sockaddr sockaddr_in6 -#endif - -extern char *dns_net_getip (char *host); -extern int dns_filladdr (char *host, int hostlen, char *port, int portlen, int ai_family, - struct _sockaddr *sAddr); -extern int udp_get (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family); -extern int udp_server (char *port, int ai_family); -extern void udp_send (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family); -extern void udp_close (int sock); - -char dnsip[UDP_LEN_HOSTNAME]; - -extern void d_printf (char *fmt,...); - - -/* closes an existing udp server */ -void -udp_close (int sock) -{ - if (sock != -1) - close (sock); - sock = -1; -}; - - -int -dns_filladdr (char *host, int hostlen, char *port, int portlen, int ai_family, - struct _sockaddr *sAddr) -{ -#ifdef _WIN32 - struct hostent *he; - char txt[255]; - - if (host[0] == 0 || port[0] == 0) { - /* we have to complete server and port from the sAddr */ - - strncpy (host, inet_ntoa (((struct sockaddr_in *) sAddr)->sin_addr), hostlen); - sprintf (txt, "%d", ntohs (((struct sockaddr_in *) sAddr)->sin_port)); - strncpy (port, txt, portlen); - } - else { - /* we have to complete the sAddr struct */ - - if ((he = gethostbyname (host)) == NULL) { // get the host info - perror ("dns_filladdr (gethostbyname)"); - return -1; - } - - ((struct sockaddr_in *) sAddr)->sin_family = ai_family; // host byte order - ((struct sockaddr_in *) sAddr)->sin_port = htons (atoi (port)); // short, network byte order - ((struct sockaddr_in *) sAddr)->sin_addr = *((struct in_addr *) he->h_addr); - memset (&(((struct sockaddr_in *) sAddr)->sin_zero), '\0', 8); // zero the rest of the struct - } - -#else - - struct addrinfo hints, - *res; - int err, i, - addrlen; - - if (host[0] == 0 || port[0] == 0) { - /* we have to complete server and port from the sAddr */ - - if (ai_family == PF_INET) - addrlen = sizeof (struct sockaddr_in); - else - addrlen = sizeof (struct sockaddr_in6); - - bzero (host, hostlen); - bzero (port, portlen); - - if ((err = - getnameinfo ((struct sockaddr *) sAddr, addrlen, host, hostlen, port, portlen, - NI_NUMERICHOST | NI_NUMERICSERV)) < 0) { - d_printf ("dns_filladdr (getnameinfo): %s\n", gai_strerror (err)); - return -1; - } - - if (strstr (host, "::ffff:") != NULL) { - for (i = 0; host[i + 7] != 0; i++) - host[i] = host[i+7]; - host[i] = 0; - } - } - else { - /* we have to complete the sAddr struct */ - - bzero (&hints, sizeof (struct addrinfo)); - hints.ai_family = ai_family; - hints.ai_socktype = SOCK_DGRAM; - - if ((err = getaddrinfo (host, port, &hints, &res)) < 0) { - d_printf ("dns_filladdr (getaddrinfo):%s\n", gai_strerror (err)); - return -1; - } - - // i hope it's enough to copy only sizeof (struct sockaddr) ? - memcpy (sAddr, res->ai_addr, res->ai_addrlen); - - freeaddrinfo (res); - } - -#endif - - return 0; -} - - -/* send text to someone */ -void -udp_send (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family) -{ - int addrlen; - - if (ai_family == PF_INET) - addrlen = sizeof (struct sockaddr_in); -#ifndef _WIN32 - else - addrlen = sizeof (struct sockaddr_in6); -#endif - - if (sendto (sock, text, len, 0, (struct sockaddr *) sAddr, addrlen) == -1) - perror ("udp_send :"); -}; - - -int -udp_server (char *port, int ai_family) -{ -#ifdef _WIN32 - - int sock; - struct sockaddr_in sAddr; // my address information - - if ((sock = socket (ai_family, SOCK_DGRAM, 0)) == -1) { - perror ("udp_server: socket"); - return -1; - } - - sAddr.sin_family = AF_INET; // host byte order - sAddr.sin_port = htons (atoi (port)); // short, network byte order - sAddr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP - - memset (&(sAddr.sin_zero), '\0', 8); // zero the rest of the struct - - if (bind (sock, (struct sockaddr *) &sAddr, sizeof (struct sockaddr)) == -1) { - perror ("udp_server: bind"); - return -1; - } - -#else - struct addrinfo hints, - *res, - *sres; - int err, - sock, - ai_family_; - - bzero (&hints, sizeof (struct addrinfo)); - - hints.ai_flags = AI_PASSIVE; - hints.ai_family = ai_family; - hints.ai_socktype = SOCK_DGRAM; - - ai_family_ = 0; - - if ((err = getaddrinfo (NULL, port, &hints, &res)) == 0) { - sres = res; - while ((ai_family_ == 0) && (sres)) { - if (sres->ai_family == ai_family || ai_family == PF_UNSPEC) - ai_family_ = sres->ai_family; - else - sres = sres->ai_next; - } - - if (sres == NULL) - sres = res; - - ai_family_ = sres->ai_family; - if (ai_family_ != ai_family && ai_family != PF_UNSPEC) { - // ai_family is not identic - freeaddrinfo (res); - return -1; - } - - if ((sock = socket (sres->ai_family, SOCK_DGRAM, 0)) < 0) { - perror ("UDP_Server (socket):"); - freeaddrinfo (res); - return -1; - } - - if ((err = bind (sock, sres->ai_addr, sres->ai_addrlen)) < 0) { - perror ("UDP_Server (bind):"); - close (sock); - freeaddrinfo (res); - return -1; - } - - freeaddrinfo (res); - } - else { - sock = -1; - d_printf ("UDP_Server (getaddrinfo):%s\n", gai_strerror (err)); - } -#endif - - return sock; -}; - -/* - gets some text - RESULT: 0 for nothing on there -*/ -int -udp_get (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family) -{ - int clen, - msglen; - fd_set sockset; - struct timeval tval; - - if (sock == -1) - return -1; - - /* what version of tcp/ip we're using */ - if (ai_family == AF_INET) - clen = sizeof (struct sockaddr_in); -#ifndef _WIN32 - else - clen = sizeof (struct sockaddr_in6); -#endif - - bzero (text, len); - - // check if we have got any data - FD_ZERO (&sockset); - FD_SET (sock, &sockset); - - tval.tv_sec = 0; - tval.tv_usec = 100; - - msglen = 0; - - if (select (sock + 1, &sockset, NULL, NULL, &tval)) { - - msglen = recvfrom (sock, text, len, 0, (struct sockaddr *) sAddr, &clen); - if (msglen < 0) - return 0; - - if ((msglen >= 0) && (msglen < len)) - text[msglen] = 0; - } - return msglen; -}; - - -char * -dns_net_getip (char *host) -{ - struct hostent *hAddr; - - hAddr = gethostbyname (host); - - if (hAddr == NULL) - return NULL; - - strncpy (dnsip, inet_ntoa (*((struct in_addr *) hAddr->h_addr)), UDP_LEN_HOSTNAME); - - return dnsip; -}; +/* $Id: udp.c,v 1.7 2003/05/08 14:35:49 stpohle Exp $ */ +/* udp.c code for the network + File Version 0.2 +*/ + +#define UDP_LEN_HOSTNAME 128 +#include +#include +#include +#include +#include +#include +#ifdef _WIN32 + #include + #include +#else + #include + #include + #include + #include + #include + #include +#endif + +#ifdef _WIN32 +#define _sockaddr sockaddr +#define bzero(a,b) memset(a,'\0',b) +#else +#define _sockaddr sockaddr_in6 +#endif + +extern char *dns_net_getip (char *host); +extern int dns_filladdr (char *host, int hostlen, char *port, int portlen, int ai_family, + struct _sockaddr *sAddr); +extern int udp_get (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family); +extern int udp_server (char *port, int ai_family); +extern void udp_send (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family); +extern void udp_close (int sock); + +char dnsip[UDP_LEN_HOSTNAME]; + +extern void d_printf (char *fmt,...); + + +/* closes an existing udp server */ +void +udp_close (int sock) +{ + if (sock != -1) + close (sock); + sock = -1; +}; + + +int +dns_filladdr (char *host, int hostlen, char *port, int portlen, int ai_family, + struct _sockaddr *sAddr) +{ +#ifdef _WIN32 + struct hostent *he; + char txt[255]; + + if (host[0] == 0 || port[0] == 0) { + /* we have to complete server and port from the sAddr */ + + strncpy (host, inet_ntoa (((struct sockaddr_in *) sAddr)->sin_addr), hostlen); + sprintf (txt, "%d", ntohs (((struct sockaddr_in *) sAddr)->sin_port)); + strncpy (port, txt, portlen); + } + else { + /* we have to complete the sAddr struct */ + + if ((he = gethostbyname (host)) == NULL) { // get the host info + perror ("dns_filladdr (gethostbyname)"); + return -1; + } + + ((struct sockaddr_in *) sAddr)->sin_family = ai_family; // host byte order + ((struct sockaddr_in *) sAddr)->sin_port = htons (atoi (port)); // short, network byte order + ((struct sockaddr_in *) sAddr)->sin_addr = *((struct in_addr *) he->h_addr); + memset (&(((struct sockaddr_in *) sAddr)->sin_zero), '\0', 8); // zero the rest of the struct + } + +#else + + struct addrinfo hints, + *res; + int err, i, + addrlen; + + if (host[0] == 0 || port[0] == 0) { + /* we have to complete server and port from the sAddr */ + + if (ai_family == PF_INET) + addrlen = sizeof (struct sockaddr_in); + else + addrlen = sizeof (struct sockaddr_in6); + + bzero (host, hostlen); + bzero (port, portlen); + + if ((err = + getnameinfo ((struct sockaddr *) sAddr, addrlen, host, hostlen, port, portlen, + NI_NUMERICHOST | NI_NUMERICSERV)) < 0) { + d_printf ("dns_filladdr (getnameinfo): %s\n", gai_strerror (err)); + return -1; + } + + if (strstr (host, "::ffff:") != NULL) { + for (i = 0; host[i + 7] != 0; i++) + host[i] = host[i+7]; + host[i] = 0; + } + } + else { + /* we have to complete the sAddr struct */ + + bzero (&hints, sizeof (struct addrinfo)); + hints.ai_family = ai_family; + hints.ai_socktype = SOCK_DGRAM; + + if ((err = getaddrinfo (host, port, &hints, &res)) < 0) { + d_printf ("dns_filladdr (getaddrinfo):%s\n", gai_strerror (err)); + return -1; + } + + // i hope it's enough to copy only sizeof (struct sockaddr) ? + memcpy (sAddr, res->ai_addr, res->ai_addrlen); + + freeaddrinfo (res); + } + +#endif + + return 0; +} + + +/* send text to someone */ +void +udp_send (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family) +{ + int addrlen; + + if (ai_family == PF_INET) + addrlen = sizeof (struct sockaddr_in); +#ifndef _WIN32 + else + addrlen = sizeof (struct sockaddr_in6); +#endif + + if (sendto (sock, text, len, 0, (struct sockaddr *) sAddr, addrlen) == -1) + perror ("udp_send :"); +}; + + +int +udp_server (char *port, int ai_family) +{ +#ifdef _WIN32 + + int sock; + struct sockaddr_in sAddr; // my address information + + if ((sock = socket (ai_family, SOCK_DGRAM, 0)) == -1) { + perror ("udp_server: socket"); + return -1; + } + + sAddr.sin_family = AF_INET; // host byte order + sAddr.sin_port = htons (atoi (port)); // short, network byte order + sAddr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP + + memset (&(sAddr.sin_zero), '\0', 8); // zero the rest of the struct + + if (bind (sock, (struct sockaddr *) &sAddr, sizeof (struct sockaddr)) == -1) { + perror ("udp_server: bind"); + return -1; + } + +#else + struct addrinfo hints, + *res, + *sres; + int err, + sock, + ai_family_; + + bzero (&hints, sizeof (struct addrinfo)); + + hints.ai_flags = AI_PASSIVE; + hints.ai_family = ai_family; + hints.ai_socktype = SOCK_DGRAM; + + ai_family_ = 0; + + if ((err = getaddrinfo (NULL, port, &hints, &res)) == 0) { + sres = res; + while ((ai_family_ == 0) && (sres)) { + if (sres->ai_family == ai_family || ai_family == PF_UNSPEC) + ai_family_ = sres->ai_family; + else + sres = sres->ai_next; + } + + if (sres == NULL) + sres = res; + + ai_family_ = sres->ai_family; + if (ai_family_ != ai_family && ai_family != PF_UNSPEC) { + // ai_family is not identic + freeaddrinfo (res); + return -1; + } + + if ((sock = socket (sres->ai_family, SOCK_DGRAM, 0)) < 0) { + perror ("UDP_Server (socket):"); + freeaddrinfo (res); + return -1; + } + + if ((err = bind (sock, sres->ai_addr, sres->ai_addrlen)) < 0) { + perror ("UDP_Server (bind):"); + close (sock); + freeaddrinfo (res); + return -1; + } + + freeaddrinfo (res); + } + else { + sock = -1; + d_printf ("UDP_Server (getaddrinfo):%s\n", gai_strerror (err)); + } +#endif + + return sock; +}; + +/* + gets some text + RESULT: 0 for nothing on there +*/ +int +udp_get (int sock, char *text, int len, struct _sockaddr *sAddr, int ai_family) +{ + int clen, + msglen; + fd_set sockset; + struct timeval tval; + + if (sock == -1) + return -1; + + /* what version of tcp/ip we're using */ + if (ai_family == AF_INET) + clen = sizeof (struct sockaddr_in); +#ifndef _WIN32 + else + clen = sizeof (struct sockaddr_in6); +#endif + + bzero (text, len); + + // check if we have got any data + FD_ZERO (&sockset); + FD_SET (sock, &sockset); + + tval.tv_sec = 0; + tval.tv_usec = 100; + + msglen = 0; + + if (select (sock + 1, &sockset, NULL, NULL, &tval)) { + + msglen = recvfrom (sock, text, len, 0, (struct sockaddr *) sAddr, &clen); + if (msglen < 0) + return 0; + + if ((msglen >= 0) && (msglen < len)) + text[msglen] = 0; + } + return msglen; +}; + + +char * +dns_net_getip (char *host) +{ + struct hostent *hAddr; + + hAddr = gethostbyname (host); + + if (hAddr == NULL) + return NULL; + + strncpy (dnsip, inet_ntoa (*((struct in_addr *) hAddr->h_addr)), UDP_LEN_HOSTNAME); + + return dnsip; +};