]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/multi.cpp
Most of network/ works
[taylor/freespace2.git] / src / network / multi.cpp
1 /*
2  * $Logfile: /Freespace2/code/Network/Multi.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * C file that contains high-level multiplayer functions
8  *
9  * $Log$
10  * Revision 1.3  2002/05/26 20:22:48  theoddone33
11  * Most of network/ works
12  *
13  * Revision 1.2  2002/05/07 03:16:47  theoddone33
14  * The Great Newline Fix
15  *
16  * Revision 1.1.1.1  2002/05/03 03:28:10  root
17  * Initial import.
18  *
19  * 
20  * 47    9/15/99 1:45a Dave
21  * Don't init joystick on standalone. Fixed campaign mode on standalone.
22  * Fixed no-score-report problem in TvT
23  * 
24  * 46    8/24/99 1:49a Dave
25  * Fixed client-side afterburner stuttering. Added checkbox for no version
26  * checking on PXO join. Made button info passing more friendly between
27  * client and server.
28  * 
29  * 45    8/22/99 5:53p Dave
30  * Scoring fixes. Added self destruct key. Put callsigns in the logfile
31  * instead of ship designations for multiplayer players.
32  * 
33  * 44    8/22/99 1:19p Dave
34  * Fixed up http proxy code. Cleaned up scoring code. Reverse the order in
35  * which d3d cards are detected.
36  * 
37  * 43    8/19/99 10:59a Dave
38  * Packet loss detection.
39  * 
40  * 42    8/16/99 4:05p Dave
41  * Big honking checkin.
42  * 
43  * 41    8/06/99 12:34a Dave
44  * Be more careful about resetting timestamps.
45  * 
46  * 40    8/04/99 2:24a Dave
47  * Fixed escort gauge ordering for dogfight.
48  * 
49  * 39    7/26/99 5:50p Dave
50  * Revised ingame join. Better? We'll see....
51  * 
52  * 38    7/08/99 10:53a Dave
53  * New multiplayer interpolation scheme. Not 100% done yet, but still
54  * better than the old way.
55  * 
56  * 37    7/06/99 4:24p Dave
57  * Mid-level checkin. Starting on some potentially cool multiplayer
58  * smoothness crap.
59  * 
60  * 36    7/03/99 5:50p Dave
61  * Make rotated bitmaps draw properly in padlock views.
62  * 
63  * 35    6/21/99 7:24p Dave
64  * netplayer pain packet. Added type E unmoving beams.
65  * 
66  * 34    6/07/99 9:51p Dave
67  * Consolidated all multiplayer ports into one.
68  * 
69  * 33    6/04/99 9:52a Dave
70  * Fixed some rendering problems.
71  * 
72  * 32    5/22/99 6:05p Dave
73  * Fixed a few localization # problems.
74  * 
75  * 31    5/22/99 5:35p Dave
76  * Debrief and chatbox screens. Fixed small hi-res HUD bug.
77  * 
78  * 30    5/14/99 1:59p Andsager
79  * Multiplayer message for subsystem cargo revealed.
80  * 
81  * 29    4/29/99 2:29p Dave
82  * Made flak work much better in multiplayer.
83  * 
84  * 28    4/28/99 11:13p Dave
85  * Temporary checkin of artillery code.
86  * 
87  * 27    4/25/99 7:43p Dave
88  * Misc small bug fixes. Made sun draw properly.
89  * 
90  * 26    4/25/99 3:02p Dave
91  * Build defines for the E3 build.
92  * 
93  * 25    4/12/99 10:07p Dave
94  * Made network startup more forgiving. Added checkmarks to dogfight
95  * screen for players who hit commit.
96  * 
97  * 24    4/09/99 2:21p Dave
98  * Multiplayer beta stuff. CD checking.
99  * 
100  * 23    3/19/99 9:51a Dave
101  * Checkin to repair massive source safe crash. Also added support for
102  * pof-style nebulae, and some new weapons code.
103  * 
104  * 23    3/11/99 5:53p Dave
105  * More network optimization. Spliced in Dell OEM planet bitmap crap.
106  * 
107  * 22    3/10/99 6:50p Dave
108  * Changed the way we buffer packets for all clients. Optimized turret
109  * fired packets. Did some weapon firing optimizations.
110  * 
111  * 21    3/09/99 6:24p Dave
112  * More work on object update revamping. Identified several sources of
113  * unnecessary bandwidth.
114  * 
115  * 20    3/08/99 7:03p Dave
116  * First run of new object update system. Looks very promising.
117  * 
118  * 19    3/02/99 4:40p Jasons
119  * Be more careful when calling server-lost-contact popup (make sure other
120  * popups aren't active)
121  * 
122  * 18    3/01/99 7:39p Dave
123  * Added prioritizing ship respawns. Also fixed respawns in TvT so teams
124  * don't mix respawn points.
125  * 
126  * 17    2/23/99 2:29p Dave
127  * First run of oldschool dogfight mode. 
128  * 
129  * 16    2/19/99 2:55p Dave
130  * Temporary checking to report the winner of a squad war match.
131  * 
132  * 15    2/17/99 2:10p Dave
133  * First full run of squad war. All freespace and tracker side stuff
134  * works.
135  * 
136  * 14    2/12/99 6:16p Dave
137  * Pre-mission Squad War code is 95% done.
138  * 
139  * 13    2/11/99 3:08p Dave
140  * PXO refresh button. Very preliminary squad war support.
141  * 
142  * 12    1/14/99 12:48a Dave
143  * Todo list bug fixes. Made a pass at putting briefing icons back into
144  * FRED. Sort of works :(
145  * 
146  * 11    1/12/99 5:45p Dave
147  * Moved weapon pipeline in multiplayer to almost exclusively client side.
148  * Very good results. Bandwidth goes down, playability goes up for crappy
149  * connections. Fixed object update problem for ship subsystems.
150  * 
151  * 10    12/14/98 12:13p Dave
152  * Spiffed up xfer system a bit. Put in support for squad logo file xfer.
153  * Need to test now.
154  * 
155  * 9     12/03/98 5:22p Dave
156  * Ported over Freespace 1 multiplayer ships.tbl and weapons.tbl
157  * checksumming.
158  * 
159  * 8     11/19/98 4:19p Dave
160  * Put IPX sockets back in psnet. Consolidated all multiplayer config
161  * files into one.
162  * 
163  * 7     11/19/98 8:03a Dave
164  * Full support for D3-style reliable sockets. Revamped packet lag/loss
165  * system, made it receiver side and at the lowest possible level.
166  * 
167  * 6     11/17/98 11:12a Dave
168  * Removed player identification by address. Now assign explicit id #'s.
169  * 
170  * 5     11/12/98 12:13a Dave
171  * Tidied code up for multiplayer test. Put in network support for flak
172  * guns.
173  *  
174  *
175  * $NoKeywords: $
176  */
177
178 #ifndef PLAT_UNIX
179 #include <winsock.h>
180 #endif
181
182 #include "pstypes.h"
183 #include "multi.h"
184 #include "multiutil.h"
185 #include "multimsgs.h"
186 #include "psnet.h"
187 #include "linklist.h"
188 #include "object.h"
189 #include "ship.h"
190 #include "hud.h"
191 #include "timer.h"
192 #include "player.h"
193 #include "missionload.h"
194 #include "missionparse.h"
195 #include "missionshipchoice.h"
196 #include "gamesequence.h"
197 #include "freespace.h"
198 #include "osapi.h"
199 #include "math.h"
200 #include "mouse.h"
201 #include "stats.h"
202 #include "stand_gui.h"
203 #include "multi_xfer.h"
204 #include "multiui.h"
205 #include "key.h"
206 #include "multilag.h"
207 #include "multiutil.h"
208 #include "multi_ingame.h"
209 #include "bmpman.h"
210 #include "popup.h"
211 #include "cmdline.h"
212 #include "chatbox.h"
213 #include "multiteamselect.h"
214 #include "multi_data.h"
215 #include "multi_kick.h"
216 #include "multi_campaign.h"
217 #include "multi_voice.h"
218 #include "multi_team.h"
219 #include "multi_respawn.h"
220 #include "multi_pmsg.h"
221 #include "multi_endgame.h"
222 #include "missiondebrief.h"
223 #include "multi_pause.h"
224 #include "multi_obj.h"
225 #include "missiongoals.h"
226 #include "multi_log.h"
227 #include "multi_rate.h"
228 #include "hudescort.h"
229 #include "alphacolors.h"
230
231 // ----------------------------------------------------------------------------------------
232 // Basic module scope defines
233 //
234 //
235
236 // timestamp defines
237 // #define NETGAME_SEND_TIME                                                            1000                                    // time between sending netgame update packets
238 // #define STATE_SEND_TIME                                                                      1000                                    // time between sending netplayer state packets
239 // #define GAMEINFO_SEND_TIME                                                           3000                                    // time between sending game information packets
240 // #define PING_SEND_TIME                                                                       2000                                    // time between player pings
241 // #define INGAME_UPDATE_TIME                                                           1000                                    // time limit between ingame join operations
242 #define NETGAME_SEND_TIME                                                               2                                               // time between sending netgame update packets
243 #define STATE_SEND_TIME                                                                 2                                               // time between sending netplayer state packets
244 #define GAMEINFO_SEND_TIME                                                              3                                               // time between sending game information packets
245 #define PING_SEND_TIME                                                                  2                                               // time between player pings
246 #define BYTES_SENT_TIME                                                                 5                                               // every five seconds
247
248 // netplayer stuff
249 #define CULL_ZOMBIE_TIME                                                                1000                                    //      zombies are checked for at this interval (in milliseconds)
250
251 // object update stuff
252 #define SEND_POS_INTERVAL                                                               30                                              // min time in milliseconds between sending position updates
253
254 // local network buffer stuff
255 #define MAX_NET_BUFFER                                                                  (1024 * 16)                     // define and variable declaration for our local tcp buffer
256 #define NUM_REENTRANT_LEVELS                                                    3
257
258 // time (in fixed seconds) to put up dialog about no contect from server
259 #define MULTI_SERVER_MAX_TIMEOUT                                                (F1_0 * 4)                                      // after this number of milliseoncds, stop client simulation
260 #define MULTI_SERVER_MAX_TIMEOUT_LARGE                          (F1_0 * 40)                                     // done anytime not in mission
261 #define MULTI_SERVER_WAIT_TIME                                          (F1_0 * 60)                                     // wait 60 seconds to reconnect with the server
262 #define MULTI_SERVER_GONE                                                               1
263 #define MULTI_SERVER_ALIVE                                                              2
264
265 #define DISCONNECT_TIMEOUT                                                              (F1_0 * 10)                                     // 10 seconds to timeout someone who cannot connnect
266
267 // define for when to show "slow network" icon
268 #define MULTI_SERVER_SLOW_PING_TIME                                     700                                     // when average ping time to server reaches this -- display hud icon
269
270 // update times for clients ships based on object update level
271 #define MULTI_CLIENT_UPDATE_TIME                                                333
272
273 int Multi_display_netinfo = 1;
274
275 // ----------------------------------------------------------------------------------------
276 // Multiplayer vars
277 //
278 //
279
280 // net player vars              
281 net_player Net_players[MAX_PLAYERS];                                                    // array of all netplayers in the game
282 net_player *Net_player;                                                                                         // pointer to console's net_player entry
283
284 // network object management
285 ushort Next_ship_signature;                                                                             // next permanent network signature to assign to an object
286 ushort Next_asteroid_signature;                                                                 // next signature for an asteroid
287 ushort Next_non_perm_signature;                                                                 // next non-permanent network signature to assign to an object
288 ushort Next_debris_signature;                                                                           // next debris signature
289
290 // netgame vars
291 netgame_info Netgame;                                                                                           // netgame information
292 int Multi_mission_loaded = 0;                                                                           // flag, so that we dont' load the mission more than once client side
293 int Ingame_join_net_signature = -1;                                                             // signature for the player obj for use when joining ingame
294 int Multi_button_info_ok = 0;                                                                           // flag saying it is ok to apply critical button info on a client machine
295 int Multi_button_info_id = 0;                                                                           // identifier of the stored button info to be applying
296
297 // low level networking vars
298 int ADDRESS_LENGTH;                                                                                                     // will be 6 for IPX, 4 for IP
299 int PORT_LENGTH;                                                                                                                // will be 2 for IPX, 2 for IP
300 int HEADER_LENGTH;                                                                                                      // 1 byte (packet type)
301
302 // misc data
303 active_game* Active_game_head;                                                                  // linked list of active games displayed on Join screen
304 int Active_game_count;                                                                                          // for interface screens as well
305 CFILE* Multi_chat_stream;                                                                                       // for streaming multiplayer chat strings to a file
306 int Multi_has_cd = 0;                                                                                           // if this machine has a cd or not (call multi_common_verify_cd() to set this)
307 int Multi_connection_speed;                                                                             // connection speed of this machine.
308 int Multi_num_players_at_start = 0;                                                             // the # of players present (kept track of only on the server) at the very start of the mission
309 short Multi_id_num = 0;                                                                                         // for assigning player id #'s
310
311 // permanent server list
312 server_item* Game_server_head;                                                          // list of permanent game servers to be querying
313
314 // timestamp data
315 int Netgame_send_time = -1;                                                     // timestamp used to send netgame info to players before misison starts
316 int State_send_time = -1;                                                               // timestamp used to send state information to the host before a mission starts
317 int Gameinfo_send_time = -1;                                                    // timestamp used by master to send game information to clients
318 int Next_ping_time = -1;                                                                // when we should next ping all
319 int Multi_server_check_count = 0;                                       // var to keep track of reentrancy when checking server status
320 int Next_bytes_time = -1;                                                               // bytes sent
321
322 // how often each player gets updated
323 int Multi_client_update_times[MAX_PLAYERS];     // client update packet timestamp
324
325 // local network buffer data
326 LOCAL ubyte net_buffer[NUM_REENTRANT_LEVELS][MAX_NET_BUFFER];
327 LOCAL ubyte Multi_read_count;
328
329 int Multi_restr_query_timestamp = -1;
330 join_request Multi_restr_join_request;
331 net_addr Multi_restr_addr;                              
332 int Multi_join_restr_mode = -1;
333
334 LOCAL fix Multi_server_wait_start;                              // variable to hold start time when waiting to reestablish with server
335
336 // non API master tracker vars
337 char Multi_tracker_login[100] = "";
338 char Multi_tracker_passwd[100] = "";
339 char Multi_tracker_squad_name[100] = "";
340 int Multi_tracker_id = -1;
341 char Multi_tracker_id_string[255];
342
343 // current file checksum
344 ushort Multi_current_file_checksum = 0;
345 int Multi_current_file_length = -1;
346
347
348 // -------------------------------------------------------------------------------------------------
349 //      multi_init() is called only once, at game start-up.  Get player address + port, initialize the
350 // network players list.
351 //
352 //
353
354 void multi_init()
355 {
356         int idx;
357
358         // read in config file
359         multi_options_read_config();
360
361         Assert( Net_player == NULL );
362         Multi_id_num = 0;
363
364         // clear out all netplayers
365         memset(Net_players, 0, sizeof(net_player) * MAX_PLAYERS);
366         for(idx=0; idx<MAX_PLAYERS; idx++){
367                 Net_players[idx].reliable_socket = INVALID_SOCKET;
368         }
369
370         // initialize the local netplayer
371         Net_player = &Net_players[0];   
372         Net_player->tracker_player_id = Multi_tracker_id;
373         Net_player->player = Player;
374         Net_player->flags = 0;  
375         Net_player->s_info.xfer_handle = -1;
376         Net_player->player_id = multi_get_new_id();
377         Net_player->client_cinfo_seq = 0;
378         Net_player->client_server_seq = 0;              
379
380         // get our connection speed
381         Multi_connection_speed = multi_get_connection_speed();                  
382         
383         // initialize other stuff
384         multi_log_init();
385
386         // load up common multiplayer icons
387         multi_load_common_icons();      
388 }
389
390 // this is an important function which re-initializes any variables required in multiplayer games. 
391 // Always make sure globals you add are re-initialized here !!!!
392 void multi_vars_init()
393 {
394         // initialize this variable right away.  Used in game_level_init for init'ing the player
395         Next_ship_signature = SHIP_SIG_MIN;             
396         Next_asteroid_signature = ASTEROID_SIG_MIN;
397         Next_non_perm_signature = NPERM_SIG_MIN;   
398         Next_debris_signature = DEBRIS_SIG_MIN;
399         
400         // server-client critical stuff
401         Multi_button_info_ok = 0;
402         Multi_button_info_id = 0;
403
404         // Ingame join stuff
405         Ingame_join_net_signature = -1;
406
407         // Netgame stuff
408         Netgame.game_state = NETGAME_STATE_FORMING;     
409
410         // team select stuff
411         Multi_ts_inited = 0;    
412
413         // load send stuff
414         Multi_mission_loaded = 0;   // client side              
415
416         // restricted game stuff
417         Multi_restr_query_timestamp = -1;       
418
419         // respawn stuff        
420         Multi_server_check_count = 0;
421
422         // reentrant variable
423         Multi_read_count = 0;
424
425         // unset the "have cd" var
426         // NOTE: we unset this here because we are going to be calling multi_common_verify_cd() 
427         //       immediately after this (in multi_level_init() to re-check the status)
428         Multi_has_cd = 0;
429
430         // current file checksum
431         Multi_current_file_checksum = 0;
432         Multi_current_file_length = -1;
433
434         Active_game_head = NULL;
435         Game_server_head = NULL;
436
437         // only the server should ever care about this
438         Multi_id_num = 0;
439 }
440
441 // -------------------------------------------------------------------------------------------------
442 //      multi_level_init() is called whenever the player starts a multiplayer game
443 //
444 //
445
446 void multi_level_init() 
447 {
448         int idx;
449
450         // NETLOG
451         ml_string(NOX("multi_level_init()"));
452
453         // initialize the Net_players array
454         for(idx=0;idx<MAX_PLAYERS;idx++) {
455                 // close all sockets down just for good measure
456                 psnet_rel_close_socket(&Net_players[idx].reliable_socket);
457
458                 memset(&Net_players[idx],0,sizeof(net_player));
459                 Net_players[idx].reliable_socket = INVALID_SOCKET;
460
461                 Net_players[idx].s_info.xfer_handle = -1;
462                 Net_players[idx].p_info.team = 0;
463         }
464
465         // initialize the Players array
466         for(idx=0;idx<MAX_PLAYERS;idx++){
467                 if(Player == &Players[idx]){
468                         continue;
469                 }
470                 memset(&Players[idx],0,sizeof(player));
471         }
472
473         multi_vars_init();      
474
475         // initialize the fake lag/loss system
476 #ifdef MULTI_USE_LAG
477         multi_lag_init();
478 #endif
479
480         // initialize the kick system
481         multi_kick_init();
482
483         // initialize all file xfer stuff
484         multi_xfer_init(multi_file_xfer_notify);
485
486         // close the chatbox (if one exists)
487         chatbox_close();        
488
489         // reset the data xfer system
490         multi_data_reset();
491
492         // initialize the voice system
493         multi_voice_init();
494
495         // intialize the pause system
496         multi_pause_reset();
497
498         // initialize endgame stuff
499         multi_endgame_init();
500
501         // initialize respawning
502         multi_respawn_init();
503
504         // initialize all netgame timestamps
505    multi_reset_timestamps();
506
507         // flush psnet sockets
508         psnet_flush();
509 }
510
511 // multi_check_listen() calls low level psnet routine to see if we have a connection from a client we
512 // should accept.
513 void multi_check_listen()
514 {
515         int i;
516         net_addr addr;
517         PSNET_SOCKET_RELIABLE sock = INVALID_SOCKET;
518
519         // call psnet routine which calls select to see if we need to check for a connect from a client
520         // by passing addr, we are telling check_for_listen to do the accept and return who it was from in
521         // addr.  The
522         sock = psnet_rel_check_for_listen(&addr);
523         if ( sock != INVALID_SOCKET ) {
524                 // be sure that my address and the server address are set correctly.
525                 if ( !psnet_same(&Psnet_my_addr, &Net_player->p_info.addr) ){
526                         Net_player->p_info.addr = Psnet_my_addr;
527                 }
528
529                 if ( !psnet_same(&Psnet_my_addr, &(Netgame.server_addr)) ){
530                         Netgame.server_addr = Psnet_my_addr;
531                 }
532
533                 // the connection was accepted in check_for_listen.  Find the netplayer whose address we connected
534                 // with and assign the socket descriptor
535                 for (i = 0; i < MAX_PLAYERS; i++ ) {
536                         if ( (Net_players[i].flags & NETINFO_FLAG_CONNECTED) && (!memcmp(&(addr.addr), &(Net_players[i].p_info.addr.addr), 6)) ) {
537                                 // mark this flag so we know he's "fully" connected
538                                 Net_players[i].flags |= NETINFO_FLAG_RELIABLE_CONNECTED;
539                                 Net_players[i].reliable_socket = sock;
540
541                                 // send player information to the joiner
542                                 send_accept_player_data( &Net_players[i], (Net_players[i].flags & NETINFO_FLAG_INGAME_JOIN)?1:0 );
543
544                                 // send a netgame update so the new client has all the necessary settings
545                                 send_netgame_update_packet();   
546
547                                 // if this is a team vs. team game, send an update
548                                 if(Netgame.type_flags & NG_TYPE_TEAM){
549                                         multi_team_send_update();
550                                 }
551
552                                 // NETLOG
553                                 ml_printf(NOX("Accepted TCP connection from %s"), Net_players[i].player == NULL ? NOX("Unknown") : Net_players[i].player->callsign);                            
554                                 break;
555                         }
556                 }
557
558                 // if we didn't find a player, close the socket
559                 if ( i == MAX_PLAYERS ) {
560                         nprintf(("Network", "Got accept on my listen socket, but unknown player.  Closing socket.\n"));
561                         psnet_rel_close_socket(&sock);
562                 }
563         }
564 }
565
566 // returns true is server hasn't been heard from in N seconds. false otherwise
567 int multi_client_server_dead()
568 {
569         fix this_time, last_time, max;
570
571         // get the last time we have heard from the server.  If greater than some default, then maybe
572         // display some icon on the HUD indicating slow network connection.  if greater than some higher
573         // max, stop simulating on the client side until we hear from the server again.
574         this_time = timer_get_fixed_seconds();
575         last_time = Netgame.server->last_heard_time;
576         // check for wrap!  must return 0
577         if ( last_time > this_time )
578                 return 0;
579
580         this_time -= last_time;
581
582         // if in mission, use the smaller timeout value.  Outside of mission, use a large one.
583         if ( MULTI_IN_MISSION ){
584                 max = MULTI_SERVER_MAX_TIMEOUT;
585         } else {
586                 max = MULTI_SERVER_MAX_TIMEOUT_LARGE;
587         }
588
589         if ( this_time > max){
590                 return 1;
591         } else {
592                 return 0;
593         }
594 }
595
596 void multi_process_incoming();          // prototype for function later in this module
597
598 // function to process network data in hopes of getting info back from server
599 int multi_client_wait_on_server()
600 {
601         int is_dead;
602
603         is_dead = multi_client_server_dead();
604
605         // if the server is back alive, tell our popup
606         if ( !is_dead ){
607                 return MULTI_SERVER_ALIVE;
608         }
609
610         // on release version -- keep popup active for 60 seconds, then bail
611 #ifdef NDEBUG
612         fix this_time = timer_get_fixed_seconds();
613         // if the timer wrapped:
614         if ( this_time < Multi_server_wait_start ) {
615                 Multi_server_wait_start = timer_get_fixed_seconds();
616                 return FALSE;
617         }
618         // check to see if timeout expired
619         this_time -= Multi_server_wait_start;
620         if ( this_time > MULTI_SERVER_WAIT_TIME ){
621                 return MULTI_SERVER_GONE;
622         }
623 #endif
624
625         return FALSE;
626 }
627
628 // function called by multiplayer clients to stop simulating when they have not heard from the server
629 // in a while.
630 void multi_client_check_server()
631 {
632         int rval;
633
634         Assert( MULTIPLAYER_CLIENT );   
635
636         // this function can get called while in the popup code below.  So we include this check as a
637         // reentrancy check.
638         if ( Multi_server_check_count )
639                 return;
640
641         // make sure we have a valid server
642         if(Netgame.server == NULL){
643                 return;
644         }
645
646         Multi_server_check_count++;
647         if(multi_client_server_dead()){
648                 Netgame.flags |= NG_FLAG_SERVER_LOST;
649         } else {
650                 Netgame.flags &= ~(NG_FLAG_SERVER_LOST);
651         }
652
653         if(Netgame.flags & NG_FLAG_SERVER_LOST) {
654                 if(!(Game_mode & GM_IN_MISSION) && !popup_active()){    
655                         // need to start a popup
656                         Multi_server_wait_start = timer_get_fixed_seconds();
657                         rval = popup_till_condition( multi_client_wait_on_server, XSTR("Cancel",641), XSTR("Contact lost with server.  Stopping simulation until contact reestablished.  Press Cancel to exit game.",642) );
658                         
659                         if ( !rval || (rval == MULTI_SERVER_GONE) ) {                           
660                                 multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_CONTACT_LOST);                                                              
661                         }
662                         Netgame.flags &= ~(NG_FLAG_SERVER_LOST);
663                 }
664         }
665
666         Multi_server_check_count--;
667 }
668
669
670 // -------------------------------------------------------------------------------------------------
671 //      process_packet_normal() will determine what sort of packet it is, and send it to the appropriate spot.
672 //      Prelimiary verification of the magic number and checksum are done here.  
673 //
674
675 void process_packet_normal(ubyte* data, header *header_info)
676 {
677         switch ( data[0] ) {
678
679                 case JOIN:
680                         process_join_packet(data, header_info);
681                         break;
682
683                 case GAME_CHAT:
684                         process_game_chat_packet( data, header_info );
685                         break;
686
687                 case NOTIFY_NEW_PLAYER:
688                         process_new_player_packet(data, header_info);
689                         break;
690
691                 case HUD_MSG:
692                         process_hud_message(data, header_info);
693                         break;
694
695                 case MISSION_MESSAGE:
696                         process_mission_message_packet( data, header_info );
697                         break;
698
699                 case LEAVE_GAME:
700                         process_leave_game_packet(data, header_info);
701                         break;
702
703                 case GAME_QUERY:
704                         process_game_query(data, header_info);
705                         break;
706
707                 case GAME_ACTIVE:
708                         process_game_active_packet(data, header_info);
709                         break;
710
711                 case GAME_INFO:
712                         process_game_info_packet( data, header_info );
713                         break;          
714
715                 case SECONDARY_FIRED_AI:
716                         process_secondary_fired_packet(data, header_info, 0);
717                         break;          
718
719                 case SECONDARY_FIRED_PLR:
720                         process_secondary_fired_packet(data, header_info, 1);
721                         break;
722
723                 case COUNTERMEASURE_FIRED:
724                         process_countermeasure_fired_packet( data, header_info );
725                         break;          
726
727                 case FIRE_TURRET_WEAPON:
728                         process_turret_fired_packet( data, header_info );
729                         break;
730
731                 case GAME_UPDATE:
732                         process_netgame_update_packet( data, header_info );
733                         break;
734
735                 case UPDATE_DESCRIPT:
736                         process_netgame_descript_packet( data, header_info );
737                         break;
738
739                 case NETPLAYER_UPDATE:
740                         process_netplayer_update_packet( data, header_info );
741                         break;
742
743                 case ACCEPT :
744                         process_accept_packet(data, header_info);
745                         break;                          
746
747                 case OBJECT_UPDATE:
748                         multi_oo_process_update(data, header_info);
749                         break;
750
751                 case SHIP_KILL:
752                         process_ship_kill_packet( data, header_info );
753                         break;
754
755                 case WING_CREATE:
756                         process_wing_create_packet( data, header_info );
757                         break;
758                         
759                 case SHIP_CREATE:
760                         process_ship_create_packet( data, header_info );
761                         break;
762
763                 case SHIP_DEPART:
764                         process_ship_depart_packet( data, header_info );
765                         break;
766
767                 case MISSION_LOG_ENTRY:
768                         process_mission_log_packet( data, header_info );
769                         break;          
770
771                 case PING:
772                         process_ping_packet(data, header_info);
773                         break;
774
775                 case PONG:
776                         process_pong_packet(data, header_info);
777                         break;          
778
779                 case XFER_PACKET:
780                         Assert(header_info->id >= 0);
781                         int np_index;
782                         PSNET_SOCKET_RELIABLE sock;
783                         sock = INVALID_SOCKET;
784
785                         // if I'm the server of the game, find out who this came from                   
786                         if((Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
787                                 np_index = find_player_id(header_info->id);
788                                 if(np_index >= 0){
789                                         sock = Net_players[np_index].reliable_socket;
790                                 }
791                         }
792                         // otherwise always use my own socket
793                         else if(Net_player != NULL){
794                                 sock = Net_player->reliable_socket;
795                         }
796                         
797                         header_info->bytes_processed = multi_xfer_process_packet(data + HEADER_LENGTH, sock) + HEADER_LENGTH;
798                         break;
799
800                 case MISSION_REQUEST:
801                         process_mission_request_packet(data,header_info);
802                         break;
803
804                 case MISSION_ITEM:
805                         process_mission_item_packet(data,header_info);
806                         break;          
807
808                 case MULTI_PAUSE_REQUEST:
809                         process_multi_pause_packet(data, header_info);
810                         break;          
811
812                 case INGAME_NAK:
813                         process_ingame_nak(data, header_info);
814                         break;
815
816                 case SHIPS_INGAME_PACKET:
817                         process_ingame_ships_packet(data, header_info);
818                         break;
819
820                 case WINGS_INGAME_PACKET:
821                         process_ingame_wings_packet(data, header_info);
822                         break;
823
824                 case MISSION_END:
825                         process_endgame_packet(data, header_info);
826                         break;
827                 
828                 case OBSERVER_UPDATE:
829                         process_observer_update_packet(data, header_info);
830                         break;
831
832                 case NETPLAYER_SLOTS_P:
833                         process_netplayer_slot_packet(data, header_info);
834                         break;
835
836                 case SHIP_STATUS_CHANGE:
837                         process_ship_status_packet(data, header_info);
838                         break;
839
840                 case PLAYER_ORDER_PACKET:
841                         process_player_order_packet(data, header_info);
842                         break;
843
844                 case INGAME_SHIP_UPDATE:
845                         process_ingame_ship_update_packet(data, header_info);
846                         break;
847
848                 case INGAME_SHIP_REQUEST:
849                         process_ingame_ship_request_packet(data, header_info);
850                         break;
851                 
852                 case FILE_SIG_INFO:
853                         process_file_sig_packet(data, header_info);
854                         break;
855
856                 case RESPAWN_NOTICE:
857                         multi_respawn_process_packet(data,header_info);                 
858                         break;
859
860                 case SUBSYSTEM_DESTROYED:
861                         process_subsystem_destroyed_packet( data, header_info );
862                         break;
863
864                 case LOAD_MISSION_NOW :
865                         process_netplayer_load_packet(data, header_info);
866                         break;
867
868                 case FILE_SIG_REQUEST :
869                         process_file_sig_request(data, header_info);
870                         break;
871
872                 case JUMP_INTO_GAME:
873                         process_jump_into_mission_packet(data, header_info);
874                         break;          
875
876                 case CLIENT_REPAIR_INFO:
877                         process_repair_info_packet(data,header_info);
878                         break;
879
880                 case MISSION_SYNC_DATA:
881                         process_mission_sync_packet(data,header_info);
882                         break;
883
884                 case STORE_MISSION_STATS:
885                         process_store_stats_packet(data, header_info);
886                         break;
887
888                 case DEBRIS_UPDATE:
889                         process_debris_update_packet(data, header_info);
890                         break;          
891
892                 case SHIP_WSTATE_CHANGE:
893                         process_ship_weapon_change( data, header_info );
894                         break;
895
896                 case WSS_UPDATE_PACKET:
897                         process_wss_update_packet(data, header_info);
898                         break;
899
900                 case WSS_REQUEST_PACKET:
901                         process_wss_request_packet( data, header_info );
902                         break;  
903
904                 case FIRING_INFO:
905                         process_firing_info_packet( data, header_info );
906                         break;          
907
908                 case CARGO_REVEALED:
909                         process_cargo_revealed_packet( data, header_info);
910                         break;          
911
912                 case SUBSYS_CARGO_REVEALED:
913                         process_subsystem_cargo_revealed_packet( data, header_info);
914                         break;          
915
916                 case MISSION_GOAL_INFO:
917                         process_mission_goal_info_packet(data, header_info);
918                         break;
919
920                 case KICK_PLAYER:
921                         process_player_kick_packet(data, header_info);
922                         break;
923
924                 case PLAYER_SETTINGS:
925                         process_player_settings_packet(data, header_info);
926                         break;
927
928                 case DENY:
929                         process_deny_packet(data, header_info);
930                         break;
931
932                 case POST_SYNC_DATA:
933                         process_post_sync_data_packet(data, header_info);
934                         break;
935
936                 case WSS_SLOTS_DATA:
937                         process_wss_slots_data_packet(data,header_info);
938                         break;
939
940                 case SHIELD_EXPLOSION:
941                         process_shield_explosion_packet( data, header_info );
942                         break;
943
944                 case PLAYER_STATS:
945                         process_player_stats_block_packet(data, header_info);
946                         break;
947
948                 case SLOT_UPDATE:
949                         process_pslot_update_packet(data,header_info);
950                         break;
951
952                 case AI_INFO_UPDATE:
953                         process_ai_info_update_packet( data, header_info );
954                         break;          
955
956                 case CAMPAIGN_UPDATE :
957                         multi_campaign_process_update(data,header_info);
958                         break;
959
960                 case CAMPAIGN_UPDATE_INGAME:
961                         multi_campaign_process_ingame_start(data,header_info);
962                         break;
963
964                 case VOICE_PACKET :
965                         multi_voice_process_packet(data,header_info);
966                         break;
967
968                 case TEAM_UPDATE :
969                         multi_team_process_packet(data,header_info);
970                         break;
971
972                 case ASTEROID_INFO:
973                         process_asteroid_info(data, header_info);
974                         break;          
975
976                 case HOST_RESTR_QUERY:
977                         process_host_restr_packet(data, header_info);
978                         break;
979
980                 case OPTIONS_UPDATE:
981                         multi_options_process_packet(data,header_info);
982                         break;
983
984                 case SQUADMSG_PLAYER:
985                         multi_msg_process_squadmsg_packet(data,header_info);
986                         break;
987
988                 case NETGAME_END_ERROR:
989                         process_netgame_end_error_packet(data,header_info);
990                         break;
991
992                 case COUNTERMEASURE_SUCCESS:
993                         process_countermeasure_success_packet( data, header_info );
994                         break;
995
996                 case CLIENT_UPDATE:
997                         process_client_update_packet(data, header_info);
998                         break;
999
1000                 case COUNTDOWN:
1001                         process_countdown_packet(data, header_info);
1002                         break;
1003
1004                 case DEBRIEF_INFO:
1005                         process_debrief_info( data, header_info );
1006                         break;
1007
1008                 case ACCEPT_PLAYER_DATA:
1009                         process_accept_player_data( data, header_info );
1010                         break;                          
1011
1012                 case HOMING_WEAPON_UPDATE:
1013                         process_homing_weapon_info( data, header_info );
1014                         break;          
1015
1016                 case EMP_EFFECT:
1017                         process_emp_effect(data, header_info);
1018                         break;
1019
1020                 case REINFORCEMENT_AVAIL:
1021                         process_reinforcement_avail( data, header_info );
1022                         break;
1023
1024                 case CHANGE_IFF:
1025                         process_change_iff_packet(data, header_info);
1026                         break;
1027
1028                 case PRIMARY_FIRED_NEW:
1029                         process_NEW_primary_fired_packet(data, header_info);
1030                         break;
1031
1032                 case COUNTERMEASURE_NEW:
1033                         process_NEW_countermeasure_fired_packet(data, header_info);
1034                         break;
1035
1036                 case BEAM_FIRED:
1037                         process_beam_fired_packet(data, header_info);
1038                         break;          
1039                         
1040                 case SW_STD_QUERY:
1041                         process_sw_query_packet(data, header_info);
1042                         break;
1043
1044                 case EVENT_UPDATE:
1045                         process_event_update_packet(data, header_info);
1046                         break;
1047
1048                 case OBJECT_UPDATE_NEW:                 
1049                         multi_oo_process_update(data, header_info);
1050                         break;
1051
1052                 case WEAPON_DET:
1053                         process_weapon_detonate_packet(data, header_info);
1054                         break;
1055
1056                 case FLAK_FIRED:
1057                         process_flak_fired_packet(data, header_info);
1058                         break;
1059
1060                 case NETPLAYER_PAIN:
1061                         process_player_pain_packet(data, header_info);
1062                         break;
1063
1064                 case LIGHTNING_PACKET:
1065                         process_lightning_packet(data, header_info);
1066                         break;
1067
1068                 case BYTES_SENT:
1069                         process_bytes_recvd_packet(data, header_info);
1070                         break;
1071
1072                 case TRANSFER_HOST:
1073                         process_host_captain_change_packet(data, header_info);
1074                         break;
1075
1076                 case SELF_DESTRUCT:
1077                         process_self_destruct_packet(data, header_info);
1078                         break;
1079
1080                 default:
1081                         nprintf(("Network", "Received packet with unknown type %d\n", data[0] ));
1082                         header_info->bytes_processed = 10000;
1083                         break;
1084
1085         } // end switch
1086 }
1087
1088
1089
1090 // Takes a bunch of messages, check them for validity,
1091 // and pass them to multi_process_data. 
1092 //  --------------------^
1093 // this should be process_packet() I think, or with the new code
1094 // process_tracker_packet() as defined in MultiTracker.[h,cpp]
1095 void multi_process_bigdata(ubyte *data, int len, net_addr *from_addr, int reliable)
1096 {
1097         int type, bytes_processed;
1098         int player_num;
1099         header header_info;
1100         ubyte *buf;     
1101
1102         // the only packets we will process from an unknown player are GAME_QUERY, GAME_INFO, JOIN, PING, PONG, ACCEPT, and GAME_ACTIVE packets
1103         player_num = find_player(from_addr);            
1104
1105         // find the player who sent the message and mark the last_heard time for this player
1106         // check to see if netplayer is null (it may be in cases such as getting lists of games from the tracker)
1107         if(player_num >= 0){
1108                 Net_players[player_num].last_heard_time = timer_get_fixed_seconds();
1109         }
1110
1111         // store fields that were passed along in the message
1112         // store header information that was captured from the network-layer header
1113         memcpy(header_info.addr, from_addr->addr, 6);
1114         memcpy(header_info.net_id, from_addr->net_id, 4);
1115         header_info.port = from_addr->port;     
1116         if(player_num >= 0){
1117                 header_info.id = Net_players[player_num].player_id;
1118         } else {
1119                 header_info.id = -1;
1120         }   
1121
1122         bytes_processed = 0;
1123         while( (bytes_processed >= 0) && (bytes_processed < len) )  {
1124
1125       buf = &(data[bytes_processed]);
1126
1127       type = buf[0];
1128
1129                 // if its coming from an unknown source, there are only certain packets we will actually process
1130                 if((player_num == -1) && !multi_is_valid_unknown_packet((ubyte)type)){
1131                         return ;
1132                 }               
1133
1134                 if ( (type<0) || (type > MAX_TYPE_ID )) {
1135                         nprintf( ("Network", "multi_process_bigdata: Invalid packet type %d!\n", type ));
1136                         return;
1137                 }               
1138
1139                 // perform any special processing checks here           
1140                 process_packet_normal(buf,&header_info);
1141                  
1142                 // MWA -- magic number was removed from header on 8/4/97.  Replaced with bytes_processed
1143                 // variable which gets stuffed whenever a packet is processed.
1144                 bytes_processed += header_info.bytes_processed;
1145         }
1146
1147         // if this is not reliable data and we have a valid player
1148         if(Net_player != NULL){
1149                 if(!MULTIPLAYER_MASTER && !reliable && (Game_mode & GM_IN_MISSION)){
1150                         Net_player->cl_bytes_recvd += len;
1151                 }
1152         }
1153 }
1154
1155 // process all reliable socket details
1156 void multi_process_reliable_details()
1157 {
1158         int idx;
1159         int sock_status;
1160
1161         // run reliable sockets
1162 #ifdef PSNET2
1163         psnet_rel_work();
1164 #endif
1165         
1166         // server operations
1167         if ( MULTIPLAYER_MASTER ){
1168                 // listen for new reliable socket connections
1169                 multi_check_listen();           
1170
1171                 // check for any broken sockets and delete any players
1172                 for(idx=0; idx<MAX_PLAYERS; idx++){
1173                         // players who _should_ be validly connected
1174                         if((idx != MY_NET_PLAYER_NUM) && MULTI_CONNECTED(Net_players[idx])){                            
1175                                 // if this guy's socket is broken or disconnected, kill him
1176                                 sock_status = psnet_rel_get_status(Net_players[idx].reliable_socket);
1177                                 if((sock_status == RNF_UNUSED) || (sock_status == RNF_BROKEN) || (sock_status == RNF_DISCONNECTED)){
1178                                         ml_string("Shutting down rel socket because of disconnect!");
1179                                         delete_player(idx);
1180                                 }
1181
1182                                 // if we're still waiting for this guy to connect on his reliable socket and he's timed out, boot him
1183                                 if(Net_players[idx].s_info.reliable_connect_time != -1){
1184                                         // if he's connected
1185                                         if(Net_players[idx].reliable_socket != INVALID_SOCKET){
1186                                                 Net_players[idx].s_info.reliable_connect_time = -1;
1187                                         } 
1188                                         // if he's timed out
1189                                         else if(((time(NULL) - Net_players[idx].s_info.reliable_connect_time) > MULTI_RELIABLE_CONNECT_WAIT) && (Net_players[idx].reliable_socket == INVALID_SOCKET)){
1190                                                 ml_string("Player timed out while connecting on reliable socket!");
1191                                                 delete_player(idx);
1192                                         }
1193                                 }                       
1194                         }
1195                 }
1196         }       
1197         // clients should detect broken sockets
1198         else {
1199                 extern unsigned int Serverconn;
1200                 if(Serverconn != 0xffffffff){
1201                         int status = psnet_rel_get_status(Serverconn);
1202                         if(status == RNF_BROKEN){
1203                                 mprintf(("CLIENT SOCKET DISCONNECTED"));
1204
1205                                 // quit the game
1206                                 if(!multi_endgame_ending()){
1207                                         multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_CONTACT_LOST);
1208                                 }
1209                         }
1210                 }
1211         }
1212 }
1213
1214 // multi_process_incoming reads incoming data off the unreliable and reliable ports and sends
1215 // the data to process_big_data
1216 void multi_process_incoming()
1217 {
1218         int size;
1219         ubyte *data, *savep;
1220         net_addr from_addr;     
1221
1222         Assert( Multi_read_count < NUM_REENTRANT_LEVELS );
1223         savep = net_buffer[Multi_read_count];
1224
1225         Multi_read_count++;
1226
1227         data = savep;
1228
1229         // get the other net players data
1230         while( (size = psnet_get(data, &from_addr))>0 ) {
1231                 // ingame joiners will ignore UDP packets until they are have picked a ship and are in the mission
1232                 if( (Net_player->flags & NETINFO_FLAG_INGAME_JOIN) && (Net_player->state != NETPLAYER_STATE_INGAME_SHIP_SELECT) ){
1233                         //nprintf(("Network","Tossing UDP like a good little ingame joiner...\n"));
1234                 } 
1235                 // otherwise process incoming data normally
1236                 else {
1237                         multi_process_bigdata(data, size, &from_addr, 0);
1238                 }
1239         } // end while
1240
1241         // read reliable sockets for data
1242         data = savep;
1243         int idx;
1244
1245         if(Net_player->flags & NETINFO_FLAG_AM_MASTER){
1246                 for (idx=0;idx<MAX_PLAYERS;idx++) {
1247                         if((Net_players[idx].flags & NETINFO_FLAG_CONNECTED) && (Net_player != NULL) && (Net_player->player_id != Net_players[idx].player_id)){
1248                                 while( (size = psnet_rel_get(Net_players[idx].reliable_socket, data, MAX_NET_BUFFER)) > 0){
1249                                         multi_process_bigdata(data, size, &Net_players[idx].p_info.addr, 1);
1250                                 }
1251                         }
1252                 }
1253         } else {
1254                 // if I'm not the master of the game, read reliable data from my connection with the server
1255                 if((Net_player->reliable_socket != INVALID_SOCKET) && (Net_player->reliable_socket != 0)){
1256                         while( (size = psnet_rel_get(Net_player->reliable_socket,data, MAX_NET_BUFFER)) > 0){                           
1257                                 multi_process_bigdata(data, size, &Netgame.server_addr, 1);
1258                         }
1259                 }
1260         }
1261                 
1262         Multi_read_count--;
1263 }
1264
1265 // -------------------------------------------------------------------------------------------------
1266 //      multi_do_frame() is called once per game loop do update all the multiplayer objects, and send
1267 // the player data to all the other net players.
1268 //
1269 //
1270
1271 int eye_tog = 1;
1272 DCF(eye_tog, "")
1273 {
1274         eye_tog = !eye_tog;
1275         if(eye_tog){
1276                 dc_printf("proper eye stuff on\n");
1277         } else {
1278                 dc_printf("proper eye stuff off\n");
1279         }
1280 }
1281
1282 void multi_do_frame()
1283 {       
1284         PSNET_TOP_LAYER_PROCESS();
1285
1286         // always set the local player eye position/orientation here so we know its valid throughout all multiplayer
1287         // function calls
1288         if((Net_player != NULL) && eye_tog){
1289                 player_get_eye(&Net_player->s_info.eye_pos, &Net_player->s_info.eye_orient);
1290         }
1291
1292         // send all buffered packets from the previous frame
1293         multi_io_send_buffered_packets();
1294
1295         // datarate tracking
1296         multi_rate_process();
1297
1298         // always process any pending endgame details
1299         multi_endgame_process();                
1300
1301         // process all reliable socket details, including :
1302         // 1.) Listening for new pending reliable connections (server)
1303         // 2.) Checking for broken sockets (server/client)
1304         // 3.) Checking for clients who haven't fully connected
1305         multi_process_reliable_details();       
1306
1307         // get the other net players data
1308         multi_process_incoming();               
1309
1310         // process object update datarate stuff (for clients and server both)
1311         multi_oo_rate_process();
1312
1313         // clients should check when last time they heard from sever was -- if too long, then
1314         // pause the simulation so wait for it to possibly come back
1315         if ( (MULTIPLAYER_CLIENT) && (Net_player->flags & NETINFO_FLAG_CONNECTED) ){
1316                 multi_client_check_server();
1317         }
1318
1319         // everybody pings all the time 
1320         if((Next_ping_time < 0) || ((time(NULL) - Next_ping_time) > PING_SEND_TIME) ){
1321                 if( (Net_player->flags & NETINFO_FLAG_AM_MASTER) ){
1322                         send_netplayer_update_packet();
1323                 }
1324                 
1325                 // ping everyone
1326                 multi_ping_send_all();
1327                 Next_ping_time = time(NULL);            
1328         }       
1329         
1330         // if I am the master, and we are not yet actually playing the mission, send off netgame
1331         // status to all other players in the game.  If I am not the master of the game, and we
1332         // are not in the game, then send out my netplayer status to the host
1333         if ( (Net_player->flags & NETINFO_FLAG_CONNECTED) && !(Game_mode & GM_IN_MISSION)){     
1334                 if ( Net_player->flags & NETINFO_FLAG_AM_MASTER ) {                     
1335                         if ( (Netgame_send_time < 0) || ((time(NULL) - Netgame_send_time) > NETGAME_SEND_TIME) ) {
1336                                 send_netgame_update_packet();                           
1337                                 
1338                                 Netgame_send_time = time(NULL);
1339                         }               
1340                 } else {
1341                         if ( (State_send_time < 0) || ((time(NULL) - State_send_time) > STATE_SEND_TIME) ){
1342                                 // observers shouldn't send an update state packet
1343                                 if ( !(Net_player->flags & NETINFO_FLAG_OBSERVER) ){
1344                                         send_netplayer_update_packet();
1345                                 }                               
1346                                 
1347                                 State_send_time = time(NULL);
1348                         }
1349                 }
1350         }
1351         else if ( (Net_player->flags & NETINFO_FLAG_CONNECTED) && (Game_mode & GM_IN_MISSION) ) {       
1352                 // if I am connected and am in the mission, do things that need to be done on a regular basis
1353                 if ( Net_player->flags & NETINFO_FLAG_AM_MASTER ) {
1354                         if ( (Gameinfo_send_time < 0) || ((time(NULL) - Gameinfo_send_time) > GAMEINFO_SEND_TIME)){
1355                                 send_game_info_packet();
1356                                 
1357                                 Gameinfo_send_time = time(NULL);
1358                         }
1359                         
1360                         // for any potential respawns
1361                         multi_respawn_handle_invul_players();
1362                         multi_respawn_check_ai();
1363
1364                         // for any potential ingame joiners
1365                         multi_handle_ingame_joiners();
1366                 } else {
1367                         // the clients need to do some processing of stuff as well                      
1368                 }
1369         }
1370
1371         // check to see if we're waiting on confirmation for a restricted ingame join
1372         if(Multi_restr_query_timestamp != -1){
1373                 // if it has elapsed, unset the ingame join flag
1374                 if(timestamp_elapsed(Multi_restr_query_timestamp)){
1375                         Multi_restr_query_timestamp = -1;
1376                         Netgame.flags &= ~(NG_FLAG_INGAME_JOINING);             
1377                 }       
1378         }
1379
1380         // while in the mission, send my PlayerControls to the host so that he can process
1381         // my movement
1382         if ( Game_mode & GM_IN_MISSION ) {
1383                 // tickers
1384                 extern void oo_update_time();
1385                 oo_update_time();
1386
1387
1388                 if ( !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){                                    
1389                         if(Net_player->flags & NETINFO_FLAG_OBSERVER){
1390                                 // if the rate limiting system says its ok
1391                                 if(multi_oo_cirate_can_send()){
1392                                         // send my observer position/object update
1393                                         send_observer_update_packet();
1394                                 }
1395                         } else if ( !(Player_ship->flags & SF_DEPARTING ) ){                            
1396                                 // if the rate limiting system says its ok
1397                                 if(multi_oo_cirate_can_send()){
1398                                         // use the new method
1399                                         multi_oo_send_control_info();
1400                                 }                               
1401                         }
1402
1403                         // bytes received info
1404                         if( (Next_bytes_time < 0) || ((time(NULL) - Next_bytes_time) > BYTES_SENT_TIME) ){
1405                                 if(Net_player != NULL){
1406                                         send_bytes_recvd_packet(Net_player);
1407
1408                                         // reset bytes recvd
1409                                         Net_player->cl_bytes_recvd = 0;
1410                                 }
1411
1412                                 // reset timestamp
1413                                 Next_bytes_time = time(NULL);                           
1414                         }
1415                 } else {                        
1416                         // sending new objects from here is dependent on having objects only created after
1417                         // the game is done moving the objects.  I think that I can enforce this.                               
1418                         multi_oo_process();                     
1419
1420                         // evaluate whether the time limit has been reached or max kills has been reached
1421                         // Commented out by Sandeep 4/12/98, was causing problems with testing.
1422                         if( ((f2fl(Netgame.options.mission_time_limit) > 0.0f) && (Missiontime > Netgame.options.mission_time_limit)) ||
1423                                  multi_kill_limit_reached() ) {
1424
1425                                 // make sure we don't do this more than once
1426                                 if(Netgame.game_state == NETGAME_STATE_IN_MISSION){                             
1427                                         multi_handle_end_mission_request();                                                                     
1428                                 }
1429                         }                       
1430                 }                       
1431         }
1432
1433         // periodically send a client update packet to all clients
1434         if((Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
1435                 int idx;
1436                 for(idx=0;idx<MAX_PLAYERS;idx++){
1437                         if(MULTI_CONNECTED(Net_players[idx]) && (Net_player != &Net_players[idx])){
1438                                 if((Multi_client_update_times[idx] < 0) || timestamp_elapsed_safe(Multi_client_update_times[idx], 1000)){
1439                                         
1440                                         send_client_update_packet(&Net_players[idx]);
1441                                         
1442                                         Multi_client_update_times[idx] = timestamp(MULTI_CLIENT_UPDATE_TIME);
1443                                 }
1444                         }
1445                 }
1446         }       
1447
1448         // process any kicked player details
1449         multi_kick_process();
1450
1451         // do any file xfer details
1452         multi_xfer_do();
1453
1454         // process any player data details (wav files, pilot pics, etc)
1455         multi_data_do();
1456
1457         // do any voice details
1458         multi_voice_process();
1459
1460         // process any player messaging details
1461         multi_msg_process();            
1462         
1463         // if on the standalone, do any gui stuff
1464         if(Game_mode & GM_STANDALONE_SERVER){
1465                 std_do_gui_frame();
1466         }       
1467
1468         // dogfight nonstandalone players should recalc the escort list every frame
1469         if(!(Game_mode & GM_STANDALONE_SERVER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT) && MULTI_IN_MISSION){
1470                 hud_setup_escort_list(0);
1471         }
1472 }
1473
1474 // -------------------------------------------------------------------------------------------------
1475 //      multi_pause_do_frame() is called once per game loop do update all the multiplayer objects, and send
1476 // the player data to all the other net players when the multiplayer game is paused. It only will do 
1477 // checking for a few specialized packets (MULTI_UNPAUSE, etc)
1478 //
1479
1480 void multi_pause_do_frame()
1481 {
1482         PSNET_TOP_LAYER_PROCESS();
1483
1484         // always set the local player eye position/orientation here so we know its valid throughout all multiplayer
1485         // function calls
1486         // if((Net_player != NULL) && eye_tog){
1487                 // player_get_eye(&Net_player->s_info.eye_pos, &Net_player->s_info.eye_orient);
1488         // }
1489
1490         // send all buffered packets from the previous frame
1491         multi_io_send_buffered_packets();
1492
1493         // always process any pending endgame details
1494         multi_endgame_process();                
1495
1496         // process all reliable socket details, including :
1497         // 1.) Listening for new pending reliable connections (server)
1498         // 2.) Checking for broken sockets (server/client)
1499         // 3.) Checking for clients who haven't fully connected
1500         multi_process_reliable_details();       
1501
1502         // these timestamps and handlers shoul be evaluated in the pause state
1503         if ( Net_player->flags & NETINFO_FLAG_AM_MASTER ) {
1504                 if ( (Gameinfo_send_time < 0) || ((time(NULL) - Gameinfo_send_time) > GAMEINFO_SEND_TIME) ){
1505                         send_game_info_packet();
1506                         
1507                         Gameinfo_send_time = time(NULL);
1508                 }                               
1509         }
1510
1511         // everybody pings all the time
1512         if((Next_ping_time < 0) || ((time(NULL) - Next_ping_time) > PING_SEND_TIME) ){
1513                 multi_ping_send_all();
1514                 
1515                 Next_ping_time = time(NULL);
1516         }
1517
1518         // periodically send a client update packet to all clients
1519         if(Net_player->flags & NETINFO_FLAG_AM_MASTER){
1520                 int idx;
1521
1522                 for(idx=0;idx<MAX_PLAYERS;idx++){
1523                         if(MULTI_CONNECTED(Net_players[idx]) && (Net_player != &Net_players[idx])){                     
1524                                 if((Multi_client_update_times[idx] < 0) || timestamp_elapsed_safe(Multi_client_update_times[idx], 1000)){
1525                                         
1526                                         send_client_update_packet(&Net_players[idx]);
1527                                         
1528                                         Multi_client_update_times[idx] = timestamp(MULTI_CLIENT_UPDATE_TIME);
1529                                 }
1530                         }                               
1531                 }
1532
1533                 // for any potential ingame joiners
1534                 multi_handle_ingame_joiners();
1535         }       
1536
1537         // do any file xfer details
1538         multi_xfer_do();
1539
1540         // process any player data details (wav files, pilot pics, etc)
1541         multi_data_do();
1542
1543         // get the other net players data
1544         multi_process_incoming();       
1545
1546         // do any voice details
1547         multi_voice_process();
1548
1549         // process any player messaging details
1550         multi_msg_process();
1551
1552         // process any kicked player details
1553         multi_kick_process();
1554
1555         // process any pending endgame details
1556         multi_endgame_process();
1557
1558         // process object update stuff (for clients and server both)
1559         if(MULTIPLAYER_MASTER){
1560                 multi_oo_process();
1561         }
1562
1563         // if on the standalone, do any gui stuff
1564         if(Game_mode & GM_STANDALONE_SERVER){
1565                 std_do_gui_frame();
1566         }
1567 }
1568
1569
1570 // --------------------------------------------------------------------------------
1571 // standalone_main_init()  the standalone equivalent of the main menu
1572 //
1573
1574 extern int sock_inited;
1575 float frame_time = (float)1.0/(float)30.0;
1576
1577 void standalone_main_init()
1578 {
1579    std_debug_set_standalone_state_string("Main Init");   
1580
1581         Game_mode = (GM_STANDALONE_SERVER | GM_MULTIPLAYER);    
1582
1583         // NETLOG
1584         ml_string(NOX("Standalone server initializing"));
1585
1586         // read in config file
1587         // multi_options_read_config();   
1588
1589         // if we failed to startup on our desired protocol, fail        
1590         if((Multi_options_g.protocol == NET_IPX) && !Ipx_active){                                               
1591 #ifndef PLAT_UNIX
1592                 MessageBox((HWND)os_get_window(), XSTR( "You have selected IPX for multiplayer Freespace, but the IPX protocol was not detected on your machine.", 1402), "Error", MB_OK);
1593 #else
1594                 fprintf (stderr, "ERROR: You have selected IPX for multiplayer Freespace, but the IPX protocol was not detected on your machine.\n");
1595 #endif
1596                 exit(1);
1597         } 
1598         if((Multi_options_g.protocol == NET_TCP) && !Tcp_active){               
1599 #ifndef PLAT_UNIX
1600                 MessageBox((HWND)os_get_window(), XSTR("You have selected TCP/IP for multiplayer Freespace, but the TCP/IP protocol was not detected on your machine.", 362), "Error", MB_OK);
1601 #else
1602                 fprintf (stderr, "ERROR: You have selected TCP/IP for multiplayer Freespace, but the TCP/IP protocol was not detected on your machine.\n");
1603 #endif
1604                 exit(1);
1605         }
1606         
1607         // set the protocol
1608 #ifdef MULTIPLAYER_BETA_BUILD
1609         Multi_options_g.protocol = NET_TCP;
1610         psnet_use_protocol(Multi_options_g.protocol);   
1611
1612         ADDRESS_LENGTH = IP_ADDRESS_LENGTH;             
1613         PORT_LENGTH = IP_PORT_LENGTH;                   
1614 #else
1615         psnet_use_protocol(Multi_options_g.protocol);
1616         switch (Multi_options_g.protocol) {
1617         case NET_IPX:
1618                 ADDRESS_LENGTH = IPX_ADDRESS_LENGTH;
1619                 PORT_LENGTH = IPX_PORT_LENGTH;
1620                 break;
1621
1622         case NET_TCP:
1623                 ADDRESS_LENGTH = IP_ADDRESS_LENGTH;             
1624                 PORT_LENGTH = IP_PORT_LENGTH;                   
1625                 break;
1626
1627         default:
1628                 Int3();
1629         } // end switch
1630 #endif
1631
1632         HEADER_LENGTH = 1;              
1633         
1634         // clear out the Netgame structure and start filling in the values
1635         // NOTE : these values are not incredibly important since they will be overwritten by the host when he joins
1636         memset( &Netgame, 0, sizeof(Netgame) ); 
1637         Netgame.game_state = NETGAME_STATE_FORMING;             // game is currently starting up
1638         Netgame.security = 0;
1639         Netgame.server_addr = Psnet_my_addr;
1640
1641         memset(&The_mission,0,sizeof(The_mission));
1642                 
1643         // reinitialize all systems     
1644         multi_level_init();     
1645
1646         // intialize endgame stuff
1647         multi_endgame_init();
1648
1649         // clear the file xfer system
1650         multi_xfer_reset();
1651         multi_xfer_force_dir(CF_TYPE_MULTI_CACHE);
1652
1653         // reset timer
1654         timestamp_reset();
1655
1656         // setup the netplayer for the standalone
1657         Net_player = &Net_players[0];   
1658         Net_player->tracker_player_id = -1;
1659         Net_player->flags |= (NETINFO_FLAG_AM_MASTER | NETINFO_FLAG_CONNECTED | NETINFO_FLAG_DO_NETWORKING | NETINFO_FLAG_MISSION_OK);
1660         Net_player->state = NETPLAYER_STATE_WAITING;
1661         Net_player->player = Player;
1662         strcpy(Player->callsign, "server");
1663         Net_player->p_info.addr = Psnet_my_addr;
1664         Net_player->s_info.xfer_handle = -1;    
1665         Net_player->player_id = multi_get_new_id();     
1666         Netgame.server = Net_player; 
1667
1668         // maybe flag the game as having a hacked ships.tbl
1669         if(!Game_ships_tbl_valid){
1670                 Netgame.flags |= NG_FLAG_HACKED_SHIPS_TBL;
1671         }
1672         // maybe flag the game as having a hacked weapons.tbl
1673         if(!Game_weapons_tbl_valid){
1674                 Netgame.flags |= NG_FLAG_HACKED_WEAPONS_TBL;
1675         }
1676
1677         // hacked data
1678         if(game_hacked_data()){
1679                 Net_player->flags |= NETINFO_FLAG_HAXOR;
1680         }
1681
1682         // setup debug flags
1683         Netgame.debug_flags = 0;
1684         /*
1685         if(!Cmdline_server_firing){
1686                 Netgame.debug_flags |= NETD_FLAG_CLIENT_FIRING;
1687         }
1688         if(!Cmdline_client_dodamage){
1689                 Netgame.debug_flags |= NETD_FLAG_CLIENT_NODAMAGE;
1690         }
1691         */
1692
1693         // setup the default game name for the standalone
1694         std_connect_set_gamename(NULL);
1695
1696         // set netgame default options
1697         multi_options_set_netgame_defaults(&Netgame.options);
1698
1699         // set local netplayer default options
1700         multi_options_set_local_defaults(&Net_player->p_info.options);
1701
1702         // set our object update level from the standalone default      
1703         Net_player->p_info.options.obj_update_level = Multi_options_g.std_datarate;
1704         switch(Net_player->p_info.options.obj_update_level){
1705         case OBJ_UPDATE_LOW:
1706                 nprintf(("Network","STANDALONE USING LOW UPDATES\n"));
1707                 break;
1708         case OBJ_UPDATE_MEDIUM:
1709                 nprintf(("Network","STANDALONE USING MEDIUM UPDATES\n"));
1710                 break;
1711         case OBJ_UPDATE_HIGH:
1712                 nprintf(("Network","STANDALONE USING HIGH UPDATE\n"));
1713                 break;
1714         case OBJ_UPDATE_LAN:
1715                 nprintf(("Network","STANDALONE USING LAN UPDATE\n"));
1716                 break;
1717         }
1718         
1719         // clear out various things
1720         psnet_flush();
1721         game_flush();
1722         ship_init();
1723
1724         std_debug_set_standalone_state_string("Main Do");
1725         std_set_standalone_fps((float)0);
1726         std_multi_set_standalone_missiontime((float)0);
1727
1728         // load my missions and campaigns
1729         multi_create_list_load_missions();
1730         multi_create_list_load_campaigns();
1731
1732         // if this is a tracker game, validate missions
1733         if(MULTI_IS_TRACKER_GAME){
1734                 multi_update_valid_missions();
1735         }
1736 }
1737
1738
1739 // --------------------------------------------------------------------------------
1740 // standalone_main_do()
1741 //
1742
1743 // DESCRIPTION : the standalone server will wait in this state until the host of the game 
1744 //               is "Waiting". That is, his state==NETPLAYER_STATE_WAITING, and he has finished
1745 //               doing everything and wants to play the game. Once this happens, we will jump
1746 //               into GS_STATE_MULTI_SERVER_WAIT
1747
1748 void standalone_main_do()
1749 {
1750    Sleep(10);  // since nothing will really be going on here, we can afford to give some time
1751                // back to the operating system.
1752
1753         // kind of a do-nothing spin state.
1754         // The standalone will eventually move into the GS_STATE_MULTI_MISSION_SYNC state when a host connects and
1755         // attempts to start a game
1756 }
1757
1758 // --------------------------------------------------------------------------------
1759 // standalone_main_close()
1760 //
1761
1762 void standalone_main_close()
1763 {
1764    std_debug_set_standalone_state_string("Main Close"); 
1765 }
1766
1767 void multi_standalone_reset_all()
1768 {       
1769         int idx;
1770
1771         // NETLOG
1772         ml_string(NOX("Standalone resetting"));
1773         
1774         // shut all game stuff down
1775         game_level_close();
1776
1777         // reinitialize the gui
1778         std_reset_standalone_gui();     
1779
1780         // close down all sockets
1781         for(idx=0;idx<MAX_PLAYERS;idx++){
1782
1783                 // 6/25/98 -- MWA -- call delete_player here to remove the player.  This closes down the socket
1784                 // and marks the player as not connected anymore.  It is probably cleaner to do this.
1785                 if ( &Net_players[idx] != Net_player ) {
1786                         delete_player( idx );
1787                 }               
1788         }
1789                 
1790         // make sure we go to the proper state. 
1791         if(gameseq_get_state() == GS_STATE_STANDALONE_MAIN){
1792                 standalone_main_init();
1793         }
1794         gameseq_post_event(GS_EVENT_STANDALONE_MAIN);   
1795 }
1796
1797 // --------------------------------------------------------------------------------
1798 // multi_server_wait_init()  do stuff like setting the status bits correctly
1799 //
1800
1801 void multi_standalone_wait_init()
1802 {       
1803         std_debug_set_standalone_state_string("Wait Do");
1804         std_multi_add_goals();   // fill in the goals for the mission into the tree view
1805         multi_reset_timestamps();
1806
1807         // create the bogus standalone object
1808         multi_create_standalone_object();
1809 }
1810
1811
1812 // --------------------------------------------------------------------------------
1813 // multi_server_wait_do_frame() wait for everyone to log in or the host to send commands
1814 // 
1815
1816 // DESCRIPTION : we will be in this state once the host of the game is waiting for everyone
1817 //               to be finished and ready to go, at which point, we will will tell everyone
1818 //               to enter the game, and we will start simulating ourselves. Note that most of
1819 //               this code is lifted from multi_wait_do_frame()
1820 void multi_standalone_wait_do()
1821 {
1822 }
1823
1824 // --------------------------------------------------------------------------------
1825 // multi_server_wait_close() cleanup
1826 //
1827
1828 void multi_standalone_wait_close()
1829 {
1830         std_debug_set_standalone_state_string("Wait Close / Game Play");
1831         
1832         // all players should reset sequencing
1833         int idx;
1834         for(idx=0;idx<MAX_PLAYERS;idx++){
1835                 if(Net_player->flags & NETINFO_FLAG_CONNECTED){
1836                         Net_players[idx].client_cinfo_seq = 0;
1837                         Net_players[idx].client_server_seq = 0; 
1838                 }
1839         }
1840 }
1841
1842
1843 // this is an artificial state which will push the standalone into the main state without it having to go through 
1844 // the init function (which would disconnect everyone and generally just screw things up)
1845 // it will also eventually do tracker stats update
1846 extern int Multi_debrief_server_framecount;
1847 void multi_standalone_postgame_init()   
1848 {
1849         std_debug_set_standalone_state_string("Postgame / Send Stats");
1850
1851         // NETLOG
1852         ml_string(NOX("Standlone entering postgame"));
1853
1854         mission_goal_fail_incomplete();
1855
1856         // handle campaign stuff
1857         if ( Game_mode & GM_CAMPAIGN_MODE ) {
1858                 // MUST store goals and events first - may be used to evaluate next mission
1859                 // store goals and events
1860                 mission_campaign_store_goals_and_events();
1861
1862                 // evaluate next mission
1863                 mission_campaign_eval_next_mission();
1864         }       
1865
1866         // always set my state to be "DEBRIEF_ACCEPT"
1867         Net_player->state = NETPLAYER_STATE_DEBRIEF_ACCEPT;     
1868
1869         // mark stats as not being store yet
1870         Netgame.flags &= ~(NG_FLAG_STORED_MT_STATS);
1871
1872         Multi_debrief_server_framecount = 0;
1873
1874         // reset network timestamps
1875         multi_reset_timestamps();
1876 }
1877
1878 void multi_standalone_postgame_do()
1879 {
1880         // wait until everyone is in the debriefing
1881         if((Netgame.game_state != NETGAME_STATE_DEBRIEF) && multi_netplayer_state_check(NETPLAYER_STATE_DEBRIEF, 1)){           
1882                 Netgame.game_state = NETGAME_STATE_DEBRIEF;
1883                 send_netgame_update_packet();
1884                 debrief_multi_server_stuff();
1885         }
1886         
1887         // process server debriefing details
1888         if(Netgame.game_state == NETGAME_STATE_DEBRIEF){
1889                 multi_debrief_server_process();
1890         }
1891 }
1892
1893 void multi_standalone_postgame_close()
1894 {
1895 }
1896
1897 void multi_reset_timestamps()
1898 {
1899         int i;
1900
1901         for ( i = 0 ; i < MAX_PLAYERS; i++ ){
1902                 Multi_client_update_times[i] = -1;
1903         }
1904         Netgame_send_time = -1;
1905         Gameinfo_send_time = -1;        
1906         Next_ping_time = -1;
1907         State_send_time = -1;
1908         Next_bytes_time = -1;
1909
1910         chatbox_reset_timestamps();
1911
1912         // do for all players so that ingame joiners work properly.
1913         for (i = 0; i < MAX_PLAYERS; i++ ) {
1914                 Players[i].update_dumbfire_time = timestamp(0);
1915                 Players[i].update_lock_time = timestamp(0);
1916
1917                 Net_players[i].s_info.voice_token_timestamp = -1;
1918         }
1919
1920         // reset standalone gui timestamps (these are not game critical, so there is not much danger)
1921         std_reset_timestamps();
1922
1923         // initialize all object update timestamps
1924         multi_oo_gameplay_init();
1925 }
1926
1927 // netgame debug flags for debug console stuff
1928 DCF(netd, "change/list netgame debug flags")
1929 {
1930         dc_get_arg(ARG_INT);
1931         
1932         // if we got an integer, and we're the server, change flags
1933         if((Dc_arg_type & ARG_INT) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Dc_arg_int <= 7)){
1934                 Netgame.debug_flags ^= (1<<Dc_arg_int);
1935         }
1936
1937         // display network flags
1938         dc_printf("BITS\n");
1939         // dc_printf("1 - Client side firing (%d)\n", Netgame.debug_flags & NETD_FLAG_CLIENT_FIRING ? 1 : 0);
1940         // dc_printf("2 - Client nodamage (%d)\n", Netgame.debug_flags & NETD_FLAG_CLIENT_NODAMAGE ? 1 : 0);
1941 }
1942
1943 // display any multiplayer/networking information here
1944 void multi_display_netinfo()
1945 {
1946         int sx = gr_screen.max_w - 200;
1947         int sy = 20;
1948         int idx;
1949
1950         // not multiplayer
1951         if(!(Game_mode & GM_MULTIPLAYER)){
1952                 return;
1953         }
1954
1955         gr_set_color_fast(&Color_normal);
1956
1957         // server or client
1958         if(MULTIPLAYER_MASTER){
1959                 gr_string(sx, sy, "SERVER"); sy += 10;
1960
1961                 for(idx=0; idx<MAX_PLAYERS; idx++){
1962                         if(MULTI_CONNECTED(Net_players[idx]) && (Net_player != &Net_players[idx]) && (Net_players[idx].player != NULL)){
1963                                 if(Net_players[idx].sv_last_pl < 0){
1964                                         gr_printf(sx, sy, "%s : %d, %d pl", Net_players[idx].player->callsign, Net_players[idx].sv_bytes_sent, 0); sy += 10;
1965                                 } else {
1966                                         gr_printf(sx, sy, "%s : %d, %d pl", Net_players[idx].player->callsign, Net_players[idx].sv_bytes_sent, Net_players[idx].sv_last_pl); sy += 10;
1967                                 }
1968                         }
1969                 }
1970         } else {
1971                 gr_string(sx, sy, "CLIENT"); sy += 10;
1972
1973                 // display PL
1974                 if(Net_player != NULL){
1975                         if(Net_player->cl_last_pl < 0){
1976                                 gr_printf(sx, sy, "PL : %d %d pl\n", Net_player->cl_bytes_recvd, 0); sy += 10;
1977                         } else {
1978                                 gr_printf(sx, sy, "PL : %d %d pl\n", Net_player->cl_bytes_recvd, Net_player->cl_last_pl); sy += 10;
1979                         }
1980                 }
1981         }
1982 }