1 /*
2 * OpenTyrian: A modern cross-platform port of Tyrian
3 * Copyright (C) 2007-2009 The OpenTyrian Development Team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19 #include "episodes.h"
20 #include "fonthand.h"
21 #include "helptext.h"
22 #include "joystick.h"
23 #include "keyboard.h"
24 #include "mainint.h"
25 #include "network.h"
26 #include "nortvars.h"
27 #include "opentyr.h"
28 #include "picload.h"
29 #include "sprite.h"
30 #include "varz.h"
31 #include "video.h"
32
33 #include <assert.h>
34
35 /* HERE BE DRAGONS!
36 *
37 * When I wrote this code I thought it was wonderful... that thought was very
38 * wrong. It works, but good luck understanding how... I don't anymore.
39 *
40 * Hopefully it'll be rewritten some day.
41 */
42
43 #define NET_VERSION 2 // increment whenever networking changes might create incompatability
44 #define NET_PORT 1333 // UDP
45
46 #define NET_PACKET_SIZE 256
47 #define NET_PACKET_QUEUE 16
48
49 #define NET_RETRY 640 // ticks to wait for packet acknowledgement before resending
50 #define NET_RESEND 320 // ticks to wait before requesting unreceived game packet
51 #define NET_KEEP_ALIVE 1600 // ticks to wait between keep-alive packets
52 #define NET_TIME_OUT 16000 // ticks to wait before considering connection dead
53
54 bool isNetworkGame = false;
55 int network_delay = 1 + 1; // minimum is 1 + 0
56
57 char *network_opponent_host = NULL;
58
59 Uint16 network_player_port = NET_PORT,
60 network_opponent_port = NET_PORT;
61
62 static char empty_string[] = "";
63 char *network_player_name = empty_string,
64 *network_opponent_name = empty_string;
65
66 #ifdef WITH_NETWORK
67 static UDPsocket socket;
68 static IPaddress ip;
69
70 UDPpacket *packet_out_temp;
71 static UDPpacket *packet_temp;
72
73 UDPpacket *packet_in[NET_PACKET_QUEUE] = { NULL },
74 *packet_out[NET_PACKET_QUEUE] = { NULL };
75
76 static Uint16 last_out_sync = 0, queue_in_sync = 0, queue_out_sync = 0, last_ack_sync = 0;
77 static Uint32 last_in_tick = 0, last_out_tick = 0;
78
79 UDPpacket *packet_state_in[NET_PACKET_QUEUE] = { NULL };
80 static UDPpacket *packet_state_in_xor[NET_PACKET_QUEUE] = { NULL };
81 UDPpacket *packet_state_out[NET_PACKET_QUEUE] = { NULL };
82
83 static Uint16 last_state_in_sync = 0, last_state_out_sync = 0;
84 static Uint32 last_state_in_tick = 0;
85
86 static bool net_initialized = false;
87 static bool connected = false, quit = false;
88 #endif
89
90 uint thisPlayerNum = 0; /* Player number on this PC (1 or 2) */
91
92 JE_boolean haltGame = false;
93
94 JE_boolean moveOk;
95
96 /* Special Requests */
97 JE_boolean pauseRequest, skipLevelRequest, helpRequest, nortShipRequest;
98 JE_boolean yourInGameMenuRequest, inGameMenuRequest;
99
100 #ifdef WITH_NETWORK
packet_copy(UDPpacket * dst,UDPpacket * src)101 static void packet_copy( UDPpacket *dst, UDPpacket *src )
102 {
103 void *temp = dst->data;
104 memcpy(dst, src, sizeof(*dst));
105 dst->data = temp;
106 memcpy(dst->data, src->data, src->len);
107 }
108
packets_shift_up(UDPpacket ** packet,int max_packets)109 static void packets_shift_up( UDPpacket **packet, int max_packets )
110 {
111 if (packet[0])
112 {
113 SDLNet_FreePacket(packet[0]);
114 }
115 for (int i = 0; i < max_packets - 1; i++)
116 {
117 packet[i] = packet[i + 1];
118 }
119 packet[max_packets - 1] = NULL;
120 }
121
packets_shift_down(UDPpacket ** packet,int max_packets)122 static void packets_shift_down( UDPpacket **packet, int max_packets )
123 {
124 if (packet[max_packets - 1])
125 {
126 SDLNet_FreePacket(packet[max_packets - 1]);
127 }
128 for (int i = max_packets - 1; i > 0; i--)
129 {
130 packet[i] = packet[i - 1];
131 }
132 packet[0] = NULL;
133 }
134
135 // prepare new packet for sending
network_prepare(Uint16 type)136 void network_prepare( Uint16 type )
137 {
138 SDLNet_Write16(type, &packet_out_temp->data[0]);
139 SDLNet_Write16(last_out_sync, &packet_out_temp->data[2]);
140 }
141
142 // send packet but don't expect acknoledgment of delivery
network_send_no_ack(int len)143 static bool network_send_no_ack( int len )
144 {
145 packet_out_temp->len = len;
146
147 if (!SDLNet_UDP_Send(socket, 0, packet_out_temp))
148 {
149 printf("SDLNet_UDP_Send: %s\n", SDL_GetError());
150 return false;
151 }
152
153 return true;
154 }
155
156 // send packet and place it in queue to be acknowledged
network_send(int len)157 bool network_send( int len )
158 {
159 bool temp = network_send_no_ack(len);
160
161 Uint16 i = last_out_sync - queue_out_sync;
162 if (i < NET_PACKET_QUEUE)
163 {
164 packet_out[i] = SDLNet_AllocPacket(NET_PACKET_SIZE);
165 packet_copy(packet_out[i], packet_out_temp);
166 } else {
167 // connection is probably bad now
168 fprintf(stderr, "warning: outbound packet queue overflow\n");
169 return false;
170 }
171
172 last_out_sync++;
173
174 if (network_is_sync())
175 last_out_tick = SDL_GetTicks();
176
177 return temp;
178 }
179
180 // send acknowledgement packet
network_acknowledge(Uint16 sync)181 static int network_acknowledge( Uint16 sync )
182 {
183 SDLNet_Write16(PACKET_ACKNOWLEDGE, &packet_out_temp->data[0]);
184 SDLNet_Write16(sync, &packet_out_temp->data[2]);
185 network_send_no_ack(4);
186
187 return 0;
188 }
189
190 // activity lately?
network_is_alive(void)191 static bool network_is_alive( void )
192 {
193 return (SDL_GetTicks() - last_in_tick < NET_TIME_OUT || SDL_GetTicks() - last_state_in_tick < NET_TIME_OUT);
194 }
195
196 // poll for new packets received, check that connection is alive, resend queued packets if necessary
network_check(void)197 int network_check( void )
198 {
199 if (!net_initialized)
200 return -1;
201
202 if (connected)
203 {
204 // timeout
205 if (!network_is_alive())
206 {
207 if (!quit)
208 network_tyrian_halt(2, false);
209 }
210
211 // keep-alive
212 static Uint32 keep_alive_tick = 0;
213 if (SDL_GetTicks() - keep_alive_tick > NET_KEEP_ALIVE)
214 {
215 network_prepare(PACKET_KEEP_ALIVE);
216 network_send_no_ack(4);
217
218 keep_alive_tick = SDL_GetTicks();
219 }
220 }
221
222 // retry
223 if (packet_out[0] && SDL_GetTicks() - last_out_tick > NET_RETRY)
224 {
225 if (!SDLNet_UDP_Send(socket, 0, packet_out[0]))
226 {
227 printf("SDLNet_UDP_Send: %s\n", SDL_GetError());
228 return -1;
229 }
230
231 last_out_tick = SDL_GetTicks();
232 }
233
234 switch (SDLNet_UDP_Recv(socket, packet_temp))
235 {
236 case -1:
237 printf("SDLNet_UDP_Recv: %s\n", SDL_GetError());
238 return -1;
239 break;
240 case 0:
241 break;
242 default:
243 if (packet_temp->channel == 0 && packet_temp->len >= 4)
244 {
245 switch (SDLNet_Read16(&packet_temp->data[0]))
246 {
247 case PACKET_ACKNOWLEDGE:
248 if ((Uint16)(SDLNet_Read16(&packet_temp->data[2]) - last_ack_sync) < NET_PACKET_QUEUE)
249 {
250 last_ack_sync = SDLNet_Read16(&packet_temp->data[2]);
251 }
252
253 {
254 Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - queue_out_sync;
255 if (i < NET_PACKET_QUEUE)
256 {
257 if (packet_out[i])
258 {
259 SDLNet_FreePacket(packet_out[i]);
260 packet_out[i] = NULL;
261 }
262 }
263 }
264
265 // remove acknowledged packets from queue
266 while (packet_out[0] == NULL && (Uint16)(last_ack_sync - queue_out_sync) < NET_PACKET_QUEUE)
267 {
268 packets_shift_up(packet_out, NET_PACKET_QUEUE);
269
270 queue_out_sync++;
271 }
272
273 last_in_tick = SDL_GetTicks();
274 break;
275
276 case PACKET_CONNECT:
277 queue_in_sync = SDLNet_Read16(&packet_temp->data[2]);
278
279 for (int i = 0; i < NET_PACKET_QUEUE; i++)
280 {
281 if (packet_in[i])
282 {
283 SDLNet_FreePacket(packet_in[i]);
284 packet_in[i] = NULL;
285 }
286 }
287
288 case PACKET_DETAILS:
289 case PACKET_WAITING:
290 case PACKET_BUSY:
291 case PACKET_GAME_QUIT:
292 case PACKET_GAME_PAUSE:
293 case PACKET_GAME_MENU:
294 {
295 Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - queue_in_sync;
296 if (i < NET_PACKET_QUEUE)
297 {
298 if (packet_in[i] == NULL)
299 packet_in[i] = SDLNet_AllocPacket(NET_PACKET_SIZE);
300 packet_copy(packet_in[i], packet_temp);
301 } else {
302 // inbound packet queue overflow/underflow
303 // under normal circumstances, this is okay
304 }
305 }
306
307 network_acknowledge(SDLNet_Read16(&packet_temp->data[2]));
308
309 case PACKET_KEEP_ALIVE:
310 last_in_tick = SDL_GetTicks();
311 break;
312
313 case PACKET_QUIT:
314 if (!quit)
315 {
316 network_prepare(PACKET_QUIT);
317 network_send(4); // PACKET_QUIT
318 }
319
320 network_acknowledge(SDLNet_Read16(&packet_temp->data[2]));
321
322 if (!quit)
323 network_tyrian_halt(1, true);
324 break;
325
326 case PACKET_STATE:
327 // place packet in queue if within limits
328 {
329 Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - last_state_in_sync + 1;
330 if (i < NET_PACKET_QUEUE)
331 {
332 if (packet_state_in[i] == NULL)
333 packet_state_in[i] = SDLNet_AllocPacket(NET_PACKET_SIZE);
334 packet_copy(packet_state_in[i], packet_temp);
335 }
336 }
337 break;
338
339 case PACKET_STATE_XOR:
340 // place packet in queue if within limits
341 {
342 Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - last_state_in_sync + 1;
343 if (i < NET_PACKET_QUEUE)
344 {
345 if (packet_state_in_xor[i] == NULL)
346 {
347 packet_state_in_xor[i] = SDLNet_AllocPacket(NET_PACKET_SIZE);
348 packet_copy(packet_state_in_xor[i], packet_temp);
349 } else if (SDLNet_Read16(&packet_state_in_xor[i]->data[0]) != PACKET_STATE_XOR) {
350 for (int j = 4; j < packet_state_in_xor[i]->len; j++)
351 packet_state_in_xor[i]->data[j] ^= packet_temp->data[j];
352 SDLNet_Write16(PACKET_STATE_XOR, &packet_state_in_xor[i]->data[0]);
353 }
354 }
355 }
356 break;
357
358 case PACKET_STATE_RESEND:
359 // resend requested state packet if still available
360 {
361 Uint16 i = last_state_out_sync - SDLNet_Read16(&packet_temp->data[2]);
362 if (i > 0 && i < NET_PACKET_QUEUE)
363 {
364 if (packet_state_out[i])
365 {
366 if (!SDLNet_UDP_Send(socket, 0, packet_state_out[i]))
367 {
368 printf("SDLNet_UDP_Send: %s\n", SDL_GetError());
369 return -1;
370 }
371 }
372 }
373 }
374 break;
375
376 default:
377 fprintf(stderr, "warning: bad packet %d received\n", SDLNet_Read16(&packet_temp->data[0]));
378 return 0;
379 break;
380 }
381
382 return 1;
383 }
384 break;
385 }
386
387 return 0;
388 }
389
390 // discard working packet, now processing next packet in queue
network_update(void)391 bool network_update( void )
392 {
393 if (packet_in[0])
394 {
395 packets_shift_up(packet_in, NET_PACKET_QUEUE);
396
397 queue_in_sync++;
398
399 return true;
400 }
401
402 return false;
403 }
404
405 // has opponent gotten all the packets we've sent?
network_is_sync(void)406 bool network_is_sync( void )
407 {
408 return (queue_out_sync - last_ack_sync == 1);
409 }
410
411
412 // prepare new state for sending
network_state_prepare(void)413 void network_state_prepare( void )
414 {
415 if (packet_state_out[0])
416 {
417 fprintf(stderr, "warning: state packet overwritten (previous packet remains unsent)\n");
418 } else {
419 packet_state_out[0] = SDLNet_AllocPacket(NET_PACKET_SIZE);
420 packet_state_out[0]->len = 28;
421 }
422
423 SDLNet_Write16(PACKET_STATE, &packet_state_out[0]->data[0]);
424 SDLNet_Write16(last_state_out_sync, &packet_state_out[0]->data[2]);
425 memset(&packet_state_out[0]->data[4], 0, 28 - 4);
426 }
427
428 // send state packet, xor packet if applicable
network_state_send(void)429 int network_state_send( void )
430 {
431 if (!SDLNet_UDP_Send(socket, 0, packet_state_out[0]))
432 {
433 printf("SDLNet_UDP_Send: %s\n", SDL_GetError());
434 return -1;
435 }
436
437 // send xor of last network_delay packets
438 if (network_delay > 1 && (last_state_out_sync + 1) % network_delay == 0 && packet_state_out[network_delay - 1] != NULL)
439 {
440 packet_copy(packet_temp, packet_state_out[0]);
441 SDLNet_Write16(PACKET_STATE_XOR, &packet_temp->data[0]);
442 for (int i = 1; i < network_delay; i++)
443 for (int j = 4; j < packet_temp->len; j++)
444 packet_temp->data[j] ^= packet_state_out[i]->data[j];
445
446 if (!SDLNet_UDP_Send(socket, 0, packet_temp))
447 {
448 printf("SDLNet_UDP_Send: %s\n", SDL_GetError());
449 return -1;
450 }
451 }
452
453 packets_shift_down(packet_state_out, NET_PACKET_QUEUE);
454
455 last_state_out_sync++;
456
457 return 0;
458 }
459
460 // receive state packet, wait until received
network_state_update(void)461 bool network_state_update( void )
462 {
463 if (network_state_is_reset())
464 {
465 return 0;
466 } else {
467 packets_shift_up(packet_state_in, NET_PACKET_QUEUE);
468
469 packets_shift_up(packet_state_in_xor, NET_PACKET_QUEUE);
470
471 last_state_in_sync++;
472
473 // current xor packet index
474 int x = network_delay - (last_state_in_sync - 1) % network_delay - 1;
475
476 // loop until needed packet is available
477 while (!packet_state_in[0])
478 {
479 // xor the packet from thin air, if possible
480 if (packet_state_in_xor[x] && SDLNet_Read16(&packet_state_in_xor[x]->data[0]) == PACKET_STATE_XOR)
481 {
482 // check for all other required packets
483 bool okay = true;
484 for (int i = 1; i <= x; i++)
485 {
486 if (packet_state_in[i] == NULL)
487 {
488 okay = false;
489 break;
490 }
491 }
492 if (okay)
493 {
494 packet_state_in[0] = SDLNet_AllocPacket(NET_PACKET_SIZE);
495 packet_copy(packet_state_in[0], packet_state_in_xor[x]);
496 for (int i = 1; i <= x; i++)
497 for (int j = 4; j < packet_state_in[0]->len; j++)
498 packet_state_in[0]->data[j] ^= packet_state_in[i]->data[j];
499 break;
500 }
501 }
502
503 static Uint32 resend_tick = 0;
504 if (SDL_GetTicks() - last_state_in_tick > NET_RESEND && SDL_GetTicks() - resend_tick > NET_RESEND)
505 {
506 SDLNet_Write16(PACKET_STATE_RESEND, &packet_out_temp->data[0]);
507 SDLNet_Write16(last_state_in_sync - 1, &packet_out_temp->data[2]);
508 network_send_no_ack(4); // PACKET_RESEND
509
510 resend_tick = SDL_GetTicks();
511 }
512
513 if (network_check() == 0)
514 SDL_Delay(1);
515 }
516
517 if (network_delay > 1)
518 {
519 // process the current in packet against the xor queue
520 if (packet_state_in_xor[x] == NULL)
521 {
522 packet_state_in_xor[x] = SDLNet_AllocPacket(NET_PACKET_SIZE);
523 packet_copy(packet_state_in_xor[x], packet_state_in[0]);
524 packet_state_in_xor[x]->status = 0;
525 } else {
526 for (int j = 4; j < packet_state_in_xor[x]->len; j++)
527 packet_state_in_xor[x]->data[j] ^= packet_state_in[0]->data[j];
528 }
529 }
530
531 last_state_in_tick = SDL_GetTicks();
532 }
533
534 return 1;
535 }
536
537 // ignore first network_delay states of level
network_state_is_reset(void)538 bool network_state_is_reset( void )
539 {
540 return (last_state_out_sync < network_delay);
541 }
542
543 // reset queues for new level
network_state_reset(void)544 void network_state_reset( void )
545 {
546 last_state_in_sync = last_state_out_sync = 0;
547
548 for (int i = 0; i < NET_PACKET_QUEUE; i++)
549 {
550 if (packet_state_in[i])
551 {
552 SDLNet_FreePacket(packet_state_in[i]);
553 packet_state_in[i] = NULL;
554 }
555 }
556 for (int i = 0; i < NET_PACKET_QUEUE; i++)
557 {
558 if (packet_state_in_xor[i])
559 {
560 SDLNet_FreePacket(packet_state_in_xor[i]);
561 packet_state_in_xor[i] = NULL;
562 }
563 }
564 for (int i = 0; i < NET_PACKET_QUEUE; i++)
565 {
566 if (packet_state_out[i])
567 {
568 SDLNet_FreePacket(packet_state_out[i]);
569 packet_state_out[i] = NULL;
570 }
571 }
572
573 last_state_in_tick = SDL_GetTicks();
574 }
575
576
577 // attempt to punch through firewall by firing off UDP packets at the opponent
578 // exchange game information
network_connect(void)579 int network_connect( void )
580 {
581 SDLNet_ResolveHost(&ip, network_opponent_host, network_opponent_port);
582
583 SDLNet_UDP_Bind(socket, 0, &ip);
584
585 Uint16 episodes = 0, episodes_local = 0;
586 assert(EPISODE_MAX <= 16);
587 for (int i = EPISODE_MAX - 1; i >= 0; i--)
588 {
589 episodes <<= 1;
590 episodes |= (episodeAvail[i] != 0);
591 }
592 episodes_local = episodes;
593
594 assert(NET_PACKET_SIZE - 12 >= 20 + 1);
595 if (strlen(network_player_name) > 20)
596 network_player_name[20] = '\0';
597
598 connect_reset:
599 network_prepare(PACKET_CONNECT);
600 SDLNet_Write16(NET_VERSION, &packet_out_temp->data[4]);
601 SDLNet_Write16(network_delay, &packet_out_temp->data[6]);
602 SDLNet_Write16(episodes_local, &packet_out_temp->data[8]);
603 SDLNet_Write16(thisPlayerNum, &packet_out_temp->data[10]);
604 strcpy((char *)&packet_out_temp->data[12], network_player_name);
605 network_send(12 + strlen(network_player_name) + 1); // PACKET_CONNECT
606
607 // until opponent sends connect packet
608 while (true)
609 {
610 push_joysticks_as_keyboard();
611 service_SDL_events(false);
612
613 if (newkey && lastkey_sym == SDLK_ESCAPE)
614 network_tyrian_halt(0, false);
615
616 // never timeout
617 last_in_tick = SDL_GetTicks();
618
619 if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_CONNECT)
620 break;
621
622 network_update();
623 network_check();
624
625 SDL_Delay(16);
626 }
627
628 connect_again:
629 if (SDLNet_Read16(&packet_in[0]->data[4]) != NET_VERSION)
630 {
631 fprintf(stderr, "error: network version did not match opponent's\n");
632 network_tyrian_halt(4, true);
633 }
634 if (SDLNet_Read16(&packet_in[0]->data[6]) != network_delay)
635 {
636 fprintf(stderr, "error: network delay did not match opponent's\n");
637 network_tyrian_halt(5, true);
638 }
639 if (SDLNet_Read16(&packet_in[0]->data[10]) == thisPlayerNum)
640 {
641 fprintf(stderr, "error: player number conflicts with opponent's\n");
642 network_tyrian_halt(6, true);
643 }
644
645 episodes = SDLNet_Read16(&packet_in[0]->data[8]);
646 for (int i = 0; i < EPISODE_MAX; i++) {
647 episodeAvail[i] &= (episodes & 1);
648 episodes >>= 1;
649 }
650
651 network_opponent_name = malloc(packet_in[0]->len - 12 + 1);
652 strcpy(network_opponent_name, (char *)&packet_in[0]->data[12]);
653
654 network_update();
655
656 // until opponent has acknowledged
657 while (!network_is_sync())
658 {
659 service_SDL_events(false);
660
661 // got a duplicate packet; process it again (but why?)
662 if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_CONNECT)
663 goto connect_again;
664
665 network_check();
666
667 // maybe opponent didn't get our packet
668 if (SDL_GetTicks() - last_out_tick > NET_RETRY)
669 goto connect_reset;
670
671 SDL_Delay(16);
672 }
673
674 // send another packet since sometimes the network syncs without both connect packets exchanged
675 // there should be a better way to handle this
676 network_prepare(PACKET_CONNECT);
677 SDLNet_Write16(NET_VERSION, &packet_out_temp->data[4]);
678 SDLNet_Write16(network_delay, &packet_out_temp->data[6]);
679 SDLNet_Write16(episodes_local, &packet_out_temp->data[8]);
680 SDLNet_Write16(thisPlayerNum, &packet_out_temp->data[10]);
681 strcpy((char *)&packet_out_temp->data[12], network_player_name);
682 network_send(12 + strlen(network_player_name) + 1); // PACKET_CONNECT
683
684 connected = true;
685
686 return 0;
687 }
688
689 // something has gone wrong :(
network_tyrian_halt(unsigned int err,bool attempt_sync)690 void network_tyrian_halt( unsigned int err, bool attempt_sync )
691 {
692 const char *err_msg[] = {
693 "Quitting...",
694 "Other player quit the game.",
695 "Network connection was lost.",
696 "Network connection failed.",
697 "Network version mismatch.",
698 "Network delay mismatch.",
699 "Network player number conflict.",
700 };
701
702 quit = true;
703
704 if (err >= COUNTOF(err_msg))
705 err = 0;
706
707 fade_black(10);
708
709 VGAScreen = VGAScreenSeg;
710
711 JE_loadPic(VGAScreen, 2, false);
712 JE_dString(VGAScreen, JE_fontCenter(err_msg[err], SMALL_FONT_SHAPES), 140, err_msg[err], SMALL_FONT_SHAPES);
713
714 JE_showVGA();
715 fade_palette(colors, 10, 0, 255);
716
717 if (attempt_sync)
718 {
719 while (!network_is_sync() && network_is_alive())
720 {
721 service_SDL_events(false);
722
723 network_check();
724 SDL_Delay(16);
725 }
726 }
727
728 if (err)
729 {
730 while (!JE_anyButton())
731 SDL_Delay(16);
732 }
733
734 fade_black(10);
735
736 SDLNet_Quit();
737
738 JE_tyrianHalt(5);
739 }
740
network_init(void)741 int network_init( void )
742 {
743 printf("Initializing network...\n");
744
745 if (network_delay * 2 > NET_PACKET_QUEUE - 2)
746 {
747 fprintf(stderr, "error: network delay would overflow packet queue\n");
748 return -4;
749 }
750
751 if (SDLNet_Init() == -1)
752 {
753 fprintf(stderr, "error: SDLNet_Init: %s\n", SDLNet_GetError());
754 return -1;
755 }
756
757 socket = SDLNet_UDP_Open(network_player_port);
758 if (!socket)
759 {
760 fprintf(stderr, "error: SDLNet_UDP_Open: %s\n", SDLNet_GetError());
761 return -2;
762 }
763
764 packet_temp = SDLNet_AllocPacket(NET_PACKET_SIZE);
765 packet_out_temp = SDLNet_AllocPacket(NET_PACKET_SIZE);
766
767 if (!packet_temp || !packet_out_temp)
768 {
769 printf("SDLNet_AllocPacket: %s\n", SDLNet_GetError());
770 return -3;
771 }
772
773 net_initialized = true;
774
775 return 0;
776 }
777
778 #endif
779
JE_clearSpecialRequests(void)780 void JE_clearSpecialRequests( void )
781 {
782 pauseRequest = false;
783 inGameMenuRequest = false;
784 skipLevelRequest = false;
785 helpRequest = false;
786 nortShipRequest = false;
787 }
788
789