1 /* $Id: network.c,v 1.79 2007-01-12 22:42:31 stpohle Exp $ */
2 /*
3 network routines.
4 */
5
6 #include "bomberclone.h"
7 #include "network.h"
8 #include "chat.h"
9 #include "packets.h"
10 #include "ogcache-client.h"
11 #include "menu.h"
12
13 int
network_server_port(char * server,char * host,int hostlen,char * port,int portlen)14 network_server_port (char *server, char *host, int hostlen, char *port, int portlen)
15 {
16 char *pos,
17 *pos2;
18
19 if (host == NULL)
20 return -1;
21
22 pos2 = pos = strchr (server, ':');
23
24 if (pos != NULL)
25 while (pos2 != NULL) {
26 pos = pos2;
27 pos2 = strchr (pos + 1, ':');
28 }
29
30 if (pos != NULL) {
31 // : f�r Portangabe gefunden
32 if (pos - server < hostlen) {
33 strncpy (host, server, pos - server);
34 host[pos - server] = 0;
35 if (pos[1] == 0)
36 sprintf (port, "11000");
37 else
38 strcpy (port, pos + 1);
39 }
40 else {
41 return -1;
42 }
43 }
44 else {
45 // Portangabe wurde nicht gefunden und wird auf 0 gesetzt
46 strncpy (host, server, hostlen);
47 sprintf (port, "11000");
48 }
49
50 return 0;
51 };
52
53
54 /*
55 try to work better with the network packet option
56 */
57 void
net_dyn_pkgoption()58 net_dyn_pkgoption ()
59 {
60 int p;
61 _net_pkgopt *npkg;
62
63 for (p = 0; p < MAX_PLAYERS; p++)
64 if (PS_IS_netplayer (players[p].state) && !PS_IS_aiplayer (players[p].state)) {
65 npkg = &players[p].net.pkgopt;
66
67 if (npkg->to_2sec > DYN_PKG_MAX_MISSING) {
68 if (npkg->send_set < 10)
69 npkg->send_set++;
70 npkg->to_2sec = 0;
71 npkg->to_timestamp = timestamp;
72 }
73
74 if ((timestamp - npkg->to_timestamp > 2000)
75 && npkg->to_2sec <= DYN_PKG_MIN_MISSING) {
76 if (npkg->send_set > PKG_SENDSETOPT)
77 npkg->send_set--;
78 npkg->to_2sec = 0;
79 npkg->to_timestamp = timestamp;
80 }
81 }
82 };
83
84
85
86
87 /*
88 setup everything for the network loop
89 */
90 int
network_init()91 network_init ()
92 {
93 char host[LEN_SERVERNAME];
94 char port[LEN_PORT];
95
96 /* we need it for the windows winsock */
97 #ifdef _WIN32
98 WSADATA wsaData;
99
100 if (WSAStartup (MAKEWORD (1, 1), &wsaData) != 0) {
101 d_printf ("WSAStartup failed.\n");
102 exit (1);
103 }
104 #endif
105
106 if (bman.net_ai_family == PF_INET)
107 sprintf (host, "IPv4");
108 #ifndef _WIN32
109 else if (bman.net_ai_family == PF_INET6)
110 sprintf (host, "IPv6");
111 #endif
112 else
113 sprintf (host, "IPv (unknown)");
114 d_printf ("Network Init with %s.\n", host);
115
116 bman.sock = -1;
117 timestamp = SDL_GetTicks ();
118
119 // start the udp server
120 bman.sock = udp_server (bman.port, bman.net_ai_family);
121
122 if (bman.sock < 0) {
123 #ifdef _WIN32
124 WSACleanup ();
125 #endif
126 return -1;
127 }
128
129 if (bman.notifygamemaster) {
130 network_server_port (bman.ogcserver, host, LEN_SERVERNAME, port, LEN_PORT);
131 if (ogc_init (bman.ogc_port, host, port, "BomberClone", bman.net_ai_family) == 0)
132 bman.notifygamemaster = 0;
133 }
134
135 // we have got our socket..
136 rscache_init ();
137
138 return 0;
139 };
140
141
142 /*
143 shutdown the network part
144 */
145 void
network_shutdown()146 network_shutdown ()
147 {
148 int i;
149 int new_server = bman.p_servnr;
150 d_printf ("network_shutdown\n");
151
152 if (GT_MP_PTPM) {
153 d_printf ("Server Quit Send information\n");
154
155 /* find new server */
156 for (i = 0; i < MAX_PLAYERS; i++) {
157 if (PS_IS_used (players[i].state) && PS_IS_netplayer (players[i].state)
158 && i != bman.p_servnr && players[i].net.flags == 0)
159 new_server = i;
160 }
161
162 d_printf ("netword_shutdown: new server set to: %d\n", new_server);
163
164 for (i = 0; i < MAX_PLAYERS; i++)
165 if (i != bman.p_servnr && PS_IS_netplayer (players[i].state)
166 && !PS_IS_aiplayer (players[i].state))
167 send_quit (&players[i].net.addr, bman.p_servnr, new_server);
168 }
169 else if (players[bman.p_servnr].net.addr.host[0] != 0) {
170 send_quit (&players[bman.p_servnr].net.addr, bman.p_nr, bman.p_servnr);
171 if (IS_LPLAYER2)
172 send_quit (&players[bman.p_servnr].net.addr, bman.p2_nr, bman.p_servnr);
173 }
174
175 if (bman.notifygamemaster) {
176 ogc_sendgamequit (bman.sock);
177 ogc_shutdown ();
178 }
179
180 udp_close (bman.sock);
181
182 bman.p_nr = -1;
183 bman.sock = -1;
184 #ifdef _WIN32
185 WSACleanup ();
186 #endif
187 };
188
189
190 int
net_check_timeout(int pl_nr)191 net_check_timeout (int pl_nr)
192 {
193 int timeout = UDP_TIMEOUT;
194
195 if ((players[pl_nr].state & (PSF_net + PSF_used + PSF_ai)) == (PSF_used + PSF_net)
196 && ((players[pl_nr].net.flags & NETF_local2) == 0)
197 && timestamp - players[pl_nr].net.timestamp > timeout
198 && players[pl_nr].net.pingreq != players[pl_nr].net.pingack) {
199 d_printf ("net_check_timeout pl_nr=%d, ack=%d, req=%d, timediff=%d\n", pl_nr,
200 players[pl_nr].net.pingack, players[pl_nr].net.pingreq,
201 timestamp - players[pl_nr].net.timestamp);
202 players[pl_nr].net.timestamp = timestamp;
203 players[pl_nr].net.pingack = players[pl_nr].net.pingreq;
204 send_ping (&players[pl_nr].net.addr, players[pl_nr].net.pingack + 100, PKG_pingreq);
205 }
206 if ((players[pl_nr].state & (PSF_net + PSF_used + PSF_ai)) == (PSF_used + PSF_net)
207 && ((players[pl_nr].net.flags & NETF_local2) == 0)
208 && timestamp - players[pl_nr].net.timestamp > timeout
209 && players[pl_nr].net.pingreq == players[pl_nr].net.pingack) {
210 d_printf ("net_check_timeout pl_nr=%d, ack=%d, req=%d, timediff=%d\n", pl_nr,
211 players[pl_nr].net.pingack, players[pl_nr].net.pingreq,
212 timestamp - players[pl_nr].net.timestamp);
213 return 1;
214 }
215 return 0;
216 };
217
218
219
220 /*
221 Read data from the network and work with it
222 */
223 int
network_loop()224 network_loop ()
225 {
226 char data[MAX_UDPDATA];
227 struct pkg *packet = (struct pkg *) data;
228 int inlen,
229 i;
230
231 _net_addr addr;
232
233 if (bman.state != GS_running && bman.state != GS_ready)
234 timestamp = SDL_GetTicks ();
235
236 /*
237 as long as we get any new data, work with them
238 */
239 inlen = udp_get (bman.sock, data, MAX_UDPDATA, &addr.sAddr, bman.net_ai_family);
240 addr.port[0] = addr.host[0] = 0;
241 if (inlen > 0)
242 dns_filladdr (addr.host, LEN_SERVERNAME, addr.port, LEN_PORT, bman.net_ai_family,
243 &addr.sAddr);
244
245 while (inlen > 0) {
246 do_pkg (packet, &addr, inlen);
247
248 // printf ("Network : inlen (%d) typ (%d) Size (%d)\n", inlen, packet->typ, pkglen);
249 inlen = udp_get (bman.sock, data, MAX_UDPDATA, &addr.sAddr, bman.net_ai_family);
250 addr.port[0] = addr.host[0] = 0;
251 if (inlen > 0)
252 dns_filladdr (addr.host, LEN_SERVERNAME, addr.port, LEN_PORT,
253 bman.net_ai_family, &addr.sAddr);
254 }
255
256 /*
257 check here for old connections who aren't answering
258 */
259 if (bman.state == GS_wait || bman.state == GS_ready || bman.state == GS_running) {
260 if (GT_MP_PTPS) {
261 if (net_check_timeout (bman.p_servnr)) {
262 d_printf ("Server Timed Out\n");
263 bman.state = GS_startup;
264 }
265 }
266 else if (GT_MP_PTPM) {
267 for (i = 1; i < MAX_PLAYERS; i++)
268 if (i != bman.p_nr && net_check_timeout (i)) {
269 d_printf ("Player %d Timed Out\n", i);
270 player_delete (i);
271 }
272 }
273 }
274
275 /*
276 resend_cache....
277 */
278 rscache_loop ();
279
280 /*
281 dynamic calibration of the network traffic option
282 */
283 net_dyn_pkgoption ();
284
285 return 0;
286 };
287
288
289 /*
290 this is needed to draw the whole uppdate of everything
291 */
292 void
draw_netupdatestate(char st)293 draw_netupdatestate (char st)
294 {
295 char text[255];
296 unsigned char b;
297 int y = 0,
298 b1,
299 z,
300 zx = 200,
301 i,
302 j,
303 s = map.size.y + MAX_PLAYERS + GAME_MAX_TUNNELS;
304 SDL_Rect src,
305 dest;
306 z = gfx.res.x - zx - 30 - 8;
307 for (i = 0; i < MAX_PLAYERS; i++)
308 if (PS_IS_used (players[i].state)) {
309 y += 50;
310 if (st) {
311 redraw_logo (0, y, gfx.res.x, y + 50);
312
313 if (players[i].gfx_nr != -1) {
314 dest.w = src.w = players[i].gfx->small_image->w;
315 dest.h = src.h = players[i].gfx->small_image->h;
316 src.x = players[i].gfx->small_image->w * down;
317 src.y = 0;
318
319 dest.x = 50;
320 dest.y = y;
321
322 SDL_BlitSurface (players[i].gfx->small_image, &src, gfx.screen, &dest);
323 gfx_blitupdaterectadd (&dest);
324 }
325
326 dest.x = zx;
327 dest.y = y;
328 dest.w = menulistimages[1][0]->w;
329 dest.h = menulistimages[1][0]->h;
330 gfx_blit (menulistimages[1][0], NULL, gfx.screen, &dest, 10000);
331 dest.x = z + zx + 4;
332 gfx_blit (menulistimages[1][2], NULL, gfx.screen, &dest, 10000);
333 // draw the bottom left and right of the list
334 dest.y = y + 29;
335 gfx_blit (menulistimages[1][8], NULL, gfx.screen, &dest, 10000);
336 dest.x = zx;
337 gfx_blit (menulistimages[1][6], NULL, gfx.screen, &dest, 10000);
338 //top & bottom
339 for (j = 4; j < z + 4; j += 4) {
340 dest.x = j + zx;
341 dest.y = y;
342 gfx_blit (menulistimages[1][1], NULL, gfx.screen, &dest, 10000);
343 dest.y = y + 29;
344 gfx_blit (menulistimages[1][7], NULL, gfx.screen, &dest, 10000);
345 }
346 //left &right
347 for (j = 4; j < 29; j += 4) {
348 dest.x = zx;
349 dest.y = y + j;
350 gfx_blit (menulistimages[1][3], NULL, gfx.screen, &dest, 10000);
351 dest.x = z + zx + 4;
352 gfx_blit (menulistimages[1][5], NULL, gfx.screen, &dest, 10000);
353 }
354 sprintf (text, "%s", players[i].name);
355 font_draw (80, y, text, 0, 4);
356 }
357 // calc percentage, this a range from 0 to 255)
358 switch (players[i].net.net_istep) {
359 case 3:
360 sprintf (text, "Getting Tunnel Data %d.", players[i].net.net_status);
361 b = (players[i].net.net_status + 1) * 255 / s;
362 break;
363 case 2:
364 sprintf (text, "Getting Field Data %d of %d.",
365 players[i].net.net_status, map.size.y);
366 b = (players[i].net.net_status + 1 + GAME_MAX_TUNNELS) * 255 / s;
367 break;
368 case 1:
369 sprintf (text, "Getting Player Data %d of %d.",
370 players[i].net.net_status, MAX_PLAYERS);
371 b = (players[i].net.net_status + 1 + GAME_MAX_TUNNELS + map.size.y) * 255 / s;
372 break;
373 default:
374 sprintf (text, "Ready");
375 b = 255;
376 break;
377 }
378
379 //draw bar
380 if (b > 0) {
381 b1 = b * z / 255;
382 dest.x = zx + 4;
383 dest.y = y + 4;
384 dest.w = menubuttonimages[2][0]->w;
385 dest.h = menubuttonimages[2][0]->h;
386 gfx_blit (menubuttonimages[2][0], NULL, gfx.screen, &dest, 10000);
387 dest.x = zx + 4 + b1 - menubuttonimages[1][2]->w;
388 if (dest.x < zx + 4)
389 dest.x = zx + 4;
390 dest.w = menubuttonimages[2][2]->w;
391 dest.h = menubuttonimages[2][2]->h;
392 gfx_blit (menubuttonimages[2][2], NULL, gfx.screen, &dest, 10000);
393 if (b1 > menubuttonimages[2][0]->w + menubuttonimages[2][2]->w) {
394 dest.w = menubuttonimages[2][1]->w;
395 dest.h = menubuttonimages[2][1]->h;
396 for (j = menubuttonimages[2][0]->w;
397 j < b1 - menubuttonimages[2][2]->w; j += menubuttonimages[2][1]->w) {
398 dest.x = j + zx + 4;
399 gfx_blit (menubuttonimages[2][1], NULL, gfx.screen, &dest, 10000);
400 }
401 }
402 }
403 // draw old status in case of debug
404 if (!players[i].net.net_istep)
405 font_draw (80, y + 20, text, 0, 4);
406 else if (debug) {
407 redraw_logo (80, y + 35, gfx.res.x - 80, 15);
408 font_draw (80, y + 35, text, 0, 4);
409 }
410 }
411 gfx_blitdraw ();
412 return;
413 }
414
415 /*
416 used to update settings at startup
417 */
418 void
net_send_playerid(int pl_nr)419 net_send_playerid (int pl_nr)
420 {
421 int i;
422
423 d_printf ("net_send_playerid pl_nr:%d\n", pl_nr);
424
425 if (GT_MP_PTPM) {
426 /*
427 Send to all connected clients the update
428 */
429 for (i = 1; i < MAX_PLAYERS; i++)
430 if (NET_CANSEND (i))
431 send_playerid (&players[i].net.addr, players[pl_nr].name,
432 players[pl_nr].net.addr.host,
433 players[pl_nr].net.addr.port, pl_nr,
434 players[pl_nr].gfx_nr, players[pl_nr].team_nr,
435 players[pl_nr].net.flags);
436 }
437 else {
438 /*
439 Send only to the Server the update and only if pn_nr == bman.p_nr
440 */
441 if (pl_nr == bman.p_nr || (IS_LPLAYER2 && pl_nr == bman.p2_nr))
442 send_playerid (&players[bman.p_servnr].net.addr, players[pl_nr].name,
443 players[pl_nr].net.addr.host, players[pl_nr].net.addr.port,
444 pl_nr, players[pl_nr].gfx_nr, players[pl_nr].team_nr,
445 players[pl_nr].net.flags);
446 }
447
448 if ((players[pl_nr].gfx_nr >= 0 && players[pl_nr].gfx != &gfx.players[players[pl_nr].gfx_nr])
449 || (players[pl_nr].gfx_nr == -1 && players[pl_nr].gfx != NULL))
450 player_set_gfx (&players[pl_nr], players[pl_nr].gfx_nr);
451 };
452
453
454 /*
455 sets up everything for the network game..
456 on servers the game field will be created and the clients will wait for the game data
457 within the network loop
458 */
459 void
net_transmit_gamedata()460 net_transmit_gamedata ()
461 {
462 int done = 0,
463 keypressed = 0,
464 x,
465 y, // network upload status for one step
466 p,
467 i,
468 net_istep; // network init step
469 SDL_Event event;
470 Uint8 *keys;
471 Uint32 downtimestamp = 0;
472
473 draw_logo ();
474
475 if (GT_MP_PTPM)
476 font_draw (100, 0, "Waiting for the Clients", 1, 0);
477 else
478 font_draw (100, 0, "Downloading Data", 1, 0);
479
480 /*
481 prepare everything for the loop
482 */
483 for (x = 0; x < MAX_PLAYERS; x++) {
484 players[x].net.timestamp = 0;
485 players[x].net.net_status = -1;
486 if ((PS_IS_aiplayer (players[x].state)) || (x == bman.p_servnr) || (x == bman.p2_nr)
487 || (players[x].net.flags & NETF_local2) == NETF_local2)
488 players[x].net.net_istep = 0;
489 else
490 players[x].net.net_istep = 3;
491 }
492
493 y = -1;
494 if (GT_MP_PTPM)
495 net_istep = 0;
496 else
497 net_istep = 3;
498
499 draw_netupdatestate (1);
500 SDL_Flip (gfx.screen);
501
502 downtimestamp = timestamp;
503 while (!done && (bman.state == GS_update || (GT_MP_PTPS && net_istep != 0))) {
504 /* the network thing */
505
506 network_loop ();
507
508 /* if PTPM check if all players are ready */
509 if (GT_MP_PTPM) {
510 if (timestamp - downtimestamp > TIME_UPDATEINFO) {
511 downtimestamp = timestamp;
512 net_send_updateinfo ();
513 }
514 for (p = 0, i = 1; p < MAX_PLAYERS; p++)
515 if (PS_IS_playing (players[p].state)
516 && players[p].net.net_istep != 0)
517 i = 0;
518 if (i == 1) { /* all players are ready */
519 done = 1;
520 bman.state = GS_ready;
521 }
522 }
523
524 /* if PTPS get all data */
525 if (GT_MP_PTPS) {
526 if (net_istep == 3) {
527 /*
528 get tunneldata
529 */
530 if ((y < GAME_MAX_TUNNELS - 1 && y == players[bman.p_nr].net.net_status)
531 || y == -1) {
532 y++;
533 downtimestamp = timestamp;
534 send_tunneldata (&players[bman.p_servnr].net.addr, y, -1, -1);
535 }
536 else if (y < GAME_MAX_TUNNELS
537 && y != players[bman.p_nr].net.net_status && y >= 0
538 && timestamp - downtimestamp > DOWNLOAD_TIMEOUT) {
539 /* we have got no tunnel data */
540 y--;
541 }
542 else if (y == GAME_MAX_TUNNELS - 1 && players[bman.p_nr].net.net_status == y) {
543 /* we have got all tunnel data */
544 y = -1;
545 players[bman.p_nr].net.net_istep = --net_istep;
546 players[bman.p_nr].net.net_status = -1;
547 }
548 }
549
550 if (net_istep == 2) {
551 /*
552 get field data
553 */
554 if ((y < map.size.y - 1 && y == players[bman.p_nr].net.net_status)
555 || y == -1) {
556 /* send field data req */
557 y++;
558 downtimestamp = timestamp;
559 send_getfield (&players[bman.p_servnr].net.addr, y);
560 }
561 else if (y < map.size.y && y != players[bman.p_nr].net.net_status
562 && y >= 0 && timestamp - downtimestamp > DOWNLOAD_TIMEOUT) {
563 /* getdata timed out - we have got no field data */
564 y--;
565 }
566 else if (y == map.size.y - 1 && players[bman.p_nr].net.net_status == y) {
567 /* we have got all field data */
568 y = -1;
569 players[bman.p_nr].net.net_istep = --net_istep;
570 players[bman.p_nr].net.net_status = -1;
571 }
572 }
573
574 if (net_istep == 1) {
575 /*
576 get player data
577 */
578 if ((y < MAX_PLAYERS - 1 && y == players[bman.p_nr].net.net_status)
579 || y == -1) {
580 /* send player date req */
581 y++;
582 downtimestamp = timestamp;
583 send_getplayerdata (&players[bman.p_servnr].net.addr, y);
584 }
585 if (y < MAX_PLAYERS && y != players[bman.p_nr].net.net_status
586 && y >= 0 && timestamp - downtimestamp > DOWNLOAD_TIMEOUT) {
587 /* we have got no player data */
588 y--;
589 }
590 if (y == MAX_PLAYERS - 1 && players[bman.p_nr].net.net_status == y) {
591 /* we have got all playerdata */
592 y = -1;
593 players[bman.p_nr].net.net_istep = --net_istep;
594 players[bman.p_nr].net.net_status = -1;
595 downtimestamp = timestamp;
596 send_playerstatus (&players[bman.p_servnr].net.addr, bman.p_nr, 0, 0);
597 }
598 }
599
600 if (net_istep == 0 && players[bman.p_nr].net.net_status == -1
601 && timestamp - downtimestamp > DOWNLOAD_TIMEOUT) {
602 /* server did not send informations back */
603 downtimestamp = timestamp;
604 send_playerstatus (&players[bman.p_servnr].net.addr, bman.p_nr, 0, 0);
605 }
606 }
607
608 /* do the grafik work */
609 draw_netupdatestate (0);
610
611 if (s_fetchevent (&event) != 0)
612 switch (event.type) {
613 case (SDL_QUIT):
614 bman.state = GS_quit;
615 bman.p_nr = -1;
616 done = 1;
617 }
618
619 keys = SDL_GetKeyState (NULL);
620
621 if (keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) {
622 done = 1;
623 bman.p_nr = -1;
624 keypressed = 1;
625 bman.state = GS_startup;
626 }
627
628 if (event.type == SDL_KEYUP)
629 keypressed = 0;
630 }
631
632 timestamp = SDL_GetTicks (); // needed for time sync.
633 SDL_Delay (1); // we don't need here anything better
634
635 /* player is only watching so just go after we have got everything
636 go to show the field */
637 if (GT_MP_PTPS && bman.state == GS_update && net_istep == 0 && players[bman.p_nr].gfx_nr == -1) {
638 done = 1;
639 bman.state = GS_running;
640 }
641 };
642
643
644 /*
645 * send informations about a player too all connected players
646 * last_change: the player will not be send if (send_to_p_nr == bman.p_nr)
647 */
648 void
net_game_send_player(int p_nr)649 net_game_send_player (int p_nr)
650 {
651 int p;
652
653 if (GT_MP_PTPM) {
654 for (p = 0; p < MAX_PLAYERS; p++)
655 if (PS_IS_netplayer (players[p].state) && p != bman.p_nr && p != bman.p2_nr
656 && p != p_nr)
657 send_playerdata (&players[p].net.addr, p_nr, &players[p_nr]);
658 }
659 else if (p_nr == bman.p_nr || p_nr == bman.p2_nr) {
660 for (p = 0; p < MAX_PLAYERS; p++)
661 if (NET_CANSEND (p))
662 send_playerdata (&players[p].net.addr, p_nr, &players[p_nr]);
663 }
664 };
665
666
667 void
net_game_send_playermove(int p_nr,int mustsend)668 net_game_send_playermove (int p_nr, int mustsend)
669 {
670 int p;
671 _player *pl;
672
673 for (p = 0; p < MAX_PLAYERS; p++)
674 if (NET_CANSEND (p)) {
675 pl = &players[p_nr];
676
677 pl->net.pkgopt.send_to--;
678 if ((pl->net.pkgopt.send_to <= 0 || mustsend))
679 send_playermove (&players[p].net.addr, p_nr, pl);
680
681 /* network packet send control */
682 if (pl->net.pkgopt.send_to <= 0 || pl->net.pkgopt.send_to > pl->net.pkgopt.send_set)
683 pl->net.pkgopt.send_to = pl->net.pkgopt.send_set;
684 }
685 };
686
687 void
net_game_send_bomb(int p,int b)688 net_game_send_bomb (int p, int b)
689 {
690 int pl;
691
692 /* check if we are slave and send something else as dropping a bomb */
693 if (GT_MP_PTPS && players[p].bombs[b].state != BS_ticking
694 && players[p].bombs[b].state != BS_trigger)
695 return;
696
697 d_printf ("Send BombData %d, %d\n", p, b);
698
699 if (p < 0 || p >= MAX_PLAYERS || b < 0 || b >= MAX_BOMBS)
700 return;
701
702 for (pl = 0; pl < MAX_PLAYERS; pl++)
703 if (NET_CANSEND (pl))
704 send_bombdata (&players[pl].net.addr, p, b, &players[p].bombs[b]);
705 };
706
707
708 void
net_game_send_field(int x,int y)709 net_game_send_field (int x, int y)
710 {
711 int pl;
712
713 d_printf ("Send FieldData %d, %d\n", x, y);
714
715 if (x < 0 || x >= MAX_FIELDSIZE_X || y < 0 || y >= MAX_FIELDSIZE_Y)
716 return;
717
718 for (pl = 0; pl < MAX_PLAYERS; pl++)
719 if (NET_CANSEND (pl))
720 send_field (&players[pl].net.addr, x, y, &map.field[x][y]);
721 };
722
723
724 /*
725 * send the information about the deleted player to all clients
726 */
727 void
net_game_send_delplayer(int pl_nr)728 net_game_send_delplayer (int pl_nr)
729 {
730 int i;
731 int new_server = bman.p_servnr;
732
733 d_printf ("net_game_send_delplayer (%d)\n", pl_nr);
734
735 if (GT_MP_PTPM && (GS_WAITRUNNING || bman.state == GS_update)) {
736
737 /* find new server, if needed */
738 if (pl_nr == bman.p_servnr) {
739 for (i = 0; i < MAX_PLAYERS; i++) {
740 if (PS_IS_used (players[i].state)
741 && PS_IS_netplayer (players[i].state) && i != bman.p_servnr
742 && players[i].net.flags == 0)
743 new_server = i;
744 }
745 d_printf ("new_game_send_delplayer: new server set to: %d\n", new_server);
746 }
747
748 for (i = 0; i < MAX_PLAYERS; i++)
749 if (NET_CANSEND (i) && i != bman.p_nr)
750 send_quit (&players[i].net.addr, pl_nr, new_server);
751 bman.updatestatusbar = 1;
752 }
753 /* we have to send that one if our own players quit */
754 else if (pl_nr == bman.p_nr || pl_nr == bman.p2_nr) {
755 send_quit (&players[bman.p_servnr].net.addr, pl_nr, -1);
756 }
757
758 inpkg_delplayer (pl_nr);
759
760 if (GT_MP_PTPM) {
761 if (bman.notifygamemaster)
762 send_ogc_update ();
763
764 if (new_server >= 0 && new_server < MAX_PLAYERS)
765 bman.p_servnr = new_server;
766 }
767 };
768
769
770 void
net_game_fillsockaddr()771 net_game_fillsockaddr ()
772 {
773 /* Update all sockaddr before the game starts */
774 int i;
775
776 for (i = 0; i < MAX_PLAYERS; i++)
777 if (!PS_IS_aiplayer (players[i].state) && players[i].net.addr.host[0] != 0
778 && players[i].net.addr.host[0] != 0)
779 dns_filladdr (players[i].net.addr.host, LEN_SERVERNAME,
780 players[i].net.addr.port, LEN_PORT, bman.net_ai_family,
781 &players[i].net.addr.sAddr);
782 };
783
784
785 void
net_send_servermode()786 net_send_servermode ()
787 {
788 int i;
789
790 for (i = 0; i < MAX_PLAYERS; i++)
791 if (NET_CANSEND (i))
792 send_servermode (&players[i].net.addr, i);
793
794 if (bman.notifygamemaster && GT_MP_PTPM)
795 send_ogc_update ();
796 };
797
798
799 /* sends to everyone an up to date playerlist*/
800 void
net_send_players()801 net_send_players ()
802 {
803 int i,
804 j;
805
806 for (j = 0; j < MAX_PLAYERS; j++)
807 if (NET_CANSEND (j))
808 for (i = 0; i < MAX_PLAYERS; i++)
809 send_playerid (&players[j].net.addr, players[i].name,
810 players[i].net.addr.host, players[i].net.addr.port,
811 i, players[i].gfx_nr, players[i].team_nr, players[i].net.flags);
812
813 };
814
815
816
817 /* sends to everyone the teamdata */
818 void
net_send_teamdata(int team_nr)819 net_send_teamdata (int team_nr)
820 {
821 int j;
822
823 if (GT_MP_PTPS)
824 return;
825
826 for (j = 0; j < MAX_PLAYERS; j++)
827 if (NET_CANSEND (j))
828 send_teamdata (&players[j].net.addr, team_nr);
829 };
830
831
832
833 void
net_send_chat(char * text,signed char notigamesrv)834 net_send_chat (char *text, signed char notigamesrv)
835 {
836 int i;
837
838 for (i = 0; i < MAX_PLAYERS; i++)
839 if (NET_CANSEND (i))
840 send_chat (&players[i].net.addr, text);
841 };
842
843
844 void
net_game_send_ill(int p_nr)845 net_game_send_ill (int p_nr)
846 {
847 int i;
848
849 d_printf ("net_game_send_ill (%d)\n", p_nr);
850
851 for (i = 0; i < MAX_PLAYERS; i++)
852 if (NET_CANSEND (i))
853 send_ill (&players[i].net.addr, p_nr, &players[p_nr]);
854 };
855
856
857
858 /* send to all players the drop item list */
859 void
net_game_send_dropitems(int pl_nr,_flyingitem ** fiptr,int cnt)860 net_game_send_dropitems (int pl_nr, _flyingitem ** fiptr, int cnt)
861 {
862 int i;
863
864 d_printf ("net_game_send_dropitems (%d): %d items droppped\n", pl_nr, cnt);
865
866 for (i = 0; i < MAX_PLAYERS; i++)
867 if (NET_CANSEND (i))
868 send_dropitems (&players[i].net.addr, pl_nr, fiptr, cnt);
869 };
870
871
872
873 /*
874 this routine will set up some things for the network game
875 after this the data should be transfered to the other clients.
876 */
net_new_game()877 void net_new_game () {
878 int p;
879
880 /* set all multiplayer depending datas */
881 bman.players_nr = 0;
882 bman.players_nr_s = 0;
883 for (p = 0; p < MAX_PLAYERS; p++) {
884 if (PS_IS_used (players[p].state))
885 bman.players_nr_s++;
886 else
887 players[p].state = 0;
888 }
889
890 if (bman.p_nr != -1)
891 players[bman.p_nr].state &= (0xFF - PSF_net); // we are the local player
892 bman.last_ex_nr = 1;
893 };
894
895
896
897 /* send special use elements into the network,
898 to make sure nothing bad happens with explosions
899 we send the ex_nr number too */
net_game_send_special(int pl_nr,int ex_nr,int type)900 void net_game_send_special (int pl_nr, int ex_nr, int type) {
901 int pl;
902
903 d_printf ("Send Special Data pl_nr:%d ex_nr:%d type:%d\n", pl_nr, ex_nr, type);
904
905 if (pl_nr < 0 || pl_nr >= MAX_PLAYERS)
906 return;
907
908 for (pl = 0; pl < MAX_PLAYERS; pl++)
909 if (NET_CANSEND (pl))
910 send_special (&players[pl].net.addr, pl_nr, type, ex_nr);
911 };
912
913
914 /* Send update informations to all clients */
915 void
net_send_updateinfo()916 net_send_updateinfo ()
917 {
918 int i;
919
920 if (GT_MP_PTPS)
921 return;
922
923 d_printf ("Send Updateinfo\n");
924
925 for (i = 0; i < MAX_PLAYERS; i++)
926 if (NET_CANSEND (i))
927 send_updateinfo (&players[i].net.addr);
928 };
929
930
931 /* Send mapinformations to all clients */
932 void
net_send_mapinfo()933 net_send_mapinfo ()
934 {
935 int i;
936
937 if (GT_MP_PTPS)
938 return;
939
940 d_printf ("Send Mapinfo\n");
941
942 for (i = 0; i < MAX_PLAYERS; i++)
943 if (NET_CANSEND (i))
944 send_mapinfo (&players[i].net.addr);
945 };
946
947
948
949 /* send an update about the game to all clients */
950 void
send_ogc_update()951 send_ogc_update ()
952 {
953 int i,
954 j;
955 char status[10];
956
957 if (!bman.notifygamemaster || GT_MP_PTPS)
958 return;
959
960 for (j = 0, i = 0; i < bman.maxplayer; i++)
961 if (PS_IS_used (players[i].state))
962 j++;
963
964 switch (bman.state) {
965 case (GS_running):
966 sprintf (status, "running");
967 break;
968 case (GS_ready):
969 sprintf (status, "ready");
970 break;
971 case (GS_wait):
972 sprintf (status, "wait");
973 break;
974 case (GS_update):
975 sprintf (status, "update");
976 break;
977 default:
978 sprintf (status, "error");
979 break;
980 }
981 ogc_sendgamestatus (bman.sock, "BomberClone", VERSION, bman.gamename, j, bman.maxplayer,
982 status);
983 };
984
985
986 /* send the respawn data to all clients and with the new position of the player */
987 void
net_game_send_respawn(int pl_nr)988 net_game_send_respawn (int pl_nr)
989 {
990 int pl;
991
992 d_printf ("Send Respawn Data %d New Position (%d,%d)\n", pl_nr);
993
994 if (pl_nr < 0 || pl_nr >= MAX_PLAYERS)
995 return;
996
997 for (pl = 0; pl < MAX_PLAYERS; pl++)
998 if (NET_CANSEND (pl))
999 send_respawn (&players[pl].net.addr, pl_nr);
1000 };
1001