Some initial work on getting load/save working for Levelsets
authorIngo Ruhnke <grumbel@gmail.com>
Wed, 13 Aug 2014 21:12:13 +0000 (23:12 +0200)
committerIngo Ruhnke <grumbel@gmail.com>
Thu, 14 Aug 2014 00:59:02 +0000 (02:59 +0200)
load() should work, save() not yet, as there is nobody updating the state after completing a level

14 files changed:
src/supertux/game_manager.cpp
src/supertux/game_manager.hpp
src/supertux/game_session.cpp
src/supertux/game_session.hpp
src/supertux/levelset.cpp
src/supertux/levelset.hpp
src/supertux/menu/contrib_levelset_menu.cpp [new file with mode: 0644]
src/supertux/menu/contrib_levelset_menu.hpp [new file with mode: 0644]
src/supertux/menu/contrib_menu.cpp
src/supertux/menu/contrib_world_menu.cpp [deleted file]
src/supertux/menu/contrib_world_menu.hpp [deleted file]
src/supertux/menu/menu_storage.cpp
src/supertux/savegame.cpp
src/supertux/savegame.hpp

index 79ffe6f..c3ca5a1 100644 (file)
@@ -44,17 +44,15 @@ GameManager::~GameManager()
 }
 
 void
-GameManager::start_level(const std::string& level_filename)
+GameManager::start_level(std::unique_ptr<World> 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> screen(new GameSession(level_filename,
-                                                 &m_savegame));
+  std::unique_ptr<Screen> screen(new GameSession(FileSystem::join(m_world->get_basedir(), level_filename),
+                                                 *m_savegame));
   g_screen_manager->push_screen(std::move(screen));
-#endif
 }
 
 void
index e058793..d5a9b39 100644 (file)
@@ -35,7 +35,7 @@ public:
   ~GameManager();
 
   void start_game(std::unique_ptr<World> world);
-  void start_level(const std::string& level_filename);
+  void start_level(std::unique_ptr<World> world, const std::string& level_filename);
 
   std::string get_level_name(const std::string& levelfile) const;
 
index 77af377..028d51c 100644 (file)
@@ -407,6 +407,12 @@ GameSession::setup()
 }
 
 void
+GameSession::leave()
+{
+  m_savegame.save();
+}
+
+void
 GameSession::update(float elapsed_time)
 {
   // handle controller
index 725f5e0..fdae705 100644 (file)
@@ -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);
index 8b19446..69a6d5a 100644 (file)
@@ -51,4 +51,10 @@ Levelset::get_num_levels() const
   return static_cast<int>(m_levels.size());
 }
 
+std::string
+Levelset::get_level_filename(int i) const
+{
+  return m_levels[i];
+}
+
 /* EOF */
index b8618f7..703dfa1 100644 (file)
@@ -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 (file)
index 0000000..c268741
--- /dev/null
@@ -0,0 +1,88 @@
+//  SuperTux
+//  Copyright (C) 2009 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/menu/contrib_levelset_menu.hpp"
+
+#include <sstream>
+
+#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> world) :
+  m_world(std::move(world)),
+  m_levelset()
+{
+  assert(m_world->is_levelset());
+
+  m_levelset = std::unique_ptr<Levelset>(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 = 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 (file)
index 0000000..0374e92
--- /dev/null
@@ -0,0 +1,43 @@
+//  SuperTux
+//  Copyright (C) 2009 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_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<World> m_world;
+  std::unique_ptr<Levelset> m_levelset;
+
+public:
+  ContribLevelsetMenu(std::unique_ptr<World> current_world);
+
+  void check_menu();
+
+private:
+  ContribLevelsetMenu(const ContribLevelsetMenu&);
+  ContribLevelsetMenu& operator=(const ContribLevelsetMenu&);
+};
+
+#endif
+
+/* EOF */
index cf862bd..f2536ac 100644 (file)
@@ -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<Menu>(new ContribWorldMenu(std::move(world))));
+      MenuManager::instance().push_menu(std::unique_ptr<Menu>(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 (file)
index 4ad9523..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-//  SuperTux
-//  Copyright (C) 2009 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/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> 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 (file)
index 6f53ac8..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-//  SuperTux
-//  Copyright (C) 2009 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_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<World> m_world;
-
-public:
-  ContribWorldMenu(std::unique_ptr<World> current_world);
-
-  void check_menu();
-
-private:
-  ContribWorldMenu(const ContribWorldMenu&);
-  ContribWorldMenu& operator=(const ContribWorldMenu&);
-};
-
-#endif
-
-/* EOF */
index 7d4481e..4a88618 100644 (file)
@@ -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"
index ba2670c..34738c4 100644 (file)
@@ -41,7 +41,7 @@ void get_table_entry(HSQUIRRELVM vm, const std::string& name)
   else
   {
     // successfully placed result on stack
-  } 
+  }
 }
 
 std::vector<std::string> get_table_keys(HSQUIRRELVM vm)
@@ -53,7 +53,7 @@ std::vector<std::string> 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<LevelState> 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<LevelState> 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())
index 7c11a0d..b6b7189 100644 (file)
@@ -47,6 +47,8 @@ public:
   {}
   std::string directory;
   std::vector<LevelState> 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;
 };