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; } }
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"; }
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"; }
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()); }
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; } }
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) {