From 8c15498863fba06e554f72e8b7fad16e99c6c3d4 Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke Date: Wed, 13 Aug 2014 23:12:13 +0200 Subject: [PATCH] Some initial work on getting load/save working for Levelsets load() should work, save() not yet, as there is nobody updating the state after completing a level --- src/supertux/game_manager.cpp | 12 ++-- src/supertux/game_manager.hpp | 2 +- src/supertux/game_session.cpp | 6 ++ src/supertux/game_session.hpp | 3 +- src/supertux/levelset.cpp | 6 ++ src/supertux/levelset.hpp | 1 + ...ib_world_menu.cpp => contrib_levelset_menu.cpp} | 52 ++++++++++++----- ...ib_world_menu.hpp => contrib_levelset_menu.hpp} | 10 ++-- src/supertux/menu/contrib_menu.cpp | 8 +-- src/supertux/menu/menu_storage.cpp | 1 - src/supertux/savegame.cpp | 65 ++++++++++++++++++---- src/supertux/savegame.hpp | 5 ++ 12 files changed, 129 insertions(+), 42 deletions(-) rename src/supertux/menu/{contrib_world_menu.cpp => contrib_levelset_menu.cpp} (51%) rename src/supertux/menu/{contrib_world_menu.hpp => contrib_levelset_menu.hpp} (78%) diff --git a/src/supertux/game_manager.cpp b/src/supertux/game_manager.cpp index 79ffe6f70..c3ca5a1fd 100644 --- a/src/supertux/game_manager.cpp +++ b/src/supertux/game_manager.cpp @@ -44,17 +44,15 @@ GameManager::~GameManager() } void -GameManager::start_level(const std::string& level_filename) +GameManager::start_level(std::unique_ptr world, const std::string& level_filename) { -#ifdef GRUMBEL m_world = std::move(world); - m_savegame.reset(new Savegame); - m_savegame->load(m_world->get_savegame_filename()); + m_savegame.reset(new Savegame(m_world->get_savegame_filename())); + m_savegame->load(); - std::unique_ptr screen(new GameSession(level_filename, - &m_savegame)); + std::unique_ptr screen(new GameSession(FileSystem::join(m_world->get_basedir(), level_filename), + *m_savegame)); g_screen_manager->push_screen(std::move(screen)); -#endif } void diff --git a/src/supertux/game_manager.hpp b/src/supertux/game_manager.hpp index e058793c1..d5a9b3991 100644 --- a/src/supertux/game_manager.hpp +++ b/src/supertux/game_manager.hpp @@ -35,7 +35,7 @@ public: ~GameManager(); void start_game(std::unique_ptr world); - void start_level(const std::string& level_filename); + void start_level(std::unique_ptr world, const std::string& level_filename); std::string get_level_name(const std::string& levelfile) const; diff --git a/src/supertux/game_session.cpp b/src/supertux/game_session.cpp index 77af3771a..028d51c8e 100644 --- a/src/supertux/game_session.cpp +++ b/src/supertux/game_session.cpp @@ -407,6 +407,12 @@ GameSession::setup() } void +GameSession::leave() +{ + m_savegame.save(); +} + +void GameSession::update(float elapsed_time) { // handle controller diff --git a/src/supertux/game_session.hpp b/src/supertux/game_session.hpp index 725f5e050..fdae70554 100644 --- a/src/supertux/game_session.hpp +++ b/src/supertux/game_session.hpp @@ -52,7 +52,8 @@ public: void draw(DrawingContext& context); void update(float frame_ratio); - void setup(); + void setup() override; + void leave() override; /// ends the current level void finish(bool win = true); diff --git a/src/supertux/levelset.cpp b/src/supertux/levelset.cpp index 8b1944610..69a6d5a40 100644 --- a/src/supertux/levelset.cpp +++ b/src/supertux/levelset.cpp @@ -51,4 +51,10 @@ Levelset::get_num_levels() const return static_cast(m_levels.size()); } +std::string +Levelset::get_level_filename(int i) const +{ + return m_levels[i]; +} + /* EOF */ diff --git a/src/supertux/levelset.hpp b/src/supertux/levelset.hpp index b8618f7fb..703dfa13f 100644 --- a/src/supertux/levelset.hpp +++ b/src/supertux/levelset.hpp @@ -30,6 +30,7 @@ public: Levelset(const std::string& basedir); int get_num_levels() const; + std::string get_level_filename(int i) const; private: Levelset(const Levelset&) = delete; diff --git a/src/supertux/menu/contrib_world_menu.cpp b/src/supertux/menu/contrib_levelset_menu.cpp similarity index 51% rename from src/supertux/menu/contrib_world_menu.cpp rename to src/supertux/menu/contrib_levelset_menu.cpp index 4ad9523f2..c268741bd 100644 --- a/src/supertux/menu/contrib_world_menu.cpp +++ b/src/supertux/menu/contrib_levelset_menu.cpp @@ -14,49 +14,73 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include "supertux/menu/contrib_world_menu.hpp" +#include "supertux/menu/contrib_levelset_menu.hpp" + +#include #include "audio/sound_manager.hpp" #include "gui/menu_item.hpp" #include "supertux/game_manager.hpp" #include "supertux/globals.hpp" +#include "supertux/levelset.hpp" #include "supertux/screen_fade.hpp" #include "supertux/screen_manager.hpp" #include "supertux/title_screen.hpp" #include "supertux/world.hpp" +#include "util/file_system.hpp" #include "util/gettext.hpp" -ContribWorldMenu::ContribWorldMenu(std::unique_ptr world) : - m_world(std::move(world)) +ContribLevelsetMenu::ContribLevelsetMenu(std::unique_ptr world) : + m_world(std::move(world)), + m_levelset() { + assert(m_world->is_levelset()); + + m_levelset = std::unique_ptr(new Levelset(m_world->get_basedir())); + + Savegame savegame(m_world->get_savegame_filename()); + savegame.load(); + LevelsetState state = savegame.get_levelset_state(m_world->get_basedir()); + add_label(m_world->get_title()); add_hl(); -#ifdef GRUMBEL - for (int i = 0; i < m_world->get_num_levels(); ++i) + for (int i = 0; i < m_levelset->get_num_levels(); ++i) { - /** get level's title */ - std::string filename = m_world->get_level_filename(i); + std::string filename = FileSystem::join(m_world->get_basedir(), m_levelset->get_level_filename(i)); std::string title = GameManager::current()->get_level_name(filename); - add_entry(i, title); + LevelState level_state = state.get_level_state(filename); + + std::ostringstream out; + if (level_state.solved) + { + out << title << " [*]"; + } + else + { + out << title << " [ ]"; + } + add_entry(i, out.str()); } -#endif add_hl(); add_back(_("Back")); } void -ContribWorldMenu::check_menu() +ContribLevelsetMenu::check_menu() { int index = check(); - if (index != -1) { + if (index != -1) + { if (get_item_by_id(index).kind == MN_ACTION) { sound_manager->stop_music(); -#ifdef GRUMBEL - GameManager::current()->start_level(std::move(m_world), index); -#endif + + // reload the World so that we have something that we can safely + // std::move() around without wreaking the ContribMenu + std::unique_ptr world = World::load(m_world->get_basedir()); + GameManager::current()->start_level(std::move(world), m_levelset->get_level_filename(index)); } } } diff --git a/src/supertux/menu/contrib_world_menu.hpp b/src/supertux/menu/contrib_levelset_menu.hpp similarity index 78% rename from src/supertux/menu/contrib_world_menu.hpp rename to src/supertux/menu/contrib_levelset_menu.hpp index 6f53ac881..0374e92ac 100644 --- a/src/supertux/menu/contrib_world_menu.hpp +++ b/src/supertux/menu/contrib_levelset_menu.hpp @@ -19,21 +19,23 @@ #include "gui/menu.hpp" +class Levelset; class World; -class ContribWorldMenu : public Menu +class ContribLevelsetMenu : public Menu { private: std::unique_ptr m_world; + std::unique_ptr m_levelset; public: - ContribWorldMenu(std::unique_ptr current_world); + ContribLevelsetMenu(std::unique_ptr current_world); void check_menu(); private: - ContribWorldMenu(const ContribWorldMenu&); - ContribWorldMenu& operator=(const ContribWorldMenu&); + ContribLevelsetMenu(const ContribLevelsetMenu&); + ContribLevelsetMenu& operator=(const ContribLevelsetMenu&); }; #endif diff --git a/src/supertux/menu/contrib_menu.cpp b/src/supertux/menu/contrib_menu.cpp index cf862bd41..f2536ac6e 100644 --- a/src/supertux/menu/contrib_menu.cpp +++ b/src/supertux/menu/contrib_menu.cpp @@ -22,7 +22,7 @@ #include "gui/menu_manager.hpp" #include "supertux/game_manager.hpp" #include "supertux/gameconfig.hpp" -#include "supertux/menu/contrib_world_menu.hpp" +#include "supertux/menu/contrib_levelset_menu.hpp" #include "supertux/menu/menu_storage.hpp" #include "supertux/title_screen.hpp" #include "supertux/world.hpp" @@ -71,7 +71,7 @@ ContribMenu::ContribMenu() : } level_count += 1; } - + std::ostringstream title; title << "[" << world->get_title() << "]"; if (level_count == 0) @@ -99,7 +99,7 @@ ContribMenu::ContribMenu() : } level_count += 1; } - + std::ostringstream title; title << world->get_title(); if (level_count == 0) @@ -148,7 +148,7 @@ ContribMenu::check_menu() } else { - MenuManager::instance().push_menu(std::unique_ptr(new ContribWorldMenu(std::move(world)))); + MenuManager::instance().push_menu(std::unique_ptr(new ContribLevelsetMenu(std::move(world)))); } } } diff --git a/src/supertux/menu/menu_storage.cpp b/src/supertux/menu/menu_storage.cpp index 7d4481e05..4a88618c2 100644 --- a/src/supertux/menu/menu_storage.cpp +++ b/src/supertux/menu/menu_storage.cpp @@ -19,7 +19,6 @@ #include "supertux/globals.hpp" #include "supertux/menu/addon_menu.hpp" #include "supertux/menu/contrib_menu.hpp" -#include "supertux/menu/contrib_world_menu.hpp" #include "supertux/menu/game_menu.hpp" #include "supertux/menu/joystick_menu.hpp" #include "supertux/menu/keyboard_menu.hpp" diff --git a/src/supertux/savegame.cpp b/src/supertux/savegame.cpp index ba2670cdf..34738c481 100644 --- a/src/supertux/savegame.cpp +++ b/src/supertux/savegame.cpp @@ -41,7 +41,7 @@ void get_table_entry(HSQUIRRELVM vm, const std::string& name) else { // successfully placed result on stack - } + } } std::vector get_table_keys(HSQUIRRELVM vm) @@ -53,7 +53,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 +80,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 +105,27 @@ std::vector get_level_states(HSQUIRRELVM vm) } // namespace +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 +145,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,18 +193,15 @@ 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); + get_table_entry(vm, "state"); - // create a new empty state table - sq_pushstring(vm, "state", -1); - sq_newtable(vm); scripting::load_squirrel_table(vm, -1, *state); if(SQ_FAILED(sq_createslot(vm, -3))) + { + sq_pop(vm, 1); throw std::runtime_error("Couldn't create state table"); + } sq_pop(vm, 1); } } @@ -195,6 +215,31 @@ Savegame::load() } void +Savegame::clear_state_table() +{ + HSQUIRRELVM vm = scripting::global_vm; + + // 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); + if(SQ_FAILED(sq_newslot(vm, -3, SQFalse))) + { + throw std::runtime_error("Couldn't create state table"); + } + } + sq_pop(vm, 1); +} + +void Savegame::save() { if (m_filename.empty()) diff --git a/src/supertux/savegame.hpp b/src/supertux/savegame.hpp index 7c11a0d41..b6b71890f 100644 --- a/src/supertux/savegame.hpp +++ b/src/supertux/savegame.hpp @@ -47,6 +47,8 @@ public: {} std::string directory; std::vector level_states; + + LevelState get_level_state(const std::string& filename); }; struct WorldmapState @@ -116,6 +118,9 @@ public: void load(); private: + void clear_state_table(); + +private: Savegame(const Savegame&) = delete; Savegame& operator=(const Savegame&) = delete; }; -- 2.11.0