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