Add license text to the top of every source file.
[Tsunagari.git] / src / client-conf.cpp
blobddbd08ab2d066181506983f332041067b38feb6d
1 /****************************
2 ** Tsunagari Tile Engine **
3 ** client-conf.cpp **
4 ** Copyright 2012 OmegaSDG **
5 ****************************/
7 // **********
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // **********
27 #include <iostream>
28 #include <fstream>
30 #include <boost/config.hpp>
31 #include <boost/program_options.hpp>
32 #include <boost/program_options/detail/config_file.hpp>
33 #include <boost/program_options/parsers.hpp>
35 #include "client-conf.h"
36 #include "nbcl/nbcl.h"
37 #include "string.h"
39 Conf conf; // Project-wide global configuration.
41 Conf::Conf()
43 worldFilename = "";
44 if (!strcmp(DEF_ENGINE_VERBOSITY, "quiet"))
45 conf.verbosity = V_QUIET;
46 else if (!strcmp(DEF_ENGINE_VERBOSITY, "normal"))
47 conf.verbosity = V_NORMAL;
48 else if (!strcmp(DEF_ENGINE_VERBOSITY, "verbose"))
49 conf.verbosity = V_VERBOSE;
50 if (!strcmp(DEF_ENGINE_HALTING, "fatal"))
51 conf.halting = FATAL;
52 else if (!strcmp(DEF_ENGINE_HALTING, "script"))
53 conf.halting = SCRIPT;
54 else if (!strcmp(DEF_ENGINE_HALTING, "error"))
55 conf.halting = ERROR;
56 windowSize.x = DEF_WINDOW_WIDTH;
57 windowSize.y = DEF_WINDOW_HEIGHT;
58 fullscreen = DEF_WINDOW_FULLSCREEN;
59 audioEnabled = DEF_AUDIO_ENABLED;
60 cacheEnabled = DEF_CACHE_ENABLED;
61 cacheTTL = DEF_CACHE_TTL;
62 cacheSize = DEF_CACHE_SIZE;
63 persistInit = 0;
64 persistCons = 0;
67 bool Conf::validate(const char* filename)
69 if (conf.worldFilename == "") {
70 Log::fatal(filename, "\"[engine] world\" option or equivalent command line option expected");
71 return false;
73 return true;
76 /* Output compiled-in engine defaults. */
77 static void defaultsQuery()
79 std::cerr << "CLIENT_CONF_PATH: "
80 << CLIENT_CONF_PATH << std::endl;
81 std::cerr << "BASE_ZIP_PATH: "
82 << BASE_ZIP_PATH << std::endl;
83 std::cerr << "XML_DTD_PATH: "
84 << XML_DTD_PATH << std::endl;
85 std::cerr << "DEF_ENGINE_VERBOSITY: "
86 << DEF_ENGINE_VERBOSITY << std::endl;
87 std::cerr << "DEF_ENGINE_HALTING: "
88 << DEF_ENGINE_HALTING << std::endl;
89 std::cerr << "DEF_WINDOW_WIDTH: "
90 << DEF_WINDOW_WIDTH << std::endl;
91 std::cerr << "DEF_WINDOW_HEIGHT: "
92 << DEF_WINDOW_HEIGHT << std::endl;
93 std::cerr << "DEF_WINDOW_FULLSCREEN: "
94 << DEF_WINDOW_FULLSCREEN << std::endl;
95 std::cerr << "DEF_AUDIO_ENABLED: "
96 << DEF_AUDIO_ENABLED << std::endl;
97 std::cerr << "DEF_CACHE_ENABLED: "
98 << DEF_CACHE_ENABLED << std::endl;
99 std::cerr << "DEF_CACHE_TTL: "
100 << DEF_CACHE_TTL << std::endl;
101 std::cerr << "DEF_CACHE_SIZE: "
102 << DEF_CACHE_SIZE << std::endl;
106 * Load the values we need to start initializing the game from an ini file.
108 * We need to know what size window to create and which World to load. This
109 * information will be stored in an ini file which we parse here.
111 * @param filename Name of the ini file to load from.
113 * @return false if error occured during processing
115 bool parseConfig(const char* filename)
117 namespace pod = boost::program_options::detail;
119 conf.cacheEnabled = DEF_CACHE_TTL && DEF_CACHE_SIZE;
121 std::ifstream config(filename);
122 if (!config) {
123 Log::err(filename, "could not parse config");
124 return false;
127 std::set<std::string> options;
128 std::map<std::string, std::string> parameters;
129 options.insert("*");
131 for (pod::config_file_iterator i(config, options), e ; i != e; ++i)
132 parameters[i->string_key] = i->value[0];
134 if (!parameters["engine.world"].empty())
135 conf.worldFilename = parameters["engine.world"];
137 if (!parameters["engine.datapath"].empty())
138 conf.dataPath = splitStr(parameters["engine.datapath"], ",");
140 if (!parameters["window.width"].empty())
141 conf.windowSize.x = atoi(parameters["window.width"].c_str());
143 if (!parameters["window.height"].empty())
144 conf.windowSize.y = atoi(parameters["window.height"].c_str());
146 if (!parameters["window.fullscreen"].empty())
147 conf.fullscreen = parseBool(parameters["window.fullscreen"]);
149 if (parameters["audio.enabled"].size())
150 conf.audioEnabled = parseBool(parameters["audio.enabled"]);
151 else
152 conf.audioEnabled = true;
154 if (!parameters["cache.enabled"].empty()) {
155 if (parseBool(parameters["cache.enabled"]))
156 conf.cacheEnabled = true;
157 else
158 conf.cacheEnabled = false;
161 if (parameters["cache.ttl"].empty())
162 conf.cacheTTL = DEF_CACHE_TTL;
163 else {
164 if (atoi(parameters["cache.ttl"].c_str()) == 0)
165 conf.cacheEnabled = 0;
166 conf.cacheTTL = atoi(parameters["cache.ttl"].c_str());
169 if (parameters["cache.size"].empty())
170 conf.cacheSize = DEF_CACHE_SIZE;
171 else {
172 if (atoi(parameters["cache.size"].c_str()) == 0)
173 conf.cacheEnabled = 0;
174 conf.cacheSize = atoi(parameters["cache.size"].c_str());
177 std::string verbosity = parameters["engine.verbosity"];
178 if (verbosity.empty())
180 else if (verbosity == "quiet")
181 conf.verbosity = V_QUIET;
182 else if (verbosity == "normal")
183 conf.verbosity = V_NORMAL;
184 else if (verbosity == "verbose")
185 conf.verbosity = V_VERBOSE;
186 else {
187 Log::err(filename, "unknown value for \"[engine] verbosity\", using default");
190 std::string halting = parameters["engine.halting"];
191 if (halting.empty())
193 else if (halting == "fatal")
194 conf.halting = FATAL;
195 else if (halting == "script")
196 conf.halting = SCRIPT;
197 else if (halting == "error")
198 conf.halting = ERROR;
199 else {
200 Log::err(filename, "unknown value for \"[engine] halting\", using default");
203 return true;
206 //! Parse and process command line options and arguments.
207 bool parseCommandLine(int argc, char* argv[])
209 NBCL cmd(argc, argv);
211 cmd.setStrayArgsDesc("[WORLD FILE]");
213 cmd.insert("-h", "--help", "", "Display this help message");
214 cmd.insert("-c", "--config", "<config file>", "Client config file to use");
215 cmd.insert("-p", "--datapath", "<file,file,...>", "Prepend zips to data path");
216 cmd.insert("-q", "--quiet", "", "Display only fatal errors");
217 cmd.insert("", "--normal", "", "Display all errors");
218 cmd.insert("-v", "--verbose", "", "Display additional information");
219 cmd.insert("-t", "--cache-ttl", "<seconds>", "Cache time-to-live in seconds");
220 cmd.insert("-m", "--cache-size", "<megabytes>", "Cache size in megabytes");
221 cmd.insert("-s", "--size", "<WxH>", "Window dimensions");
222 cmd.insert("-f", "--fullscreen", "", "Run in fullscreen mode");
223 cmd.insert("-w", "--window", "", "Run in windowed mode");
224 cmd.insert("", "--fatal-halt", "", "Stop engine only on fatal errors");
225 cmd.insert("", "--script-halt", "", "Stop engine on script errors");
226 cmd.insert("", "--error-halt", "", "Stop engine on all errors");
227 cmd.insert("", "--no-audio", "", "Disable audio");
228 cmd.insert("", "--query", "", "Query compiled-in engine defaults");
229 cmd.insert("", "--version", "", "Print the engine version string");
231 if (!cmd.parse()) {
232 cmd.usage();
233 return false;
236 std::vector<std::string> strayArgs = cmd.getStrayArgsList();
237 if (strayArgs.size() > 1) {
238 cmd.usage();
239 return false;
241 else if (strayArgs.size() == 1)
242 conf.worldFilename = strayArgs[0];
244 if (cmd.check("--help")) {
245 cmd.usage();
246 return false;
249 if (cmd.check("--version")) {
250 std::cout << TSUNAGARI_RELEASE_VERSION << std::endl;
251 return false;
254 if (cmd.check("--query")) {
255 defaultsQuery();
256 return false;
259 if (cmd.check("--config")) {
260 if (!parseConfig(cmd.get("--config").c_str()))
261 return false;
264 if (cmd.check("--datapath"))
265 conf.dataPath = splitStr(cmd.get("--datapath"), ",");
267 int verbcount = 0;
268 if (cmd.check("--quiet")) {
269 conf.verbosity = V_QUIET;
270 verbcount++;
272 if (cmd.check("--normal")) {
273 conf.verbosity = V_NORMAL;
274 verbcount++;
276 if (cmd.check("--verbose")) {
277 conf.verbosity = V_VERBOSE;
278 verbcount++;
280 if (verbcount > 1)
281 Log::err("cmdline", "multiple verbosity flags on cmdline, using most verbose");
283 int haltcount = 0;
284 if (cmd.check("--fatal-halt")) {
285 conf.halting = FATAL;
286 haltcount++;
288 if (cmd.check("--script-halt")) {
289 conf.halting = SCRIPT;
290 haltcount++;
292 if (cmd.check("--error-halt")) {
293 conf.halting = ERROR;
294 haltcount++;
296 if (haltcount > 1)
297 Log::err("cmdline", "multiple halting flags on cmdline, using most stringent");
299 if (cmd.check("--no-audio"))
300 conf.audioEnabled = false;
302 if (cmd.check("--cache-ttl")) {
303 conf.cacheTTL = atoi(cmd.get("--cache-ttl").c_str());
304 if (conf.cacheTTL == 0)
305 conf.cacheEnabled = false;
308 if (cmd.check("--cache-size")) {
309 conf.cacheSize = atoi(cmd.get("--cache-size").c_str());
310 if (conf.cacheSize == 0)
311 conf.cacheEnabled = false;
314 if (cmd.check("--size")) {
315 std::vector<std::string> dim = splitStr(cmd.get("--size"), "x");
316 if (dim.size() != 2) {
317 Log::fatal("cmdline", "invalid argument for -s/--size");
318 return false;
320 conf.windowSize.x = atoi(dim[0].c_str());
321 conf.windowSize.y = atoi(dim[1].c_str());
324 if (cmd.check("--fullscreen") && cmd.check("--window")) {
325 Log::fatal("cmdline", "-f/--fullscreen and -w/--window mutually exclusive");
326 return false;
329 if (cmd.check("--fullscreen"))
330 conf.fullscreen = true;
332 if (cmd.check("--window"))
333 conf.fullscreen = false;
335 return true;