Hacked together basic support for Levelset saving
authorIngo Ruhnke <grumbel@gmail.com>
Thu, 14 Aug 2014 02:32:34 +0000 (04:32 +0200)
committerIngo Ruhnke <grumbel@gmail.com>
Thu, 14 Aug 2014 02:32:34 +0000 (04:32 +0200)
src/supertux/game_manager.cpp
src/supertux/game_session.cpp
src/supertux/levelset_screen.cpp [new file with mode: 0644]
src/supertux/levelset_screen.hpp [new file with mode: 0644]
src/supertux/menu/contrib_levelset_menu.cpp
src/supertux/savegame.cpp
src/supertux/savegame.hpp

index 2546e94..45215d3 100644 (file)
 #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> world, const std::string& level_
   m_savegame.reset(new Savegame(m_world->get_savegame_filename()));
   m_savegame->load();
 
-  std::unique_ptr<Screen> screen(new GameSession(FileSystem::join(m_world->get_basedir(), level_filename),
-                                                 *m_savegame));
+  std::unique_ptr<Screen> screen(new LevelsetScreen(m_world->get_basedir(),
+                                                    level_filename,
+                                                    *m_savegame));
   g_screen_manager->push_screen(std::move(screen));
 }
 
index 028d51c..8fb7427 100644 (file)
 #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 (file)
index 0000000..0aec48a
--- /dev/null
@@ -0,0 +1,85 @@
+//  SuperTux
+//  Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
+//
+//  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 <http://www.gnu.org/licenses/>.
+
+#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> 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 (file)
index 0000000..5a72cf1
--- /dev/null
@@ -0,0 +1,56 @@
+//  SuperTux
+//  Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
+//
+//  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 <http://www.gnu.org/licenses/>.
+
+#ifndef HEADER_SUPERTUX_SUPERTUX_LEVELSET_SCREEN_HPP
+#define HEADER_SUPERTUX_SUPERTUX_LEVELSET_SCREEN_HPP
+
+#include <string>
+
+#include "supertux/screen.hpp"
+#include "util/currenton.hpp"
+
+class Savegame;
+
+class LevelsetScreen : public Screen,
+                       public Currenton<LevelsetScreen>
+{
+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 */
index c268741..3ef0b3b 100644 (file)
@@ -47,8 +47,9 @@ ContribLevelsetMenu::ContribLevelsetMenu(std::unique_ptr<World> 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;
index 16c6a0f..c7a7330 100644 (file)
@@ -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<std::string> get_table_keys(HSQUIRRELVM vm)
 {
   std::vector<std::string> worlds;
@@ -105,6 +127,24 @@ std::vector<LevelState> 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 */
index b6b7189..d5f3c41 100644 (file)
@@ -49,6 +49,7 @@ public:
   std::vector<LevelState> 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<std::string> 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<std::string> get_worldmaps();
   WorldmapState get_worldmap_state(const std::string& name);