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/network.c

953 lines
27 KiB

/* $Id: network.c,v 1.61 2004/02/04 22:56:55 patty21 Exp $ */
/*
network routines.
*/
#include "bomberclone.h"
#include "network.h"
#include "chat.h"
#include "packets.h"
#include "ogcache-client.h"
#include "menu.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 (players[p].state) && !PS_IS_aiplayer(players[p].state)) {
npkg = &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 ()
{
char host[LEN_SERVERNAME];
char port[LEN_PORT];
/* 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
if (bman.net_ai_family == PF_INET)
sprintf (host, "IPv4");
#ifndef _WIN32
else if (bman.net_ai_family == PF_INET6)
sprintf (host, "IPv6");
#endif
else
sprintf (host, "IPv (unknown)");
d_printf ("Network Init with %s.\n", host);
bman.sock = -1;
timestamp = SDL_GetTicks ();
// start the udp server
bman.sock = udp_server (bman.port, bman.net_ai_family);
if (bman.sock < 0) {
#ifdef _WIN32
WSACleanup ();
#endif
return -1;
}
if (bman.notifygamemaster) {
network_server_port (bman.ogcserver, host, LEN_SERVERNAME, port, LEN_PORT);
if (ogc_init (bman.ogc_port, host, port, "BomberClone", bman.net_ai_family) == 0)
bman.notifygamemaster = 0;
}
// we have got our socket.. so now allocate the memory for the resend_cache
resend_cache.data = (char *) malloc (PKG_RESENDCACHE_SIZE);
resend_cache.fill = 0;
return 0;
};
/*
shutdown the network part
*/
void
network_shutdown ()
{
int i;
d_printf ("network_shutdown\n");
if (GT_MP_PTPM) {
d_printf ("Server Quit Send information\n");
for (i = 0; i < MAX_PLAYERS; i++)
if (i != bman.p_servnr && PS_IS_netplayer (players[i].state) && !PS_IS_aiplayer (players[i].state))
send_quit (&players[i].net.addr, NULL, NULL);
}
else if (players[bman.p_servnr].net.addr.host[0] != 0)
send_quit (&players[bman.p_servnr].net.addr, NULL, NULL);
if (bman.notifygamemaster) {
ogc_sendgamequit (bman.sock);
ogc_shutdown ();
}
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 ((players[pl_nr].state & (PSF_net + PSF_used + PSF_ai)) == (PSF_used + PSF_net)
&& timestamp - players[pl_nr].net.timestamp > timeout
&& players[pl_nr].net.pingreq != players[pl_nr].net.pingack) {
d_printf ("net_check_timeout pl_nr=%d, ack=%d, req=%d, timediff=%d\n", pl_nr,
players[pl_nr].net.pingack, players[pl_nr].net.pingreq,
timestamp - players[pl_nr].net.timestamp);
players[pl_nr].net.timestamp = timestamp;
players[pl_nr].net.pingack = players[pl_nr].net.pingreq;
send_ping (&players[pl_nr].net.addr, players[pl_nr].net.pingack + 100,
PKG_pingreq);
}
if ((players[pl_nr].state & (PSF_net + PSF_used + PSF_ai)) == (PSF_used + PSF_net)
&& timestamp - players[pl_nr].net.timestamp > timeout
&& players[pl_nr].net.pingreq == players[pl_nr].net.pingack) {
d_printf ("net_check_timeout pl_nr=%d, ack=%d, req=%d, timediff=%d\n", pl_nr,
players[pl_nr].net.pingack, players[pl_nr].net.pingreq,
timestamp - 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 (bman.p_servnr)) {
d_printf ("Server Timed Out\n");
bman.state = GS_startup;
}
}
else if (GT_MP_PTPM) {
for (i = 1; i < MAX_PLAYERS; i++)
if (i != bman.p_nr && 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 st)
{
char text[255];
unsigned char b;
int y = 0,
b1,
z,
zx=200,
i,
j,
s=map.size.y+MAX_PLAYERS+GAME_MAX_TUNNELS;
SDL_Rect src,
dest;
z=gfx.res.x-zx-30-8;
for (i = 0; i < MAX_PLAYERS; i++)
if (PS_IS_used (players[i].state)) {
y += 50;
if (st) {
redraw_logo (0, y, gfx.res.x, y + 50);
if (players[i].gfx_nr != -1) {
dest.w = src.w = players[i].gfx->smal_size.x;
dest.h = src.h = players[i].gfx->smal_size.y;
src.x = players[i].gfx->smal_size.x * down;
src.y = 0;
dest.x = 50;
dest.y = y;
SDL_BlitSurface (players[i].gfx->smal_image, &src, gfx.screen, &dest);
gfx_blitupdaterectadd (&dest);
}
dest.x = zx;
dest.y = y;
dest.w = menu.listimages[1][0]->w;
dest.h = menu.listimages[1][0]->h;
gfx_blit (menu.listimages[1][0], NULL, gfx.screen, &dest, 10000);
dest.x = z+zx+4;
gfx_blit (menu.listimages[1][2], NULL, gfx.screen, &dest, 10000);
// draw the bottom left and right of the list
dest.y = y+29;
gfx_blit (menu.listimages[1][8], NULL, gfx.screen, &dest, 10000);
dest.x = zx;
gfx_blit (menu.listimages[1][6], NULL, gfx.screen, &dest, 10000);
//top & bottom
for (j=4;j<z+4;j+=4) {
dest.x=j+zx;dest.y=y;
gfx_blit (menu.listimages[1][1], NULL, gfx.screen, &dest, 10000);
dest.y = y+29;
gfx_blit (menu.listimages[1][7], NULL, gfx.screen, &dest, 10000);
}
//left &right
for (j=4;j<29;j+=4) {
dest.x=zx;dest.y=y+j;
gfx_blit (menu.listimages[1][3], NULL, gfx.screen, &dest, 10000);
dest.x = z+zx+4;
gfx_blit (menu.listimages[1][5], NULL, gfx.screen, &dest, 10000);
}
sprintf (text, "%s", players[i].name);
font_draw (80, y, text, 0, 4);
}
// calc percentage, this a range from 0 to 255)
switch(players[i].net.net_istep){
case 3:
sprintf (text, "Getting Tunnel Data %d.", players[i].net.net_status);
b=(players[i].net.net_status+1)*255/s;
break;
case 2:
sprintf (text, "Getting Field Data %d of %d.", players[i].net.net_status,
map.size.y);
b=(players[i].net.net_status+1+GAME_MAX_TUNNELS)*255/s;
break;
case 1:
sprintf (text, "Getting Player Data %d of %d.", players[i].net.net_status,
MAX_PLAYERS);
b=(players[i].net.net_status+1+GAME_MAX_TUNNELS+map.size.y)*255/s;
break;
default:
sprintf (text, "Ready");
b=255;
break;
}
//draw bar
if (b>0) {
b1=b*z/255;
dest.x = zx+4;
dest.y = y+4;
dest.w = menu.buttonimages[2][0]->w;
dest.h = menu.buttonimages[2][0]->h;
gfx_blit (menu.buttonimages[2][0], NULL, gfx.screen, &dest, 10000);
dest.x = zx+4+b1-menu.buttonimages[1][2]->w;
if (dest.x<zx+4) dest.x=zx+4;
dest.w = menu.buttonimages[2][2]->w;
dest.h = menu.buttonimages[2][2]->h;
gfx_blit (menu.buttonimages[2][2], NULL, gfx.screen, &dest, 10000);
if (b1>menu.buttonimages[2][0]->w+menu.buttonimages[2][2]->w) {
dest.w = menu.buttonimages[2][1]->w;
dest.h = menu.buttonimages[2][1]->h;
for(j=menu.buttonimages[2][0]->w;j<b1-menu.buttonimages[2][2]->w;
j+=menu.buttonimages[2][1]->w) {
dest.x=j+zx+4;
gfx_blit (menu.buttonimages[2][1], NULL, gfx.screen, &dest, 10000);
}
}
}
// draw old status in case of debug
if (!players[i].net.net_istep)
font_draw (80, y + 20, text, 0, 4);
else
if (debug) {
redraw_logo (80, y+35, gfx.res.x-80, 15);
font_draw (80, y + 35, text, 0, 4);
}
}
gfx_blitdraw ();
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 (!PS_IS_aiplayer (players[i].state) && players[i].net.addr.host[0] != 0)
send_playerid (&players[i].net.addr, players[pl_nr].name,
players[pl_nr].net.addr.host, players[pl_nr].net.addr.port,
pl_nr, players[pl_nr].gfx_nr, players[pl_nr].net.flags);
}
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 (&players[bman.p_servnr].net.addr, players[pl_nr].name,
players[pl_nr].net.addr.host, players[pl_nr].net.addr.port,
pl_nr, players[pl_nr].gfx_nr, players[pl_nr].net.flags);
}
player_set_gfx (&players[pl_nr], 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_transmit_gamedata ()
{
int done = 0,
keypressed = 0,
x,
y, // network upload status for one step
p,
i,
net_istep; // network init step
SDL_Event event;
Uint8 *keys;
Uint32 downtimestamp = 0;
draw_logo ();
if (GT_MP_PTPM)
font_draw (100, 0, "Waiting for the Clients", 1, 0);
else
font_draw (100, 0, "Downloading Data", 1, 0);
/*
prepare everything for the loop
*/
for (x = 0; x < MAX_PLAYERS; x++) {
players[x].net.timestamp = 0;
players[x].net.net_status = -1;
if ((PS_IS_aiplayer (players[x].state)) || (x==bman.p_servnr))
players[x].net.net_istep = 0;
else
players[x].net.net_istep = 3;
}
y = -1;
if (GT_MP_PTPM)
net_istep = 0;
else
net_istep = 3;
draw_netupdatestate (1);
SDL_Flip (gfx.screen);
downtimestamp = timestamp;
while (!done && (bman.state == GS_update || (GT_MP_PTPS && net_istep != 0))) {
/* the network thing */
network_loop ();
/* if PTPM check if all players are ready */
if (GT_MP_PTPM) {
if (timestamp - downtimestamp > TIME_UPDATEINFO) {
downtimestamp = timestamp;
net_send_updateinfo();
}
for (p = 1, i = 1; p < MAX_PLAYERS; p++)
if (PS_IS_playing (players[p].state) && 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 == 3) {
/*
get tunneldata
*/
if ((y < GAME_MAX_TUNNELS - 1 && y == players[bman.p_nr].net.net_status)
|| y == -1) {
y++;
downtimestamp = timestamp;
send_tunneldata (&players[bman.p_servnr].net.addr, y, -1, -1);
}
else if (y < GAME_MAX_TUNNELS && y != players[bman.p_nr].net.net_status
&& y >= 0 && timestamp - downtimestamp > DOWNLOAD_TIMEOUT) {
/* we have got no tunnel data*/
y--;
}
else if (y == GAME_MAX_TUNNELS - 1 && players[bman.p_nr].net.net_status == y) {
/* we have got all tunnel data */
y = -1;
players[bman.p_nr].net.net_istep = --net_istep;
players[bman.p_nr].net.net_status = -1;
}
}
if (net_istep == 2) {
/*
get field data
*/
if ((y < map.size.y - 1 && y == players[bman.p_nr].net.net_status)
|| y == -1) {
/* send field data req */
y++;
downtimestamp = timestamp;
send_getfield (&players[bman.p_servnr].net.addr, y);
}
else if (y < map.size.y && y != players[bman.p_nr].net.net_status
&& y >= 0 && timestamp - downtimestamp > DOWNLOAD_TIMEOUT) {
/* getdata timed out - we have got no field data */
y--;
}
else if (y == map.size.y - 1 && players[bman.p_nr].net.net_status == y) {
/* we have got all field data */
y = -1;
players[bman.p_nr].net.net_istep = --net_istep;
players[bman.p_nr].net.net_status = -1;
}
}
if (net_istep == 1) {
/*
get player data
*/
if ((y < MAX_PLAYERS - 1 && y == players[bman.p_nr].net.net_status) || y == -1) {
/* send player date req */
y++;
downtimestamp = timestamp;
send_getplayerdata (&players[bman.p_servnr].net.addr, y);
}
if (y < MAX_PLAYERS && y != 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 && players[bman.p_nr].net.net_status == y) {
/* we have got all playerdata */
y = -1;
players[bman.p_nr].net.net_istep = --net_istep;
players[bman.p_nr].net.net_status = -1;
downtimestamp = timestamp;
send_playerstatus (&players[bman.p_servnr].net.addr, bman.p_nr, 0, 0);
}
}
if (net_istep == 0 && players[bman.p_nr].net.net_status == -1
&& timestamp - downtimestamp > DOWNLOAD_TIMEOUT) {
/* server did not send informations back */
downtimestamp = timestamp;
send_playerstatus (&players[bman.p_servnr].net.addr, bman.p_nr, 0, 0);
}
}
/* do the grafik work */
draw_netupdatestate (0);
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
&& 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_netplayer (players[p].state) && p != bman.p_nr)
send_playerdata (&players[p].net.addr, p_nr, &players[p_nr]);
}
else if (p_nr == bman.p_nr) {
for (p = 0; p < MAX_PLAYERS; p++)
if (PS_IS_netplayer (players[p].state) && p != bman.p_nr && NET_CANSEND(p))
send_playerdata (&players[p].net.addr, p_nr, &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_aiplayer (players[p].state) && PS_IS_netplayer (players[p].state) && p != bman.p_nr) {
pl = &players[p_nr];
pl->net.pkgopt.send_to--;
if ((pl->net.pkgopt.send_to <= 0 || mustsend) && NET_CANSEND(p))
send_playermove (&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 && players[p].bombs[b].state != BS_ticking && players[p].bombs[b].state != BS_trigger)
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_aiplayer (players[pl].state) && PS_IS_netplayer (players[pl].state) && pl != bman.p_nr && NET_CANSEND(pl))
send_bombdata (&players[pl].net.addr, p, b, &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_aiplayer (players[pl].state) && PS_IS_netplayer (players[pl].state) && pl != bman.p_nr && NET_CANSEND(pl))
send_field (&players[pl].net.addr, x, y, &map.field[x][y]);
};
void
net_delplayer (int pl_nr)
{
char host[LEN_SERVERNAME];
char port[LEN_PORT];
int i;
d_printf ("net_delplayer (%d)\n", pl_nr);
bman.updatestatusbar = 1; // force an update
if (pl_nr == bman.p_nr) {
/* we're not wanted */
network_shutdown ();
bman.state = GS_startup;
}
else {
strncpy (host, players[pl_nr].net.addr.host, LEN_SERVERNAME);
strncpy (port, players[pl_nr].net.addr.port, LEN_PORT);
players[pl_nr].state &= (0xFF - (PSF_used + PSF_net + PSF_alife)); /* delete
player flags */
players[pl_nr].net.net_istep = 0; // needed for disconnect during the update
bman.players_nr_s--;
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_aiplayer (players[i].state) && PS_IS_netplayer (players[i].state))
send_quit (&players[i].net.addr, host, port);
if (bman.notifygamemaster)
send_ogc_update ();
bman.updatestatusbar=1;
}
}
if (GT_MP_PTPS && pl_nr == bman.p_servnr) /* server quit */
bman.state = GS_startup;
if (GT_MP_PTPM && bman.notifygamemaster)
send_ogc_update ();
d_playerdetail (" Player Left ... Playerlist\n");
inpkg_delplayer (pl_nr);
};
void
net_game_fillsockaddr ()
{
/* Update all sockaddr before the game starts */
int i;
for (i = 0; i < MAX_PLAYERS; i++)
if (!PS_IS_aiplayer (players[i].state) && players[i].net.addr.host[0] != 0 && players[i].net.addr.host[0] != 0)
dns_filladdr (players[i].net.addr.host, LEN_SERVERNAME,
players[i].net.addr.port, LEN_PORT, bman.net_ai_family,
&players[i].net.addr.sAddr);
};
void
net_send_servermode ()
{
int i;
for (i = 0; i < MAX_PLAYERS; i++)
if (!PS_IS_aiplayer (players[i].state) && PS_IS_netplayer (players[i].state) && i != bman.p_nr && NET_CANSEND(i))
send_servermode (&players[i].net.addr, i);
if (bman.notifygamemaster && GT_MP_PTPM)
send_ogc_update ();
};
/* 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_aiplayer (players[j].state) && PS_IS_netplayer (players[j].state) && j != bman.p_nr)
for (i = 0; i < MAX_PLAYERS; i++)
send_playerid (&players[j].net.addr, players[i].name,
players[i].net.addr.host, players[i].net.addr.port, i,
players[i].gfx_nr, players[i].net.flags);
};
void
net_send_chat (char *text, signed char notigamesrv)
{
int i;
for (i = 0; i < MAX_PLAYERS; i++)
if ((!PS_IS_aiplayer (players[i].state)) && PS_IS_netplayer (players[i].state) && i != bman.p_nr && NET_CANSEND(i))
send_chat (&players[i].net.addr, 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_aiplayer (players[i].state)) && PS_IS_netplayer (players[i].state) && i != bman.p_nr && NET_CANSEND(i))
send_ill (&players[i].net.addr, p_nr, &players[p_nr]);
};
/* send to all players the drop item list */
void net_game_send_dropitems (int pl_nr, _flyingitem **fiptr, int cnt) {
int i;
d_printf ("net_game_send_dropitems (%d): %d items droppped\n", pl_nr, cnt);
for (i = 0; i < MAX_PLAYERS; i++)
if ((!PS_IS_aiplayer (players[i].state)) && PS_IS_netplayer (players[i].state) && i != bman.p_nr && NET_CANSEND(i))
send_dropitems (&players[i].net.addr, pl_nr, fiptr, cnt);
};
/*
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;
/* set all multiplayer depending datas */
bman.players_nr = 0;
bman.players_nr_s = 0;
for (p = 0; p < MAX_PLAYERS; p++) {
if (PS_IS_used (players[p].state))
bman.players_nr_s++;
else
players[p].state = 0;
}
if (bman.p_nr != -1)
players[bman.p_nr].state &= (0xFF - PSF_net); // we are the local player
bman.last_ex_nr = 1;
};
/* send special use elements into the network,
to make sure nothing bad happens with explosions
we send the ex_nr number too */
void
net_game_send_special (int pl_nr, int ex_nr)
{
int pl;
d_printf ("Send Special Data %d\n", pl_nr);
if (pl_nr < 0 || pl_nr >= MAX_PLAYERS)
return;
for (pl = 0; pl < MAX_PLAYERS; pl++)
if (!PS_IS_aiplayer (players[pl].state) && PS_IS_netplayer (players[pl].state) && pl != pl_nr && NET_CANSEND(pl))
send_special (&players[pl].net.addr, pl_nr, players[pl_nr].special.type, ex_nr);
};
/* Send update informations to all clients */
void
net_send_updateinfo ()
{
int i;
if (GT_MP_PTPS)
return;
d_printf ("Send Updateinfo\n");
for (i = 0; i < MAX_PLAYERS; i++)
if (!PS_IS_aiplayer (players[i].state) && PS_IS_netplayer (players[i].state) && i != bman.p_nr && NET_CANSEND(i))
send_updateinfo (&players[i].net.addr);
};
/* Send mapinformations to all clients */
void
net_send_mapinfo ()
{
int i;
if (GT_MP_PTPS)
return;
d_printf ("Send Mapinfo\n");
for (i = 0; i < MAX_PLAYERS; i++)
if (!PS_IS_aiplayer (players[i].state) && PS_IS_netplayer (players[i].state) && i != bman.p_nr && NET_CANSEND(i))
send_mapinfo (&players[i].net.addr);
};
/* send an update about the game to all clients */
void send_ogc_update () {
int i, j;
char status[10];
if (!bman.notifygamemaster || GT_MP_PTPS)
return;
for (j = 0, i = 0; i < bman.maxplayer; i++)
if (PS_IS_used (players[i].state))
j++;
switch (bman.state) {
case (GS_running):
sprintf (status, "running");
break;
case (GS_ready):
sprintf (status, "ready");
break;
case (GS_wait):
sprintf (status, "wait");
break;
case (GS_update):
sprintf (status, "update");
break;
default:
sprintf (status, "error");
break;
}
ogc_sendgamestatus (bman.sock, "BomberClone", VERSION, bman.gamename, j, bman.maxplayer, status);
};
/* send the respawn data to all clients and with the new position of the player */
void net_game_send_respawn (int pl_nr) {
int pl;
d_printf ("Send Respawn Data %d New Position (%d,%d)\n", pl_nr);
if (pl_nr < 0 || pl_nr >= MAX_PLAYERS)
return;
for (pl = 0; pl < MAX_PLAYERS; pl++)
if (!PS_IS_aiplayer (players[pl].state) && PS_IS_netplayer (players[pl].state) && pl != pl_nr && NET_CANSEND(pl))
send_respawn (&players[pl].net.addr, pl_nr);
};