1 /* $Id: network.c,v 1.17 2003/02/28 03:54:55 btb Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14 
15 #ifdef HAVE_CONFIG_H
16 #include <conf.h>
17 #endif
18 
19 #ifdef RCS
20 static char rcsid[] = "$Id: network.c,v 1.17 2003/02/28 03:54:55 btb Exp $";
21 #endif
22 
23 #define PATCH12
24 
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 
29 #include "pstypes.h"
30 #include "strutil.h"
31 #include "args.h"
32 #include "timer.h"
33 #include "mono.h"
34 #include "ipx.h"
35 #include "newmenu.h"
36 #include "key.h"
37 #include "gauges.h"
38 #include "object.h"
39 #include "error.h"
40 #include "laser.h"
41 #include "gamesave.h"
42 #include "gamemine.h"
43 #include "player.h"
44 #include "gameseq.h"
45 #include "fireball.h"
46 #include "network.h"
47 #include "game.h"
48 #include "multi.h"
49 #include "endlevel.h"
50 #include "palette.h"
51 #include "cntrlcen.h"
52 #include "powerup.h"
53 #include "menu.h"
54 #include "sounds.h"
55 #include "text.h"
56 #include "kmatrix.h"
57 #include "newdemo.h"
58 #include "multibot.h"
59 #include "wall.h"
60 #include "bm.h"
61 #include "effects.h"
62 #include "physics.h"
63 #include "switch.h"
64 #include "automap.h"
65 #include "byteswap.h"
66 #include "netmisc.h"
67 #include "kconfig.h"
68 #include "playsave.h"
69 #include "cfile.h"
70 
71 #ifdef MACINTOSH
72 #include <Events.h>
73 #include <Errors.h>     // for appletalk networking errors
74 #include "appltalk.h"
75 #endif
76 
77 #define LHX(x)          ((x)*(MenuHires?2:1))
78 #define LHY(y)          ((y)*(MenuHires?2.4:1))
79 
80 #define PID_LITE_INFO           43
81 #define PID_SEND_ALL_GAMEINFO   44
82 #define PID_PLAYERSINFO         45
83 #define PID_REQUEST             46
84 #define PID_SYNC                47
85 #define PID_PDATA               48
86 #define PID_ADDPLAYER           49
87 #define PID_DUMP                51
88 #define PID_ENDLEVEL            52
89 #define PID_QUIT_JOINING        54
90 #define PID_OBJECT_DATA         55
91 #define PID_GAME_LIST           56
92 #define PID_GAME_INFO           57
93 #define PID_PING_SEND           58
94 #define PID_PING_RETURN         59
95 #define PID_GAME_UPDATE         60
96 #define PID_ENDLEVEL_SHORT      61
97 #define PID_NAKED_PDATA         62
98 #define PID_GAME_PLAYERS        63
99 #define PID_NAMES_RETURN        64
100 
101 #define NETGAME_ANARCHY         0
102 #define NETGAME_TEAM_ANARCHY    1
103 #define NETGAME_ROBOT_ANARCHY   2
104 #define NETGAME_COOPERATIVE     3
105 #define NETGAME_CAPTURE_FLAG    4
106 #define NETGAME_HOARD           5
107 #define NETGAME_TEAM_HOARD      6
108 
109 #define NETSECURITY_OFF                 0
110 #define NETSECURITY_WAIT_FOR_PLAYERS    1
111 #define NETSECURITY_WAIT_FOR_GAMEINFO   2
112 #define NETSECURITY_WAIT_FOR_SYNC       3
113 
114 // MWA -- these structures are aligned -- please save me sanity and
115 // headaches by keeping alignment if these are changed!!!!  Contact
116 // me for info.
117 
118 typedef struct endlevel_info {
119 	ubyte                               type;
120 	ubyte                               player_num;
121 	byte                                connected;
122 	ubyte                               seconds_left;
123 	short                               kill_matrix[MAX_PLAYERS][MAX_PLAYERS];
124 	short                               kills;
125 	short                               killed;
126 } endlevel_info;
127 
128 typedef struct endlevel_info_short {
129 	ubyte                               type;
130 	ubyte                               player_num;
131 	byte                                connected;
132 	ubyte                               seconds_left;
133 } endlevel_info_short;
134 
135 // WARNING!!! This is the top part of netgame_info...if that struct changes,
136 //      this struct much change as well.  ie...they are aligned and the join system will
137 // not work without it.
138 
139 // MWA  if this structure changes -- please make appropriate changes to receive_netgame_info
140 // code for macintosh in netmisc.c
141 
142 typedef struct lite_info {
143 	ubyte                           type;
144 	int                             Security;
145 	char                            game_name[NETGAME_NAME_LEN+1];
146 	char                            mission_title[MISSION_NAME_LEN+1];
147 	char                            mission_name[9];
148 	int                             levelnum;
149 	ubyte                           gamemode;
150 	ubyte                           RefusePlayers;
151 	ubyte                           difficulty;
152 	ubyte                           game_status;
153 	ubyte                           numplayers;
154 	ubyte                           max_numplayers;
155 	ubyte                           numconnected;
156 	ubyte                           game_flags;
157 	ubyte                           protocol_version;
158 	ubyte                           version_major;
159 	ubyte                           version_minor;
160 	ubyte                           team_vector;
161 } __pack__ lite_info;
162 
163 // IF YOU CHANGE THE SIZE OF ANY OF THE FOLLOWING STRUCTURES
164 // MAKE THE MACINTOSH DEFINES BE THE SAME SIZE AS THE PC OR
165 // I WILL HAVE TO HURT YOU VERY BADLY!!!  -- MWA
166 
167 #ifdef MACINTOSH
168 #define NETGAME_INFO_SIZE       ( Network_game_type == IPX_GAME?355:sizeof(netgame_info) )
169 #define ALLNETPLAYERSINFO_SIZE  ( Network_game_type == IPX_GAME?317:sizeof(AllNetPlayers_info) )
170 #define LITE_INFO_SIZE          ( Network_game_type == IPX_GAME?72:sizeof(lite_info) )
171 #define SEQUENCE_PACKET_SIZE    ( Network_game_type == IPX_GAME?34:sizeof(sequence_packet) )
172 #define FRAME_INFO_SIZE         ( Network_game_type == IPX_GAME?541:sizeof(frame_info) )
173 #define IPX_SHORT_INFO_SIZE     ( 490 )
174 #else
175 #define NETGAME_INFO_SIZE       sizeof(netgame_info)
176 #define ALLNETPLAYERSINFO_SIZE  sizeof(AllNetPlayers_info)
177 #define LITE_INFO_SIZE          sizeof(lite_info)
178 #define SEQUENCE_PACKET_SIZE    sizeof(sequence_packet)
179 #define FRAME_INFO_SIZE         sizeof(frame_info)
180 #define IPX_SHORT_INFO_SIZE     sizeof(short_frame_info)
181 #endif
182 
183 #define MAX_ACTIVE_NETGAMES     12
184 
185 netgame_info Active_games[MAX_ACTIVE_NETGAMES];
186 AllNetPlayers_info ActiveNetPlayers[MAX_ACTIVE_NETGAMES];
187 AllNetPlayers_info *TempPlayersInfo,TempPlayersBase;
188 int NamesInfoSecurity=-1;
189 
190 // MWAnetgame_info *TempNetInfo;
191 netgame_info TempNetInfo;
192 
193 extern void multi_send_drop_marker (int player,vms_vector position,char messagenum,char text[]);
194 extern void multi_send_kill_goal_counts();
195 extern int newmenu_dotiny( char * title, char * subtitle, int nitems, newmenu_item * item, void (*subfunction)(int nitems,newmenu_item * items, int * last_key, int citem) );
196 
197 void network_process_naked_pdata (char *,int);
198 extern void multi_send_robot_controls(char);
199 
200 void network_flush();
201 void network_listen();
202 void network_update_netgame();
203 void network_check_for_old_version(char pnum);
204 void network_send_objects();
205 void network_send_rejoin_sync(int player_num);
206 void network_send_game_info(sequence_packet *their);
207 void network_send_endlevel_short_sub(int from_player_num, int to_player);
208 void network_read_sync_packet(netgame_info * sp, int rsinit);
209 int  network_wait_for_playerinfo();
210 void network_process_pdata(char *data);
211 void network_read_object_packet(ubyte *data );
212 void network_read_endlevel_packet(ubyte *data );
213 void network_read_endlevel_short_packet(ubyte *data );
214 void network_ping(ubyte flat, int pnum);
215 void network_handle_ping_return(ubyte pnum);
216 void network_process_names_return(char *data);
217 void network_send_player_names(sequence_packet *their);
218 int  network_choose_connect();
219 void network_more_game_options();
220 void network_count_powerups_in_mine();
221 int  network_wait_for_all_info(int choice);
222 void network_AdjustMaxDataSize();
223 void network_do_big_wait(int choice);
224 void network_send_extras();
225 void network_read_pdata_packet(frame_info *pd);
226 void network_read_pdata_short_packet(short_frame_info *pd);
227 
228 void ClipRank(signed char *rank);
229 void DoRefuseStuff(sequence_packet *their);
230 int  GetNewPlayerNumber(sequence_packet *their);
231 void SetAllAllowablesTo(int on);
232 
233 int num_active_games = 0;
234 int PacketsPerSec=10;
235 int MaxXDataSize=NET_XDATA_SIZE;
236 
237 int     Netlife_kills=0, Netlife_killed=0;
238 
239 int     Network_debug=0;
240 int     Network_active=0;
241 
242 int     Network_status = 0;
243 int     Network_games_changed = 0;
244 
245 int     Network_socket = 0;
246 int     Network_allow_socket_changes = 1;
247 
248 int     NetSecurityFlag=NETSECURITY_OFF;
249 int     NetSecurityNum=0;
250 int     Network_sending_extras=0;
251 int     VerifyPlayerJoined=-1;
252 int     Player_joining_extras=-1;  // This is so we know who to send 'latecomer' packets to.
253 											  // We could just send updates to everyone but that kills the sender!
254 
255 // For rejoin object syncing
256 
257 int     Network_rejoined = 0;       // Did WE rejoin this game?
258 int     Network_new_game = 0;            // Is this the first level of a new game?
259 int     Network_send_objects = 0;  // Are we in the process of sending objects to a player?
260 int     Network_send_objnum = -1;   // What object are we sending next?
261 int     Network_player_added = 0;   // Is this a new player or a returning player?
262 int     Network_send_object_mode = 0; // What type of objects are we sending, static or dynamic?
263 sequence_packet Network_player_rejoining; // Who is rejoining now?
264 
265 fix     LastPacketTime[MAX_PLAYERS]; // For timeouts of idle/crashed players
266 
267 int     PacketUrgent = 0;
268 int     NetGameType=0;
269 int     TotalMissedPackets=0,TotalPacketsGot=0;
270 
271 frame_info      MySyncPack,UrgentSyncPack;
272 ubyte           MySyncPackInitialized = 0;              // Set to 1 if the MySyncPack is zeroed.
273 ushort          my_segments_checksum = 0;
274 
275 sequence_packet My_Seq;
276 char WantPlayersInfo=0;
277 char WaitingForPlayerInfo=0;
278 
279 char *RankStrings[]={"(unpatched) ","Cadet ","Ensign ","Lieutenant ","Lt.Commander ",
280 								"Commander ","Captain ","Vice Admiral ","Admiral ","Demigod "};
281 
282 extern obj_position Player_init[MAX_PLAYERS];
283 
284 extern int force_cockpit_redraw;
285 
286 #define DUMP_CLOSED     0
287 #define DUMP_FULL       1
288 #define DUMP_ENDLEVEL   2
289 #define DUMP_DORK       3
290 #define DUMP_ABORTED    4
291 #define DUMP_CONNECTED  5
292 #define DUMP_LEVEL      6
293 #define DUMP_KICKED     7
294 
295 extern ubyte Version_major,Version_minor;
296 extern ubyte SurfingNet;
297 extern char MaxPowerupsAllowed[MAX_POWERUP_TYPES];
298 extern char PowerupsInMine[MAX_POWERUP_TYPES];
299 
300 extern void multi_send_stolen_items();
301 
302 int network_wait_for_snyc();
303 extern void multi_send_wall_status (int,ubyte,ubyte,ubyte);
304 extern void multi_send_wall_status_specific (int,int,ubyte,ubyte,ubyte);
305 
306 extern void game_disable_cheats();
307 
308 char IWasKicked=0;
309 FILE *SendLogFile,*RecieveLogFile;
310 int TTSent[100],TTRecv[100];
311 
312 extern int Final_boss_is_dead;
313 
314 // following is network stuff for appletalk
315 
316 void network_dump_appletalk_player(ubyte node, ushort net, ubyte socket, int why);
317 
318 #define NETWORK_OEM 0x10
319 
320 #ifdef MACINTOSH
321 
322 int Network_game_type;                                  // used to tell IPX vs. appletalk games
323 
324 #define MAX_ZONES               255
325 #define MAX_ZONE_LENGTH         33
326 #define DEFAULT_ZONE_NAME       "\p*"
327 #define MAX_REGISTER_TRIES      5                                       // maximum time we will try and register a netgame
328 char Network_zone_name[MAX_ZONE_LENGTH];                // zone name game being played in for appletalk
329 char Zone_names[MAX_ZONES][MAX_ZONE_LENGTH];    // total list of zones that we can see
330 ubyte appletalk_use_broadcast = 0;
331 ubyte Network_game_validated = 0;               // validates a game before being able to join
332 ubyte Network_game_validate_choice = 0;
333 ubyte Network_appletalk_type = 0;               // type of appletalk network game is being played on
334 
335 #define ETHERTALK_TYPE  0
336 #define LOCALTALK_TYPE  1
337 #define OTHERTALK_TYPE  2
338 
339 
340 void network_release_registered_game(void);
341 
342 #endif
343 
344 void
network_init(void)345 network_init(void)
346 {
347 
348 	// So you want to play a netgame, eh?  Let's a get a few things
349 	// straight
350 
351    int t;
352 	int save_pnum = Player_num;
353 
354 	game_disable_cheats();
355    IWasKicked=0;
356    Final_boss_is_dead=0;
357    NamesInfoSecurity=-1;
358 
359 
360    #ifdef NETPROFILING
361 	   OpenSendLog();
362 		OpenRecieveLog();
363 	#endif
364 
365 	for (t=0;t<MAX_POWERUP_TYPES;t++)
366 		{
367 			MaxPowerupsAllowed[t]=0;
368 			PowerupsInMine[t]=0;
369 		}
370 
371    TotalMissedPackets=0; TotalPacketsGot=0;
372 
373 	memset(&Netgame, 0, sizeof(netgame_info));
374 	memset(&NetPlayers,0,sizeof(AllNetPlayers_info));
375 	memset(&My_Seq, 0, sizeof(sequence_packet));
376 	My_Seq.type = PID_REQUEST;
377 	memcpy(My_Seq.player.callsign, Players[Player_num].callsign, CALLSIGN_LEN+1);
378 
379    #if defined (D2_OEM)
380 	   Version_minor|=NETWORK_OEM;
381 	#endif
382 
383 	My_Seq.player.version_major=Version_major;
384 	My_Seq.player.version_minor=Version_minor;
385    My_Seq.player.rank=GetMyNetRanking();
386 
387 	if (Network_game_type == IPX_GAME) {
388 		memcpy(My_Seq.player.network.ipx.node, ipx_get_my_local_address(), 6);
389 		memcpy(My_Seq.player.network.ipx.server, ipx_get_my_server_address(), 4 );
390 	#ifdef MACINTOSH
391 	} else {
392 		My_Seq.player.network.appletalk.node = appletalk_get_my_node();
393 		My_Seq.player.network.appletalk.net = appletalk_get_my_net();
394 		My_Seq.player.network.appletalk.socket = appletalk_get_my_socket();
395 	#endif
396 	}
397 #ifdef MACINTOSH
398 	My_Seq.player.computer_type = MAC;
399 #else
400 	My_Seq.player.computer_type = DOS;
401 #endif
402 
403 	for (Player_num = 0; Player_num < MAX_NUM_NET_PLAYERS; Player_num++)
404 		init_player_stats_game();
405 
406 	Player_num = save_pnum;
407 	multi_new_game();
408 	Network_new_game = 1;
409 	Control_center_destroyed = 0;
410 	network_flush();
411 
412 	Netgame.PacketsPerSec=10;
413 
414    if ((t=FindArg("-packets")))
415     {
416      Netgame.PacketsPerSec=atoi(Args[t+1]);
417      if (Netgame.PacketsPerSec<1)
418       Netgame.PacketsPerSec=1;
419      else if (Netgame.PacketsPerSec>20)
420       Netgame.PacketsPerSec=20;
421      mprintf ((0,"Will send %d packets per second",Netgame.PacketsPerSec));
422     }
423    if (FindArg("-shortpackets"))
424     {
425      Netgame.ShortPackets=1;
426      mprintf ((0,"Will send short packets.\n"));
427     }
428 }
429 
430 int
network_i_am_master(void)431 network_i_am_master(void)
432 {
433 	// I am the lowest numbered player in this game?
434 
435 	int i;
436 
437 	if (!(Game_mode & GM_NETWORK))
438 		return (Player_num == 0);
439 
440 	for (i = 0; i < Player_num; i++)
441 		if (Players[i].connected)
442 			return 0;
443 	return 1;
444 }
445 int
network_who_is_master(void)446 network_who_is_master(void)
447 {
448 	// Who is the master of this game?
449 
450 	int i;
451 
452 	if (!(Game_mode & GM_NETWORK))
453 		return (Player_num == 0);
454 
455 	for (i = 0; i < N_players; i++)
456 		if (Players[i].connected)
457 			return i;
458 	return Player_num;
459 }
network_how_many_connected()460 int network_how_many_connected()
461  {
462   int num=0,i;
463 
464 	for (i = 0; i < N_players; i++)
465 		if (Players[i].connected)
466 			num++;
467    return (num);
468  }
469 
470 #define ENDLEVEL_SEND_INTERVAL  (F1_0*2)
471 #define ENDLEVEL_IDLE_TIME      (F1_0*20)
472 /*
473 void
474 network_endlevel_poll( int nitems, newmenu_item * menus, int * key, int citem )
475 {
476 	// Polling loop for End-of-level menu
477 
478 	static fix t1 = 0;
479 	int i = 0;
480 	int num_ready = 0;
481 	int num_escaped = 0;
482 	int goto_secret = 0;
483 
484 	int previous_state[MAX_NUM_NET_PLAYERS];
485 	int previous_seconds_left;
486 
487 	menus = menus;
488 	citem = citem;
489 	nitems = nitems;
490 	key = key;
491 
492 	// Send our endlevel packet at regular intervals
493 
494 	if (timer_get_approx_seconds() > (t1+ENDLEVEL_SEND_INTERVAL))
495 	{
496 		network_send_endlevel_packet();
497 		t1 = timer_get_approx_seconds();
498 	}
499 
500 	for (i = 0; i < N_players; i++)
501 		previous_state[i] = Players[i].connected;
502 
503 	previous_seconds_left = Countdown_seconds_left;
504 
505 	network_listen();
506 
507 	for (i = 0; i < N_players; i++)
508 	{
509 		if (Players[i].connected == 1)
510 		{
511 			// Check timeout for idle players
512 			if (timer_get_approx_seconds() > LastPacketTime[i]+ENDLEVEL_IDLE_TIME)
513 			{
514 				mprintf((0, "idle timeout for player %d.\n", i));
515 				Players[i].connected = 0;
516 				network_send_endlevel_sub(i);
517 			}
518 		}
519 
520 		if ((Players[i].connected != 1) && (Players[i].connected != 5) && (Players[i].connected != 6))
521 			num_ready++;
522 		if (Players[i].connected != 1)
523 			num_escaped++;
524 		if (Players[i].connected == 4)
525 			goto_secret = 1;
526 	}
527 
528 	if (num_escaped == N_players) // All players are out of the mine
529 	{
530 		Countdown_seconds_left = -1;
531 	}
532 
533 
534 	if (num_ready == N_players) // All players have checked in or are disconnected
535 	{
536 		if (goto_secret)
537 			*key = -3;
538 		else
539 			*key = -2;
540 	}
541 } */
542 
543 void
network_endlevel_poll2(int nitems,newmenu_item * menus,int * key,int citem)544 network_endlevel_poll2( int nitems, newmenu_item * menus, int * key, int citem )
545 {
546 	// Polling loop for End-of-level menu
547 
548 	static fix t1 = 0;
549 	int i = 0;
550 	int num_ready = 0;
551 	int goto_secret = 0;
552 
553 	menus = menus;
554 	citem = citem;
555 	nitems = nitems;
556 	key = key;
557 
558 	// Send our endlevel packet at regular intervals
559 
560 	if (timer_get_approx_seconds() > (t1+ENDLEVEL_SEND_INTERVAL))
561 	{
562 		network_send_endlevel_packet();
563 		t1 = timer_get_approx_seconds();
564 	}
565 
566 //   mprintf ((0,"Trying to listen!\n"));
567 	network_listen();
568 
569 	for (i = 0; i < N_players; i++)
570 	{
571 		if ((Players[i].connected != 1) && (Players[i].connected != 5) && (Players[i].connected != 6))
572 			num_ready++;
573 		if (Players[i].connected == 4)
574 			goto_secret = 1;
575 	}
576 
577 	if (num_ready == N_players) // All players have checked in or are disconnected
578 	{
579 		if (goto_secret)
580 			*key = -3;
581 		else
582 			*key = -2;
583 	}
584 }
585 
586 
587 extern fix StartAbortMenuTime;
588 
589 void
network_endlevel_poll3(int nitems,newmenu_item * menus,int * key,int citem)590 network_endlevel_poll3( int nitems, newmenu_item * menus, int * key, int citem )
591 {
592 	// Polling loop for End-of-level menu
593 
594    int num_ready=0,i;
595 
596 	menus = menus;
597 	citem = citem;
598 	nitems = nitems;
599 	key = key;
600 
601 	if (timer_get_approx_seconds() > (StartAbortMenuTime+(F1_0 * 8)))
602     *key=-2;
603 
604 
605 	network_listen();
606 
607 
608 	for (i = 0; i < N_players; i++)
609 		if ((Players[i].connected != 1) && (Players[i].connected != 5) && (Players[i].connected != 6))
610 			num_ready++;
611 
612 	if (num_ready == N_players) // All players have checked in or are disconnected
613 			*key = -2;
614 
615 }
616 
617 
618 int
network_endlevel(int * secret)619 network_endlevel(int *secret)
620 {
621 	// Do whatever needs to be done between levels
622 
623    int i;
624 
625    *secret=0;
626 
627 	//network_flush();
628 
629 	Network_status = NETSTAT_ENDLEVEL; // We are between levels
630 
631 	network_listen();
632 
633 	network_send_endlevel_packet();
634 
635 	for (i=0; i<N_players; i++)
636 	{
637 		LastPacketTime[i] = timer_get_approx_seconds();
638 	}
639 
640 	network_send_endlevel_packet();
641 	network_send_endlevel_packet();
642 	MySyncPackInitialized = 0;
643 
644 	network_update_netgame();
645 
646 	return(0);
647 }
648 
649 int
can_join_netgame(netgame_info * game,AllNetPlayers_info * people)650 can_join_netgame(netgame_info *game,AllNetPlayers_info *people)
651 {
652 	// Can this player rejoin a netgame in progress?
653 
654 	int i, num_players;
655 
656 	if (game->game_status == NETSTAT_STARTING)
657      return 1;
658 
659 	if (game->game_status != NETSTAT_PLAYING)
660     {
661       mprintf ((0,"Error: Can't join because game_status !=NETSTAT_PLAYING\n"));
662 		return 0;
663     }
664 
665    if (game->version_major==0 && Version_major>0)
666     {
667 	   mprintf ((0,"Error:Can't join because version majors don't match!\n"));
668 		return (0);
669     }
670 
671 	if (game->version_major>0 && Version_major==0)
672     {
673 	   mprintf ((0,"Error:Can't join because version majors2 don't match!\n"));
674 		return (0);
675     }
676 
677 	// Game is in progress, figure out if this guy can re-join it
678 
679 	num_players = game->numplayers;
680 
681 	if (!(game->game_flags & NETGAME_FLAG_CLOSED)) {
682 		// Look for player that is not connected
683 
684 		if (game->numconnected==game->max_numplayers)
685 		 return (2);
686 
687 //      mprintf ((0,"Refuse = %d\n",game->RefusePlayers));
688 
689 		if (game->RefusePlayers)
690 		 return (3);
691 
692 		if (game->numplayers < game->max_numplayers)
693 			return 1;
694 
695 		if (game->numconnected<num_players)
696 			return 1;
697 
698 	}
699 
700 	if (people==NULL)
701     {
702       mprintf ((0,"Error! Can't join because people==NULL!\n"));
703 		return 0;
704     }
705 
706 	// Search to see if we were already in this closed netgame in progress
707 
708 	for (i = 0; i < num_players; i++) {
709 		if (Network_game_type == IPX_GAME) {
710 			if ( (!stricmp(Players[Player_num].callsign, people->players[i].callsign)) &&
711 				  (!memcmp(My_Seq.player.network.ipx.node, people->players[i].network.ipx.node, 6)) &&
712 				  (!memcmp(My_Seq.player.network.ipx.server, people->players[i].network.ipx.server, 4)) )
713 				break;
714 		} else {
715 			if ( (!stricmp(Players[Player_num].callsign, people->players[i].callsign)) &&
716 				  (My_Seq.player.network.appletalk.node == people->players[i].network.appletalk.node) &&
717 				  (My_Seq.player.network.appletalk.net == people->players[i].network.appletalk.net) )
718 				break;
719 		}
720 	}
721 
722 	if (i != num_players)
723 		return 1;
724 
725    mprintf ((0,"Error: Can't join because at end of list!\n"));
726 	return 0;
727 }
728 
729 void
network_disconnect_player(int playernum)730 network_disconnect_player(int playernum)
731 {
732 	// A player has disconnected from the net game, take whatever steps are
733 	// necessary
734 
735 	if (playernum == Player_num)
736 	{
737 		Int3(); // Weird, see Rob
738 		return;
739 	}
740 
741 	Players[playernum].connected = 0;
742    NetPlayers.players[playernum].connected = 0;
743    if (VerifyPlayerJoined==playernum)
744 	  VerifyPlayerJoined=-1;
745 
746 //      create_player_appearance_effect(&Objects[Players[playernum].objnum]);
747 	multi_make_player_ghost(playernum);
748 
749 	if (Newdemo_state == ND_STATE_RECORDING)
750 		newdemo_record_multi_disconnect(playernum);
751 
752 	multi_strip_robots(playernum);
753 }
754 
755 void
network_new_player(sequence_packet * their)756 network_new_player(sequence_packet *their)
757 {
758 	int objnum;
759 	int pnum;
760 
761 	pnum = their->player.connected;
762 
763 	Assert(pnum >= 0);
764 	Assert(pnum < MaxNumNetPlayers);
765 
766 	objnum = Players[pnum].objnum;
767 
768 	if (Newdemo_state == ND_STATE_RECORDING) {
769 		int new_player;
770 
771 		if (pnum == N_players)
772 			new_player = 1;
773 		else
774 			new_player = 0;
775 		newdemo_record_multi_connect(pnum, new_player, their->player.callsign);
776 	}
777 
778 	memcpy(Players[pnum].callsign, their->player.callsign, CALLSIGN_LEN+1);
779 	memcpy(NetPlayers.players[pnum].callsign, their->player.callsign, CALLSIGN_LEN+1);
780 
781 
782    ClipRank (&their->player.rank);
783    NetPlayers.players[pnum].rank=their->player.rank;
784 	NetPlayers.players[pnum].version_major=their->player.version_major;
785 	NetPlayers.players[pnum].version_minor=their->player.version_minor;
786    network_check_for_old_version(pnum);
787 
788 	if (Network_game_type == IPX_GAME) {
789 		if ( (*(uint *)their->player.network.ipx.server) != 0 )
790 			ipx_get_local_target( their->player.network.ipx.server, their->player.network.ipx.node, Players[pnum].net_address );
791 		else
792 			memcpy(Players[pnum].net_address, their->player.network.ipx.node, 6);
793 
794 		memcpy(NetPlayers.players[pnum].network.ipx.node, their->player.network.ipx.node, 6);
795 		memcpy(NetPlayers.players[pnum].network.ipx.server, their->player.network.ipx.server, 4);
796 	} else {
797 		NetPlayers.players[pnum].network.appletalk.node = their->player.network.appletalk.node;
798 		NetPlayers.players[pnum].network.appletalk.net = their->player.network.appletalk.net;
799 		NetPlayers.players[pnum].network.appletalk.socket = their->player.network.appletalk.socket;
800 	}
801 
802 	Players[pnum].n_packets_got = 0;
803 	Players[pnum].connected = 1;
804 	Players[pnum].net_kills_total = 0;
805 	Players[pnum].net_killed_total = 0;
806 	memset(kill_matrix[pnum], 0, MAX_PLAYERS*sizeof(short));
807 	Players[pnum].score = 0;
808 	Players[pnum].flags = 0;
809 	Players[pnum].KillGoalCount=0;
810 
811 	if (pnum == N_players)
812 	{
813 		N_players++;
814 		Netgame.numplayers = N_players;
815 	}
816 
817 	digi_play_sample(SOUND_HUD_MESSAGE, F1_0);
818 
819    ClipRank (&their->player.rank);
820 
821    if (FindArg("-norankings"))
822 	  HUD_init_message("'%s' %s\n",their->player.callsign, TXT_JOINING);
823    else
824      HUD_init_message("%s'%s' %s\n",RankStrings[their->player.rank],their->player.callsign, TXT_JOINING);
825 
826 	multi_make_ghost_player(pnum);
827 
828 	multi_send_score();
829 	multi_sort_kill_list();
830 
831 //      create_player_appearance_effect(&Objects[objnum]);
832 }
833 
834 char RefuseThisPlayer=0,WaitForRefuseAnswer=0,RefuseTeam;
835 char RefusePlayerName[12];
836 fix RefuseTimeLimit=0;
837 
network_welcome_player(sequence_packet * their)838 void network_welcome_player(sequence_packet *their)
839 {
840 	// Add a player to a game already in progress
841 	ubyte local_address[6];
842 	int player_num;
843 	int i;
844 
845    WaitForRefuseAnswer=0;
846 
847 	if (FindArg("-NoMatrixCheat"))
848 	{
849 		if ((their->player.version_minor & 0x0F) < 3)
850 		{
851 					network_dump_player(their->player.network.ipx.server, their->player.network.ipx.node, DUMP_DORK);
852 					return;
853 		}
854 	}
855 
856 	if (HoardEquipped())
857 	{
858    // If hoard game, and this guy isn't D2 Christmas (v1.2), dump him
859 
860 	   if ((Game_mode & GM_HOARD) && ((their->player.version_minor & 0x0F)<2))
861 		{
862 			if (Network_game_type == IPX_GAME)
863 				network_dump_player(their->player.network.ipx.server, their->player.network.ipx.node, DUMP_DORK);
864 			#ifdef MACINTOSH
865 			else
866 				network_dump_appletalk_player(their->player.network.appletalk.node, their->player.network.appletalk.net, their->player.network.appletalk.socket, DUMP_DORK);
867 			#endif
868 			return;
869 		}
870 	}
871 
872 	// Don't accept new players if we're ending this level.  Its safe to
873 	// ignore since they'll request again later
874 
875 	if ((Endlevel_sequence) || (Control_center_destroyed))
876 	{
877 		mprintf((0, "Ignored request from new player to join during endgame.\n"));
878 		if (Network_game_type == IPX_GAME)
879 			network_dump_player(their->player.network.ipx.server,their->player.network.ipx.node, DUMP_ENDLEVEL);
880 		#ifdef MACINTOSH
881 		else
882 			network_dump_appletalk_player(their->player.network.appletalk.node, their->player.network.appletalk.net, their->player.network.appletalk.socket, DUMP_ENDLEVEL);
883 		#endif
884 		return;
885 	}
886 
887 	if (Network_send_objects || Network_sending_extras)
888 	{
889 		// Ignore silently, we're already responding to someone and we can't
890 		// do more than one person at a time.  If we don't dump them they will
891 		// re-request in a few seconds.
892 		return;
893 	}
894 
895 	if (their->player.connected != Current_level_num)
896 	{
897 		mprintf((0, "Dumping player due to old level number.\n"));
898 		if (Network_game_type == IPX_GAME)
899 			network_dump_player(their->player.network.ipx.server, their->player.network.ipx.node, DUMP_LEVEL);
900 		#ifdef MACINTOSH
901 		else
902 			network_dump_appletalk_player(their->player.network.appletalk.node, their->player.network.appletalk.net, their->player.network.appletalk.socket, DUMP_LEVEL);
903 		#endif
904 		return;
905 	}
906 
907 	player_num = -1;
908 	memset(&Network_player_rejoining, 0, sizeof(sequence_packet));
909 	Network_player_added = 0;
910 
911 	if (Network_game_type == IPX_GAME) {
912 		if ( (*(uint *)their->player.network.ipx.server) != 0 )
913 			ipx_get_local_target( their->player.network.ipx.server, their->player.network.ipx.node, local_address );
914 		else
915 			memcpy(local_address, their->player.network.ipx.node, 6);
916 	}
917 
918 	for (i = 0; i < N_players; i++)
919 	{
920 		if ( (Network_game_type == IPX_GAME) && (!stricmp(Players[i].callsign, their->player.callsign )) && (!memcmp(Players[i].net_address,local_address, 6)) )
921 		{
922 			player_num = i;
923 			break;
924 		}
925 #ifdef MACINTOSH                // note link to above if
926 			else if ( (!stricmp(Players[i].callsign, their->player.callsign)) &&
927 				    (NetPlayers.players[i].network.appletalk.node == their->player.network.appletalk.node) &&
928 					(NetPlayers.players[i].network.appletalk.net == their->player.network.appletalk.net)) {
929 			player_num = i;
930 			break;
931 		}
932 #endif
933 	}
934 
935 	if (player_num == -1)
936 	{
937 		// Player is new to this game
938 
939 		if ( !(Netgame.game_flags & NETGAME_FLAG_CLOSED) && (N_players < MaxNumNetPlayers))
940 		{
941 			// Add player in an open slot, game not full yet
942 
943 			player_num = N_players;
944 			Network_player_added = 1;
945 		}
946 		else if (Netgame.game_flags & NETGAME_FLAG_CLOSED)
947 		{
948 			// Slots are open but game is closed
949 
950 			if (Network_game_type == IPX_GAME)
951 				network_dump_player(their->player.network.ipx.server, their->player.network.ipx.node, DUMP_CLOSED);
952 			#ifdef MACINTOSH
953 			else
954 				network_dump_appletalk_player(their->player.network.appletalk.node, their->player.network.appletalk.net, their->player.network.appletalk.socket, DUMP_CLOSED);
955 			#endif
956 			return;
957 		}
958 		else
959 		{
960 			// Slots are full but game is open, see if anyone is
961 			// disconnected and replace the oldest player with this new one
962 
963 			int oldest_player = -1;
964 			fix oldest_time = timer_get_approx_seconds();
965 
966 			Assert(N_players == MaxNumNetPlayers);
967 
968 			for (i = 0; i < N_players; i++)
969 			{
970 				if ( (!Players[i].connected) && (LastPacketTime[i] < oldest_time))
971 				{
972 					oldest_time = LastPacketTime[i];
973 					oldest_player = i;
974 				}
975 			}
976 
977 			if (oldest_player == -1)
978 			{
979 				// Everyone is still connected
980 
981 				if (Network_game_type == IPX_GAME)
982 					network_dump_player(their->player.network.ipx.server, their->player.network.ipx.node, DUMP_FULL);
983 				#ifdef MACINTOSH
984 				else
985 					network_dump_appletalk_player(their->player.network.appletalk.node, their->player.network.appletalk.net, their->player.network.appletalk.socket, DUMP_FULL);
986 				#endif
987 				return;
988 			}
989 			else
990 			{
991 				// Found a slot!
992 
993 				player_num = oldest_player;
994 				Network_player_added = 1;
995 			}
996 		}
997 	}
998 	else
999 	{
1000 		// Player is reconnecting
1001 
1002 		if (Players[player_num].connected)
1003 		{
1004 			mprintf((0, "Extra REQUEST from player ignored.\n"));
1005 			return;
1006 		}
1007 
1008 		if (Newdemo_state == ND_STATE_RECORDING)
1009 			newdemo_record_multi_reconnect(player_num);
1010 
1011 		Network_player_added = 0;
1012 
1013 		digi_play_sample(SOUND_HUD_MESSAGE, F1_0);
1014 
1015 		if (FindArg("-norankings"))
1016 			HUD_init_message("'%s' %s", Players[player_num].callsign, TXT_REJOIN);
1017 		else
1018 			HUD_init_message("%s'%s' %s", RankStrings[NetPlayers.players[player_num].rank],Players[player_num].callsign, TXT_REJOIN);
1019 	}
1020 
1021 	Players[player_num].KillGoalCount=0;
1022 
1023 	// Send updated Objects data to the new/returning player
1024 
1025 
1026 	Network_player_rejoining = *their;
1027 	Network_player_rejoining.player.connected = player_num;
1028 	Network_send_objects = 1;
1029 	Network_send_objnum = -1;
1030 
1031 	network_send_objects();
1032 }
1033 
network_objnum_is_past(int objnum)1034 int network_objnum_is_past(int objnum)
1035 {
1036 	// determine whether or not a given object number has already been sent
1037 	// to a re-joining player.
1038 
1039 	int player_num = Network_player_rejoining.player.connected;
1040 	int obj_mode = !((object_owner[objnum] == -1) || (object_owner[objnum] == player_num));
1041 
1042 	if (!Network_send_objects)
1043 		return 0; // We're not sending objects to a new player
1044 
1045 	if (obj_mode > Network_send_object_mode)
1046 		return 0;
1047 	else if (obj_mode < Network_send_object_mode)
1048 		return 1;
1049 	else if (objnum < Network_send_objnum)
1050 		return 1;
1051 	else
1052 		return 0;
1053 }
1054 
1055 #define OBJ_PACKETS_PER_FRAME 1
1056 extern void multi_send_active_door(char);
1057 extern void multi_send_door_open_specific(int,int,int,ubyte);
1058 
1059 
network_send_door_updates(int pnum)1060 void network_send_door_updates(int pnum)
1061 {
1062 	// Send door status when new player joins
1063 
1064 	int i;
1065 
1066    pnum=pnum;
1067 
1068 //   Assert (pnum>-1 && pnum<N_players);
1069 
1070 	for (i = 0; i < Num_walls; i++)
1071 	{
1072       if ((Walls[i].type == WALL_DOOR) && ((Walls[i].state == WALL_DOOR_OPENING) || (Walls[i].state == WALL_DOOR_WAITING) || (Walls[i].state == WALL_DOOR_OPEN)))
1073 			multi_send_door_open_specific(pnum,Walls[i].segnum, Walls[i].sidenum,Walls[i].flags);
1074 		else if ((Walls[i].type == WALL_BLASTABLE) && (Walls[i].flags & WALL_BLASTED))
1075 			multi_send_door_open_specific(pnum,Walls[i].segnum, Walls[i].sidenum,Walls[i].flags);
1076 		else if ((Walls[i].type == WALL_BLASTABLE) && (Walls[i].hps != WALL_HPS))
1077 			multi_send_hostage_door_status(i);
1078 		else
1079 			multi_send_wall_status_specific(pnum,i,Walls[i].type,Walls[i].flags,Walls[i].state);
1080 	}
1081 }
1082 
1083 extern vms_vector MarkerPoint[];
network_send_markers()1084 void network_send_markers()
1085  {
1086   // send marker positions/text to new player
1087 
1088 
1089   int i;
1090 
1091   for (i=0;i<8;i++)
1092    {
1093     if (MarkerObject[(i*2)]!=-1)
1094      multi_send_drop_marker (i,MarkerPoint[(i*2)],0,MarkerMessage[i*2]);
1095     if (MarkerObject[(i*2)+1]!=-1)
1096      multi_send_drop_marker (i,MarkerPoint[(i*2)+1],1,MarkerMessage[(i*2)+1]);
1097    }
1098  }
1099 
network_process_monitor_vector(int vector)1100 void network_process_monitor_vector(int vector)
1101 {
1102 	int i, j;
1103 	int count = 0;
1104 	segment *seg;
1105 
1106 	for (i=0; i <= Highest_segment_index; i++)
1107 	{
1108 		int tm, ec, bm;
1109 		seg = &Segments[i];
1110 		for (j = 0; j < 6; j++)
1111 		{
1112 			if ( ((tm = seg->sides[j].tmap_num2) != 0) &&
1113 				  ((ec = TmapInfo[tm&0x3fff].eclip_num) != -1) &&
1114 				  ((bm = Effects[ec].dest_bm_num) != -1) )
1115 			{
1116 				if (vector & (1 << count))
1117 				{
1118 					seg->sides[j].tmap_num2 = bm | (tm&0xc000);
1119 				//      mprintf((0, "Monitor %d blown up.\n", count));
1120 				}
1121 				//else
1122 				  //    mprintf((0, "Monitor %d intact.\n", count));
1123 				count++;
1124 				Assert(count < 32);
1125 			}
1126 		}
1127 	}
1128 }
1129 
network_create_monitor_vector(void)1130 int network_create_monitor_vector(void)
1131 {
1132 	int i, j, k;
1133 	int num_blown_bitmaps = 0;
1134 	int monitor_num = 0;
1135 	#define NUM_BLOWN_BITMAPS 20
1136 	int blown_bitmaps[NUM_BLOWN_BITMAPS];
1137 	int vector = 0;
1138 	segment *seg;
1139 
1140 	for (i=0; i < Num_effects; i++)
1141 	{
1142 		if (Effects[i].dest_bm_num > 0) {
1143 			for (j = 0; j < num_blown_bitmaps; j++)
1144 				if (blown_bitmaps[j] == Effects[i].dest_bm_num)
1145 					break;
1146 			if (j == num_blown_bitmaps) {
1147 				blown_bitmaps[num_blown_bitmaps++] = Effects[i].dest_bm_num;
1148 				Assert(num_blown_bitmaps < NUM_BLOWN_BITMAPS);
1149 			}
1150 		}
1151 	}
1152 
1153 //	for (i = 0; i < num_blown_bitmaps; i++)
1154 //		mprintf((0, "Blown bitmap #%d = %d.\n", i, blown_bitmaps[i]));
1155 
1156 	for (i=0; i <= Highest_segment_index; i++)
1157 	{
1158 		int tm, ec;
1159 		seg = &Segments[i];
1160 		for (j = 0; j < 6; j++)
1161 		{
1162 			if ((tm = seg->sides[j].tmap_num2) != 0)
1163 			{
1164 				if ( ((ec = TmapInfo[tm&0x3fff].eclip_num) != -1) &&
1165 					  (Effects[ec].dest_bm_num != -1) )
1166 				{
1167 				//      mprintf((0, "Monitor %d intact.\n", monitor_num));
1168 					monitor_num++;
1169 					Assert(monitor_num < 32);
1170 				}
1171 				else
1172 				{
1173 					for (k = 0; k < num_blown_bitmaps; k++)
1174 					{
1175 						if ((tm&0x3fff) == blown_bitmaps[k])
1176 						{
1177 							//mprintf((0, "Monitor %d destroyed.\n", monitor_num));
1178 							vector |= (1 << monitor_num);
1179 							monitor_num++;
1180 							Assert(monitor_num < 32);
1181 							break;
1182 						}
1183 					}
1184 				}
1185 			}
1186 		}
1187 	}
1188   //	mprintf((0, "Final monitor vector %x.\n", vector));
1189 	return(vector);
1190 }
1191 
network_stop_resync(sequence_packet * their)1192 void network_stop_resync(sequence_packet *their)
1193 {
1194 	if (Network_game_type == IPX_GAME) {
1195 		if ( (!memcmp(Network_player_rejoining.player.network.ipx.node, their->player.network.ipx.node, 6)) &&
1196 			  (!memcmp(Network_player_rejoining.player.network.ipx.server, their->player.network.ipx.server, 4)) &&
1197 		     (!stricmp(Network_player_rejoining.player.callsign, their->player.callsign)) )
1198 		{
1199 			mprintf((0, "Aborting resync for player %s.\n", their->player.callsign));
1200 			Network_send_objects = 0;
1201 			Network_sending_extras=0;
1202 			Network_rejoined=0;
1203 			Player_joining_extras=-1;
1204 			Network_send_objnum = -1;
1205 		}
1206 	} else {
1207 		if ( (Network_player_rejoining.player.network.appletalk.node == their->player.network.appletalk.node) &&
1208 			 (Network_player_rejoining.player.network.appletalk.net == their->player.network.appletalk.net) &&
1209 			 (!stricmp(Network_player_rejoining.player.callsign, their->player.callsign)) )
1210 		{
1211 			mprintf((0, "Aborting resync for player %s.\n", their->player.callsign));
1212 			Network_send_objects = 0;
1213 			Network_sending_extras=0;
1214 			Network_rejoined=0;
1215 			Player_joining_extras=-1;
1216 			Network_send_objnum = -1;
1217 		}
1218 	}
1219 }
1220 
1221 byte object_buffer[IPX_MAX_DATA_SIZE];
1222 
network_send_objects(void)1223 void network_send_objects(void)
1224 {
1225 	short remote_objnum;
1226 	byte owner;
1227 	int loc, i, h;
1228 
1229 	static int obj_count = 0;
1230 	static int frame_num = 0;
1231 
1232 	int obj_count_frame = 0;
1233 	int player_num = Network_player_rejoining.player.connected;
1234 
1235 	// Send clear objects array trigger and send player num
1236 
1237 	Assert(Network_send_objects != 0);
1238 	Assert(player_num >= 0);
1239 	Assert(player_num < MaxNumNetPlayers);
1240 
1241 	if (Endlevel_sequence || Control_center_destroyed)
1242 	{
1243 		// Endlevel started before we finished sending the goods, we'll
1244 		// have to stop and try again after the level.
1245 
1246 		if (Network_game_type == IPX_GAME)
1247 			network_dump_player(Network_player_rejoining.player.network.ipx.server,Network_player_rejoining.player.network.ipx.node, DUMP_ENDLEVEL);
1248 		#ifdef MACINTOSH
1249 		else
1250 			network_dump_appletalk_player(Network_player_rejoining.player.network.appletalk.node,Network_player_rejoining.player.network.appletalk.net, Network_player_rejoining.player.network.appletalk.socket, DUMP_ENDLEVEL);
1251 		#endif
1252 		Network_send_objects = 0;
1253 		return;
1254 	}
1255 
1256 	for (h = 0; h < OBJ_PACKETS_PER_FRAME; h++) // Do more than 1 per frame, try to speed it up without
1257 															  // over-stressing the receiver.
1258 	{
1259 		obj_count_frame = 0;
1260 		memset(object_buffer, 0, IPX_MAX_DATA_SIZE);
1261 		object_buffer[0] = PID_OBJECT_DATA;
1262 		loc = 3;
1263 
1264 		if (Network_send_objnum == -1)
1265 		{
1266 			obj_count = 0;
1267 			Network_send_object_mode = 0;
1268 //       mprintf((0, "Sending object array to player %d.\n", player_num));
1269 			*(short *)(object_buffer+loc) = INTEL_SHORT(-1);            loc += 2;
1270 			object_buffer[loc] = player_num;                            loc += 1;
1271 			/* Placeholder for remote_objnum, not used here */          loc += 2;
1272 			Network_send_objnum = 0;
1273 			obj_count_frame = 1;
1274 			frame_num = 0;
1275 		}
1276 
1277 		for (i = Network_send_objnum; i <= Highest_object_index; i++)
1278 		{
1279 			if ((Objects[i].type != OBJ_POWERUP) && (Objects[i].type != OBJ_PLAYER) &&
1280 				 (Objects[i].type != OBJ_CNTRLCEN) && (Objects[i].type != OBJ_GHOST) &&
1281 				 (Objects[i].type != OBJ_ROBOT) && (Objects[i].type != OBJ_HOSTAGE) &&
1282 				 !(Objects[i].type==OBJ_WEAPON && Objects[i].id==PMINE_ID))
1283 				continue;
1284 			if ((Network_send_object_mode == 0) && ((object_owner[i] != -1) && (object_owner[i] != player_num)))
1285 				continue;
1286 			if ((Network_send_object_mode == 1) && ((object_owner[i] == -1) || (object_owner[i] == player_num)))
1287 				continue;
1288 
1289 			if ( ((IPX_MAX_DATA_SIZE-1) - loc) < (sizeof(object)+5) )
1290 				break; // Not enough room for another object
1291 
1292 			obj_count_frame++;
1293 			obj_count++;
1294 
1295 			remote_objnum = objnum_local_to_remote((short)i, &owner);
1296 			Assert(owner == object_owner[i]);
1297 
1298 			*(short *)(object_buffer+loc) = INTEL_SHORT((short)i);      loc += 2;
1299 			object_buffer[loc] = owner;                                 loc += 1;
1300 			*(short *)(object_buffer+loc) = INTEL_SHORT(remote_objnum); loc += 2;
1301 			memcpy(&object_buffer[loc], &Objects[i], sizeof(object));
1302 			if (Network_game_type == IPX_GAME)
1303 				swap_object((object *)&object_buffer[loc]);
1304 			loc += sizeof(object);
1305 //                      mprintf((0, "..packing object %d, remote %d\n", i, remote_objnum));
1306 		}
1307 
1308 		if (obj_count_frame) // Send any objects we've buffered
1309 		{
1310 			frame_num++;
1311 
1312 			Network_send_objnum = i;
1313 			object_buffer[1] = obj_count_frame;  object_buffer[2] = frame_num;
1314 //       mprintf((0, "Object packet %d contains %d objects.\n", frame_num, obj_count_frame));
1315 
1316 			Assert(loc <= IPX_MAX_DATA_SIZE);
1317 
1318 			if (Network_game_type == IPX_GAME)
1319 				ipx_send_internetwork_packet_data( object_buffer, loc, Network_player_rejoining.player.network.ipx.server, Network_player_rejoining.player.network.ipx.node );
1320 			#ifdef MACINTOSH
1321 			else
1322 				appletalk_send_packet_data( object_buffer, loc, Network_player_rejoining.player.network.appletalk.node,
1323 					Network_player_rejoining.player.network.appletalk.net,
1324 					Network_player_rejoining.player.network.appletalk.socket);
1325 			#endif
1326 
1327 			// OLD ipx_send_packet_data(object_buffer, loc, &Network_player_rejoining.player.node);
1328 		}
1329 
1330 		if (i > Highest_object_index)
1331 		{
1332 			if (Network_send_object_mode == 0)
1333 			{
1334 				Network_send_objnum = 0;
1335 				Network_send_object_mode = 1; // go to next mode
1336 			}
1337 			else
1338 			{
1339 				Assert(Network_send_object_mode == 1);
1340 
1341 				frame_num++;
1342 				// Send count so other side can make sure he got them all
1343 //                              mprintf((0, "Sending end marker in packet #%d.\n", frame_num));
1344 				mprintf((0, "Sent %d objects.\n", obj_count));
1345 				object_buffer[0] = PID_OBJECT_DATA;
1346 				object_buffer[1] = 1;
1347 				object_buffer[2] = frame_num;
1348 				*(short *)(object_buffer+3) = INTEL_SHORT(-2);
1349 				*(short *)(object_buffer+6) = INTEL_SHORT(obj_count);
1350 				//OLD ipx_send_packet_data(object_buffer, 8, &Network_player_rejoining.player.node);
1351 				if (Network_game_type == IPX_GAME)
1352 					ipx_send_internetwork_packet_data(object_buffer, 8, Network_player_rejoining.player.network.ipx.server, Network_player_rejoining.player.network.ipx.node);
1353 				#ifdef MACINTOSH
1354 				else
1355 					appletalk_send_packet_data( object_buffer, 8, Network_player_rejoining.player.network.appletalk.node,
1356 												Network_player_rejoining.player.network.appletalk.net,
1357 												Network_player_rejoining.player.network.appletalk.socket);
1358 				#endif
1359 
1360 
1361 				// Send sync packet which tells the player who he is and to start!
1362 				network_send_rejoin_sync(player_num);
1363 				mprintf ((0,"VerfiyPlayerJoined is now set to %d\n",player_num));
1364 				VerifyPlayerJoined=player_num;
1365 
1366 				// Turn off send object mode
1367 				Network_send_objnum = -1;
1368 				Network_send_objects = 0;
1369 				obj_count = 0;
1370 
1371 				//if (!network_i_am_master ())
1372 				// Int3();  // Bad!! Get Jason.  Someone goofy is trying to get ahold of the game!
1373 
1374 				Network_sending_extras=40; // start to send extras
1375 			   Player_joining_extras=player_num;
1376 
1377 				return;
1378 			} // mode == 1;
1379 		} // i > Highest_object_index
1380 	} // For PACKETS_PER_FRAME
1381 }
1382 
1383 extern void multi_send_powerup_update();
1384 
network_send_rejoin_sync(int player_num)1385 void network_send_rejoin_sync(int player_num)
1386 {
1387 	int i, j;
1388 
1389 	Players[player_num].connected = 1; // connect the new guy
1390 	LastPacketTime[player_num] = timer_get_approx_seconds();
1391 
1392 	if (Endlevel_sequence || Control_center_destroyed)
1393 	{
1394 		// Endlevel started before we finished sending the goods, we'll
1395 		// have to stop and try again after the level.
1396 
1397 		if (Network_game_type == IPX_GAME)
1398 			network_dump_player(Network_player_rejoining.player.network.ipx.server,Network_player_rejoining.player.network.ipx.node, DUMP_ENDLEVEL);
1399 		#ifdef MACINTOSH
1400 		else
1401 			network_dump_appletalk_player(Network_player_rejoining.player.network.appletalk.node,Network_player_rejoining.player.network.appletalk.net, Network_player_rejoining.player.network.appletalk.socket, DUMP_ENDLEVEL);
1402 		#endif
1403 		Network_send_objects = 0;
1404 		Network_sending_extras=0;
1405 		return;
1406 	}
1407 
1408 	if (Network_player_added)
1409 	{
1410 		Network_player_rejoining.type = PID_ADDPLAYER;
1411 		Network_player_rejoining.player.connected = player_num;
1412 		network_new_player(&Network_player_rejoining);
1413 
1414 		for (i = 0; i < N_players; i++)
1415 		{
1416 			if ((i != player_num) && (i != Player_num) && (Players[i].connected))
1417 				if (Network_game_type == IPX_GAME) {
1418 					send_sequence_packet( Network_player_rejoining, NetPlayers.players[i].network.ipx.server, NetPlayers.players[i].network.ipx.node, Players[i].net_address);
1419 				#ifdef MACINTOSH
1420 				} else {
1421 					appletalk_send_packet_data( (ubyte *)&Network_player_rejoining, sizeof(sequence_packet), NetPlayers.players[i].network.appletalk.node,
1422 												NetPlayers.players[i].network.appletalk.net, NetPlayers.players[i].network.appletalk.socket);
1423 				#endif
1424 				}
1425 		}
1426 	}
1427 
1428 	// Send sync packet to the new guy
1429 
1430 	network_update_netgame();
1431 
1432 	// Fill in the kill list
1433 	for (j=0; j<MAX_PLAYERS; j++)
1434 	{
1435 		for (i=0; i<MAX_PLAYERS;i++)
1436 			Netgame.kills[j][i] = kill_matrix[j][i];
1437 		Netgame.killed[j] = Players[j].net_killed_total;
1438 		Netgame.player_kills[j] = Players[j].net_kills_total;
1439 		Netgame.player_score[j] = Players[j].score;
1440 	}
1441 
1442 	Netgame.level_time = Players[Player_num].time_level;
1443 	Netgame.monitor_vector = network_create_monitor_vector();
1444 
1445 	mprintf((0, "Sending rejoin sync packet!!!\n"));
1446 
1447 	if (Network_game_type == IPX_GAME) {
1448 		send_internetwork_full_netgame_packet(Network_player_rejoining.player.network.ipx.server, Network_player_rejoining.player.network.ipx.node);
1449 		send_netplayers_packet(Network_player_rejoining.player.network.ipx.server, Network_player_rejoining.player.network.ipx.node);
1450 	#ifdef MACINTOSH
1451 	} else {
1452 		appletalk_send_packet_data( (ubyte *)&Netgame, sizeof(netgame_info), Network_player_rejoining.player.network.appletalk.node,
1453 									Network_player_rejoining.player.network.appletalk.net,
1454 									Network_player_rejoining.player.network.appletalk.socket);
1455 		appletalk_send_packet_data( (ubyte *)&NetPlayers, sizeof(AllNetPlayers_info), Network_player_rejoining.player.network.appletalk.node,
1456 									Network_player_rejoining.player.network.appletalk.net,
1457 									Network_player_rejoining.player.network.appletalk.socket);
1458 	#endif
1459 	}
1460 	return;
1461 }
resend_sync_due_to_packet_loss_for_allender()1462 void resend_sync_due_to_packet_loss_for_allender ()
1463 {
1464    int i,j;
1465 
1466    mprintf ((0,"I'm resending a sync packet! VPJ=%d\n",VerifyPlayerJoined));
1467 
1468 	network_update_netgame();
1469 
1470 	// Fill in the kill list
1471 	for (j=0; j<MAX_PLAYERS; j++)
1472 	{
1473 		for (i=0; i<MAX_PLAYERS;i++)
1474 			Netgame.kills[j][i] = kill_matrix[j][i];
1475 		Netgame.killed[j] = Players[j].net_killed_total;
1476 		Netgame.player_kills[j] = Players[j].net_kills_total;
1477 		Netgame.player_score[j] = Players[j].score;
1478 	}
1479 
1480 	Netgame.level_time = Players[Player_num].time_level;
1481 	Netgame.monitor_vector = network_create_monitor_vector();
1482 
1483 	if (Network_game_type == IPX_GAME) {
1484 		send_internetwork_full_netgame_packet(Network_player_rejoining.player.network.ipx.server, Network_player_rejoining.player.network.ipx.node);
1485 		send_netplayers_packet(Network_player_rejoining.player.network.ipx.server, Network_player_rejoining.player.network.ipx.node);
1486 	#ifdef MACINTOSH
1487 	} else {
1488 		appletalk_send_packet_data( (ubyte *)&Netgame, sizeof(netgame_info), Network_player_rejoining.player.network.appletalk.node,
1489 									Network_player_rejoining.player.network.appletalk.net,
1490 									Network_player_rejoining.player.network.appletalk.socket);
1491 		appletalk_send_packet_data( (ubyte *)&NetPlayers, sizeof(AllNetPlayers_info), Network_player_rejoining.player.network.appletalk.node,
1492 									Network_player_rejoining.player.network.appletalk.net,
1493 									Network_player_rejoining.player.network.appletalk.socket);
1494 	#endif
1495 	}
1496 }
1497 
1498 
network_get_player_name(int objnum)1499 char * network_get_player_name( int objnum )
1500 {
1501 	if ( objnum < 0 ) return NULL;
1502 	if ( Objects[objnum].type != OBJ_PLAYER ) return NULL;
1503 	if ( Objects[objnum].id >= MAX_PLAYERS ) return NULL;
1504 	if ( Objects[objnum].id >= N_players ) return NULL;
1505 
1506 	return Players[Objects[objnum].id].callsign;
1507 }
1508 
1509 
network_add_player(sequence_packet * p)1510 void network_add_player(sequence_packet *p)
1511 {
1512 	int i;
1513 
1514 	mprintf((0, "Got add player request!\n"));
1515 
1516 	for (i=0; i<N_players; i++ )    {
1517 		if (Network_game_type == IPX_GAME) {
1518 			if ( !memcmp( NetPlayers.players[i].network.ipx.node, p->player.network.ipx.node, 6) && !memcmp(NetPlayers.players[i].network.ipx.server, p->player.network.ipx.server, 4))
1519 				return;         // already got them
1520 		} else {
1521 			if ( (NetPlayers.players[i].network.appletalk.node == p->player.network.appletalk.node) &&
1522 				 (NetPlayers.players[i].network.appletalk.net == p->player.network.appletalk.net))
1523 					return;
1524 		}
1525 	}
1526 
1527 	if (Network_game_type == IPX_GAME) {
1528 		memcpy( NetPlayers.players[N_players].network.ipx.node, p->player.network.ipx.node, 6 );
1529 		memcpy( NetPlayers.players[N_players].network.ipx.server, p->player.network.ipx.server, 4 );
1530 	} else {
1531 		NetPlayers.players[N_players].network.appletalk.node = p->player.network.appletalk.node;
1532 		NetPlayers.players[N_players].network.appletalk.net = p->player.network.appletalk.net;
1533 		NetPlayers.players[N_players].network.appletalk.socket = p->player.network.appletalk.socket;
1534 	}
1535 
1536    ClipRank (&p->player.rank);
1537 
1538 	memcpy( NetPlayers.players[N_players].callsign, p->player.callsign, CALLSIGN_LEN+1 );
1539 	NetPlayers.players[N_players].version_major=p->player.version_major;
1540 	NetPlayers.players[N_players].version_minor=p->player.version_minor;
1541    NetPlayers.players[N_players].rank=p->player.rank;
1542 	NetPlayers.players[N_players].connected = 1;
1543    network_check_for_old_version (N_players);
1544 
1545 	Players[N_players].KillGoalCount=0;
1546 	Players[N_players].connected = 1;
1547 	LastPacketTime[N_players] = timer_get_approx_seconds();
1548 	N_players++;
1549 	Netgame.numplayers = N_players;
1550 
1551 	// Broadcast updated info
1552 
1553    mprintf ((0,"sending_game_info!\n"));
1554 	network_send_game_info(NULL);
1555 }
1556 
1557 // One of the players decided not to join the game
1558 
network_remove_player(sequence_packet * p)1559 void network_remove_player(sequence_packet *p)
1560 {
1561 	int i,pn;
1562 
1563 	pn = -1;
1564 	for (i=0; i<N_players; i++ )    {
1565 		if (Network_game_type == IPX_GAME) {
1566 			if (!memcmp(NetPlayers.players[i].network.ipx.node, p->player.network.ipx.node, 6) && !memcmp(NetPlayers.players[i].network.ipx.server, p->player.network.ipx.server, 4)) {
1567 				pn = i;
1568 				break;
1569 			}
1570 		} else {
1571 			if ( (NetPlayers.players[i].network.appletalk.node == p->player.network.appletalk.node) && (NetPlayers.players[i].network.appletalk.net == p->player.network.appletalk.net) ) {
1572 				pn = i;
1573 				break;
1574 			}
1575 		}
1576 	}
1577 
1578 	if (pn < 0 ) return;
1579 
1580 	for (i=pn; i<N_players-1; i++ ) {
1581 		if (Network_game_type == IPX_GAME) {
1582 			memcpy( NetPlayers.players[i].network.ipx.node, NetPlayers.players[i+1].network.ipx.node, 6 );
1583 			memcpy( NetPlayers.players[i].network.ipx.server, NetPlayers.players[i+1].network.ipx.server, 4 );
1584 		} else {
1585 			NetPlayers.players[i].network.appletalk.node = NetPlayers.players[i+1].network.appletalk.node;
1586 			NetPlayers.players[i].network.appletalk.net = NetPlayers.players[i+1].network.appletalk.net;
1587 			NetPlayers.players[i].network.appletalk.socket = NetPlayers.players[i+1].network.appletalk.socket;
1588 		}
1589 		memcpy( NetPlayers.players[i].callsign, NetPlayers.players[i+1].callsign, CALLSIGN_LEN+1 );
1590 		NetPlayers.players[i].version_major=NetPlayers.players[i+1].version_major;
1591 		NetPlayers.players[i].version_minor=NetPlayers.players[i+1].version_minor;
1592 
1593 	   NetPlayers.players[i].rank=NetPlayers.players[i+1].rank;
1594  		ClipRank (&NetPlayers.players[i].rank);
1595 	   network_check_for_old_version(i);
1596 	}
1597 
1598 	N_players--;
1599 	Netgame.numplayers = N_players;
1600 
1601 	// Broadcast new info
1602 
1603 	network_send_game_info(NULL);
1604 
1605 }
1606 
1607 void
network_dump_player(ubyte * server,ubyte * node,int why)1608 network_dump_player(ubyte * server, ubyte *node, int why)
1609 {
1610 	// Inform player that he was not chosen for the netgame
1611 
1612 	sequence_packet temp;
1613 
1614 	temp.type = PID_DUMP;
1615 	memcpy(temp.player.callsign, Players[Player_num].callsign, CALLSIGN_LEN+1);
1616 	temp.player.connected = why;
1617 	if (Network_game_type == IPX_GAME) {
1618 		send_internetwork_sequence_packet(temp, server, node);
1619 	} else {
1620 		Int3();
1621 	}
1622 }
1623 
1624 #ifdef MACINTOSH
network_dump_appletalk_player(ubyte node,ushort net,ubyte socket,int why)1625 void network_dump_appletalk_player(ubyte node, ushort net, ubyte socket, int why)
1626 {
1627 	sequence_packet temp;
1628 
1629 	temp.type = PID_DUMP;
1630 	memcpy(temp.player.callsign, Players[Player_num].callsign, CALLSIGN_LEN+1);
1631 	temp.player.connected = why;
1632 	if (Network_game_type == APPLETALK_GAME) {
1633 		appletalk_send_packet_data( (ubyte *)&temp, sizeof(sequence_packet), node, net, socket );
1634 	} else {
1635 		Int3();
1636 	}
1637 }
1638 #endif
1639 
1640 void
network_send_game_list_request()1641 network_send_game_list_request()
1642 {
1643 	// Send a broadcast request for game info
1644 
1645 	sequence_packet me;
1646 
1647 	mprintf((0, "Sending game_list request.\n"));
1648 	me.type = PID_GAME_LIST;
1649 	memcpy( me.player.callsign, Players[Player_num].callsign, CALLSIGN_LEN+1 );
1650 
1651 	if (Network_game_type == IPX_GAME) {
1652 		memcpy( me.player.network.ipx.node, ipx_get_my_local_address(), 6 );
1653 		memcpy( me.player.network.ipx.server, ipx_get_my_server_address(), 4 );
1654 
1655 		send_broadcast_sequence_packet(me);
1656 	#ifdef MACINTOSH
1657 	} else {
1658 		me.player.network.appletalk.node = appletalk_get_my_node();
1659 		me.player.network.appletalk.net = appletalk_get_my_net();
1660 		me.player.network.appletalk.socket = appletalk_get_my_socket();
1661 		appletalk_send_game_info( (ubyte *)&me, sizeof(sequence_packet), Network_zone_name );
1662 	#endif
1663 	}
1664 }
1665 
network_send_all_info_request(char type,int which_security)1666 void network_send_all_info_request(char type,int which_security)
1667 {
1668 	// Send a broadcast request for game info
1669 
1670 	sequence_packet me;
1671 
1672 	mprintf((0, "Sending all_info request.\n"));
1673 
1674 	me.Security=which_security;
1675 	me.type = type;
1676 	memcpy( me.player.callsign, Players[Player_num].callsign, CALLSIGN_LEN+1 );
1677 
1678 	if (Network_game_type == IPX_GAME) {
1679 		memcpy( me.player.network.ipx.node, ipx_get_my_local_address(), 6 );
1680 		memcpy( me.player.network.ipx.server, ipx_get_my_server_address(), 4 );
1681 
1682 		send_broadcast_sequence_packet(me);
1683 	#ifdef MACINTOSH
1684 	} else {
1685 		me.player.network.appletalk.node = appletalk_get_my_node();
1686 		me.player.network.appletalk.net = appletalk_get_my_net();
1687 		me.player.network.appletalk.socket = appletalk_get_my_socket();
1688 		appletalk_send_game_info( (ubyte *)&me, sizeof(sequence_packet), Network_zone_name );
1689 	#endif
1690 	}
1691 }
1692 
1693 
1694 void
network_update_netgame(void)1695 network_update_netgame(void)
1696 {
1697 	// Update the netgame struct with current game variables
1698 
1699 	int i, j;
1700 
1701    Netgame.numconnected=0;
1702    for (i=0;i<N_players;i++)
1703 	 if (Players[i].connected)
1704 		Netgame.numconnected++;
1705 
1706 // This is great: D2 1.0 and 1.1 ignore upper part of the game_flags field of
1707 //	the lite_info struct when you're sitting on the join netgame screen.  We can
1708 //	"sneak" Hoard information into this field.  This is better than sending
1709 //	another packet that could be lost in transit.
1710 
1711 
1712 	if (HoardEquipped())
1713 	{
1714 		if (Game_mode & GM_HOARD)
1715 		{
1716 			Netgame.game_flags |=NETGAME_FLAG_HOARD;
1717 			if (Game_mode & GM_TEAM)
1718 				Netgame.game_flags |=NETGAME_FLAG_TEAM_HOARD;
1719 		}
1720 	}
1721 
1722 	if (Network_status == NETSTAT_STARTING)
1723 		return;
1724 
1725 	Netgame.numplayers = N_players;
1726 	Netgame.game_status = Network_status;
1727 	Netgame.max_numplayers = MaxNumNetPlayers;
1728 
1729 	for (i = 0; i < MAX_NUM_NET_PLAYERS; i++)
1730 	{
1731 		NetPlayers.players[i].connected = Players[i].connected;
1732 		for(j = 0; j < MAX_NUM_NET_PLAYERS; j++)
1733 			Netgame.kills[i][j] = kill_matrix[i][j];
1734 
1735 		Netgame.killed[i] = Players[i].net_killed_total;
1736 		Netgame.player_kills[i] = Players[i].net_kills_total;
1737 		Netgame.player_score[i] = Players[i].score;
1738 		Netgame.player_flags[i] = (Players[i].flags & (PLAYER_FLAGS_BLUE_KEY | PLAYER_FLAGS_RED_KEY | PLAYER_FLAGS_GOLD_KEY));
1739 	}
1740 	Netgame.team_kills[0] = team_kills[0];
1741 	Netgame.team_kills[1] = team_kills[1];
1742 	Netgame.levelnum = Current_level_num;
1743 
1744 
1745 }
1746 
1747 void
network_send_endlevel_sub(int player_num)1748 network_send_endlevel_sub(int player_num)
1749 {
1750 	endlevel_info end;
1751 	int i, j;
1752 
1753 	// Send an endlevel packet for a player
1754 	end.type                = PID_ENDLEVEL;
1755 	end.player_num = player_num;
1756 	end.connected   = Players[player_num].connected;
1757 	end.kills               = INTEL_SHORT(Players[player_num].net_kills_total);
1758 	end.killed              = INTEL_SHORT(Players[player_num].net_killed_total);
1759 	memcpy(end.kill_matrix, kill_matrix[player_num], MAX_PLAYERS*sizeof(short));
1760 #ifdef WORDS_BIGENDIAN
1761 	for (i = 0; i < MAX_PLAYERS; i++)
1762 		for (j = 0; j < MAX_PLAYERS; j++)
1763 			end.kill_matrix[i][j] = INTEL_SHORT(end.kill_matrix[i][j]);
1764 #else
1765 	j = j;          // to satisfy compiler
1766 #endif
1767 
1768 	if (Players[player_num].connected == 1) // Still playing
1769 	{
1770 		Assert(Control_center_destroyed);
1771 		end.seconds_left = Countdown_seconds_left;
1772 	}
1773 
1774 //      mprintf((0, "Sending endlevel packet.\n"));
1775 
1776 	for (i = 0; i < N_players; i++)
1777 	{
1778 		if ((i != Player_num) && (i!=player_num) && (Players[i].connected)) {
1779 		  if (Players[i].connected==1)
1780 			 network_send_endlevel_short_sub(player_num,i);
1781 		  else {
1782 			if (Network_game_type == IPX_GAME)
1783 				ipx_send_packet_data((ubyte *)&end, sizeof(endlevel_info), NetPlayers.players[i].network.ipx.server, NetPlayers.players[i].network.ipx.node,Players[i].net_address);
1784 			#ifdef MACINTOSH
1785 			else
1786 				appletalk_send_packet_data( (ubyte *)&end, sizeof(endlevel_info), NetPlayers.players[i].network.appletalk.node,
1787 											NetPlayers.players[i].network.appletalk.net,
1788 											NetPlayers.players[i].network.appletalk.socket);
1789 			#endif
1790 			}
1791 		}
1792 	}
1793 }
1794 
1795 void
network_send_endlevel_packet(void)1796 network_send_endlevel_packet(void)
1797 {
1798 	// Send an updated endlevel status to other hosts
1799 
1800 	network_send_endlevel_sub(Player_num);
1801 }
1802 
1803 
1804 void
network_send_endlevel_short_sub(int from_player_num,int to_player)1805 network_send_endlevel_short_sub(int from_player_num,int to_player)
1806 {
1807 	endlevel_info_short end;
1808 
1809 	// Send an endlevel packet for a player
1810 	end.type                = PID_ENDLEVEL_SHORT;
1811 	end.player_num = from_player_num;
1812 	end.connected   = Players[from_player_num].connected;
1813 	end.seconds_left = Countdown_seconds_left;
1814 
1815 
1816 	if (Players[from_player_num].connected == 1) // Still playing
1817 	{
1818 		Assert(Control_center_destroyed);
1819 	}
1820 
1821 	if ((to_player != Player_num) && (to_player!=from_player_num) && (Players[to_player].connected))
1822 	{
1823 		mprintf((0, "Sending short endlevel packet to %s.\n",Players[to_player].callsign));
1824 		if (Network_game_type == IPX_GAME)
1825 			ipx_send_packet_data((ubyte *)&end, sizeof(endlevel_info_short), NetPlayers.players[to_player].network.ipx.server, NetPlayers.players[to_player].network.ipx.node,Players[to_player].net_address);
1826 		#ifdef MACINTOSH
1827 		else
1828 			appletalk_send_packet_data( (ubyte *)&end, sizeof(endlevel_info_short), NetPlayers.players[to_player].network.appletalk.node,
1829 										NetPlayers.players[to_player].network.appletalk.net,
1830 										NetPlayers.players[to_player].network.appletalk.socket);
1831 		#endif
1832 	}
1833 }
1834 
1835 extern fix ThisLevelTime;
1836 
1837 void
network_send_game_info(sequence_packet * their)1838 network_send_game_info(sequence_packet *their)
1839 {
1840 	// Send game info to someone who requested it
1841 
1842 	char old_type, old_status;
1843    fix timevar;
1844    int i;
1845 
1846 	mprintf((0, "Sending game info.\n"));
1847 
1848 	network_update_netgame(); // Update the values in the netgame struct
1849 
1850 	old_type = Netgame.type;
1851 	old_status = Netgame.game_status;
1852 
1853 	Netgame.type = PID_GAME_INFO;
1854    NetPlayers.type = PID_PLAYERSINFO;
1855 
1856    NetPlayers.Security=Netgame.Security;
1857 	Netgame.version_major=Version_major;
1858 	Netgame.version_minor=Version_minor;
1859 
1860 	if (Endlevel_sequence || Control_center_destroyed)
1861 		Netgame.game_status = NETSTAT_ENDLEVEL;
1862 
1863 	if (Netgame.PlayTimeAllowed)
1864     {
1865 		timevar=i2f (Netgame.PlayTimeAllowed*5*60);
1866 		i=f2i(timevar-ThisLevelTime);
1867 		if (i<30)
1868 			Netgame.game_status=NETSTAT_ENDLEVEL;
1869 	}
1870 
1871 	if (!their) {
1872 		if (Network_game_type == IPX_GAME) {
1873 			send_broadcast_full_netgame_packet();
1874 			send_broadcast_netplayers_packet();
1875 		} // nothing to do for appletalk games I think....
1876 	} else {
1877 		if (Network_game_type == IPX_GAME) {
1878 			send_internetwork_full_netgame_packet(their->player.network.ipx.server, their->player.network.ipx.node);
1879 			send_netplayers_packet(their->player.network.ipx.server, their->player.network.ipx.node);
1880 		#ifdef MACINTOSH
1881 		} else {
1882 			appletalk_send_packet_data( (ubyte *)&Netgame, sizeof(netgame_info), their->player.network.appletalk.node,
1883 										their->player.network.appletalk.net, their->player.network.appletalk.socket );
1884 			appletalk_send_packet_data( (ubyte *)&NetPlayers, sizeof(AllNetPlayers_info), their->player.network.appletalk.node,
1885 										their->player.network.appletalk.net, their->player.network.appletalk.socket );
1886 		#endif
1887 		}
1888 	}
1889 
1890 	Netgame.type = old_type;
1891 	Netgame.game_status = old_status;
1892 }
1893 
network_send_lite_info(sequence_packet * their)1894 void network_send_lite_info(sequence_packet *their)
1895 {
1896 	// Send game info to someone who requested it
1897 
1898 	char old_type, old_status,oldstatus;
1899 
1900 	mprintf((0, "Sending lite game info.\n"));
1901 
1902 	network_update_netgame(); // Update the values in the netgame struct
1903 
1904 	old_type = Netgame.type;
1905 	old_status = Netgame.game_status;
1906 
1907 	Netgame.type = PID_LITE_INFO;
1908 
1909 	if (Endlevel_sequence || Control_center_destroyed)
1910 		Netgame.game_status = NETSTAT_ENDLEVEL;
1911 
1912 // If hoard mode, make this game look closed even if it isn't
1913    if (HoardEquipped())
1914 	{
1915 		if (Game_mode & GM_HOARD)
1916 		{
1917 			oldstatus=Netgame.game_status;
1918 			Netgame.game_status=NETSTAT_ENDLEVEL;
1919 			Netgame.gamemode=NETGAME_CAPTURE_FLAG;
1920 			if (oldstatus==NETSTAT_ENDLEVEL)
1921 				Netgame.game_flags|=NETGAME_FLAG_REALLY_ENDLEVEL;
1922 			if (oldstatus==NETSTAT_STARTING)
1923 				Netgame.game_flags|=NETGAME_FLAG_REALLY_FORMING;
1924 		}
1925 	}
1926 
1927 	if (!their) {
1928 		if (Network_game_type == IPX_GAME) {
1929 			send_broadcast_lite_netgame_packet();
1930 		}               // nothing to do for appletalk I think....
1931 	} else {
1932 		if (Network_game_type == IPX_GAME) {
1933 			send_internetwork_lite_netgame_packet(their->player.network.ipx.server, their->player.network.ipx.node);
1934 		#ifdef MACINTOSH
1935 		} else {
1936 			appletalk_send_packet_data( (ubyte *)&Netgame, sizeof(lite_info), their->player.network.appletalk.node,
1937 										their->player.network.appletalk.net, their->player.network.appletalk.socket );
1938 		#endif
1939 		}
1940 	}
1941 
1942 	//  Restore the pre-hoard mode
1943 	if (HoardEquipped())
1944 	{
1945 		if (Game_mode & GM_HOARD)
1946 		{
1947 			if (!(Game_mode & GM_TEAM))
1948  			   Netgame.gamemode=NETGAME_HOARD;
1949 			else
1950  			   Netgame.gamemode=NETGAME_TEAM_HOARD;
1951 			Netgame.game_flags&=~NETGAME_FLAG_REALLY_ENDLEVEL;
1952 			Netgame.game_flags&=~NETGAME_FLAG_REALLY_FORMING;
1953 			Netgame.game_flags&=~NETGAME_FLAG_TEAM_HOARD;
1954 		}
1955 	}
1956 
1957 	Netgame.type = old_type;
1958 	Netgame.game_status = old_status;
1959 
1960 }
1961 
network_send_netgame_update()1962 void network_send_netgame_update()
1963 {
1964 	// Send game info to someone who requested it
1965 
1966 	char old_type, old_status;
1967 	int i;
1968 
1969 	mprintf((0, "Sending updated game info.\n"));
1970 
1971 	network_update_netgame(); // Update the values in the netgame struct
1972 
1973 	old_type = Netgame.type;
1974 	old_status = Netgame.game_status;
1975 
1976 	Netgame.type = PID_GAME_UPDATE;
1977 
1978 	if (Endlevel_sequence || Control_center_destroyed)
1979 		Netgame.game_status = NETSTAT_ENDLEVEL;
1980 
1981 	for (i=0; i<N_players; i++ )    {
1982 		if ( (Players[i].connected) && (i!=Player_num ) )       {
1983 			if (Network_game_type == IPX_GAME) {
1984 				send_lite_netgame_packet(NetPlayers.players[i].network.ipx.server, NetPlayers.players[i].network.ipx.node, Players[i].net_address);
1985 			#ifdef MACINTOSH
1986 			} else {
1987 				appletalk_send_packet_data( (ubyte *)&Netgame, sizeof(lite_info), NetPlayers.players[i].network.appletalk.node,
1988 											NetPlayers.players[i].network.appletalk.net, NetPlayers.players[i].network.appletalk.socket );
1989 			#endif
1990 			}
1991 		}
1992 	}
1993 
1994 	Netgame.type = old_type;
1995 	Netgame.game_status = old_status;
1996 }
1997 
network_send_request(void)1998 int network_send_request(void)
1999 {
2000 	// Send a request to join a game 'Netgame'.  Returns 0 if we can join this
2001 	// game, non-zero if there is some problem.
2002 	int i;
2003 
2004 	if (Netgame.numplayers < 1)
2005 	 return 1;
2006 
2007 	for (i = 0; i < MAX_NUM_NET_PLAYERS; i++)
2008 	  if (NetPlayers.players[i].connected)
2009 	      break;
2010 
2011 	Assert(i < MAX_NUM_NET_PLAYERS);
2012 
2013 	mprintf((0, "Sending game enroll request to player %d (%s). Serv=%x Node=%x Level=%d\n", i, Players[i].callsign,NetPlayers.players[i].network.ipx.server,NetPlayers.players[i].network.ipx.node,Netgame.levelnum));
2014 
2015 //      segments_checksum = netmisc_calc_checksum( Segments, sizeof(segment)*(Highest_segment_index+1) );
2016 
2017 	My_Seq.type = PID_REQUEST;
2018 	My_Seq.player.connected = Current_level_num;
2019 
2020 	if (Network_game_type == IPX_GAME) {
2021 		send_internetwork_sequence_packet(My_Seq, NetPlayers.players[i].network.ipx.server, NetPlayers.players[i].network.ipx.node);
2022 	#ifdef MACINTOSH
2023 	} else {
2024 		appletalk_send_packet_data( (ubyte *)&My_Seq, sizeof(sequence_packet), NetPlayers.players[i].network.appletalk.node,
2025 									NetPlayers.players[i].network.appletalk.net,
2026 									NetPlayers.players[i].network.appletalk.socket);
2027 	#endif
2028 	}
2029 
2030 	return i;
2031 }
2032 
2033 int SecurityCheck=0;
2034 
network_process_gameinfo(ubyte * data)2035 void network_process_gameinfo(ubyte *data)
2036 {
2037 	int i, j;
2038 	netgame_info *new = (netgame_info *)data;
2039 #ifdef WORDS_BIGENDIAN
2040 	netgame_info tmp_info;
2041 
2042 	if (Network_game_type == IPX_GAME)  {
2043 		receive_netgame_packet(data, &tmp_info, 0);                     // get correctly aligned structure
2044 		new = &tmp_info;
2045 	}
2046 #endif
2047 
2048 
2049    WaitingForPlayerInfo=0;
2050 
2051    if (new->Security !=TempPlayersInfo->Security)
2052     {
2053      Int3();     // Get Jason
2054      return;     // If this first half doesn't go with the second half
2055     }
2056 
2057 	Network_games_changed = 1;
2058 
2059    //mprintf((0, "Got game data for game %s.\n", new->game_name));
2060 
2061    Assert (TempPlayersInfo!=NULL);
2062 
2063 	for (i = 0; i < num_active_games; i++)
2064 	 {
2065 	  //mprintf ((0,"GAMEINFO: Game %d is %s!\n",i,Active_games[i].game_name));
2066 
2067 	  if (!stricmp(Active_games[i].game_name, new->game_name) &&
2068 				  Active_games[i].Security==new->Security)
2069 	       break;
2070 	 }
2071 
2072 	if (i == MAX_ACTIVE_NETGAMES)
2073 	{
2074 		mprintf((0, "Too many netgames.\n"));
2075 		return;
2076 	}
2077 
2078 // MWA  memcpy(&Active_games[i], data, sizeof(netgame_info));
2079 	memcpy(&Active_games[i], (ubyte *)new, sizeof(netgame_info));
2080 	memcpy (&ActiveNetPlayers[i],TempPlayersInfo,sizeof(AllNetPlayers_info));
2081 
2082    if (SecurityCheck)
2083 	 if (Active_games[i].Security==SecurityCheck)
2084 		SecurityCheck=-1;
2085 
2086 	//mprintf ((0,"Recieved %d unique games...\n",i));
2087 
2088 	if (i == num_active_games)
2089 		num_active_games++;
2090 
2091 	if (Active_games[i].numplayers == 0)
2092 	{
2093 	 mprintf ((0,"DELETING THIS GAME!!!\n"));
2094 		// Delete this game
2095 		for (j = i; j < num_active_games-1; j++)
2096 	{
2097 	     memcpy(&Active_games[j], &Active_games[j+1], sizeof(netgame_info));
2098 	   memcpy (&ActiveNetPlayers[j],&ActiveNetPlayers[j+1],sizeof(AllNetPlayers_info));
2099 	}
2100 		num_active_games--;
2101 		SecurityCheck=0;
2102 	}
2103 }
2104 
network_process_lite_info(ubyte * data)2105 void network_process_lite_info(ubyte *data)
2106 {
2107 	int i, j;
2108 	lite_info *new = (lite_info *)data;
2109 #ifdef WORDS_BIGENDIAN
2110 	lite_info tmp_info;
2111 
2112 	if (Network_game_type == IPX_GAME) {
2113 		receive_netgame_packet(data, (netgame_info *)&tmp_info, 1);
2114 		new = &tmp_info;
2115 	}
2116 #endif
2117 
2118 	Network_games_changed = 1;
2119 
2120    //mprintf((0, "Got game data for game %s.\n", new->game_name));
2121 
2122 	for (i = 0; i < num_active_games; i++)
2123     {
2124       //mprintf ((0,"GAMEINFO: Game %d is %s!\n",i,Active_games[i].game_name));
2125 
2126       if ((!stricmp(Active_games[i].game_name, new->game_name)) &&
2127 			 Active_games[i].Security==new->Security)
2128 				break;
2129     }
2130 
2131 	if (i == MAX_ACTIVE_NETGAMES)
2132 	{
2133 		mprintf((0, "Too many netgames.\n"));
2134 		return;
2135 	}
2136 
2137 	memcpy(&Active_games[i], (ubyte *)new, sizeof(lite_info));
2138 
2139 // See if this is really a Hoard game
2140 // If so, adjust all the data accordingly
2141 
2142 	if (HoardEquipped())
2143 	{
2144 		if (Active_games[i].game_flags & NETGAME_FLAG_HOARD)
2145 		{
2146 			Active_games[i].gamemode=NETGAME_HOARD;
2147 			Active_games[i].game_status=NETSTAT_PLAYING;
2148 
2149 			if (Active_games[i].game_flags & NETGAME_FLAG_TEAM_HOARD)
2150 				Active_games[i].gamemode=NETGAME_TEAM_HOARD;
2151 			if (Active_games[i].game_flags & NETGAME_FLAG_REALLY_ENDLEVEL)
2152 				Active_games[i].game_status=NETSTAT_ENDLEVEL;
2153 			if (Active_games[i].game_flags & NETGAME_FLAG_REALLY_FORMING)
2154 				Active_games[i].game_status=NETSTAT_STARTING;
2155 		}
2156 	}
2157 
2158    //mprintf ((0,"Recieved %d unique games...\n",i));
2159 
2160 	if (i == num_active_games)
2161 		num_active_games++;
2162 
2163 	if (Active_games[i].numplayers == 0)
2164     {
2165 	   mprintf ((0,"DELETING THIS GAME!!!\n"));
2166 		// Delete this game
2167 		for (j = i; j < num_active_games-1; j++)
2168 	{
2169 	     memcpy(&Active_games[j], &Active_games[j+1], sizeof(netgame_info));
2170 	}
2171 		num_active_games--;
2172 	}
2173 }
2174 
network_process_dump(sequence_packet * their)2175 void network_process_dump(sequence_packet *their)
2176 {
2177 	// Our request for join was denied.  Tell the user why.
2178 
2179 	char temp[40];
2180 	int i;
2181 
2182 	mprintf((0, "Dumped by player %s, type %d.\n", their->player.callsign, their->player.connected));
2183 
2184    if (their->player.connected!=7)
2185 		nm_messagebox(NULL, 1, TXT_OK, NET_DUMP_STRINGS(their->player.connected));
2186 	else
2187 		{
2188 		 for (i=0;i<N_players;i++)
2189 			if (!stricmp (their->player.callsign,Players[i].callsign))
2190 			{
2191 				if (i!=network_who_is_master())
2192 				{
2193 					HUD_init_message ("%s attempted to kick you out.",their->player.callsign);
2194 				}
2195 				else
2196 				{
2197 				  sprintf (temp,"%s has kicked you out!",their->player.callsign);
2198 				  nm_messagebox(NULL, 1, TXT_OK, &temp);
2199 			    if (Network_status==NETSTAT_PLAYING)
2200 				  {
2201 					IWasKicked=1;
2202 					multi_leave_game();
2203 				  }
2204 				 else
2205 					Network_status = NETSTAT_MENU;
2206 		      }
2207 		   }
2208  		}
2209 }
network_process_request(sequence_packet * their)2210 void network_process_request(sequence_packet *their)
2211 {
2212 	// Player is ready to receieve a sync packet
2213 	int i;
2214 
2215 	mprintf((0, "Player %s ready for sync.\n", their->player.callsign));
2216 
2217 	for (i = 0; i < N_players; i++) {
2218 		if (Network_game_type == IPX_GAME) {
2219 			if (!memcmp(their->player.network.ipx.server, NetPlayers.players[i].network.ipx.server, 4) && !memcmp(their->player.network.ipx.node, NetPlayers.players[i].network.ipx.node, 6) && (!stricmp(their->player.callsign, NetPlayers.players[i].callsign))) {
2220 				Players[i].connected = 1;
2221 				break;
2222 			}
2223 		} else {
2224 			if ( (their->player.network.appletalk.node == NetPlayers.players[i].network.appletalk.node) && (their->player.network.appletalk.net == NetPlayers.players[i].network.appletalk.net) && (!stricmp(their->player.callsign, NetPlayers.players[i].callsign)) ) {
2225 				Players[i].connected = 1;
2226 				break;
2227 			}
2228 		}
2229 	}
2230 }
2231 
2232 #define REFUSE_INTERVAL F1_0 * 8
2233 extern void multi_reset_object_texture (object *);
2234 
network_process_packet(ubyte * data,int length)2235 void network_process_packet(ubyte *data, int length )
2236 {
2237 	sequence_packet *their = (sequence_packet *)data;
2238 #ifdef WORDS_BIGENDIAN
2239 	sequence_packet tmp_packet;
2240 
2241 	if (Network_game_type == IPX_GAME) {
2242 		receive_sequence_packet(data, &tmp_packet);
2243 		their = &tmp_packet;                                            // reassign their to point to correctly alinged structure
2244 	}
2245 #endif
2246 
2247    //mprintf( (0, "Got packet of length %d, type %d\n", length, their->type ));
2248 
2249 //      if ( length < sizeof(sequence_packet) ) return;
2250 
2251 	length = length;
2252 
2253 	switch( data[0] )       {
2254 
2255 	 case PID_GAME_INFO:		// Jason L. says we can safely ignore this type.
2256 	 	break;
2257 
2258      case PID_PLAYERSINFO:
2259 
2260 		mprintf ((0,"Got a PID_PLAYERSINFO!\n"));
2261 
2262 		if (Network_status==NETSTAT_WAITING)
2263 		{
2264 			if (Network_game_type == IPX_GAME)
2265 				receive_netplayers_packet(data, &TempPlayersBase);
2266 			else
2267 				memcpy (&TempPlayersBase,data,sizeof(AllNetPlayers_info));
2268 
2269 			if (TempPlayersBase.Security!=Netgame.Security)
2270 			 {
2271 			  mprintf ((0,"Bad security for PLAYERSINFO\n"));
2272 			  break;
2273 			 }
2274 
2275 			mprintf ((0,"Got a waiting PID_PLAYERSINFO!\n"));
2276 			if (length!=ALLNETPLAYERSINFO_SIZE)
2277 			{
2278 				mprintf ((0,"Invalid size for netplayers packet!\n"));
2279 				return;
2280 			}
2281 
2282 			TempPlayersInfo=&TempPlayersBase;
2283 			WaitingForPlayerInfo=0;
2284 			NetSecurityNum=TempPlayersInfo->Security;
2285 			NetSecurityFlag=NETSECURITY_WAIT_FOR_SYNC;
2286 	   }
2287 
2288      break;
2289 
2290    case PID_LITE_INFO:
2291 
2292 	 if (length != LITE_INFO_SIZE)
2293 		 {
2294 		  mprintf ((0,"WARNING! Recieved invalid size for PID_LITE_INFO\n"));
2295 		  return;
2296 		 }
2297 
2298 	 if (Network_status == NETSTAT_BROWSING)
2299 		network_process_lite_info (data);
2300     break;
2301 
2302 	case PID_GAME_LIST:
2303 		// Someone wants a list of games
2304 
2305 	   if (length != SEQUENCE_PACKET_SIZE)
2306 		 {
2307 		  mprintf ((0,"WARNING! Recieved invalid size for PID_GAME_LIST\n"));
2308 		  return;
2309 		 }
2310 
2311 		mprintf((0, "Got a PID_GAME_LIST!\n"));
2312 		if ((Network_status == NETSTAT_PLAYING) || (Network_status == NETSTAT_STARTING) || (Network_status == NETSTAT_ENDLEVEL))
2313 			if (network_i_am_master())
2314 				network_send_lite_info(their);
2315 		break;
2316 
2317 
2318 	case PID_SEND_ALL_GAMEINFO:
2319 
2320 	   if (length != SEQUENCE_PACKET_SIZE)
2321 		 {
2322 		  mprintf ((0,"WARNING! Recieved invalid size for PID_SEND_ALL_GAMEINFO\n"));
2323 		  return;
2324 		 }
2325 
2326 		if ((Network_status == NETSTAT_PLAYING) || (Network_status == NETSTAT_STARTING) || (Network_status == NETSTAT_ENDLEVEL))
2327 			if (network_i_am_master() && their->Security==Netgame.Security)
2328 				network_send_game_info(their);
2329 		break;
2330 
2331 	case PID_ADDPLAYER:
2332 
2333 		mprintf( (0, "Got NEWPLAYER message from %s.\n", their->player.callsign));
2334 
2335 	   if (length != SEQUENCE_PACKET_SIZE)
2336 		 {
2337 		  mprintf ((0,"WARNING! Recieved invalid size for PID_ADDPLAYER\n"));
2338 		  return;
2339 		 }
2340 		mprintf( (0, "Got NEWPLAYER message from %s.\n", their->player.callsign));
2341 		network_new_player(their);
2342 		break;
2343 	case PID_REQUEST:
2344 	   if (length != SEQUENCE_PACKET_SIZE)
2345 		 {
2346 		  mprintf ((0,"WARNING! Recieved invalid size for PID_REQUEST\n"));
2347 		  return;
2348 		 }
2349 
2350 		mprintf( (0, "Got REQUEST from '%s'\n", their->player.callsign ));
2351 		if (Network_status == NETSTAT_STARTING)
2352 		{
2353 			// Someone wants to join our game!
2354 			network_add_player(their);
2355 		}
2356 		else if (Network_status == NETSTAT_WAITING)
2357 		{
2358 			// Someone is ready to recieve a sync packet
2359 			network_process_request(their);
2360 		}
2361 		else if (Network_status == NETSTAT_PLAYING)
2362 		{
2363 			// Someone wants to join a game in progress!
2364 			if (Netgame.RefusePlayers)
2365 		DoRefuseStuff (their);
2366 		   else
2367 				network_welcome_player(their);
2368 		}
2369 		break;
2370 	case PID_DUMP:
2371 
2372 	   if (length != SEQUENCE_PACKET_SIZE)
2373 		 {
2374 		  mprintf ((0,"WARNING! Recieved invalid size for PID_DUMP\n"));
2375 		  return;
2376 		 }
2377 
2378 		if (Network_status == NETSTAT_WAITING || Network_status==NETSTAT_PLAYING )
2379 			network_process_dump(their);
2380 		break;
2381 	case PID_QUIT_JOINING:
2382 
2383 	   if (length != SEQUENCE_PACKET_SIZE)
2384 		 {
2385 		  mprintf ((0,"WARNING! Recieved invalid size for PID_QUIT_JOINING\n"));
2386 		  return;
2387 		 }
2388 		if (Network_status == NETSTAT_STARTING)
2389 			network_remove_player( their );
2390 		else if ((Network_status == NETSTAT_PLAYING) && (Network_send_objects))
2391 			network_stop_resync( their );
2392 		break;
2393 	case PID_SYNC:
2394 
2395 		mprintf ((0,"Got a sync packet! Network_status=%d\n",NETSTAT_WAITING));
2396 
2397 		if (Network_status == NETSTAT_WAITING)  {
2398 
2399 			if (Network_game_type == IPX_GAME)
2400 				receive_full_netgame_packet(data, &TempNetInfo);
2401 			else
2402 				memcpy((ubyte *)&(TempNetInfo), data, sizeof(netgame_info));
2403 
2404 			if (TempNetInfo.Security!=Netgame.Security)
2405 			 {
2406 				mprintf ((0,"Bad security on sync packet.\n"));
2407 				break;
2408 			 }
2409 
2410 			if (NetSecurityFlag==NETSECURITY_WAIT_FOR_SYNC)
2411 			 {
2412 			  if (TempNetInfo.Security==TempPlayersInfo->Security)
2413 			  {
2414 				network_read_sync_packet (&TempNetInfo,0);
2415 				NetSecurityFlag=0;
2416 				NetSecurityNum=0;
2417 			  }
2418 			 }
2419 			else
2420 			 {
2421 			NetSecurityFlag=NETSECURITY_WAIT_FOR_PLAYERS;
2422 			NetSecurityNum=TempNetInfo.Security;
2423 
2424 			if ( network_wait_for_playerinfo())
2425 				network_read_sync_packet((netgame_info *)data,0);
2426 
2427 			NetSecurityFlag=0;
2428 			NetSecurityNum=0;
2429 			 }
2430 		}
2431 		break;
2432 
2433 	case PID_PDATA:
2434 		if ((Game_mode&GM_NETWORK) && ((Network_status == NETSTAT_PLAYING)||(Network_status == NETSTAT_ENDLEVEL) || Network_status==NETSTAT_WAITING)) {
2435 			network_process_pdata((char *)data);
2436 		}
2437 		break;
2438    case PID_NAKED_PDATA:
2439 		if ((Game_mode&GM_NETWORK) && ((Network_status == NETSTAT_PLAYING)||(Network_status == NETSTAT_ENDLEVEL) || Network_status==NETSTAT_WAITING))
2440 			network_process_naked_pdata((char *)data,length);
2441 	   break;
2442 
2443 	case PID_OBJECT_DATA:
2444 		if (Network_status == NETSTAT_WAITING)
2445 			network_read_object_packet(data);
2446 		break;
2447 	case PID_ENDLEVEL:
2448 		if ((Network_status == NETSTAT_ENDLEVEL) || (Network_status == NETSTAT_PLAYING))
2449 			network_read_endlevel_packet(data);
2450 		else
2451 			mprintf((0, "Junked endlevel packet.\n"));
2452 		break;
2453 	case PID_ENDLEVEL_SHORT:
2454 		if ((Network_status == NETSTAT_ENDLEVEL) || (Network_status == NETSTAT_PLAYING))
2455 			network_read_endlevel_short_packet(data);
2456 		else
2457 			mprintf((0, "Junked short endlevel packet!\n"));
2458 		break;
2459 
2460 	case PID_GAME_UPDATE:
2461 		mprintf ((0,"Got a GAME_UPDATE!\n"));
2462 
2463 		if (Network_status==NETSTAT_PLAYING)
2464 		 {
2465 			if (Network_game_type == IPX_GAME)
2466 				receive_lite_netgame_packet(data, &TempNetInfo);
2467 			else
2468 				memcpy((ubyte *)&TempNetInfo, data, sizeof(lite_info) );
2469 		  if (TempNetInfo.Security==Netgame.Security)
2470 			 memcpy (&Netgame,(ubyte *)&TempNetInfo,sizeof(lite_info));
2471 		 }
2472 		if (Game_mode & GM_TEAM)
2473 		 {
2474 			int i;
2475 
2476 			for (i=0;i<N_players;i++)
2477 			 if (Players[i].connected)
2478 		    	multi_reset_object_texture (&Objects[Players[i].objnum]);
2479 		    reset_cockpit();
2480 		 }
2481 	   break;
2482    case PID_PING_SEND:
2483 		network_ping (PID_PING_RETURN,data[1]);
2484 		break;
2485    case PID_PING_RETURN:
2486 		network_handle_ping_return(data[1]);  // data[1] is player who told us of their ping time
2487 		break;
2488    case PID_NAMES_RETURN:
2489 		if (Network_status==NETSTAT_BROWSING && NamesInfoSecurity!=-1)
2490 		  network_process_names_return (data);
2491 		break;
2492 	case PID_GAME_PLAYERS:
2493 		// Someone wants a list of players in this game
2494 
2495 	   if (length != SEQUENCE_PACKET_SIZE)
2496 		 {
2497 		  mprintf ((0,"WARNING! Recieved invalid size for PID_GAME_PLAYERS\n"));
2498 		  return;
2499 		 }
2500 
2501 		mprintf((0, "Got a PID_GAME_PLAYERS!\n"));
2502 		if ((Network_status == NETSTAT_PLAYING) || (Network_status == NETSTAT_STARTING) || (Network_status == NETSTAT_ENDLEVEL))
2503 			if (network_i_am_master() && their->Security==Netgame.Security)
2504 				network_send_player_names(their);
2505 		break;
2506 
2507 	default:
2508 		mprintf((0, "Ignoring invalid packet type.\n"));
2509 		Int3(); // Invalid network packet type, see ROB
2510 	   break;
2511 	}
2512 }
2513 
2514 #ifndef NDEBUG
dump_segments()2515 void dump_segments()
2516 {
2517 	FILE * fp;
2518 
2519 	fp = fopen( "TEST.DMP", "wb" );
2520 	fwrite( Segments, sizeof(segment)*(Highest_segment_index+1),1, fp );
2521 	fclose(fp);
2522 	mprintf( (0, "SS=%d\n", sizeof(segment) ));
2523 }
2524 #endif
2525 
2526 
2527 void
network_read_endlevel_packet(ubyte * data)2528 network_read_endlevel_packet( ubyte *data )
2529 {
2530 	// Special packet for end of level syncing
2531 	int playernum;
2532 	endlevel_info *end = (endlevel_info *)data;
2533 #ifdef WORDS_BIGENDIAN
2534 	int i, j;
2535 
2536 	for (i = 0; i < MAX_PLAYERS; i++)
2537 		for (j = 0; j < MAX_PLAYERS; j++)
2538 			end->kill_matrix[i][j] = INTEL_SHORT(end->kill_matrix[i][j]);
2539 	end->kills = INTEL_SHORT(end->kills);
2540 	end->killed = INTEL_SHORT(end->killed);
2541 #endif
2542 
2543 	playernum = end->player_num;
2544 
2545 	Assert(playernum != Player_num);
2546 
2547 	if (playernum>=N_players)
2548 	 {
2549 		Int3(); // weird, but it an happen in a coop restore game
2550 		return; // if it happens in a coop restore, don't worry about it
2551 	 }
2552 
2553 	if ((Network_status == NETSTAT_PLAYING) && (end->connected != 0))
2554 		return; // Only accept disconnect packets if we're not out of the level yet
2555 
2556 	Players[playernum].connected = end->connected;
2557 	memcpy(&kill_matrix[playernum][0], end->kill_matrix, MAX_PLAYERS*sizeof(short));
2558 	Players[playernum].net_kills_total = end->kills;
2559 	Players[playernum].net_killed_total = end->killed;
2560 
2561 	if ((Players[playernum].connected == 1) && (end->seconds_left < Countdown_seconds_left))
2562 		Countdown_seconds_left = end->seconds_left;
2563 
2564 	LastPacketTime[playernum] = timer_get_approx_seconds();
2565 
2566 //      mprintf((0, "Got endlevel packet from player %d.\n", playernum));
2567 }
2568 
2569 void
network_read_endlevel_short_packet(ubyte * data)2570 network_read_endlevel_short_packet( ubyte *data )
2571 {
2572 	// Special packet for end of level syncing
2573 
2574 	int playernum;
2575 	endlevel_info_short *end;
2576 
2577 	end = (endlevel_info_short *)data;
2578 
2579 	playernum = end->player_num;
2580 
2581 	Assert(playernum != Player_num);
2582 
2583 	if (playernum>=N_players)
2584 	 {
2585 		Int3(); // weird, but it can happen in a coop restore game
2586 		return; // if it happens in a coop restore, don't worry about it
2587 	 }
2588 
2589 	if ((Network_status == NETSTAT_PLAYING) && (end->connected != 0))
2590 	 {
2591 		//mprintf ((0,"Returning early for short_endlevel\n"));
2592 		return; // Only accept disconnect packets if we're not out of the level yet
2593 	 }
2594 
2595 	Players[playernum].connected = end->connected;
2596 
2597 	if ((Players[playernum].connected == 1) && (end->seconds_left < Countdown_seconds_left))
2598 		Countdown_seconds_left = end->seconds_left;
2599 
2600 	LastPacketTime[playernum] = timer_get_approx_seconds();
2601 }
2602 
2603 
2604 void
network_pack_objects(void)2605 network_pack_objects(void)
2606 {
2607 	// Switching modes, pack the object array
2608 
2609 	special_reset_objects();
2610 }
2611 
2612 int
network_verify_objects(int remote,int local)2613 network_verify_objects(int remote, int local)
2614 {
2615 	int i;
2616 	int nplayers, got_controlcen=0;
2617 
2618    mprintf ((0,"NETWORK:remote=%d local=%d\n",remote,local));
2619 
2620 	if ((remote-local) > 10)
2621 		return(-1);
2622 
2623 	if (Game_mode & GM_MULTI_ROBOTS)
2624 		got_controlcen = 1;
2625 
2626 	nplayers = 0;
2627 
2628 	for (i = 0; i <= Highest_object_index; i++)
2629 	{
2630 		if ((Objects[i].type == OBJ_PLAYER) || (Objects[i].type == OBJ_GHOST))
2631 			nplayers++;
2632 		if (Objects[i].type == OBJ_CNTRLCEN)
2633 			got_controlcen=1;
2634 	}
2635 
2636     if (got_controlcen && (MaxNumNetPlayers<=nplayers))
2637 		return(0);
2638 
2639 	return(1);
2640 }
2641 
2642 void
network_read_object_packet(ubyte * data)2643 network_read_object_packet( ubyte *data )
2644 {
2645 	// Object from another net player we need to sync with
2646 
2647 	short objnum, remote_objnum;
2648 	byte obj_owner;
2649 	int segnum, i;
2650 	object *obj;
2651 
2652 	static int my_pnum = 0;
2653 	static int mode = 0;
2654 	static int object_count = 0;
2655 	static int frame_num = 0;
2656 	int nobj = data[1];
2657 	int loc = 3;
2658 	int remote_frame_num = data[2];
2659 
2660 	frame_num++;
2661 
2662 //      mprintf((0, "Object packet %d (remote #%d) contains %d objects.\n", frame_num, remote_frame_num, nobj));
2663 
2664 	for (i = 0; i < nobj; i++)
2665 	{
2666 		objnum = INTEL_SHORT( *(short *)(data+loc) );                   loc += 2;
2667 		obj_owner = data[loc];                                          loc += 1;
2668 		remote_objnum = INTEL_SHORT( *(short *)(data+loc) );            loc += 2;
2669 
2670 		if (objnum == -1)
2671 		{
2672 			// Clear object array
2673 			mprintf((0, "Clearing object array.\n"));
2674 
2675 			init_objects();
2676 			Network_rejoined = 1;
2677 			my_pnum = obj_owner;
2678 			change_playernum_to(my_pnum);
2679 			mode = 1;
2680 			object_count = 0;
2681 			frame_num = 1;
2682 		}
2683 		else if (objnum == -2)
2684 		{
2685 			// Special debug checksum marker for entire send
2686 			if (mode == 1)
2687 			{
2688 				network_pack_objects();
2689 				mode = 0;
2690 			}
2691 			mprintf((0, "Objnum -2 found in frame local %d remote %d.\n", frame_num, remote_frame_num));
2692 			mprintf((0, "Got %d objects, expected %d.\n", object_count, remote_objnum));
2693 			if (remote_objnum != object_count) {
2694 				Int3();
2695 			}
2696 			if (network_verify_objects(remote_objnum, object_count))
2697 			{
2698 				// Failed to sync up
2699 				nm_messagebox(NULL, 1, TXT_OK, TXT_NET_SYNC_FAILED);
2700 				Network_status = NETSTAT_MENU;
2701 				return;
2702 			}
2703 			frame_num = 0;
2704 		}
2705 		else
2706 		{
2707 			if (frame_num != remote_frame_num)
2708 				Int3();
2709 		  	mprintf ((0,"Got a type 3 object packet!\n"));
2710 			object_count++;
2711 			if ((obj_owner == my_pnum) || (obj_owner == -1))
2712 			{
2713 				if (mode != 1)
2714 					Int3(); // SEE ROB
2715 				objnum = remote_objnum;
2716 				//if (objnum > Highest_object_index)
2717 				//{
2718 				//      Highest_object_index = objnum;
2719 				//      num_objects = Highest_object_index+1;
2720 				//}
2721 			}
2722 			else {
2723 				if (mode == 1)
2724 				{
2725 					network_pack_objects();
2726 					mode = 0;
2727 				}
2728 				objnum = obj_allocate();
2729 			}
2730 			if (objnum != -1) {
2731 				obj = &Objects[objnum];
2732 				if (obj->segnum != -1)
2733 					obj_unlink(objnum);
2734 				Assert(obj->segnum == -1);
2735 				Assert(objnum < MAX_OBJECTS);
2736 				memcpy(obj, &data[loc], sizeof(object));
2737 				if (Network_game_type == IPX_GAME)
2738 					swap_object(obj);
2739 				loc += sizeof(object);
2740 				segnum = obj->segnum;
2741 				obj->next = obj->prev = obj->segnum = -1;
2742 				obj->attached_obj = -1;
2743 				if (segnum > -1)
2744 					obj_link(obj-Objects,segnum);
2745 				if (obj_owner == my_pnum)
2746 					map_objnum_local_to_local(objnum);
2747 				else if (obj_owner != -1)
2748 					map_objnum_local_to_remote(objnum, remote_objnum, obj_owner);
2749 				else
2750 					object_owner[objnum] = -1;
2751 			}
2752 		} // For a standard onbject
2753 	} // For each object in packet
2754 }
2755 
network_sync_poll(int nitems,newmenu_item * menus,int * key,int citem)2756 void network_sync_poll( int nitems, newmenu_item * menus, int * key, int citem )
2757 {
2758 	// Polling loop waiting for sync packet to start game
2759 
2760 	static fix t1 = 0;
2761 
2762 	menus = menus;
2763 	citem = citem;
2764 	nitems = nitems;
2765 
2766 	network_listen();
2767 
2768 	if (Network_status != NETSTAT_WAITING)  // Status changed to playing, exit the menu
2769 		*key = -2;
2770 
2771 	if (!Network_rejoined && (timer_get_approx_seconds() > t1+F1_0*2))
2772 	{
2773 		int i;
2774 
2775 		// Poll time expired, re-send request
2776 
2777 		t1 = timer_get_approx_seconds();
2778 
2779 		mprintf((0, "Re-sending join request.\n"));
2780 		i = network_send_request();
2781 		if (i < 0)
2782 			*key = -2;
2783 	}
2784 }
2785 
network_start_poll(int nitems,newmenu_item * menus,int * key,int citem)2786 void network_start_poll( int nitems, newmenu_item * menus, int * key, int citem )
2787 {
2788 	int i,n,nm;
2789 
2790 	key=key;
2791 	citem=citem;
2792 
2793 	Assert(Network_status == NETSTAT_STARTING);
2794 
2795 	if (!menus[0].value) {
2796 			menus[0].value = 1;
2797 			menus[0].redraw = 1;
2798 	}
2799 
2800 	for (i=1; i<nitems; i++ )       {
2801 		if ( (i>= N_players) && (menus[i].value) )      {
2802 			menus[i].value = 0;
2803 			menus[i].redraw = 1;
2804 		}
2805 	}
2806 
2807 	nm = 0;
2808 	for (i=0; i<nitems; i++ )       {
2809 		if ( menus[i].value )   {
2810 			nm++;
2811 			if ( nm > N_players )   {
2812 				menus[i].value = 0;
2813 				menus[i].redraw = 1;
2814 			}
2815 		}
2816 	}
2817 
2818 	if ( nm > MaxNumNetPlayers )    {
2819 		nm_messagebox( TXT_ERROR, 1, TXT_OK, "%s %d %s", TXT_SORRY_ONLY, MaxNumNetPlayers, TXT_NETPLAYERS_IN );
2820 		// Turn off the last player highlighted
2821 		for (i = N_players; i > 0; i--)
2822 			if (menus[i].value == 1)
2823 			{
2824 				menus[i].value = 0;
2825 				menus[i].redraw = 1;
2826 				break;
2827 			}
2828 	}
2829 
2830 //       if (nitems > MAX_PLAYERS ) return;
2831 
2832 	n = Netgame.numplayers;
2833 	network_listen();
2834 
2835 	if (n < Netgame.numplayers )
2836 	{
2837 		digi_play_sample (SOUND_HUD_MESSAGE,F1_0);
2838 
2839       mprintf ((0,"More players are printed!"));
2840 		if (FindArg("-norankings"))
2841 	      sprintf( menus[N_players-1].text, "%d. %-20s", N_players,NetPlayers.players[N_players-1].callsign );
2842 		else
2843 	      sprintf( menus[N_players-1].text, "%d. %s%-20s", N_players, RankStrings[NetPlayers.players[N_players-1].rank],NetPlayers.players[N_players-1].callsign );
2844 
2845 		menus[N_players-1].redraw = 1;
2846 		if (N_players <= MaxNumNetPlayers)
2847 		{
2848 			menus[N_players-1].value = 1;
2849 		}
2850 	}
2851 	else if ( n > Netgame.numplayers )
2852 	{
2853 		// One got removed...
2854 
2855       digi_play_sample (SOUND_HUD_KILL,F1_0);
2856 
2857 		for (i=0; i<N_players; i++ )
2858 		{
2859 
2860 	 if (FindArg("-norankings"))
2861 		 sprintf( menus[i].text, "%d. %-20s", i+1, NetPlayers.players[i].callsign );
2862 	 else
2863 		 sprintf( menus[i].text, "%d. %s%-20s", i+1, RankStrings[NetPlayers.players[i].rank],NetPlayers.players[i].callsign );
2864 			if (i < MaxNumNetPlayers)
2865 				menus[i].value = 1;
2866 			else
2867 				menus[i].value = 0;
2868 			menus[i].redraw = 1;
2869 		}
2870 		for (i=N_players; i<n; i++ )
2871 		{
2872 			sprintf( menus[i].text, "%d. ", i+1 );          // Clear out the deleted entries...
2873 			menus[i].value = 0;
2874 			menus[i].redraw = 1;
2875 		}
2876    }
2877 }
2878 
2879 int opt_cinvul, opt_team_anarchy, opt_coop, opt_show_on_map, opt_closed,opt_maxnet;
2880 int last_cinvul=0,last_maxnet,opt_team_hoard;
2881 int opt_refuse,opt_capture;
2882 
network_game_param_poll(int nitems,newmenu_item * menus,int * key,int citem)2883 void network_game_param_poll( int nitems, newmenu_item * menus, int * key, int citem )
2884 {
2885 	static int oldmaxnet=0;
2886 
2887 	if (((HoardEquipped() && menus[opt_team_hoard].value) || (menus[opt_team_anarchy].value || menus[opt_capture].value)) && !menus[opt_closed].value && !menus[opt_refuse].value) {
2888 		menus[opt_refuse].value = 1;
2889 		menus[opt_refuse].redraw = 1;
2890 		menus[opt_refuse-1].value = 0;
2891 		menus[opt_refuse-1].redraw = 1;
2892 		menus[opt_refuse-2].value = 0;
2893 		menus[opt_refuse-2].redraw = 1;
2894 	}
2895 
2896 	#ifndef MACINTOSH
2897 	if (menus[opt_coop].value)
2898 	#else
2899 	if ( (menus[opt_coop].value) || ((Network_game_type == APPLETALK_GAME) && (Network_appletalk_type == LOCALTALK_TYPE) && (menus[opt_coop-1].value)) )
2900 	#endif
2901 	{
2902 		oldmaxnet=1;
2903 
2904 		if (menus[opt_maxnet].value>2)
2905 		{
2906 		    menus[opt_maxnet].value=2;
2907 		    menus[opt_maxnet].redraw=1;
2908 		}
2909 
2910 		if (menus[opt_maxnet].max_value>2)
2911 		{
2912 		    menus[opt_maxnet].max_value=2;
2913 		    menus[opt_maxnet].redraw=1;
2914 		}
2915 
2916 		#ifdef MACINTOSH
2917 		if ( (Network_game_type == APPLETALK_GAME) && (Network_appletalk_type == LOCALTALK_TYPE) ) {
2918 			if (menus[opt_maxnet].value > 0) {
2919 			    menus[opt_maxnet].value=0;
2920 			    menus[opt_maxnet].redraw=1;
2921 			}
2922 			if (menus[opt_maxnet].max_value > 0) {
2923 				menus[opt_maxnet].max_value=0;
2924 				menus[opt_maxnet].redraw=1;
2925 			}
2926 		}
2927 		#endif
2928 
2929 	     if (!Netgame.game_flags & NETGAME_FLAG_SHOW_MAP)
2930 			Netgame.game_flags |= NETGAME_FLAG_SHOW_MAP;
2931 
2932 		if (Netgame.PlayTimeAllowed || Netgame.KillGoal)
2933 		{
2934 		    Netgame.PlayTimeAllowed=0;
2935 		    Netgame.KillGoal=0;
2936 		}
2937 
2938 	}
2939 	else // if !Coop game
2940     {
2941 		if (oldmaxnet)
2942 		{
2943 		    oldmaxnet=0;
2944 			menus[opt_maxnet].value=6;
2945 			menus[opt_maxnet].max_value=6;
2946 
2947 		    #ifdef MACINTOSH
2948 			if ( (Network_game_type == APPLETALK_GAME) && (Network_appletalk_type == LOCALTALK_TYPE) ) {
2949 				menus[opt_maxnet].value=1;
2950 				menus[opt_maxnet].max_value=1;
2951 			}
2952 			#endif
2953 
2954 		}
2955  	}
2956 
2957     if ( last_maxnet != menus[opt_maxnet].value )
2958 	{
2959 		sprintf( menus[opt_maxnet].text, "Maximum players: %d", menus[opt_maxnet].value+2 );
2960 		last_maxnet = menus[opt_maxnet].value;
2961 		menus[opt_maxnet].redraw = 1;
2962 	}
2963  }
2964 
2965 int netgame_difficulty;
2966 
network_get_game_params(char * game_name,int * mode,int * game_flags,int * level)2967 int network_get_game_params( char * game_name, int *mode, int *game_flags, int *level )
2968 {
2969 	int i;
2970 	int opt, opt_name, opt_level, opt_mode,opt_moreopts;
2971 	newmenu_item m[20];
2972 	char name[NETGAME_NAME_LEN+1];
2973 	char slevel[5];
2974 	char level_text[32];
2975 	char srmaxnet[50];
2976 
2977 	int new_mission_num;
2978 	int anarchy_only;
2979 
2980 	*game_flags=*game_flags;
2981 
2982 	SetAllAllowablesTo (1);
2983 	NamesInfoSecurity=-1;
2984 
2985 	for (i=0;i<MAX_PLAYERS;i++)
2986 		if (i!=Player_num)
2987 			Players[i].callsign[0]=0;
2988 
2989 	MaxNumNetPlayers=8;
2990 	Netgame.KillGoal=0;
2991 	Netgame.PlayTimeAllowed=0;
2992 	Netgame.Allow_marker_view=1;
2993 	netgame_difficulty=Player_default_difficulty;
2994 
2995 	new_mission_num = multi_choose_mission(&anarchy_only);
2996 
2997 	if (new_mission_num < 0)
2998 		return -1;
2999 
3000 	if (!(FindArg ("-packets") && FindArg ("-shortpackets")))
3001 		if (!network_choose_connect ())
3002 			return -1;
3003 
3004 #ifdef MACINTOSH
3005 	if ( (Network_game_type == APPLETALK_GAME) && (Network_appletalk_type == LOCALTALK_TYPE) )
3006 		MaxNumNetPlayers = 3;
3007 #endif
3008 
3009 	strcpy(Netgame.mission_name, Mission_list[new_mission_num].filename);
3010 	strcpy(Netgame.mission_title, Mission_list[new_mission_num].mission_name);
3011 	Netgame.control_invul_time = control_invul_time;
3012 
3013 	sprintf( name, "%s%s", Players[Player_num].callsign, TXT_S_GAME );
3014 	sprintf( slevel, "1" );
3015 
3016 	opt = 0;
3017 	m[opt].type = NM_TYPE_TEXT; m[opt].text = TXT_DESCRIPTION; opt++;
3018 
3019 	opt_name = opt;
3020 	m[opt].type = NM_TYPE_INPUT; m[opt].text = name; m[opt].text_len = NETGAME_NAME_LEN; opt++;
3021 
3022 	sprintf(level_text, "%s (1-%d)", TXT_LEVEL_, Last_level);
3023 
3024 //      if (Last_secret_level < -1)
3025 //              sprintf(level_text+strlen(level_text)-1, ", S1-S%d)", -Last_secret_level);
3026 //      else if (Last_secret_level == -1)
3027 //              sprintf(level_text+strlen(level_text)-1, ", S1)");
3028 
3029 	Assert(strlen(level_text) < 32);
3030 
3031 	m[opt].type = NM_TYPE_TEXT; m[opt].text = level_text; opt++;
3032 
3033 	opt_level = opt;
3034 	m[opt].type = NM_TYPE_INPUT; m[opt].text = slevel; m[opt].text_len=4; opt++;
3035 //	m[opt].type = NM_TYPE_TEXT; m[opt].text = TXT_OPTIONS; opt++;
3036 
3037 	opt_mode = opt;
3038 	m[opt].type = NM_TYPE_RADIO; m[opt].text = TXT_ANARCHY; m[opt].value=1; m[opt].group=0; opt++;
3039 	m[opt].type = NM_TYPE_RADIO; m[opt].text = TXT_TEAM_ANARCHY; m[opt].value=0; m[opt].group=0; opt_team_anarchy=opt; opt++;
3040 	m[opt].type = NM_TYPE_RADIO; m[opt].text = TXT_ANARCHY_W_ROBOTS; m[opt].value=0; m[opt].group=0; opt++;
3041 	m[opt].type = NM_TYPE_RADIO; m[opt].text = TXT_COOPERATIVE; m[opt].value=0; m[opt].group=0; opt_coop=opt; opt++;
3042 	m[opt].type = NM_TYPE_RADIO; m[opt].text = "Capture the flag"; m[opt].value=0; m[opt].group=0; opt_capture=opt; opt++;
3043 
3044 	if (HoardEquipped())
3045 	{
3046 		m[opt].type = NM_TYPE_RADIO; m[opt].text = "Hoard"; m[opt].value=0; m[opt].group=0; opt++;
3047 		m[opt].type = NM_TYPE_RADIO; m[opt].text = "Team Hoard"; m[opt].value=0; m[opt].group=0; opt_team_hoard=opt; opt++;
3048 	   m[opt].type = NM_TYPE_TEXT; m[opt].text = ""; opt++;
3049 	}
3050 	else
3051 	 {  m[opt].type = NM_TYPE_TEXT; m[opt].text = ""; opt++; }
3052 
3053 	m[opt].type = NM_TYPE_RADIO; m[opt].text = "Open game"; m[opt].group=1; m[opt].value=0; opt++;
3054 	opt_closed = opt;
3055 	m[opt].type = NM_TYPE_RADIO; m[opt].text = TXT_CLOSED_GAME; m[opt].group=1; m[opt].value=0; opt++;
3056    opt_refuse = opt;
3057    m[opt].type = NM_TYPE_RADIO; m[opt].text = "Restricted Game              "; m[opt].group=1; m[opt].value=Netgame.RefusePlayers; opt++;
3058 
3059 //      m[opt].type = NM_TYPE_CHECK; m[opt].text = TXT_SHOW_IDS; m[opt].value=0; opt++;
3060 
3061    opt_maxnet = opt;
3062    sprintf( srmaxnet, "Maximum players: %d", MaxNumNetPlayers);
3063    m[opt].type = NM_TYPE_SLIDER; m[opt].value=MaxNumNetPlayers-2; m[opt].text= srmaxnet; m[opt].min_value=0;
3064    m[opt].max_value=MaxNumNetPlayers-2; opt++;
3065    last_maxnet=MaxNumNetPlayers-2;
3066 
3067    opt_moreopts=opt;
3068    m[opt].type = NM_TYPE_MENU;  m[opt].text = "More options..."; opt++;
3069 
3070 	Assert(opt <= 20);
3071 
3072 menu:
3073    ExtGameStatus=GAMESTAT_NETGAME_OPTIONS;
3074 	i = newmenu_do1( NULL, NULL, opt, m, network_game_param_poll, 1 );
3075 									//TXT_NETGAME_SETUP
3076    if (i==opt_moreopts)
3077     {
3078      if ( m[opt_mode+3].value )
3079       Game_mode=GM_MULTI_COOP;
3080      network_more_game_options();
3081      Game_mode=0;
3082      goto menu;
3083     }
3084   Netgame.RefusePlayers=m[opt_refuse].value;
3085 
3086 
3087 	if ( i > -1 )   {
3088 		int j;
3089 
3090    MaxNumNetPlayers = m[opt_maxnet].value+2;
3091    Netgame.max_numplayers=MaxNumNetPlayers;
3092 
3093 		for (j = 0; j < num_active_games; j++)
3094 			if (!stricmp(Active_games[j].game_name, name))
3095 			{
3096 				nm_messagebox(TXT_ERROR, 1, TXT_OK, TXT_DUPLICATE_NAME);
3097 				goto menu;
3098 			}
3099 
3100 		strcpy( game_name, name );
3101 
3102 
3103 		*level = atoi(slevel);
3104 
3105 		if ((*level < 1) || (*level > Last_level))
3106 		{
3107 			nm_messagebox(TXT_ERROR, 1, TXT_OK, TXT_LEVEL_OUT_RANGE );
3108 			sprintf(slevel, "1");
3109 			goto menu;
3110 		}
3111 		if ( m[opt_mode].value )
3112 			*mode = NETGAME_ANARCHY;
3113 
3114 #ifdef SHAREWARE
3115 		else
3116 		{
3117 			nm_messagebox(TXT_SORRY, 1, TXT_OK, TXT_REGISTERED_ONLY );
3118 			m[opt_mode+1].value = 0;
3119 			m[opt_mode+2].value = 0;
3120 			m[opt_mode+3].value = 0;
3121 		   if (HoardEquipped())
3122 				m[opt_mode+4].value = 0;
3123 
3124 			m[opt_mode].value = 1;
3125 			goto menu;
3126 		}
3127 #else
3128 		else if (m[opt_mode+1].value) {
3129 			*mode = NETGAME_TEAM_ANARCHY;
3130 		}
3131 		else if (m[opt_capture].value)
3132 			*mode = NETGAME_CAPTURE_FLAG;
3133 		else if (HoardEquipped() && m[opt_capture+1].value)
3134 				*mode = NETGAME_HOARD;
3135 		else if (HoardEquipped() && m[opt_capture+2].value)
3136 				*mode = NETGAME_TEAM_HOARD;
3137 		else if (anarchy_only) {
3138 			nm_messagebox(NULL, 1, TXT_OK, TXT_ANARCHY_ONLY_MISSION);
3139 			m[opt_mode+2].value = 0;
3140 			m[opt_mode+3].value = 0;
3141 			m[opt_mode].value = 1;
3142 			goto menu;
3143 		}
3144 		else if ( m[opt_mode+2].value )
3145 			*mode = NETGAME_ROBOT_ANARCHY;
3146 		else if ( m[opt_mode+3].value )
3147 			*mode = NETGAME_COOPERATIVE;
3148 		else Int3(); // Invalid mode -- see Rob
3149 #endif
3150 		if (m[opt_closed].value)
3151 			Netgame.game_flags |= NETGAME_FLAG_CLOSED;
3152 
3153 	}
3154 
3155 	return i;
3156 }
3157 
3158 void
network_set_game_mode(int gamemode)3159 network_set_game_mode(int gamemode)
3160 {
3161 	Show_kill_list = 1;
3162 
3163 	if ( gamemode == NETGAME_ANARCHY )
3164 		Game_mode = GM_NETWORK;
3165 	else if ( gamemode == NETGAME_ROBOT_ANARCHY )
3166 		Game_mode = GM_NETWORK | GM_MULTI_ROBOTS;
3167 	else if ( gamemode == NETGAME_COOPERATIVE )
3168 		Game_mode = GM_NETWORK | GM_MULTI_COOP | GM_MULTI_ROBOTS;
3169 	else if (gamemode == NETGAME_CAPTURE_FLAG)
3170 		{
3171 		 Game_mode = GM_NETWORK | GM_TEAM | GM_CAPTURE;
3172 		 Show_kill_list=3;
3173 		}
3174 
3175 	else if (HoardEquipped() && gamemode == NETGAME_HOARD)
3176 		 Game_mode = GM_NETWORK | GM_HOARD;
3177 	else if (HoardEquipped() && gamemode == NETGAME_TEAM_HOARD)
3178 		 {
3179 		  Game_mode = GM_NETWORK | GM_HOARD | GM_TEAM;
3180  		  Show_kill_list=3;
3181 		 }
3182 	else if ( gamemode == NETGAME_TEAM_ANARCHY )
3183 	{
3184 		Game_mode = GM_NETWORK | GM_TEAM;
3185 		Show_kill_list = 3;
3186 	}
3187 	else
3188 		Int3();
3189 
3190 #if 0
3191 #ifdef MACINTOSH			// minimize players on localtalk games
3192 	if ( (Network_game_type == APPLETALK_GAME) && (Network_appletalk_type == LOCALTALK_TYPE) ) {
3193 		if (Game_mode & GM_MULTI_ROBOTS)
3194 			MaxNumNetPlayers = 2;
3195 		else
3196 			MaxNumNetPlayers = 3;
3197 	} else {
3198 		if (Game_mode & GM_MULTI_COOP)
3199 			MaxNumNetPlayers = 4;
3200 		else
3201 			MaxNumNetPlayers = 8;
3202 	}
3203 #endif
3204 #endif
3205 
3206 }
3207 
3208 int
network_find_game(void)3209 network_find_game(void)
3210 {
3211 	// Find out whether or not there is space left on this socket
3212 
3213 	fix t1;
3214 
3215 	Network_status = NETSTAT_BROWSING;
3216 
3217 	num_active_games = 0;
3218 
3219 	show_boxed_message(TXT_WAIT);
3220 
3221 	network_send_game_list_request();
3222 	t1 = timer_get_approx_seconds() + F1_0*3;
3223 
3224 	while (timer_get_approx_seconds() < t1) // Wait 3 seconds for replies
3225 		network_listen();
3226 
3227 	clear_boxed_message();
3228 
3229 //      mprintf((0, "%s %d %s\n", TXT_FOUND, num_active_games, TXT_ACTIVE_GAMES));
3230 
3231 	if (num_active_games < MAX_ACTIVE_NETGAMES)
3232 		return 0;
3233 	return 1;
3234 }
3235 
network_read_sync_packet(netgame_info * sp,int rsinit)3236 void network_read_sync_packet( netgame_info * sp, int rsinit)
3237 {
3238 	int i, j;
3239 	char temp_callsign[CALLSIGN_LEN+1];
3240 #ifdef WORDS_BIGENDIAN
3241 	netgame_info tmp_info;
3242 
3243 	if ( (Network_game_type == IPX_GAME) && (sp != &Netgame) ) {                            // for macintosh -- get the values unpacked to our structure format
3244 		receive_full_netgame_packet((ubyte *)sp, &tmp_info);
3245 		sp = &tmp_info;
3246 	}
3247 #endif
3248 
3249    if (rsinit)
3250      TempPlayersInfo=&NetPlayers;
3251 
3252 	// This function is now called by all people entering the netgame.
3253 
3254 	// mprintf( (0, "%s %d\n", TXT_STARTING_NETGAME, sp->levelnum ));
3255 
3256 	if (sp != &Netgame)
3257 	 {
3258 	  memcpy( &Netgame, sp, sizeof(netgame_info) );
3259 	  memcpy (&NetPlayers,TempPlayersInfo,sizeof (AllNetPlayers_info));
3260 	 }
3261 
3262 	N_players = sp->numplayers;
3263 	Difficulty_level = sp->difficulty;
3264 	Network_status = sp->game_status;
3265 
3266    //Assert(Function_mode != FMODE_GAME);
3267 
3268 	// New code, 11/27
3269 
3270 	mprintf((1, "Netgame.checksum = %d, calculated checksum = %d.\n", Netgame.segments_checksum, my_segments_checksum));
3271 
3272 	if (Netgame.segments_checksum != my_segments_checksum)
3273 	{
3274 		Network_status = NETSTAT_MENU;
3275 		nm_messagebox(TXT_ERROR, 1, TXT_OK, TXT_NETLEVEL_NMATCH);
3276 #ifdef RELEASE
3277 		return;
3278 #endif
3279 	}
3280 
3281 	// Discover my player number
3282 
3283 	memcpy(temp_callsign, Players[Player_num].callsign, CALLSIGN_LEN+1);
3284 
3285 	Player_num = -1;
3286 
3287 	for (i=0; i<MAX_NUM_NET_PLAYERS; i++ )  {
3288 		Players[i].net_kills_total = 0;
3289 //              Players[i].net_killed_total = 0;
3290 	}
3291 
3292 	for (i=0; i<N_players; i++ )    {
3293 		if (Network_game_type == IPX_GAME) {
3294 			if ( (!memcmp( TempPlayersInfo->players[i].network.ipx.node, My_Seq.player.network.ipx.node, 6 )) && (!stricmp( TempPlayersInfo->players[i].callsign, temp_callsign)) ) {
3295 				if (Player_num!=-1) {
3296 					Int3(); // Hey, we've found ourselves twice
3297 					mprintf ((0,"Hey, we've found ourselves twice!\n"));
3298 					Network_status = NETSTAT_MENU;
3299 					return;
3300 				}
3301 				change_playernum_to(i);
3302 			}
3303 		} else {
3304 			if ( (TempPlayersInfo->players[i].network.appletalk.node == My_Seq.player.network.appletalk.node) && (!stricmp( TempPlayersInfo->players[i].callsign, temp_callsign)) ) {
3305 				if (Player_num!=-1) {
3306 					Int3(); // Hey, we've found ourselves twice
3307 					Network_status = NETSTAT_MENU;
3308 					return;
3309 				}
3310 				change_playernum_to(i);
3311 			}
3312 		}
3313 		memcpy( Players[i].callsign, TempPlayersInfo->players[i].callsign, CALLSIGN_LEN+1 );
3314 
3315 		if (Network_game_type == IPX_GAME) {
3316 			if ( (*(uint *)TempPlayersInfo->players[i].network.ipx.server) != 0 )
3317 				ipx_get_local_target( TempPlayersInfo->players[i].network.ipx.server, TempPlayersInfo->players[i].network.ipx.node, Players[i].net_address );
3318 			else
3319 				memcpy( Players[i].net_address, TempPlayersInfo->players[i].network.ipx.node, 6 );
3320 		}
3321 
3322 		Players[i].n_packets_got=0;                             // How many packets we got from them
3323 		Players[i].n_packets_sent=0;                            // How many packets we sent to them
3324 		Players[i].connected = TempPlayersInfo->players[i].connected;
3325 		Players[i].net_kills_total = sp->player_kills[i];
3326 		Players[i].net_killed_total = sp->killed[i];
3327 		if ((Network_rejoined) || (i != Player_num))
3328 			Players[i].score = sp->player_score[i];
3329 		for (j = 0; j < MAX_NUM_NET_PLAYERS; j++)
3330 		{
3331 			kill_matrix[i][j] = sp->kills[i][j];
3332 		}
3333 	}
3334 
3335 	if ( Player_num < 0 )   {
3336 		mprintf ((0,"Bad Player_num, resetting to NETSTAT_MENU!\n"));
3337 		Network_status = NETSTAT_MENU;
3338 		return;
3339 	}
3340 
3341 	if (Network_rejoined)
3342 		for (i=0; i<N_players;i++)
3343 			Players[i].net_killed_total = sp->killed[i];
3344 
3345 	if (Network_rejoined) {
3346 		network_process_monitor_vector(sp->monitor_vector);
3347 		Players[Player_num].time_level = sp->level_time;
3348 	}
3349 
3350 	team_kills[0] = sp->team_kills[0];
3351 	team_kills[1] = sp->team_kills[1];
3352 
3353 	Players[Player_num].connected = 1;
3354    NetPlayers.players[Player_num].connected = 1;
3355    NetPlayers.players[Player_num].rank=GetMyNetRanking();
3356 
3357 	if (!Network_rejoined)
3358 		for (i=0; i<NumNetPlayerPositions; i++) {
3359 			Objects[Players[i].objnum].pos = Player_init[Netgame.locations[i]].pos;
3360 			Objects[Players[i].objnum].orient = Player_init[Netgame.locations[i]].orient;
3361 			obj_relink(Players[i].objnum,Player_init[Netgame.locations[i]].segnum);
3362 		}
3363 
3364 	Objects[Players[Player_num].objnum].type = OBJ_PLAYER;
3365 
3366    mprintf ((0,"Changing to NETSTAT_PLAYING!\n"));
3367 	Network_status = NETSTAT_PLAYING;
3368 	Function_mode = FMODE_GAME;
3369 	multi_sort_kill_list();
3370 
3371 }
3372 
3373 void
network_send_sync(void)3374 network_send_sync(void)
3375 {
3376 	int i, j, np;
3377 
3378 	// Randomize their starting locations...
3379 
3380 	d_srand( timer_get_fixed_seconds() );
3381 	for (i=0; i<NumNetPlayerPositions; i++ )
3382 	{
3383 		if (Players[i].connected)
3384 			Players[i].connected = 1; // Get rid of endlevel connect statuses
3385 		if (Game_mode & GM_MULTI_COOP)
3386 			Netgame.locations[i] = i;
3387 		else {
3388 			do
3389 			{
3390 				np = d_rand() % NumNetPlayerPositions;
3391 				for (j=0; j<i; j++ )
3392 				{
3393 					if (Netgame.locations[j]==np)
3394 					{
3395 						np =-1;
3396 						break;
3397 					}
3398 				}
3399 			} while (np<0);
3400 			// np is a location that is not used anywhere else..
3401 			Netgame.locations[i]=np;
3402 //                      mprintf((0, "Player %d starting in location %d\n" ,i ,np ));
3403 		}
3404 	}
3405 
3406 	// Push current data into the sync packet
3407 
3408 	network_update_netgame();
3409 	Netgame.game_status = NETSTAT_PLAYING;
3410 	Netgame.type = PID_SYNC;
3411 	Netgame.segments_checksum = my_segments_checksum;
3412 
3413 	for (i=0; i<N_players; i++ )    {
3414 		if ((!Players[i].connected) || (i == Player_num))
3415 			continue;
3416 
3417 		if (Network_game_type == IPX_GAME) {
3418 		// Send several times, extras will be ignored
3419 			send_internetwork_full_netgame_packet(NetPlayers.players[i].network.ipx.server, NetPlayers.players[i].network.ipx.node);
3420 			send_netplayers_packet(NetPlayers.players[i].network.ipx.server, NetPlayers.players[i].network.ipx.node);
3421 		#ifdef MACINTOSH
3422 		} else {
3423 				appletalk_send_packet_data( (ubyte *)&Netgame, sizeof(netgame_info), NetPlayers.players[i].network.appletalk.node,
3424 					NetPlayers.players[i].network.appletalk.net,
3425 					NetPlayers.players[i].network.appletalk.socket);
3426 				appletalk_send_packet_data( (ubyte *)&NetPlayers, sizeof(AllNetPlayers_info), NetPlayers.players[i].network.appletalk.node,
3427 					NetPlayers.players[i].network.appletalk.net,
3428 					NetPlayers.players[i].network.appletalk.socket);
3429 		#endif
3430 		}
3431 
3432 	}
3433 	network_read_sync_packet(&Netgame,1); // Read it myself, as if I had sent it
3434 }
3435 
3436 int
network_select_teams(void)3437 network_select_teams(void)
3438 {
3439 #ifndef SHAREWARE
3440 	newmenu_item m[MAX_PLAYERS+4];
3441 	int choice, opt, opt_team_b;
3442 	ubyte team_vector = 0;
3443 	char team_names[2][CALLSIGN_LEN+1];
3444 	int i;
3445 	int pnums[MAX_PLAYERS+2];
3446 
3447 	// One-time initialization
3448 
3449 	for (i = N_players/2; i < N_players; i++) // Put first half of players on team A
3450 	{
3451 		team_vector |= (1 << i);
3452 	}
3453 
3454 	sprintf(team_names[0], "%s", TXT_BLUE);
3455 	sprintf(team_names[1], "%s", TXT_RED);
3456 
3457 	// Here comes da menu
3458 menu:
3459 	m[0].type = NM_TYPE_INPUT; m[0].text = team_names[0]; m[0].text_len = CALLSIGN_LEN;
3460 
3461 	opt = 1;
3462 	for (i = 0; i < N_players; i++)
3463 	{
3464 		if (!(team_vector & (1 << i)))
3465 		{
3466 			m[opt].type = NM_TYPE_MENU; m[opt].text = NetPlayers.players[i].callsign; pnums[opt] = i; opt++;
3467 		}
3468 	}
3469 	opt_team_b = opt;
3470 	m[opt].type = NM_TYPE_INPUT; m[opt].text = team_names[1]; m[opt].text_len = CALLSIGN_LEN; opt++;
3471 	for (i = 0; i < N_players; i++)
3472 	{
3473 		if (team_vector & (1 << i))
3474 		{
3475 			m[opt].type = NM_TYPE_MENU; m[opt].text = NetPlayers.players[i].callsign; pnums[opt] = i; opt++;
3476 		}
3477 	}
3478 	m[opt].type = NM_TYPE_TEXT; m[opt].text = ""; opt++;
3479 	m[opt].type = NM_TYPE_MENU; m[opt].text = TXT_ACCEPT; opt++;
3480 
3481 	Assert(opt <= MAX_PLAYERS+4);
3482 
3483 	choice = newmenu_do(NULL, TXT_TEAM_SELECTION, opt, m, NULL);
3484 
3485 	if (choice == opt-1)
3486 	{
3487 		if ((opt-2-opt_team_b < 2) || (opt_team_b == 1))
3488 		{
3489 			nm_messagebox(NULL, 1, TXT_OK, TXT_TEAM_MUST_ONE);
3490 			#ifdef RELEASE
3491 				goto menu;
3492 			#endif
3493 		}
3494 
3495 		Netgame.team_vector = team_vector;
3496 		strcpy(Netgame.team_name[0], team_names[0]);
3497 		strcpy(Netgame.team_name[1], team_names[1]);
3498 		return 1;
3499 	}
3500 
3501 	else if ((choice > 0) && (choice < opt_team_b)) {
3502 		team_vector |= (1 << pnums[choice]);
3503 	}
3504 	else if ((choice > opt_team_b) && (choice < opt-2)) {
3505 		team_vector &= ~(1 << pnums[choice]);
3506 	}
3507 	else if (choice == -1)
3508 		return 0;
3509 	goto menu;
3510 #else
3511 	return 0;
3512 #endif
3513 }
3514 
3515 int
network_select_players(void)3516 network_select_players(void)
3517 {
3518 	int i, j;
3519    newmenu_item m[MAX_PLAYERS+4];
3520    char text[MAX_PLAYERS+4][45];
3521 	char title[50];
3522 	int save_nplayers;              //how may people would like to join
3523 
3524 	network_add_player( &My_Seq );
3525 
3526 	for (i=0; i< MAX_PLAYERS+4; i++ ) {
3527 		sprintf( text[i], "%d.  %-20s", i+1, "" );
3528 		m[i].type = NM_TYPE_CHECK; m[i].text = text[i]; m[i].value = 0;
3529 	}
3530 
3531 	m[0].value = 1;                         // Assume server will play...
3532 
3533    if (FindArg("-norankings"))
3534 		sprintf( text[0], "%d. %-20s", 1, Players[Player_num].callsign );
3535 	else
3536 		sprintf( text[0], "%d. %s%-20s", 1, RankStrings[NetPlayers.players[Player_num].rank],Players[Player_num].callsign );
3537 
3538 	sprintf( title, "%s %d %s", TXT_TEAM_SELECT, MaxNumNetPlayers, TXT_TEAM_PRESS_ENTER );
3539 
3540 GetPlayersAgain:
3541    ExtGameStatus=GAMESTAT_NETGAME_PLAYER_SELECT;
3542 	j=newmenu_do1( NULL, title, MAX_PLAYERS+4, m, network_start_poll, 1 );
3543 
3544 	save_nplayers = N_players;
3545 
3546 	if (j<0)
3547 	{
3548 		// Aborted!
3549 		// Dump all players and go back to menu mode
3550 
3551 abort:
3552 		for (i=1; i<save_nplayers; i++) {
3553 			if (Network_game_type == IPX_GAME)
3554 				network_dump_player(NetPlayers.players[i].network.ipx.server,NetPlayers.players[i].network.ipx.node, DUMP_ABORTED);
3555 			#ifdef MACINTOSH
3556 			else
3557 				network_dump_appletalk_player(NetPlayers.players[i].network.appletalk.node,NetPlayers.players[i].network.appletalk.net, NetPlayers.players[i].network.appletalk.socket, DUMP_ABORTED);
3558 			#endif
3559 		}
3560 
3561 
3562 		Netgame.numplayers = 0;
3563 		network_send_game_info(0); // Tell everyone we're bailing
3564 
3565 		Network_status = NETSTAT_MENU;
3566 		return(0);
3567 	}
3568 
3569 	// Count number of players chosen
3570 
3571 	N_players = 0;
3572 	for (i=0; i<save_nplayers; i++ )
3573 	{
3574 		if (m[i].value)
3575 			N_players++;
3576 	}
3577 
3578 	if ( N_players > Netgame.max_numplayers) {
3579 		#ifndef MACINTOSH
3580 		nm_messagebox( TXT_ERROR, 1, TXT_OK, "%s %d %s", TXT_SORRY_ONLY, MaxNumNetPlayers, TXT_NETPLAYERS_IN );
3581 		#else
3582 		nm_messagebox( TXT_ERROR, 1, TXT_OK, "%s %d netplayers for this game.", TXT_SORRY_ONLY, MaxNumNetPlayers );
3583 		#endif
3584 		N_players = save_nplayers;
3585 		goto GetPlayersAgain;
3586 	}
3587 
3588 #ifdef RELEASE
3589 	if ( N_players < 2 )    {
3590 		nm_messagebox( TXT_ERROR, 1, TXT_OK, TXT_TEAM_ATLEAST_TWO );
3591 		N_players = save_nplayers;
3592 		goto GetPlayersAgain;
3593 	}
3594 #endif
3595 
3596 #ifdef RELEASE
3597 	if ( (Netgame.gamemode == NETGAME_TEAM_ANARCHY ||
3598 		   Netgame.gamemode == NETGAME_CAPTURE_FLAG || Netgame.gamemode == NETGAME_TEAM_HOARD) && (N_players < 2) ) {
3599 		nm_messagebox(TXT_ERROR, 1, TXT_OK, "You must select at least two\nplayers to start a team game" );
3600 		N_players = save_nplayers;
3601 		goto GetPlayersAgain;
3602 	}
3603 #endif
3604 
3605 	// Remove players that aren't marked.
3606 	N_players = 0;
3607 	for (i=0; i<save_nplayers; i++ )        {
3608 		if (m[i].value)
3609 		{
3610 			if (i > N_players)
3611 			{
3612 				if (Network_game_type == IPX_GAME) {
3613 					memcpy(NetPlayers.players[N_players].network.ipx.node, NetPlayers.players[i].network.ipx.node, 6);
3614 					memcpy(NetPlayers.players[N_players].network.ipx.server, NetPlayers.players[i].network.ipx.server, 4);
3615 				} else {
3616 					NetPlayers.players[N_players].network.appletalk.node = NetPlayers.players[i].network.appletalk.node;
3617 					NetPlayers.players[N_players].network.appletalk.net = NetPlayers.players[i].network.appletalk.net;
3618 					NetPlayers.players[N_players].network.appletalk.socket = NetPlayers.players[i].network.appletalk.socket;
3619 				}
3620 				memcpy(NetPlayers.players[N_players].callsign, NetPlayers.players[i].callsign, CALLSIGN_LEN+1);
3621 				NetPlayers.players[N_players].version_major=NetPlayers.players[i].version_major;
3622 				NetPlayers.players[N_players].version_minor=NetPlayers.players[i].version_minor;
3623 				NetPlayers.players[N_players].rank=NetPlayers.players[i].rank;
3624 				ClipRank (&NetPlayers.players[N_players].rank);
3625 				network_check_for_old_version(i);
3626 			}
3627 			Players[N_players].connected = 1;
3628 			N_players++;
3629 		}
3630 		else
3631 		{
3632 			if (Network_game_type == IPX_GAME)
3633 				network_dump_player(NetPlayers.players[i].network.ipx.server,NetPlayers.players[i].network.ipx.node, DUMP_DORK);
3634 			#ifdef MACINTOSH
3635 			else
3636 				network_dump_appletalk_player(NetPlayers.players[i].network.appletalk.node,NetPlayers.players[i].network.appletalk.net, NetPlayers.players[i].network.appletalk.socket, DUMP_DORK);
3637 			#endif
3638 		}
3639 	}
3640 
3641 	for (i = N_players; i < MAX_NUM_NET_PLAYERS; i++) {
3642 		if (Network_game_type == IPX_GAME) {
3643 		memset(NetPlayers.players[i].network.ipx.node, 0, 6);
3644 		memset(NetPlayers.players[i].network.ipx.server, 0, 4);
3645 	    } else {
3646 		NetPlayers.players[i].network.appletalk.node = 0;
3647 		NetPlayers.players[i].network.appletalk.net = 0;
3648 		NetPlayers.players[i].network.appletalk.socket = 0;
3649 	    }
3650 	memset(NetPlayers.players[i].callsign, 0, CALLSIGN_LEN+1);
3651 		NetPlayers.players[i].version_major=0;
3652 		NetPlayers.players[i].version_minor=0;
3653 		NetPlayers.players[i].rank=0;
3654 	}
3655 
3656    mprintf ((0,"Select teams: Game mode is %d\n",Netgame.gamemode));
3657 
3658 	if (Netgame.gamemode == NETGAME_TEAM_ANARCHY ||
3659 	    Netgame.gamemode == NETGAME_CAPTURE_FLAG ||
3660 		 Netgame.gamemode == NETGAME_TEAM_HOARD)
3661 		 if (!network_select_teams())
3662 			goto abort;
3663 
3664 	return(1);
3665 }
3666 
3667 void
network_start_game()3668 network_start_game()
3669 {
3670 	int i;
3671 	char game_name[NETGAME_NAME_LEN+1];
3672 	int chosen_game_mode, game_flags, level;
3673 
3674 	if (Network_game_type == IPX_GAME) {
3675 
3676 		Assert( FRAME_INFO_SIZE < IPX_MAX_DATA_SIZE );
3677 		mprintf((0, "Using frame_info len %d, max %d.\n", FRAME_INFO_SIZE, IPX_MAX_DATA_SIZE));
3678 
3679 		if ( !Network_active )
3680 		{
3681 			nm_messagebox(NULL, 1, TXT_OK, TXT_IPX_NOT_FOUND );
3682 			return;
3683 		}
3684 	#ifdef MACINTOSH
3685 	} else {
3686 		int err;
3687 		char buf[256];
3688 
3689 		Assert( FRAME_INFO_SIZE < APPLETALK_MAX_DATA_SIZE );
3690 		mprintf((0, "Using frame_info len %d, max %d.\n", sizeof(frame_info), APPLETALK_MAX_DATA_SIZE));
3691 		if (Appletalk_active <= 0) {
3692 			switch (Appletalk_active) {
3693 			case APPLETALK_NOT_OPEN:
3694 				sprintf(buf, "Appletalk is not currently active.\nPlease enable AppleTalk from the\nChooser and restart Descent.");
3695 				break;
3696 			case APPLETALK_BAD_LISTENER:
3697 				sprintf(buf, "The Resource Fork of Descent appears damaged.\nPlease re-install Descent or contact\nMacPlay technical support.");
3698 				break;
3699 			case APPLETALK_NO_LOCAL_ADDR:
3700 				sprintf(buf, "Wow! Strange!\n\nNo Local Address.");
3701 				break;
3702 			case APPLETALK_NO_SOCKET:
3703 				sprintf(buf, "All AppleTalk sockets are in use.\nTry shutting down other network\napplications and restarting Descent.\n");
3704 				break;
3705 			}
3706 			nm_messagebox(NULL, 1, TXT_OK, buf);
3707 			return;
3708 		}
3709 		strcpy(Network_zone_name, DEFAULT_ZONE_NAME);
3710 	#endif
3711 	}
3712 
3713 	network_init();
3714 	change_playernum_to(0);
3715 
3716 	if (network_find_game())
3717 	{
3718 		nm_messagebox(NULL, 1, TXT_OK, TXT_NET_FULL);
3719 		return;
3720 	}
3721 
3722 	game_flags = 0;
3723 	i = network_get_game_params( game_name, &chosen_game_mode, &game_flags, &level );
3724 
3725 	if (i<0) return;
3726 
3727 	N_players = 0;
3728 
3729 // LoadLevel(level); Old, no longer used.
3730 
3731 	Netgame.difficulty = Difficulty_level;
3732 	Netgame.gamemode = chosen_game_mode;
3733 	Netgame.game_status = NETSTAT_STARTING;
3734 	Netgame.numplayers = 0;
3735 	Netgame.max_numplayers = MaxNumNetPlayers;
3736 	Netgame.levelnum = level;
3737 	Netgame.protocol_version = MULTI_PROTO_VERSION;
3738 
3739 	strcpy(Netgame.game_name, game_name);
3740 
3741 	Network_status = NETSTAT_STARTING;
3742 
3743 	#ifdef MACINTOSH
3744 	if (Network_game_type == APPLETALK_GAME) {
3745 		OSErr err;
3746 		fix t1;
3747 		int count = 0;
3748 
3749 		show_boxed_message("Registering Netgame");
3750 		do {
3751 			err = appletalk_register_netgame( game_name, TickCount() );
3752 			t1 = timer_get_fixed_seconds() + F1_0;
3753 			while (timer_get_fixed_seconds() < t1) ;
3754 			count++;
3755 		} while ( (err == nbpDuplicate) && (count != MAX_REGISTER_TRIES) );
3756 		clear_boxed_message();
3757 		if ( (err == tooManyReqs) || (count == MAX_REGISTER_TRIES) ) {
3758 			nm_messagebox(NULL, 1, TXT_OK, "AppleTalk Network is too busy.\nPlease try again shortly.");
3759 			Game_mode = GM_GAME_OVER;
3760 			return;
3761 		}
3762 	}
3763 	#endif
3764 
3765 	network_set_game_mode(Netgame.gamemode);
3766 
3767    d_srand( timer_get_fixed_seconds() );
3768    Netgame.Security=d_rand();  // For syncing Netgames with player packets
3769 
3770 	if(network_select_players())
3771 	{
3772 		StartNewLevel(Netgame.levelnum, 0);
3773 	}
3774 	else
3775 		Game_mode = GM_GAME_OVER;
3776 
3777 }
3778 
restart_net_searching(newmenu_item * m)3779 void restart_net_searching(newmenu_item * m)
3780 {
3781 	int i;
3782 	N_players = 0;
3783 	num_active_games = 0;
3784 
3785 	memset(Active_games, 0, sizeof(netgame_info)*MAX_ACTIVE_NETGAMES);
3786 
3787 	for (i = 0; i < MAX_ACTIVE_NETGAMES; i++)
3788 	{
3789 		sprintf(m[i+2].text, "%d.                                                     ",i+1);
3790 		m[i+2].redraw = 1;
3791 	}
3792 
3793    NamesInfoSecurity=-1;
3794 	Network_games_changed = 1;
3795 }
3796 
3797 char *ModeLetters[]={"ANRCHY","TEAM","ROBO","COOP","FLAG","HOARD","TMHOARD"};
3798 
3799 int NumActiveNetgames=0;
3800 
network_join_poll(int nitems,newmenu_item * menus,int * key,int citem)3801 void network_join_poll( int nitems, newmenu_item * menus, int * key, int citem )
3802 {
3803 	// Polling loop for Join Game menu
3804 	static fix t1 = 0;
3805 	int i, osocket,join_status,temp;
3806 
3807 	menus = menus;
3808 	citem = citem;
3809 	nitems = nitems;
3810 	key = key;
3811 
3812 	if ( (Network_game_type == IPX_GAME) && Network_allow_socket_changes ) {
3813 		osocket = Network_socket;
3814 
3815 		if ( *key==KEY_PAGEDOWN )       { Network_socket--; *key = 0; }
3816 		if ( *key==KEY_PAGEUP )         { Network_socket++; *key = 0; }
3817 
3818 		if (Network_socket>99)
3819 			Network_socket=99;
3820 		if (Network_socket<-99)
3821 			Network_socket=-99;
3822 
3823 		if ( Network_socket+IPX_DEFAULT_SOCKET > 0x8000 )
3824 			Network_socket  = 0x8000 - IPX_DEFAULT_SOCKET;
3825 
3826 		if ( Network_socket+IPX_DEFAULT_SOCKET < 0 )
3827 			Network_socket  = IPX_DEFAULT_SOCKET;
3828 
3829 		if (Network_socket != osocket )         {
3830 			sprintf( menus[0].text, "\t%s %+d (PgUp/PgDn to change)", TXT_CURRENT_IPX_SOCKET, Network_socket );
3831 			menus[0].redraw = 1;
3832 			mprintf(( 0, "Changing to socket %d\n", Network_socket ));
3833 			network_listen();
3834 			mprintf ((0,"netgood 1!\n"));
3835 			ipx_change_default_socket( IPX_DEFAULT_SOCKET + Network_socket );
3836 			mprintf ((0,"netgood 2!\n"));
3837 			restart_net_searching(menus);
3838 			mprintf ((0,"netgood 3!\n"));
3839 			network_send_game_list_request();
3840 			mprintf ((0,"netgood 4!\n"));
3841 			return;
3842 		}
3843 	}
3844 
3845 	// send a request for game info every 3 seconds
3846 
3847 	if (Network_game_type == IPX_GAME) {
3848 		if (timer_get_approx_seconds() > t1+F1_0*3) {
3849 			t1 = timer_get_approx_seconds();
3850 			network_send_game_list_request();
3851 		}
3852 #ifdef MACINTOSH
3853 	} else if (timer_get_approx_seconds() > t1+F1_0*20) {
3854 		hide_cursor();
3855 		t1 = timer_get_approx_seconds();
3856 		restart_net_searching(menus);
3857 		show_boxed_message("Requesting list of Netgames");
3858 		network_send_game_list_request();
3859 		clear_boxed_message();
3860 		show_cursor();
3861 #endif
3862 	}
3863 
3864 	temp=num_active_games;
3865 
3866 	network_listen();
3867 
3868 	NumActiveNetgames=num_active_games;
3869 
3870 	if (!Network_games_changed)
3871 		return;
3872 
3873 	if (temp!=num_active_games)
3874 		digi_play_sample (SOUND_HUD_MESSAGE,F1_0);
3875 
3876 	Network_games_changed = 0;
3877 	mprintf ((0,"JOIN POLL: I'm looking at %d games!\n",num_active_games));
3878 
3879 	// Copy the active games data into the menu options
3880 	for (i = 0; i < num_active_games; i++)
3881 	{
3882 		int game_status = Active_games[i].game_status;
3883 		int j,x, k,tx,ty,ta,nplayers = 0;
3884 		char levelname[8],MissName[25],GameName[25],thold[2];
3885 		thold[1]=0;
3886 
3887 		// These next two loops protect against menu skewing
3888 		// if missiontitle or gamename contain a tab
3889 
3890 		for (x=0,tx=0,k=0,j=0;j<15;j++)
3891 		{
3892 			if (Active_games[i].mission_title[j]=='\t')
3893 				continue;
3894 			thold[0]=Active_games[i].mission_title[j];
3895 			gr_get_string_size (thold,&tx,&ty,&ta);
3896 
3897 			if ((x+=tx)>=LHX(55))
3898 			{
3899 				MissName[k]=MissName[k+1]=MissName[k+2]='.';
3900 				k+=3;
3901 				break;
3902 			}
3903 
3904 			MissName[k++]=Active_games[i].mission_title[j];
3905 		}
3906 		MissName[k]=0;
3907 
3908 		for (x=0,tx=0,k=0,j=0;j<15;j++)
3909 		{
3910 			if (Active_games[i].game_name[j]=='\t')
3911 				continue;
3912 			thold[0]=Active_games[i].game_name[j];
3913 			gr_get_string_size (thold,&tx,&ty,&ta);
3914 
3915 			if ((x+=tx)>=LHX(55))
3916 			{
3917 				GameName[k]=GameName[k+1]=GameName[k+2]='.';
3918 				k+=3;
3919 				break;
3920 			}
3921 			GameName[k++]=Active_games[i].game_name[j];
3922 		}
3923 		GameName[k]=0;
3924 
3925 
3926 		nplayers=Active_games[i].numconnected;
3927 
3928 		if (Active_games[i].levelnum < 0)
3929 			sprintf(levelname, "S%d", -Active_games[i].levelnum);
3930 		else
3931 			sprintf(levelname, "%d", Active_games[i].levelnum);
3932 
3933 		if (game_status == NETSTAT_STARTING)
3934 		{
3935 			sprintf (menus[i+2].text,"%d.\t%s \t%s \t  %d/%d \t%s \t %s \t%s",
3936 					 i+1,GameName,ModeLetters[Active_games[i].gamemode],nplayers,
3937 					 Active_games[i].max_numplayers,MissName,levelname,"Forming");
3938 		}
3939 		else if (game_status == NETSTAT_PLAYING)
3940 		{
3941 			join_status=can_join_netgame(&Active_games[i],NULL);
3942 			//		 mprintf ((0,"Joinstatus=%d\n",join_status));
3943 
3944 			if (join_status==1)
3945 				sprintf (menus[i+2].text,"%d.\t%s \t%s \t  %d/%d \t%s \t %s \t%s",
3946 						 i+1,GameName,ModeLetters[Active_games[i].gamemode],nplayers,
3947 						 Active_games[i].max_numplayers,MissName,levelname,"Open");
3948 			else if (join_status==2)
3949 				sprintf (menus[i+2].text,"%d.\t%s \t%s \t  %d/%d \t%s \t %s \t%s",
3950 						 i+1,GameName,ModeLetters[Active_games[i].gamemode],nplayers,
3951 						 Active_games[i].max_numplayers,MissName,levelname,"Full");
3952 			else if (join_status==3)
3953 				sprintf (menus[i+2].text,"%d.\t%s \t%s \t  %d/%d \t%s \t %s \t%s",
3954 						 i+1,GameName,ModeLetters[Active_games[i].gamemode],nplayers,
3955 						 Active_games[i].max_numplayers,MissName,levelname,"Restrict");
3956 			else
3957 				sprintf (menus[i+2].text,"%d.\t%s \t%s \t  %d/%d \t%s \t %s \t%s",
3958 						 i+1,GameName,ModeLetters[Active_games[i].gamemode],nplayers,
3959 						 Active_games[i].max_numplayers,MissName,levelname,"Closed");
3960 
3961 		}
3962 		else
3963 			sprintf (menus[i+2].text,"%d.\t%s \t%s \t  %d/%d \t%s \t %s \t%s",
3964 					 i+1,GameName,ModeLetters[Active_games[i].gamemode],nplayers,
3965 					 Active_games[i].max_numplayers,MissName,levelname,"Between");
3966 
3967 
3968 		Assert(strlen(menus[i+2].text) < 100);
3969 		menus[i+2].redraw = 1;
3970 	}
3971 
3972 	for (i = num_active_games; i < MAX_ACTIVE_NETGAMES; i++)
3973 	{
3974 		sprintf(menus[i+2].text, "%d.                                                     ",i+1);
3975 		menus[i+2].redraw = 1;
3976 	}
3977 }
3978 
3979 int
network_wait_for_sync(void)3980 network_wait_for_sync(void)
3981 {
3982 	char text[60];
3983 	newmenu_item m[2];
3984 	int i, choice;
3985 
3986 	Network_status = NETSTAT_WAITING;
3987 
3988 	m[0].type=NM_TYPE_TEXT; m[0].text = text;
3989 	m[1].type=NM_TYPE_TEXT; m[1].text = TXT_NET_LEAVE;
3990 
3991 	i = network_send_request();
3992 
3993 	if (i < 0)
3994 		return(-1);
3995 
3996 	sprintf( m[0].text, "%s\n'%s' %s", TXT_NET_WAITING, NetPlayers.players[i].callsign, TXT_NET_TO_ENTER );
3997 
3998 menu:
3999 	choice=newmenu_do( NULL, TXT_WAIT, 2, m, network_sync_poll );
4000 
4001 	if (choice > -1)
4002 		goto menu;
4003 
4004 	if (Network_status != NETSTAT_PLAYING)
4005 	{
4006 		sequence_packet me;
4007 
4008 //              if (Network_status == NETSTAT_ENDLEVEL)
4009 //              {
4010 //                      network_send_endlevel_packet(0);
4011 //                      longjmp(LeaveGame, 0);
4012 //              }
4013 
4014 		mprintf((0, "Aborting join.\n"));
4015 		me.type = PID_QUIT_JOINING;
4016 		memcpy( me.player.callsign, Players[Player_num].callsign, CALLSIGN_LEN+1 );
4017 		if (Network_game_type == IPX_GAME) {
4018 			memcpy( me.player.network.ipx.node, ipx_get_my_local_address(), 6 );
4019 			memcpy( me.player.network.ipx.server, ipx_get_my_server_address(), 4 );
4020 			send_internetwork_sequence_packet(me, NetPlayers.players[0].network.ipx.server, NetPlayers.players[0].network.ipx.node);
4021 		#ifdef MACINTOSH
4022 		} else {
4023 			me.player.network.appletalk.node = appletalk_get_my_node();
4024 			me.player.network.appletalk.net = appletalk_get_my_net();
4025 			me.player.network.appletalk.socket = appletalk_get_my_socket();
4026 		#endif
4027 		}
4028 		N_players = 0;
4029 		Function_mode = FMODE_MENU;
4030 		Game_mode = GM_GAME_OVER;
4031 		return(-1);     // they cancelled
4032 	}
4033 	return(0);
4034 }
4035 
4036 void
network_request_poll(int nitems,newmenu_item * menus,int * key,int citem)4037 network_request_poll( int nitems, newmenu_item * menus, int * key, int citem )
4038 {
4039 	// Polling loop for waiting-for-requests menu
4040 
4041 	int i = 0;
4042 	int num_ready = 0;
4043 
4044 	menus = menus;
4045 	citem = citem;
4046 	nitems = nitems;
4047 	key = key;
4048 
4049 	// Send our endlevel packet at regular intervals
4050 
4051 //      if (timer_get_approx_seconds() > t1+ENDLEVEL_SEND_INTERVAL)
4052 //      {
4053 //              network_send_endlevel_packet();
4054 //              t1 = timer_get_approx_seconds();
4055 //      }
4056 
4057 	network_listen();
4058 
4059 	for (i = 0; i < N_players; i++)
4060 	{
4061 		if ((Players[i].connected == 1) || (Players[i].connected == 0))
4062 			num_ready++;
4063 	}
4064 
4065 	if (num_ready == N_players) // All players have checked in or are disconnected
4066 	{
4067 		*key = -2;
4068 	}
4069 }
4070 
4071 void
network_wait_for_requests(void)4072 network_wait_for_requests(void)
4073 {
4074 	// Wait for other players to load the level before we send the sync
4075 	int choice, i;
4076 	newmenu_item m[1];
4077 
4078 	Network_status = NETSTAT_WAITING;
4079 
4080 	m[0].type=NM_TYPE_TEXT; m[0].text = TXT_NET_LEAVE;
4081 
4082 	mprintf((0, "Entered wait_for_requests : N_players = %d.\n", N_players));
4083 
4084 	for (choice = 0; choice < N_players; choice++)
4085 		mprintf((0, "Players[%d].connected = %d.\n", choice, Players[choice].connected));
4086 
4087 	Network_status = NETSTAT_WAITING;
4088 	network_flush();
4089 
4090 	Players[Player_num].connected = 1;
4091 
4092 menu:
4093 	choice = newmenu_do(NULL, TXT_WAIT, 1, m, network_request_poll);
4094 
4095 	if (choice == -1)
4096 	{
4097 		// User aborted
4098 		choice = nm_messagebox(NULL, 3, TXT_YES, TXT_NO, TXT_START_NOWAIT, TXT_QUITTING_NOW);
4099 		if (choice == 2)
4100 			return;
4101 		if (choice != 0)
4102 			goto menu;
4103 
4104 		// User confirmed abort
4105 
4106 		for (i=0; i < N_players; i++) {
4107 			if ((Players[i].connected != 0) && (i != Player_num)) {
4108 				if (Network_game_type == IPX_GAME)
4109 					network_dump_player(NetPlayers.players[i].network.ipx.server, NetPlayers.players[i].network.ipx.node, DUMP_ABORTED);
4110 				#ifdef MACINTOSH
4111 				else
4112 					network_dump_appletalk_player(NetPlayers.players[i].network.appletalk.node, NetPlayers.players[i].network.appletalk.net, NetPlayers.players[i].network.appletalk.socket, DUMP_ABORTED);
4113 				#endif
4114 			}
4115 		}
4116 
4117 		#ifdef MACINTOSH
4118 		if (Network_game_type == APPLETALK_GAME)
4119 			network_release_registered_game();
4120 		#endif
4121 		longjmp(LeaveGame, 0);
4122 	}
4123 	else if (choice != -2)
4124 		goto menu;
4125 }
4126 
4127 int
network_level_sync(void)4128 network_level_sync(void)
4129 {
4130 	// Do required syncing between (before) levels
4131 
4132 	int result;
4133 
4134 	mprintf((0, "Player %d entering network_level_sync.\n", Player_num));
4135 
4136 	MySyncPackInitialized = 0;
4137 
4138 //      my_segments_checksum = netmisc_calc_checksum(Segments, sizeof(segment)*(Highest_segment_index+1));
4139 
4140 	network_flush(); // Flush any old packets
4141 
4142 	if (N_players == 0)
4143 		result = network_wait_for_sync();
4144 	else if (network_i_am_master())
4145 	{
4146 		network_wait_for_requests();
4147 		network_send_sync();
4148 		result = 0;
4149 	}
4150 	else
4151 		result = network_wait_for_sync();
4152 
4153    network_count_powerups_in_mine();
4154 
4155 	if (result)
4156 	{
4157 		Players[Player_num].connected = 0;
4158 		network_send_endlevel_packet();
4159 		#ifdef MACINTOSH
4160 		if (Network_game_type == APPLETALK_GAME)
4161 			network_release_registered_game();
4162 		#endif
4163 		longjmp(LeaveGame, 0);
4164 	}
4165 	return(0);
4166 }
4167 
network_count_powerups_in_mine(void)4168 void network_count_powerups_in_mine(void)
4169  {
4170   int i;
4171 
4172   for (i=0;i<MAX_POWERUP_TYPES;i++)
4173 	PowerupsInMine[i]=0;
4174 
4175   for (i=0;i<=Highest_object_index;i++)
4176 	{
4177 	 if (Objects[i].type==OBJ_POWERUP)
4178 	  {
4179 		PowerupsInMine[Objects[i].id]++;
4180 		if (multi_powerup_is_4pack(Objects[i].id))
4181 		   PowerupsInMine[Objects[i].id-1]+=4;
4182 	  }
4183 	}
4184 
4185  }
4186 
4187 #ifdef MACINTOSH
4188 
4189 // code to release the NBP binding of an appletalk game
4190 
network_release_registered_game()4191 void network_release_registered_game()
4192 {
4193 	if (Network_game_type == APPLETALK_GAME)
4194 		appletalk_remove_netgame();
4195 }
4196 
4197 // code to sort zone lists....
4198 
zone_sort_func(const char ** e0,const char ** e1)4199 int zone_sort_func(const char **e0, const char **e1)
4200 {
4201 	return strcmp(*e0, *e1);
4202 }
4203 
network_get_appletalk_zone()4204 void network_get_appletalk_zone()
4205 {
4206 	int num_zones, i, item, default_item;
4207 	char **zone_list;
4208 	char default_zone[MAX_ZONE_LENGTH];			// my zone
4209 
4210 	Network_zone_name[0] = '\0';
4211 
4212 	show_boxed_message("Looking for AppleTalk Zones");
4213 	num_zones = appletalk_get_zone_names(&zone_list);
4214 	clear_boxed_message();
4215 
4216 	if (num_zones < 0)	{		// error in getting zone list...maybe no router available....
4217 		if ( (num_zones == tooManyReqs) || (num_zones == noDataArea) ){
4218 			nm_messagebox(NULL, 1, TXT_OK, "AppleTalk Network is too busy.\nPlease try again shortly.");
4219 			longjmp(LeaveGame,0);
4220 		}
4221 		num_zones = 0;
4222 	}
4223 
4224 	if (num_zones == 0) {
4225 		strcpy(Network_zone_name, DEFAULT_ZONE_NAME);
4226 		return;
4227 	}
4228 
4229 	if (num_zones == 1) {
4230 		Network_zone_name[0] = (char)(strlen(zone_list[0]));
4231 		memcpy( &(Network_zone_name[1]), zone_list[0], strlen(zone_list[0]) );
4232 		goto zone_done;
4233 	}
4234 
4235 // sort the zone names
4236 
4237 	for (i = 0; i < num_zones; i++)
4238 		strlwr(zone_list[i]);
4239 
4240 	qsort(zone_list, num_zones, sizeof(char *), zone_sort_func);
4241 
4242 // get my current zone so we can highlight that one first
4243 
4244 	if (appletalk_get_my_zone(default_zone))
4245 		default_item = 0;
4246 	else {
4247 		for (i = 0; i < num_zones; i++) {
4248 			if ( !stricmp(zone_list[i], default_zone) ) {
4249 				default_item = i;
4250 				break;
4251 			}
4252 		}
4253 	}
4254 
4255 rezone:
4256 	item = newmenu_listbox1("AppleTalk Zones", num_zones, zone_list, 0, default_item, NULL);
4257 
4258 	if (item == -1)
4259 		goto rezone;
4260 
4261 	Network_zone_name[0] = (char)(strlen(zone_list[item]));
4262 	memcpy( &(Network_zone_name[1]), zone_list[item], strlen(zone_list[item]) );
4263 
4264 zone_done:
4265 	for (i = 0; i < num_zones; i++)
4266 		d_free(zone_list[i]);
4267 	d_free(zone_list);
4268 }
4269 #endif
4270 
4271 void nm_draw_background1(char * filename);
4272 
network_join_game()4273 void network_join_game()
4274 {
4275 	int choice, i;
4276 	char menu_text[MAX_ACTIVE_NETGAMES+2][200];
4277 
4278 	newmenu_item m[MAX_ACTIVE_NETGAMES+2];
4279 
4280 	if (Network_game_type == IPX_GAME) {
4281 		if ( !Network_active )
4282 		{
4283 			nm_messagebox(NULL, 1, TXT_OK, TXT_IPX_NOT_FOUND);
4284 			return;
4285 		}
4286 	#ifdef MACINTOSH
4287 	} else if (Appletalk_active <= 0) {
4288 		char buf[256];
4289 
4290 		switch (Appletalk_active) {
4291 			case APPLETALK_NOT_OPEN:
4292 				sprintf(buf, "Appletalk is not currently active.\nPlease enable AppleTalk from the\nChooser and restart Descent.");
4293 				break;
4294 			case APPLETALK_BAD_LISTENER:
4295 				sprintf(buf, "The Resource Fork of Descent appears damaged.\nPlease re-install Descent or contact\nMacPlay technical support.");
4296 				break;
4297 			case APPLETALK_NO_LOCAL_ADDR:
4298 				sprintf(buf, "Wow! Strange!\n\nNo Local Address.");
4299 				break;
4300 			case APPLETALK_NO_SOCKET:
4301 				sprintf(buf, "All AppleTalk sockets are in use.\nTry shutting down other network\napplications and restarting Descent.\n");
4302 				break;
4303 		}
4304 		nm_messagebox(NULL, 1, TXT_OK, buf);
4305 		return;
4306 	#endif
4307 	}
4308 
4309 	network_init();
4310 
4311 	N_players = 0;
4312 
4313 	setjmp(LeaveGame);
4314 
4315 	#ifdef MACINTOSH
4316 	if (Network_game_type == APPLETALK_GAME)
4317 		network_get_appletalk_zone();
4318 	#endif
4319 
4320 	Network_send_objects = 0;
4321 	Network_sending_extras=0;
4322 	Network_rejoined=0;
4323 
4324 	Network_status = NETSTAT_BROWSING; // We are looking at a game menu
4325 
4326    network_flush();
4327 	network_listen();  // Throw out old info
4328 
4329 	#ifdef MACINTOSH
4330 	if (Network_game_type == IPX_GAME)
4331 	#endif		// note link to if
4332 		network_send_game_list_request(); // broadcast a request for lists
4333 
4334 	num_active_games = 0;
4335 
4336    memset(m, 0, sizeof(newmenu_item)*MAX_ACTIVE_NETGAMES);
4337    memset(Active_games, 0, sizeof(netgame_info)*MAX_ACTIVE_NETGAMES);
4338    memset(ActiveNetPlayers,0,sizeof(AllNetPlayers_info)*MAX_ACTIVE_NETGAMES);
4339 
4340 	gr_set_fontcolor(BM_XRGB(15,15,23),-1);
4341 
4342 	m[0].text = menu_text[0];
4343 	m[0].type = NM_TYPE_TEXT;
4344 	if (Network_game_type == IPX_GAME) {
4345 		if (Network_allow_socket_changes)
4346 			sprintf( m[0].text, "\tCurrent IPX Socket is default %+d (PgUp/PgDn to change)", Network_socket );
4347 		else
4348 			strcpy( m[0].text, "" ); //sprintf( m[0].text, "" );
4349 	#ifdef MACINTOSH
4350 	} else {
4351 		p2cstr(Network_zone_name);
4352 		if (strcmp(Network_zone_name, "*"))		// only print if there is a zone name
4353 			sprintf(m[0].text, "\tCurrent Zone is %s", Network_zone_name);		// is Network_zone_name a pascal string????
4354 		c2pstr(Network_zone_name);
4355 	#endif
4356 	}
4357 
4358 	m[1].text=menu_text[1];
4359 	m[1].type=NM_TYPE_TEXT;
4360 	sprintf (m[1].text,"\tGAME \tMODE \t#PLYRS \tMISSION \tLEV \tSTATUS");
4361 
4362 	for (i = 0; i < MAX_ACTIVE_NETGAMES; i++) {
4363 		m[i+2].text = menu_text[i+2];
4364 		m[i+2].type = NM_TYPE_MENU;
4365 		sprintf(m[i+2].text, "%d.                                                               ", i+1);
4366 		m[i+2].redraw = 1;
4367 	}
4368 
4369 	Network_games_changed = 1;
4370 remenu:
4371 	SurfingNet=1;
4372 	nm_draw_background1(Menu_pcx_name);             //load this here so if we abort after loading level, we restore the palette
4373 	gr_palette_load(gr_palette);
4374    ExtGameStatus=GAMESTAT_JOIN_NETGAME;
4375 	choice=newmenu_dotiny("NETGAMES", NULL,MAX_ACTIVE_NETGAMES+2, m, network_join_poll);
4376 	SurfingNet=0;
4377 
4378 	if (choice==-1) {
4379 		Network_status = NETSTAT_MENU;
4380 		return; // they cancelled
4381 	}
4382    choice-=2;
4383 
4384 	if (choice >=num_active_games)
4385 	{
4386 		nm_messagebox(TXT_SORRY, 1, TXT_OK, TXT_INVALID_CHOICE);
4387 		goto remenu;
4388 	}
4389 
4390 	// Choice has been made and looks legit
4391 	if (Active_games[choice].game_status == NETSTAT_ENDLEVEL)
4392 	{
4393 		nm_messagebox(TXT_SORRY, 1, TXT_OK, TXT_NET_GAME_BETWEEN2);
4394 		goto remenu;
4395 	}
4396 
4397 	if (Active_games[choice].protocol_version != MULTI_PROTO_VERSION)
4398 	{
4399 		if (Active_games[choice].protocol_version == 3) {
4400 			#ifndef SHAREWARE
4401 				nm_messagebox(TXT_SORRY, 1, TXT_OK, "Your version of Descent 2\nis incompatible with the\nDemo version");
4402 			#endif
4403 		}
4404 		else if (Active_games[choice].protocol_version == 4) {
4405 			#ifdef SHAREWARE
4406 				nm_messagebox(TXT_SORRY, 1, TXT_OK, "This Demo version of\nDescent 2 is incompatible\nwith the full commercial version");
4407 			#endif
4408 		}
4409 		else
4410 			nm_messagebox(TXT_SORRY, 1, TXT_OK, TXT_VERSION_MISMATCH);
4411 
4412 		goto remenu;
4413 	}
4414 
4415 #ifndef SHAREWARE
4416 	{
4417 		// Check for valid mission name
4418 			mprintf((0, "Loading mission:%s.\n", Active_games[choice].mission_name));
4419 			if (!load_mission_by_name(Active_games[choice].mission_name))
4420 			{
4421 				nm_messagebox(NULL, 1, TXT_OK, TXT_MISSION_NOT_FOUND);
4422 				goto remenu;
4423 			}
4424 	}
4425 #endif
4426 
4427 #if defined (D2_OEM)
4428 	{
4429 		if (Active_games[choice].levelnum>8)
4430 		 {
4431 				nm_messagebox(NULL, 1, TXT_OK, "This OEM version only supports\nthe first 8 levels!");
4432 				goto remenu;
4433 		 }
4434 	}
4435 #endif
4436 
4437      if (!network_wait_for_all_info (choice))
4438 		{
4439 		  nm_messagebox (TXT_SORRY,1,TXT_OK,"There was a join error!");
4440 		  Network_status = NETSTAT_BROWSING; // We are looking at a game menu
4441 		  goto remenu;
4442 		}
4443 
4444 	  Network_status = NETSTAT_BROWSING; // We are looking at a game menu
4445 
4446      if (!can_join_netgame(&Active_games[choice],&ActiveNetPlayers[choice]))
4447 			{
4448 				if (Active_games[choice].numplayers == Active_games[choice].max_numplayers)
4449 					nm_messagebox(TXT_SORRY, 1, TXT_OK, TXT_GAME_FULL);
4450 				else
4451 					nm_messagebox(TXT_SORRY, 1, TXT_OK, TXT_IN_PROGRESS);
4452 				goto remenu;
4453 			}
4454 
4455 	// Choice is valid, prepare to join in
4456 
4457 	memcpy(&Netgame, &Active_games[choice], sizeof(netgame_info));
4458    memcpy (&NetPlayers,&ActiveNetPlayers[choice],sizeof(AllNetPlayers_info));
4459 
4460 	Difficulty_level = Netgame.difficulty;
4461 	MaxNumNetPlayers = Netgame.max_numplayers;
4462 	change_playernum_to(1);
4463 
4464 	#ifdef MACINTOSH
4465 
4466 // register the joining player with NBP.  This will have the nice effect of a player wanting to
4467 // join to be able to see the netgame if this player were to become the master.
4468 
4469 	if (Network_game_type == APPLETALK_GAME) {
4470 		OSErr err;
4471 		int count = 0;
4472 		fix t1;
4473 
4474 		show_boxed_message("Registering Netgame");
4475 		do {
4476 			err = appletalk_register_netgame( Active_games[choice].game_name, TickCount() );
4477 			t1 = timer_get_fixed_seconds() + F1_0;
4478 			while ( timer_get_fixed_seconds() < t1 ) ;
4479 			count++;
4480 		} while ( (err == nbpDuplicate) && (count != MAX_REGISTER_TRIES) );
4481 		clear_boxed_message();
4482 		if ( (err == tooManyReqs) || (count == MAX_REGISTER_TRIES) ) {
4483 			nm_messagebox(NULL, 1, TXT_OK, "AppleTalk Network is too busy.\nPlease try again shortly.");
4484 			goto remenu;
4485 		}
4486 	}
4487 	#endif
4488 
4489 	network_set_game_mode(Netgame.gamemode);
4490 
4491 	network_AdjustMaxDataSize ();
4492 
4493 	StartNewLevel(Netgame.levelnum, 0);
4494 
4495 	return;         // look ma, we're in a game!!!
4496 }
4497 
network_AdjustMaxDataSize()4498 void network_AdjustMaxDataSize ()
4499  {
4500 
4501    if (Netgame.ShortPackets)
4502 	MaxXDataSize=NET_XDATA_SIZE;
4503    else
4504       MaxXDataSize=NET_XDATA_SIZE;
4505  }
4506 
4507 
4508 fix StartWaitAllTime=0;
4509 int WaitAllChoice=0;
4510 #define ALL_INFO_REQUEST_INTERVAL F1_0*3
4511 
network_wait_all_poll(int nitems,newmenu_item * menus,int * key,int citem)4512 void network_wait_all_poll( int nitems, newmenu_item * menus, int * key, int citem )
4513  {
4514   static fix t1=0;
4515 
4516   menus=menus;
4517   nitems=nitems;
4518   citem=citem;
4519 
4520   if (timer_get_approx_seconds() > t1+ALL_INFO_REQUEST_INTERVAL)
4521 	{
4522 		network_send_all_info_request(PID_SEND_ALL_GAMEINFO,SecurityCheck);
4523 		t1 = timer_get_approx_seconds();
4524 	}
4525 
4526   network_do_big_wait(WaitAllChoice);
4527 
4528   if(SecurityCheck==-1)
4529    *key=-2;
4530  }
4531 
network_wait_for_all_info(int choice)4532 int network_wait_for_all_info (int choice)
4533  {
4534   int pick;
4535 
4536   newmenu_item m[2];
4537 
4538   m[0].type=NM_TYPE_TEXT; m[0].text = "Press Escape to cancel";
4539 
4540   WaitAllChoice=choice;
4541   StartWaitAllTime=timer_get_approx_seconds();
4542   SecurityCheck=Active_games[choice].Security;
4543   NetSecurityFlag=0;
4544 
4545   GetMenu:
4546   pick=newmenu_do( NULL, "Connecting...", 1, m, network_wait_all_poll );
4547 
4548   if (pick>-1 && SecurityCheck!=-1)
4549 	goto GetMenu;
4550 
4551   if (SecurityCheck==-1)
4552     {
4553 	   SecurityCheck=0;
4554 	   return (1);
4555 	 }
4556   SecurityCheck=0;
4557   return (0);
4558  }
4559 
network_do_big_wait(int choice)4560 void network_do_big_wait(int choice)
4561 {
4562 	int size;
4563 	ubyte packet[IPX_MAX_DATA_SIZE],*data;
4564 	AllNetPlayers_info *temp_info;
4565 #ifdef WORDS_BIGENDIAN
4566 	AllNetPlayers_info info_struct;
4567 #endif
4568 #ifdef MACINTOSH
4569 	ubyte apacket[APPLETALK_MAX_DATA_SIZE];
4570 #endif
4571 
4572 	#ifdef MACINTOSH
4573 	if (Network_game_type == APPLETALK_GAME)
4574 		size=appletalk_get_packet_data( apacket );
4575 	else
4576 	#endif
4577 		size=ipx_get_packet_data( packet );
4578 
4579   if (size>0)
4580 	{
4581 		#ifdef MACINTOSH
4582 		if (Network_game_type == APPLETALK_GAME)
4583 			data = apacket;
4584 		else
4585 		#endif
4586 			data = packet;
4587 
4588 	 switch (data[0])
4589      {
4590 		case PID_GAME_INFO:
4591 
4592 		if (Network_game_type == IPX_GAME) {
4593 			receive_full_netgame_packet(data, &TempNetInfo);
4594 		} else {
4595 			memcpy((ubyte *)&TempNetInfo, data, sizeof(netgame_info));
4596 		}
4597 		mprintf ((0,"This is %s game with a security of %d\n",TempNetInfo.game_name,TempNetInfo.Security));
4598 
4599       if (TempNetInfo.Security !=SecurityCheck)
4600 		 {
4601 		  mprintf ((0,"Bad security on big_wait...rejecting.\n"));
4602 		  break;
4603 		 }
4604 
4605       if (NetSecurityFlag==NETSECURITY_WAIT_FOR_GAMEINFO)
4606 	   {
4607 		   if (TempPlayersInfo->Security==TempNetInfo.Security)
4608 			{
4609 			  mprintf ((0,"EQUAL !: Game=%d Players=%d ",TempPlayersInfo->Security,TempNetInfo.Security));
4610 	        if (TempPlayersInfo->Security==SecurityCheck)
4611 			  {
4612 			  		memcpy (&Active_games[choice],(ubyte *)&TempNetInfo,sizeof(netgame_info));
4613 			  		memcpy (&ActiveNetPlayers[choice],TempPlayersInfo,sizeof(AllNetPlayers_info));
4614 			  		SecurityCheck=-1;
4615 			  }
4616 			}
4617 	   }
4618 	  	else
4619 	   {
4620 	      NetSecurityFlag=NETSECURITY_WAIT_FOR_PLAYERS;
4621 	      NetSecurityNum=TempNetInfo.Security;
4622 
4623 	      if (network_wait_for_playerinfo())
4624 			{
4625 			   mprintf ((0,"HUH? Game=%d Player=%d\n",NetSecurityNum,TempPlayersInfo->Security));
4626 				memcpy (&Active_games[choice],(ubyte *)&TempNetInfo,sizeof(netgame_info));
4627 				memcpy (&ActiveNetPlayers[choice],TempPlayersInfo,sizeof(AllNetPlayers_info));
4628 			  	SecurityCheck=-1;
4629 			}
4630 	      NetSecurityFlag=0;
4631 	      NetSecurityNum=0;
4632 	   }
4633 	break;
4634       case PID_PLAYERSINFO:
4635 	       mprintf ((0,"Got a PID_PLAYERSINFO!\n"));
4636 
4637 			if (Network_game_type == IPX_GAME) {
4638 #ifndef WORDS_BIGENDIAN
4639 				temp_info=(AllNetPlayers_info *)data;
4640 #else
4641 				receive_netplayers_packet(data, &info_struct);
4642 				temp_info = &info_struct;
4643 #endif
4644 			} else {
4645 				temp_info = (AllNetPlayers_info *)data;
4646 			}
4647 			if (temp_info->Security!=SecurityCheck)
4648 				break;     // If this isn't the guy we're looking for, move on
4649 
4650 			memcpy (&TempPlayersBase,(ubyte *)&temp_info,sizeof(AllNetPlayers_info));
4651 			TempPlayersInfo=&TempPlayersBase;
4652 			WaitingForPlayerInfo=0;
4653 			NetSecurityNum=TempPlayersInfo->Security;
4654 			NetSecurityFlag=NETSECURITY_WAIT_FOR_GAMEINFO;
4655 			break;
4656 	   }
4657 	}
4658 }
4659 
network_leave_game()4660 void network_leave_game()
4661 {
4662    int nsave;
4663 
4664 	network_do_frame(1, 1);
4665 
4666    #ifdef NETPROFILING
4667 	fclose (SendLogFile);
4668 	   fclose (RecieveLogFile);
4669 	#endif
4670 
4671 	if ((network_i_am_master()))
4672 	{
4673 		while (Network_sending_extras>1 && Player_joining_extras!=-1)
4674 		  network_send_extras();
4675 
4676 		Netgame.numplayers = 0;
4677 	   nsave=N_players;
4678 	   N_players=0;
4679 		network_send_game_info(NULL);
4680 		N_players=nsave;
4681 
4682 		mprintf ((0,"HEY! I'm master and I've left.\n"));
4683 	}
4684 
4685 	Players[Player_num].connected = 0;
4686 	network_send_endlevel_packet();
4687 	change_playernum_to(0);
4688 	Game_mode = GM_GAME_OVER;
4689    write_player_file();
4690 
4691 //	WIN(ipx_destroy_read_thread());
4692 
4693 	network_flush();
4694 }
4695 
network_flush()4696 void network_flush()
4697 {
4698 	#ifdef MACINTOSH
4699 	ubyte apacket[APPLETALK_MAX_DATA_SIZE];
4700 	#endif
4701 	ubyte packet[IPX_MAX_DATA_SIZE];
4702 
4703 	#ifdef MACINTOSH
4704 	if ( (Network_game_type == APPLETALK_GAME) && (Appletalk_active <= 0) )
4705 		return;
4706 	#endif
4707 
4708 	if ( Network_game_type == IPX_GAME )
4709 		if (!Network_active) return;
4710 
4711 	#ifdef MACINTOSH
4712 	if (Network_game_type == APPLETALK_GAME)
4713 		while (appletalk_get_packet_data(apacket) > 0) ;
4714 	else
4715 	#endif
4716 		while (ipx_get_packet_data(packet) > 0) ;
4717 }
4718 
network_listen()4719 void network_listen()
4720 {
4721 	#ifdef MACINTOSH
4722 	ubyte apacket[APPLETALK_MAX_DATA_SIZE];
4723 	#endif
4724 	int size;
4725 	ubyte packet[IPX_MAX_DATA_SIZE];
4726 	int i,loopmax=999;
4727 
4728 	if (Network_status==NETSTAT_PLAYING && Netgame.ShortPackets && !Network_send_objects)
4729 	 {
4730 		loopmax=N_players*Netgame.PacketsPerSec;
4731 	 }
4732 
4733 	#ifdef MACINTOSH
4734 	if ( (Network_game_type == APPLETALK_GAME) && (Appletalk_active <= 0) )
4735 		return;
4736 	#endif
4737 
4738 	if (Network_game_type == IPX_GAME)
4739 		if (!Network_active) return;
4740 
4741 	if (!(Game_mode & GM_NETWORK) && (Function_mode == FMODE_GAME))
4742 		mprintf((0, "Calling network_listen() when not in net game.\n"));
4743 
4744 	WaitingForPlayerInfo=1;
4745 	NetSecurityFlag=NETSECURITY_OFF;
4746 
4747 	i=1;
4748 	if (Network_game_type == IPX_GAME) {
4749 		size = ipx_get_packet_data( packet );
4750 		while ( size > 0)       {
4751 			network_process_packet( packet, size );
4752 			if (++i>loopmax)
4753 			 break;
4754 			size = ipx_get_packet_data( packet );
4755 		}
4756 	#ifdef MACINTOSH
4757 	} else {
4758 		size = appletalk_get_packet_data( apacket );
4759 		while ( size > 0)       {
4760 			network_process_packet( apacket, size );
4761 			if (++i>loopmax)
4762 			 break;
4763 			size = appletalk_get_packet_data( apacket );
4764 		}
4765 	#endif
4766 	}
4767 }
4768 
network_wait_for_playerinfo()4769 int network_wait_for_playerinfo()
4770 {
4771 	int size,retries=0;
4772 	ubyte packet[IPX_MAX_DATA_SIZE];
4773 	struct AllNetPlayers_info *TempInfo;
4774 	fix basetime;
4775 	ubyte id;
4776 #ifdef WORDS_BIGENDIAN
4777 	AllNetPlayers_info info_struct;
4778 #endif
4779 #ifdef MACINTOSH
4780 	ubyte apacket[APPLETALK_MAX_DATA_SIZE];
4781 #endif
4782 
4783 	#ifdef MACINTOSH
4784 	if ( (Network_game_type == APPLETALK_GAME) && (Appletalk_active <= 0) )
4785 		return;
4786 	#endif
4787 
4788 	if ( Network_game_type == IPX_GAME)
4789 		if (!Network_active) return(0);
4790 
4791       //  if (!WaitingForPlayerInfo)
4792 	// return (1);
4793 
4794 	if (!(Game_mode & GM_NETWORK) && (Function_mode == FMODE_GAME))
4795 		{
4796 	mprintf((0, "Calling network_wait_for_playerinfo() when not in net game.\n"));
4797 		}
4798 	if (Network_status==NETSTAT_PLAYING)
4799 	 {
4800 		  Int3(); //MY GOD! Get Jason...this is the source of many problems
4801 	     return (0);
4802 	 }
4803    basetime=timer_get_approx_seconds();
4804 
4805    while (WaitingForPlayerInfo && retries<50 && (timer_get_approx_seconds()<(basetime+(F1_0*5))))
4806       {
4807 		if (Network_game_type == IPX_GAME) {
4808 			size = ipx_get_packet_data( packet );
4809 			id = packet[0];
4810 		} else {
4811 			#ifdef MACINTOSH
4812 			size = appletalk_get_packet_data( apacket );
4813 			id = apacket[0];
4814 			#endif
4815 		}
4816 
4817 	if (size>0 && id==PID_PLAYERSINFO)
4818 	{
4819 #ifdef WORDS_BIGENDIAN
4820 #ifdef MACINTOSH
4821 		if (Network_game_type == APPLETALK_GAME) {
4822 			TempInfo = (AllNetPlayers_info *)apacket;
4823 		} else
4824 #endif
4825 		{
4826 			receive_netplayers_packet(packet, &info_struct);
4827 			TempInfo = &info_struct;
4828 		}
4829 #else
4830 		TempInfo=(AllNetPlayers_info *)packet;
4831 #endif
4832 
4833 		retries++;
4834 
4835 	    if (NetSecurityFlag==NETSECURITY_WAIT_FOR_PLAYERS)
4836 	     {
4837 	      if (NetSecurityNum==TempInfo->Security)
4838 	       {
4839 		mprintf ((0,"HEYEQUAL: Player=%d Game=%d\n",TempInfo->Security,NetSecurityNum));
4840 		memcpy (&TempPlayersBase,(ubyte *)TempInfo,sizeof(AllNetPlayers_info));
4841 		TempPlayersInfo=&TempPlayersBase;
4842 		NetSecurityFlag=NETSECURITY_OFF;
4843 		NetSecurityNum=0;
4844 		WaitingForPlayerInfo=0;
4845 		return (1);
4846 	       }
4847 	      else
4848 	       continue;
4849 	     }
4850 	    else
4851 	     {
4852 	      mprintf ((0,"I'm original!\n"));
4853 
4854 	      NetSecurityNum=TempInfo->Security;
4855 	      NetSecurityFlag=NETSECURITY_WAIT_FOR_GAMEINFO;
4856 
4857 	      memcpy (&TempPlayersBase,(ubyte *)TempInfo,sizeof(AllNetPlayers_info));
4858 	      TempPlayersInfo=&TempPlayersBase;
4859 	      WaitingForPlayerInfo=0;
4860 	      return (1);
4861 	     }
4862 	   }
4863 	 }
4864    return (0);
4865   }
4866 
4867 
network_send_data(ubyte * ptr,int len,int urgent)4868 void network_send_data( ubyte * ptr, int len, int urgent )
4869 {
4870 	char check;
4871 
4872    #ifdef NETPROFILING
4873 	   TTSent[ptr[0]]++;
4874 	   fprintf (SendLogFile,"Packet type: %d Len:%d Urgent:%d TT=%d\n",ptr[0],len,urgent,TTSent[ptr[0]]);
4875 	   fflush (SendLogFile);
4876 	#endif
4877 
4878 	if (Endlevel_sequence)
4879 		return;
4880 
4881 	if (!MySyncPackInitialized)     {
4882 		MySyncPackInitialized = 1;
4883 		memset( &MySyncPack, 0, sizeof(frame_info) );
4884 	}
4885 
4886 	if (urgent)
4887 		PacketUrgent = 1;
4888 
4889 	if ((MySyncPack.data_size+len) > MaxXDataSize ) {
4890 		check = ptr[0];
4891 		network_do_frame(1, 0);
4892 		if (MySyncPack.data_size != 0) {
4893 			mprintf((0, "%d bytes were added to data by network_do_frame!\n", MySyncPack.data_size));
4894 			Int3();
4895 		}
4896 //              Int3();         // Trying to send too much!
4897 //              return;
4898 		mprintf((0, "Packet overflow, sending additional packet, type %d len %d.\n", ptr[0], len));
4899 		Assert(check == ptr[0]);
4900 	}
4901 
4902 	Assert(MySyncPack.data_size+len <= MaxXDataSize);
4903 
4904 	memcpy( &MySyncPack.data[MySyncPack.data_size], ptr, len );
4905 	MySyncPack.data_size += len;
4906 }
4907 
network_timeout_player(int playernum)4908 void network_timeout_player(int playernum)
4909 {
4910 	// Remove a player from the game if we haven't heard from them in
4911 	// a long time.
4912 	int i, n = 0;
4913 
4914 	Assert(playernum < N_players);
4915 	Assert(playernum > -1);
4916 
4917 	network_disconnect_player(playernum);
4918 	create_player_appearance_effect(&Objects[Players[playernum].objnum]);
4919 
4920 	digi_play_sample(SOUND_HUD_MESSAGE, F1_0);
4921 
4922 	HUD_init_message("%s %s", Players[playernum].callsign, TXT_DISCONNECTING);
4923 	for (i = 0; i < N_players; i++)
4924 		if (Players[i].connected)
4925 			n++;
4926 
4927 	if (n == 1)
4928 	{
4929 		nm_messagebox(NULL, 1, TXT_OK, TXT_YOU_ARE_ONLY);
4930 	}
4931 }
4932 
4933 fix last_send_time = 0;
4934 fix last_timeout_check = 0;
4935 
4936 #ifdef WORDS_BIGENDIAN
squish_short_frame_info(short_frame_info old_info,ubyte * data)4937 void squish_short_frame_info(short_frame_info old_info, ubyte *data)
4938 {
4939 	int loc = 0;
4940 	int tmpi;
4941 	short tmps;
4942 
4943 	data[0] = old_info.type;                                            loc++;
4944 	/* skip three for pad byte */                                       loc += 3;
4945 	tmpi = INTEL_INT(old_info.numpackets);
4946 	memcpy(&(data[loc]), &tmpi, 4);                                     loc += 4;
4947 
4948 	memcpy(&(data[loc]), old_info.thepos.bytemat, 9);                   loc += 9;
4949 	tmps = INTEL_SHORT(old_info.thepos.xo);
4950 	memcpy(&(data[loc]), &tmps, 2);                                     loc += 2;
4951 	tmps = INTEL_SHORT(old_info.thepos.yo);
4952 	memcpy(&(data[loc]), &tmps, 2);                                     loc += 2;
4953 	tmps = INTEL_SHORT(old_info.thepos.zo);
4954 	memcpy(&(data[loc]), &tmps, 2);                                     loc += 2;
4955 	tmps = INTEL_SHORT(old_info.thepos.segment);
4956 	memcpy(&(data[loc]), &tmps, 2);                                     loc += 2;
4957 	tmps = INTEL_SHORT(old_info.thepos.velx);
4958 	memcpy(&(data[loc]), &tmps, 2);                                     loc += 2;
4959 	tmps = INTEL_SHORT(old_info.thepos.vely);
4960 	memcpy(&(data[loc]), &tmps, 2);                                     loc += 2;
4961 	tmps = INTEL_SHORT(old_info.thepos.velz);
4962 	memcpy(&(data[loc]), &tmps, 2);                                     loc += 2;
4963 
4964 	tmps = INTEL_SHORT(old_info.data_size);
4965 	memcpy(&(data[loc]), &tmps, 2);                                     loc += 2;
4966 
4967 	data[loc] = old_info.playernum;                                     loc++;
4968 	data[loc] = old_info.obj_render_type;                               loc++;
4969 	data[loc] = old_info.level_num;                                     loc++;
4970 	memcpy(&(data[loc]), old_info.data, old_info.data_size);
4971 }
4972 #endif
4973 
4974 char NakedBuf[NET_XDATA_SIZE+4];
4975 int NakedPacketLen=0;
4976 int NakedPacketDestPlayer=-1;
4977 
network_do_frame(int force,int listen)4978 void network_do_frame(int force, int listen)
4979 {
4980 	int i;
4981 	short_frame_info ShortSyncPack;
4982 	static fix LastEndlevel=0;
4983 
4984 	if (!(Game_mode&GM_NETWORK)) return;
4985 
4986 	if ((Network_status != NETSTAT_PLAYING) || (Endlevel_sequence)) // Don't send postion during escape sequence...
4987 		goto listen;
4988 
4989   if (NakedPacketLen)
4990 	{
4991 		Assert (NakedPacketDestPlayer>-1);
4992 //         mprintf ((0,"Sending a naked packet to %s (%d bytes)!\n",Players[NakedPacketDestPlayer].callsign,NakedPacketLen));
4993 		if (Network_game_type == IPX_GAME)
4994 			ipx_send_packet_data( (ubyte *)NakedBuf, NakedPacketLen, NetPlayers.players[NakedPacketDestPlayer].network.ipx.server, NetPlayers.players[NakedPacketDestPlayer].network.ipx.node,Players[NakedPacketDestPlayer].net_address );
4995 		#ifdef MACINTOSH
4996 		else
4997 			appletalk_send_packet_data( (ubyte *)NakedBuf, NakedPacketLen, NetPlayers.players[NakedPacketDestPlayer].network.appletalk.node, NetPlayers.players[NakedPacketDestPlayer].network.appletalk.net,NetPlayers.players[NakedPacketDestPlayer].network.appletalk.socket );
4998 		#endif
4999 		NakedPacketLen=0;
5000 		NakedPacketDestPlayer=-1;
5001    }
5002 
5003    if (WaitForRefuseAnswer && timer_get_approx_seconds()>(RefuseTimeLimit+(F1_0*12)))
5004 		WaitForRefuseAnswer=0;
5005 
5006 	last_send_time += FrameTime;
5007 	last_timeout_check += FrameTime;
5008 
5009    // Send out packet PacksPerSec times per second maximum... unless they fire, then send more often...
5010    if ( (last_send_time>F1_0/Netgame.PacketsPerSec) || (Network_laser_fired) || force || PacketUrgent )       {
5011 		if ( Players[Player_num].connected )    {
5012 			int objnum = Players[Player_num].objnum;
5013 			PacketUrgent = 0;
5014 
5015 			if (listen) {
5016 				multi_send_robot_frame(0);
5017 				multi_send_fire();              // Do firing if needed..
5018 			}
5019 
5020 			last_send_time = 0;
5021 
5022 			if (Netgame.ShortPackets)
5023 			{
5024 #ifdef WORDS_BIGENDIAN
5025 				ubyte send_data[IPX_MAX_DATA_SIZE];
5026 				//int squished_size;
5027 #endif
5028 				create_shortpos(&ShortSyncPack.thepos, Objects+objnum, 0);
5029 				ShortSyncPack.type                                      = PID_PDATA;
5030 				ShortSyncPack.playernum                         = Player_num;
5031 				ShortSyncPack.obj_render_type           = Objects[objnum].render_type;
5032 				ShortSyncPack.level_num                         = Current_level_num;
5033 				ShortSyncPack.data_size                         = MySyncPack.data_size;
5034 				memcpy (&ShortSyncPack.data[0],&MySyncPack.data[0],MySyncPack.data_size);
5035 
5036 				for (i=0; i<N_players; i++ )    {
5037 					if ( (Players[i].connected) && (i!=Player_num ) )       {
5038 						MySyncPack.numpackets = Players[i].n_packets_sent++;
5039 						ShortSyncPack.numpackets=MySyncPack.numpackets;
5040 						if (Network_game_type == IPX_GAME) {
5041 #ifndef WORDS_BIGENDIAN
5042 							ipx_send_packet_data( (ubyte *)&ShortSyncPack, sizeof(short_frame_info)-MaxXDataSize+MySyncPack.data_size, NetPlayers.players[i].network.ipx.server, NetPlayers.players[i].network.ipx.node,Players[i].net_address );
5043 #else
5044 							squish_short_frame_info(ShortSyncPack, send_data);
5045 							ipx_send_packet_data( (ubyte *)send_data, IPX_SHORT_INFO_SIZE-MaxXDataSize+MySyncPack.data_size, NetPlayers.players[i].network.ipx.server, NetPlayers.players[i].network.ipx.node,Players[i].net_address );
5046 #endif
5047 						#ifdef MACINTOSH
5048 						} else {
5049 							appletalk_send_packet_data( (ubyte *)&ShortSyncPack, sizeof(short_frame_info)-MaxXDataSize+MySyncPack.data_size, NetPlayers.players[i].network.appletalk.node, NetPlayers.players[i].network.appletalk.net, NetPlayers.players[i].network.appletalk.socket );
5050 						#endif
5051 						}
5052 					}
5053 				}
5054 			}
5055 			else  // If long packets
5056 			{
5057 				int send_data_size;
5058 
5059 				MySyncPack.type                                 = PID_PDATA;
5060 				MySyncPack.playernum                    = Player_num;
5061 				MySyncPack.obj_render_type              = Objects[objnum].render_type;
5062 				MySyncPack.level_num                    = Current_level_num;
5063 				MySyncPack.obj_segnum                   = Objects[objnum].segnum;
5064 				MySyncPack.obj_pos                              = Objects[objnum].pos;
5065 				MySyncPack.obj_orient                   = Objects[objnum].orient;
5066 				MySyncPack.phys_velocity                = Objects[objnum].mtype.phys_info.velocity;
5067 				MySyncPack.phys_rotvel                  = Objects[objnum].mtype.phys_info.rotvel;
5068 
5069 				send_data_size = MySyncPack.data_size;                  // do this so correct size data is sent
5070 
5071 #ifdef WORDS_BIGENDIAN                        // do the swap stuff
5072 				if (Network_game_type == IPX_GAME) {
5073 					MySyncPack.obj_segnum = INTEL_SHORT(MySyncPack.obj_segnum);
5074 					MySyncPack.obj_pos.x = INTEL_INT((int)MySyncPack.obj_pos.x);
5075 					MySyncPack.obj_pos.y = INTEL_INT((int)MySyncPack.obj_pos.y);
5076 					MySyncPack.obj_pos.z = INTEL_INT((int)MySyncPack.obj_pos.z);
5077 
5078 					MySyncPack.obj_orient.rvec.x = INTEL_INT((int)MySyncPack.obj_orient.rvec.x);
5079 					MySyncPack.obj_orient.rvec.y = INTEL_INT((int)MySyncPack.obj_orient.rvec.y);
5080 					MySyncPack.obj_orient.rvec.z = INTEL_INT((int)MySyncPack.obj_orient.rvec.z);
5081 					MySyncPack.obj_orient.uvec.x = INTEL_INT((int)MySyncPack.obj_orient.uvec.x);
5082 					MySyncPack.obj_orient.uvec.y = INTEL_INT((int)MySyncPack.obj_orient.uvec.y);
5083 					MySyncPack.obj_orient.uvec.z = INTEL_INT((int)MySyncPack.obj_orient.uvec.z);
5084 					MySyncPack.obj_orient.fvec.x = INTEL_INT((int)MySyncPack.obj_orient.fvec.x);
5085 					MySyncPack.obj_orient.fvec.y = INTEL_INT((int)MySyncPack.obj_orient.fvec.y);
5086 					MySyncPack.obj_orient.fvec.z = INTEL_INT((int)MySyncPack.obj_orient.fvec.z);
5087 
5088 					MySyncPack.phys_velocity.x = INTEL_INT((int)MySyncPack.phys_velocity.x);
5089 					MySyncPack.phys_velocity.y = INTEL_INT((int)MySyncPack.phys_velocity.y);
5090 					MySyncPack.phys_velocity.z = INTEL_INT((int)MySyncPack.phys_velocity.z);
5091 
5092 					MySyncPack.phys_rotvel.x = INTEL_INT((int)MySyncPack.phys_rotvel.x);
5093 					MySyncPack.phys_rotvel.y = INTEL_INT((int)MySyncPack.phys_rotvel.y);
5094 					MySyncPack.phys_rotvel.z = INTEL_INT((int)MySyncPack.phys_rotvel.z);
5095 
5096 					MySyncPack.data_size = INTEL_SHORT(MySyncPack.data_size);
5097 				}
5098 #endif
5099 
5100 				for (i=0; i<N_players; i++ )    {
5101 					if ( (Players[i].connected) && (i!=Player_num ) )       {
5102 						if (Network_game_type == IPX_GAME)
5103 							MySyncPack.numpackets = INTEL_INT(Players[i].n_packets_sent);
5104 						else
5105 							MySyncPack.numpackets = Players[i].n_packets_sent;
5106 
5107 						Players[i].n_packets_sent++;
5108 						if (Network_game_type == IPX_GAME)
5109 							ipx_send_packet_data( (ubyte *)&MySyncPack, sizeof(frame_info)-MaxXDataSize+send_data_size, NetPlayers.players[i].network.ipx.server, NetPlayers.players[i].network.ipx.node,Players[i].net_address );
5110 						#ifdef MACINTOSH
5111 						else
5112 							appletalk_send_packet_data( (ubyte *)&MySyncPack, sizeof(frame_info)-MaxXDataSize+send_data_size, NetPlayers.players[i].network.appletalk.node, NetPlayers.players[i].network.appletalk.net, NetPlayers.players[i].network.appletalk.socket);
5113 						#endif
5114 					}
5115 				}
5116 			}
5117 
5118 			MySyncPack.data_size = 0;               // Start data over at 0 length.
5119 			if (Control_center_destroyed)
5120 			{
5121 				if (Player_is_dead)
5122 					Players[Player_num].connected=3;
5123 				if (timer_get_approx_seconds() > (LastEndlevel+(F1_0/2)))
5124 				{
5125 					network_send_endlevel_packet();
5126 					LastEndlevel=timer_get_approx_seconds();
5127 				}
5128 			}
5129 			//mprintf( (0, "Packet has %d bytes appended (TS=%d)\n", MySyncPack.data_size, sizeof(frame_info)-MaxXDataSize+MySyncPack.data_size ));
5130 		}
5131 	}
5132 
5133 	if (!listen)
5134 		return;
5135 
5136 	if ((last_timeout_check > F1_0) && !(Control_center_destroyed))
5137 	{
5138 		fix approx_time = timer_get_approx_seconds();
5139 		// Check for player timeouts
5140 		for (i = 0; i < N_players; i++)
5141 		{
5142 			if ((i != Player_num) && (Players[i].connected == 1))
5143 			{
5144 				if ((LastPacketTime[i] == 0) || (LastPacketTime[i] > approx_time))
5145 				{
5146 					LastPacketTime[i] = approx_time;
5147 					continue;
5148 				}
5149 				if ((approx_time - LastPacketTime[i]) > (15*F1_0))
5150 					network_timeout_player(i);
5151 			}
5152 		}
5153 		last_timeout_check = 0;
5154 	}
5155 
5156 listen:
5157 	if (!listen)
5158 	{
5159 		MySyncPack.data_size = 0;
5160 		return;
5161 	}
5162 	network_listen();
5163 
5164    if (VerifyPlayerJoined!=-1 && !(FrameCount & 63))
5165 	  resend_sync_due_to_packet_loss_for_allender(); // This will resend to network_player_rejoining
5166 
5167 	if (Network_send_objects)
5168 		network_send_objects();
5169 
5170 	if (Network_sending_extras && VerifyPlayerJoined==-1)
5171 	{
5172 	  network_send_extras();
5173 	  return;
5174     }
5175 }
5176 
5177 int missed_packets = 0;
5178 
5179 int ConsistencyCount = 0;
5180 
network_consistency_error(void)5181 void network_consistency_error(void)
5182 {
5183 	if (++ConsistencyCount < 10)
5184 		return;
5185 
5186 	Function_mode = FMODE_MENU;
5187 	#ifndef MACINTOSH
5188 	nm_messagebox(NULL, 1, TXT_OK, TXT_CONSISTENCY_ERROR);
5189 	#else
5190 	nm_messagebox(NULL, 1, TXT_OK, "Failed to join the netgame.\nYou are missing packets.  Check\nyour network connection and\ntry again.");
5191 	#endif
5192 	Function_mode = FMODE_GAME;
5193 	ConsistencyCount = 0;
5194 	multi_quit_game = 1;
5195 	multi_leave_menu = 1;
5196 	multi_reset_stuff();
5197 	Function_mode = FMODE_MENU;
5198 }
5199 
network_process_pdata(char * data)5200 void network_process_pdata (char *data)
5201  {
5202   Assert (Game_mode & GM_NETWORK);
5203 
5204   if (Netgame.ShortPackets)
5205 	network_read_pdata_short_packet ((short_frame_info *)data);
5206   else
5207 	network_read_pdata_packet ((frame_info *)data);
5208  }
5209 
network_read_pdata_packet(frame_info * pd)5210 void network_read_pdata_packet(frame_info *pd )
5211 {
5212 	int TheirPlayernum;
5213 	int TheirObjnum;
5214 	object * TheirObj = NULL;
5215 
5216 // frame_info should be aligned...for mac, make the necessary adjustments
5217 #ifdef WORDS_BIGENDIAN
5218 	if (Network_game_type == IPX_GAME) {
5219 		pd->numpackets = INTEL_INT(pd->numpackets);
5220 		pd->obj_pos.x = INTEL_INT(pd->obj_pos.x);
5221 		pd->obj_pos.y = INTEL_INT(pd->obj_pos.y);
5222 		pd->obj_pos.z = INTEL_INT(pd->obj_pos.z);
5223 
5224 		pd->obj_orient.rvec.x = (fix)INTEL_INT((int)pd->obj_orient.rvec.x);
5225 		pd->obj_orient.rvec.y = (fix)INTEL_INT((int)pd->obj_orient.rvec.y);
5226 		pd->obj_orient.rvec.z = (fix)INTEL_INT((int)pd->obj_orient.rvec.z);
5227 		pd->obj_orient.uvec.x = (fix)INTEL_INT((int)pd->obj_orient.uvec.x);
5228 		pd->obj_orient.uvec.y = (fix)INTEL_INT((int)pd->obj_orient.uvec.y);
5229 		pd->obj_orient.uvec.z = (fix)INTEL_INT((int)pd->obj_orient.uvec.z);
5230 		pd->obj_orient.fvec.x = (fix)INTEL_INT((int)pd->obj_orient.fvec.x);
5231 		pd->obj_orient.fvec.y = (fix)INTEL_INT((int)pd->obj_orient.fvec.y);
5232 		pd->obj_orient.fvec.z = (fix)INTEL_INT((int)pd->obj_orient.fvec.z);
5233 
5234 		pd->phys_velocity.x = (fix)INTEL_INT((int)pd->phys_velocity.x);
5235 		pd->phys_velocity.y = (fix)INTEL_INT((int)pd->phys_velocity.y);
5236 		pd->phys_velocity.z = (fix)INTEL_INT((int)pd->phys_velocity.z);
5237 
5238 		pd->phys_rotvel.x = (fix)INTEL_INT((int)pd->phys_rotvel.x);
5239 		pd->phys_rotvel.y = (fix)INTEL_INT((int)pd->phys_rotvel.y);
5240 		pd->phys_rotvel.z = (fix)INTEL_INT((int)pd->phys_rotvel.z);
5241 
5242 		pd->obj_segnum = INTEL_SHORT(pd->obj_segnum);
5243 		pd->data_size = INTEL_SHORT(pd->data_size);
5244 	}
5245 #endif
5246 
5247 	TheirPlayernum = pd->playernum;
5248 	TheirObjnum = Players[pd->playernum].objnum;
5249 
5250 	if (TheirPlayernum < 0) {
5251 		Int3(); // This packet is bogus!!
5252 		return;
5253 	}
5254 
5255    if (VerifyPlayerJoined!=-1 && TheirPlayernum==VerifyPlayerJoined)
5256 	 {
5257 	  // Hurray! Someone really really got in the game (I think).
5258      mprintf ((0,"Hurray! VPJ (%d) reset!\n",VerifyPlayerJoined));
5259      VerifyPlayerJoined=-1;
5260 	 }
5261 
5262 	if (!multi_quit_game && (TheirPlayernum >= N_players)) {
5263 		if (Network_status!=NETSTAT_WAITING)
5264 		 {
5265 			Int3(); // We missed an important packet!
5266 			network_consistency_error();
5267 			return;
5268 		 }
5269 		else
5270 		 return;
5271 	}
5272 	if (Endlevel_sequence || (Network_status == NETSTAT_ENDLEVEL) ) {
5273 		int old_Endlevel_sequence = Endlevel_sequence;
5274 		Endlevel_sequence = 1;
5275 		if ( pd->data_size>0 )  {
5276 			// pass pd->data to some parser function....
5277 			multi_process_bigdata( pd->data, pd->data_size );
5278 		}
5279 		Endlevel_sequence = old_Endlevel_sequence;
5280 		return;
5281 	}
5282 //      mprintf((0, "Gametime = %d, Frametime = %d.\n", GameTime, FrameTime));
5283 
5284 	if ((byte)pd->level_num != Current_level_num)
5285 	{
5286 		mprintf((0, "Got frame packet from player %d wrong level %d!\n", pd->playernum, pd->level_num));
5287 		return;
5288 	}
5289 
5290 	TheirObj = &Objects[TheirObjnum];
5291 
5292 	//------------- Keep track of missed packets -----------------
5293 	Players[TheirPlayernum].n_packets_got++;
5294 	TotalPacketsGot++;
5295 	LastPacketTime[TheirPlayernum] = timer_get_approx_seconds();
5296 
5297 	if  ( pd->numpackets != Players[TheirPlayernum].n_packets_got ) {
5298 		int missed_packets;
5299 
5300 		missed_packets = pd->numpackets-Players[TheirPlayernum].n_packets_got;
5301 		if ((pd->numpackets-Players[TheirPlayernum].n_packets_got)>0)
5302 			TotalMissedPackets += pd->numpackets-Players[TheirPlayernum].n_packets_got;
5303 
5304 			if ( missed_packets > 0 )
5305 				mprintf(( 0, "Missed %d packets from player #%d (%d total)\n", pd->numpackets-Players[TheirPlayernum].n_packets_got, TheirPlayernum, missed_packets ));
5306 			else
5307 				mprintf( (0, "Got %d late packets from player #%d (%d total)\n", Players[TheirPlayernum].n_packets_got-pd->numpackets, TheirPlayernum, missed_packets ));
5308 
5309 		#ifdef MACINTOSH
5310 		#ifdef APPLETALK_DEBUG
5311 		if (Network_game_type == APPLETALK_GAME) {
5312 			if ( missed_packets > 0 )
5313 				fprintf( at_fp, "Missed %d packets from player #%d (%d total)\n", pd->numpackets-Players[TheirPlayernum].n_packets_got, TheirPlayernum, missed_packets );
5314 			else
5315 				fprintf( at_fp, "Got %d late packets from player #%d (%d total)\n", Players[TheirPlayernum].n_packets_got-pd->numpackets, TheirPlayernum, missed_packets );
5316 		}
5317 		#endif
5318 
5319 		#ifdef IPX_DEBUG
5320 		if (Network_game_type == IPX_GAME) {
5321 			if ( missed_packets > 0 )
5322 				fprintf( ipx_fp, "Missed %d packets from player #%d (%d total)\n", pd->numpackets-Players[TheirPlayernum].n_packets_got, TheirPlayernum, missed_packets );
5323 			else
5324 				fprintf( ipx_fp, "Got %d late packets from player #%d (%d total)\n", Players[TheirPlayernum].n_packets_got-pd->numpackets, TheirPlayernum, missed_packets );
5325 		}
5326 		#endif
5327 		#endif
5328 
5329 		Players[TheirPlayernum].n_packets_got = pd->numpackets;
5330 	}
5331 
5332 	//------------ Read the player's ship's object info ----------------------
5333 	TheirObj->pos                           = pd->obj_pos;
5334 	TheirObj->orient                        = pd->obj_orient;
5335 	TheirObj->mtype.phys_info.velocity = pd->phys_velocity;
5336 	TheirObj->mtype.phys_info.rotvel = pd->phys_rotvel;
5337 
5338 	if ((TheirObj->render_type != pd->obj_render_type) && (pd->obj_render_type == RT_POLYOBJ))
5339 		multi_make_ghost_player(TheirPlayernum);
5340 
5341 	obj_relink(TheirObjnum,pd->obj_segnum);
5342 
5343 	if (TheirObj->movement_type == MT_PHYSICS)
5344 		set_thrust_from_velocity(TheirObj);
5345 
5346 	//------------ Welcome them back if reconnecting --------------
5347 	if (!Players[TheirPlayernum].connected) {
5348 		Players[TheirPlayernum].connected = 1;
5349 
5350 		if (Newdemo_state == ND_STATE_RECORDING)
5351 			newdemo_record_multi_reconnect(TheirPlayernum);
5352 
5353 		multi_make_ghost_player(TheirPlayernum);
5354 
5355 		create_player_appearance_effect(&Objects[TheirObjnum]);
5356 
5357 		digi_play_sample( SOUND_HUD_MESSAGE, F1_0);
5358 
5359 		ClipRank (&NetPlayers.players[TheirPlayernum].rank);
5360 
5361 		if (FindArg("-norankings"))
5362 			HUD_init_message( "'%s' %s", Players[TheirPlayernum].callsign, TXT_REJOIN );
5363 		else
5364 			HUD_init_message( "%s'%s' %s", RankStrings[NetPlayers.players[TheirPlayernum].rank],Players[TheirPlayernum].callsign, TXT_REJOIN );
5365 
5366 
5367 		multi_send_score();
5368 	}
5369 
5370 	//------------ Parse the extra data at the end ---------------
5371 
5372 	if ( pd->data_size>0 )  {
5373 		// pass pd->data to some parser function....
5374 		multi_process_bigdata( pd->data, pd->data_size );
5375 	}
5376 
5377 }
5378 
5379 #ifdef WORDS_BIGENDIAN
get_short_frame_info(ubyte * old_info,short_frame_info * new_info)5380 void get_short_frame_info(ubyte *old_info, short_frame_info *new_info)
5381 {
5382 	int loc = 0;
5383 
5384 	new_info->type = old_info[loc];                                     loc++;
5385 	/* skip three for pad byte */                                       loc += 3;
5386 	memcpy(&(new_info->numpackets), &(old_info[loc]), 4);               loc += 4;
5387 	new_info->numpackets = INTEL_INT(new_info->numpackets);
5388 	memcpy(new_info->thepos.bytemat, &(old_info[loc]), 9);              loc += 9;
5389 	memcpy(&(new_info->thepos.xo), &(old_info[loc]), 2);                loc += 2;
5390 	memcpy(&(new_info->thepos.yo), &(old_info[loc]), 2);                loc += 2;
5391 	memcpy(&(new_info->thepos.zo), &(old_info[loc]), 2);                loc += 2;
5392 	memcpy(&(new_info->thepos.segment), &(old_info[loc]), 2);           loc += 2;
5393 	memcpy(&(new_info->thepos.velx), &(old_info[loc]), 2);              loc += 2;
5394 	memcpy(&(new_info->thepos.vely), &(old_info[loc]), 2);              loc += 2;
5395 	memcpy(&(new_info->thepos.velz), &(old_info[loc]), 2);              loc += 2;
5396 	new_info->thepos.xo = INTEL_SHORT(new_info->thepos.xo);
5397 	new_info->thepos.yo = INTEL_SHORT(new_info->thepos.yo);
5398 	new_info->thepos.zo = INTEL_SHORT(new_info->thepos.zo);
5399 	new_info->thepos.segment = INTEL_SHORT(new_info->thepos.segment);
5400 	new_info->thepos.velx = INTEL_SHORT(new_info->thepos.velx);
5401 	new_info->thepos.vely = INTEL_SHORT(new_info->thepos.vely);
5402 	new_info->thepos.velz = INTEL_SHORT(new_info->thepos.velz);
5403 
5404 	memcpy(&(new_info->data_size), &(old_info[loc]), 2);                loc += 2;
5405 	new_info->data_size = INTEL_SHORT(new_info->data_size);
5406 	new_info->playernum = old_info[loc];                                loc++;
5407 	new_info->obj_render_type = old_info[loc];                          loc++;
5408 	new_info->level_num = old_info[loc];                                loc++;
5409 	memcpy(new_info->data, &(old_info[loc]), new_info->data_size);
5410 }
5411 #else
5412 #define get_short_frame_info(old_info, new_info) \
5413 	memcpy(new_info, old_info, sizeof(short_frame_info))
5414 #endif
5415 
network_read_pdata_short_packet(short_frame_info * pd)5416 void network_read_pdata_short_packet(short_frame_info *pd )
5417 {
5418 	int TheirPlayernum;
5419 	int TheirObjnum;
5420 	object * TheirObj = NULL;
5421 	short_frame_info new_pd;
5422 
5423 // short frame info is not aligned because of shortpos.  The mac
5424 // will call totally hacked and gross function to fix this up.
5425 
5426 	if (Network_game_type == IPX_GAME) {
5427 		get_short_frame_info((ubyte *)pd, &new_pd);
5428 	} else {
5429 		memcpy(&new_pd, (ubyte *)pd, sizeof(short_frame_info));
5430 	}
5431 
5432 	TheirPlayernum = new_pd.playernum;
5433 	TheirObjnum = Players[new_pd.playernum].objnum;
5434 
5435 	if (TheirPlayernum < 0) {
5436 		Int3(); // This packet is bogus!!
5437 		return;
5438 	}
5439 	if (!multi_quit_game && (TheirPlayernum >= N_players)) {
5440 		if (Network_status!=NETSTAT_WAITING)
5441 		 {
5442 			Int3(); // We missed an important packet!
5443 			network_consistency_error();
5444 			return;
5445 		 }
5446 		else
5447 		 return;
5448 	}
5449 
5450    if (VerifyPlayerJoined!=-1 && TheirPlayernum==VerifyPlayerJoined)
5451 	 {
5452 	  // Hurray! Someone really really got in the game (I think).
5453       mprintf ((0,"Hurray! VPJ (%d) reset!\n",VerifyPlayerJoined));
5454       VerifyPlayerJoined=-1;
5455 	 }
5456 
5457 	if (Endlevel_sequence || (Network_status == NETSTAT_ENDLEVEL) ) {
5458 		int old_Endlevel_sequence = Endlevel_sequence;
5459 		Endlevel_sequence = 1;
5460 		if ( new_pd.data_size>0 )       {
5461 			// pass pd->data to some parser function....
5462 			multi_process_bigdata( new_pd.data, new_pd.data_size );
5463 		}
5464 		Endlevel_sequence = old_Endlevel_sequence;
5465 		return;
5466 	}
5467 //      mprintf((0, "Gametime = %d, Frametime = %d.\n", GameTime, FrameTime));
5468 
5469 	if ((byte)new_pd.level_num != Current_level_num)
5470 	{
5471 		mprintf((0, "Got frame packet from player %d wrong level %d!\n", new_pd.playernum, new_pd.level_num));
5472 		return;
5473 	}
5474 
5475 	TheirObj = &Objects[TheirObjnum];
5476 
5477 	//------------- Keep track of missed packets -----------------
5478 	Players[TheirPlayernum].n_packets_got++;
5479 	TotalPacketsGot++;
5480 	LastPacketTime[TheirPlayernum] = timer_get_approx_seconds();
5481 
5482 	if  ( new_pd.numpackets != Players[TheirPlayernum].n_packets_got )      {
5483 		int missed_packets;
5484 
5485 		missed_packets = new_pd.numpackets-Players[TheirPlayernum].n_packets_got;
5486 		if ((new_pd.numpackets-Players[TheirPlayernum].n_packets_got)>0)
5487 			TotalMissedPackets += new_pd.numpackets-Players[TheirPlayernum].n_packets_got;
5488 
5489 		if ( missed_packets > 0 )
5490 			mprintf( (0, "Missed %d packets from player #%d (%d total)\n", new_pd.numpackets-Players[TheirPlayernum].n_packets_got, TheirPlayernum, missed_packets ));
5491 		else
5492 			mprintf( (0, "Got %d late packets from player #%d (%d total)\n", Players[TheirPlayernum].n_packets_got-new_pd.numpackets, TheirPlayernum, missed_packets ));
5493 
5494 		Players[TheirPlayernum].n_packets_got = new_pd.numpackets;
5495 	}
5496 
5497 	//------------ Read the player's ship's object info ----------------------
5498 
5499 	extract_shortpos(TheirObj, &new_pd.thepos, 0);
5500 
5501 	if ((TheirObj->render_type != new_pd.obj_render_type) && (new_pd.obj_render_type == RT_POLYOBJ))
5502 		multi_make_ghost_player(TheirPlayernum);
5503 
5504 	if (TheirObj->movement_type == MT_PHYSICS)
5505 		set_thrust_from_velocity(TheirObj);
5506 
5507 	//------------ Welcome them back if reconnecting --------------
5508 	if (!Players[TheirPlayernum].connected) {
5509 		Players[TheirPlayernum].connected = 1;
5510 
5511 		if (Newdemo_state == ND_STATE_RECORDING)
5512 			newdemo_record_multi_reconnect(TheirPlayernum);
5513 
5514 		multi_make_ghost_player(TheirPlayernum);
5515 
5516 		create_player_appearance_effect(&Objects[TheirObjnum]);
5517 
5518 		digi_play_sample( SOUND_HUD_MESSAGE, F1_0);
5519 		ClipRank (&NetPlayers.players[TheirPlayernum].rank);
5520 
5521 		if (FindArg("-norankings"))
5522 			HUD_init_message( "'%s' %s", Players[TheirPlayernum].callsign, TXT_REJOIN );
5523 		else
5524 			HUD_init_message( "%s'%s' %s", RankStrings[NetPlayers.players[TheirPlayernum].rank],Players[TheirPlayernum].callsign, TXT_REJOIN );
5525 
5526 
5527 		multi_send_score();
5528 	}
5529 
5530 	//------------ Parse the extra data at the end ---------------
5531 
5532 	if ( new_pd.data_size>0 )       {
5533 		// pass pd->data to some parser function....
5534 		multi_process_bigdata( new_pd.data, new_pd.data_size );
5535 	}
5536 
5537 }
5538 
5539 
network_set_power(void)5540 void network_set_power (void)
5541  {
5542   int opt=0,choice,opt_primary,opt_second,opt_power;
5543   newmenu_item m[40];
5544 
5545   opt_primary=opt;
5546   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Laser upgrade"; m[opt].value=Netgame.DoLaserUpgrade; opt++;
5547   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Super lasers"; m[opt].value=Netgame.DoSuperLaser; opt++;
5548   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Quad Lasers"; m[opt].value=Netgame.DoQuadLasers; opt++;
5549   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Vulcan cannon"; m[opt].value=Netgame.DoVulcan; opt++;
5550   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Spreadfire cannon"; m[opt].value=Netgame.DoSpread; opt++;
5551   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Plasma cannon"; m[opt].value=Netgame.DoPlasma; opt++;
5552   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Fusion cannon"; m[opt].value=Netgame.DoFusions; opt++;
5553   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Gauss cannon"; m[opt].value=Netgame.DoGauss; opt++;
5554   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Helix cannon"; m[opt].value=Netgame.DoHelix; opt++;
5555   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Phoenix cannon"; m[opt].value=Netgame.DoPhoenix; opt++;
5556   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Omega cannon"; m[opt].value=Netgame.DoOmega; opt++;
5557 
5558   opt_second=opt;
5559   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Homing Missiles"; m[opt].value=Netgame.DoHoming; opt++;
5560   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Proximity Bombs"; m[opt].value=Netgame.DoProximity; opt++;
5561   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Smart Missiles"; m[opt].value=Netgame.DoSmarts; opt++;
5562   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Mega Missiles"; m[opt].value=Netgame.DoMegas; opt++;
5563   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Flash Missiles"; m[opt].value=Netgame.DoFlash; opt++;
5564   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Guided Missiles"; m[opt].value=Netgame.DoGuided; opt++;
5565   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Smart Mines"; m[opt].value=Netgame.DoSmartMine; opt++;
5566   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Mercury Missiles"; m[opt].value=Netgame.DoMercury; opt++;
5567   m[opt].type = NM_TYPE_CHECK; m[opt].text = "EarthShaker Missiles"; m[opt].value=Netgame.DoEarthShaker; opt++;
5568 
5569   opt_power=opt;
5570   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Invulnerability"; m[opt].value=Netgame.DoInvulnerability; opt++;
5571   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Cloaking"; m[opt].value=Netgame.DoCloak; opt++;
5572   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Afterburners"; m[opt].value=Netgame.DoAfterburner; opt++;
5573   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Ammo rack"; m[opt].value=Netgame.DoAmmoRack; opt++;
5574   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Energy Converter"; m[opt].value=Netgame.DoConverter; opt++;
5575   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Headlight"; m[opt].value=Netgame.DoHeadlight; opt++;
5576 
5577   choice = newmenu_do(NULL, "Objects to allow", opt, m, NULL);
5578 
5579   Netgame.DoLaserUpgrade=m[opt_primary].value;
5580   Netgame.DoSuperLaser=m[opt_primary+1].value;
5581   Netgame.DoQuadLasers=m[opt_primary+2].value;
5582   Netgame.DoVulcan=m[opt_primary+3].value;
5583   Netgame.DoSpread=m[opt_primary+4].value;
5584   Netgame.DoPlasma=m[opt_primary+5].value;
5585   Netgame.DoFusions=m[opt_primary+6].value;
5586   Netgame.DoGauss=m[opt_primary+7].value;
5587   Netgame.DoHelix=m[opt_primary+8].value;
5588   Netgame.DoPhoenix=m[opt_primary+9].value;
5589   Netgame.DoOmega=m[opt_primary+10].value;
5590 
5591   Netgame.DoHoming=m[opt_second].value;
5592   Netgame.DoProximity=m[opt_second+1].value;
5593   Netgame.DoSmarts=m[opt_second+2].value;
5594   Netgame.DoMegas=m[opt_second+3].value;
5595   Netgame.DoFlash=m[opt_second+4].value;
5596   Netgame.DoGuided=m[opt_second+5].value;
5597   Netgame.DoSmartMine=m[opt_second+6].value;
5598   Netgame.DoMercury=m[opt_second+7].value;
5599   Netgame.DoEarthShaker=m[opt_second+8].value;
5600 
5601   Netgame.DoInvulnerability=m[opt_power].value;
5602   Netgame.DoCloak=m[opt_power+1].value;
5603   Netgame.DoAfterburner=m[opt_power+2].value;
5604   Netgame.DoAmmoRack=m[opt_power+3].value;
5605   Netgame.DoConverter=m[opt_power+4].value;
5606   Netgame.DoHeadlight=m[opt_power+5].value;
5607 
5608  }
5609 
SetAllAllowablesTo(int on)5610 void SetAllAllowablesTo (int on)
5611  {
5612   last_cinvul = control_invul_time = 0;   //default to zero
5613 
5614   Netgame.DoMegas=Netgame.DoSmarts=Netgame.DoFusions=Netgame.DoHelix=\
5615   Netgame.DoPhoenix=Netgame.DoCloak=Netgame.DoInvulnerability=\
5616   Netgame.DoAfterburner=Netgame.DoGauss=Netgame.DoVulcan=Netgame.DoPlasma=on;
5617 
5618   Netgame.DoOmega=Netgame.DoSuperLaser=Netgame.DoProximity=\
5619   Netgame.DoSpread=Netgame.DoMercury=Netgame.DoSmartMine=Netgame.DoFlash=\
5620   Netgame.DoGuided=Netgame.DoEarthShaker=on;
5621 
5622   Netgame.DoConverter=Netgame.DoAmmoRack=Netgame.DoHeadlight=on;
5623   Netgame.DoHoming=Netgame.DoLaserUpgrade=Netgame.DoQuadLasers=on;
5624   Netgame.BrightPlayers=Netgame.invul=on;
5625  }
5626 
5627 fix LastPTA;
5628 int LastKillGoal;
5629 
5630 // Jeez -- mac compiler can't handle all of these on the same decl line.
5631 int opt_setpower,opt_playtime,opt_killgoal,opt_socket,opt_marker_view,opt_light,opt_show_on_map;
5632 int opt_difficulty,opt_packets,opt_short_packets, opt_bright,opt_start_invul;
5633 int opt_show_names;
5634 
5635 void network_more_options_poll( int nitems, newmenu_item * menus, int * key, int citem );
5636 
network_more_game_options()5637 void network_more_game_options ()
5638  {
5639   int opt=0,i;
5640   char PlayText[80],KillText[80],srinvul[50],socket_string[5],packstring[5];
5641   newmenu_item m[21];
5642 
5643   sprintf (socket_string,"%d",Network_socket);
5644   sprintf (packstring,"%d",Netgame.PacketsPerSec);
5645 
5646   opt_difficulty = opt;
5647   m[opt].type = NM_TYPE_SLIDER; m[opt].value=netgame_difficulty; m[opt].text=TXT_DIFFICULTY; m[opt].min_value=0; m[opt].max_value=(NDL-1); opt++;
5648 
5649   opt_cinvul = opt;
5650   sprintf( srinvul, "%s: %d %s", TXT_REACTOR_LIFE, control_invul_time*5, TXT_MINUTES_ABBREV );
5651   m[opt].type = NM_TYPE_SLIDER; m[opt].value=control_invul_time; m[opt].text= srinvul; m[opt].min_value=0; m[opt].max_value=10; opt++;
5652 
5653   opt_playtime=opt;
5654   sprintf( PlayText, "Max time: %d %s", Netgame.PlayTimeAllowed*5, TXT_MINUTES_ABBREV );
5655   m[opt].type = NM_TYPE_SLIDER; m[opt].value=Netgame.PlayTimeAllowed; m[opt].text= PlayText; m[opt].min_value=0; m[opt].max_value=10; opt++;
5656 
5657   opt_killgoal=opt;
5658   sprintf( KillText, "Kill Goal: %d kills", Netgame.KillGoal*5);
5659   m[opt].type = NM_TYPE_SLIDER; m[opt].value=Netgame.KillGoal; m[opt].text= KillText; m[opt].min_value=0; m[opt].max_value=10; opt++;
5660 
5661   opt_start_invul=opt;
5662   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Invulnerable when reappearing"; m[opt].value=Netgame.invul; opt++;
5663 
5664   opt_marker_view = opt;
5665   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Allow camera views from Markers"; m[opt].value=Netgame.Allow_marker_view; opt++;
5666   opt_light = opt;
5667   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Indestructible lights"; m[opt].value=Netgame.AlwaysLighting; opt++;
5668 
5669   opt_bright = opt;
5670   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Bright player ships"; m[opt].value=Netgame.BrightPlayers; opt++;
5671 
5672   opt_show_names=opt;
5673   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Show enemy names on HUD"; m[opt].value=Netgame.ShowAllNames; opt++;
5674 
5675   opt_show_on_map=opt;
5676   m[opt].type = NM_TYPE_CHECK; m[opt].text = TXT_SHOW_ON_MAP; m[opt].value=(Netgame.game_flags & NETGAME_FLAG_SHOW_MAP); opt_show_on_map=opt; opt++;
5677 
5678   opt_short_packets=opt;
5679   m[opt].type = NM_TYPE_CHECK; m[opt].text = "Short packets"; m[opt].value=Netgame.ShortPackets; opt++;
5680 
5681   opt_setpower = opt;
5682   m[opt].type = NM_TYPE_MENU;  m[opt].text = "Set Objects allowed..."; opt++;
5683 
5684   if (Network_game_type == IPX_GAME) {
5685 	  m[opt].type = NM_TYPE_TEXT; m[opt].text = "Network socket"; opt++;
5686 	  opt_socket = opt;
5687 	  m[opt].type = NM_TYPE_INPUT; m[opt].text = socket_string; m[opt].text_len=4; opt++;
5688   }
5689 
5690   m[opt].type = NM_TYPE_TEXT; m[opt].text = "Packets per second (2 - 20)"; opt++;
5691   opt_packets=opt;
5692   m[opt].type = NM_TYPE_INPUT; m[opt].text=packstring; m[opt].text_len=2; opt++;
5693 
5694   LastKillGoal=Netgame.KillGoal;
5695   LastPTA=Netgame.PlayTimeAllowed;
5696 
5697   menu:
5698 
5699   ExtGameStatus=GAMESTAT_MORE_NETGAME_OPTIONS;
5700   i = newmenu_do1( NULL, "Additional netgame options", opt, m, network_more_options_poll, 0 );
5701 
5702    //control_invul_time = atoi( srinvul )*60*F1_0;
5703     control_invul_time = m[opt_cinvul].value;
5704     Netgame.control_invul_time = control_invul_time*5*F1_0*60;
5705 
5706   if (i==opt_setpower)
5707    {
5708     network_set_power ();
5709     goto menu;
5710    }
5711 
5712   Netgame.PacketsPerSec=atoi(packstring);
5713 
5714   if (Netgame.PacketsPerSec>20)
5715 	{
5716 	 Netgame.PacketsPerSec=20;
5717 	 nm_messagebox(TXT_ERROR, 1, TXT_OK, "Packet value out of range\nSetting value to 20");
5718 	}
5719   if (Netgame.PacketsPerSec<2)
5720 	{
5721 	  nm_messagebox(TXT_ERROR, 1, TXT_OK, "Packet value out of range\nSetting value to 2");
5722 	  Netgame.PacketsPerSec=2;
5723 	}
5724 
5725   mprintf ((0,"Hey! Sending out %d packets per second\n",Netgame.PacketsPerSec));
5726 
5727 	if (Network_game_type == IPX_GAME) {
5728 		if ((atoi(socket_string))!=Network_socket) {
5729 			Network_socket=atoi(socket_string);
5730 			ipx_change_default_socket( IPX_DEFAULT_SOCKET + Network_socket );
5731 		}
5732 	}
5733 
5734   Netgame.invul=m[opt_start_invul].value;
5735   Netgame.BrightPlayers=m[opt_bright].value;
5736   Netgame.ShortPackets=m[opt_short_packets].value;
5737   Netgame.ShowAllNames=m[opt_show_names].value;
5738   network_AdjustMaxDataSize();
5739 
5740   Netgame.Allow_marker_view=m[opt_marker_view].value;
5741   Netgame.AlwaysLighting=m[opt_light].value;
5742   netgame_difficulty=Difficulty_level = m[opt_difficulty].value;
5743   if (m[opt_show_on_map].value)
5744 	Netgame.game_flags |= NETGAME_FLAG_SHOW_MAP;
5745 
5746 
5747  }
5748 
network_more_options_poll(int nitems,newmenu_item * menus,int * key,int citem)5749 void network_more_options_poll( int nitems, newmenu_item * menus, int * key, int citem )
5750  {
5751    menus = menus;
5752    citem = citem;      // kills compile warnings
5753    nitems = nitems;
5754    key = key;
5755 
5756    if ( last_cinvul != menus[opt_cinvul].value )   {
5757 	sprintf( menus[opt_cinvul].text, "%s: %d %s", TXT_REACTOR_LIFE, menus[opt_cinvul].value*5, TXT_MINUTES_ABBREV );
5758 	last_cinvul = menus[opt_cinvul].value;
5759 	menus[opt_cinvul].redraw = 1;
5760    }
5761 
5762   if (menus[opt_playtime].value!=LastPTA)
5763    {
5764     #ifdef SHAREWARE
5765       LastPTA=0;
5766       nm_messagebox ("Sorry",1,TXT_OK,"Registered version only!");
5767       menus[opt_playtime].value=0;
5768       menus[opt_playtime].redraw=1;
5769       return;
5770     #endif
5771 
5772     if (Game_mode & GM_MULTI_COOP)
5773      {
5774       LastPTA=0;
5775       nm_messagebox ("Sorry",1,TXT_OK,"You can't change those for coop!");
5776       menus[opt_playtime].value=0;
5777       menus[opt_playtime].redraw=1;
5778       return;
5779      }
5780 
5781     Netgame.PlayTimeAllowed=menus[opt_playtime].value;
5782     sprintf( menus[opt_playtime].text, "Max Time: %d %s", Netgame.PlayTimeAllowed*5, TXT_MINUTES_ABBREV );
5783     LastPTA=Netgame.PlayTimeAllowed;
5784     menus[opt_playtime].redraw=1;
5785    }
5786   if (menus[opt_killgoal].value!=LastKillGoal)
5787    {
5788     #ifdef SHAREWARE
5789       nm_messagebox ("Sorry",1,TXT_OK,"Registered version only!");
5790       menus[opt_killgoal].value=0;
5791       menus[opt_killgoal].redraw=1;
5792       LastKillGoal=0;
5793       return;
5794 	 #endif
5795 
5796 
5797     if (Game_mode & GM_MULTI_COOP)
5798      {
5799       nm_messagebox ("Sorry",1,TXT_OK,"You can't change those for coop!");
5800       menus[opt_killgoal].value=0;
5801       menus[opt_killgoal].redraw=1;
5802       LastKillGoal=0;
5803       return;
5804      }
5805 
5806 
5807     Netgame.KillGoal=menus[opt_killgoal].value;
5808     sprintf( menus[opt_killgoal].text, "Kill Goal: %d kills", Netgame.KillGoal*5);
5809     LastKillGoal=Netgame.KillGoal;
5810     menus[opt_killgoal].redraw=1;
5811    }
5812  }
5813 
5814 extern void multi_send_light (int,ubyte);
5815 extern void multi_send_light_specific (int,int,ubyte);
5816 
network_send_smash_lights(int pnum)5817 void network_send_smash_lights (int pnum)
5818  {
5819   // send the lights that have been blown out
5820 
5821   int i;
5822 
5823   pnum=pnum;
5824 
5825   for (i=0;i<=Highest_segment_index;i++)
5826    if (Light_subtracted[i])
5827     multi_send_light_specific(pnum,i,Light_subtracted[i]);
5828  }
5829 
5830 extern int Num_triggers;
5831 extern void multi_send_trigger_specific (char pnum,char);
5832 
network_send_fly_thru_triggers(int pnum)5833 void network_send_fly_thru_triggers (int pnum)
5834  {
5835   // send the fly thru triggers that have been disabled
5836 
5837   int i;
5838 
5839   for (i=0;i<Num_triggers;i++)
5840    if (Triggers[i].flags & TF_DISABLED)
5841     multi_send_trigger_specific(pnum,i);
5842  }
5843 
network_send_player_flags()5844 void network_send_player_flags()
5845  {
5846   int i;
5847 
5848   for (i=0;i<N_players;i++)
5849 	multi_send_flags(i);
5850  }
5851 
network_ping(ubyte flag,int pnum)5852 void network_ping (ubyte flag,int pnum)
5853 {
5854 	ubyte mybuf[2];
5855 
5856 	mybuf[0]=flag;
5857 	mybuf[1]=Player_num;
5858 
5859 	if (Network_game_type == IPX_GAME)
5860 		ipx_send_packet_data( (ubyte *)mybuf, 2, NetPlayers.players[pnum].network.ipx.server, NetPlayers.players[pnum].network.ipx.node,Players[pnum].net_address );
5861 	#ifdef MACINTOSH
5862 	else
5863 		appletalk_send_packet_data( (ubyte *)mybuf, 2, NetPlayers.players[pnum].network.appletalk.node, NetPlayers.players[pnum].network.appletalk.net, NetPlayers.players[pnum].network.appletalk.socket);
5864 	#endif
5865 }
5866 
5867 extern fix PingLaunchTime,PingReturnTime;
5868 
network_handle_ping_return(ubyte pnum)5869 void network_handle_ping_return (ubyte pnum)
5870  {
5871   if (PingLaunchTime==0 || pnum>=N_players)
5872 	{
5873 	 mprintf ((0,"Got invalid PING RETURN from %s!\n",Players[pnum].callsign));
5874     return;
5875    }
5876 
5877   PingReturnTime=timer_get_fixed_seconds();
5878 
5879   HUD_init_message ("Ping time for %s is %d ms!",Players[pnum].callsign,
5880 	f2i(fixmul(PingReturnTime-PingLaunchTime,i2f(1000))));
5881   PingLaunchTime=0;
5882  }
5883 
network_send_ping(ubyte pnum)5884 void network_send_ping (ubyte pnum)
5885  {
5886   network_ping (PID_PING_SEND,pnum);
5887  }
5888 
DoRefuseStuff(sequence_packet * their)5889 void DoRefuseStuff (sequence_packet *their)
5890  {
5891   int i,new_player_num;
5892 
5893   ClipRank (&their->player.rank);
5894 
5895   for (i=0;i<MAX_PLAYERS;i++)
5896 	 if (!strcmp (their->player.callsign,Players[i].callsign))
5897 	{
5898 		network_welcome_player(their);
5899 			return;
5900 		}
5901 
5902    if (!WaitForRefuseAnswer)
5903     {
5904 	for (i=0;i<MAX_PLAYERS;i++)
5905 		 if (!strcmp (their->player.callsign,Players[i].callsign))
5906 		{
5907 			network_welcome_player(their);
5908 				return;
5909 			}
5910 
5911       digi_play_sample (SOUND_HUD_JOIN_REQUEST,F1_0*2);
5912 
5913       if (Game_mode & GM_TEAM)
5914 		 {
5915 
5916 
5917       if (!FindArg("-norankings"))
5918 	      HUD_init_message ("%s %s wants to join",RankStrings[their->player.rank],their->player.callsign);
5919      	#ifndef MACINTOSH
5920 		HUD_init_message ("%s joining. Alt-1 assigns to team %s. Alt-2 to team %s",their->player.callsign,Netgame.team_name[0],Netgame.team_name[1]);
5921 		#else
5922 		HUD_init_message ("%s joining. Opt-1 assigns to team %s. Opt-2 to team %s",their->player.callsign,Netgame.team_name[0],Netgame.team_name[1]);
5923 		#endif
5924 //                      HUD_init_message ("Alt-1 to place on team %s!",Netgame.team_name[0]);
5925 //                      HUD_init_message ("Alt-2 to place on team %s!",Netgame.team_name[1]);
5926 		 }
5927 		else
5928 		HUD_init_message ("%s wants to join...press F6 to connect",their->player.callsign);
5929 
5930 	   strcpy (RefusePlayerName,their->player.callsign);
5931 	   RefuseTimeLimit=timer_get_approx_seconds();
5932 		RefuseThisPlayer=0;
5933 		WaitForRefuseAnswer=1;
5934 	 }
5935 	else
5936 	 {
5937 	for (i=0;i<MAX_PLAYERS;i++)
5938 		 if (!strcmp (their->player.callsign,Players[i].callsign))
5939 		{
5940 			network_welcome_player(their);
5941 				return;
5942 			}
5943 
5944 		if (strcmp(their->player.callsign,RefusePlayerName))
5945 			return;
5946 
5947 		if (RefuseThisPlayer)
5948 		 {
5949 				RefuseTimeLimit=0;
5950 				RefuseThisPlayer=0;
5951 				WaitForRefuseAnswer=0;
5952 				if (Game_mode & GM_TEAM)
5953 				 {
5954 					new_player_num=GetNewPlayerNumber (their);
5955 					mprintf ((0,"Newplayernum=%d\n",new_player_num));
5956 
5957 					Assert (RefuseTeam==1 || RefuseTeam==2);
5958 
5959 					if (RefuseTeam==1)
5960 					Netgame.team_vector &=(~(1<<new_player_num));
5961 					else
5962 					Netgame.team_vector |=(1<<new_player_num);
5963 					network_welcome_player(their);
5964 					network_send_netgame_update ();
5965 				 }
5966 				else
5967 					network_welcome_player(their);
5968 			   return;
5969 		 }
5970 
5971 	  if ((timer_get_approx_seconds()) > RefuseTimeLimit+REFUSE_INTERVAL)
5972 		{
5973 			RefuseTimeLimit=0;
5974 			RefuseThisPlayer=0;
5975 			WaitForRefuseAnswer=0;
5976 			if (!strcmp (their->player.callsign,RefusePlayerName)) {
5977 				if (Network_game_type == IPX_GAME)
5978 					network_dump_player(their->player.network.ipx.server,their->player.network.ipx.node, DUMP_DORK);
5979 				#ifdef MACINTOSH
5980 				else
5981 					network_dump_appletalk_player(their->player.network.appletalk.node,their->player.network.appletalk.net, their->player.network.appletalk.socket, DUMP_DORK);
5982 				#endif
5983 			}
5984 			return;
5985 		}
5986 
5987     }
5988  }
5989 
GetNewPlayerNumber(sequence_packet * their)5990 int GetNewPlayerNumber (sequence_packet *their)
5991   {
5992 	 int i;
5993 
5994 	 their=their;
5995 
5996 		if ( N_players < MaxNumNetPlayers)
5997 			return (N_players);
5998 
5999 		else
6000 		{
6001 			// Slots are full but game is open, see if anyone is
6002 			// disconnected and replace the oldest player with this new one
6003 
6004 			int oldest_player = -1;
6005 			fix oldest_time = timer_get_approx_seconds();
6006 
6007 			Assert(N_players == MaxNumNetPlayers);
6008 
6009 			for (i = 0; i < N_players; i++)
6010 			{
6011 				if ( (!Players[i].connected) && (LastPacketTime[i] < oldest_time))
6012 				{
6013 					oldest_time = LastPacketTime[i];
6014 					oldest_player = i;
6015 				}
6016 			}
6017 	    return (oldest_player);
6018 	  }
6019   }
6020 
network_send_extras()6021 void network_send_extras ()
6022  {
6023 	Assert (Player_joining_extras>-1);
6024 
6025    if (!network_i_am_master())
6026 	 {
6027 	  mprintf ((0,"Hey! I'm not the master and I was gonna send info!\n"));
6028 	 // Int3();
6029 	 // Network_sending_extras=0;
6030 	 // return;
6031     }
6032 
6033 
6034    if (Network_sending_extras==40)
6035 		network_send_fly_thru_triggers(Player_joining_extras);
6036    if (Network_sending_extras==38)
6037 	network_send_door_updates(Player_joining_extras);
6038    if (Network_sending_extras==35)
6039 		network_send_markers();
6040    if (Network_sending_extras==30 && (Game_mode & GM_MULTI_ROBOTS))
6041 		multi_send_stolen_items();
6042 	if (Network_sending_extras==25 && (Netgame.PlayTimeAllowed || Netgame.KillGoal))
6043 		multi_send_kill_goal_counts();
6044    if (Network_sending_extras==20)
6045 		network_send_smash_lights(Player_joining_extras);
6046    if (Network_sending_extras==15)
6047 		network_send_player_flags();
6048    if (Network_sending_extras==10)
6049 		multi_send_powerup_update();
6050  //  if (Network_sending_extras==5)
6051 //		network_send_door_updates(Player_joining_extras); // twice!
6052 
6053 	Network_sending_extras--;
6054    if (!Network_sending_extras)
6055 	 Player_joining_extras=-1;
6056  }
6057 
6058 
network_send_naked_packet(char * buf,short len,int who)6059 void network_send_naked_packet(char *buf, short len, int who)
6060 {
6061 	if (!(Game_mode&GM_NETWORK)) return;
6062 
6063    if (NakedPacketLen==0)
6064 	 {
6065 	   NakedBuf[0]=PID_NAKED_PDATA;
6066 	   NakedBuf[1]=Player_num;
6067 		NakedPacketLen=2;
6068 	 }
6069 
6070    if (len+NakedPacketLen>MaxXDataSize)
6071     {
6072 //         mprintf ((0,"Sending a naked packet of %d bytes.\n",NakedPacketLen));
6073 		if (Network_game_type == IPX_GAME)
6074 			ipx_send_packet_data( (ubyte *)NakedBuf, NakedPacketLen, NetPlayers.players[who].network.ipx.server, NetPlayers.players[who].network.ipx.node,Players[who].net_address );
6075 		#ifdef MACINTOSH
6076 		else
6077 			appletalk_send_packet_data( (ubyte *)NakedBuf, NakedPacketLen, NetPlayers.players[who].network.appletalk.node, NetPlayers.players[who].network.appletalk.net, NetPlayers.players[who].network.appletalk.socket );
6078 		#endif
6079 		NakedPacketLen=2;
6080 		memcpy (&NakedBuf[NakedPacketLen],buf,len);
6081 		NakedPacketLen+=len;
6082 		NakedPacketDestPlayer=who;
6083 	 }
6084    else
6085 	 {
6086 		memcpy (&NakedBuf[NakedPacketLen],buf,len);
6087 		NakedPacketLen+=len;
6088 		NakedPacketDestPlayer=who;
6089 	 }
6090  }
6091 
6092 
network_process_naked_pdata(char * data,int len)6093 void network_process_naked_pdata (char *data,int len)
6094  {
6095    int pnum=data[1];
6096    Assert (data[0]=PID_NAKED_PDATA);
6097 
6098 //   mprintf ((0,"Processing a naked packet of %d length.\n",len));
6099 
6100 	if (pnum < 0) {
6101 	   mprintf ((0,"Naked packet is bad!\n"));
6102 		Int3(); // This packet is bogus!!
6103 		return;
6104 	}
6105 
6106 	if (!multi_quit_game && (pnum >= N_players)) {
6107 		if (Network_status!=NETSTAT_WAITING)
6108 		 {
6109 			Int3(); // We missed an important packet!
6110 			network_consistency_error();
6111 			return;
6112 		 }
6113 		else
6114 		 return;
6115 	}
6116 
6117 	if (Endlevel_sequence || (Network_status == NETSTAT_ENDLEVEL) ) {
6118 		int old_Endlevel_sequence = Endlevel_sequence;
6119 		Endlevel_sequence = 1;
6120 		multi_process_bigdata( data+2, len-2);
6121 		Endlevel_sequence = old_Endlevel_sequence;
6122 		return;
6123 	}
6124 
6125 	multi_process_bigdata( data+2, len-2 );
6126  }
6127 
6128 int ConnectionPacketLevel[]={0,1,1,1};
6129 int ConnectionSecLevel[]={12,3,5,7};
6130 
6131 int AppletalkConnectionPacketLevel[]={0,1,0};
6132 int AppletalkConnectionSecLevel[]={10,3,8};
6133 
6134 #if defined(RELEASE) && !defined(MACINTOSH)		// use the code below for mac appletalk games
network_choose_connect()6135 int network_choose_connect ()
6136  {
6137   return (1);
6138  }
6139 #else
network_choose_connect()6140 int network_choose_connect ()
6141  {
6142 #if 0
6143 	newmenu_item m[16];
6144 	int choice,opt=0;
6145 #endif
6146 
6147 	if (Network_game_type == IPX_GAME) {
6148 		#if 0
6149 	   m[opt].type = NM_TYPE_MENU;  m[opt].text = "Local Subnet"; opt++;
6150 	   m[opt].type = NM_TYPE_MENU;  m[opt].text = "14.4 modem over Internet"; opt++;
6151 	   m[opt].type = NM_TYPE_MENU;  m[opt].text = "28.8 modem over Internet"; opt++;
6152 	   m[opt].type = NM_TYPE_MENU;  m[opt].text = "ISDN or T1 over Internet"; opt++;
6153 
6154 	   choice = newmenu_do1( NULL, "Choose connection type", opt, m, NULL, 0 );
6155 
6156 		if (choice<0)
6157 		 return (NULL);
6158 
6159 	   Assert (choice>=0 && choice<=3);
6160 
6161 		Netgame.ShortPackets=ConnectionPacketLevel[choice];
6162 		Netgame.PacketsPerSec=ConnectionSecLevel[choice];
6163 		#endif
6164 	   return (1);
6165 	#ifdef MACINTOSH
6166 	} else {
6167 	   m[opt].type = NM_TYPE_MENU;  m[opt].text = "EtherTalk"; opt++;
6168 	   m[opt].type = NM_TYPE_MENU;  m[opt].text = "LocalTalk"; opt++;
6169 	   m[opt].type = NM_TYPE_MENU;  m[opt].text = "Other"; opt++;
6170 
6171 	   choice = newmenu_do1( NULL, "Choose connection type", opt, m, NULL, 0 );
6172 
6173 		if (choice<0)
6174 		 return (NULL);
6175 
6176 		Network_appletalk_type = choice;
6177 
6178 		Assert (choice>=0 && choice<=2);
6179 
6180 		Netgame.ShortPackets=AppletalkConnectionPacketLevel[choice];
6181 		Netgame.PacketsPerSec=AppletalkConnectionSecLevel[choice];
6182 	   return (1);
6183 	#endif
6184 	}
6185   return (0);
6186  }
6187 #endif
6188 
6189 
6190 
6191 #ifdef NETPROFILING
OpenSendLog()6192 void OpenSendLog ()
6193  {
6194   int i;
6195   SendLogFile=(FILE *)fopen ("sendlog.net","w");
6196   for (i=0;i<100;i++)
6197 	TTSent[i]=0;
6198  }
OpenRecieveLog()6199 void OpenRecieveLog ()
6200  {
6201   int i;
6202   RecieveLogFile=(FILE *)fopen ("recvlog.net","w");
6203   for (i=0;i<100;i++)
6204 	TTRecv[i]=0;
6205  }
6206 #endif
6207 
GetMyNetRanking()6208 int GetMyNetRanking ()
6209  {
6210   int rank;
6211   int eff;
6212 
6213   if (Netlife_kills+Netlife_killed==0)
6214   	 return (1);
6215 
6216   rank=(int) (((float)Netlife_kills/3000.0)*8.0);
6217 
6218   eff=(int)((float)((float)Netlife_kills/((float)Netlife_killed+(float)Netlife_kills))*100.0);
6219 
6220   if (rank>8)
6221    rank=8;
6222 
6223   if (eff<0)
6224 	 eff=0;
6225 
6226   if (eff<60)
6227 	rank-=((59-eff)/10);
6228 
6229   if (rank<0)
6230 	rank=0;
6231   if (rank>8)
6232 	rank=8;
6233 
6234   mprintf ((0,"Rank is %d (%s)\n",rank+1,RankStrings[rank+1]));
6235   return (rank+1);
6236  }
6237 
ClipRank(signed char * rank)6238 void ClipRank (signed char *rank)
6239  {
6240   // This function insures no crashes when dealing with D2 1.0
6241 
6242 
6243   if (*rank<0 || *rank>9)
6244 	*rank=0;
6245  }
network_check_for_old_version(char pnum)6246 void network_check_for_old_version (char pnum)
6247  {
6248   if (NetPlayers.players[(int)pnum].version_major==1 && (NetPlayers.players[(int)pnum].version_minor & 0x0F)==0)
6249 	NetPlayers.players[(int)pnum].rank=0;
6250  }
6251 
network_request_player_names(int n)6252 void network_request_player_names (int n)
6253  {
6254   network_send_all_info_request (PID_GAME_PLAYERS,Active_games[n].Security);
6255   NamesInfoSecurity=Active_games[n].Security;
6256  }
6257 
6258 extern char already_showing_info;
6259 extern int newmenu_dotiny2( char * title, char * subtitle, int nitems, newmenu_item * item, void (*subfunction)(int nitems,newmenu_item * items, int * last_key, int citem));
6260 
network_process_names_return(char * data)6261 void network_process_names_return (char *data)
6262  {
6263 	newmenu_item m[15];
6264    char mtext[15][50],temp[50];
6265 	int i,t,l,gnum,num=0,count=5,numplayers;
6266 
6267    if (NamesInfoSecurity!=(*(int *)(data+1)))
6268 	 {
6269 	  mprintf ((0,"Bad security on names return!\n"));
6270 	  mprintf ((0,"NIS=%d data=%d\n",NamesInfoSecurity,(*(int *)(data+1))));
6271 	  return;
6272 	 }
6273 
6274    numplayers=data[count]; count++;
6275 
6276    if (numplayers==255)
6277 	 {
6278 		 SurfingNet=0;
6279 		 NamesInfoSecurity=-1;
6280  		 nm_messagebox(NULL, 1, "OK", "That game is refusing\nname requests.\n");
6281 		 SurfingNet=1;
6282 		 return;
6283 	 }
6284 
6285    Assert (numplayers>0 && numplayers<MAX_NUM_NET_PLAYERS);
6286 
6287    for (i=0;i<12;i++)
6288 	{
6289 	 m[i].text=(char *)&mtext[i];
6290     m[i].type=NM_TYPE_TEXT;
6291 	}
6292 
6293    for (gnum=-1,i=0;i<num_active_games;i++)
6294 	 {
6295 	  if (NamesInfoSecurity==Active_games[i].Security)
6296 		{
6297 		 gnum=i;
6298 		 break;
6299 		}
6300 	 }
6301 
6302 	if (gnum==-1)
6303     {
6304        SurfingNet=0;
6305 		 NamesInfoSecurity=-1;
6306  		 nm_messagebox(NULL, 1, "OK", "The game you have requested\nnames from is gone.\n");
6307 		 SurfingNet=1;
6308 		 return;
6309 	 }
6310 
6311    sprintf (mtext[num],"Players of game '%s':",Active_games[gnum].game_name); num++;
6312    for (i=0;i<numplayers;i++)
6313 	 {
6314 	  l=data[count++];
6315 
6316      mprintf ((0,"%s\n",data+count));
6317 
6318 	  for (t=0;t<CALLSIGN_LEN+1;t++)
6319 		 temp[t]=data[count++];
6320      if (FindArg("-norankings"))
6321 	     sprintf (mtext[num],"%s",temp);
6322 	  else
6323 	     sprintf (mtext[num],"%s%s",RankStrings[l],temp);
6324 
6325 	  num++;
6326 	 }
6327 
6328 	if (data[count]==99)
6329 	{
6330 	 sprintf (mtext[num++]," ");
6331 	 sprintf (mtext[num++],"Short packets: %s",data[count+1]?"On":"Off");
6332 	 sprintf (mtext[num++],"Packets Per Second: %d",data[count+2]);
6333    }
6334 
6335 	already_showing_info=1;
6336 	newmenu_dotiny2( NULL, NULL, num, m, NULL);
6337 	already_showing_info=0;
6338  }
6339 
6340 char NameReturning=1;
6341 
network_send_player_names(sequence_packet * their)6342 void network_send_player_names (sequence_packet *their)
6343  {
6344   int numconnected=0,count=0,i,t;
6345   char buf[80];
6346 
6347   if (!their)
6348    {
6349     mprintf ((0,"Got a player name without a return address! Get Jason\n"));
6350 	 return;
6351 	}
6352 
6353    buf[0]=PID_NAMES_RETURN; count++;
6354    (*(int *)(buf+1))=Netgame.Security; count+=4;
6355 
6356    if (!NameReturning)
6357 	 {
6358      buf[count]=255; count++;
6359 	  goto sendit;
6360 	 }
6361 
6362    mprintf ((0,"RealSec=%d DS=%d\n",Netgame.Security,*(int *)(buf+1)));
6363 
6364    for (i=0;i<N_players;i++)
6365 	 if (Players[i].connected)
6366 		numconnected++;
6367 
6368    buf[count]=numconnected; count++;
6369    for (i=0;i<N_players;i++)
6370 	 if (Players[i].connected)
6371 	  {
6372 		buf[count++]=NetPlayers.players[i].rank;
6373 
6374 		for (t=0;t<CALLSIGN_LEN+1;t++)
6375 		 {
6376 		  buf[count]=NetPlayers.players[i].callsign[t];
6377 		  count++;
6378 		 }
6379 	  }
6380 
6381    buf[count++]=99;
6382 	buf[count++]=Netgame.ShortPackets;
6383 	buf[count++]=Netgame.PacketsPerSec;
6384 
6385    sendit:
6386    				;		// empty statement allows compilation on mac which does not have the
6387    						// statement below and kills the compiler when there is no
6388    						// statement following the label "sendit"
6389 
6390    #ifndef MACINTOSH
6391 	   ipx_send_internetwork_packet_data((ubyte *)buf, count, their->player.network.ipx.server, their->player.network.ipx.node);
6392 	#endif
6393  }
6394 
6395 
HoardEquipped()6396 int HoardEquipped()
6397 {
6398 	static int checked=-1;
6399 
6400 #ifdef WINDOWS
6401 	return 0;
6402 #endif
6403 
6404 	if (checked==-1)
6405 	{
6406 		if (cfexist("hoard.ham"))
6407 			checked=1;
6408 		else
6409 			checked=0;
6410 	}
6411 	return (checked);
6412 }
6413