From: Ingo Ruhnke Date: Wed, 13 Aug 2014 21:12:13 +0000 (+0200) Subject: Some initial work on getting load/save working for Levelsets X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=8c15498863fba06e554f72e8b7fad16e99c6c3d4;p=supertux.git 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 --- 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_levelset_menu.cpp b/src/supertux/menu/contrib_levelset_menu.cpp new file mode 100644 index 000000000..c268741bd --- /dev/null +++ b/src/supertux/menu/contrib_levelset_menu.cpp @@ -0,0 +1,88 @@ +// SuperTux +// Copyright (C) 2009 Ingo Ruhnke +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#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" + +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(); + + for (int i = 0; i < m_levelset->get_num_levels(); ++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); + 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()); + } + + add_hl(); + add_back(_("Back")); +} + +void +ContribLevelsetMenu::check_menu() +{ + int index = check(); + if (index != -1) + { + if (get_item_by_id(index).kind == MN_ACTION) + { + sound_manager->stop_music(); + + // 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)); + } + } +} + +/* EOF */ diff --git a/src/supertux/menu/contrib_levelset_menu.hpp b/src/supertux/menu/contrib_levelset_menu.hpp new file mode 100644 index 000000000..0374e92ac --- /dev/null +++ b/src/supertux/menu/contrib_levelset_menu.hpp @@ -0,0 +1,43 @@ +// SuperTux +// Copyright (C) 2009 Ingo Ruhnke +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#ifndef HEADER_SUPERTUX_SUPERTUX_MENU_CONTRIB_WORLD_MENU_HPP +#define HEADER_SUPERTUX_SUPERTUX_MENU_CONTRIB_WORLD_MENU_HPP + +#include "gui/menu.hpp" + +class Levelset; +class World; + +class ContribLevelsetMenu : public Menu +{ +private: + std::unique_ptr m_world; + std::unique_ptr m_levelset; + +public: + ContribLevelsetMenu(std::unique_ptr current_world); + + void check_menu(); + +private: + ContribLevelsetMenu(const ContribLevelsetMenu&); + ContribLevelsetMenu& operator=(const ContribLevelsetMenu&); +}; + +#endif + +/* EOF */ 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/contrib_world_menu.cpp b/src/supertux/menu/contrib_world_menu.cpp deleted file mode 100644 index 4ad9523f2..000000000 --- a/src/supertux/menu/contrib_world_menu.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// SuperTux -// Copyright (C) 2009 Ingo Ruhnke -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// 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 "audio/sound_manager.hpp" -#include "gui/menu_item.hpp" -#include "supertux/game_manager.hpp" -#include "supertux/globals.hpp" -#include "supertux/screen_fade.hpp" -#include "supertux/screen_manager.hpp" -#include "supertux/title_screen.hpp" -#include "supertux/world.hpp" -#include "util/gettext.hpp" - -ContribWorldMenu::ContribWorldMenu(std::unique_ptr world) : - m_world(std::move(world)) -{ - add_label(m_world->get_title()); - add_hl(); - -#ifdef GRUMBEL - for (int i = 0; i < m_world->get_num_levels(); ++i) - { - /** get level's title */ - std::string filename = m_world->get_level_filename(i); - std::string title = GameManager::current()->get_level_name(filename); - add_entry(i, title); - } -#endif - - add_hl(); - add_back(_("Back")); -} - -void -ContribWorldMenu::check_menu() -{ - int index = check(); - 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 - } - } -} - -/* EOF */ diff --git a/src/supertux/menu/contrib_world_menu.hpp b/src/supertux/menu/contrib_world_menu.hpp deleted file mode 100644 index 6f53ac881..000000000 --- a/src/supertux/menu/contrib_world_menu.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// SuperTux -// Copyright (C) 2009 Ingo Ruhnke -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#ifndef HEADER_SUPERTUX_SUPERTUX_MENU_CONTRIB_WORLD_MENU_HPP -#define HEADER_SUPERTUX_SUPERTUX_MENU_CONTRIB_WORLD_MENU_HPP - -#include "gui/menu.hpp" - -class World; - -class ContribWorldMenu : public Menu -{ -private: - std::unique_ptr m_world; - -public: - ContribWorldMenu(std::unique_ptr current_world); - - void check_menu(); - -private: - ContribWorldMenu(const ContribWorldMenu&); - ContribWorldMenu& operator=(const ContribWorldMenu&); -}; - -#endif - -/* EOF */ 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; };