Savegame reorganization Step 1: a simpler interface to saving and loading.

Move finish_save_game and extract_summary_data_from_save to savegame.cpp.
This commit is contained in:
Jörg Hinrichs 2009-04-07 21:44:34 +00:00
parent a3757e256f
commit 99f4bbd384
4 changed files with 106 additions and 107 deletions

View file

@ -116,7 +116,6 @@ static void replace_space2underbar(std::string &name) {
#endif /* _WIN32 */
static void extract_summary_from_config(config& cfg_save, config& cfg_summary);
static void extract_summary_data_from_save(const game_state& gamestate, config& out);
player_info* game_state::get_player(const std::string& id) {
std::map< std::string, player_info >::iterator found = players.find(id);
@ -857,27 +856,6 @@ scoped_ostream open_save_game(const std::string &label)
}
}
void finish_save_game(config_writer &out, const game_state& gamestate, const std::string &label)
{
std::string name = label;
std::replace(name.begin(),name.end(),' ','_');
std::string fname(get_saves_dir() + "/" + name);
try {
if(!out.good()) {
throw game::save_game_failed(_("Could not write to file"));
}
config& summary = save_summary(label);
extract_summary_data_from_save(gamestate,summary);
const int mod_time = static_cast<int>(file_create_time(fname));
summary["mod_time"] = str_cast(mod_time);
write_save_index();
} catch(io_exception& e) {
throw game::save_game_failed(e.what());
}
}
namespace {
bool save_index_loaded = false;
config save_index_cfg;
@ -933,83 +911,6 @@ void write_save_index()
}
}
void extract_summary_data_from_save(const game_state& gamestate, config& out)
{
const bool has_replay = gamestate.replay_data.empty() == false;
const bool has_snapshot = gamestate.snapshot.child("side");
out["replay"] = has_replay ? "yes" : "no";
out["snapshot"] = has_snapshot ? "yes" : "no";
out["label"] = gamestate.label;
out["campaign"] = gamestate.campaign;
out["campaign_type"] = gamestate.campaign_type;
out["scenario"] = gamestate.scenario;
out["difficulty"] = gamestate.difficulty;
out["version"] = gamestate.version;
out["corrupt"] = "";
if(has_snapshot) {
out["turn"] = gamestate.snapshot["turn_at"];
if(gamestate.snapshot["turns"] != "-1") {
out["turn"] = out["turn"].str() + "/" + gamestate.snapshot["turns"].str();
}
}
// Find the first human leader so we can display their icon in the load menu.
/** @todo Ideally we should grab all leaders if there's more than 1 human player? */
std::string leader;
for(std::map<std::string, player_info>::const_iterator p = gamestate.players.begin();
p!=gamestate.players.end(); ++p) {
for(std::vector<unit>::const_iterator u = p->second.available_units.begin(); u != p->second.available_units.end(); ++u) {
if(u->can_recruit()) {
leader = u->type_id();
}
}
}
bool shrouded = false;
if(leader == "") {
const config& snapshot = has_snapshot ? gamestate.snapshot : gamestate.starting_pos;
foreach (const config &side, snapshot.child_range("side"))
{
if (side["controller"] != "human") {
continue;
}
if (utils::string_bool(side["shroud"])) {
shrouded = true;
}
foreach (const config &u, side.child_range("unit"))
{
if (utils::string_bool(u["canrecruit"], false)) {
leader = u["id"];
break;
}
}
}
}
out["leader"] = leader;
out["map_data"] = "";
if(!shrouded) {
if(has_snapshot) {
if (!gamestate.snapshot.find_child("side", "shroud", "yes")) {
out["map_data"] = gamestate.snapshot["map_data"];
}
} else if(has_replay) {
if (!gamestate.starting_pos.find_child("side", "shroud", "yes")) {
out["map_data"] = gamestate.starting_pos["map_data"];
}
}
}
}
void extract_summary_from_config(config& cfg_save, config& cfg_summary)
{
const config &cfg_snapshot = cfg_save.child("snapshot");

View file

@ -327,7 +327,6 @@ bool save_game_exists(const std::string & name);
/** Throws game::save_game_failed. */
scoped_ostream open_save_game(const std::string &label);
void finish_save_game(config_writer &out, const game_state& gamestate, const std::string &label);
/** Load/Save games. */
void load_game(const std::string& name, game_state& gamestate, std::string* error_log);

View file

@ -16,6 +16,7 @@
#include "savegame.hpp"
#include "dialogs.hpp" //FIXME: move illegal file character function here and get rid of this include
#include "foreach.hpp"
#include "game_end_exceptions.hpp"
#include "game_events.hpp"
#include "gettext.hpp"
@ -145,7 +146,7 @@ void savegame::save_game_internal(const std::string& filename)
{
config_writer out(ss, preferences::compress_saves());
::write_game(out, snapshot_, gamestate_);
finish_save_game(out, gamestate_, gamestate_.label);
finish_save_game(out);
}
scoped_ostream os(open_save_game(filename_));
(*os) << ss.str();
@ -155,6 +156,104 @@ void savegame::save_game_internal(const std::string& filename)
}
}
void savegame::finish_save_game(config_writer &out)
{
std::string name = gamestate_.label;
std::replace(name.begin(),name.end(),' ','_');
std::string fname(get_saves_dir() + "/" + name);
try {
if(!out.good()) {
throw game::save_game_failed(_("Could not write to file"));
}
config& summary = save_summary(gamestate_.label);
extract_summary_data_from_save(summary);
const int mod_time = static_cast<int>(file_create_time(fname));
summary["mod_time"] = str_cast(mod_time);
write_save_index();
} catch(io_exception& e) {
throw game::save_game_failed(e.what());
}
}
void savegame::extract_summary_data_from_save(config& out)
{
const bool has_replay = gamestate_.replay_data.empty() == false;
const bool has_snapshot = gamestate_.snapshot.child("side");
out["replay"] = has_replay ? "yes" : "no";
out["snapshot"] = has_snapshot ? "yes" : "no";
out["label"] = gamestate_.label;
out["campaign"] = gamestate_.campaign;
out["campaign_type"] = gamestate_.campaign_type;
out["scenario"] = gamestate_.scenario;
out["difficulty"] = gamestate_.difficulty;
out["version"] = gamestate_.version;
out["corrupt"] = "";
if(has_snapshot) {
out["turn"] = gamestate_.snapshot["turn_at"];
if(gamestate_.snapshot["turns"] != "-1") {
out["turn"] = out["turn"].str() + "/" + gamestate_.snapshot["turns"].str();
}
}
// Find the first human leader so we can display their icon in the load menu.
/** @todo Ideally we should grab all leaders if there's more than 1 human player? */
std::string leader;
for(std::map<std::string, player_info>::const_iterator p = gamestate_.players.begin();
p!=gamestate_.players.end(); ++p) {
for(std::vector<unit>::const_iterator u = p->second.available_units.begin(); u != p->second.available_units.end(); ++u) {
if(u->can_recruit()) {
leader = u->type_id();
}
}
}
bool shrouded = false;
if(leader == "") {
const config& snapshot = has_snapshot ? gamestate_.snapshot : gamestate_.starting_pos;
foreach (const config &side, snapshot.child_range("side"))
{
if (side["controller"] != "human") {
continue;
}
if (utils::string_bool(side["shroud"])) {
shrouded = true;
}
foreach (const config &u, side.child_range("unit"))
{
if (utils::string_bool(u["canrecruit"], false)) {
leader = u["id"];
break;
}
}
}
}
out["leader"] = leader;
out["map_data"] = "";
if(!shrouded) {
if(has_snapshot) {
if (!gamestate_.snapshot.find_child("side", "shroud", "yes")) {
out["map_data"] = gamestate_.snapshot["map_data"];
}
} else if(has_replay) {
if (!gamestate_.starting_pos.find_child("side", "shroud", "yes")) {
out["map_data"] = gamestate_.starting_pos["map_data"];
}
}
}
}
void savegame::set_filename(std::string filename)
{
filename.erase(std::remove_if(filename.begin(), filename.end(),

View file

@ -100,20 +100,20 @@ private:
data manipulation has to happen before calling this method */
void save_game_internal(const std::string& filename);
void finish_save_game(config_writer &out);
void extract_summary_data_from_save(config& out);
game_state& gamestate_;
/** Gamestate information at the time of saving. Note that this object is needed here, since
even if it is empty the code relies on it to be there. */
config snapshot_;
/** Filename of the savegame file on disk */
std::string filename_;
std::string filename_; /** Filename of the savegame file on disk */
/** Title of the savegame dialog */
const std::string title_;
const std::string title_; /** Title of the savegame dialog */
/** Error message to be displayed if the savefile could not be generated. */
std::string error_message_;
std::string error_message_; /** Error message to be displayed if the savefile could not be generated. */
/** Determines if the save is done interactively or not. This controls if a filename is
generated automatically (interactive = false) and if a message is displayed that the