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

Move gamestatus.cpp::load_game to savegame.cpp.
This commit is contained in:
Jörg Hinrichs 2009-04-12 21:03:10 +00:00
parent e9181d3ad5
commit 9fabc334cb
3 changed files with 134 additions and 95 deletions

View File

@ -24,6 +24,7 @@
#include "log.hpp"
#include "game_preferences.hpp"
#include "replay.hpp"
#include "savegame.hpp" //FIXME: only because of replace_space2underbar
#include "statistics.hpp"
#include "unit_id.hpp"
#include "wesconfig.h"
@ -42,77 +43,9 @@
#define ERR_NG lg::err(lg::engine)
#ifdef _WIN32
#include <windows.h>
static void write_player(const player_info& player, config& cfg);
/**
* conv_ansi_utf8()
* - Convert a string between ANSI encoding (for Windows filename) and UTF-8
* string &name
* - filename to be converted
* bool a2u
* - if true, convert the string from ANSI to UTF-8.
* - if false, reverse. (convert it from UTF-8 to ANSI)
*/
void conv_ansi_utf8(std::string &name, bool a2u) {
int wlen = MultiByteToWideChar(a2u ? CP_ACP : CP_UTF8, 0,
name.c_str(), -1, NULL, 0);
if (wlen == 0) return;
WCHAR *wc = new WCHAR[wlen];
if (wc == NULL) return;
if (MultiByteToWideChar(a2u ? CP_ACP : CP_UTF8, 0, name.c_str(), -1,
wc, wlen) == 0) {
delete wc;
return;
}
int alen = WideCharToMultiByte(!a2u ? CP_ACP : CP_UTF8, 0, wc, wlen,
NULL, 0, NULL, NULL);
if (alen == 0) {
delete wc;
return;
}
CHAR *ac = new CHAR[alen];
if (ac == NULL) {
delete wc;
return;
}
WideCharToMultiByte(!a2u ? CP_ACP : CP_UTF8, 0, wc, wlen,
ac, alen, NULL, NULL);
delete wc;
if (ac == NULL) {
return;
}
name = ac;
delete ac;
return;
}
void replace_underbar2space(std::string &name) {
LOG_NG << "conv(A2U)-from:[" << name << "]" << std::endl;
conv_ansi_utf8(name, true);
LOG_NG << "conv(A2U)-to:[" << name << "]" << std::endl;
LOG_NG << "replace_underbar2space-from:[" << name << "]" << std::endl;
std::replace(name.begin(), name.end(), '_', ' ');
LOG_NG << "replace_underbar2space-to:[" << name << "]" << std::endl;
}
static void replace_space2underbar(std::string &name) {
LOG_NG << "conv(U2A)-from:[" << name << "]" << std::endl;
conv_ansi_utf8(name, false);
LOG_NG << "conv(U2A)-to:[" << name << "]" << std::endl;
LOG_NG << "replace_underbar2space-from:[" << name << "]" << std::endl;
std::replace(name.begin(), name.end(), ' ', '_');
LOG_NG << "replace_underbar2space-to:[" << name << "]" << std::endl;
}
#else /* ! _WIN32 */
void replace_underbar2space(std::string &name) {
std::replace(name.begin(),name.end(),'_',' ');
}
static void replace_space2underbar(std::string &name) {
std::replace(name.begin(),name.end(),' ','_');
}
#endif /* _WIN32 */
static void extract_summary_from_config(config& cfg_save, config& cfg_summary);
@ -757,31 +690,6 @@ void read_save_file(const std::string& name, config& cfg, std::string* error_log
}
}
static void copy_era(config &cfg)
{
const config &replay_start = cfg.child("replay_start");
if (!replay_start) return;
const config &era = replay_start.child("era");
if (!era) return;
config &snapshot = cfg.child("snapshot");
if (!snapshot) return;
snapshot.add_child("era", era);
}
void load_game(const std::string& name, game_state& gamestate, std::string* error_log)
{
log_scope("load_game");
config cfg;
read_save_file(name,cfg,error_log);
copy_era(cfg);
gamestate = game_state(cfg);
}
void load_game_summary(const std::string& name, config& cfg_summary, std::string* error_log){
log_scope("load_game_summary");

View File

@ -23,16 +23,90 @@
#include "log.hpp"
#include "map.hpp"
#include "map_label.hpp"
#include "unit_id.hpp"
#include "preferences_display.hpp"
#include "replay.hpp"
#include "serialization/binary_or_text.hpp"
#include "serialization/parser.hpp"
#include "sound.hpp"
#include "statistics.hpp"
#include "unit_id.hpp"
#include "version.hpp"
#define LOG_SAVE LOG_STREAM(info, engine)
#ifdef _WIN32
#include <windows.h>
/**
* conv_ansi_utf8()
* - Convert a string between ANSI encoding (for Windows filename) and UTF-8
* string &name
* - filename to be converted
* bool a2u
* - if true, convert the string from ANSI to UTF-8.
* - if false, reverse. (convert it from UTF-8 to ANSI)
*/
/*
void conv_ansi_utf8(std::string &name, bool a2u) {
int wlen = MultiByteToWideChar(a2u ? CP_ACP : CP_UTF8, 0,
name.c_str(), -1, NULL, 0);
if (wlen == 0) return;
WCHAR *wc = new WCHAR[wlen];
if (wc == NULL) return;
if (MultiByteToWideChar(a2u ? CP_ACP : CP_UTF8, 0, name.c_str(), -1,
wc, wlen) == 0) {
delete wc;
return;
}
int alen = WideCharToMultiByte(!a2u ? CP_ACP : CP_UTF8, 0, wc, wlen,
NULL, 0, NULL, NULL);
if (alen == 0) {
delete wc;
return;
}
CHAR *ac = new CHAR[alen];
if (ac == NULL) {
delete wc;
return;
}
WideCharToMultiByte(!a2u ? CP_ACP : CP_UTF8, 0, wc, wlen,
ac, alen, NULL, NULL);
delete wc;
if (ac == NULL) {
return;
}
name = ac;
delete ac;
return;
}
void replace_underbar2space(std::string &name) {
LOG_SAVE << "conv(A2U)-from:[" << name << "]" << std::endl;
conv_ansi_utf8(name, true);
LOG_SAVE << "conv(A2U)-to:[" << name << "]" << std::endl;
LOG_SAVE << "replace_underbar2space-from:[" << name << "]" << std::endl;
std::replace(name.begin(), name.end(), '_', ' ');
LOG_SAVE << "replace_underbar2space-to:[" << name << "]" << std::endl;
}
void replace_space2underbar(std::string &name) {
LOG_SAVE << "conv(U2A)-from:[" << name << "]" << std::endl;
conv_ansi_utf8(name, false);
LOG_SAVE << "conv(U2A)-to:[" << name << "]" << std::endl;
LOG_SAVE << "replace_underbar2space-from:[" << name << "]" << std::endl;
std::replace(name.begin(), name.end(), ' ', '_');
LOG_SAVE << "replace_underbar2space-to:[" << name << "]" << std::endl;
}
#else /* ! _WIN32 */
void replace_underbar2space(std::string &name) {
std::replace(name.begin(),name.end(),'_',' ');
}
void replace_space2underbar(std::string &name) {
std::replace(name.begin(),name.end(),' ','_');
}
#endif /* _WIN32 */
loadgame::loadgame(display& gui, const config& game_config, game_state& gamestate)
: game_config_(game_config)
, gui_(gui)
@ -108,6 +182,35 @@ void loadgame::load_game(std::string& filename, bool show_replay, bool cancel_or
}
void loadgame::read_save_file(const std::string& name, config& cfg, std::string* error_log)
{
std::string modified_name = name;
::replace_space2underbar(modified_name);
// Try reading the file both with and without underscores
scoped_istream file_stream = istream_file(get_saves_dir() + "/" + modified_name);
if (file_stream->fail())
file_stream = istream_file(get_saves_dir() + "/" + name);
cfg.clear();
try{
if(is_gzip_file(name)) {
read_gz(cfg, *file_stream, error_log);
} else {
detect_format_and_read(cfg, *file_stream, error_log);
}
} catch (config::error &err)
{
LOG_SAVE << err.message;
throw game::load_game_failed();
}
if(cfg.empty()) {
LOG_SAVE << "Could not parse file data into config\n";
throw game::load_game_failed();
}
}
void loadgame::check_version_compatibility()
{
// do not load if too old, if either the savegame or the current game
@ -152,7 +255,12 @@ void loadgame::load_multiplayer_game()
std::string error_log;
{
cursor::setter cur(cursor::WAIT);
::load_game(filename_, gamestate_, &error_log);
log_scope("load_game");
read_save_file(filename_, load_config_, &error_log);
copy_era(load_config_);
gamestate_ = game_state(load_config_);
}
if(!error_log.empty()) {
@ -172,6 +280,20 @@ void loadgame::load_multiplayer_game()
check_version_compatibility();
}
void loadgame::copy_era(config &cfg)
{
const config &replay_start = cfg.child("replay_start");
if (!replay_start) return;
const config &era = replay_start.child("era");
if (!era) return;
config &snapshot = cfg.child("snapshot");
if (!snapshot) return;
snapshot.add_child("era", era);
}
savegame::savegame(game_state& gamestate, const std::string title)
: gamestate_(gamestate)
, snapshot_()

View File

@ -43,7 +43,9 @@ public:
private:
void show_dialog(bool show_replay, bool cancel_orders);
void read_save_file(const std::string& name, config& cfg, std::string* error_log);
void check_version_compatibility();
void copy_era(config& cfg);
const config& game_config_;
display& gui_;
@ -189,4 +191,11 @@ private:
virtual void before_save();
};
#ifdef _WIN32
void conv_ansi_utf8(std::string &name, bool a2u);
#endif
void replace_underbar2space(std::string &name);
void replace_space2underbar(std::string &name);
#endif