예제 #1
0
void LoadGalaxySetupData(const std::string& filename, GalaxySetupData& galaxy_setup_data) {
    SaveGamePreviewData ignored_save_preview_data;

    ScopedTimer timer("LoadGalaxySetupData: " + filename, true);

    try {
        fs::path path = FilenameToPath(filename);
        fs::ifstream ifs(path, std::ios_base::binary);

        if (!ifs)
            throw std::runtime_error(UNABLE_TO_OPEN_FILE);

        try {
            // first attempt binary deserialziation
            freeorion_bin_iarchive ia(ifs);

            ia >> BOOST_SERIALIZATION_NVP(ignored_save_preview_data);
            ia >> BOOST_SERIALIZATION_NVP(galaxy_setup_data);

        } catch(...) {
            // if binary deserialization failed, try more-portable XML deserialization

            // reset to start of stream (attempted binary serialization will have consumed some input...)
            boost::iostreams::seek(ifs, 0, std::ios_base::beg);
            freeorion_xml_iarchive ia(ifs);

            ia >> BOOST_SERIALIZATION_NVP(ignored_save_preview_data);
            ia >> BOOST_SERIALIZATION_NVP(galaxy_setup_data);
        }
        // skipping additional deserialization which is not needed for this function

    } catch(const std::exception& err) {
        ErrorLogger() << "LoadGalaxySetupData(...) failed!  Error: " << err.what();
        return;
    }
}
예제 #2
0
void LoadGame(const std::string& filename, ServerSaveGameData& server_save_game_data,
              std::vector<PlayerSaveGameData>& player_save_game_data, Universe& universe,
              EmpireManager& empire_manager, SpeciesManager& species_manager,
              CombatLogManager& combat_log_manager, GalaxySetupData& galaxy_setup_data)
{
    //boost::this_thread::sleep(boost::posix_time::seconds(1));

    ScopedTimer timer("LoadGame: " + filename, true);

    // player notifications
    if (ServerApp* server = ServerApp::GetApp())
        server->Networking().SendMessage(TurnProgressMessage(Message::LOADING_GAME));

    GetUniverse().EncodingEmpire() = ALL_EMPIRES;

    std::map<int, SaveGameEmpireData>   ignored_save_game_empire_data;
    SaveGamePreviewData                 ignored_save_preview_data;
    std::vector<PlayerSaveHeaderData>   ignored_player_save_header_data;

    empire_manager.Clear();
    universe.Clear();

    try {
        // set up input archive / stream for loading
        const fs::path path = FilenameToPath(filename);
        fs::ifstream ifs(path, std::ios_base::binary);
        if (!ifs)
            throw std::runtime_error(UNABLE_TO_OPEN_FILE);

        try {
            // first attempt binary deserialziation
            freeorion_bin_iarchive ia(ifs);
            DebugLogger() << "Reading binary iarchive";
            ia >> BOOST_SERIALIZATION_NVP(ignored_save_preview_data);
            ia >> BOOST_SERIALIZATION_NVP(galaxy_setup_data);
            ia >> BOOST_SERIALIZATION_NVP(server_save_game_data);
            ia >> BOOST_SERIALIZATION_NVP(ignored_player_save_header_data);
            ia >> BOOST_SERIALIZATION_NVP(ignored_save_game_empire_data);

            ia >> BOOST_SERIALIZATION_NVP(player_save_game_data);
            ia >> BOOST_SERIALIZATION_NVP(empire_manager);
            ia >> BOOST_SERIALIZATION_NVP(species_manager);
            ia >> BOOST_SERIALIZATION_NVP(combat_log_manager);
            Deserialize(ia, universe);
            DebugLogger() << "Done deserializing";
        } catch (...) {
            // if binary deserialization failed, try more-portable XML deserialization

            // reset to start of stream (attempted binary serialization will have consumed some input...)
            boost::iostreams::seek(ifs, 0, std::ios_base::beg);

            // allocate buffers for serialized gamestate
            DebugLogger() << "Allocating buffers for XML deserialization...";
            std::string serial_str, compressed_str;
            try {
                serial_str.reserve(    std::pow(2.0, 29.0));
                compressed_str.reserve(std::pow(2.0, 26.0));
            } catch (...) {
                DebugLogger() << "Unable to preallocate full deserialization buffers. Attempting deserialization with dynamic buffer allocation.";
            }

            // create archive with (preallocated) buffer...
            freeorion_xml_iarchive xia(ifs);
            // read from save file: uncompressed header serialized data, with compressed main archive string at end...
            // deserialize uncompressed save header info
            xia >> BOOST_SERIALIZATION_NVP(ignored_save_preview_data);
            xia >> BOOST_SERIALIZATION_NVP(galaxy_setup_data);
            xia >> BOOST_SERIALIZATION_NVP(server_save_game_data);
            xia >> BOOST_SERIALIZATION_NVP(ignored_player_save_header_data);
            xia >> BOOST_SERIALIZATION_NVP(ignored_save_game_empire_data);
            // extract compressed gamestate info
            xia >> BOOST_SERIALIZATION_NVP(compressed_str);

            // wrap compressed string in iostream::stream to extract compressed data
            typedef boost::iostreams::basic_array_source<char> SourceDevice;
            SourceDevice compressed_source(compressed_str.data(), compressed_str.size());
            boost::iostreams::stream<SourceDevice> c_source(compressed_source);

            // wrap uncompressed buffer string in iostream::stream to receive decompressed string
            typedef boost::iostreams::back_insert_device<std::string> InsertDevice;
            InsertDevice serial_inserter(serial_str);
            boost::iostreams::stream<InsertDevice> s_sink(serial_inserter);

            // set up filter to decompress data
            boost::iostreams::filtering_istreambuf i;
            i.push(boost::iostreams::zlib_decompressor());
            i.push(c_source);
            boost::iostreams::copy(i, s_sink);
            s_sink.flush();

            // wrap uncompressed buffer string in iostream::stream to extract decompressed string
            SourceDevice serial_source(serial_str.data(), serial_str.size());
            boost::iostreams::stream<SourceDevice> s_source(serial_source);

            // create archive with (preallocated) buffer...
            freeorion_xml_iarchive xia2(s_source);
            // deserialize main gamestate info
            xia2 >> BOOST_SERIALIZATION_NVP(player_save_game_data);
            xia2 >> BOOST_SERIALIZATION_NVP(empire_manager);
            xia2 >> BOOST_SERIALIZATION_NVP(species_manager);
            xia2 >> BOOST_SERIALIZATION_NVP(combat_log_manager);
            Deserialize(xia2, universe);
        }

    } catch (const std::exception& err) {
        ErrorLogger() << "LoadGame(...) failed!  Error: " << err.what();
        return;
    }
    DebugLogger() << "LoadGame : Successfully loaded save file";
}
예제 #3
0
void SaveGame(const std::string& filename, const ServerSaveGameData& server_save_game_data,
              const std::vector<PlayerSaveGameData>& player_save_game_data, const Universe& universe,
              const EmpireManager& empire_manager, const SpeciesManager& species_manager,
              const CombatLogManager& combat_log_manager, const GalaxySetupData& galaxy_setup_data,
              bool multiplayer)
{
    ScopedTimer timer("SaveGame: " + filename, true);

    bool use_binary = GetOptionsDB().Get<bool>("binary-serialization");
    DebugLogger() << "SaveGame(" << (use_binary ? "binary" : "zlib-xml") << ") filename: " << filename;
    GetUniverse().EncodingEmpire() = ALL_EMPIRES;

    DebugLogger() << "Compiling save empire and preview data";
    std::map<int, SaveGameEmpireData> empire_save_game_data = CompileSaveGameEmpireData(empire_manager);
    SaveGamePreviewData save_preview_data;
    CompileSaveGamePreviewData(server_save_game_data, player_save_game_data, empire_save_game_data, save_preview_data);


    // reinterpret save game data as header data for uncompressed header
    std::vector<PlayerSaveHeaderData> player_save_header_data;
    for (std::vector<PlayerSaveGameData>::const_iterator it = player_save_game_data.begin();
            it != player_save_game_data.end(); ++it)
    {
        player_save_header_data.push_back(*it);
    }


    try {
        fs::path path = FilenameToPath(filename);
        // A relative path should be relative to the save directory.
        if (path.is_relative()) {
            path = GetSaveDir()/path;
            DebugLogger() << "Made save path relative to save dir. Is now: " << path;
        }

        if (multiplayer) {
            // Make sure the path points into our save directory
            if (!IsInside(path, GetSaveDir())) {
                path = GetSaveDir() / path.filename();
            }
        }

        // set up output archive / stream for saving
        fs::ofstream ofs(path, std::ios_base::binary);
        if (!ofs)
            throw std::runtime_error(UNABLE_TO_OPEN_FILE);

        if (use_binary) {
            DebugLogger() << "Creating binary oarchive";
            freeorion_bin_oarchive boa(ofs);
            boa << BOOST_SERIALIZATION_NVP(save_preview_data);
            boa << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
            boa << BOOST_SERIALIZATION_NVP(server_save_game_data);
            boa << BOOST_SERIALIZATION_NVP(player_save_header_data);
            boa << BOOST_SERIALIZATION_NVP(empire_save_game_data);

            boa << BOOST_SERIALIZATION_NVP(player_save_game_data);
            boa << BOOST_SERIALIZATION_NVP(empire_manager);
            boa << BOOST_SERIALIZATION_NVP(species_manager);
            boa << BOOST_SERIALIZATION_NVP(combat_log_manager);
            Serialize(boa, universe);
            DebugLogger() << "Done serializing";

        } else {
            // Two-tier serialization:
            // main archive is uncompressed serialized header data first
            // then contains a string for compressed second archive
            // that contains the main gamestate info


            // allocate buffers for serialized gamestate
            DebugLogger() << "Allocating buffers for XML serialization...";
            std::string serial_str, compressed_str;
            try {
                serial_str.reserve(    std::pow(2.0, 29.0));
                compressed_str.reserve(std::pow(2.0, 26.0));
            } catch (...) {
                DebugLogger() << "Unable to preallocate full serialization buffers. Attempting serialization with dynamic buffer allocation.";
            }

            // wrap buffer string in iostream::stream to receive serialized data
            typedef boost::iostreams::back_insert_device<std::string> InsertDevice;
            InsertDevice serial_inserter(serial_str);
            boost::iostreams::stream<InsertDevice> s_sink(serial_inserter);

            // create archive with (preallocated) buffer...
            freeorion_xml_oarchive xoa(s_sink);
            // serialize main gamestate info
            xoa << BOOST_SERIALIZATION_NVP(player_save_game_data);
            xoa << BOOST_SERIALIZATION_NVP(empire_manager);
            xoa << BOOST_SERIALIZATION_NVP(species_manager);
            xoa << BOOST_SERIALIZATION_NVP(combat_log_manager);
            Serialize(xoa, universe);
            s_sink.flush();

            // wrap gamestate string in iostream::stream to extract serialized data
            typedef boost::iostreams::basic_array_source<char> SourceDevice;
            SourceDevice source(serial_str.data(), serial_str.size());
            boost::iostreams::stream<SourceDevice> s_source(source);

            // wrap compresed buffer string in iostream::streams to receive compressed string
            InsertDevice compressed_inserter(compressed_str);
            boost::iostreams::stream<InsertDevice> c_sink(compressed_inserter);

            // compression-filter gamestate into compressed string
            boost::iostreams::filtering_ostreambuf o;
            o.push(boost::iostreams::zlib_compressor());
            o.push(c_sink);
            boost::iostreams::copy(s_source, o);
            c_sink.flush();

            // write to save file: uncompressed header serialized data, with compressed main archive string at end...
            freeorion_xml_oarchive xoa2(ofs);
            // serialize uncompressed save header info
            xoa2 << BOOST_SERIALIZATION_NVP(save_preview_data);
            xoa2 << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
            xoa2 << BOOST_SERIALIZATION_NVP(server_save_game_data);
            xoa2 << BOOST_SERIALIZATION_NVP(player_save_header_data);
            xoa2 << BOOST_SERIALIZATION_NVP(empire_save_game_data);
            // append compressed gamestate info
            xoa2 << BOOST_SERIALIZATION_NVP(compressed_str);
        }

    } catch (const std::exception& e) {
        ErrorLogger() << UserString("UNABLE_TO_WRITE_SAVE_FILE") << " SaveGame exception: " << ": " << e.what();
        throw e;
    }
    DebugLogger() << "SaveGame : Successfully wrote save file";
}
예제 #4
0
void HumanClientApp::LoadSinglePlayerGame(std::string filename/* = ""*/) {
    DebugLogger() << "HumanClientApp::LoadSinglePlayerGame";

    if (!filename.empty()) {
        if (!exists(FilenameToPath(filename))) {
            std::string msg = "HumanClientApp::LoadSinglePlayerGame() given a nonexistent file \""
                            + filename + "\" to load; aborting.";
            DebugLogger() << msg;
            std::cerr << msg << '\n';
            abort();
        }
    } else {
        try {
            SaveFileDialog sfd(SP_SAVE_FILE_EXTENSION, true);
            sfd.Run();
            if (!sfd.Result().empty())
                filename = sfd.Result();
        } catch (const std::exception& e) {
            ClientUI::MessageBox(e.what(), true);
        }
    }

    if (filename.empty()) {
        DebugLogger() << "HumanClientApp::LoadSinglePlayerGame has empty filename. Aborting load.";
        return;
    }

    // end any currently-playing game before loading new one
    if (m_game_started) {
        EndGame();
        // delay to make sure old game is fully cleaned up before attempting to start a new one
        boost::this_thread::sleep(boost::posix_time::seconds(3));
    } else {
        DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() not already in a game, so don't need to end it";
    }

    if (!GetOptionsDB().Get<bool>("force-external-server")) {
        DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() Starting server";
        StartServer();
        DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() Server started";
    } else {
        DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() assuming external server will be available";
    }

    DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() Connecting to server";
    unsigned int start_time = Ticks();
    while (!m_networking.ConnectToLocalHostServer()) {
        if (SERVER_CONNECT_TIMEOUT < Ticks() - start_time) {
            ErrorLogger() << "HumanClientApp::LoadSinglePlayerGame() server connecting timed out";
            ClientUI::MessageBox(UserString("ERR_CONNECT_TIMED_OUT"), true);
            KillServer();
            return;
        }
    }

    DebugLogger() << "HumanClientApp::LoadSinglePlayerGame() Connected to server";

    m_connected = true;
    m_networking.SetPlayerID(Networking::INVALID_PLAYER_ID);
    m_networking.SetHostPlayerID(Networking::INVALID_PLAYER_ID);
    SetEmpireID(ALL_EMPIRES);

    SinglePlayerSetupData setup_data;
    // leving GalaxySetupData information default / blank : not used when loading a game
    setup_data.m_new_game = false;
    setup_data.m_filename = filename;
    // leving setup_data.m_players empty : not specified when loading a game, as server will generate from save file


    m_networking.SendMessage(HostSPGameMessage(setup_data));
    m_fsm->process_event(HostSPGameRequested());
}
예제 #5
0
void SaveGame(const std::string& filename, const ServerSaveGameData& server_save_game_data,
              const std::vector<PlayerSaveGameData>& player_save_game_data,
              const Universe& universe, const EmpireManager& empire_manager,
              const SpeciesManager& species_manager, const CombatLogManager& combat_log_manager,
              const GalaxySetupData& galaxy_setup_data, bool multiplayer)
{
    DebugLogger() << "SaveGame:: filename: " << filename;
    GetUniverse().EncodingEmpire() = ALL_EMPIRES;

    std::map<int, SaveGameEmpireData> empire_save_game_data = CompileSaveGameEmpireData(empire_manager);
    SaveGamePreviewData save_preview_data;
    CompileSaveGamePreviewData(server_save_game_data, player_save_game_data, empire_save_game_data, save_preview_data);

    try {
        fs::path path = FilenameToPath(filename);
        // A relative path should be relative to the save directory.
        if (path.is_relative()) {
            path = GetSaveDir()/path;
            DebugLogger() << "Made save path relative to save dir. Is now: " << path;
        }

        if (multiplayer) {
            // Make sure the path points into our save directory
            if (!IsInside(path, GetSaveDir())){
                path = GetSaveDir() / path.filename();
            }
        }

        fs::ofstream ofs(path, std::ios_base::binary);

        if (!ofs)
            throw std::runtime_error(UNABLE_TO_OPEN_FILE);

        if (GetOptionsDB().Get<bool>("binary-serialization")) {
            freeorion_bin_oarchive oa(ofs);
            oa << BOOST_SERIALIZATION_NVP(save_preview_data);
            oa << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
            oa << BOOST_SERIALIZATION_NVP(server_save_game_data);
            oa << BOOST_SERIALIZATION_NVP(player_save_game_data);
            oa << BOOST_SERIALIZATION_NVP(empire_save_game_data);
            oa << BOOST_SERIALIZATION_NVP(empire_manager);
            oa << BOOST_SERIALIZATION_NVP(species_manager);
            oa << BOOST_SERIALIZATION_NVP(combat_log_manager);
            Serialize(oa, universe);
        } else {
            freeorion_xml_oarchive oa(ofs);
            oa << BOOST_SERIALIZATION_NVP(save_preview_data);
            oa << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
            oa << BOOST_SERIALIZATION_NVP(server_save_game_data);
            oa << BOOST_SERIALIZATION_NVP(player_save_game_data);
            oa << BOOST_SERIALIZATION_NVP(empire_save_game_data);
            oa << BOOST_SERIALIZATION_NVP(empire_manager);
            oa << BOOST_SERIALIZATION_NVP(species_manager);
            oa << BOOST_SERIALIZATION_NVP(combat_log_manager);
            Serialize(oa, universe);
        }
    } catch (const std::exception& e) {
        ErrorLogger() << UserString("UNABLE_TO_WRITE_SAVE_FILE") << " SaveGame exception: " << ": " << e.what();
        throw e;
    }
}
예제 #6
0
void LoadGame(const std::string& filename, ServerSaveGameData& server_save_game_data,
              std::vector<PlayerSaveGameData>& player_save_game_data,
              Universe& universe, EmpireManager& empire_manager,
              SpeciesManager& species_manager, CombatLogManager& combat_log_manager,
              GalaxySetupData& galaxy_setup_data, bool alternate_serialization)
{
    //boost::this_thread::sleep(boost::posix_time::seconds(5));
    bool use_binary = GetOptionsDB().Get<bool>("binary-serialization") ^ alternate_serialization;

    // player notifications
    if (ServerApp* server = ServerApp::GetApp())
        server->Networking().SendMessage(TurnProgressMessage(Message::LOADING_GAME));

    GetUniverse().EncodingEmpire() = ALL_EMPIRES;

    std::map<int, SaveGameEmpireData> ignored_save_game_empire_data;
    SaveGamePreviewData ignored_save_preview_data;

    empire_manager.Clear();
    universe.Clear();

    try {
        const fs::path path = FilenameToPath(filename);
        fs::ifstream ifs(path, std::ios_base::binary);

        if (!ifs)
            throw std::runtime_error(UNABLE_TO_OPEN_FILE);
        if (use_binary) {
            freeorion_bin_iarchive ia(ifs);
            DebugLogger() << "LoadGame : Passing Preview Data";
            ia >> BOOST_SERIALIZATION_NVP(ignored_save_preview_data);

            DebugLogger() << "LoadGame : Reading Galaxy Setup Data";
            ia >> BOOST_SERIALIZATION_NVP(galaxy_setup_data);

            DebugLogger() << "LoadGame : Reading Server Save Game Data";
            ia >> BOOST_SERIALIZATION_NVP(server_save_game_data);
            DebugLogger() << "LoadGame : Reading Player Save Game Data";
            ia >> BOOST_SERIALIZATION_NVP(player_save_game_data);

            DebugLogger() << "LoadGame : Reading Empire Save Game Data (Ignored)";
            ia >> BOOST_SERIALIZATION_NVP(ignored_save_game_empire_data);
            DebugLogger() << "LoadGame : Reading Empires Data";
            ia >> BOOST_SERIALIZATION_NVP(empire_manager);
            DebugLogger() << "LoadGame : Reading Species Data";
            ia >> BOOST_SERIALIZATION_NVP(species_manager);
            DebugLogger() << "LoadGame : Reading Combat Logs";
            ia >> BOOST_SERIALIZATION_NVP(combat_log_manager);
            DebugLogger() << "LoadGame : Reading Universe Data";
            Deserialize(ia, universe);
        } else {
            freeorion_xml_iarchive ia(ifs);
            DebugLogger() << "LoadGame : Passing Preview Data";
            ia >> BOOST_SERIALIZATION_NVP(ignored_save_preview_data);

            DebugLogger() << "LoadGame : Reading Galaxy Setup Data";
            ia >> BOOST_SERIALIZATION_NVP(galaxy_setup_data);

            DebugLogger() << "LoadGame : Reading Server Save Game Data";
            ia >> BOOST_SERIALIZATION_NVP(server_save_game_data);
            DebugLogger() << "LoadGame : Reading Player Save Game Data";
            ia >> BOOST_SERIALIZATION_NVP(player_save_game_data);

            DebugLogger() << "LoadGame : Reading Empire Save Game Data (Ignored)";
            ia >> BOOST_SERIALIZATION_NVP(ignored_save_game_empire_data);
            DebugLogger() << "LoadGame : Reading Empires Data";
            ia >> BOOST_SERIALIZATION_NVP(empire_manager);
            DebugLogger() << "LoadGame : Reading Species Data";
            ia >> BOOST_SERIALIZATION_NVP(species_manager);
            DebugLogger() << "LoadGame : Reading Combat Logs";
            ia >> BOOST_SERIALIZATION_NVP(combat_log_manager);
            DebugLogger() << "LoadGame : Reading Universe Data";
            Deserialize(ia, universe);
        }
    } catch (const std::exception& e) {