void fs2netd_gameserver_update(bool force) { if ( !Logged_in ) { return; } // server hasn't started yet? if ( !(Net_player->flags & NETINFO_FLAG_MT_CONNECTED) ) { return; } // is it actually time for an update if ( !force && (timer_get_seconds() < Next_gameserver_update) ) { return; } strcpy_s(Multi_tracker_game_data.mission_name, Netgame.mission_name); strcpy_s(Multi_tracker_game_data.title, Netgame.title); strcpy_s(Multi_tracker_game_data.campaign_name, Netgame.campaign_name); Multi_tracker_game_data.campaign_mode = (ubyte)Netgame.campaign_mode; Multi_tracker_game_data.players = (short)multi_num_players(); Multi_tracker_game_data.game_state = (ubyte)Netgame.game_state; FS2NetD_SendServerUpdate(); // set timeout for every 2 minutes Next_gameserver_update = timer_get_seconds() + 120; ml_string("FS2NetD sent game server update"); }
void fs2netd_gameserver_start() { if ( !Logged_in ) { return; } // already been here if (Net_player->flags & NETINFO_FLAG_MT_CONNECTED) { return; } memset(&Multi_tracker_game_data, 0, sizeof(tracker_game_data)); strcpy_s(Multi_tracker_game_data.name, Netgame.name); strcpy_s(Multi_tracker_game_data.mission_name, Netgame.mission_name); strcpy_s(Multi_tracker_game_data.title, Netgame.title); strcpy_s(Multi_tracker_game_data.campaign_name, Netgame.campaign_name); if ( strlen(Multi_fs_tracker_channel) ) { strcpy_s(Multi_tracker_game_data.chat_channel, Multi_fs_tracker_channel); } Multi_tracker_game_data.campaign_mode = (ubyte)Netgame.campaign_mode; Multi_tracker_game_data.flags = Netgame.flags; Multi_tracker_game_data.type_flags = Netgame.type_flags; Multi_tracker_game_data.players = (short)multi_num_players(); Multi_tracker_game_data.max_players = (short)Netgame.max_players; Multi_tracker_game_data.mode = (ubyte)Netgame.mode; Multi_tracker_game_data.rank_base = (ubyte)Netgame.rank_base; Multi_tracker_game_data.game_state = (ubyte)Netgame.game_state; Multi_tracker_game_data.speed = (ubyte)multi_get_connection_speed(); FS2NetD_SendServerStart(); Net_player->flags |= NETINFO_FLAG_MT_CONNECTED; // initial update should be about 2 seconds from now Next_gameserver_update = timer_get_seconds() + 2; ml_string("FS2NetD sent game server start"); }
void FS2NetD_SendServerStart() { int buffer_size; char buffer[550]; ubyte tvar; INIT_PACKET( PCKT_SERVER_START ); PXO_ADD_STRING( Netgame.name ); PXO_ADD_STRING( Netgame.mission_name ); PXO_ADD_STRING( Netgame.title ); PXO_ADD_STRING( Netgame.campaign_name ); tvar = (ubyte)Netgame.campaign_mode; PXO_ADD_DATA( tvar ); PXO_ADD_INT( Netgame.flags ); PXO_ADD_INT( Netgame.type_flags ); PXO_ADD_SHORT( (short)multi_num_players() ); PXO_ADD_SHORT( (short)Netgame.max_players ); tvar = (ubyte)Netgame.mode; PXO_ADD_DATA( tvar ); tvar = (ubyte)Netgame.rank_base; PXO_ADD_DATA( tvar ); tvar = (ubyte)Netgame.game_state; PXO_ADD_DATA( tvar ); tvar = (ubyte)multi_get_connection_speed(); PXO_ADD_DATA( tvar ); PXO_ADD_STRING(Multi_fs_tracker_channel); DONE_PACKET(); FS2NetD_SendData(buffer, buffer_size); }
void FS2NetD_SendServerUpdate() { int buffer_size; char buffer[550]; ubyte tvar; INIT_PACKET( PCKT_SERVER_UPDATE ); PXO_ADD_STRING( Netgame.mission_name ); PXO_ADD_STRING( Netgame.title ); PXO_ADD_STRING( Netgame.campaign_name ); tvar = (ubyte)Netgame.campaign_mode; PXO_ADD_DATA( tvar ); PXO_ADD_SHORT( (short)multi_num_players() ); tvar = (ubyte)Netgame.game_state; PXO_ADD_DATA( tvar ); DONE_PACKET(); FS2NetD_SendData(buffer, buffer_size); }
// Initialize the dead popup data void popupdead_start() { int i; UI_BUTTON *b; if ( Popupdead_active ) { return; } // increment number of deaths Player->failures_this_session++; // create base window Popupdead_window.create(Popupdead_background_coords[gr_screen.res][0], Popupdead_background_coords[gr_screen.res][1], 1, 1, 0); Popupdead_window.set_foreground_bmap(Popupdead_background_filename[gr_screen.res]); Popupdead_num_choices = 0; Popupdead_multi_type = -1; if ((The_mission.max_respawn_delay >= 0) && ( Game_mode & GM_MULTIPLAYER )) { Popupdead_timer = timestamp(The_mission.max_respawn_delay * 1000); if (Game_mode & GM_MULTIPLAYER) { if(!(Net_player->flags & NETINFO_FLAG_LIMBO)){ if (The_mission.max_respawn_delay) { HUD_printf("Player will automatically respawn in %d seconds", The_mission.max_respawn_delay); } else { HUD_printf("Player will automatically respawn now"); } } } } if ( Game_mode & GM_NORMAL ) { // also do a campaign check here? if (0) { //((Player->show_skip_popup) && (!Popupdead_skip_already_shown) && (Game_mode & GM_CAMPAIGN_MODE) && (Game_mode & GM_NORMAL) && (Player->failures_this_session >= PLAYER_MISSION_FAILURE_LIMIT)) { // init the special preliminary death popup that gives the skip option Popupdead_button_text[0] = XSTR( "Do Not Skip This Mission", 1473); Popupdead_button_text[1] = XSTR( "Advance To The Next Mission", 1474); Popupdead_button_text[2] = XSTR( "Don't Show Me This Again", 1475); Popupdead_num_choices = POPUPDEAD_NUM_CHOICES_SKIP; Popupdead_skip_active = 1; } else if(The_mission.flags & MISSION_FLAG_RED_ALERT) { // We can't staticly declare these because they are externalized Popupdead_button_text[0] = XSTR( "Quick Start Mission", 105); Popupdead_button_text[1] = XSTR( "Return To Flight Deck", 106); Popupdead_button_text[2] = XSTR( "Return To Briefing", 107); Popupdead_button_text[3] = XSTR( "Replay previous mission", 1432); Popupdead_num_choices = POPUPDEAD_NUM_CHOICES_RA; } else { Popupdead_button_text[0] = XSTR( "Quick Start Mission", 105); Popupdead_button_text[1] = XSTR( "Return To Flight Deck", 106); Popupdead_button_text[2] = XSTR( "Return To Briefing", 107); Popupdead_num_choices = POPUPDEAD_NUM_CHOICES; } } else { // in multiplayer, we have different choices depending on respawn mode, etc. // if the player has run out of respawns and must either quit and become an observer if(Net_player->flags & NETINFO_FLAG_LIMBO){ // the master should not be able to quit the game if( ((Net_player->flags & NETINFO_FLAG_AM_MASTER) && (multi_num_players() > 1)) || (Net_player->flags & NETINFO_FLAG_TEAM_CAPTAIN) ) { Popupdead_button_text[0] = XSTR( "Observer Mode", 108); Popupdead_num_choices = 1; Popupdead_multi_type = POPUPDEAD_OBS_ONLY; } else { Popupdead_button_text[0] = XSTR( "Observer Mode", 108); Popupdead_button_text[1] = XSTR( "Return To Flight Deck", 106); Popupdead_num_choices = 2; Popupdead_multi_type = POPUPDEAD_OBS_QUIT; } } else { // the master of the game should not be allowed to quit if ( ((Net_player->flags & NETINFO_FLAG_AM_MASTER) && (multi_num_players() > 1)) || (Net_player->flags & NETINFO_FLAG_TEAM_CAPTAIN) ) { Popupdead_button_text[0] = XSTR( "Respawn", 109); Popupdead_num_choices = 1; Popupdead_multi_type = POPUPDEAD_RESPAWN_ONLY; } else { Popupdead_button_text[0] = XSTR( "Respawn", 109); if(!Cmdline_mpnoreturn) { Popupdead_button_text[1] = XSTR( "Return To Flight Deck", 106); Popupdead_num_choices = 2; } else { Popupdead_num_choices = 1; } Popupdead_multi_type = POPUPDEAD_RESPAWN_QUIT; } } } // create buttons for (i=0; i < Popupdead_num_choices; i++) { b = &Popupdead_buttons[i]; b->create(&Popupdead_window, "", Popupdead_button_coords[gr_screen.res][i][0], Popupdead_button_coords[gr_screen.res][i][1], 30, 20, 0, 1); b->set_bmaps(Popupdead_button_filenames[gr_screen.res][i], 3, 0); b->set_highlight_action(common_play_highlight_sound); // create invisible buttons to detect mouse presses... can't use mask since button region is dynamically sized int lx, w, h; gr_get_string_size(&w, &h, Popupdead_button_text[i]); lx = Popupdead_region_coords[gr_screen.res][i][0] - w; b = &Popupdead_button_regions[i]; b->create(&Popupdead_window, "", lx, Popupdead_region_coords[gr_screen.res][i][1], Popupdead_region_coords[gr_screen.res][i][2]-lx, Popupdead_region_coords[gr_screen.res][i][3]-Popupdead_region_coords[gr_screen.res][i][1], 0, 1); b->hide(); } Popupdead_default_choice = 0; Popupdead_choice = -1; Popupdead_active = 1; }
void fs2netd_store_stats() { if ( !Logged_in ) { return; } ml_string("Sending stats to server"); // default to not saving the stats Multi_debrief_stats_accept_code = 0; if (Duplicate_login_detected) { Duplicate_login_detected = false; multi_display_chat_msg( XSTR("<Duplicate login detected - stats have been tossed>", 1582), 0, 0 ); ml_string( XSTR("<Duplicate login detected - stats have been tossed>", 1583) ); fs2netd_store_stats_results(); return; } if ( game_hacked_data() ) { multi_display_chat_msg( XSTR("<Hacked tables detected - stats have been tossed>", 1584), 0, 0 ); popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR("You are playing with a hacked tables, your stats will not be saved", 1585) ); fs2netd_store_stats_results(); return; } if ( (multi_num_players() <= 1) && (Multi_num_players_at_start <= 1) ) { multi_display_chat_msg(XSTR("<Not enough players were present at game start or end, stats will not be saved>", 1048), 0, 0); ml_string( XSTR("<Not enough players were present at game start or end, stats will not be saved>", 1048) ); fs2netd_store_stats_results(); return; } /* // if any players have hacked info for(int idx = 0; idx < MAX_PLAYERS; idx++) { if ( MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (Net_players[idx].flags & NETINFO_FLAG_HAXOR) ) { multi_display_chat_msg( XSTR("<Connected player has hacked info - tossing invalid stats>", -1), 0, 0 ); return; } } */ if ( !fs2netd_check_mission(Netgame.mission_name) ) { multi_display_chat_msg(XSTR("<Server detected a non PXO validated mission. Stats will not be saved>", 1049), 0, 0); popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR("This is not a PXO validated mission, your stats will not be saved", 1050)); fs2netd_store_stats_results(); return; } int spd_ret = fs2netd_send_player(); switch (spd_ret) { // 0 = pilot updated, 1 = invalid pilot, 2 = invalid (expired?) sid case -1: ml_string("<stats have been tossed - server error>"); break; case 0: ml_string( XSTR("<stats have been accepted>", 850) ); Multi_debrief_stats_accept_code = 1; break; case 1: ml_string("<stats have been tossed - pilot error>"); break; case 2: // we should never get here with the new code Int3(); ml_string("<stats have been tossed - invalid tracker id>"); break; default: multi_display_chat_msg( XSTR("Unknown Stats Store Request Reply", 1586), 0, 0 ); break; } fs2netd_store_stats_results(); }
void fs2netd_debrief_init() { if ( !(Game_mode & GM_MULTIPLAYER) ) { return; } if ( !Om_tracker_flag ) { return; } if ( !Is_connected ) { return; } uint CurrentMissionChsum; bool mValidStatus = false; cf_chksum_long(Netgame.mission_name, &CurrentMissionChsum); mValidStatus = FS2NetD_CheckSingleMission(Netgame.mission_name, CurrentMissionChsum); if ( ((multi_num_players() > 1) || (Multi_num_players_at_start > 1)) && !game_hacked_data() && mValidStatus ) { // verify that we are logged in before doing anything else fs2netd_login(); int spd_ret = FS2NetD_SendPlayerData(PXO_SID, Players[Player_num].callsign, Multi_tracker_login, &Players[Player_num]); switch (spd_ret) { // 0 = pilot updated, 1 = invalid pilot, 2 = invalid (expired?) sid case -1: multi_display_chat_msg( XSTR("<Did not receive response from server within timeout period>", -1), 0, 0 ); multi_display_chat_msg( XSTR("<Your stats may not have been stored>", -1), 0, 0 ); multi_display_chat_msg( XSTR("<This is not a critical error>", -1), 0, 0 ); Multi_debrief_stats_accept_code = 1; break; case 0: multi_display_chat_msg( XSTR("<stats have been accepted>", 850), 0, 0 ); Multi_debrief_stats_accept_code = 1; break; case 1: multi_display_chat_msg( XSTR("<stats have been tossed>", 850), 0, 0 ); multi_display_chat_msg( XSTR("WARNING: Your pilot was invalid, this is a serious error, possible data corruption", -1), 0, 0 ); Multi_debrief_stats_accept_code = 0; break; case 2: // we really shouldn't be here with the new code, but handle it just in case Int3(); fs2netd_login(); if (PXO_SID != -1) { if ( !FS2NetD_SendPlayerData(PXO_SID, Players[Player_num].callsign, Multi_tracker_login, &Players[Player_num]) ) { multi_display_chat_msg( XSTR("<stats have been accepted>", 850), 0, 0 ); Multi_debrief_stats_accept_code = 1; break; } } multi_display_chat_msg( XSTR("<stats have been tossed>", 851), 0, 0 ); Multi_debrief_stats_accept_code = 0; break; default: multi_display_chat_msg( XSTR("Unknown Stats Store Request Reply", -1), 0, 0 ); break; } } else { multi_display_chat_msg( XSTR("<stats have been tossed>", 851), 0, 0 ); Multi_debrief_stats_accept_code = 0; } }
void fs2netd_do_frame() { int rc, buffer_size, buffer_offset; char buffer[300], str[256]; ubyte pid = 0; int itemp; static fix NextPing = -1, NextHeartBeat = -1; static fix GotPong = -1; bool reset = false; // don't bother with this if we aren't on FS2NetD if ( !Om_tracker_flag ) { return; } if ( !(Game_mode & GM_MULTIPLAYER) ) { return; } // not connected to server if ( !Is_connected ) { return; } // in a previous processing loop, so don't do a frame until that has completed if ( In_process ) { return; } // if we didn't get a PONG within 4 minutes the server connection must have dropped if ( (GotPong != -1) && ((NextPing - GotPong) > (240 * F1_0)) ) { ml_printf("FS2NetD WARNING: Lost connection to server!"); FS2NetD_Disconnect(); Is_connected = false; Logged_in = false; PXO_SID = -1; NextHeartBeat = -1; NextPing = -1; GotPong = -1; // try to reinit the server connection fs2netd_login(); // make sure that we are good to go if ( !Is_connected ) { if (!Is_standalone) { gamesnd_play_iface(SND_GENERAL_FAIL); popup(PF_USE_AFFIRMATIVE_ICON | PF_TITLE_BIG | PF_TITLE_RED, 1, POPUP_OK, "ERROR:\nLost connection to the FS2NetD server!"); } return; } else { ml_printf("FS2NetD NOTICE: Connection to server has been reestablished!"); } } // send out ping every 60 seconds if ( (NextPing == -1) || (timer_get_fixed_seconds() >= NextPing) ) { // if we have seen a long period of time between pings then reset the pong time too if ( (timer_get_fixed_seconds() - NextPing) > (120 * F1_0) ) { reset = true; } NextPing = timer_get_fixed_seconds() + (60 * F1_0); // we go ahead and set the initial GotPong here, even though we haven't gotten a pong yet if ( (GotPong == -1) || reset ) { GotPong = NextPing; reset = false; } FS2NetD_Ping(); ml_printf("FS2NetD sent PING"); } // send out server heartbeat every 2 minutes, unless forced to by an update if ( (Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Multi_create_force_heartbeat || (NextHeartBeat == -1) || (timer_get_fixed_seconds() >= NextHeartBeat)) ) { Multi_create_force_heartbeat = 0; NextHeartBeat = timer_get_fixed_seconds() + (120 * F1_0); FS2NetD_SendHeartBeat(Netgame.name, Netgame.mission_name, Netgame.title, Netgame.type_flags, Netgame.server_addr.port, multi_num_players()); ml_printf("FS2NetD sent HeartBeat"); } // Check for GWall messages - ping replies, etc if ( (rc = FS2NetD_GetData(buffer, sizeof(buffer))) != -1 ) { int rc_total = rc; buffer_offset = 0; while (rc_total > buffer_offset) { // make sure we have enough data to try and process if (rc_total < BASE_PACKET_SIZE) { break; } PXO_GET_DATA( pid ); PXO_GET_INT( buffer_size ); while ( (rc_total < buffer_size) && ((sizeof(buffer) - rc_total) > 0) ) { if ( (rc = FS2NetD_GetData(buffer+rc_total, sizeof(buffer) - rc_total)) != -1 ) { rc_total += rc; } else { break; } } if (buffer_size <= 0) { break; } // we don't have the full packet, so bail if (rc_total < buffer_size) { break; } // processing time! switch (pid) { case PCKT_PING: { PXO_GET_INT( itemp ); ml_printf("FS2NetD received PING"); FS2NetD_Pong(itemp); break; } case PCKT_PONG: { PXO_GET_INT( itemp ); ml_printf("FS2NetD received PONG: %d ms", timer_get_milliseconds() - itemp); GotPong = timer_get_fixed_seconds(); break; } case PCKT_NETOWRK_WALL: { PXO_GET_STRING( str ); ml_printf("FS2NetD WALL received MSG: %s", str); switch (Netgame.game_state) { case NETGAME_STATE_FORMING: case NETGAME_STATE_BRIEFING: case NETGAME_STATE_MISSION_SYNC: case NETGAME_STATE_DEBRIEF: multi_display_chat_msg(str, 0, 0); break; /* -- Won't Happen - multi_do_frame() is not called during paused state so the game will not even receive the data during it case NETGAME_STATE_PAUSED: // EASY! send_game_chat_packet(Net_player, str, MULTI_MSG_ALL, NULL); break; */ case NETGAME_STATE_IN_MISSION: // gotta make it paused //multi_pause_request(1); //send_game_chat_packet(Net_player, str, MULTI_MSG_ALL, NULL); HUD_printf(str); break; default: // do-nothing break; } break; } default: { ml_printf("Unexpected FS2NetD Packet - PID = %x", pid); break; } } buffer_offset += (buffer_size - BASE_PACKET_SIZE); } } }