// process a player kick packet void process_player_kick_packet(ubyte *data, header *hinfo) { int player_num,from_player,ban,reason; short player_id; int offset = HEADER_LENGTH; // get the address of the guy who is to be kicked GET_SHORT(player_id); GET_INT(ban); GET_INT(reason); player_num = find_player_id(player_id); PACKET_SET_SIZE(); // only the server should ever receive a request to kick a guy Assert(Net_player->flags & NETINFO_FLAG_AM_MASTER); // determine who sent the packet from_player = find_player_id(hinfo->id); // check to see if this guy is allowed to make such a request if((from_player == -1) || !multi_kick_can_kick(&Net_players[from_player]) ){ nprintf(("Network","Received a kick request from an invalid player!!\n")); } // otherwise, process the request fully else { // make sure we have a valid player to kick if(player_num == -1){ nprintf(("Network","Received request to kick an unknown player!\n")); } else { // will handle all the rest of the details multi_kick_player(player_num,ban,reason); } } }
// internal helper function for sort. // sorts first by priority number and then alphabetically int escort_compare_func(const void* e1, const void* e2) { escort_info* escort1, *escort2; int diff; int ret; escort1 = (escort_info*)e1; escort2 = (escort_info*)e2; // multiplayer dogfight if ((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)) { int n1, n2; n1 = find_player_id(escort1->np_id); n2 = find_player_id(escort2->np_id); if ((n1 < 0) || (n2 < 0) || (Net_players[n1].m_player == NULL) || (Net_players[n2].m_player == NULL)) { ret = 0; } else { // player 1 is higher than player 2 if (Net_players[n1].m_player->stats.m_kill_count_ok >= Net_players[n2].m_player->stats.m_kill_count_ok) { ret = -1; } else { ret = 1; } } } else { diff = escort2->priority - escort1->priority; if (diff != 0) { ret = diff; } else { char* name1, *name2; name1 = Ships[Objects[escort1->objnum].instance].ship_name; name2 = Ships[Objects[escort2->objnum].instance].ship_name; ret = stricmp(name1, name2); } } return ret; }
// process incoming squadmate messaging info void multi_msg_process_squadmsg_packet(unsigned char *data, header *hinfo) { int command; ushort net_sig; short source_id; int source_index; char s_val; int offset = HEADER_LENGTH; // get all packet data GET_INT(command); GET_SHORT(source_id); GET_USHORT(net_sig); GET_DATA(s_val); PACKET_SET_SIZE(); // determine who the order is from source_index = find_player_id(source_id); if(source_index == -1){ nprintf(("Network","Received squadmsg order packet from unknown player!!\n")); return; } // display the squadmessage somehow multi_msg_show_squadmsg(&Net_players[source_index],command,net_sig,(int)s_val); }
// called once per frame to remove dead or departed ships from the escort list void hud_escort_cull_list() { int i, objnum; int np_index; // multiplayer dogfight if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){ for ( i = 0; i < Num_escort_ships; i++ ) { np_index = find_player_id(Escort_ships[i].np_id); // maybe remove him if he left if ( np_index < 0 ) { hud_remove_ship_from_escort_index(i, -1); i--; } } } // everything else else { for ( i = 0; i < Num_escort_ships; i++ ) { objnum = Escort_ships[i].objnum; Assert( objnum >=0 && objnum < MAX_OBJECTS ); if ( Objects[objnum].flags & OF_SHOULD_BE_DEAD || Ships[Objects[objnum].instance].flags & SF_HIDDEN_FROM_SENSORS ) { hud_remove_ship_from_escort_index(i, objnum); i--; } } } }
// multiplayer dogfight void hud_escort_show_icon_dogfight(int x, int y, int index) { #ifndef NEW_HUD int hull_integrity = 100; char buf[255]; int np_index; object *objp; ship_info *sip; int stat_shift = 40; // always use the standard color to avoid confusion hud_set_gauge_color(HUD_ESCORT_VIEW); // netplayer index np_index = find_player_id(Escort_ships[index].np_id); if((np_index < 0) || (np_index >= MAX_PLAYERS) || (Net_players[np_index].m_player == NULL)){ return; } // print out player name strcpy(buf, Net_players[np_index].m_player->callsign); gr_force_fit_string(buf, 255, 100 - stat_shift); emp_hud_string( x + current_hud->Escort_name[0], y + current_hud->Escort_name[1], EG_ESCORT1 + index, buf); // can we get the player object? objp = NULL; if((Net_players[np_index].m_player->objnum >= 0) && (Net_players[np_index].m_player->objnum < MAX_OBJECTS) && (Objects[Net_players[np_index].m_player->objnum].type == OBJ_SHIP)){ objp = &Objects[Net_players[np_index].m_player->objnum]; if((objp->instance >= 0) && (objp->instance < MAX_SHIPS) && (Ships[objp->instance].ship_info_index >= 0) && (Ships[objp->instance].ship_info_index < MAX_SHIPS)){ sip = &Ship_info[Ships[objp->instance].ship_info_index]; } else { return; } hull_integrity = (int)(((float)objp->hull_strength / (float)Ships[objp->instance].ship_max_hull_strength) * 100.0f); if(hull_integrity < 0){ hull_integrity = 0; } } // show ship integrity if(objp == NULL){ emp_hud_printf( x+current_hud->Escort_integrity[0] - stat_shift, y+current_hud->Escort_integrity[1], EG_NULL, "%d", Net_players[np_index].m_player->stats.m_kill_count_ok); } else { emp_hud_printf( x+current_hud->Escort_integrity[0] - stat_shift, y+current_hud->Escort_integrity[1], EG_NULL, "(%d%%) %d", hull_integrity, Net_players[np_index].m_player->stats.m_kill_count_ok); } #endif }
// multiplayer dogfight void HudGaugeEscort::renderIconDogfight(int x, int y, int index) { int hull_integrity = 100; char buf[255]; int np_index; object *objp; int stat_shift = 40; // always use the standard color to avoid confusion setGaugeColor(); // netplayer index np_index = find_player_id(Escort_ships[index].np_id); if((np_index < 0) || (np_index >= MAX_PLAYERS) || (Net_players[np_index].m_player == NULL)){ return; } // print out player name strcpy_s(buf, Net_players[np_index].m_player->callsign); font::force_fit_string(buf, 255, 100 - stat_shift); renderString( x + ship_name_offsets[0], y + ship_name_offsets[1], EG_ESCORT1 + index, buf); // can we get the player object? objp = NULL; if((Net_players[np_index].m_player->objnum >= 0) && (Net_players[np_index].m_player->objnum < MAX_OBJECTS) && (Objects[Net_players[np_index].m_player->objnum].type == OBJ_SHIP)){ objp = &Objects[Net_players[np_index].m_player->objnum]; if((objp->instance >= 0) && (objp->instance < MAX_SHIPS) && (Ships[objp->instance].ship_info_index >= 0) && (Ships[objp->instance].ship_info_index < MAX_SHIPS)){ // } else { return; } hull_integrity = (int)(((float)objp->hull_strength / (float)Ships[objp->instance].ship_max_hull_strength) * 100.0f); if(hull_integrity < 0){ hull_integrity = 0; } } // show ship integrity if(objp == NULL){ renderPrintf( x+ship_integrity_offsets[0] - stat_shift, y+ship_integrity_offsets[1], EG_NULL, "%d", Net_players[np_index].m_player->stats.m_kill_count_ok); } else { renderPrintf( x+ship_integrity_offsets[0] - stat_shift, y+ship_integrity_offsets[1], EG_NULL, "(%d%%) %d", hull_integrity, Net_players[np_index].m_player->stats.m_kill_count_ok); } }
// called once per frame to refresh the escort list if important flags changed void hud_escort_cull_list() { int i; int np_index; // multiplayer dogfight if(MULTI_DOGFIGHT){ for ( i = 0; i < Num_escort_ships; i++ ) { np_index = find_player_id(Escort_ships[i].np_id); // maybe remove him if he left if ( np_index < 0 ) { hud_setup_escort_list(0); break; } } } // everything else else { for ( i = 0; i < Num_escort_ships; i++ ) { int objnum = Escort_ships[i].objnum; Assert( objnum >=0 && objnum < MAX_OBJECTS ); if ( Objects[objnum].flags[Object::Object_Flags::Should_be_dead] ) { hud_setup_escort_list(0); break; } else if ( Objects[objnum].type == OBJ_SHIP ) { int shipnum = Objects[objnum].instance; Assert( shipnum >= 0 && shipnum < MAX_SHIPS ); if ( (Ships[shipnum].flags[Ship::Ship_Flags::Hidden_from_sensors]) || ((Ships[shipnum].flags[Ship::Ship_Flags::Stealth]) && ((Ships[shipnum].team != Player_ship->team) || (Ships[shipnum].flags[Ship::Ship_Flags::Friendly_stealth_invis]))) ) { hud_setup_escort_list(0); break; } } } } }
// called once per frame to refresh the escort list if important flags changed void hud_escort_cull_list() { int i; int np_index; // multiplayer dogfight if(MULTI_DOGFIGHT){ for ( i = 0; i < Num_escort_ships; i++ ) { np_index = find_player_id(Escort_ships[i].np_id); // maybe remove him if he left if ( np_index < 0 ) { hud_setup_escort_list(0); break; } } } // everything else else { for ( i = 0; i < Num_escort_ships; i++ ) { int objnum = Escort_ships[i].objnum; Assert( objnum >=0 && objnum < MAX_OBJECTS ); if ( Objects[objnum].flags & OF_SHOULD_BE_DEAD ) { hud_setup_escort_list(0); break; } else if ( Objects[objnum].type == OBJ_SHIP ) { int shipnum = Objects[objnum].instance; Assert( shipnum >= 0 && shipnum < MAX_SHIPS ); if ( (Ships[shipnum].flags & SF_HIDDEN_FROM_SENSORS) || ((Ships[shipnum].flags2 & SF2_STEALTH) && ((Ships[shipnum].team != Player_ship->team) || (Ships[shipnum].flags2 & SF2_FRIENDLY_STEALTH_INVIS))) ) { hud_setup_escort_list(0); break; } } } } }
// process an incoming respawn info packet void multi_respawn_process_packet(ubyte *data, header *hinfo) { ubyte code,cur_link_status; char cur_primary_bank,cur_secondary_bank; ushort net_sig,ship_ets; short player_id; int player_index; vector v; char parse_name[1024] = ""; int offset = HEADER_LENGTH; // determine who send the packet player_index = find_player_id(hinfo->id); if(player_index == -1){ nprintf(("Network","Couldn't find player for processing respawn packet!\n")); } // get the opcode GET_DATA(code); // do something based upon the opcode switch((int)code){ case AI_RESPAWN_NOTICE: p_object *pobjp; GET_USHORT( net_sig ); pobjp = mission_parse_get_arrival_ship( net_sig ); Assert( pobjp != NULL ); multi_respawn_ai( pobjp ); break; case RESPAWN_BROADCAST: // get the respawn data GET_USHORT(net_sig); get_vector_data( data, &offset, v ); GET_SHORT(player_id); GET_DATA(cur_primary_bank); GET_DATA(cur_secondary_bank); GET_DATA(cur_link_status); GET_USHORT(ship_ets); GET_STRING(parse_name); player_index = find_player_id(player_id); if(player_index == -1){ nprintf(("Network","Couldn't find player to respawn!\n")); break; } // create the ship and assign its position, net_signature, and class // respawn the player multi_respawn_player(&Net_players[player_index], cur_primary_bank, cur_secondary_bank, cur_link_status, ship_ets, net_sig, parse_name, &v); // if this is for me, I should jump back into gameplay if(&Net_players[player_index] == Net_player){ extern int Player_multi_died_check; Player_multi_died_check = -1; gameseq_post_event(GS_EVENT_ENTER_GAME); } break; case RESPAWN_REQUEST: // determine whether he wants to respawn as an observer or not GET_DATA(code); nprintf(("Network","Received respawn request\n")); if(player_index == -1){ nprintf(("Network","Received respawn request from unknown player!\n")); break; } // make sure he's not making an invalid request if((code == 0) && !(Net_players[player_index].flags & NETINFO_FLAG_RESPAWNING)){ nprintf(("Network","Received respawn request from player who shouldn't be respawning!\n")); Int3(); break; } else if((code == 1) && !(Net_players[player_index].flags & NETINFO_FLAG_LIMBO)){ nprintf(("Network","Received respawn observer request from a player who shouldn't be respawning as an observer!\n")); Int3(); break; } // otherwise perform the operation // respawn the guy as an observer if(code){ multi_respawn_make_observer(&Net_players[player_index]); } // respawn him as normal else { // create his new ship, and change him from respawning to respawned Assert(Net_players[player_index].p_info.p_objp != NULL); if(Net_players[player_index].p_info.p_objp != NULL){ multi_respawn_player(&Net_players[player_index], Net_players[player_index].s_info.cur_primary_bank, Net_players[player_index].s_info.cur_secondary_bank,Net_players[player_index].s_info.cur_link_status, Net_players[player_index].s_info.ship_ets, 0, Net_players[player_index].p_info.p_objp->name); } } break; } PACKET_SET_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(); }