X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Flevel_subset.cpp;h=9d1b246b64bb44b90e9d8119737db2bb4abd64a3;hb=e8ad98fce495724db80d89a14de98815e0b7e877;hp=f4011211ee5c44c8b1bf7f46ccc7a55fa2423145;hpb=9a756d020e12c792adbd6bb3970ce5a6829e35de;p=supertux.git diff --git a/src/level_subset.cpp b/src/level_subset.cpp index f4011211e..9d1b246b6 100644 --- a/src/level_subset.cpp +++ b/src/level_subset.cpp @@ -18,20 +18,38 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. -#include "setup.h" +#include + +#include +#include +#include +#include +#include "app/setup.h" #include "level.h" -#include "globals.h" -#include "screen/surface.h" +#include "resources.h" +#include "app/globals.h" +#include "video/surface.h" #include "level_subset.h" +#include "lisp/parser.h" +#include "lisp/lisp.h" + +using namespace SuperTux; + +static bool has_suffix(const std::string& data, const std::string& suffix) +{ + if (data.length() >= suffix.length()) + return data.compare(data.length() - suffix.length(), suffix.length(), suffix) == 0; + else + return false; +} LevelSubset::LevelSubset() - : image(0), levels(0) + : levels(0) { } LevelSubset::~LevelSubset() { - delete image; } void LevelSubset::create(const std::string& subset_name) @@ -41,113 +59,76 @@ void LevelSubset::create(const std::string& subset_name) new_subset.name = subset_name; new_subset.title = "Unknown Title"; new_subset.description = "No description so far."; + new_subset.hide_from_contribs = false; new_subset.save(); - //new_lev.save(subset_name, 1, 0); } -void LevelSubset::parse (lisp_object_t* cursor) +void LevelSubset::read_info_file(const std::string& info_file) { - while(!lisp_nil_p(cursor)) - { - lisp_object_t* cur = lisp_car(cursor); - char *s; + lisp::Parser parser; + std::auto_ptr root (parser.parse(info_file)); - if (!lisp_cons_p(cur) || !lisp_symbol_p (lisp_car(cur))) - { - printf("Not good"); - } - else - { - if (strcmp(lisp_symbol(lisp_car(cur)), "title") == 0) - { - if(( s = lisp_string(lisp_car(lisp_cdr(cur)))) != NULL) - { - title = s; - } - } - else if (strcmp(lisp_symbol(lisp_car(cur)), "description") == 0) - { - if(( s = lisp_string(lisp_car(lisp_cdr(cur)))) != NULL) - { - description = s; - } - } - } - cursor = lisp_cdr (cursor); - } + const lisp::Lisp* info = root->get_lisp("supertux-level-subset"); + if(!info) + throw std::runtime_error("File is not a levelsubset file"); + + hide_from_contribs = false; + + info->get("title", title); + info->get("description", description); + info->get_vector("levels", levels); + info->get("hide-from-contribs", hide_from_contribs); } -void LevelSubset::load(const char* subset) +void LevelSubset::load(const std::string& subset) { - FILE* fi; - char filename[1024]; - char str[1024]; - int i; - lisp_object_t* root_obj = 0; - name = subset; - - snprintf(filename, 1024, "%s/levels/%s/info", st_dir, subset); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/levels/%s/info", datadir.c_str(), subset); - if(faccessible(filename)) - { - fi = fopen(filename, "r"); - if (fi == NULL) + + // Check in which directory our subset is located (ie. ~/.supertux/ + // or SUPERTUX_DATADIR) + std::string filename = get_resource_filename( + std::string("levels/") + subset + "/info"); + if(filename == "") { + std::stringstream msg; + msg << "Couldn't find level subset '" << subset << "'."; + throw new std::runtime_error(msg.str()); + } + + try { + read_info_file(filename); + } catch(std::exception& e) { + std::stringstream msg; + msg << "Couldn't parse info file '" << filename << "': " << e.what(); + throw new std::runtime_error(msg.str()); + } + + // test is a worldmap exists + has_worldmap = false; + std::string worldmap = get_resource_filename( + std::string("levels/") + subset + "/worldmap.stwm"); + if(worldmap != "") { + has_worldmap = true; + } + + if (levels.empty()) + { // Level info file doesn't define any levels, so read the + // directory to see what we can find + std::set files; + + filename = datadir + "/levels/" + subset + "/"; + files = FileSystem::read_directory(filename); + + filename = st_dir + "/levels/" + subset + "/"; + std::set user_files = FileSystem::read_directory(filename); + files.insert(user_files.begin(), user_files.end()); + + for(std::set::iterator i = files.begin(); i != files.end(); ++i) { - perror(filename); - } - lisp_stream_t stream; - lisp_stream_init_file (&stream, fi); - root_obj = lisp_read (&stream); - - if (root_obj->type == LISP_TYPE_EOF || root_obj->type == LISP_TYPE_PARSE_ERROR) - { - printf("World: Parse Error in file %s", filename); - } - - lisp_object_t* cur = lisp_car(root_obj); - - if (!lisp_symbol_p (cur)) - { - printf("World: Read error in %s",filename); - } - - if (strcmp(lisp_symbol(cur), "supertux-level-subset") == 0) - { - parse(lisp_cdr(root_obj)); - - } - - lisp_free(root_obj); - fclose(fi); - - snprintf(str, 1024, "%s.png", filename); - if(faccessible(str)) - { - delete image; - image = new Surface(str,IGNORE_ALPHA); - } - else - { - snprintf(filename, 1024, "%s/images/status/level-subset-info.png", datadir.c_str()); - delete image; - image = new Surface(filename,IGNORE_ALPHA); + if (has_suffix(*i, ".stl")) + levels.push_back(get_resource_filename( + std::string("levels/" + subset+ "/" + *i))); } } - - for(i=1; i != -1; ++i) - { - /* Get the number of levels in this subset */ - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", st_dir, subset,i); - if(!faccessible(filename)) - { - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", datadir.c_str(), subset,i); - if(!faccessible(filename)) - break; - } - } - levels = --i; } void @@ -159,11 +140,11 @@ LevelSubset::save() /* Save data file: */ filename = "/levels/" + name + "/"; - fcreatedir(filename.c_str()); + FileSystem::fcreatedir(filename.c_str()); filename = std::string(st_dir) + "/levels/" + name + "/info"; - if(!fwriteable(filename.c_str())) + if(!FileSystem::fwriteable(filename.c_str())) filename = datadir + "/levels/" + name + "/info"; - if(fwriteable(filename.c_str())) + if(FileSystem::fwriteable(filename.c_str())) { fi = fopen(filename.c_str(), "w"); if (fi == NULL) @@ -172,7 +153,7 @@ LevelSubset::save() } /* Write header: */ - fprintf(fi,";SuperTux-Level-Subset\n"); + fprintf(fi,";; SuperTux-Level-Subset\n"); fprintf(fi,"(supertux-level-subset\n"); /* Save title info: */ @@ -181,25 +162,35 @@ LevelSubset::save() /* Save the description: */ fprintf(fi," (description \"%s\")\n", description.c_str()); + /* Save the hide from Contrbis menu boolean: */ + fprintf(fi," (hide-from-contribs %s)\n", hide_from_contribs ? "#t" : "#f"); + fprintf( fi,")"); fclose(fi); } } +void +LevelSubset::add_level(const std::string& name) +{ + levels.push_back(name); +} + std::string LevelSubset::get_level_filename(unsigned int num) { - char filename[1024]; - - // Load data file: - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", st_dir, - name.c_str(), num); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", datadir.c_str(), - name.c_str(), num); - - return std::string(filename); + assert(num < levels.size()); + return levels[num]; } -/* EOF */ +std::string +LevelSubset::get_worldmap_filename() +{ + return std::string("/levels/" + name + "/worldmap.stwm"); +} +int +LevelSubset::get_num_levels() const +{ + return levels.size(); +}