Unified Messaging Subsystem
[supertux.git] / src / level_subset.cpp
1 //  $Id$
2 // 
3 //  SuperTux
4 //  Copyright (C) 2004 SuperTux Development Team, see AUTHORS for details
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 // 
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 //  02111-1307, USA.
20 #include <config.h>
21
22 #include <sstream>
23 #include <stdexcept>
24 #include <assert.h>
25 #include <unistd.h>
26 #include <physfs.h>
27 #include "level.hpp"
28 #include "msg.hpp"
29 #include "resources.hpp"
30 #include "file_system.hpp"
31 #include "video/surface.hpp"
32 #include "level_subset.hpp"
33 #include "lisp/parser.hpp"
34 #include "lisp/lisp.hpp"
35 #include "lisp/writer.hpp"
36
37 static bool has_suffix(const std::string& data, const std::string& suffix)
38 {
39   if (data.length() >= suffix.length())
40     return data.compare(data.length() - suffix.length(), suffix.length(), suffix) == 0;
41   else
42     return false;
43 }
44
45 LevelSubset::LevelSubset()
46   : levels(0)
47 {
48 }
49
50 LevelSubset::~LevelSubset()
51 {
52 }
53
54 void LevelSubset::create(const std::string& subset_name)
55 {
56   Level new_lev;
57   LevelSubset new_subset;
58   new_subset.name = subset_name;
59   new_subset.title = "Unknown Title";
60   new_subset.description = "No description so far.";
61   new_subset.hide_from_contribs = false;
62   new_subset.save();
63 }
64
65 void LevelSubset::read_info_file(const std::string& info_file)
66 {
67   lisp::Parser parser;
68   std::auto_ptr<lisp::Lisp> root (parser.parse(info_file));
69
70   const lisp::Lisp* info = root->get_lisp("supertux-level-subset");
71   if(!info)
72     throw std::runtime_error("File is not a levelsubset file");
73
74   hide_from_contribs = false;
75
76   info->get("title", title);
77   info->get("description", description);
78   info->get_vector("levels", levels);
79   info->get("hide-from-contribs", hide_from_contribs);
80 }
81
82 void LevelSubset::load(const std::string& subset)
83 {
84   name = subset;
85   
86   std::string infofile = subset + "/info";
87   try {
88     read_info_file(infofile);
89   } catch(std::exception& e) {
90     std::stringstream msg;
91     msg << "Couldn't parse info file '" << infofile << "': " << e.what();
92     throw std::runtime_error(msg.str());
93   }
94
95   // test is a worldmap exists
96   has_worldmap = false;
97   std::string worldmap = subset + "/worldmap.stwm";
98   if(PHYSFS_exists(worldmap.c_str())) {
99     has_worldmap = true;
100   }
101
102   if (levels.empty()) { 
103     // Level info file doesn't define any levels, so read the
104     // directory to see what we can find
105       
106     std::string path = subset + "/";
107     char** files = PHYSFS_enumerateFiles(path.c_str());
108     if(!files) {
109       msg_warning("Couldn't read subset dir '" 
110                 << path << "'");
111       return;
112     }
113
114     for(const char* const* filename = files; *filename != 0; ++filename) {
115       if(has_suffix(*filename, ".stl")) {
116         levels.push_back(path + *filename);
117       }
118     }
119     PHYSFS_freeList(files);
120   }
121 }
122
123 void
124 LevelSubset::save()
125 {
126   /* Save data file: */
127   std::string filename = name + "/info";
128   lisp::Writer writer(filename);
129
130   writer.start_list("supertux-level-subset");
131   writer.write_string("title", title);
132   writer.write_string("description", description);
133   writer.write_bool("hide-from-contribs", hide_from_contribs);
134   writer.end_list("supertux-level-subset");
135 }
136
137 void
138 LevelSubset::add_level(const std::string& name)
139 {
140   levels.push_back(name);
141 }
142
143 std::string
144 LevelSubset::get_level_filename(unsigned int num)
145 {
146   assert(num < levels.size());
147   return levels[num];
148 }
149
150 std::string
151 LevelSubset::get_worldmap_filename()
152 {
153   return std::string(name + "/worldmap.stwm");
154 }
155
156 int
157 LevelSubset::get_num_levels() const
158 {
159   return levels.size();
160 }