void HumanClientApp::Autosave() {
    // autosave only on appropriate turn numbers, and when enabled for current
    // game type (single vs. multiplayer)
    int autosave_turns = GetOptionsDB().Get<int>("autosave.turns");
    if (autosave_turns < 1)
        return;     // avoid divide by zero
    if (CurrentTurn() % autosave_turns != 0 && CurrentTurn() != 1)
        return;     // turns divisible by autosave_turns, and first turn, have autosaves done
    if (m_single_player_game && !GetOptionsDB().Get<bool>("autosave.single-player"))
        return;
    if (!m_single_player_game && !GetOptionsDB().Get<bool>("autosave.multiplayer"))
        return;

    const char* legal_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-";

    // get empire name, filtered for filename acceptability
    int client_empire_id = EmpireID();
    const Empire* empire = GetEmpire(client_empire_id);
    std::string empire_name;
    if (empire)
        empire_name = empire->Name();
    else
        empire_name = UserString("OBSERVER");
    std::string::size_type first_good_empire_char = empire_name.find_first_of(legal_chars);
    if (first_good_empire_char == std::string::npos) {
        empire_name.clear();
    } else {
        std::string::size_type first_bad_empire_char = empire_name.find_first_not_of(legal_chars, first_good_empire_char);
        empire_name = empire_name.substr(first_good_empire_char, first_bad_empire_char - first_good_empire_char);
    }

    // get player name, also filtered
    std::string player_name;
    if (empire)
        player_name = empire->PlayerName();
    std::string::size_type first_good_player_char = player_name.find_first_of(legal_chars);
    if (first_good_player_char == std::string::npos) {
        player_name.clear();
    } else {
        std::string::size_type first_bad_player_char = player_name.find_first_not_of(legal_chars, first_good_player_char);
        player_name = player_name.substr(first_good_player_char, first_bad_player_char - first_good_player_char);
    }

    // select filename extension
    std::string extension;
    if (m_single_player_game)
        extension = SP_SAVE_FILE_EXTENSION;
    else
        extension = MP_SAVE_FILE_EXTENSION;

    // Add timestamp to autosave generated files
    std::string datetime_str = FilenameTimestamp();

    boost::filesystem::path autosave_dir_path(GetSaveDir() / "auto");

    std::string save_filename = boost::io::str(boost::format("FreeOrion_%s_%s_%04d_%s%s") % player_name % empire_name % CurrentTurn() % datetime_str % extension);
    boost::filesystem::path save_path(autosave_dir_path / save_filename);
    std::string path_string = PathString(save_path);

    try {
        // ensure autosave directory exists
        if (!exists(autosave_dir_path))
            boost::filesystem::create_directories(autosave_dir_path);
    } catch (const std::exception& e) {
        ErrorLogger() << "Autosave unable to check / create autosave directory: " << e.what();
        std::cerr << "Autosave unable to check / create autosave directory: " << e.what() << std::endl;
    }

    // check for and remove excess oldest autosaves
    int max_autosaves = GetOptionsDB().Get<int>("autosave.limit");
    RemoveOldestFiles(max_autosaves, autosave_dir_path);

    // create new save
    DebugLogger() << "Autosaving to: " << path_string;
    try {
        SaveGame(path_string);
    } catch (const std::exception& e) {
        ErrorLogger() << "Autosave failed: " << e.what();
        std::cerr << "Autosave failed: " << e.what() << std::endl;
    }
}
Exemple #2
0
SaveFileDialog::SaveFileDialog (const std::string& extension, bool load ) :
CUIWnd ( UserString ( "GAME_MENU_SAVE_FILES" ),
         ( GG::GUI::GetGUI()->AppWidth() - SAVE_FILE_DIALOG_WIDTH ) / 2,
         ( GG::GUI::GetGUI()->AppHeight() - SAVE_FILE_DIALOG_HEIGHT ) / 2,
         SAVE_FILE_DIALOG_WIDTH,
         SAVE_FILE_DIALOG_HEIGHT,
         GG::INTERACTIVE | GG::DRAGABLE | GG::MODAL | GG::RESIZABLE ) {
    m_extension = extension;
    m_load_only = load;
    boost::shared_ptr<GG::Font> font = ClientUI::GetFont();
    SetMinSize ( GG::Pt ( 2*SAVE_FILE_DIALOG_MIN_WIDTH, 2*SAVE_FILE_DIALOG_MIN_HEIGHT ) );

    m_layout = new GG::Layout ( GG::X0, GG::Y0,
                                SAVE_FILE_DIALOG_WIDTH - LeftBorder() - RightBorder(),
                                SAVE_FILE_DIALOG_HEIGHT - TopBorder() - BottomBorder(), 3, 4 );
    m_layout->SetCellMargin ( SAVE_FILE_CELL_MARGIN );
    m_layout->SetBorderMargin ( SAVE_FILE_CELL_MARGIN*2 );

    m_file_list = new SaveFileListBox();
    m_file_list->SetStyle ( GG::LIST_SINGLESEL | GG::LIST_SORTDESCENDING );
    m_file_list->SetColHeaders ( new SaveFileRow() );


    m_confirm_btn = new CUIButton ( UserString ( "OK" ) );
    CUIButton* cancel_btn = new CUIButton ( UserString ( "CANCEL" ) );

    m_name_edit = new CUIEdit ( GG::X0, GG::Y0, GG::X1, "", font );
    GG::TextControl* filename_label = new GG::TextControl ( GG::X0, GG::Y0, UserString ( "SAVE_FILENAME" ), font, ClientUI::TextColor() );
    GG::TextControl* directory_label = new GG::TextControl ( GG::X0, GG::Y0, UserString ( "SAVE_DIRECTORY" ), font, ClientUI::TextColor() );
    m_current_dir_edit = new CUIEdit ( GG::X0, GG::Y0, GG::X1, PathString ( GetSaveDir() ), font );
    m_browse_dir_btn = new CUIButton ( "..." );

    m_layout->Add ( m_file_list,    0, 0, 1, 4 );
    m_layout->Add ( filename_label, 1, 0, 1, 1 );
    m_layout->Add ( m_name_edit,    1, 1, 1, 2 );
    m_layout->Add ( m_confirm_btn,    1, 3 );
    m_layout->Add ( directory_label,2, 0 );
    m_layout->Add ( m_current_dir_edit,  2, 1 );
    m_layout->Add ( m_browse_dir_btn,    2, 2 );
    m_layout->Add ( cancel_btn,          2, 3 );


    m_layout->SetRowStretch ( 0, 1.0 );
    m_layout->SetMinimumRowHeight ( 1, font->TextExtent ( m_confirm_btn->Text() ).y );
    m_layout->SetMinimumRowHeight ( 2, font->TextExtent ( cancel_btn->Text() ).y );

    m_layout->SetMinimumColumnWidth ( 0, std::max ( font->TextExtent ( filename_label->Text() ).x,
                                      font->TextExtent ( directory_label->Text() ).x ) );
    m_layout->SetColumnStretch ( 1, 1.0 );
    m_layout->SetMinimumColumnWidth ( 2, m_browse_dir_btn->MinUsableSize().x +
                                      SAVE_FILE_BUTTON_MARGIN*2 );
    m_layout->SetMinimumColumnWidth ( 3, std::max ( m_confirm_btn->MinUsableSize().x,
                                      cancel_btn->MinUsableSize().x ) +
                                      SAVE_FILE_BUTTON_MARGIN );

    SetLayout ( m_layout );

    GG::Connect ( m_confirm_btn->LeftClickedSignal,      &SaveFileDialog::Confirm,           this );
    GG::Connect ( cancel_btn->LeftClickedSignal,         &SaveFileDialog::Cancel,            this );
    GG::Connect ( m_file_list->SelChangedSignal,         &SaveFileDialog::SelectionChanged,  this );
    GG::Connect ( m_file_list->DoubleClickedSignal,      &SaveFileDialog::DoubleClickRow,    this );
    GG::Connect ( m_browse_dir_btn->LeftClickedSignal,   &SaveFileDialog::BrowseDirectories, this );
    GG::Connect ( m_name_edit->EditedSignal,             &SaveFileDialog::FileNameEdited,    this );

    UpdatePreviewList();
    
    if(!m_load_only){
        m_name_edit->SetText(std::string("save-") + FilenameTimestamp());
        m_name_edit->SelectAll();
    }
}