You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bomberclone/src/packets.c

1081 lines
29 KiB

/* 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++;
bman.updatestatusbar=1;
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;
else
bman.bfield[bomb->pos.x][bomb->pos.y] = 1; // keep the bfield up to date
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 ();
};
/* Player Special
* moves/bombs... whatever will be send as we use it */
void do_special (struct pkg_special *sp_pkg, _net_addr *addr) {
if (addr->pl_nr == -1)
return;
if (sp_pkg->pl_nr == -1)
return;
/* check if the right player is sending the information */
if (addr->pl_nr != 0 && addr->pl_nr != sp_pkg->pl_nr)
return;
bman.players[sp_pkg->pl_nr].special = sp_pkg->typ;
special_use (sp_pkg->pl_nr);
};
void send_special (_net_addr *addr, int p_nr, int typ) {
struct pkg_special sp_dat;
sp_dat.h.typ = PKG_special;
sp_dat.h.len = sizeof (struct pkg_special);
sp_dat.pl_nr = p_nr;
sp_dat.h.flags = PKGF_ackreq;
send_pkg ((struct pkg *) &sp_dat, addr);
};
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)
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;
};