Moved some state handling code into WorldState, sort of, most of it still just goes...
authorIngo Ruhnke <grumbel@gmail.com>
Mon, 11 Aug 2014 03:10:07 +0000 (05:10 +0200)
committerIngo Ruhnke <grumbel@gmail.com>
Mon, 11 Aug 2014 22:21:35 +0000 (00:21 +0200)
src/supertux/world.cpp
src/supertux/world.hpp
src/supertux/world_state.cpp [new file with mode: 0644]
src/supertux/world_state.hpp [new file with mode: 0644]

index f9bc52a..c2063a7 100644 (file)
@@ -27,6 +27,7 @@
 #include "supertux/screen_fade.hpp"
 #include "supertux/screen_manager.hpp"
 #include "supertux/world.hpp"
+#include "supertux/world_state.hpp"
 #include "util/file_system.hpp"
 #include "util/reader.hpp"
 #include "util/string_util.hpp"
@@ -58,7 +59,7 @@ World::World() :
   m_world_thread(),
   m_title(),
   m_description(),
-  m_player_status(new PlayerStatus),
+  m_world_state(new WorldState),
   m_hide_from_contribs(false),
   m_is_levelset(true)
 {
@@ -157,113 +158,13 @@ World::run()
 void
 World::save_state()
 {
-  { // make sure the savegame directory exists
-    std::string dirname = FileSystem::dirname(m_savegame_filename);
-    if(!PHYSFS_exists(dirname.c_str()))
-    {
-      if(!PHYSFS_mkdir(dirname.c_str()))
-      {
-        std::ostringstream msg;
-        msg << "Couldn't create directory for savegames '"
-            << dirname << "': " <<PHYSFS_getLastError();
-        throw std::runtime_error(msg.str());
-      }
-    }
-
-    if(!PHYSFS_isDirectory(dirname.c_str()))
-    {
-      std::ostringstream msg;
-      msg << "Savegame path '" << dirname << "' is not a directory";
-      throw std::runtime_error(msg.str());
-    }
-  }
-
-  HSQUIRRELVM vm = scripting::global_vm;
-
-  lisp::Writer writer(m_savegame_filename);
-
-  writer.start_list("supertux-savegame");
-  writer.write("version", 1);
-
-  using namespace worldmap;
-  if(WorldMap::current() != NULL)
-  {
-    std::ostringstream title;
-    title << WorldMap::current()->get_title();
-    title << " (" << WorldMap::current()->solved_level_count()
-          << "/" << WorldMap::current()->level_count() << ")";
-    writer.write("title", title.str());
-  }
-
-  writer.start_list("tux");
-  m_player_status->write(writer);
-  writer.end_list("tux");
-
-  writer.start_list("state");
-
-  sq_pushroottable(vm);
-  sq_pushstring(vm, "state", -1);
-  if(SQ_SUCCEEDED(sq_get(vm, -2))) {
-    scripting::save_squirrel_table(vm, -1, writer);
-    sq_pop(vm, 1);
-  }
-  sq_pop(vm, 1);
-  writer.end_list("state");
-
-  writer.end_list("supertux-savegame");
+  m_world_state->save(m_savegame_filename);
 }
 
 void
 World::load_state()
 {
-  if(!PHYSFS_exists(m_savegame_filename.c_str()))
-  {
-    log_info << m_savegame_filename << ": doesn't exist, not loading state" << std::endl;
-  }
-  else
-  {
-    try
-    {
-      HSQUIRRELVM vm = scripting::global_vm;
-
-      lisp::Parser parser;
-      const lisp::Lisp* root = parser.parse(m_savegame_filename);
-
-      const lisp::Lisp* lisp = root->get_lisp("supertux-savegame");
-      if(lisp == NULL)
-        throw std::runtime_error("file is not a supertux-savegame file");
-
-      int version = 1;
-      lisp->get("version", version);
-      if(version != 1)
-        throw std::runtime_error("incompatible savegame version");
-
-      const lisp::Lisp* tux = lisp->get_lisp("tux");
-      if(tux == NULL)
-        throw std::runtime_error("No tux section in savegame");
-      m_player_status->read(*tux);
-
-      const lisp::Lisp* state = lisp->get_lisp("state");
-      if(state == NULL)
-        throw std::runtime_error("No state section in savegame");
-
-      sq_pushroottable(vm);
-      sq_pushstring(vm, "state", -1);
-      if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse)))
-        sq_pop(vm, 1);
-
-      sq_pushstring(vm, "state", -1);
-      sq_newtable(vm);
-      scripting::load_squirrel_table(vm, -1, *state);
-      if(SQ_FAILED(sq_createslot(vm, -3)))
-        throw std::runtime_error("Couldn't create state table");
-      sq_pop(vm, 1);
-    }
-    catch(const std::exception& e)
-    {
-      log_fatal << "Couldn't load savegame: " << e.what() << std::endl;
-    }
-  }
+  m_world_state->load(m_savegame_filename);
 }
 
 std::string
@@ -272,10 +173,10 @@ World::get_level_filename(unsigned int i) const
   return FileSystem::join(m_basedir, m_levels[i]);
 }
 
-unsigned int
+int
 World::get_num_levels() const
 {
-  return m_levels.size();
+  return static_cast<int>(m_levels.size());
 }
 
 int
index 04fad22..a952640 100644 (file)
@@ -23,8 +23,7 @@
 #include <vector>
 
 #include "util/currenton.hpp"
-
-class PlayerStatus;
+#include "supertux/world_state.hpp"
 
 class World : public Currenton<World>
 {
@@ -47,14 +46,14 @@ public:
   void save_state();
   void load_state();
 
-  unsigned int get_num_levels() const;
+  int get_num_levels() const;
   int get_num_solved_levels() const;
 
   std::string get_level_filename(unsigned int i) const;
   std::string get_basedir() const;
   std::string get_title() const;
 
-  PlayerStatus* get_player_status() const { return m_player_status.get(); }
+  PlayerStatus* get_player_status() const { return m_world_state->get_player_status(); }
 
   void run();
 
@@ -69,7 +68,7 @@ private:
   HSQOBJECT m_world_thread;
   std::string m_title;
   std::string m_description;
-  std::unique_ptr<PlayerStatus> m_player_status;
+  std::unique_ptr<WorldState> m_world_state;
 
   bool m_hide_from_contribs;
   bool m_is_levelset;
diff --git a/src/supertux/world_state.cpp b/src/supertux/world_state.cpp
new file mode 100644 (file)
index 0000000..d0dbd8b
--- /dev/null
@@ -0,0 +1,165 @@
+//  SuperTux
+//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
+//                2014 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  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/world_state.hpp"
+
+#include "lisp/lisp.hpp"
+#include "lisp/parser.hpp"
+#include "lisp/writer.hpp"
+#include "physfs/ifile_streambuf.hpp"
+#include "scripting/serialize.hpp"
+#include "scripting/squirrel_util.hpp"
+#include "supertux/player_status.hpp"
+#include "util/file_system.hpp"
+#include "util/log.hpp"
+#include "worldmap/worldmap.hpp"
+
+WorldState::WorldState() :
+  m_player_status(new PlayerStatus)
+{
+}
+
+void
+WorldState::load(const std::string& filename)
+{
+  if(!PHYSFS_exists(filename.c_str()))
+  {
+    log_info << filename << ": doesn't exist, not loading state" << std::endl;
+  }
+  else
+  {
+    try
+    {
+      HSQUIRRELVM vm = scripting::global_vm;
+
+      lisp::Parser parser;
+      const lisp::Lisp* root = parser.parse(filename);
+
+      const lisp::Lisp* lisp = root->get_lisp("supertux-savegame");
+      if(lisp == NULL)
+      {
+        throw std::runtime_error("file is not a supertux-savegame file");
+      }
+      else
+      {
+        int version = 1;
+        lisp->get("version", version);
+        if(version != 1)
+        {
+          throw std::runtime_error("incompatible savegame version");
+        }
+        else
+        {
+          const lisp::Lisp* tux = lisp->get_lisp("tux");
+          if(tux == NULL)
+          {
+            throw std::runtime_error("No tux section in savegame");
+          }
+          {
+            m_player_status->read(*tux);
+          }
+
+          const lisp::Lisp* state = lisp->get_lisp("state");
+          if(state == NULL)
+          {
+            throw std::runtime_error("No state section in savegame");
+          }
+          else
+          {
+            sq_pushroottable(vm);
+            sq_pushstring(vm, "state", -1);
+            if(SQ_FAILED(sq_deleteslot(vm, -2, SQFalse)))
+              sq_pop(vm, 1);
+
+            sq_pushstring(vm, "state", -1);
+            sq_newtable(vm);
+            scripting::load_squirrel_table(vm, -1, *state);
+            if(SQ_FAILED(sq_createslot(vm, -3)))
+              throw std::runtime_error("Couldn't create state table");
+            sq_pop(vm, 1);
+          }
+        }
+      }
+    }
+    catch(const std::exception& e)
+    {
+      log_fatal << "Couldn't load savegame: " << e.what() << std::endl;
+    }
+  }
+}
+
+void
+WorldState::save(const std::string& filename)
+{
+  { // make sure the savegame directory exists
+    std::string dirname = FileSystem::dirname(filename);
+    if(!PHYSFS_exists(dirname.c_str()))
+    {
+      if(!PHYSFS_mkdir(dirname.c_str()))
+      {
+        std::ostringstream msg;
+        msg << "Couldn't create directory for savegames '"
+            << dirname << "': " <<PHYSFS_getLastError();
+        throw std::runtime_error(msg.str());
+      }
+    }
+
+    if(!PHYSFS_isDirectory(dirname.c_str()))
+    {
+      std::ostringstream msg;
+      msg << "Savegame path '" << dirname << "' is not a directory";
+      throw std::runtime_error(msg.str());
+    }
+  }
+
+  HSQUIRRELVM vm = scripting::global_vm;
+
+  lisp::Writer writer(filename);
+
+  writer.start_list("supertux-savegame");
+  writer.write("version", 1);
+
+  using namespace worldmap;
+  if(WorldMap::current() != NULL)
+  {
+    std::ostringstream title;
+    title << WorldMap::current()->get_title();
+    title << " (" << WorldMap::current()->solved_level_count()
+          << "/" << WorldMap::current()->level_count() << ")";
+    writer.write("title", title.str());
+  }
+
+  writer.start_list("tux");
+  m_player_status->write(writer);
+  writer.end_list("tux");
+
+  writer.start_list("state");
+
+  sq_pushroottable(vm);
+  sq_pushstring(vm, "state", -1);
+  if(SQ_SUCCEEDED(sq_get(vm, -2)))
+  {
+    scripting::save_squirrel_table(vm, -1, writer);
+    sq_pop(vm, 1);
+  }
+  sq_pop(vm, 1);
+  writer.end_list("state");
+
+  writer.end_list("supertux-savegame");
+}
+
+/* EOF */
diff --git a/src/supertux/world_state.hpp b/src/supertux/world_state.hpp
new file mode 100644 (file)
index 0000000..a3d2c3e
--- /dev/null
@@ -0,0 +1,46 @@
+//  SuperTux
+//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
+//                2014 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  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_WORLD_STATE_HPP
+#define HEADER_SUPERTUX_SUPERTUX_WORLD_STATE_HPP
+
+#include <string>
+#include <memory>
+
+class PlayerStatus;
+
+class WorldState
+{
+private:
+  std::unique_ptr<PlayerStatus> m_player_status;
+
+public:
+  WorldState();
+
+  PlayerStatus* get_player_status() const { return m_player_status.get(); }
+
+  void save(const std::string& filename);
+  void load(const std::string& filename);
+
+private:
+  WorldState(const WorldState&) = delete;
+  WorldState& operator=(const WorldState&) = delete;
+};
+
+#endif
+
+/* EOF */