// update the standalone with the mission settings I have picked (mission filename, etc) void multi_options_update_mission(netgame_info *ng, int campaign_mode) { ubyte data[MAX_PACKET_SIZE],code; int packet_size = 0; // should be a host on a standalone Assert((Net_player->flags & NETINFO_FLAG_GAME_HOST) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)); // build the header BUILD_HEADER(OPTIONS_UPDATE); code = MULTI_OPTION_MISSION; ADD_DATA(code); // type (coop or team vs. team) ADD_INT(ng->type_flags); // respawns ADD_UINT(ng->respawn); // add the mission/campaign filename code = (ubyte)campaign_mode; ADD_DATA(code); if(campaign_mode){ ADD_STRING(ng->campaign_name); } else { ADD_STRING(ng->mission_name); } // send to the server multi_io_send_reliable(Net_player, data, packet_size); }
// send a squadmsg packet to a player void multi_msg_send_squadmsg_packet(net_player *target,net_player *source,int command,ushort net_sig,int subsys_type) { ubyte data[100]; char s_val; int packet_size; Assert(source != NULL); Assert(target != NULL); if((source == NULL) || (target == NULL)){ return; } // build the header BUILD_HEADER(SQUADMSG_PLAYER); // add the command and targeting data ADD_INT(command); // add the id of the guy sending the order ADD_SHORT(source->player_id); // net signature ADD_USHORT(net_sig); // targeted subsytem (or -1 if none) s_val = (char)subsys_type; ADD_DATA(s_val); // send to the player multi_io_send_reliable(target, data, packet_size); }
// update the standalone with the settings I have picked at the "start game" screen void multi_options_update_start_game(netgame_info *ng) { ubyte data[MAX_PACKET_SIZE],code; int packet_size = 0; // should be a host on a standalone Assert((Net_player->flags & NETINFO_FLAG_GAME_HOST) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)); // build the header BUILD_HEADER(OPTIONS_UPDATE); code = MULTI_OPTION_START_GAME; ADD_DATA(code); // add the start game options ADD_STRING(ng->name); ADD_INT(ng->mode); ADD_INT(ng->security); // add mode-specific data switch(ng->mode){ case NG_MODE_PASSWORD: ADD_STRING(ng->passwd); break; case NG_MODE_RANK_ABOVE: case NG_MODE_RANK_BELOW: ADD_INT(ng->rank_base); break; } // send to the standalone server multi_io_send_reliable(Net_player, data, packet_size); }
// send a player kick packet void send_player_kick_packet(int player_index, int ban, int reason) { ubyte data[MAX_PACKET_SIZE]; int packet_size = 0; BUILD_HEADER(KICK_PLAYER); // add the address of the player to be kicked ADD_SHORT(Net_players[player_index].player_id); // indicate if he should be banned ADD_INT(ban); ADD_INT(reason); // send the request to the server multi_io_send_reliable(Net_player, data, packet_size); }
// send a request to the server saying I want to respawn (as an observer or not) void multi_respawn_send_request(int as_observer) { ubyte data[10],val; int packet_size = 0; // build the header and add the opcode BUILD_HEADER(RESPAWN_NOTICE); val = RESPAWN_REQUEST; ADD_DATA(val); // add a byte indicating whether or not we want to respawn as an observer val = (ubyte)as_observer; ADD_DATA(val); // send the request to the server multi_io_send_reliable(Net_player, data, packet_size); }
// update everyone with my local settings void multi_options_update_local() { ubyte data[MAX_PACKET_SIZE],code; int packet_size = 0; // if i'm the server, don't do anything if(Net_player->flags & NETINFO_FLAG_AM_MASTER){ return; } // build the header and add the opcode BUILD_HEADER(OPTIONS_UPDATE); code = MULTI_OPTION_LOCAL; ADD_DATA(code); // add the netgame options add_local_options(data, &packet_size, &Net_player->p_info.options); // send the packet multi_io_send_reliable(Net_player, data, packet_size); }
// update everyone on the current netgame options void multi_options_update_netgame() { ubyte data[MAX_PACKET_SIZE],code; int packet_size = 0; Assert(Net_player->flags & NETINFO_FLAG_GAME_HOST); // build the header and add the opcode BUILD_HEADER(OPTIONS_UPDATE); code = MULTI_OPTION_SERVER; ADD_DATA(code); // add the netgame options add_server_options(data, &packet_size, &Netgame.options); // send the packet if(Net_player->flags & NETINFO_FLAG_AM_MASTER){ multi_io_send_to_all_reliable(data, packet_size); } else { multi_io_send_reliable(Net_player, data, packet_size); } }
// process an incoming multi options packet void multi_options_process_packet(unsigned char *data, header *hinfo) { ubyte code; multi_local_options bogus; int idx,player_index; char str[255]; int offset = HEADER_LENGTH; // find out who is sending this data player_index = find_player_id(hinfo->id); if (player_index < 0) { nprintf(("Network", "Received packet from unknown player!\n")); return; } // get the packet code GET_DATA(code); switch(code){ // get the start game options case MULTI_OPTION_START_GAME: Assert(Game_mode & GM_STANDALONE_SERVER); // get the netgame name GET_STRING(Netgame.name); // get the netgame mode GET_INT(Netgame.mode); // get the security # GET_INT(Netgame.security); // get mode specific data switch(Netgame.mode){ case NG_MODE_PASSWORD: GET_STRING(Netgame.passwd); break; case NG_MODE_RANK_ABOVE: case NG_MODE_RANK_BELOW: GET_INT(Netgame.rank_base); break; } // update standalone stuff std_connect_set_gamename(Netgame.name); std_multi_update_netgame_info_controls(); break; // get mission choice options case MULTI_OPTION_MISSION: netgame_info ng; char title[NAME_LENGTH+1]; int campaign_type,max_players; memset(&ng,0,sizeof(netgame_info)); Assert(Game_mode & GM_STANDALONE_SERVER); // coop or team vs. team mode GET_INT(ng.type_flags); if((ng.type_flags & NG_TYPE_TEAM) && !(Netgame.type_flags & NG_TYPE_TEAM)){ multi_team_reset(); } // if squad war was switched on if((ng.type_flags & NG_TYPE_SW) && !(Netgame.type_flags & NG_TYPE_SW)){ mprintf(("STANDALONE TURNED ON SQUAD WAR!!\n")); } Netgame.type_flags = ng.type_flags; // new respawn count GET_UINT(Netgame.respawn); // name string memset(str,0,255); GET_DATA(code); // campaign mode if(code){ GET_STRING(ng.campaign_name); // set the netgame max players here if the filename has changed if(strcmp(Netgame.campaign_name,ng.campaign_name) != 0){ memset(title,0,NAME_LENGTH+1); if(!mission_campaign_get_info(ng.campaign_name,title,&campaign_type,&max_players)){ Netgame.max_players = 0; } else { Netgame.max_players = max_players; } strcpy_s(Netgame.campaign_name,ng.campaign_name); } Netgame.campaign_mode = 1; // put brackets around the campaign name if(Game_mode & GM_STANDALONE_SERVER){ strcpy_s(str,"("); strcat_s(str,Netgame.campaign_name); strcat_s(str,")"); std_multi_set_standalone_mission_name(str); } } // non-campaign mode else { GET_STRING(ng.mission_name); if(strcmp(Netgame.mission_name,ng.mission_name) != 0){ if(strlen(ng.mission_name)){ Netgame.max_players = mission_parse_get_multi_mission_info( ng.mission_name ); } else { // setting this to -1 will prevent us from being seen on the network Netgame.max_players = -1; } strcpy_s(Netgame.mission_name,ng.mission_name); strcpy_s(Game_current_mission_filename,Netgame.mission_name); } Netgame.campaign_mode = 0; // set the mission name if(Game_mode & GM_STANDALONE_SERVER){ std_multi_set_standalone_mission_name(Netgame.mission_name); } } // update FS2NetD as well if (MULTI_IS_TRACKER_GAME) { fs2netd_gameserver_update(true); } send_netgame_update_packet(); break; // get the netgame options case MULTI_OPTION_SERVER: get_server_options(data, &offset, &Netgame.options); // if we're a standalone set for no sound, do so here if((Game_mode & GM_STANDALONE_SERVER) && !Multi_options_g.std_voice){ Netgame.options.flags |= MSO_FLAG_NO_VOICE; } else { // maybe update the quality of sound multi_voice_maybe_update_vars(Netgame.options.voice_qos,Netgame.options.voice_record_time); } // set the skill level Game_skill_level = Netgame.options.skill_level; if((Game_mode & GM_STANDALONE_SERVER) && !(Game_mode & GM_CAMPAIGN_MODE)){ Netgame.respawn = Netgame.options.respawn; } // if we have the "temp closed" flag toggle if(Netgame.options.flags & MLO_FLAG_TEMP_CLOSED){ Netgame.flags ^= NG_FLAG_TEMP_CLOSED; } Netgame.options.flags &= ~(MLO_FLAG_TEMP_CLOSED); // if i'm the standalone server, I should rebroadcast to all other players if(Game_mode & GM_STANDALONE_SERVER){ for(idx=0;idx<MAX_PLAYERS;idx++){ if(MULTI_CONNECTED(Net_players[idx]) && (Net_player != &Net_players[idx]) && (&Net_players[idx] != &Net_players[player_index]) ){ multi_io_send_reliable(&Net_players[idx], data, offset); } } send_netgame_update_packet(); } break; // local netplayer options case MULTI_OPTION_LOCAL: if(player_index == -1){ get_local_options(data, &offset, &bogus); } else { get_local_options(data, &offset, &Net_players[player_index].p_info.options); //If the client has sent an object update higher than that which the server allows, reset it if (Net_player->flags & NETINFO_FLAG_AM_MASTER) { if (Net_players[player_index].p_info.options.obj_update_level > Cmdline_objupd) { Net_players[player_index].p_info.options.obj_update_level = Cmdline_objupd; } } } break; } PACKET_SET_SIZE(); }