2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/Network/multi_options.cpp $
16 * Revision 1.6 2005/10/02 09:30:10 taylor
17 * sync up rest of big-endian network changes. it should at least be as good as what's in FS2_Open now, only better :)
19 * Revision 1.5 2004/06/11 01:34:41 tigital
20 * byte-swapping changes for bigendian systems
22 * Revision 1.4 2003/05/25 02:30:43 taylor
25 * Revision 1.3 2002/06/09 04:41:23 relnev
26 * added copyright header
28 * Revision 1.2 2002/05/26 20:22:48 theoddone33
29 * Most of network/ works
31 * Revision 1.1.1.1 2002/05/03 03:28:10 root
35 * 22 8/27/99 12:32a Dave
36 * Allow the user to specify a local port through the launcher.
38 * 21 8/22/99 1:19p Dave
39 * Fixed up http proxy code. Cleaned up scoring code. Reverse the order in
40 * which d3d cards are detected.
42 * 20 8/04/99 6:01p Dave
43 * Oops. Make sure standalones log in.
45 * 19 7/09/99 9:51a Dave
46 * Added thick polyline code.
48 * 18 5/03/99 8:32p Dave
49 * New version of multi host options screen.
51 * 17 4/25/99 7:43p Dave
52 * Misc small bug fixes. Made sun draw properly.
54 * 16 4/20/99 6:39p Dave
55 * Almost done with artillery targeting. Added support for downloading
56 * images on the PXO screen.
58 * 15 3/10/99 6:50p Dave
59 * Changed the way we buffer packets for all clients. Optimized turret
60 * fired packets. Did some weapon firing optimizations.
62 * 14 3/09/99 6:24p Dave
63 * More work on object update revamping. Identified several sources of
64 * unnecessary bandwidth.
66 * 13 3/08/99 7:03p Dave
67 * First run of new object update system. Looks very promising.
69 * 12 2/21/99 6:01p Dave
70 * Fixed standalone WSS packets.
72 * 11 2/19/99 2:55p Dave
73 * Temporary checking to report the winner of a squad war match.
75 * 10 2/12/99 6:16p Dave
76 * Pre-mission Squad War code is 95% done.
78 * 9 2/11/99 3:08p Dave
79 * PXO refresh button. Very preliminary squad war support.
81 * 8 11/20/98 11:16a Dave
82 * Fixed up IPX support a bit. Making sure that switching modes and
83 * loading/saving pilot files maintains proper state.
85 * 7 11/19/98 4:19p Dave
86 * Put IPX sockets back in psnet. Consolidated all multiplayer config
89 * 6 11/19/98 8:03a Dave
90 * Full support for D3-style reliable sockets. Revamped packet lag/loss
91 * system, made it receiver side and at the lowest possible level.
93 * 5 11/17/98 11:12a Dave
94 * Removed player identification by address. Now assign explicit id #'s.
96 * 4 10/13/98 9:29a Dave
97 * Started neatening up freespace.h. Many variables renamed and
98 * reorganized. Added AlphaColors.[h,cpp]
100 * 3 10/07/98 6:27p Dave
101 * Globalized mission and campaign file extensions. Removed Silent Threat
102 * special code. Moved \cache \players and \multidata into the \data
105 * 2 10/07/98 10:53a Dave
108 * 1 10/07/98 10:50a Dave
110 * 20 9/10/98 1:17p Dave
111 * Put in code to flag missions and campaigns as being MD or not in Fred
112 * and Freespace. Put in multiplayer support for filtering out MD
113 * missions. Put in multiplayer popups for warning of non-valid missions.
115 * 19 7/07/98 2:49p Dave
118 * 18 6/04/98 11:04a Allender
119 * object update level stuff. Don't reset to high when becoming an
120 * observer of any type. default to low when guy is a dialup customer
122 * 17 5/24/98 3:45a Dave
123 * Minor object update fixes. Justify channel information on PXO. Add a
124 * bunch of configuration stuff for the standalone.
126 * 16 5/19/98 1:35a Dave
127 * Tweaked pxo interface. Added rankings url to pxo.cfg. Make netplayer
128 * local options update dynamically in netgames.
130 * 15 5/08/98 5:05p Dave
131 * Go to the join game screen when quitting multiplayer. Fixed mission
132 * text chat bugs. Put mission type symbols on the create game list.
133 * Started updating standalone gui controls.
135 * 14 5/06/98 12:36p Dave
136 * Make sure clients can leave the debrief screen easily at all times. Fix
137 * respawn count problem.
139 * 13 5/03/98 7:04p Dave
140 * Make team vs. team work mores smoothly with standalone. Change how host
141 * interacts with standalone for picking missions. Put in a time limit for
142 * ingame join ship select. Fix ingame join ship select screen for Vasudan
145 * 12 5/03/98 2:52p Dave
146 * Removed multiplayer furball mode.
148 * 11 4/23/98 6:18p Dave
149 * Store ETS values between respawns. Put kick feature in the text
150 * messaging system. Fixed text messaging system so that it doesn't
151 * process or trigger ship controls. Other UI fixes.
153 * 10 4/22/98 5:53p Dave
154 * Large reworking of endgame sequencing. Updated multi host options
155 * screen for new artwork. Put in checks for host or team captains leaving
158 * 9 4/16/98 11:39p Dave
159 * Put in first run of new multiplayer options screen. Still need to
160 * complete final tab.
162 * 8 4/13/98 4:50p Dave
163 * Maintain status of weapon bank/links through respawns. Put # players on
164 * create game mission list. Make observer not have engine sounds. Make
165 * oberver pivot point correct. Fixed respawn value getting reset every
166 * time host options screen started.
168 * 7 4/09/98 11:01p Dave
169 * Put in new multi host options screen. Tweaked multiplayer options a
172 * 6 4/09/98 5:43p Dave
173 * Remove all command line processing from the demo. Began work fixing up
174 * the new multi host options screen.
176 * 5 4/06/98 6:37p Dave
177 * Put in max_observers netgame server option. Make sure host is always
178 * defaulted to alpha 1 or zeta 1. Changed create game so that MAX_PLAYERS
179 * can always join but need to be kicked before commit can happen. Put in
180 * support for server ending a game and notifying clients of a special
183 * 4 4/04/98 4:22p Dave
184 * First rev of UDP reliable sockets is done. Seems to work well if not
187 * 3 4/03/98 1:03a Dave
188 * First pass at unreliable guaranteed delivery packets.
190 * 2 3/31/98 4:51p Dave
191 * Removed medals screen and multiplayer buttons from demo version. Put in
192 * new pilot popup screen. Make ships in mp team vs. team have proper team
193 * ids. Make mp respawns a permanent option saved in the player file.
195 * 1 3/30/98 6:24p Dave
202 #include "osregistry.h"
204 #include "multimsgs.h"
205 #include "freespace.h"
206 #include "stand_server.h"
207 #include "multiutil.h"
208 #include "multi_voice.h"
209 #include "multi_options.h"
210 #include "multi_team.h"
211 #include "multi_fstracker.h"
212 #include "multi_pxo.h"
215 // ----------------------------------------------------------------------------------
216 // MULTI OPTIONS DEFINES/VARS
220 #define MULTI_OPTION_SERVER 0 // server update follows
221 #define MULTI_OPTION_LOCAL 1 // local netplayer options follow
222 #define MULTI_OPTION_START_GAME 2 // host's start game options on the standalone server
223 #define MULTI_OPTION_MISSION 3 // host's mission selection stuff on a standalone server
226 #define MULTI_CFG_FILE NOX("multi.cfg")
227 multi_global_options Multi_options_g;
229 char Multi_options_proxy[512] = "";
230 ushort Multi_options_proxy_port = 0;
232 // ----------------------------------------------------------------------------------
233 // MULTI OPTIONS FUNCTIONS
237 void multi_options_read_config_fs1();
240 // load in the config file
241 #define NEXT_TOKEN() do { tok = strtok(NULL, "\n"); if(tok != NULL){ drop_leading_white_space(tok); drop_trailing_white_space(tok); } } while(0);
242 #define SETTING(s) ( !SDL_strcasecmp(tok, s) )
243 void multi_options_read_config()
245 // set default value for the global multi options
246 memset(&Multi_options_g, 0, sizeof(multi_global_options));
247 Multi_options_g.protocol = NET_TCP;
248 Multi_options_g.pxo = 0;
250 // do we have a forced port via commandline or registry?
251 ushort forced_port = (ushort)os_config_read_uint("Network", "ForcePort", 0);
252 Multi_options_g.port = (Cmdline_network_port >= 0) ? (ushort)Cmdline_network_port : forced_port == 0 ? (ushort)DEFAULT_GAME_PORT : forced_port;
254 Multi_options_g.log = (Cmdline_multi_log) ? 1 : 0;
255 Multi_options_g.datarate_cap = OO_HIGH_RATE_DEFAULT;
256 SDL_strlcpy(Multi_options_g.user_tracker_ip, MULTI_PXO_USER_TRACKER_IP, SDL_arraysize(Multi_options_g.user_tracker_ip));
257 SDL_strlcpy(Multi_options_g.game_tracker_ip, MULTI_PXO_GAME_TRACKER_IP, SDL_arraysize(Multi_options_g.game_tracker_ip));
258 SDL_strlcpy(Multi_options_g.pxo_ip, MULTI_PXO_CHAT_IP, SDL_arraysize(Multi_options_g.pxo_ip));
259 SDL_strlcpy(Multi_options_g.pxo_rank_url, MULTI_PXO_RANKINGS_URL, SDL_arraysize(Multi_options_g.pxo_rank_url));
260 SDL_strlcpy(Multi_options_g.pxo_create_url, MULTI_PXO_CREATE_URL, SDL_arraysize(Multi_options_g.pxo_create_url));
261 SDL_strlcpy(Multi_options_g.pxo_verify_url, MULTI_PXO_VERIFY_URL, SDL_arraysize(Multi_options_g.pxo_verify_url));
262 SDL_strlcpy(Multi_options_g.pxo_banner_url, MULTI_PXO_BANNER_URL, SDL_arraysize(Multi_options_g.pxo_banner_url));
265 Multi_options_g.std_max_players = -1;
266 Multi_options_g.std_datarate = OBJ_UPDATE_HIGH;
267 Multi_options_g.std_voice = 1;
268 memset(Multi_options_g.std_passwd, 0, STD_PASSWD_LEN);
269 memset(Multi_options_g.std_pname, 0, STD_NAME_LEN);
270 Multi_options_g.std_framecap = 60;
277 // read in the config file
278 in = cfopen(MULTI_CFG_FILE, "rt", CFILE_NORMAL, CF_TYPE_DATA);
280 // if we failed to open the config file, user default settings
282 nprintf(("Network","Failed to open network config file, using default settings\n"));
287 // read in the game info
291 // parse the first line
292 tok = strtok(str," \t");
296 drop_leading_white_space(tok);
297 drop_trailing_white_space(tok);
302 // all possible options
303 // only standalone cares about the following options
307 Multi_options_g.pxo = 1;
310 SDL_strlcpy(Multi_fs_tracker_channel, tok, SDL_arraysize(Multi_fs_tracker_channel));
313 if(SETTING("+name")){
314 // set the standalone server's permanent name
317 SDL_strlcpy(Multi_options_g.std_pname, tok, STD_NAME_LEN);
320 if(SETTING("+no_voice")){
321 // standalone won't allow voice transmission
322 Multi_options_g.std_voice = 0;
324 if(SETTING("+max_players")){
325 // set the max # of players on the standalone
328 if(!((atoi(tok) < 1) || (atoi(tok) > MAX_PLAYERS))){
329 Multi_options_g.std_max_players = atoi(tok);
340 if(SETTING("+passwd")){
341 // set the standalone host password
344 SDL_strlcpy(Multi_options_g.std_passwd, tok, STD_PASSWD_LEN);
347 if(SETTING("+low_update")){
348 // set standalone to low updates
349 Multi_options_g.std_datarate = OBJ_UPDATE_LOW;
351 if(SETTING("+med_update")){
352 // set standalone to medium updates
353 Multi_options_g.std_datarate = OBJ_UPDATE_MEDIUM;
355 if(SETTING("+high_update")){
356 // set standalone to high updates
357 Multi_options_g.std_datarate = OBJ_UPDATE_HIGH;
359 if(SETTING("+lan_update")){
360 // set standalone to high updates
361 Multi_options_g.std_datarate = OBJ_UPDATE_LAN;
369 // common to all modes
370 if(SETTING("+user_server")){
371 // ip addr of user tracker
374 SDL_strlcpy(Multi_options_g.user_tracker_ip, tok, SDL_arraysize(Multi_options_g.user_tracker_ip));
377 if(SETTING("+game_server")){
378 // ip addr of game tracker
381 SDL_strlcpy(Multi_options_g.game_tracker_ip, tok, SDL_arraysize(Multi_options_g.game_tracker_ip));
384 if(SETTING("+chat_server")){
385 // ip addr of pxo chat server
388 SDL_strlcpy(Multi_options_g.pxo_ip, tok, SDL_arraysize(Multi_options_g.pxo_ip));
391 if(SETTING("+rank_url")){
392 // url of pilot rankings page
395 SDL_strlcpy(Multi_options_g.pxo_rank_url, tok, SDL_arraysize(Multi_options_g.pxo_rank_url));
398 if(SETTING("+create_url")){
399 // url of pxo account create page
402 SDL_strlcpy(Multi_options_g.pxo_create_url, tok, SDL_arraysize(Multi_options_g.pxo_create_url));
405 if(SETTING("+verify_url")){
406 // url of pxo account verify page
409 SDL_strlcpy(Multi_options_g.pxo_verify_url, tok, SDL_arraysize(Multi_options_g.pxo_verify_url));
412 if(SETTING("+banner_url")){
413 // url of pxo account verify page
416 SDL_strlcpy(Multi_options_g.pxo_banner_url, tok, SDL_arraysize(Multi_options_g.pxo_banner_url));
419 if(SETTING("+datarate")){
420 // set the max datarate for high updates
423 if(atoi(tok) >= 4000){
424 Multi_options_g.datarate_cap = atoi(tok);
428 if(SETTING("+http_proxy")){
429 // get the proxy server
432 char *ip = strtok(tok, ":");
434 SDL_strlcpy(Multi_options_proxy, ip, SDL_arraysize(Multi_options_proxy));
436 ip = strtok(NULL, "");
438 Multi_options_proxy_port = (ushort)atoi(ip);
440 SDL_strlcpy(Multi_options_proxy, "", SDL_arraysize(Multi_options_proxy));
446 // close the config file
450 multi_options_read_config_fs1();
455 void multi_options_read_config_fs1()
462 // FS1 demo is single-player only, so don't bother with this
468 // read in the pxo config file
469 in = cfopen("pxo.cfg", "rt", CFILE_NORMAL, CF_TYPE_DATA);
472 // first line should be user tracker
473 if ( cfgets(str, 512, in) ) {
474 drop_leading_white_space(str);
475 drop_trailing_white_space(str);
477 SDL_strlcpy(Multi_options_g.user_tracker_ip, str, SDL_arraysize(Multi_options_g.user_tracker_ip));
480 // next line should be game tracker
481 if ( cfgets(str, 512, in) ) {
482 drop_leading_white_space(str);
483 drop_trailing_white_space(str);
485 SDL_strlcpy(Multi_options_g.game_tracker_ip, str, SDL_arraysize(Multi_options_g.game_tracker_ip));
488 // next, irc/chat server
489 if ( cfgets(str, 512, in) ) {
490 drop_leading_white_space(str);
491 drop_trailing_white_space(str);
493 SDL_strlcpy(Multi_options_g.pxo_ip, str, SDL_arraysize(Multi_options_g.pxo_ip));
496 // web link: rankings
497 if ( cfgets(str, 512, in) ) {
498 drop_leading_white_space(str);
499 drop_trailing_white_space(str);
501 SDL_strlcpy(Multi_options_g.pxo_rank_url, str, SDL_arraysize(Multi_options_g.pxo_rank_url));
504 // web link: register/create account
505 if ( cfgets(str, 512, in) ) {
506 drop_leading_white_space(str);
507 drop_trailing_white_space(str);
509 SDL_strlcpy(Multi_options_g.pxo_create_url, str, SDL_arraysize(Multi_options_g.pxo_create_url));
512 // web link: verify account/user
513 if ( cfgets(str, 512, in) ) {
514 drop_leading_white_space(str);
515 drop_trailing_white_space(str);
517 SDL_strlcpy(Multi_options_g.pxo_verify_url, str, SDL_arraysize(Multi_options_g.pxo_verify_url));
524 // maybe read standalone config
526 // read in the config file
527 in = cfopen("std.cfg", "rt", CFILE_NORMAL, CF_TYPE_DATA);
531 // read in the game info
535 // parse the first line
536 tok = strtok(str," \t");
540 drop_leading_white_space(tok);
541 drop_trailing_white_space(tok);
553 if(SETTING("+name")){
554 // set the standalone server's permanent name
557 SDL_strlcpy(Multi_options_g.std_pname, tok, STD_NAME_LEN);
560 if(SETTING("+no_voice")){
561 // standalone won't allow voice transmission
562 Multi_options_g.std_voice = 0;
564 if(SETTING("+max_players")){
565 // set the max # of players on the standalone
568 if(!((atoi(tok) < 1) || (atoi(tok) > MAX_PLAYERS))){
569 Multi_options_g.std_max_players = atoi(tok);
580 if(SETTING("+passwd")){
581 // set the standalone host password
584 SDL_strlcpy(Multi_options_g.std_passwd, tok, STD_PASSWD_LEN);
589 if(SETTING("+low_update")){
590 // set standalone to low updates
591 Multi_options_g.std_datarate = OBJ_UPDATE_LOW;
593 if(SETTING("+med_update")){
594 // set standalone to medium updates
595 Multi_options_g.std_datarate = OBJ_UPDATE_MEDIUM;
597 if(SETTING("+high_update")){
598 // set standalone to high updates
599 Multi_options_g.std_datarate = OBJ_UPDATE_HIGH;
601 if(SETTING("+lan_update")){
602 // set standalone to high updates
603 Multi_options_g.std_datarate = OBJ_UPDATE_LAN;
614 // set netgame defaults
615 // NOTE : should be used when creating a newpilot
616 void multi_options_set_netgame_defaults(multi_server_options *options)
618 // any player can do squadmate messaging
619 options->squad_set = MSO_SQUAD_ANY;
621 // only the host can end the game
622 options->endgame_set = MSO_END_HOST;
624 // allow ingame file xfer and custom pilot pix
625 options->flags = (MSO_FLAG_INGAME_XFER | MSO_FLAG_ACCEPT_PIX);
627 // set the default time limit to be -1 (no limit)
628 options->mission_time_limit = fl2f(-1.0f);
630 // set the default max kills for a mission
632 options->kill_limit = 99999;
634 options->kill_limit = 9999;
637 // set the default # of respawns
638 options->respawn = 2;
640 // set the default # of max observers
641 options->max_observers = 2;
643 // set the default netgame qos
644 options->voice_qos = 10;
646 // set the default token timeout
647 options->voice_token_wait = 2000; // he must wait 2 seconds between voice gets
649 // set the default max voice record time
650 options->voice_record_time = 5000;
653 // set local netplayer defaults
654 // NOTE : should be used when creating a newpilot
655 void multi_options_set_local_defaults(multi_local_options *options)
657 // accept pix by default and broadcast on the local subnet
658 options->flags = (MLO_FLAG_ACCEPT_PIX | MLO_FLAG_LOCAL_BROADCAST);
660 // set the object update level based on the type of network connection specified by the user
661 // at install (or launcher) time.
662 if ( Psnet_connection == NETWORK_CONNECTION_DIALUP ) {
663 options->obj_update_level = OBJ_UPDATE_LOW;
665 options->obj_update_level = OBJ_UPDATE_HIGH;
669 // fill in the passed netgame options struct with the data from my player file data (only host/server should do this)
670 void multi_options_netgame_load(multi_server_options *options)
673 memcpy(options,&Player->m_server_options,sizeof(multi_server_options));
677 // fill in the passed local options struct with the data from my player file data (all machines except standalone should do this)
678 void multi_options_local_load(multi_local_options *options, net_player *pxo_pl)
681 memcpy(options,&Player->m_local_options,sizeof(multi_local_options));
684 // stuff pxo squad info
687 SDL_strlcpy(pxo_pl->p_info.pxo_squad_name, Multi_tracker_squad_name, LOGIN_LEN);
692 // update everyone on the current netgame options
693 void multi_options_update_netgame()
695 ubyte data[MAX_PACKET_SIZE],code;
698 SDL_assert(Net_player->flags & NETINFO_FLAG_GAME_HOST);
700 // build the header and add the opcode
701 BUILD_HEADER(OPTIONS_UPDATE);
702 code = MULTI_OPTION_SERVER;
705 // add the netgame options
706 Netgame.options.flags = INTEL_INT( Netgame.options.flags );
707 Netgame.options.respawn = INTEL_INT( Netgame.options.respawn );
708 Netgame.options.voice_token_wait = INTEL_INT( Netgame.options.voice_token_wait );
709 Netgame.options.voice_record_time = INTEL_INT( Netgame.options.voice_record_time );
710 Netgame.options.kill_limit= INTEL_INT( Netgame.options.kill_limit );
711 Netgame.options.mission_time_limit = (fix)INTEL_INT( Netgame.options.mission_time_limit );
712 ADD_DATA(Netgame.options);
715 if(Net_player->flags & NETINFO_FLAG_AM_MASTER){
716 multi_io_send_to_all_reliable(data, packet_size);
718 // update tracker as well
719 if (Net_player->flags & NETINFO_FLAG_MT_CONNECTED) {
720 multi_fs_tracker_update_game(&Netgame);
723 multi_io_send_reliable(Net_player, data, packet_size);
727 // update everyone with my local settings
728 void multi_options_update_local()
730 ubyte data[MAX_PACKET_SIZE],code;
733 // if i'm the server, don't do anything
734 if(Net_player->flags & NETINFO_FLAG_AM_MASTER){
738 // build the header and add the opcode
739 BUILD_HEADER(OPTIONS_UPDATE);
740 code = MULTI_OPTION_LOCAL;
743 // add the netgame options
744 Net_player->p_info.options.flags = INTEL_INT( Net_player->p_info.options.flags );
745 Net_players->p_info.options.obj_update_level = INTEL_INT( Net_player->p_info.options.obj_update_level );
746 ADD_DATA(Net_player->p_info.options);
749 multi_io_send_reliable(Net_player, data, packet_size);
752 // update the standalone with the settings I have picked at the "start game" screen
753 void multi_options_update_start_game(netgame_info *ng)
755 ubyte data[MAX_PACKET_SIZE],code;
758 // should be a host on a standalone
759 SDL_assert((Net_player->flags & NETINFO_FLAG_GAME_HOST) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER));
762 BUILD_HEADER(OPTIONS_UPDATE);
763 code = MULTI_OPTION_START_GAME;
766 // add the start game options
767 ADD_STRING(ng->name);
769 ADD_INT(ng->security);
771 // add mode-specific data
773 case NG_MODE_PASSWORD:
774 ADD_STRING(ng->passwd);
776 case NG_MODE_RANK_ABOVE:
777 case NG_MODE_RANK_BELOW:
778 ADD_INT(ng->rank_base);
782 // send to the standalone server
783 multi_io_send_reliable(Net_player, data, packet_size);
786 // update the standalone with the mission settings I have picked (mission filename, etc)
787 void multi_options_update_mission(netgame_info *ng, int campaign_mode)
789 ubyte data[MAX_PACKET_SIZE],code;
792 // should be a host on a standalone
793 SDL_assert((Net_player->flags & NETINFO_FLAG_GAME_HOST) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER));
796 BUILD_HEADER(OPTIONS_UPDATE);
797 code = MULTI_OPTION_MISSION;
800 // type (coop or team vs. team)
801 ADD_INT(ng->type_flags);
804 ADD_UINT(ng->respawn);
806 // add the mission/campaign filename
807 code = (ubyte)campaign_mode;
810 ADD_STRING(ng->campaign_name);
812 ADD_STRING(ng->mission_name);
815 // send to the server
816 multi_io_send_reliable(Net_player, data, packet_size);
820 // ----------------------------------------------------------------------------------
821 // MULTI OPTIONS FUNCTIONS
824 // process an incoming multi options packet
825 void multi_options_process_packet(unsigned char *data, header *hinfo)
828 multi_local_options bogus;
829 int idx,player_index;
831 int offset = HEADER_LENGTH;
833 // find out who is sending this data
834 player_index = find_player_id(hinfo->id);
836 // get the packet code
839 // get the start game options
840 case MULTI_OPTION_START_GAME:
841 SDL_assert(Game_mode & GM_STANDALONE_SERVER);
843 // get the netgame name
844 GET_STRING(Netgame.name);
846 // get the netgame mode
847 GET_INT(Netgame.mode);
849 // get the security #
850 GET_INT(Netgame.security);
852 // get mode specific data
853 switch(Netgame.mode){
854 case NG_MODE_PASSWORD:
855 GET_STRING(Netgame.passwd);
857 case NG_MODE_RANK_ABOVE:
858 case NG_MODE_RANK_BELOW:
859 GET_INT(Netgame.rank_base);
863 // update standalone stuff
864 std_connect_set_gamename(Netgame.name);
865 std_multi_update_netgame_info_controls();
868 // get mission choice options
869 case MULTI_OPTION_MISSION:
871 char title[NAME_LENGTH+1];
872 int campaign_type,max_players;
876 SDL_assert(Game_mode & GM_STANDALONE_SERVER);
878 // coop or team vs. team mode
879 GET_INT(ng.type_flags);
880 if((ng.type_flags & NG_TYPE_TEAM) && !(Netgame.type_flags & NG_TYPE_TEAM)){
883 // if squad war was switched on
884 if((ng.type_flags & NG_TYPE_SW) && !(Netgame.type_flags & NG_TYPE_SW)){
885 mprintf(("STANDALONE TURNED ON SQUAD WAR!!\n"));
887 Netgame.type_flags = ng.type_flags;
890 GET_UINT(Netgame.respawn);
898 GET_STRING(ng.campaign_name);
900 // set the netgame max players here if the filename has changed
901 if(strcmp(Netgame.campaign_name,ng.campaign_name)){
903 if(!mission_campaign_get_info(ng.campaign_name,title,&campaign_type,&max_players)){
904 Netgame.max_players = 0;
906 Netgame.max_players = max_players;
909 SDL_strlcpy(Netgame.campaign_name, ng.campaign_name, SDL_arraysize(Netgame.campaign_name));
912 Netgame.campaign_mode = 1;
914 // put brackets around the campaign name
915 if(Game_mode & GM_STANDALONE_SERVER){
916 SDL_snprintf(str, SDL_arraysize(str), "(%s)", Netgame.campaign_name);
917 std_multi_set_standalone_mission_name(str);
922 GET_STRING(ng.mission_name);
924 if(strcmp(Netgame.mission_name,ng.mission_name)){
925 if(strlen(ng.mission_name)){
926 Netgame.max_players = mission_parse_get_multi_mission_info( ng.mission_name );
928 // setting this to -1 will prevent us from being seen on the network
929 Netgame.max_players = -1;
931 SDL_strlcpy(Netgame.mission_name, ng.mission_name, SDL_arraysize(Netgame.mission_name));
932 SDL_strlcpy(Game_current_mission_filename, Netgame.mission_name, SDL_arraysize(Game_current_mission_filename));
935 Netgame.campaign_mode = 0;
937 // set the mission name
938 if(Game_mode & GM_STANDALONE_SERVER){
939 std_multi_set_standalone_mission_name(Netgame.mission_name);
943 send_netgame_update_packet();
946 // get the netgame options
947 case MULTI_OPTION_SERVER:
948 GET_DATA(Netgame.options);
949 Netgame.options.flags = INTEL_INT( Netgame.options.flags );
950 Netgame.options.respawn = INTEL_INT( Netgame.options.respawn );
951 Netgame.options.voice_token_wait = INTEL_INT( Netgame.options.voice_token_wait );
952 Netgame.options.voice_record_time = INTEL_INT( Netgame.options.voice_record_time );
953 Netgame.options.kill_limit = INTEL_INT( Netgame.options.kill_limit );
954 Netgame.options.mission_time_limit = (fix)INTEL_INT( Netgame.options.mission_time_limit );
956 // if we're a standalone set for no sound, do so here
957 if((Game_mode & GM_STANDALONE_SERVER) && !Multi_options_g.std_voice){
958 Netgame.options.flags |= MSO_FLAG_NO_VOICE;
960 // maybe update the quality of sound
961 multi_voice_maybe_update_vars(Netgame.options.voice_qos,Netgame.options.voice_record_time);
964 // set the skill level
965 Game_skill_level = Netgame.options.skill_level;
967 if((Game_mode & GM_STANDALONE_SERVER) && !(Game_mode & GM_CAMPAIGN_MODE)){
968 Netgame.respawn = Netgame.options.respawn;
971 // if we have the "temp closed" flag toggle
972 if(Netgame.options.flags & MLO_FLAG_TEMP_CLOSED){
973 Netgame.flags ^= NG_FLAG_TEMP_CLOSED;
975 Netgame.options.flags &= ~(MLO_FLAG_TEMP_CLOSED);
977 // if i'm the standalone server, I should rebroadcast to all other players
978 if(Game_mode & GM_STANDALONE_SERVER){
979 for(idx=0;idx<MAX_PLAYERS;idx++){
980 if(MULTI_CONNECTED(Net_players[idx]) && (Net_player != &Net_players[idx]) && (&Net_players[idx] != &Net_players[player_index]) ){
981 multi_io_send_reliable(&Net_players[idx], data, offset);
985 send_netgame_update_packet();
989 // local netplayer options
990 case MULTI_OPTION_LOCAL:
991 if(player_index == -1){
992 GET_DATA(bogus); //data not used, so don't swap!
994 GET_DATA(Net_players[player_index].p_info.options);
995 Net_players[player_index].p_info.options.flags = INTEL_INT( Net_players[player_index].p_info.options.flags );
996 Net_players[player_index].p_info.options.obj_update_level = INTEL_INT( Net_players[player_index].p_info.options.obj_update_level );