From fb4786d141830d3aff65ebee0ef61ee41863e952 Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke Date: Sun, 10 Aug 2014 05:43:09 +0200 Subject: [PATCH] Display number of solved levels in ContribMenu, kind of ugly patch, save system needs a refactor --- src/supertux/menu/contrib_menu.cpp | 20 ++++++- src/supertux/world.cpp | 87 ++++++++++++++++++++++++++++-- src/supertux/world.hpp | 10 +++- 3 files changed, 110 insertions(+), 7 deletions(-) diff --git a/src/supertux/menu/contrib_menu.cpp b/src/supertux/menu/contrib_menu.cpp index 6bf8fcf5aa6..4078059960e 100644 --- a/src/supertux/menu/contrib_menu.cpp +++ b/src/supertux/menu/contrib_menu.cpp @@ -17,13 +17,16 @@ #include "supertux/menu/contrib_menu.hpp" #include +#include #include "gui/menu_manager.hpp" #include "supertux/game_manager.hpp" +#include "supertux/gameconfig.hpp" #include "supertux/menu/contrib_world_menu.hpp" #include "supertux/menu/menu_storage.hpp" #include "supertux/title_screen.hpp" #include "supertux/world.hpp" +#include "util/file_system.hpp" #include "util/gettext.hpp" ContribMenu::ContribMenu() : @@ -47,11 +50,24 @@ ContribMenu::ContribMenu() : { try { - std::unique_ptr world (new World()); + std::unique_ptr world (new World); + world->load(*it + "/info"); + if (!world->hide_from_contribs) { - add_entry(i++, world->get_title()); + { // FIXME: yuck, this should be easier + std::ostringstream stream; + std::string worlddirname = FileSystem::basename(*it); + stream << "profile" << g_config->profile << "/" << worlddirname << ".stsg"; + std::string slotfile = stream.str(); + world->set_savegame_filename(stream.str()); + world->load_state(); + } + + std::ostringstream title; + title << world->get_title() << " (" << world->get_num_solved_levels() << "/" << world->get_num_levels() << ")"; + add_entry(i++, title.str()); m_contrib_worlds.push_back(std::move(world)); } } diff --git a/src/supertux/world.cpp b/src/supertux/world.cpp index f2e83002abf..05470f89aaf 100644 --- a/src/supertux/world.cpp +++ b/src/supertux/world.cpp @@ -34,6 +34,7 @@ World* World::current_ = NULL; World::World() : + worldname(), levels(), basedir(), savegame_filename(), @@ -85,6 +86,7 @@ void World::load(const std::string& filename) { basedir = FileSystem::dirname(filename); + worldname = basedir + "worldmap.stwm"; lisp::Parser parser; const lisp::Lisp* root = parser.parse(filename); @@ -115,12 +117,19 @@ World::load(const std::string& filename) for(const char* const* filename = files; *filename != 0; ++filename) { if(StringUtil::has_suffix(*filename, ".stl")) { - levels.push_back(path + *filename); + Level level; + level.fullpath = path + *filename; + level.name = *filename; + levels.push_back(level); } } PHYSFS_freeList(files); - std::sort(levels.begin(), levels.end(), StringUtil::numeric_less); + std::sort(levels.begin(), levels.end(), + [](const Level& lhs, const Level& rhs) + { + return StringUtil::numeric_less(lhs.fullpath, rhs.fullpath); + }); } void @@ -197,7 +206,12 @@ World::load_state() { using namespace scripting; - if(PHYSFS_exists(savegame_filename.c_str())) { + if(!PHYSFS_exists(savegame_filename.c_str())) + { + log_info << savegame_filename << ": doesn't exist, not loading state" << std::endl; + } + else + { try { lisp::Parser parser; const lisp::Lisp* root = parser.parse(savegame_filename); @@ -240,7 +254,7 @@ World::load_state() const std::string& World::get_level_filename(unsigned int i) const { - return levels[i]; + return levels[i].fullpath; } unsigned int @@ -249,6 +263,71 @@ World::get_num_levels() const return levels.size(); } +int +World::get_num_solved_levels() const +{ + int num_solved_levels = 0; + + HSQUIRRELVM vm = scripting::global_vm; + int oldtop = sq_gettop(vm); + + sq_pushroottable(vm); + sq_pushstring(vm, "state", -1); + if(SQ_FAILED(sq_get(vm, -2))) + { + log_warning << "failed to get 'state' table" << std::endl; + } + else + { + sq_pushstring(vm, "worlds", -1); + if(SQ_FAILED(sq_get(vm, -2))) + { + log_warning << "failed to get 'state.worlds' table" << std::endl; + } + else + { + sq_pushstring(vm, worldname.c_str(), -1); + if(SQ_FAILED(sq_get(vm, -2))) + { + log_warning << "failed to get state.worlds['" << worldname << "']" << std::endl; + } + else + { + sq_pushstring(vm, "levels", -1); + if(SQ_FAILED(sq_get(vm, -2))) + { + log_warning << "failed to get state.worlds['" << worldname << "'].levels" << std::endl; + } + else + { + for(auto level : levels) + { + sq_pushstring(vm, level.name.c_str(), -1); + if(SQ_FAILED(sq_get(vm, -2))) + { + log_warning << "failed to get state.worlds['" << worldname << "'].levels['" + << level.name << "']" << std::endl; + } + else + { + bool solved = scripting::read_bool(vm, "solved"); + if (solved) + { + num_solved_levels += 1; + } + sq_pop(vm, 1); + } + } + } + } + } + } + + sq_settop(vm, oldtop); + + return num_solved_levels; +} + const std::string& World::get_basedir() const { diff --git a/src/supertux/world.hpp b/src/supertux/world.hpp index bab44e954a4..c976c603788 100644 --- a/src/supertux/world.hpp +++ b/src/supertux/world.hpp @@ -45,6 +45,7 @@ class World void load_state(); unsigned int get_num_levels() const; + int get_num_solved_levels() const; const std::string& get_level_filename(unsigned int i) const; const std::string& get_basedir() const; @@ -55,7 +56,14 @@ class World void run(); private: - std::vector levels; + std::string worldname; + struct Level + { + std::string fullpath; + std::string name; + }; + + std::vector levels; std::string basedir; std::string savegame_filename; /// squirrel table that saves persistent state (about the world)