1 /* $id:$ */
2 /* network commands and data */
3
4 #include "basic.h"
5 #include "bomberclone.h"
6 #include "network.h"
7 #include "packets.h"
8 #include "chat.h"
9 #include "sound.h"
10 #include "menu.h"
11
12 extern _point debug_field;
13 extern int debug_lastping;
14
15 static short int pkg_lastid; /* the packet id, this will only counted
16 * up nothing more.. if we are at 0x10000
17 * we will start at 0 */
18
19 struct _resend_cache resend_cache;
20 struct _inpkg_index inpkg_index[PKG_IN_INDEX_NUM];
21 int inpkg_index_pos = 0;
22
23
24 /*
25 * help function to get the playernumber from the address.
26 * this function does not indicate which player it is, this function only checks
27 * if the packet comed from a known player
28 */
get_player_nr(char * host,char * port)29 int get_player_nr (char *host, char *port) {
30 int i,
31 res;
32
33 for (i = 0, res = -1; (i < MAX_PLAYERS && res == -1); i++) {
34 if (players[i].net.addr.host[0] != 0)
35 if ((strcmp (players[i].net.addr.host, host) == 0)
36 && (strcmp (players[i].net.addr.port, port) == 0))
37 res = i;
38 }
39 return res;
40 }
41
42
43 /*
44 * Packettype: error
45 */
send_error(_net_addr * addr,char * text)46 void send_error (_net_addr * addr, char *text) {
47 struct pkg_error p_err;
48
49 d_printf ("Send Network Error : %s\n", text);
50 strncpy (p_err.text, text, 127);
51 p_err.h.typ = PKG_error;
52 p_err.h.flags = 0;
53 p_err.h.len = HTON16 (sizeof (struct pkg_error));
54 p_err.nr = 0;
55
56 send_pkg ((struct pkg *) &p_err, addr);
57 };
58
59
do_error(struct pkg_error * data,_net_addr * addr)60 void do_error (struct pkg_error *data, _net_addr * addr) {
61 d_printf ("Network Error from %s:%s : '%s'\n", addr->host, addr->port, data->text);
62
63 /* check if the packet comes from the server, the server
64 * never gets errormessages from a client, if a client has
65 * some trouble the client will just disconnect */
66 if (GT_MP_PTPS && addr->pl_nr == bman.p_servnr) {
67 menu_displaymessage ("Network Error", "Got Error from: %s:%s\nMessage:%s", addr->host,
68 addr->port, data->text);
69 network_shutdown ();
70 }
71 };
72
73
74
75 /*
76 * Packettype: joingame
77 * client sends this to the server if he want's to join
78 *
79 * 1) check if this package comes from a already joined and known player
80 * if so: just send the current playerlist back.
81 * else:
82 * 2) find free playerslot and add the player there
83 * 3) send to all players the new playerid
84 */
do_joingame(struct pkg_joingame * p_jg,_net_addr * addr)85 void do_joingame (struct pkg_joingame *p_jg, _net_addr * addr) {
86 _player *pl;
87 int i,
88 vma,
89 vmi,
90 vsu;
91 char text[255];
92
93 d_printf ("do_joingame (From:%s:%s Player(name:%s) addr:%p\n", addr->host, addr->port, p_jg->name, addr);
94
95 sscanf (VERSION, "%d.%d.%d", &vma, &vmi, &vsu);
96
97 /* Do some basic checks befor we accept this data packet
98 * 1) check if we are a server */
99 if (GT_MP_PTPS) {
100 sprintf (text, "Sorry this is a client and not a server.");
101 send_error (addr, text);
102 return;
103 }
104 /* 2) check the version */
105 if (p_jg->ver_sub != vsu || p_jg->ver_major != vma || p_jg->ver_minor != vmi) {
106 sprintf (text, "Version Error - Host/Server Version: %s", VERSION);
107 send_error (addr, text);
108 return;
109 }
110
111 /* 3) check if we have a password */
112 d_printf ("Password Check Server:\"%s\" Client:\"%s\" %d, %d\n", bman.password,
113 p_jg->password, strlen (bman.password), strlen (p_jg->password));
114 if (bman.passwordenabled && (strncmp (bman.password, p_jg->password, LEN_PASSWORD)
115 || strlen (bman.password) != strlen (p_jg->password))) {
116 send_error (addr, "This game is Password protected. Your Password is wrong.");
117 return;
118 }
119
120 /* find a free place for the player and add the player to the game */
121 if (GS_WAITRUNNING && GT_MP_PTPM) {
122 int j,
123 freeslot;
124 /* find a free playerslot and check if this player isn't already in the list */
125 for (i = -1, freeslot = -1, j = 0; j < MAX_PLAYERS; j++) {
126 if (!PS_IS_used (players[j].state) && freeslot == -1)
127 freeslot = j;
128 if (strncmp (players[j].net.addr.host, addr->host, LEN_SERVERNAME) == 0
129 && strncmp (players[j].net.addr.port, addr->port, LEN_PORT) == 0
130 && ((p_jg->secondplayer && (players[j].net.flags & NETF_local2) != 0)
131 || (!p_jg->secondplayer && (players[j].net.flags & NETF_local2) == 0)))
132 i = j;
133 }
134
135 if (i == -1)
136 i = freeslot;
137
138 if ((i >= 0) && (i < MAX_PLAYERS) && (i < bman.maxplayer)) {
139 /* free player slot found ... fill in data */
140 pl = &players[i];
141
142 pl->state = PSF_used + PSF_net;
143 if (strncmp (pl->name, p_jg->name, LEN_PLAYERNAME) == 0)
144 d_printf (" Player ReJoined : Nr:[%d] Name:%10s\n", i, p_jg->name);
145 else {
146 d_printf (" Player Added : Nr:[%d] Name:%10s\n", i, p_jg->name);
147 pl->points = 0;
148 pl->wins = 0;
149 pl->nbrKilled = 0;
150 pl->team_nr = -1;
151
152 team_choose (pl);
153 }
154
155 strncpy (pl->name, p_jg->name, LEN_PLAYERNAME);
156
157 pl->gfx_nr = -1;
158 pl->gfx = NULL;
159
160 pl->state &= (0xFF - (PSF_alife + PSF_playing));
161
162 /* Reset the network data */
163 pl->net.timestamp = timestamp;
164 pl->net.pkgopt.to_timestamp = timestamp;
165 pl->net.pkgopt.to_2sec = 0;
166 pl->net.pkgopt.send_to = 0;
167 pl->net.pkgopt.send_set = PKG_SENDSETOPT;
168
169 strncpy (pl->net.addr.host, addr->host, LEN_SERVERNAME);
170 strncpy (pl->net.addr.port, addr->port, LEN_PORT);
171 dns_filladdr (pl->net.addr.host, LEN_SERVERNAME, pl->net.addr.port,
172 LEN_PORT, bman.net_ai_family, &pl->net.addr.sAddr);
173 if (p_jg->secondplayer)
174 pl->net.flags = NETF_local2 + NETF_firewall;
175 else
176 pl->net.flags = NETF_firewall;
177 pl->net.addr.pl_nr = i;
178 bman.players_nr_s++;
179 addr->pl_nr = i;
180
181 /* send to the new client the servermode and the complete playerlist */
182 if ((!p_jg->secondplayer) && !(players[j].net.flags & NETF_local2))
183 send_mapinfo (addr);
184 send_servermode (addr, i); // with this packet the client know it'S pl_nr
185
186 }
187
188 else if (GS_WAITRUNNING) {
189 send_error (addr, "No Free Playerslot found\n");
190 return;
191 }
192
193 else if (!GS_WAITRUNNING) {
194 send_error (addr, "Update mode, please try again.\n");
195 return;
196 }
197 }
198
199 d_playerdetail ("*** PLAYER List ***");
200 bman.updatestatusbar = 1;
201 };
202
203
send_joingame(_net_addr * addr,char * name,int secondplayer)204 void send_joingame (_net_addr * addr, char *name, int secondplayer) {
205 struct pkg_joingame p_jg;
206 int vmi,
207 vma,
208 vsu;
209
210 d_printf ("send_joingame SendTo: %s:%s (Name:%16s)\n", addr->host, addr->port, name);
211
212 sscanf (VERSION, "%d.%d.%d", &vma, &vmi, &vsu);
213
214 p_jg.h.typ = PKG_joingame;
215 p_jg.h.flags = PKGF_ackreq;
216 p_jg.h.len = HTON16 (sizeof (struct pkg_joingame));
217 p_jg.ver_sub = vsu;
218 p_jg.ver_major = vma;
219 p_jg.ver_minor = vmi;
220 p_jg.secondplayer = secondplayer;
221 strncpy (p_jg.name, name, LEN_PLAYERNAME);
222 strncpy (p_jg.password, bman.password, LEN_PASSWORD);
223
224 bman.firewall = 1;
225 send_pkg ((struct pkg *) &p_jg, addr);
226 };
227
228
229
230 /***
231 *** Packettype: contest
232 *** Test the connection from a new player for the firewall flag.
233 *** This packet will be send from one player to the other the
234 *** current server will only get this packet if a connection test was positive
235 ***/
236 void
do_contest(struct pkg_contest * ct_pkg,_net_addr * addr)237 do_contest (struct pkg_contest *ct_pkg, _net_addr * addr)
238 {
239 d_printf ("do_contest (pl_nr = %d) from=%d to=%d\n", addr->pl_nr, ct_pkg->from, ct_pkg->to);
240
241 if (addr->pl_nr >= MAX_PLAYERS
242 || (addr->pl_nr == -1 && PS_IS_netplayer (players[ct_pkg->from].state))) {
243 d_printf (" addr->pl_nr out of range (0-MAX_PLAYERS)\n");
244 return;
245 }
246
247 /* master will have to change the firewall flag on a player */
248 if (GT_MP_PTPM) {
249 if ((ct_pkg->from < 0 || ct_pkg->from >= MAX_PLAYERS
250 || ct_pkg->to < -1 || ct_pkg->to >= MAX_PLAYERS
251 || addr->pl_nr != ct_pkg->from)) {
252 d_printf (" from or to value out of range (0-MAX_PLAYERS)\n");
253 return;
254 }
255 /* ignore packet it's just a workaround for
256 * some hardware router */
257 if (ct_pkg->to == -1) return;
258
259 players[ct_pkg->to].net.flags &= (0xFF - NETF_firewall);
260 net_game_send_player (ct_pkg->to);
261 }
262
263 /* if a client get this packet we send a packet
264 * to the server that we have got this packet. */
265 else {
266 send_contest (&players[bman.p_servnr].net.addr, ct_pkg->from, bman.p_nr, 1);
267 bman.firewall = 0;
268 }
269 }
270
271
272 void
send_contest(_net_addr * addr,int from,int to,int ackreq)273 send_contest (_net_addr * addr, int from, int to, int ackreq)
274 {
275 struct pkg_contest ct_pkg;
276
277 d_printf ("send_contest addr->id:%d, from:%d, to:%d\n", addr->pl_nr, from, to);
278
279 ct_pkg.h.typ = PKG_contest;
280 if (ackreq)
281 ct_pkg.h.flags = PKGF_ackreq;
282 else
283 ct_pkg.h.flags = 0;
284 ct_pkg.h.len = HTON16 (sizeof (struct pkg_contest));
285
286 ct_pkg.from = from;
287 ct_pkg.to = to;
288
289 send_pkg ((struct pkg *) &ct_pkg, addr);
290 }
291
292
293 /***
294 *** Packettype: playerid
295 *** Update Playerinformation, Teampoints of a Player, Points
296 ***
297 ***
298 *** if : the pl_nr == -1 send the whole list to the sender
299 *** else: set the new values for this player
300 ***/
301 void
do_playerid(struct pkg_playerid * p_id,_net_addr * addr)302 do_playerid (struct pkg_playerid *p_id, _net_addr * addr)
303 {
304 _player *pl;
305 int i;
306
307 d_printf
308 ("do_playerid (From:%s:%s pl_nr=%d) Player(name:%s [%s:%s], pl_nr:%d state:%d,%d)\n",
309 addr->host, addr->port, addr->pl_nr, p_id->name, p_id->host, p_id->port, p_id->pl_nr, p_id->state, PS_IS_alife (p_id->state));
310
311 /*
312 * check if we have to send the whole playerlist to a client
313 */
314 if (GT_MP_PTPM && p_id->pl_nr == -1 && addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS) {
315 /* Send all connected players the new PlayerID, except to the new player */
316 pl = &players[addr->pl_nr];
317 for (i = 0; i < MAX_PLAYERS; i++)
318 if (NET_CANSEND (i) && addr->pl_nr != i)
319 send_playerid (&players[i].net.addr, pl->name, pl->net.addr.host,
320 pl->net.addr.port, pl->net.addr.pl_nr, pl->gfx_nr,
321 pl->team_nr, pl->net.flags);
322
323 for (i = 0; i < MAX_PLAYERS; i++)
324 send_playerid (addr, players[i].name, players[i].net.addr.host,
325 players[i].net.addr.port, i, players[i].gfx_nr, players[i].team_nr,
326 players[i].net.flags);
327 }
328
329 /*
330 * check if we have to update someones data
331 */
332 else if ((GT_MP_PTPM && p_id->pl_nr >= 0 && p_id->pl_nr < MAX_PLAYERS &&
333 p_id->pl_nr != bman.p_nr && p_id->pl_nr != bman.p2_nr && bman.state == GS_wait)
334 || (GT_MP_PTPS && p_id->pl_nr >= 0 && p_id->pl_nr < MAX_PLAYERS)) {
335
336 pl = &players[p_id->pl_nr];
337
338 pl->net.timestamp = timestamp;
339 pl->net.pingreq = pl->net.pingack + 5;
340 if (GT_MP_PTPS)
341 pl->net.flags = p_id->netflags;
342 if (p_id->host[0] != 0 && p_id->pl_nr != bman.p_servnr) { // copy addr only if p_id != server
343 pl->net.addr.pl_nr = addr->pl_nr;
344 strncpy (pl->net.addr.host, p_id->host, LEN_SERVERNAME);
345 strncpy (pl->net.addr.port, p_id->port, LEN_PORT);
346 dns_filladdr (pl->net.addr.host, LEN_SERVERNAME,
347 pl->net.addr.port, LEN_PORT, bman.net_ai_family, &pl->net.addr.sAddr);
348 }
349 /* player is used, we need to check if it's the second player from the server
350 * to set it's host and port name */
351 else if (PS_IS_used (p_id->state) && p_id->pl_nr != bman.p_servnr) { // copy addr only if p_id != server
352 strncpy (pl->net.addr.host, players[bman.p_servnr].net.addr.host, LEN_SERVERNAME);
353 strncpy (pl->net.addr.port, players[bman.p_servnr].net.addr.port, LEN_PORT);
354 memcpy (&pl->net.addr.sAddr, &players[bman.p_servnr].net.addr.sAddr,
355 sizeof (struct _sockaddr));
356 }
357
358 /* Check if we have to make a network test.. only client to client
359 * we won't check 2 players too because it won't be possible to send
360 * something to them.
361 *
362 * Check only as long as pl->state is still not a network player */
363 if (GT_MP_PTPS && !(PS_IS_netplayer (pl->state)) && (PS_IS_netplayer (p_id->state))
364 && p_id->pl_nr != bman.p_servnr && p_id->pl_nr != bman.p_nr
365 && !(pl->net.flags & NETF_local2) && p_id->pl_nr != bman.p2_nr) {
366
367 send_contest (&pl->net.addr, bman.p_nr, -1, 0); // send contest without ackreq.
368 /* make sure we still get messages from the server, this is a
369 * work around for some hardware routers */
370 send_contest (&players[bman.p_servnr].net.addr, bman.p_nr, -1, 1);
371 }
372
373 /* to make sure that in games the client won't reborn without a reason */
374 if (bman.state != GS_running || PS_IS_alife (pl->state) == 1)
375 pl->state = p_id->state;
376 else
377 pl->state = p_id->state & (0xFF - PSF_alife);
378
379 /* set the NETWORK flag for the network player.
380 * this had to be done after the contest part. */
381 if (p_id->pl_nr != bman.p_nr && PS_IS_used (pl->state))
382 pl->state |= PSF_net;
383 else
384 pl->state &= (0xff - PSF_net);
385
386 /* make sure we won't end up in an infinite loop, because of a slow network.
387 * only accept the gfx data from other players. Our own we will not overwrite.*/
388 if ((bman.state != GS_wait
389 || (p_id->pl_nr != bman.p_nr && p_id->pl_nr != bman.p2_nr))
390 && pl->gfx_nr != p_id->gfx_nr)
391 player_set_gfx (pl, p_id->gfx_nr);
392 strncpy (pl->name, p_id->name, LEN_PLAYERNAME);
393
394 if (GT_MP_PTPS) {
395 pl->points = NTOH16 (p_id->points);
396 pl->nbrKilled = NTOH16 (p_id->nbrKilled);
397 pl->wins = NTOH16 (p_id->wins);
398 pl->team_nr = p_id->team_nr;
399 if (pl->team_nr >= 0 && pl->team_nr < MAX_TEAMS) {
400 teams[pl->team_nr].points = NTOH16 (p_id->team_points);
401 teams[pl->team_nr].wins = NTOH16 (p_id->team_wins);
402 }
403 }
404
405 /* Send all connected players the new PlayerID */
406 if (GT_MP_PTPM && GS_WAITRUNNING && addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS)
407 net_send_playerid (addr->pl_nr);
408 }
409
410 /*
411 * if we are already in a game don't let the player change the gfx */
412 else if (GT_MP_PTPM && p_id->pl_nr >= 0 && p_id->pl_nr < MAX_PLAYERS &&
413 p_id->pl_nr != bman.p_nr && p_id->pl_nr != bman.p2_nr && bman.state != GS_wait) {
414 /* Send all connected players the new PlayerID */
415 if (GT_MP_PTPM && GS_WAITRUNNING && addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS)
416 net_send_playerid (addr->pl_nr);
417 }
418
419 // d_playerdetail ("*** PLAYER List ***");
420 team_update ();
421 bman.updatestatusbar = 1;
422 };
423
424
425 void
send_playerid(_net_addr * addr,char * name,char * pladdr,char * plport,int pl_nr,int gfx_nr,int team_nr,signed char netflags)426 send_playerid (_net_addr * addr, char *name, char *pladdr, char *plport,
427 int pl_nr, int gfx_nr, int team_nr, signed char netflags)
428 {
429 struct pkg_playerid p_id;
430
431 d_printf ("send_playerid SendTo: %s:%s (Name:%16s p_nr:%d)\n", addr->host,
432 addr->port, name, pl_nr);
433
434 p_id.h.typ = PKG_playerid;
435 p_id.h.flags = PKGF_ackreq;
436 p_id.h.len = HTON16 (sizeof (struct pkg_playerid));
437
438 if (name != NULL)
439 strncpy (p_id.name, name, LEN_PLAYERNAME);
440 else
441 p_id.name[0] = 0;
442
443 if (pladdr == NULL)
444 p_id.host[0] = 0;
445 else
446 strncpy (p_id.host, pladdr, LEN_SERVERNAME);
447
448 if (plport == NULL)
449 p_id.port[0] = 0;
450 else
451 strncpy (p_id.port, plport, LEN_PORT);
452
453 p_id.pl_nr = pl_nr;
454 p_id.netflags = netflags;
455 p_id.gfx_nr = gfx_nr;
456 if (pl_nr != -1) {
457 p_id.points = HTON16 (players[pl_nr].points);
458 p_id.wins = HTON16 (players[pl_nr].wins);
459 p_id.nbrKilled = HTON16 (players[pl_nr].nbrKilled);
460 p_id.state = players[pl_nr].state;
461 p_id.team_nr = team_nr;
462 if (team_nr >= 0 && team_nr < MAX_TEAMS) {
463 p_id.team_points = teams[team_nr].points;
464 p_id.team_wins = teams[team_nr].wins;
465 }
466 }
467 else {
468 p_id.points = 0;
469 p_id.wins = 0;
470 p_id.nbrKilled = 0;
471 p_id.state = 0;
472 p_id.team_nr = -1;
473 p_id.team_points = 0;
474 p_id.team_wins = 0;
475 }
476
477 send_pkg ((struct pkg *) &p_id, addr);
478 };
479
480
481
482 /***
483 *** Packettype: teamdata
484 *** Server Side:
485 *** Send all teamdata to the client.
486 *** Client Side:
487 *** Get all Teamdata
488 ***/
489 void
do_teamdata(struct pkg_teamdata * td,_net_addr * addr)490 do_teamdata (struct pkg_teamdata *td, _net_addr * addr)
491 {
492 int i;
493
494 if (addr->pl_nr == -1)
495 return;
496
497 d_printf ("do_teamdata (addr->pl_nr: %d): team:%d col:%d wins:%d\n", addr->pl_nr, td->team_nr, td->col, td->wins);
498
499 if (addr->pl_nr == bman.p_servnr) { /* packet comes from the server */
500 if (td->team_nr >= 0 && td->team_nr < MAX_TEAMS) {
501 strncpy (teams[td->team_nr].name, td->name, LEN_PLAYERNAME);
502 teams[td->team_nr].col = td->col;
503 teams[td->team_nr].wins = td->wins;
504 bman.updatestatusbar = 1;
505 }
506 }
507 else {
508 if (td->team_nr < 0 || td->team_nr >= MAX_TEAMS) {
509 for (i = 0; i < MAX_TEAMS; i++)
510 send_teamdata (addr, i);
511 }
512 else {
513 send_teamdata (addr, td->team_nr);
514 }
515 }
516 }
517
518
519 void
send_teamdata(_net_addr * addr,int team_nr)520 send_teamdata (_net_addr * addr, int team_nr)
521 {
522 struct pkg_teamdata td;
523
524 d_printf ("send_teamdata (%s:%s) team:%d\n", addr->host, addr->port, team_nr);
525
526 td.h.typ = PKG_teamdata;
527 td.h.flags = PKGF_ackreq;
528 td.h.len = HTON16 (sizeof (struct pkg_teamdata));
529
530 td.team_nr = team_nr;
531 if (team_nr >= 0 && team_nr < MAX_PLAYERS) {
532 strncpy (td.name, teams[team_nr].name, LEN_PLAYERNAME);
533 td.wins = teams[team_nr].wins;
534 td.col = teams[team_nr].col;
535 }
536 else {
537 td.name[0] = 0;
538 td.wins = 0;
539 td.col = 0;
540 }
541 send_pkg ((struct pkg *) &td, addr);
542 }
543
544
545 /***
546 *** Packettype: servermode
547 ***/
548 void
do_servermode(struct pkg_servermode * s_mod,_net_addr * addr)549 do_servermode (struct pkg_servermode *s_mod, _net_addr * addr)
550 {
551 if (addr->pl_nr == -1)
552 return;
553
554 d_printf ("do_servermode (%s:%s) state = %d\n", addr->host, addr->port, s_mod->state);
555
556 /* if we just have connected the bman.p_nr is still -1, so we handle the
557 servermode packet still alittle diffrent */
558 if ((!s_mod->lplayer2 && bman.p_nr == -1) || (s_mod->lplayer2 && bman.p2_nr == -1)) {
559 d_printf (" Server gave us: p_nr/p2_nr: %d(old:%d), p_servnr: %d(old:%d), lplayer2:%d\n", s_mod->p_nr,
560 bman.p_nr, s_mod->p_servnr, bman.p_servnr, s_mod->lplayer2);
561
562 /* set the p_servnr to the playerslot which is the server */
563 if (bman.p_servnr != s_mod->p_servnr) {
564 memcpy (&players[s_mod->p_servnr].net, &players[bman.p_servnr].net,
565 sizeof (_net_player));
566 memset (&players[bman.p_servnr], '\0', sizeof (_net_player));
567 bman.p_servnr = s_mod->p_servnr;
568 }
569
570 /* set now the new p_nr number */
571 if (s_mod->p_nr >= 0 && s_mod->p_nr < MAX_PLAYERS && bman.p_nr == -1
572 && s_mod->lplayer2 == 0) {
573 bman.p_nr = s_mod->p_nr;
574 bman.firewall = 1;
575 players[bman.p_nr].net.flags = NETF_firewall;
576 players[bman.p_nr].state &= (0xFF - PSF_net);
577 strncpy (players[s_mod->p_nr].name, bman.playername, LEN_PLAYERNAME);
578
579 /* send playerid with p_nr -1 so we get the whole playerlist
580 * do the same with the teamdata */
581 send_playerid (addr, NULL, NULL, NULL, -1, -1, -1, 0);
582 send_teamdata (addr, -1);
583 }
584 else if (s_mod->p_nr >= 0 && s_mod->p_nr < MAX_PLAYERS && bman.p2_nr == -1
585 && s_mod->lplayer2 == 1) {
586 bman.p2_nr = s_mod->p_nr;
587 players[bman.p2_nr].net.flags = NETF_firewall + NETF_local2;
588 players[bman.p2_nr].state &= (0xFF - PSF_net);
589 strncpy (players[s_mod->p_nr].name, bman.player2name, LEN_PLAYERNAME);
590 send_playerid (addr, NULL, NULL, NULL, -1, -1, -1, 0);
591 send_teamdata (addr, -1);
592 }
593 }
594
595 /* do the normal update */
596 if (GT_MP_PTPS && addr->pl_nr == bman.p_servnr) {
597 bman.state = s_mod->state;
598 bman.gametype = s_mod->gametype;
599 bman.dropitemsondeath = s_mod->dropitemsondeath;
600 map.state = s_mod->mapstate;
601
602 bman.players_nr_s = s_mod->players;
603 bman.lastwinner = s_mod->last_winner;
604
605 map.size.x = s_mod->fieldsize_x;
606 map.size.y = s_mod->fieldsize_y;
607
608 strncpy (map.tileset, s_mod->tileset, LEN_TILESETNAME);
609 }
610
611 bman.updatestatusbar = 1;
612 };
613
614
615 void
send_servermode(_net_addr * addr,int pl_nr)616 send_servermode (_net_addr * addr, int pl_nr)
617 {
618 struct pkg_servermode s_mod;
619
620 switch (bman.state) {
621 case (GS_startup):
622 d_printf ("Send ServerMode : startup");
623 break;
624 case (GS_ready):
625 d_printf ("Send ServerMode : ready");
626 break;
627 case (GS_running):
628 d_printf ("Send ServerMode : running");
629 break;
630 case (GS_quit):
631 d_printf ("Send ServerMode : quit");
632 break;
633 case (GS_wait):
634 d_printf ("Send ServerMode : wait");
635 break;
636 case (GS_update):
637 d_printf ("Send ServerMode : update");
638 break;
639 default:
640 d_printf ("Send ServerMode : mode %d", bman.state);
641 }
642
643 d_printf ("Addr: %p\n", addr);
644
645 s_mod.h.typ = PKG_servermode;
646 s_mod.h.len = HTON16 (sizeof (struct pkg_servermode));
647 s_mod.h.flags = PKGF_ackreq;
648 s_mod.type = bman.gametype;
649 s_mod.dropitemsondeath = bman.dropitemsondeath;
650 s_mod.mapstate = map.state;
651 if (bman.state == GS_quit) /* do not send GS_quit */
652 s_mod.state = GS_startup;
653 else
654 s_mod.state = bman.state;
655 s_mod.gametype = bman.gametype;
656 s_mod.players = bman.players_nr_s;
657 s_mod.maxplayer = bman.maxplayer;
658 s_mod.p_nr = pl_nr;
659 if (pl_nr >= 0 && pl_nr < MAX_PLAYERS
660 && (players[pl_nr].net.flags & NETF_local2) == NETF_local2)
661 s_mod.lplayer2 = 1;
662 else
663 s_mod.lplayer2 = 0;
664 s_mod.p_servnr = bman.p_servnr;
665 s_mod.last_winner = bman.lastwinner;
666 s_mod.fieldsize_x = map.size.x;
667 s_mod.fieldsize_y = map.size.y;
668 strncpy (s_mod.tileset, map.tileset, LEN_TILESETNAME);
669 send_pkg ((struct pkg *) &s_mod, addr);
670 };
671
672
673
674 /***
675 *** Packettype: field
676 ***/
677 void
send_field(_net_addr * addr,int x,int y,_field * field)678 send_field (_net_addr * addr, int x, int y, _field * field)
679 {
680 struct pkg_field f_dat;
681 int i;
682
683 d_printf ("send_field [%d,%d]\n", x, y);
684
685 f_dat.h.typ = PKG_field;
686 f_dat.h.len = HTON16 (sizeof (struct pkg_field));
687 f_dat.h.flags = PKGF_ackreq;
688
689 f_dat.x = x;
690 f_dat.y = y;
691
692 if (x < 0 || x >= map.size.x || y < 0 || y >= map.size.y)
693 return;
694
695 for (i = 0; i < 4; i++) {
696 f_dat.ex[i].count = map.field[x][y].ex[i].count;
697 f_dat.ex[i].frame = (int) map.field[x][y].ex[i].frame;
698 f_dat.ex[i].bomb_p = map.field[x][y].ex[i].bomb_p;
699 f_dat.ex[i].bomb_b = map.field[x][y].ex[i].bomb_b;
700 }
701 f_dat.type = map.field[x][y].type;
702 f_dat.mixframe = map.field[x][y].mixframe;
703 f_dat.special = map.field[x][y].special;
704 f_dat.frame = HTON16 (FTOI16 (map.field[x][y].frame));
705 f_dat.ex_nr = HTON32 (map.field[x][y].ex_nr);
706
707 send_pkg ((struct pkg *) &f_dat, addr);
708 };
709
710
711 void
do_field(struct pkg_field * f_dat,_net_addr * addr)712 do_field (struct pkg_field *f_dat, _net_addr * addr)
713 {
714 int i;
715
716 if (addr->pl_nr == -1)
717 return;
718
719 if (f_dat->x < map.size.x && f_dat->y < map.size.y) {
720 /* convert the fielddata */
721 map.field[f_dat->x][f_dat->y].type = f_dat->type; // CHECK_BFIELD::: FOR BOMBS:::::
722 map.field[f_dat->x][f_dat->y].mixframe = f_dat->mixframe;
723 map.field[f_dat->x][f_dat->y].special = f_dat->special;
724 for (i = 0; i < 4; i++) { /* set the explosion field data */
725 map.field[f_dat->x][f_dat->y].ex[i].count = f_dat->ex[i].count;
726 map.field[f_dat->x][f_dat->y].ex[i].frame = f_dat->ex[i].frame;
727 map.field[f_dat->x][f_dat->y].ex[i].bomb_p = f_dat->ex[i].bomb_p;
728 map.field[f_dat->x][f_dat->y].ex[i].bomb_b = f_dat->ex[i].bomb_b;
729 }
730 map.field[f_dat->x][f_dat->y].frame = I16TOF (NTOH16 (f_dat->frame));
731 map.field[f_dat->x][f_dat->y].ex_nr = NTOH32 (f_dat->ex_nr);
732 }
733 if (bman.state == GS_running)
734 stonelist_add (f_dat->x, f_dat->y);
735
736 if (NTOH32 (f_dat->ex_nr) > bman.last_ex_nr)
737 bman.last_ex_nr = NTOH32 (f_dat->ex_nr);
738
739 d_printf ("do_field (%d,%d) ex_nr = %d, special = %d, type = %d\n",
740 f_dat->x, f_dat->y, NTOH32 (f_dat->ex_nr), f_dat->special, f_dat->type);
741 };
742
743
744 /***
745 *** Packettype: pingack/pingreq
746 ***/
747 void
do_ping(struct pkg_ping * p_dat,_net_addr * addr)748 do_ping (struct pkg_ping *p_dat, _net_addr * addr)
749 {
750 if (addr->pl_nr == -1)
751 return;
752
753 if (p_dat->h.typ == PKG_pingack)
754 /* ping was an answer */
755 players[addr->pl_nr].net.pingack = NTOH32 (p_dat->data);
756
757 else
758 /* send the answer */
759 send_ping (addr, NTOH32 (p_dat->data), PKG_pingack);
760
761 d_printf ("do_ping pl_nr[%d] (%s:%s) req=%d, ack=%d\n", addr->pl_nr,
762 addr->host, addr->port, players[addr->pl_nr].net.pingreq,
763 players[addr->pl_nr].net.pingack);
764 };
765
766 void
send_ping(_net_addr * addr,int data,unsigned char typ)767 send_ping (_net_addr * addr, int data, unsigned char typ)
768 {
769 struct pkg_ping p_dat;
770
771 if (addr->pl_nr == -1)
772 return;
773
774 p_dat.h.len = HTON16 (sizeof (struct pkg_ping));
775 p_dat.h.flags = 0;
776
777 if (typ == PKG_pingack) {
778 p_dat.h.typ = typ;
779 p_dat.data = HTON32 (data);
780 send_pkg ((struct pkg *) &p_dat, addr);
781 }
782
783 else if (typ == PKG_pingreq) {
784 p_dat.h.typ = typ;
785 p_dat.data = HTON32 (data);
786 send_pkg ((struct pkg *) &p_dat, addr);
787 }
788
789 d_printf ("send_ping Player[%d] (%s:%s) req=%d, ack=%d\n", addr->pl_nr,
790 addr->host, addr->port, players[addr->pl_nr].net.pingreq,
791 players[addr->pl_nr].net.pingack);
792
793 players[addr->pl_nr].net.timestamp = timestamp; /* we need to set it here, so we can check
794 for the timeout again */
795 };
796
797
798 /***
799 *** Packettype: playerdata
800 ***/
801 void
send_playerdata(_net_addr * addr,int p_nr,_player * pl)802 send_playerdata (_net_addr * addr, int p_nr, _player * pl)
803 {
804 struct pkg_playerdata p_dat;
805
806 p_dat.h.typ = PKG_playerdata;
807 p_dat.h.len = HTON16 (sizeof (struct pkg_playerdata));
808
809 if (bman.state == GS_update)
810 p_dat.h.flags = 0;
811 else
812 p_dat.h.flags = PKGF_ackreq;
813
814 p_dat.pos.x = HTON16 (FTOI16 (pl->pos.x));
815 p_dat.pos.y = HTON16 (FTOI16 (pl->pos.y));
816 p_dat.bombs_n = pl->bombs_n;
817 p_dat.d = pl->d;
818 p_dat.range = pl->range;
819 p_dat.gfx_nr = pl->gfx_nr;
820 p_dat.state = pl->state;
821 p_dat.wins = HTON16 (pl->wins);
822 p_dat.points = HTON16 (pl->points);
823 p_dat.nbrKilled = HTON16 (pl->nbrKilled);
824 p_dat.dead_by = pl->dead_by;
825 p_dat.frame = HTON16 (FTOI16 (pl->frame));
826 p_dat.p_nr = p_nr;
827 p_dat.ready = pl->ready;
828 p_dat.team_nr = pl->team_nr;
829
830 send_pkg ((struct pkg *) &p_dat, addr);
831 };
832
833
834 void
do_playerdata(struct pkg_playerdata * p_dat,_net_addr * addr)835 do_playerdata (struct pkg_playerdata *p_dat, _net_addr * addr)
836 {
837 _player *pl;
838
839 if (addr->pl_nr == -1)
840 return;
841
842 if (p_dat->p_nr < 0 || p_dat->p_nr >= MAX_PLAYERS)
843 return;
844
845 d_printf ("do_playerdata (From: %d) p_nr: %d --> state alife? %d new %d\n", addr->pl_nr, p_dat->p_nr, PS_IS_alife(players[p_dat->p_nr].state) , PS_IS_alife(p_dat->state));
846 bman.updatestatusbar = 1; // force an update
847
848 pl = &players[p_dat->p_nr];
849
850 if (bman.state == GS_running && bman.p_nr != p_dat->p_nr) {
851 pl->points = NTOH16 (p_dat->points);
852 pl->nbrKilled = NTOH16 (p_dat->nbrKilled);
853 pl->dead_by = NTOH16 (p_dat->dead_by);
854 pl->team_nr = p_dat->team_nr;
855 }
856 else if (bman.state != GS_running || bman.p_nr != p_dat->p_nr) {
857 pl->pos.x = I16TOF (NTOH16 (p_dat->pos.x));
858 pl->pos.y = I16TOF (NTOH16 (p_dat->pos.y));
859 pl->dead_by = p_dat->dead_by;
860 pl->nbrKilled = NTOH16 (p_dat->nbrKilled);
861 pl->points = NTOH16 (p_dat->points);
862 pl->d = p_dat->d;
863 pl->bombs_n = p_dat->bombs_n;
864 pl->range = p_dat->range;
865 pl->frame = I16TOF (NTOH16 (p_dat->frame));
866 pl->state = p_dat->state;
867 pl->team_nr = p_dat->team_nr;
868 pl->ready = p_dat->ready;
869 team_update ();
870 }
871
872 if (p_dat->dead_by < 0 || p_dat->dead_by >= MAX_PLAYERS) /* set player state no matter what */
873 pl->state = p_dat->state;
874 else { /* player died in the game */
875 /* check if the player just died */
876 if (PS_IS_alife (pl->state) && PS_IS_dead (p_dat->state)) {
877 /* player just died */
878 player_died (pl, p_dat->dead_by, 1);
879 }
880 pl->state = p_dat->state;
881 }
882
883 /* set the state of the player */
884 if (p_dat->p_nr != bman.p_nr && PS_IS_used (pl->state))
885 pl->state |= PSF_net;
886 else
887 pl->state &= (0xff - PSF_net);
888
889 if (p_dat->gfx_nr == -1)
890 pl->state &= (0xff - PSF_alife);
891
892 if (bman.state == GS_update && PS_IS_used (p_dat->state))
893 bman.players_nr_s++;
894
895 if (players[bman.p_nr].net.net_istep == 1)
896 players[bman.p_nr].net.net_status = p_dat->p_nr;
897
898 player_set_gfx (pl, p_dat->gfx_nr);
899 }
900
901
902 /***
903 *** Packettype: ill
904 ***/
905 void
do_ill(struct pkg_ill * ill,_net_addr * addr)906 do_ill (struct pkg_ill *ill, _net_addr * addr)
907 {
908 int i,
909 old_to;
910
911 if (addr->pl_nr == -1)
912 return;
913
914 d_printf ("do_ill (From: %d) For Player %d\n", addr->pl_nr, ill->pl_nr);
915 if (ill->pl_nr < 0 || ill->pl_nr >= MAX_PLAYERS || ill->pl_nr == bman.p_nr)
916 return;
917
918 for (i = 0; i < PI_max; i++) {
919 old_to = players[ill->pl_nr].ill[i].to;
920 players[ill->pl_nr].ill[i].to = I32TOF (NTOH32 (ill->to[i]));
921 if (players[ill->pl_nr].ill[i].to <= 0.0f && old_to > 0.0f)
922 player_clear_ilness (&players[ill->pl_nr], i);
923 else if (players[ill->pl_nr].ill[i].to > 0.0f && old_to <= 0.0f)
924 player_set_ilness (&players[ill->pl_nr], i, players[ill->pl_nr].ill[i].to);
925 d_printf (" to[%d]:%f dataf:%f datai:%d\n", i, players[ill->pl_nr].ill[i].to,
926 players[ill->pl_nr].ill[i].dataf, players[ill->pl_nr].ill[i].datai);
927 }
928 };
929
930 void
send_ill(_net_addr * addr,int p_nr,_player * pl)931 send_ill (_net_addr * addr, int p_nr, _player * pl)
932 {
933 struct pkg_ill ill;
934 int i;
935
936 ill.h.typ = PKG_ill;
937 ill.h.len = HTON16 (sizeof (struct pkg_ill));
938 ill.h.flags = PKGF_ackreq;
939
940 ill.pl_nr = p_nr;
941 for (i = 0; i < PI_max; i++)
942 ill.to[i] = HTON32 (FTOI32 (pl->ill[i].to));
943
944 send_pkg ((struct pkg *) &ill, addr);
945 };
946
947
948 /***
949 *** Packettype: playermove
950 ***/
951 void
send_playermove(_net_addr * addr,int p_nr,_player * pl)952 send_playermove (_net_addr * addr, int p_nr, _player * pl)
953 {
954 struct pkg_playermove p_dat;
955
956 p_dat.h.typ = PKG_playermove;
957 p_dat.h.len = HTON16 (sizeof (struct pkg_playermove));
958 p_dat.h.flags = 0;
959
960 p_dat.pos.x = HTON16 (FTOI16 (pl->pos.x));
961 p_dat.pos.y = HTON16 (FTOI16 (pl->pos.y));
962 p_dat.m = pl->m;
963 p_dat.d = pl->d;
964 p_dat.p_nr = p_nr;
965 p_dat.speed = HTON16 (FTOI16 (pl->speed));
966 p_dat.tunnelto = HTON16 (FTOI16 (pl->tunnelto));
967
968 send_pkg ((struct pkg *) &p_dat, addr);
969 };
970
971 void
do_playermove(struct pkg_playermove * p_dat,_net_addr * addr)972 do_playermove (struct pkg_playermove *p_dat, _net_addr * addr)
973 {
974 _player *pl;
975
976 if (addr->pl_nr == -1)
977 return;
978
979 if (p_dat->p_nr == -1)
980 return;
981
982 if (addr->pl_nr == -1) // unknown player
983 return;
984
985 /* check if the right player is sending the information */
986 pl = &players[p_dat->p_nr];
987
988 pl->m = p_dat->m;
989 pl->d = p_dat->d;
990 pl->speed = I16TOF (NTOH16 (p_dat->speed));
991 pl->pos.x = I16TOF (NTOH16 (p_dat->pos.x));
992 pl->pos.y = I16TOF (NTOH16 (p_dat->pos.y));
993 pl->tunnelto = I16TOF (NTOH16 (p_dat->tunnelto));
994 }
995
996
997 /***
998 *** Packettype: bombdata
999 ***/
do_bombdata(struct pkg_bombdata * b_dat,_net_addr * addr)1000 void do_bombdata (struct pkg_bombdata *b_dat, _net_addr * addr) {
1001 _bomb *bomb;
1002
1003 if (addr->pl_nr == -1)
1004 return;
1005
1006 if (b_dat->p_nr >= MAX_PLAYERS || b_dat->b_nr >= MAX_BOMBS) {
1007 d_printf ("Bomb Error\n");
1008 return;
1009 }
1010
1011 if (b_dat->state == BS_off)
1012 return; // if there was a bomb let it explose don't delete the bomb
1013
1014 d_printf ("do_bombdata [%f,%f] Player: %d PlayerIgnition: %d Bomb: %d, ex_nr:%d\n",
1015 I16TOF (NTOH16 (b_dat->x)), I16TOF (NTOH16 (b_dat->y)), b_dat->p_nr, b_dat->pi_nr, b_dat->b_nr, NTOH32 (b_dat->ex_nr));
1016
1017 bomb = &players[b_dat->p_nr].bombs[b_dat->b_nr];
1018 if (bomb->state == BS_exploding) {
1019 d_printf ("do_bombdata ---> bomb is already exploding\n");
1020 return;
1021 }
1022 // Update player ignition
1023 bomb->id.pIgnition = b_dat->pi_nr;
1024 if ((bomb->pos.x != NTOH16 (b_dat->x) || bomb->pos.y != NTOH16 (b_dat->y))
1025 && bomb->state == BS_exploding && b_dat->state != BS_exploding)
1026 d_printf ("do_bombdata WARNING : bomb explosion haven't finished\n");
1027
1028 if (bomb->state != BS_off) { // handle push & kick special
1029 map.bfield[(int) bomb->pos.x][(int) bomb->pos.y] = 0; //remove bomb at old location
1030 stonelist_add (bomb->pos.x, bomb->pos.y);
1031 stonelist_add (bomb->pos.x + 1, bomb->pos.y);
1032 stonelist_add (bomb->pos.x, bomb->pos.y + 1);
1033 stonelist_add (bomb->pos.x + 1, bomb->pos.y + 1);
1034 }
1035
1036 if (bomb->state == BS_off && (b_dat->state == BS_ticking || b_dat->state == BS_trigger))
1037 snd_play (SND_bombdrop);
1038
1039 /* convert position back to float */
1040 bomb->pos.x = I16TOF (NTOH16 (b_dat->x));
1041 bomb->pos.y = I16TOF (NTOH16 (b_dat->y));
1042
1043 if (bomb->state != b_dat->state && bomb->state != BS_ticking)
1044 bomb->to = I32TOF (NTOH32 (b_dat->to)); /* only set if the bomb isn't already ticking
1045 to make sure the timeout won't be resetted
1046 by an old network packet */
1047
1048 map.bfield[(int) bomb->pos.x][(int) bomb->pos.y] = 1; // keep the bfield up to date
1049
1050 bomb->r = b_dat->r;
1051 bomb->ex_nr = NTOH32 (b_dat->ex_nr);
1052 bomb->state = b_dat->state & 0x0F;
1053
1054 if (bomb->mode != b_dat->state >> 4) { // bombmode changed set source to current position
1055 bomb->source.x = bomb->pos.x;
1056 bomb->source.y = bomb->pos.y;
1057 }
1058 bomb->mode = b_dat->state >> 4;
1059 bomb->fdata = I16TOF (NTOH16 (b_dat->fdata));
1060 bomb->dest.x = I16TOF (NTOH16 (b_dat->destx));
1061 bomb->dest.y = I16TOF (NTOH16 (b_dat->desty));
1062
1063 if (bomb->state == BS_exploding)
1064 bomb_explode (bomb, 0);
1065
1066 if (bomb->ex_nr > bman.last_ex_nr)
1067 bman.last_ex_nr = bomb->ex_nr;
1068 };
1069
1070 void
send_bombdata(_net_addr * addr,int p,int b,_bomb * bomb)1071 send_bombdata (_net_addr * addr, int p, int b, _bomb * bomb)
1072 {
1073 struct pkg_bombdata b_dat;
1074
1075 b_dat.h.typ = PKG_bombdata;
1076 b_dat.h.len = HTON16 (sizeof (struct pkg_bombdata));
1077 b_dat.x = HTON16 (FTOI16 (bomb->pos.x));
1078 b_dat.y = HTON16 (FTOI16 (bomb->pos.y));
1079 b_dat.to = HTON32 (FTOI32 (bomb->to));
1080 b_dat.r = bomb->r;
1081 b_dat.ex_nr = HTON32 (bomb->ex_nr);
1082 b_dat.state = (bomb->mode << 4) | (bomb->state);
1083 b_dat.b_nr = b;
1084 b_dat.p_nr = p;
1085 b_dat.pi_nr = bomb->id.pIgnition;
1086 b_dat.h.flags = PKGF_ackreq;
1087 b_dat.fdata = HTON16 (FTOI16 (bomb->fdata));
1088 b_dat.destx = HTON16 (FTOI16 (bomb->dest.x));
1089 b_dat.desty = HTON16 (FTOI16 (bomb->dest.y));
1090
1091 send_pkg ((struct pkg *) &b_dat, addr);
1092 };
1093
1094
1095 /***
1096 *** Packettype: bombdata
1097 *** recive a request for some tunneldata or receive tunneldata
1098 ***/
1099 void
do_tunneldata(struct pkg_tunneldata * tun_pkg,_net_addr * addr)1100 do_tunneldata (struct pkg_tunneldata *tun_pkg, _net_addr * addr)
1101 {
1102 d_printf ("do_tunneldata: From %d [%s:%s] (Tunnel %d Target [%d,%d])\n",
1103 addr->pl_nr, addr->host, addr->port, tun_pkg->tunnel_nr,
1104 NTOH16 (tun_pkg->target.x), NTOH16 (tun_pkg->target.y));
1105
1106 if (addr->pl_nr != bman.p_servnr && GT_MP_PTPM && NTOH16 (tun_pkg->target.y) == -1
1107 && NTOH16 (tun_pkg->target.x) == -1) {
1108 send_tunneldata (addr, tun_pkg->tunnel_nr,
1109 map.tunnel[tun_pkg->tunnel_nr].x, map.tunnel[tun_pkg->tunnel_nr].y);
1110 players[addr->pl_nr].net.net_status = tun_pkg->tunnel_nr;
1111 players[addr->pl_nr].net.net_istep = 3;
1112 }
1113 else if (addr->pl_nr == bman.p_servnr && tun_pkg->tunnel_nr < GAME_MAX_TUNNELS) {
1114 map.tunnel[tun_pkg->tunnel_nr].x = NTOH16 (tun_pkg->target.x);
1115 map.tunnel[tun_pkg->tunnel_nr].y = NTOH16 (tun_pkg->target.y);
1116 players[bman.p_nr].net.net_status = tun_pkg->tunnel_nr;
1117 }
1118 };
1119
1120 /* send a tunneldata request (x && y == -1) or send tunneldata */
1121 void
send_tunneldata(_net_addr * addr,int tunnelnr,int x,int y)1122 send_tunneldata (_net_addr * addr, int tunnelnr, int x, int y)
1123 {
1124 struct pkg_tunneldata tun_pkg;
1125
1126 d_printf ("send_tunneldata (Tunnel %d Target [%d,%d])\n", tunnelnr, x, y);
1127
1128 tun_pkg.h.typ = PKG_tunneldata;
1129 tun_pkg.h.flags = PKGF_ackreq;
1130 tun_pkg.h.len = HTON16 (sizeof (struct pkg_tunneldata));
1131
1132 if (GT_MP_PTPM || (GT_MP_PTPS && x == -1 && y == -1)) {
1133 tun_pkg.tunnel_nr = tunnelnr;
1134 tun_pkg.target.x = HTON16 (x);
1135 tun_pkg.target.y = HTON16 (y);
1136
1137 send_pkg ((struct pkg *) &tun_pkg, addr);
1138 }
1139 };
1140
1141
1142 /***
1143 *** Packettype: quit
1144 ***/
1145 void
send_quit(_net_addr * addr,int pl_nr,int new_server)1146 send_quit (_net_addr * addr, int pl_nr, int new_server)
1147 {
1148 struct pkg_quit q_dat;
1149
1150 d_printf ("send_quit (%s:%s) pl_nr: %d\n", addr->host, addr->port, pl_nr);
1151
1152 q_dat.h.typ = PKG_quit;
1153 q_dat.h.flags = 0;
1154 q_dat.h.len = HTON16 (sizeof (struct pkg_quit));
1155 if (pl_nr == -1)
1156 q_dat.pl_nr = bman.p_nr;
1157 else
1158 q_dat.pl_nr = pl_nr;
1159 q_dat.new_server = new_server;
1160 send_pkg ((struct pkg *) &q_dat, addr);
1161 };
1162
1163
1164 void
do_quit(struct pkg_quit * q_dat,_net_addr * addr)1165 do_quit (struct pkg_quit *q_dat, _net_addr * addr)
1166 {
1167 d_printf ("do_quit (%s:%s) pl_nr=%d new_server=%d\n", addr->host, addr->port, q_dat->pl_nr,
1168 q_dat->new_server);
1169
1170 if (addr->pl_nr == -1)
1171 return;
1172
1173 if (q_dat->pl_nr == -1)
1174 q_dat->pl_nr = addr->pl_nr;
1175
1176 bman.updatestatusbar = 1;
1177 player_delete (q_dat->pl_nr);
1178
1179 /* the player who send this quit */
1180 if (q_dat->pl_nr == bman.p_servnr && q_dat->new_server != bman.p_servnr) {
1181 d_printf ("do_quit: new server is set to: %d\n", q_dat->new_server);
1182 bman.p_servnr = q_dat->new_server;
1183
1184 if (GT_MP_PTPM && bman.notifygamemaster) {
1185 /* if there are any AI players delete the network flag from them */
1186 int i;
1187
1188 for (i = 0; i < MAX_PLAYERS; i++)
1189 if (PS_IS_aiplayer (players[i].state))
1190 players[i].state &= (0xFF - PSF_net);
1191
1192 send_ogc_update ();
1193 }
1194 }
1195 else if (q_dat->pl_nr == bman.p_servnr && q_dat->new_server == bman.p_servnr)
1196 menu_displaymessage ("Server Quit",
1197 "The game closed because you are the only one who is left."
1198 " Or the server could not find any other possible new server.");
1199 };
1200
1201
1202 /***
1203 *** Packettype: getfield
1204 ***/
1205 void
send_getfield(_net_addr * addr,int line)1206 send_getfield (_net_addr * addr, int line)
1207 {
1208 struct pkg_getfield gf_dat;
1209
1210 gf_dat.h.typ = PKG_getfield;
1211 gf_dat.h.len = HTON16 (sizeof (struct pkg_getfield));
1212 gf_dat.h.flags = 0;
1213 gf_dat.line = line;
1214 send_pkg ((struct pkg *) &gf_dat, addr);
1215 };
1216
1217
1218 void
do_getfield(struct pkg_getfield * gf_dat,_net_addr * addr)1219 do_getfield (struct pkg_getfield *gf_dat, _net_addr * addr)
1220 {
1221 if (addr->pl_nr == -1)
1222 return;
1223
1224 if (gf_dat->line < 0 || gf_dat->line >= MAX_FIELDSIZE_Y)
1225 return;
1226
1227 if (addr->pl_nr != -1 && bman.state == GS_update && GT_MP_PTPM) {
1228 if (addr->pl_nr != bman.p_servnr && addr->pl_nr < MAX_PLAYERS) {
1229 players[addr->pl_nr].net.net_status = gf_dat->line;
1230 players[addr->pl_nr].net.net_istep = 2;
1231 }
1232 }
1233 send_fieldline (addr, gf_dat->line);
1234 };
1235
1236
1237 /***
1238 *** Packettype: fieldline
1239 ***/
1240 void
send_fieldline(_net_addr * addr,int line)1241 send_fieldline (_net_addr * addr, int line)
1242 {
1243 int i,
1244 j;
1245 struct pkg_fieldline f_dat;
1246
1247 f_dat.h.typ = PKG_fieldline;
1248 f_dat.h.len = HTON16 (sizeof (struct pkg_fieldline));
1249 f_dat.h.flags = 0;
1250 f_dat.line = line;
1251
1252 if (line < 0 || line >= MAX_FIELDSIZE_Y)
1253 return;
1254
1255 for (i = 0; i < MAX_FIELDSIZE_X; i++) {
1256 f_dat.type[i] = map.field[i][line].type;
1257 f_dat.special[i] = map.field[i][line].special;
1258 map.field[i][line].frame = 0.0f;
1259 map.field[i][line].ex_nr = 0;
1260 for (j = 0; j < 4; j++) {
1261 map.field[i][line].ex[j].frame = 0.0f;
1262 map.field[i][line].ex[j].count = 0;
1263 }
1264 }
1265 send_pkg ((struct pkg *) &f_dat, addr);
1266 };
1267
1268
1269 void
do_fieldline(struct pkg_fieldline * f_dat,_net_addr * addr)1270 do_fieldline (struct pkg_fieldline *f_dat, _net_addr * addr)
1271 {
1272 int i,
1273 d;
1274
1275 if (addr->pl_nr == -1)
1276 return;
1277
1278 if (addr->pl_nr != bman.p_servnr) {
1279 /* the data we have got are not from the server */
1280 d_printf ("do_fieldline: the data we have got are not from the server\n");
1281 return;
1282 }
1283 if (f_dat->line < 0 || f_dat->line >= MAX_FIELDSIZE_Y) {
1284 /* the line number is wrong */
1285 d_printf ("do_fieldline: the line number is not correct\n");
1286 return;
1287 }
1288
1289 if (players[bman.p_nr].net.net_istep == 2)
1290 players[bman.p_nr].net.net_status = f_dat->line;
1291
1292 for (i = 0; i < MAX_FIELDSIZE_X; i++) {
1293 map.field[i][f_dat->line].type = f_dat->type[i];
1294 map.field[i][f_dat->line].special = f_dat->special[i];
1295 map.field[i][f_dat->line].frame = 0.0f;
1296 for (d = 0; d < 4; d++) {
1297 map.field[i][f_dat->line].ex[d].frame = 0.0f;
1298 map.field[i][f_dat->line].ex[d].count = 0;
1299 }
1300 }
1301 };
1302
1303
1304 /***
1305 *** Packettype: getplayerdata
1306 ***/
1307 void
send_getplayerdata(_net_addr * addr,int pl)1308 send_getplayerdata (_net_addr * addr, int pl)
1309 {
1310 struct pkg_getplayerdata gp_dat;
1311
1312 gp_dat.h.typ = PKG_getplayerdata;
1313 gp_dat.h.len = HTON16 (sizeof (struct pkg_getplayerdata));
1314 gp_dat.pl_nr = pl;
1315 gp_dat.h.flags = 0;
1316 send_pkg ((struct pkg *) &gp_dat, addr);
1317 };
1318
1319
1320 void
do_getplayerdata(struct pkg_getplayerdata * gp_dat,_net_addr * addr)1321 do_getplayerdata (struct pkg_getplayerdata *gp_dat, _net_addr * addr)
1322 {
1323 if (addr->pl_nr == -1)
1324 return;
1325
1326 if (gp_dat->pl_nr < 0 || gp_dat->pl_nr >= MAX_PLAYERS)
1327 return;
1328
1329 if (addr->pl_nr != -1 && bman.state == GS_update && GT_MP_PTPM) {
1330 if (addr->pl_nr != bman.p_servnr && addr->pl_nr < MAX_PLAYERS) {
1331 players[addr->pl_nr].net.net_status = gp_dat->pl_nr;
1332 players[addr->pl_nr].net.net_istep = 1;
1333 }
1334 }
1335 send_playerdata (addr, gp_dat->pl_nr, &players[gp_dat->pl_nr]);
1336 };
1337
1338
1339 /***
1340 *** Packettype: playerstatus
1341 ***/
1342 void
do_playerstatus(struct pkg_playerstatus * stat,_net_addr * addr)1343 do_playerstatus (struct pkg_playerstatus *stat, _net_addr * addr)
1344 {
1345 d_printf ("do_playerstatus (%s,%s)\n", addr->host, addr->port);
1346
1347 if (addr->pl_nr != bman.p_servnr && !(GT_MP_PTPM)) {
1348 /* the data we have got are not from the server */
1349 d_printf ("do_playerstatus: the data we have got are not from the server\n");
1350 return;
1351 }
1352 if (stat->pl_nr < 0 || stat->pl_nr >= MAX_PLAYERS) {
1353 /* the player number is wrong */
1354 d_printf ("do_playerstatus: playernumber not correct\n");
1355 return;
1356 }
1357
1358 players[addr->pl_nr].net.net_status = stat->status;
1359 players[addr->pl_nr].net.net_istep = stat->net_istep;
1360 /*
1361 if (GT_MP_PTPM)
1362 for (i = 0; i < MAX_PLAYERS; i++)
1363 if (players[i].net.addr.host[0] != 0)
1364 send_playerstatus (addr, stat->pl_nr,
1365 stat->net_istep, stat->status);
1366 */
1367 };
1368
1369 void
send_playerstatus(_net_addr * addr,int pl_nr,int net_istep,int status)1370 send_playerstatus (_net_addr * addr, int pl_nr, int net_istep, int status)
1371 {
1372 struct pkg_playerstatus stat;
1373
1374 d_printf ("send_playerstatus (%s,%s) %d, %d, %d\n", addr->host,
1375 addr->port, pl_nr, net_istep, status);
1376
1377 stat.h.typ = PKG_playerstatus;
1378 stat.h.flags = 0;
1379 stat.h.len = HTON16 (sizeof (struct pkg_playerstatus));
1380 stat.pl_nr = pl_nr;
1381 stat.net_istep = net_istep;
1382 stat.status = status;
1383
1384 send_pkg ((struct pkg *) &stat, addr);
1385 };
1386
1387 /***
1388 *** Packettype: updateinfo
1389 ***/
1390 void
do_updateinfo(struct pkg_updateinfo * stat,_net_addr * addr)1391 do_updateinfo (struct pkg_updateinfo *stat, _net_addr * addr)
1392 {
1393 int i;
1394
1395 d_printf ("do_updateinfo (%s,%s)\n", addr->host, addr->port);
1396
1397 if (addr->pl_nr != bman.p_servnr && !(GT_MP_PTPM)) {
1398 /* the data we have got are not from the server */
1399 d_printf ("do_updateinfo: the data we have got are not from the server\n");
1400 return;
1401 }
1402 for (i = 0; i < MAX_PLAYERS; i++)
1403 if ((i != bman.p_servnr) && (i != bman.p_nr)) {
1404 players[i].net.net_status = stat->status[i];
1405 players[i].net.net_istep = stat->step[i];
1406 }
1407 };
1408
1409 void
send_updateinfo(_net_addr * addr)1410 send_updateinfo (_net_addr * addr)
1411 {
1412 struct pkg_updateinfo stat;
1413 int i;
1414 stat.h.typ = PKG_updateinfo;
1415 stat.h.flags = 0;
1416 stat.h.len = HTON16 (sizeof (struct pkg_updateinfo));
1417 for (i = 0; i < MAX_PLAYERS; i++) {
1418 stat.step[i] = players[i].net.net_istep;
1419 stat.status[i] = players[i].net.net_status;
1420 }
1421 send_pkg ((struct pkg *) &stat, addr);
1422 };
1423
1424
1425 /***
1426 *** Packettype: chat
1427 ***/
1428 void
do_chat(struct pkg_chat * chat_pkg,_net_addr * addr)1429 do_chat (struct pkg_chat *chat_pkg, _net_addr * addr)
1430 {
1431 d_printf ("do_chat (%s:%s) %d Text:%s\n", addr->host, addr->port, addr->pl_nr, chat_pkg->text);
1432
1433 chat_addline (chat_pkg->text, -1);
1434 };
1435
1436
1437 void
send_chat(_net_addr * addr,char * text)1438 send_chat (_net_addr * addr, char *text)
1439 {
1440 struct pkg_chat chat_pkg;
1441 int i;
1442
1443 chat_pkg.h.typ = PKG_chat;
1444 chat_pkg.h.flags = 0;
1445 chat_pkg.h.len = HTON16 (sizeof (struct pkg_chat));
1446
1447 for (i = 0; i < sizeof (chat_pkg.text); i++)
1448 chat_pkg.text[i] = 0;
1449 strncpy (chat_pkg.text, text, sizeof (struct pkg_chat) - sizeof (struct pkg));
1450
1451 send_pkg ((struct pkg *) &chat_pkg, addr);
1452 };
1453
1454
1455 /***
1456 *** Packettype: pkgack
1457 ***/
1458 void
send_pkgack(_net_addr * addr,unsigned char typ,short int id)1459 send_pkgack (_net_addr * addr, unsigned char typ, short int id)
1460 {
1461 struct pkg_pkgack p_ack;
1462
1463 p_ack.h.typ = PKG_pkgack;
1464 p_ack.h.flags = 0;
1465 p_ack.h.len = HTON16 (sizeof (struct pkg_pkgack));
1466 p_ack.id = HTON16 (id);
1467 p_ack.typ = typ;
1468
1469 send_pkg ((struct pkg *) &p_ack, addr);
1470 };
1471
1472
1473 void
do_pkgack(struct pkg_pkgack * p_ack,_net_addr * addr)1474 do_pkgack (struct pkg_pkgack *p_ack, _net_addr * addr)
1475 {
1476 d_printf ("do_pkgack pl_nr:%d type:%u id:%u\n", addr->pl_nr, p_ack->typ, p_ack->id);
1477 if ( ! rscache_del (addr, p_ack->typ, NTOH16 (p_ack->id)))
1478 d_printf ("do_pkgack ERROR rscache_del data not found : pl_nr:%d type:%u id:%u\n", addr->pl_nr, p_ack->typ, p_ack->id);
1479 };
1480
1481
1482 /***
1483 *** Packettype: dropitems
1484 *** send a generated list of drop items
1485 ***/
1486 void
send_dropitems(_net_addr * addr,int pl_nr,_flyingitem ** fitems,int cnt)1487 send_dropitems (_net_addr * addr, int pl_nr, _flyingitem ** fitems, int cnt)
1488 {
1489 char outdata[BUF_SIZE]; // this should be enough memory for the outgoin data
1490 struct pkg_dropitem *dipkg = (struct pkg_dropitem *) outdata; // set the pointer to outdata
1491 int i;
1492
1493 dipkg->h.typ = PKG_dropitem;
1494 dipkg->h.len = HTON16 (sizeof (struct pkg_dropitem) + cnt * sizeof (struct pkgdropitemelemt));
1495 dipkg->h.flags = PKGF_ackreq;
1496 dipkg->pl_nr = pl_nr;
1497 dipkg->from.x = HTON16 (FTOI16 (players[pl_nr].pos.x));
1498 dipkg->from.y = HTON16 (FTOI16 (players[pl_nr].pos.y));
1499 dipkg->count = cnt;
1500
1501 for (i = 0; (i < cnt && fitems[i] != NULL); i++) {
1502 dipkg->items[i].x = (int) fitems[i]->to.x;
1503 dipkg->items[i].y = (int) fitems[i]->to.y;
1504 dipkg->items[i].typ = (int) fitems[i]->type;
1505 }
1506
1507 send_pkg ((struct pkg *) dipkg, addr);
1508 };
1509
1510
1511 void
do_dropitems(struct pkg_dropitem * di_pkg,_net_addr * addr)1512 do_dropitems (struct pkg_dropitem *di_pkg, _net_addr * addr)
1513 {
1514 int i;
1515 _pointf from;
1516 _point to;
1517
1518 d_printf ("do_dropitems from:%d (pl_nr %d, cnt %d)\n", addr->pl_nr, di_pkg->pl_nr,
1519 di_pkg->count);
1520 if (addr->pl_nr == -1)
1521 return;
1522 from.x = I16TOF (NTOH16 (di_pkg->from.x));
1523 from.y = I16TOF (NTOH16 (di_pkg->from.y));
1524
1525 for (i = 0; i < di_pkg->count; i++) {
1526 to.x = di_pkg->items[i].x;
1527 to.y = di_pkg->items[i].y;
1528 flitems_additem (from, to, di_pkg->items[i].typ);
1529 }
1530 };
1531
1532
1533
1534 /***
1535 *** Packettype: special
1536 *** moves/bombs... whatever will be send as we use it
1537 ***/
do_special(struct pkg_special * sp_pkg,_net_addr * addr)1538 void do_special (struct pkg_special *sp_pkg, _net_addr * addr) {
1539 d_printf ("do_special (addr %d, pl_nr %d, typ %d)\n", addr->pl_nr, sp_pkg->pl_nr, sp_pkg->typ);
1540 if (addr->pl_nr == -1 || sp_pkg->pl_nr == -1 || sp_pkg->pl_nr == bman.p_nr
1541 || sp_pkg->pl_nr == bman.p2_nr)
1542 return;
1543
1544 /* set or use special */
1545 if (sp_pkg->typ < SP_max) {
1546 players[sp_pkg->pl_nr].special.type = sp_pkg->typ;
1547 bman.last_ex_nr = NTOH32 (sp_pkg->ex_nr);
1548 special_use (sp_pkg->pl_nr);
1549 }
1550
1551 /* clear special */
1552 else if (sp_pkg->typ == SP_clear)
1553 players[sp_pkg->pl_nr].special.clear = 1;
1554 };
1555
1556
1557 void
send_special(_net_addr * addr,int p_nr,int typ,int ex_nr)1558 send_special (_net_addr * addr, int p_nr, int typ, int ex_nr)
1559 {
1560 struct pkg_special sp_dat;
1561
1562 sp_dat.h.typ = PKG_special;
1563 sp_dat.h.len = HTON16 (sizeof (struct pkg_special));
1564 sp_dat.h.flags = PKGF_ackreq;
1565 sp_dat.pl_nr = p_nr;
1566 sp_dat.typ = typ;
1567 sp_dat.ex_nr = HTON32 (ex_nr);
1568 send_pkg ((struct pkg *) &sp_dat, addr);
1569 };
1570
1571
1572 /***
1573 *** Packettype: mapinfo
1574 ***/
1575 void
send_mapinfo(_net_addr * addr)1576 send_mapinfo (_net_addr * addr)
1577 {
1578 struct pkg_mapinfo map_pkg;
1579 #ifndef BUG_MAPINFO
1580 _net_addr *test; // VERY DIRTY WORKAROUND WHY IS HERE A BUG
1581 #endif
1582 map_pkg.h.typ = PKG_mapinfo;
1583 map_pkg.h.len = HTON16 (sizeof (struct pkg_mapinfo));
1584 map_pkg.h.flags = PKGF_ackreq;
1585 map_pkg.size_x = map.size.x;
1586 map_pkg.size_y = map.size.y;
1587 map_pkg.bombs = map.bombs;
1588 map_pkg.fire = map.fire;
1589 map_pkg.shoes = map.shoes;
1590 map_pkg.mixed = map.mixed;
1591 map_pkg.death = map.death;
1592 map_pkg.sp_trigger = map.sp_trigger;
1593 map_pkg.sp_row = map.sp_row;
1594 map_pkg.sp_push = map.sp_push;
1595 map_pkg.start_bombs = bman.start_bombs;
1596 map_pkg.start_range = bman.start_range;
1597 sprintf (map_pkg.start_speed, "%4f", bman.start_speed);
1598 sprintf (map_pkg.bomb_tickingtime, "%4f", bman.bomb_tickingtime);
1599
1600 if (map.random_tileset)
1601 map_pkg.tileset[0] = 0;
1602 else
1603 strncpy (map_pkg.tileset, map.tileset, LEN_TILESETNAME);
1604 map_pkg.map_selection = map.map_selection;
1605 strncpy (map_pkg.mapname, map.map, LEN_FILENAME);
1606 d_printf ("send_mapinfo: Tileset: %s\n", map.tileset);
1607 #ifndef BUG_MAPINFO
1608 test = addr; // VERY DIRTY WORKAROUND WHY IS HERE A BUG
1609 send_pkg ((struct pkg *) &map_pkg, addr);
1610 addr = test; // VERY DIRTY WORKAROUND WHY IS HERE A BUG
1611 #else
1612 printf ("Addr before send: %p\n", addr);
1613 send_pkg ((struct pkg *) &map_pkg, addr);
1614 printf ("Addr after send: %p\n", addr);
1615 #endif
1616 };
1617
1618
1619 void
do_mapinfo(struct pkg_mapinfo * map_pkg,_net_addr * addr)1620 do_mapinfo (struct pkg_mapinfo *map_pkg, _net_addr * addr)
1621 {
1622 d_printf ("do_mapinfo (addr %d) size[%d,%d]\n", addr->pl_nr, map_pkg->size_x, map_pkg->size_y);
1623
1624 /* check if the server send this information */
1625 if (addr->pl_nr != bman.p_servnr)
1626 return;
1627
1628 if (map_pkg->tileset[0] == 0) {
1629 map.random_tileset = 1;
1630 map.tileset[0] = 0;
1631 }
1632 else {
1633 map.random_tileset = 0;
1634 strncpy (map.tileset, map_pkg->tileset, LEN_TILESETNAME);
1635 }
1636 strncpy (map.map, map_pkg->mapname, LEN_FILENAME);
1637 map.map_selection = map_pkg->map_selection;
1638 map.size.x = map_pkg->size_x;
1639 map.size.y = map_pkg->size_y;
1640 map.bombs = map_pkg->bombs;
1641 map.fire = map_pkg->fire;
1642 map.shoes = map_pkg->shoes;
1643 map.mixed = map_pkg->mixed;
1644 map.death = map_pkg->death;
1645 map.sp_trigger = map_pkg->sp_trigger;
1646 map.sp_push = map_pkg->sp_push;
1647 map.sp_row = map_pkg->sp_row;
1648
1649 bman.start_bombs = map_pkg->start_bombs;
1650 bman.start_range = map_pkg->start_range;
1651 sscanf (map_pkg->start_speed, "%f", &bman.start_speed);
1652 sscanf (map_pkg->bomb_tickingtime, "%f", &bman.bomb_tickingtime);
1653 };
1654
1655
1656 /***
1657 *** Respawn Date Handling
1658 ***/
1659 void
send_respawn(_net_addr * addr,int plnr)1660 send_respawn (_net_addr * addr, int plnr)
1661 {
1662 struct pkg_respawn r_dat;
1663
1664 r_dat.h.typ = PKG_respawn;
1665 r_dat.h.len = HTON16 (sizeof (struct pkg_respawn));
1666 r_dat.h.flags = PKGF_ackreq;
1667 r_dat.pl_nr = plnr;
1668 r_dat.state = players[plnr].state;
1669 r_dat.x = players[plnr].pos.x;
1670 r_dat.y = players[plnr].pos.y;
1671 send_pkg ((struct pkg *) &r_dat, addr);
1672 };
1673
1674
1675 void
do_respawn(struct pkg_respawn * r_pkg,_net_addr * addr)1676 do_respawn (struct pkg_respawn *r_pkg, _net_addr * addr)
1677 {
1678 d_printf ("do_respawn (addr %d, pl_nr %d, pos %d,%d)\n", addr->pl_nr, r_pkg->pl_nr, r_pkg->x,
1679 r_pkg->y);
1680 if (addr->pl_nr == -1 || r_pkg->pl_nr == -1)
1681 return;
1682
1683 if ((r_pkg->state & PSF_respawn) == PSF_respawn) {
1684 players[r_pkg->pl_nr].pos.x = r_pkg->x;
1685 players[r_pkg->pl_nr].pos.y = r_pkg->y;
1686 players[r_pkg->pl_nr].state &= (0xFF - PSF_alife);
1687 players[r_pkg->pl_nr].state |= PSF_respawn;
1688 players[r_pkg->pl_nr].frame = 0.0f;
1689
1690 }
1691 else if (r_pkg->state & (PSF_respawn + PSF_alife)) {
1692 players[r_pkg->pl_nr].pos.x = r_pkg->x;
1693 players[r_pkg->pl_nr].pos.y = r_pkg->y;
1694 players[r_pkg->pl_nr].state |= PSF_alife;
1695 players[r_pkg->pl_nr].state &= (0xFF - PSF_respawn);
1696 }
1697 };
1698
1699
1700
1701 /***
1702 *** gameinfo packet is used to get some data from a running game
1703 *** just fill in the informations we need and send this packet back.
1704 ***/
1705 void
do_gameinfo(struct pkg_gameinfo * pgi,_net_addr * addr)1706 do_gameinfo (struct pkg_gameinfo *pgi, _net_addr * addr)
1707 {
1708 if (GT_MP_PTPM && pgi->password == -1) {
1709 d_printf ("do_gameinfo (from: %s:%s) Broadcast Req: %d\n", addr->host, addr->port,
1710 pgi->broadcast);
1711
1712 strncpy (pgi->version, VERSION, LEN_VERSION);
1713 pgi->maxplayers = bman.maxplayer;
1714 pgi->curplayers = bman.players_nr_s;
1715 pgi->h.len = HTON16 (sizeof (struct pkg_gameinfo));
1716 strncpy (pgi->gamename, bman.gamename, LEN_GAMENAME);
1717 send_pkg ((struct pkg *) pgi, addr);
1718 }
1719 else if (pgi->password != -1)
1720 d_printf ("do_gameinfo (from: %s:%s) ** NO REQUEST **\n", addr->host, addr->port);
1721 else
1722 d_printf ("do_gameinfo (from: %s:%s) ** WE ARE NOT THE MASTER OF THIS GAME **\n",
1723 addr->host, addr->port);
1724 }
1725
1726
1727 void
send_gameinfo(_net_addr * addr,int sock,int broadcast)1728 send_gameinfo (_net_addr * addr, int sock, int broadcast)
1729 {
1730 struct pkg_gameinfo pgi;
1731
1732 pgi.h.typ = PKG_gameinfo;
1733 pgi.h.len = HTON16 (sizeof (struct pkg_gameinfo));
1734 pgi.h.flags = 0;
1735 pgi.timestamp = timestamp;
1736 pgi.gamename[0] = 0;
1737 pgi.version[0] = 0;
1738 pgi.password = -1;
1739 pgi.broadcast = broadcast;
1740
1741 if (bman.net_ai_family != PF_INET)
1742 pgi.h.flags = pgi.h.flags | PKGF_ipv6;
1743 if (broadcast)
1744 udp_sendbroadcast (sock, (char *) &pgi, NTOH16 (pgi.h.len), &addr->sAddr,
1745 bman.net_ai_family);
1746 else
1747 udp_send (sock, (char *) &pgi, NTOH16 (pgi.h.len), &addr->sAddr, bman.net_ai_family);
1748 };
1749
1750
1751 /***
1752 *** general packet handling, like check for double recived packets
1753 *** network type. Autoreply on PKGF_ackreq and such things.
1754 ***/
1755
1756 /* check incoming packet, if we have got the same already if so return != -1
1757 if we haven't got it yet, Add to the incache and return -1 */
1758 int
inpkg_check(unsigned char typ,short int id,_net_addr * addr)1759 inpkg_check (unsigned char typ, short int id, _net_addr * addr)
1760 {
1761 int i,
1762 pos;
1763
1764 /* check if the player is still connected */
1765 if (!PS_IS_used (players[addr->pl_nr].state))
1766 return -1;
1767
1768 /* find packet */
1769 for (i = 0, pos = -1; (i < PKG_IN_INDEX_NUM && pos == -1); i++)
1770 if (inpkg_index[i].pl_nr == addr->pl_nr
1771 && inpkg_index[i].typ == typ && inpkg_index[i].id == id)
1772 pos = i;
1773
1774 if (pos == -1) {
1775 /* add to index */
1776 if (++inpkg_index_pos >= PKG_IN_INDEX_NUM)
1777 inpkg_index_pos = 0;
1778
1779 inpkg_index[inpkg_index_pos].pl_nr = addr->pl_nr;
1780 inpkg_index[inpkg_index_pos].typ = typ;
1781 inpkg_index[inpkg_index_pos].id = id;
1782 }
1783 return pos;
1784 };
1785
1786
1787 /* delete all old pkg indexes about a player */
1788 void
inpkg_delplayer(int pl_nr)1789 inpkg_delplayer (int pl_nr)
1790 {
1791 int i;
1792
1793 for (i = 0; i < PKG_IN_INDEX_NUM; i++)
1794 if (inpkg_index[i].pl_nr == pl_nr)
1795 inpkg_index[i].pl_nr = -1;
1796 }
1797
1798
1799 /* sends the packet and if PKGF_ackreq is set add packet to the resendcache */
1800 void
send_pkg(struct pkg * packet,_net_addr * addr)1801 send_pkg (struct pkg *packet, _net_addr * addr)
1802 {
1803 d_printf ("send_pkg: plnr:%d, typ:%u id:%u\n", addr->pl_nr, packet->h.typ, packet->h.id);
1804
1805 /* check if the packet would be send to
1806 * an AI_Player, so ignore it. */
1807 if ((addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS)
1808 && PS_IS_aiplayer (players[addr->pl_nr].state))
1809 return;
1810
1811 /* set the id for the packet and the network flags
1812 * the id is needed for the inpkg index to check for
1813 * double reached packets
1814 * The id is limited to 32700 if */
1815 packet->h.id = HTON16 (pkg_lastid++ % 32767);
1816 if (bman.net_ai_family != PF_INET)
1817 packet->h.flags = packet->h.flags | PKGF_ipv6;
1818 udp_send (bman.sock, (char *) packet, NTOH16 (packet->h.len), &addr->sAddr, bman.net_ai_family);
1819
1820 /* if PKGF_ackreq is set add the packet to the resendcache
1821 * so we can resend it if no PKF_ackreq returned for the packet. */
1822 if (packet->h.flags & PKGF_ackreq)
1823 rscache_add (addr, packet);
1824 };
1825
1826
1827 /* forward the packet to all who are behind a firewall */
1828 void
fwd_pkg(struct pkg * packet,_net_addr * addr)1829 fwd_pkg (struct pkg *packet, _net_addr * addr)
1830 {
1831 int pl;
1832
1833 if (GT_MP_PTPS) /* clients don't forward anything */
1834 return;
1835
1836 if (packet->h.typ >= PKG_field && packet->h.typ < PKG_quit) {
1837 for (pl = 0; pl < MAX_PLAYERS; pl++)
1838 if ((!PS_IS_aiplayer (players[pl].state)) && PS_IS_netplayer (players[pl].state)
1839 && ((players[addr->pl_nr].net.flags & NETF_firewall) == NETF_firewall
1840 || (players[pl].net.flags & NETF_firewall) == NETF_firewall)
1841 && pl != addr->pl_nr && (players[pl].net.flags & NETF_local2) == 0)
1842 send_pkg (packet, &players[pl].net.addr);
1843 }
1844 else if (packet->h.typ > PKG_quit)
1845 d_fatal ("fwd_pkg: not forwarding unknown packet From Player:%d (%s) Typ:%d Len:%d\n",
1846 addr->pl_nr, players[addr->pl_nr].name, packet->h.typ, NTOH16 (packet->h.len));
1847 };
1848
1849
1850 /* entry point for all incoming network data. determinate packet type and
1851 forward it to all needed functions, like inpkg_check()--> send answer if needed,
1852 if we are the server then forward the packet if needed
1853 and go into the do_PACKETTYP function */
1854 void
do_pkg(struct pkg * packet,_net_addr * addr,int len)1855 do_pkg (struct pkg *packet, _net_addr * addr, int len)
1856 {
1857 d_printf ("do_pkg: plnr:%d, typ:%u id:%u\n", addr->pl_nr, packet->h.typ, packet->h.id);
1858 if (((packet->h.flags & PKGF_ipv6) == 0 && bman.net_ai_family != PF_INET)
1859 || ((packet->h.flags & PKGF_ipv6) != 0 && bman.net_ai_family == PF_INET)) {
1860 d_printf ("do_pkg: packet comes from the wrong network type\n");
1861 return;
1862 }
1863
1864 /* Check the size of the incoming packet */
1865 if (len != NTOH16(packet->h.len)) {
1866 d_printf ("do_pkg: len(%d) of the incoming packet is not the same as in pkg->h.len(%d)\n", len, NTOH16(packet->h.len));
1867 return;
1868 }
1869
1870 /* get the addr and set the ping timeout value
1871 * check if the packet is from a player in the game and not from someone else
1872 * this exception is only for PKG_joingame, PKG_error */
1873 addr->pl_nr = get_player_nr (addr->host, addr->port);
1874 if ((addr->pl_nr < 0 || addr->pl_nr >= MAX_PLAYERS) && packet->h.typ > PKG_joingame
1875 && PS_IS_netplayer (players[addr->pl_nr].state)) {
1876 d_printf ("do_pkg: error addr->pl_nr out of range\n");
1877 return;
1878 }
1879
1880 if (addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS) {
1881 players[addr->pl_nr].net.timestamp = timestamp;
1882 players[addr->pl_nr].net.pingreq = players[addr->pl_nr].net.pingack + 5;
1883
1884 /* test if we have any important packet */
1885 if (packet->h.flags & PKGF_ackreq) {
1886
1887 /* we need to send an acknolege so the client
1888 * knows we have got this packet and delete
1889 * it from the resend cache. */
1890 send_pkgack (addr, packet->h.typ, NTOH16 (packet->h.id));
1891
1892 /* check the packet with the index so we can
1893 * ignore packets we already have got
1894 * this is important to keep away from
1895 * the bomb is dropped twice bug. */
1896 if (inpkg_check (packet->h.typ, NTOH16 (packet->h.id), addr) != -1) {
1897 /* we have got this packet already */
1898 d_printf ("do_pkg: double packet ignoring addr->pl_nr=%d type:%d\n", addr->pl_nr, packet->h.typ);
1899 if (addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS)
1900 players[addr->pl_nr].net.pkgopt.to_2sec++;
1901 return;
1902 }
1903 }
1904
1905 /* forward packet */
1906 if (GT_MP_PTPM)
1907 fwd_pkg (packet, addr);
1908 }
1909
1910 switch (packet->h.typ) {
1911 case (PKG_error):
1912 do_error ((struct pkg_error *) packet, addr);
1913 break;
1914 case (PKG_gameinfo):
1915 do_gameinfo ((struct pkg_gameinfo *) packet, addr);
1916 break;
1917 case (PKG_playerid):
1918 do_playerid ((struct pkg_playerid *) packet, addr);
1919 break;
1920 case (PKG_servermode):
1921 do_servermode ((struct pkg_servermode *) packet, addr);
1922 break;
1923 case (PKG_field):
1924 do_field ((struct pkg_field *) packet, addr);
1925 break;
1926 case (PKG_contest):
1927 do_contest ((struct pkg_contest *) packet, addr);
1928 break;
1929 case (PKG_pingreq):
1930 do_ping ((struct pkg_ping *) packet, addr);
1931 break;
1932 case (PKG_pingack):
1933 do_ping ((struct pkg_ping *) packet, addr);
1934 break;
1935 case (PKG_bombdata):
1936 do_bombdata ((struct pkg_bombdata *) packet, addr);
1937 break;
1938 case (PKG_playerdata):
1939 do_playerdata ((struct pkg_playerdata *) packet, addr);
1940 break;
1941 case (PKG_quit):
1942 do_quit ((struct pkg_quit *) packet, addr);
1943 break;
1944 case (PKG_getfield):
1945 do_getfield ((struct pkg_getfield *) packet, addr);
1946 break;
1947 case (PKG_getplayerdata):
1948 do_getplayerdata ((struct pkg_getplayerdata *) packet, addr);
1949 break;
1950 case (PKG_fieldline):
1951 do_fieldline ((struct pkg_fieldline *) packet, addr);
1952 break;
1953 case (PKG_playerstatus):
1954 do_playerstatus ((struct pkg_playerstatus *) packet, addr);
1955 break;
1956 case (PKG_pkgack):
1957 do_pkgack ((struct pkg_pkgack *) packet, addr);
1958 break;
1959 case (PKG_chat):
1960 do_chat ((struct pkg_chat *) packet, addr);
1961 break;
1962 case (PKG_playermove):
1963 do_playermove ((struct pkg_playermove *) packet, addr);
1964 break;
1965 case (PKG_ill):
1966 do_ill ((struct pkg_ill *) packet, addr);
1967 break;
1968 case (PKG_special):
1969 do_special ((struct pkg_special *) packet, addr);
1970 break;
1971 case (PKG_mapinfo):
1972 do_mapinfo ((struct pkg_mapinfo *) packet, addr);
1973 break;
1974 case (PKG_tunneldata):
1975 do_tunneldata ((struct pkg_tunneldata *) packet, addr);
1976 break;
1977 case (PKG_joingame):
1978 do_joingame ((struct pkg_joingame *) packet, addr);
1979 break;
1980 case (PKG_dropitem):
1981 do_dropitems ((struct pkg_dropitem *) packet, addr);
1982 break;
1983 case (PKG_respawn):
1984 do_respawn ((struct pkg_respawn *) packet, addr);
1985 break;
1986 case (PKG_updateinfo):
1987 do_updateinfo ((struct pkg_updateinfo *) packet, addr);
1988 break;
1989 case (PKG_teamdata):
1990 do_teamdata ((struct pkg_teamdata *) packet, addr);
1991 break;
1992 default:
1993 send_error (addr, "BomberClone: unknown data packet");
1994 break;
1995 }
1996 };
1997