Replace sq_newslot with sq_createslot where appropriate (shorter and does the same...
[supertux.git] / src / supertux / savegame.cpp
index 34738c4..f6f456a 100644 (file)
 
 #include "supertux/savegame.hpp"
 
+#include <algorithm>
+
 #include "lisp/lisp.hpp"
 #include "lisp/parser.hpp"
 #include "lisp/writer.hpp"
 #include "physfs/ifile_streambuf.hpp"
+#include "scripting/scripting.hpp"
 #include "scripting/serialize.hpp"
 #include "scripting/squirrel_util.hpp"
-#include "scripting/squirrel_util.hpp"
 #include "supertux/player_status.hpp"
 #include "util/file_system.hpp"
 #include "util/log.hpp"
@@ -44,6 +46,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_createslot(vm, -3)))
+    {
+      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 +129,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)
 {
@@ -195,14 +237,8 @@ Savegame::load()
           {
             sq_pushroottable(vm);
             get_table_entry(vm, "state");
-
             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);
+            sq_pop(vm, 2);
           }
         }
       }
@@ -222,16 +258,10 @@ Savegame::clear_state_table()
   // 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)))
+    if(SQ_FAILED(sq_createslot(vm, -3)))
     {
       throw std::runtime_error("Couldn't create state table");
     }
@@ -386,7 +416,7 @@ Savegame::get_levelsets()
 }
 
 LevelsetState
-Savegame::get_levelset_state(const std::string& name)
+Savegame::get_levelset_state(const std::string& basedir)
 {
   LevelsetState result;
 
@@ -398,7 +428,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);
@@ -413,4 +443,35 @@ 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);
+
+    bool old_solved = false;
+    scripting::get_bool(vm, "solved", old_solved);
+    scripting::store_bool(vm, "solved", solved || old_solved);
+  }
+  catch(const std::exception& err)
+  {
+    log_warning << err.what() << std::endl;
+  }
+
+  sq_settop(vm, oldtop);
+}
+
 /* EOF */