From: Ingo Ruhnke Date: Thu, 14 Aug 2014 02:32:34 +0000 (+0200) Subject: Hacked together basic support for Levelset saving X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=e9ef8ed568b3f7380788339d927fc66609534875;p=supertux.git Hacked together basic support for Levelset saving --- diff --git a/src/supertux/game_manager.cpp b/src/supertux/game_manager.cpp index 2546e9476..45215d362 100644 --- a/src/supertux/game_manager.cpp +++ b/src/supertux/game_manager.cpp @@ -24,11 +24,12 @@ #include "supertux/game_session.hpp" #include "supertux/gameconfig.hpp" #include "supertux/globals.hpp" +#include "supertux/levelset_screen.hpp" +#include "supertux/savegame.hpp" #include "supertux/screen.hpp" #include "supertux/screen_fade.hpp" #include "supertux/screen_manager.hpp" #include "supertux/world.hpp" -#include "supertux/savegame.hpp" #include "util/file_system.hpp" #include "util/log.hpp" #include "worldmap/worldmap.hpp" @@ -50,8 +51,9 @@ GameManager::start_level(std::unique_ptr world, const std::string& level_ m_savegame.reset(new Savegame(m_world->get_savegame_filename())); m_savegame->load(); - std::unique_ptr screen(new GameSession(FileSystem::join(m_world->get_basedir(), level_filename), - *m_savegame)); + std::unique_ptr screen(new LevelsetScreen(m_world->get_basedir(), + level_filename, + *m_savegame)); g_screen_manager->push_screen(std::move(screen)); } diff --git a/src/supertux/game_session.cpp b/src/supertux/game_session.cpp index 028d51c8e..8fb7427e9 100644 --- a/src/supertux/game_session.cpp +++ b/src/supertux/game_session.cpp @@ -34,13 +34,14 @@ #include "supertux/gameconfig.hpp" #include "supertux/globals.hpp" #include "supertux/levelintro.hpp" +#include "supertux/levelset_screen.hpp" #include "supertux/menu/menu_storage.hpp" #include "supertux/menu/options_menu.hpp" #include "supertux/player_status.hpp" +#include "supertux/savegame.hpp" #include "supertux/screen_fade.hpp" #include "supertux/screen_manager.hpp" #include "supertux/sector.hpp" -#include "supertux/savegame.hpp" #include "util/file_system.hpp" #include "util/gettext.hpp" #include "worldmap/worldmap.hpp" @@ -409,7 +410,6 @@ GameSession::setup() void GameSession::leave() { - m_savegame.save(); } void @@ -494,7 +494,14 @@ GameSession::finish(bool win) if(win) { if(WorldMap::current()) + { WorldMap::current()->finished_level(level.get()); + } + + if (LevelsetScreen::current()) + { + LevelsetScreen::current()->finished_level(win); + } } g_screen_manager->pop_screen(); diff --git a/src/supertux/levelset_screen.cpp b/src/supertux/levelset_screen.cpp new file mode 100644 index 000000000..0aec48ac9 --- /dev/null +++ b/src/supertux/levelset_screen.cpp @@ -0,0 +1,85 @@ +// SuperTux +// Copyright (C) 2014 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/levelset_screen.hpp" + +#include "supertux/game_session.hpp" +#include "supertux/globals.hpp" +#include "supertux/savegame.hpp" +#include "supertux/screen_fade.hpp" +#include "supertux/screen_manager.hpp" +#include "util/file_system.hpp" + +LevelsetScreen::LevelsetScreen(const std::string& basedir, const std::string& level_filename, + Savegame& savegame) : + m_basedir(basedir), + m_level_filename(level_filename), + m_savegame(savegame), + m_level_started(false), + m_solved(false) +{ + LevelsetState state = m_savegame.get_levelset_state(basedir); + LevelState level_state = state.get_level_state(level_filename); + m_solved = level_state.solved; +} + +LevelsetScreen::~LevelsetScreen() +{ +} + +void +LevelsetScreen::draw(DrawingContext&) +{ +} + +void +LevelsetScreen::update(float elapsed_time) +{ +} + +void +LevelsetScreen::finished_level(bool win) +{ + m_solved = m_solved || win; +} + +void +LevelsetScreen::setup() +{ + if (m_level_started) + { + log_info << "Saving Levelset state" << std::endl; + // this gets called when the GameSession is done and we return back to the + m_savegame.set_levelset_state(m_basedir, m_level_filename, m_solved); + m_savegame.save(); + g_screen_manager->pop_screen(); + } + else + { + m_level_started = true; + + std::unique_ptr screen(new GameSession(FileSystem::join(m_basedir, m_level_filename), + m_savegame)); + g_screen_manager->push_screen(std::move(screen)); + } +} + +void +LevelsetScreen::leave() +{ +} + +/* EOF */ diff --git a/src/supertux/levelset_screen.hpp b/src/supertux/levelset_screen.hpp new file mode 100644 index 000000000..5a72cf137 --- /dev/null +++ b/src/supertux/levelset_screen.hpp @@ -0,0 +1,56 @@ +// SuperTux +// Copyright (C) 2014 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_LEVELSET_SCREEN_HPP +#define HEADER_SUPERTUX_SUPERTUX_LEVELSET_SCREEN_HPP + +#include + +#include "supertux/screen.hpp" +#include "util/currenton.hpp" + +class Savegame; + +class LevelsetScreen : public Screen, + public Currenton +{ +private: + std::string m_basedir; + std::string m_level_filename; + Savegame& m_savegame; + bool m_level_started; + bool m_solved; + +public: + LevelsetScreen(const std::string& basedir, const std::string& level_filename, Savegame& savegame); + ~LevelsetScreen(); + + void draw(DrawingContext&) override; + void update(float elapsed_time) override; + + void setup() override; + void leave() override; + + void finished_level(bool win); + +private: + LevelsetScreen(const LevelsetScreen&) = delete; + LevelsetScreen& operator=(const LevelsetScreen&) = delete; +}; + +#endif + +/* EOF */ diff --git a/src/supertux/menu/contrib_levelset_menu.cpp b/src/supertux/menu/contrib_levelset_menu.cpp index c268741bd..3ef0b3b44 100644 --- a/src/supertux/menu/contrib_levelset_menu.cpp +++ b/src/supertux/menu/contrib_levelset_menu.cpp @@ -47,8 +47,9 @@ ContribLevelsetMenu::ContribLevelsetMenu(std::unique_ptr world) : 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); + std::string filename = m_levelset->get_level_filename(i); + std::string full_filename = FileSystem::join(m_world->get_basedir(), filename); + std::string title = GameManager::current()->get_level_name(full_filename); LevelState level_state = state.get_level_state(filename); std::ostringstream out; diff --git a/src/supertux/savegame.cpp b/src/supertux/savegame.cpp index 16c6a0fb6..c7a7330fc 100644 --- a/src/supertux/savegame.cpp +++ b/src/supertux/savegame.cpp @@ -44,6 +44,28 @@ void get_table_entry(HSQUIRRELVM vm, const std::string& name) } } +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_newslot(vm, -3, SQFalse))) + { + 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) { std::vector worlds; @@ -105,6 +127,24 @@ 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) { @@ -380,7 +420,7 @@ Savegame::get_levelsets() } LevelsetState -Savegame::get_levelset_state(const std::string& name) +Savegame::get_levelset_state(const std::string& basedir) { LevelsetState result; @@ -392,7 +432,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); @@ -407,4 +447,33 @@ 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); + + scripting::store_bool(vm, "solved", solved); + } + catch(const std::exception& err) + { + log_warning << err.what() << std::endl; + } + + sq_settop(vm, oldtop); +} + /* EOF */ diff --git a/src/supertux/savegame.hpp b/src/supertux/savegame.hpp index b6b71890f..d5f3c4161 100644 --- a/src/supertux/savegame.hpp +++ b/src/supertux/savegame.hpp @@ -49,6 +49,7 @@ public: std::vector level_states; LevelState get_level_state(const std::string& filename); + void store_level_state(const LevelState& state); }; struct WorldmapState @@ -110,6 +111,9 @@ public: std::vector get_levelsets(); LevelsetState get_levelset_state(const std::string& name); + void set_levelset_state(const std::string& basedir, + const std::string& level_filename, + bool solved); std::vector get_worldmaps(); WorldmapState get_worldmap_state(const std::string& name);