X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fsupertux%2Fsavegame.cpp;h=f6f456a03fc1b6fd84b3334e80a31a5f9c2af5e8;hb=05d168f5e5bbd46e44b1b1ad857d2d8c59b230c1;hp=ba2670cdf71486b2577b06ad08d809b7c416af45;hpb=c161b88a74b82d755866b5a0294f1a3aaa41d55d;p=supertux.git diff --git a/src/supertux/savegame.cpp b/src/supertux/savegame.cpp index ba2670cdf..f6f456a03 100644 --- a/src/supertux/savegame.cpp +++ b/src/supertux/savegame.cpp @@ -17,13 +17,15 @@ #include "supertux/savegame.hpp" +#include + #include "lisp/lisp.hpp" #include "lisp/parser.hpp" #include "lisp/writer.hpp" #include "physfs/ifile_streambuf.hpp" +#include "scripting/scripting.hpp" #include "scripting/serialize.hpp" #include "scripting/squirrel_util.hpp" -#include "scripting/squirrel_util.hpp" #include "supertux/player_status.hpp" #include "util/file_system.hpp" #include "util/log.hpp" @@ -41,7 +43,29 @@ void get_table_entry(HSQUIRRELVM vm, const std::string& name) else { // successfully placed result on stack - } + } +} + +void get_or_create_table_entry(HSQUIRRELVM vm, const std::string& name) +{ + sq_pushstring(vm, name.c_str(), -1); + if(SQ_FAILED(sq_get(vm, -2))) + { + sq_pushstring(vm, name.c_str(), -1); + sq_newtable(vm); + if(SQ_FAILED(sq_createslot(vm, -3))) + { + throw std::runtime_error("failed to create '" + name + "' table entry"); + } + else + { + get_table_entry(vm, name); + } + } + else + { + // successfully placed result on stack + } } std::vector get_table_keys(HSQUIRRELVM vm) @@ -53,7 +77,7 @@ std::vector get_table_keys(HSQUIRRELVM vm) { //here -1 is the value and -2 is the key const char* result; - if(SQ_FAILED(sq_getstring(vm, -2, &result))) + if(SQ_FAILED(sq_getstring(vm, -2, &result))) { std::ostringstream msg; msg << "Couldn't get string value for key"; @@ -80,7 +104,7 @@ std::vector get_level_states(HSQUIRRELVM vm) { //here -1 is the value and -2 is the key const char* result; - if(SQ_FAILED(sq_getstring(vm, -2, &result))) + if(SQ_FAILED(sq_getstring(vm, -2, &result))) { std::ostringstream msg; msg << "Couldn't get string value"; @@ -105,6 +129,45 @@ std::vector get_level_states(HSQUIRRELVM vm) } // namespace +void +LevelsetState::store_level_state(const LevelState& in_state) +{ + auto it = std::find_if(level_states.begin(), level_states.end(), + [&in_state](const LevelState& state) + { + return state.filename == in_state.filename; + }); + if (it != level_states.end()) + { + *it = in_state; + } + else + { + level_states.push_back(in_state); + } +} + +LevelState +LevelsetState::get_level_state(const std::string& filename) +{ + auto it = std::find_if(level_states.begin(), level_states.end(), + [filename](const LevelState& state) + { + return state.filename == filename; + }); + if (it != level_states.end()) + { + return *it; + } + else + { + log_warning << "failed to retrieve level state for " << filename << std::endl; + LevelState state; + state.filename = filename; + return state; + } +} + Savegame::Savegame(const std::string& filename) : m_filename(filename), m_player_status(new PlayerStatus) @@ -124,6 +187,8 @@ Savegame::load() return; } + clear_state_table(); + if(!PHYSFS_exists(m_filename.c_str())) { log_info << m_filename << ": doesn't exist, not loading state" << std::endl; @@ -170,19 +235,10 @@ Savegame::load() } else { - // delete existing state table, if it exists sq_pushroottable(vm); - sq_pushstring(vm, "state", -1); - if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse))) - sq_pop(vm, 1); - - // create a new empty state table - sq_pushstring(vm, "state", -1); - sq_newtable(vm); + get_table_entry(vm, "state"); scripting::load_squirrel_table(vm, -1, *state); - if(SQ_FAILED(sq_createslot(vm, -3))) - throw std::runtime_error("Couldn't create state table"); - sq_pop(vm, 1); + sq_pop(vm, 2); } } } @@ -195,6 +251,25 @@ Savegame::load() } void +Savegame::clear_state_table() +{ + HSQUIRRELVM vm = scripting::global_vm; + + // delete existing state table, if it exists + sq_pushroottable(vm); + { + // create a new empty state table + sq_pushstring(vm, "state", -1); + sq_newtable(vm); + if(SQ_FAILED(sq_createslot(vm, -3))) + { + throw std::runtime_error("Couldn't create state table"); + } + } + sq_pop(vm, 1); +} + +void Savegame::save() { if (m_filename.empty()) @@ -341,7 +416,7 @@ Savegame::get_levelsets() } LevelsetState -Savegame::get_levelset_state(const std::string& name) +Savegame::get_levelset_state(const std::string& basedir) { LevelsetState result; @@ -353,7 +428,7 @@ Savegame::get_levelset_state(const std::string& name) sq_pushroottable(vm); get_table_entry(vm, "state"); get_table_entry(vm, "levelsets"); - get_table_entry(vm, name); + get_table_entry(vm, basedir); get_table_entry(vm, "levels"); result.level_states = get_level_states(vm); @@ -368,4 +443,35 @@ Savegame::get_levelset_state(const std::string& name) return result; } +void +Savegame::set_levelset_state(const std::string& basedir, + const std::string& level_filename, + bool solved) +{ + LevelsetState state = get_levelset_state(basedir); + + HSQUIRRELVM vm = scripting::global_vm; + int oldtop = sq_gettop(vm); + + try + { + sq_pushroottable(vm); + get_table_entry(vm, "state"); + get_or_create_table_entry(vm, "levelsets"); + get_or_create_table_entry(vm, basedir); + get_or_create_table_entry(vm, "levels"); + get_or_create_table_entry(vm, level_filename); + + bool old_solved = false; + scripting::get_bool(vm, "solved", old_solved); + scripting::store_bool(vm, "solved", solved || old_solved); + } + catch(const std::exception& err) + { + log_warning << err.what() << std::endl; + } + + sq_settop(vm, oldtop); +} + /* EOF */