The Battle for Wesnoth  1.15.0-dev
wesnoth.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "addon/manager.hpp"
16 #include "build_info.hpp"
17 #include "commandline_options.hpp" // for commandline_options, etc
18 #include "config.hpp" // for config, config::error, etc
19 #include "cursor.hpp" // for set, CURSOR_TYPE::NORMAL, etc
20 #include "editor/editor_main.hpp"
21 #include "filesystem.hpp" // for filesystem::file_exists, filesystem::io_exception, etc
22 #include "floating_label.hpp"
23 #include "font/error.hpp" // for error
24 #include "font/font_config.hpp" // for load_font_config, etc
25 #include "formula/formula.hpp" // for formula_error
26 #include "game_config.hpp" // for path, debug, debug_lua, etc
27 #include "game_config_manager.hpp" // for game_config_manager, etc
28 #include "game_end_exceptions.hpp"
29 #include "game_launcher.hpp" // for game_launcher, etc
30 #include "gettext.hpp"
31 #include "gui/core/event/handler.hpp" // for tmanager
34 #include "gui/dialogs/message.hpp" // for show_error_message
35 #include "gui/dialogs/title_screen.hpp" // for title_screen, etc
36 #include "gui/gui.hpp" // for init
37 #include "picture.hpp" // for flush_cache, etc
38 #include "log.hpp" // for LOG_STREAM, general, logger, etc
39 #include "preferences/general.hpp" // for core_id, etc
43 #include "sdl/exception.hpp" // for exception
44 #include "sdl/rect.hpp"
45 #include "serialization/binary_or_text.hpp" // for config_writer
46 #include "serialization/parser.hpp" // for read
47 #include "serialization/preprocessor.hpp" // for preproc_define, etc
49 #include "serialization/schema_validator.hpp" // for strict_validation_enabled and schema_validator
50 #include "sound.hpp" // for commit_music_changes, etc
51 #include "statistics.hpp" // for fresh_stats
52 #include "utils/functional.hpp"
53 #include "game_version.hpp" // for version_info
54 #include "video.hpp" // for CVideo
55 #include "wesconfig.h" // for PACKAGE
56 #include "widgets/button.hpp" // for button
57 #include "wml_exception.hpp" // for wml_exception
58 
59 #ifdef _WIN32
60 #include "log_windows.hpp"
61 
62 #include <float.h>
63 #endif // _WIN32
64 
65 #ifndef _MSC_VER
66 #include <fenv.h>
67 #endif // _MSC_VER
68 
69 #include <SDL.h> // for SDL_Init, SDL_INIT_TIMER
70 
71 #include <boost/iostreams/categories.hpp> // for input, output
72 #include <boost/iostreams/copy.hpp> // for copy
73 #include <boost/iostreams/filter/bzip2.hpp> // for bzip2_compressor, etc
74 
75 #if defined(_MSC_VER)
76 #pragma warning(push)
77 #pragma warning(disable : 4456)
78 #pragma warning(disable : 4458)
79 #endif
80 
81 #include <boost/iostreams/filter/gzip.hpp> // for gzip_compressor, etc
82 
83 #if defined(_MSC_VER)
84 #pragma warning(pop)
85 #endif
86 
87 #include <boost/iostreams/filtering_stream.hpp> // for filtering_stream
88 #include <boost/program_options/errors.hpp> // for error
89 
90 #include <algorithm> // for transform
91 #include <cerrno> // for ENOMEM
92 #include <clocale> // for setlocale, LC_ALL, etc
93 #include <cstdio> // for remove, fprintf, stderr
94 #include <cstdlib> // for srand, exit
95 #include <ctime> // for time, ctime, std::time_t
96 #include <exception> // for exception
97 #include <fstream> // for operator<<, basic_ostream, etc
98 #include <iostream> // for cerr, cout
99 #include <vector>
100 
101 //#define NO_CATCH_AT_GAME_END
102 
103 #ifdef _WIN32
104 
105 #ifdef INADDR_ANY
106 #undef INADDR_ANY
107 #endif
108 
109 #ifdef INADDR_BROADCAST
110 #undef INADDR_BROADCAST
111 #endif
112 
113 #ifdef INADDR_NONE
114 #undef INADDR_NONE
115 #endif
116 
117 #include <windows.h>
118 
119 #endif // _WIN32
120 
121 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
122 #include "gui/widgets/debug.hpp"
123 #endif
124 
125 class end_level_exception;
126 namespace game
127 {
128 struct error;
129 }
130 
131 static lg::log_domain log_config("config");
132 #define LOG_CONFIG LOG_STREAM(info, log_config)
133 
134 #define LOG_GENERAL LOG_STREAM(info, lg::general())
135 
136 static lg::log_domain log_preprocessor("preprocessor");
137 #define LOG_PREPROC LOG_STREAM(info, log_preprocessor)
138 
139 // this is needed to allow identical functionality with clean refactoring
140 // play_game only returns on an error, all returns within play_game can
141 // be replaced with this
142 static void safe_exit(int res)
143 {
144  LOG_GENERAL << "exiting with code " << res << "\n";
145  exit(res);
146 }
147 
148 // maybe this should go in a util file somewhere?
149 template<typename filter>
150 static void encode(const std::string& input_file, const std::string& output_file)
151 {
152  try {
153  std::ifstream ifile(input_file.c_str(), std::ios_base::in | std::ios_base::binary);
154  ifile.peek(); // We need to touch the stream to set the eof bit
155 
156  if(!ifile.good()) {
157  std::cerr << "Input file " << input_file
158  << " is not good for reading. Exiting to prevent bzip2 from segfaulting\n";
159  safe_exit(1);
160  }
161 
162  std::ofstream ofile(output_file.c_str(), std::ios_base::out | std::ios_base::binary);
163 
164  boost::iostreams::filtering_stream<boost::iostreams::output> stream;
165  stream.push(filter());
166  stream.push(ofile);
167 
168  boost::iostreams::copy(ifile, stream);
169  ifile.close();
170 
171  safe_exit(remove(input_file.c_str()));
172  } catch(const filesystem::io_exception& e) {
173  std::cerr << "IO error: " << e.what() << "\n";
174  }
175 }
176 
177 template<typename filter>
178 static void decode(const std::string& input_file, const std::string& output_file)
179 {
180  try {
181  std::ofstream ofile(output_file.c_str(), std::ios_base::out | std::ios_base::binary);
182  std::ifstream ifile(input_file.c_str(), std::ios_base::in | std::ios_base::binary);
183 
184  boost::iostreams::filtering_stream<boost::iostreams::input> stream;
185  stream.push(filter());
186  stream.push(ifile);
187 
188  boost::iostreams::copy(stream, ofile);
189  ifile.close();
190 
191  safe_exit(remove(input_file.c_str()));
192  } catch(const filesystem::io_exception& e) {
193  std::cerr << "IO error: " << e.what() << "\n";
194  }
195 }
196 
197 static void gzip_encode(const std::string& input_file, const std::string& output_file)
198 {
199  encode<boost::iostreams::gzip_compressor>(input_file, output_file);
200 }
201 
202 static void gzip_decode(const std::string& input_file, const std::string& output_file)
203 {
204  decode<boost::iostreams::gzip_decompressor>(input_file, output_file);
205 }
206 
207 static void bzip2_encode(const std::string& input_file, const std::string& output_file)
208 {
209  encode<boost::iostreams::bzip2_compressor>(input_file, output_file);
210 }
211 
212 static void bzip2_decode(const std::string& input_file, const std::string& output_file)
213 {
214  decode<boost::iostreams::bzip2_decompressor>(input_file, output_file);
215 }
216 
217 static void handle_preprocess_command(const commandline_options& cmdline_opts)
218 {
219  preproc_map input_macros;
220 
221  if(cmdline_opts.preprocess_input_macros) {
222  std::string file = *cmdline_opts.preprocess_input_macros;
223  if(filesystem::file_exists(file) == false) {
224  std::cerr << "please specify an existing file. File " << file << " doesn't exist.\n";
225  return;
226  }
227 
228  std::cerr << SDL_GetTicks() << " Reading cached defines from: " << file << "\n";
229 
230  config cfg;
231 
232  try {
234  read(cfg, *stream);
235  } catch(const config::error& e) {
236  std::cerr << "Caught a config error while parsing file '" << file << "':\n" << e.message << std::endl;
237  }
238 
239  int read = 0;
240 
241  // use static preproc_define::read_pair(config) to make a object
242  for(const config::any_child& value : cfg.all_children_range()) {
243  const preproc_map::value_type def = preproc_define::read_pair(value.cfg);
244  input_macros[def.first] = def.second;
245  ++read;
246  }
247 
248  std::cerr << SDL_GetTicks() << " Read " << read << " defines.\n";
249  }
250 
251  const std::string resourceToProcess(*cmdline_opts.preprocess_path);
252  const std::string targetDir(*cmdline_opts.preprocess_target);
253 
254  uint32_t startTime = SDL_GetTicks();
255 
256  // If the users add the SKIP_CORE define we won't preprocess data/core
257  bool skipCore = false;
258  bool skipTerrainGFX = false;
259 
260  // The 'core_defines_map' is the one got from data/core macros
261  preproc_map defines_map(input_macros);
262 
263  if(cmdline_opts.preprocess_defines) {
264  // add the specified defines
265  for(const std::string& define : *cmdline_opts.preprocess_defines) {
266  if(define.empty()) {
267  std::cerr << "empty define supplied\n";
268  continue;
269  }
270 
271  LOG_PREPROC << "adding define: " << define << '\n';
272  defines_map.emplace(define, preproc_define(define));
273 
274  if(define == "SKIP_CORE") {
275  std::cerr << "'SKIP_CORE' defined.\n";
276  skipCore = true;
277  } else if(define == "NO_TERRAIN_GFX") {
278  std::cerr << "'NO_TERRAIN_GFX' defined." << std::endl;
279  skipTerrainGFX = true;
280  }
281  }
282  }
283 
284  // add the WESNOTH_VERSION define
285  defines_map["WESNOTH_VERSION"] = preproc_define(game_config::wesnoth_version.str());
286 
287  std::cerr << "added " << defines_map.size() << " defines.\n";
288 
289  // preprocess core macros first if we don't skip the core
290  if(skipCore == false) {
291  std::cerr << "preprocessing common macros from 'data/core' ...\n";
292 
293  // process each folder explicitly to gain speed
294  preprocess_resource(game_config::path + "/data/core/macros", &defines_map);
295 
296  if(skipTerrainGFX == false) {
297  preprocess_resource(game_config::path + "/data/core/terrain-graphics", &defines_map);
298  }
299 
300  std::cerr << "acquired " << (defines_map.size() - input_macros.size()) << " 'data/core' defines.\n";
301  } else {
302  std::cerr << "skipped 'data/core'\n";
303  }
304 
305  // preprocess resource
306  std::cerr << "preprocessing specified resource: " << resourceToProcess << " ...\n";
307 
308  preprocess_resource(resourceToProcess, &defines_map, true, true, targetDir);
309  std::cerr << "acquired " << (defines_map.size() - input_macros.size()) << " total defines.\n";
310 
311  if(cmdline_opts.preprocess_output_macros) {
312  std::string outputFileName = "_MACROS_.cfg";
313  if(!cmdline_opts.preprocess_output_macros->empty()) {
314  outputFileName = *cmdline_opts.preprocess_output_macros;
315  }
316 
317  std::string outputPath = targetDir + "/" + outputFileName;
318 
319  std::cerr << "writing '" << outputPath << "' with " << defines_map.size() << " defines.\n";
320 
322  if(!out->fail()) {
323  config_writer writer(*out, false);
324 
325  for(auto& define_pair : defines_map) {
326  define_pair.second.write(writer, define_pair.first);
327  }
328  } else {
329  std::cerr << "couldn't open the file.\n";
330  }
331  }
332 
333  std::cerr << "preprocessing finished. Took " << SDL_GetTicks() - startTime << " ticks.\n";
334 }
335 
336 static int handle_validate_command(const std::string& file, abstract_validator& validator, const std::vector<std::string>& defines) {
337  preproc_map defines_map;
338  for(const std::string& define : defines) {
339  if(define.empty()) {
340  std::cerr << "empty define supplied\n";
341  continue;
342  }
343 
344  LOG_PREPROC << "adding define: " << define << '\n';
345  defines_map.emplace(define, preproc_define(define));
346  }
347  filesystem::scoped_istream stream = preprocess_file(file, &defines_map);
348  config result;
349  read(result, *stream, &validator);
350  // TODO: Return 1 if any errors found.
351  return 0;
352 }
353 
354 /** Process commandline-arguments */
355 static int process_command_args(const commandline_options& cmdline_opts)
356 {
357  // Options that don't change behavior based on any others should be checked alphabetically below.
358 
359  if(cmdline_opts.userconfig_dir) {
361  }
362 
363  if(cmdline_opts.userconfig_path) {
364  std::cout << filesystem::get_user_config_dir() << '\n';
365  return 0;
366  }
367 
368  if(cmdline_opts.userdata_dir) {
370  }
371 
372  if(cmdline_opts.userdata_path) {
373  std::cout << filesystem::get_user_data_dir() << '\n';
374  return 0;
375  }
376 
377  if(cmdline_opts.data_dir) {
378  const std::string datadir = *cmdline_opts.data_dir;
379 #ifdef _WIN32
380  // use c_str to ensure that index 1 points to valid element since c_str() returns null-terminated string
381  if(datadir.c_str()[1] == ':') {
382 #else
383  if(datadir[0] == '/') {
384 #endif
385  game_config::path = datadir;
386  } else {
387  game_config::path = filesystem::get_cwd() + '/' + datadir;
388  }
389 
391  std::cerr << "Overriding data directory with " << game_config::path << std::endl;
392 
394  std::cerr << "Could not find directory '" << game_config::path << "'\n";
395  throw config::error("directory not found");
396  }
397 
398  // don't update font as we already updating it in game ctor
399  // font_manager_.update_font_path();
400  }
401 
402  if(cmdline_opts.data_path) {
403  std::cout << game_config::path << '\n';
404  return 0;
405  }
406 
407  if(cmdline_opts.debug_lua) {
408  game_config::debug_lua = true;
409  }
410 
411  if(cmdline_opts.gunzip) {
412  const std::string input_file(*cmdline_opts.gunzip);
413  if(!filesystem::is_gzip_file(input_file)) {
414  std::cerr << "file '" << input_file << "'isn't a .gz file\n";
415  return 2;
416  }
417 
418  const std::string output_file(input_file, 0, input_file.length() - 3);
419  gzip_decode(input_file, output_file);
420  }
421 
422  if(cmdline_opts.bunzip2) {
423  const std::string input_file(*cmdline_opts.bunzip2);
424  if(!filesystem::is_bzip2_file(input_file)) {
425  std::cerr << "file '" << input_file << "'isn't a .bz2 file\n";
426  return 2;
427  }
428 
429  const std::string output_file(input_file, 0, input_file.length() - 4);
430  bzip2_decode(input_file, output_file);
431  }
432 
433  if(cmdline_opts.gzip) {
434  const std::string input_file(*cmdline_opts.gzip);
435  const std::string output_file(*cmdline_opts.gzip + ".gz");
436  gzip_encode(input_file, output_file);
437  }
438 
439  if(cmdline_opts.bzip2) {
440  const std::string input_file(*cmdline_opts.bzip2);
441  const std::string output_file(*cmdline_opts.bzip2 + ".bz2");
442  bzip2_encode(input_file, output_file);
443  }
444 
445  if(cmdline_opts.help) {
446  std::cout << cmdline_opts;
447  return 0;
448  }
449 
450  if(cmdline_opts.log) {
451  for(const auto& log_pair : cmdline_opts.log.get()) {
452  const std::string log_domain = log_pair.second;
453  const int severity = log_pair.first;
454  if(!lg::set_log_domain_severity(log_domain, severity)) {
455  std::cerr << "unknown log domain: " << log_domain << '\n';
456  return 2;
457  }
458  }
459  }
460 
461  if(cmdline_opts.logdomains) {
462  std::cout << lg::list_logdomains(*cmdline_opts.logdomains);
463  return 0;
464  }
465 
466  if(cmdline_opts.path) {
467  std::cout << game_config::path << "\n";
468  return 0;
469  }
470 
471  if(cmdline_opts.log_precise_timestamps) {
473  }
474 
475  if(cmdline_opts.rng_seed) {
476  srand(*cmdline_opts.rng_seed);
477  }
478 
479  if(cmdline_opts.screenshot || cmdline_opts.render_image) {
480  SDL_setenv("SDL_VIDEODRIVER", "dummy", 1);
481  }
482 
483  if(cmdline_opts.strict_validation) {
485  }
486 
487  if(cmdline_opts.version) {
488  std::cout << "Battle for Wesnoth" << " " << game_config::wesnoth_version.str() << "\n\n";
489  std::cout << "Library versions:\n" << game_config::library_versions_report() << '\n';
490  std::cout << "Optional features:\n" << game_config::optional_features_report();
491 
492  return 0;
493  }
494 
495  if(cmdline_opts.report) {
496  std::cout << "\n========= BUILD INFORMATION =========\n\n" << game_config::full_build_report();
497  return 0;
498  }
499 
500  if(cmdline_opts.validate_schema) {
502  validator.set_create_exceptions(false); // Don't crash if there's an error, just go ahead anyway
503  handle_validate_command(*cmdline_opts.validate_schema, validator, {});
504  }
505 
506  // Options changing their behavior dependent on some others should be checked below.
507 
508  if(cmdline_opts.preprocess) {
509  handle_preprocess_command(cmdline_opts);
510  return 0;
511  }
512 
513  if(cmdline_opts.validate_wml) {
514  std::string schema_path;
515  if(cmdline_opts.validate_with) {
516  schema_path = *cmdline_opts.validate_with;
517  } else {
518  schema_path = filesystem::get_wml_location("schema/game_config.cfg");
519  }
520  schema_validation::schema_validator validator(schema_path);
521  validator.set_create_exceptions(false); // Don't crash if there's an error, just go ahead anyway
522  handle_validate_command(*cmdline_opts.validate_wml, validator, boost::get_optional_value_or(cmdline_opts.preprocess_defines, {}));
523  }
524 
525  // Not the most intuitive solution, but I wanted to leave current semantics for now
526  return -1;
527 }
528 
529 /**
530  * I would prefer to setup locale first so that early error
531  * messages can get localized, but we need the game_launcher
532  * initialized to have filesystem::get_intl_dir() to work. Note: setlocale()
533  * does not take GUI language setting into account.
534  */
535 static void init_locale()
536 {
537 #if defined _WIN32 || defined __APPLE__
538  setlocale(LC_ALL, "English");
539 #else
540  std::setlocale(LC_ALL, "C");
541 #endif
542 
543  const std::string& intl_dir = filesystem::get_intl_dir();
544 
545  translation::bind_textdomain(PACKAGE, intl_dir.c_str(), "UTF-8");
546  translation::bind_textdomain(PACKAGE "-lib", intl_dir.c_str(), "UTF-8");
548 }
549 
550 /**
551  * Print an alert and instructions to stderr about early initialization errors.
552  *
553  * This is provided as an aid for users dealing with potential data dir
554  * configuration issues. The first code to read core WML *has* the
555  * responsibility to call this function in the event of a problem, to inform
556  * the user of the most likely possible cause and suggest a course of action
557  * to solve the issue.
558  */
560 {
561  // NOTE: wrap output to 80 columns.
562  std::cerr << '\n'
563  << "An error at this point during initialization usually indicates that the data\n"
564  << "directory above was not correctly set or detected. Try passing the correct path\n"
565  << "in the command line with the --data-dir switch or as the only argument.\n";
566 }
567 
568 /**
569  * Handles the lua script command line arguments if present.
570  * This function will only run once.
571  */
573 {
574  static bool first_time = true;
575 
576  if(!first_time) {
577  return;
578  }
579 
580  first_time = false;
581 
582  if(!game->init_lua_script()) {
583  // std::cerr << "error when loading lua scripts at startup\n";
584  // std::cerr << "could not load lua script: " << *cmdline_opts.script_file << std::endl;
585  }
586 }
587 
588 #ifdef _MSC_VER
589 static void check_fpu()
590 {
591  uint32_t f_control;
592 
593  if(_controlfp_s(&f_control, 0, 0) == 0) {
594  uint32_t unused;
595  uint32_t rounding_mode = f_control & _MCW_RC;
596  uint32_t precision_mode = f_control & _MCW_PC;
597 
598  if(rounding_mode != _RC_NEAR) {
599  std::cerr << "Floating point rounding mode is currently '"
600  << ((rounding_mode == _RC_CHOP)
601  ? "chop"
602  : (rounding_mode == _RC_UP)
603  ? "up"
604  : (rounding_mode == _RC_DOWN)
605  ? "down"
606  : (rounding_mode == _RC_NEAR) ? "near" : "unknown")
607  << "' setting to 'near'\n";
608 
609  if(_controlfp_s(&unused, _RC_NEAR, _MCW_RC)) {
610  std::cerr << "failed to set floating point rounding type to 'near'\n";
611  }
612  }
613 
614  if(precision_mode != _PC_53) {
615  std::cerr << "Floating point precision mode is currently '"
616  << ((precision_mode == _PC_53)
617  ? "double"
618  : (precision_mode == _PC_24)
619  ? "single"
620  : (precision_mode == _PC_64) ? "double extended" : "unknown")
621  << "' setting to 'double'\n";
622 
623  if(_controlfp_s(&unused, _PC_53, _MCW_PC)) {
624  std::cerr << "failed to set floating point precision type to 'double'\n";
625  }
626  }
627  } else {
628  std::cerr << "_controlfp_s failed.\n";
629  }
630 }
631 #else
632 static void check_fpu()
633 {
634  switch(fegetround()) {
635  case FE_TONEAREST:
636  break;
637  case FE_DOWNWARD:
638  std::cerr << "Floating point precision mode is currently 'downward'";
639  goto reset_fpu;
640  case FE_TOWARDZERO:
641  std::cerr << "Floating point precision mode is currently 'toward-zero'";
642  goto reset_fpu;
643  case FE_UPWARD:
644  std::cerr << "Floating point precision mode is currently 'upward'";
645  goto reset_fpu;
646  default:
647  std::cerr << "Floating point precision mode is currently 'unknown'";
648  goto reset_fpu;
649  reset_fpu:
650  std::cerr << "setting to 'nearest'";
651  fesetround(FE_TONEAREST);
652  break;
653  }
654 }
655 #endif
656 
657 /**
658  * Setups the game environment and enters
659  * the titlescreen or game loops.
660  */
661 static int do_gameloop(const std::vector<std::string>& args)
662 {
663  srand(std::time(nullptr));
664 
665  commandline_options cmdline_opts = commandline_options(args);
667 
668  int finished = process_command_args(cmdline_opts);
669  if(finished != -1) {
670 #ifdef _WIN32
671  if(lg::using_own_console()) {
672  std::cerr << "Press enter to continue..." << std::endl;
673  std::cin.get();
674  }
675 #endif
676 
677  return finished;
678  }
679 
680  const auto game = std::make_unique<game_launcher>(cmdline_opts, args[0].c_str());
681  const int start_ticks = SDL_GetTicks();
682 
683  init_locale();
684 
685  bool res;
686 
687  // Do initialize fonts before reading the game config, to have game
688  // config error messages displayed. fonts will be re-initialized later
689  // when the language is read from the game config.
690  res = font::load_font_config();
691  if(res == false) {
692  std::cerr << "could not initialize fonts\n";
693  // The most common symptom of a bogus data dir path -- warn the user.
695  return 1;
696  }
697 
698  res = game->init_language();
699  if(res == false) {
700  std::cerr << "could not initialize the language\n";
701  return 1;
702  }
703 
704  res = game->init_video();
705  if(res == false) {
706  std::cerr << "could not initialize display\n";
707  return 1;
708  }
709 
711  if(res == false) {
712  std::cerr << "could not initialize image preferences\n";
713  return 1;
714  }
715 
717  res = game->init_joystick();
718  if(res == false) {
719  std::cerr << "could not initialize joystick\n";
720  }
721  }
722 
723  check_fpu();
724  const cursor::manager cursor_manager;
726 
727 #if(defined(_X11) && !defined(__APPLE__)) || defined(_WIN32)
728  SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
729 #endif
730 
731  gui2::init();
732  const gui2::event::manager gui_event_manager;
733 
734  game_config_manager config_manager(cmdline_opts, game->jump_to_editor());
735 
736  gui2::dialogs::loading_screen::display([&res, &config_manager]() {
738  res = config_manager.init_game_config(game_config_manager::NO_FORCE_RELOAD);
739 
740  if(res == false) {
741  std::cerr << "could not initialize game config\n";
742  return;
743  }
744 
746 
747  res = font::load_font_config();
748  if(res == false) {
749  std::cerr << "could not re-initialize fonts for the current language\n";
750  return;
751  }
752 
754 
756  });
757 
758  if(res == false) {
759  return 1;
760  }
761 
762  LOG_CONFIG << "time elapsed: " << (SDL_GetTicks() - start_ticks) << " ms\n";
763 
764  plugins_manager plugins_man(new application_lua_kernel);
765 
766  plugins_context::Reg const callbacks[] {
767  {"play_multiplayer", std::bind(&game_launcher::play_multiplayer, game.get(), game_launcher::MP_CONNECT)},
768  };
769 
770  plugins_context::aReg const accessors[] {
771  {"command_line", std::bind(&commandline_options::to_config, &cmdline_opts)},
772  };
773 
774  plugins_context plugins("titlescreen", callbacks, accessors);
775 
776  plugins.set_callback("exit", [](const config& cfg) { safe_exit(cfg["code"].to_int(0)); }, false);
777 
778  for(;;) {
779  // reset the TC, since a game can modify it, and it may be used
780  // by images in add-ons or campaigns dialogs
782 
784 
785  if(!game->is_loading()) {
786  const config& cfg = config_manager.game_config().child("titlescreen_music");
787  if(cfg) {
788  for(const config& i : cfg.child_range("music")) {
790  }
791 
792  config title_music_config;
793  title_music_config["name"] = game_config::title_music;
794  title_music_config["append"] = true;
795  title_music_config["immediate"] = true;
796  sound::play_music_config(title_music_config);
797  } else {
800  }
801  }
802 
803  handle_lua_script_args(&*game, cmdline_opts);
804 
805  plugins.play_slice();
806  plugins.play_slice();
807 
808  if(cmdline_opts.unit_test) {
809  if(cmdline_opts.timeout) {
810  std::cerr << "The wesnoth built-in timeout feature has been removed.\n" << std::endl;
811  std::cerr << "Please use a platform-specific script which will kill the overtime process instead.\n"
812  << std::endl;
813  std::cerr << "For examples in bash, or in windows cmd, see the forums, or the wesnoth repository."
814  << std::endl;
815  std::cerr
816  << "The bash script is called `run_wml_tests`, the windows script is part of the VC project.\n"
817  << std::endl;
818  }
819 
820  int worker_result = game->unit_test();
821  std::cerr << ((worker_result == 0) ? "PASS TEST " : "FAIL TEST ")
822  << ((worker_result == 3) ? "(INVALID REPLAY)" : "")
823  << ((worker_result == 4) ? "(ERRORED REPLAY)" : "") << ": " << *cmdline_opts.unit_test
824  << std::endl;
825  return worker_result;
826  }
827 
828  if(game->play_test() == false) {
829  return 0;
830  }
831 
832  if(game->play_screenshot_mode() == false) {
833  return 0;
834  }
835 
836  if(game->play_render_image_mode() == false) {
837  return 0;
838  }
839 
840  // Start directly a campaign
841  if(game->goto_campaign() == false) {
842  if(game->jump_to_campaign_id().empty())
843  continue; // Go to main menu
844  else
845  return 1; // we got an error starting the campaign from command line
846  }
847 
848  // Start directly a multiplayer
849  // Eventually with a specified server
850  if(game->goto_multiplayer() == false) {
851  continue; // Go to main menu
852  }
853 
854  // Start directly a commandline multiplayer game
855  if(game->play_multiplayer_commandline() == false) {
856  return 0;
857  }
858 
859  if(game->goto_editor() == false) {
860  return 0;
861  }
862 
863  const font::floating_label_context label_manager;
864 
866 
868 
869  // If loading a game, skip the titlescreen entirely
870  if(game->is_loading()) {
871  if(!game->load_game()) {
872  game->clear_loaded_game();
873  }
874 
875  game->launch_game(should_reload);
876  continue;
877  }
878 
880 
881  /*
882  * Quick explanation of the titlscreen loop:
883  *
884  * The dialog's redraw_background_ flag is initialized as true in the constructor, so the dialog will always
885  * display at least once when this loop is executed. Each time it's opened, the aforementioned flag is set to
886  * false, and any selection that results in leaving the dialog simply sets the window's retval and proceeds to
887  * the appropriate action.
888  *
889  * Certain actions (such as window resizing) set the flag to true, which allows the dialog to reopen with any
890  * layout changes such as those dictated by window resolution.
891  */
893  dlg.show();
894  }
895 
896  switch(dlg.get_retval()) {
898  LOG_GENERAL << "quitting game...\n";
899  return 0;
902  if(!game->play_multiplayer(game_launcher::MP_CONNECT)) {
903  continue;
904  }
905  break;
908  if(!game->play_multiplayer(game_launcher::MP_HOST)) {
909  continue;
910  }
911  break;
914  if(!game->play_multiplayer(game_launcher::MP_LOCAL)) {
915  continue;
916  }
917  break;
919  gui2::dialogs::loading_screen::display([&config_manager]() {
920  config_manager.reload_changed_game_config();
921  });
922  break;
924  game->start_editor();
925  break;
927  gui2::dialogs::end_credits::display();
928  break;
930  game->launch_game(should_reload);
931  break;
933  break;
934  }
935  }
936 }
937 
938 #ifdef _WIN32
939 static bool parse_commandline_argument(const char*& next, const char* end, std::string& res)
940 {
941  // strip leading whitespace
942  while(next != end && *next == ' ') {
943  ++next;
944  }
945 
946  if(next == end) {
947  return false;
948  }
949 
950  bool is_excaped = false;
951 
952  for(; next != end; ++next) {
953  if(*next == ' ' && !is_excaped) {
954  break;
955  } else if(*next == '"' && !is_excaped) {
956  is_excaped = true;
957  continue;
958  } else if(*next == '"' && is_excaped && next + 1 != end && *(next + 1) == '"') {
959  res.push_back('"');
960  ++next;
961  continue;
962  } else if(*next == '"' && is_excaped) {
963  is_excaped = false;
964  continue;
965  } else {
966  res.push_back(*next);
967  }
968  }
969 
970  return true;
971 }
972 
973 static std::vector<std::string> parse_commandline_arguments(std::string input)
974 {
975  const char* start = &input[0];
976  const char* end = start + input.size();
977 
978  std::string buffer;
979  std::vector<std::string> res;
980 
981  while(parse_commandline_argument(start, end, buffer)) {
982  res.emplace_back();
983  res.back().swap(buffer);
984  }
985 
986  return res;
987 }
988 #endif
989 
990 #ifndef _WIN32
992 {
993  exit(0);
994 }
995 #endif
996 
997 #ifdef _WIN32
998 #define error_exit(res) \
999  do { \
1000  if(lg::using_own_console()) { \
1001  std::cerr << "Press enter to continue..." << std::endl; \
1002  std::cin.get(); \
1003  } \
1004  return res; \
1005  } while(false)
1006 #else
1007 #define error_exit(res) return res
1008 #endif
1009 
1010 #ifdef __APPLE__
1011 extern "C" int wesnoth_main(int argc, char** argv);
1012 int wesnoth_main(int argc, char** argv)
1013 #else
1014 int main(int argc, char** argv)
1015 #endif
1016 {
1017 #ifdef _WIN32
1018  UNUSED(argc);
1019  UNUSED(argv);
1020 
1021  // windows argv is ansi encoded by default
1022  std::vector<std::string> args =
1023  parse_commandline_arguments(unicode_cast<std::string>(std::wstring(GetCommandLineW())));
1024 
1025  // HACK: we don't parse command line arguments using program_options until
1026  // the startup banner is printed. We need to get a console up and
1027  // running before then if requested, so just perform a trivial search
1028  // here and let program_options ignore the switch later.
1029  for(std::size_t k = 0; k < args.size(); ++k) {
1030  if(args[k] == "--wconsole" ||
1031  args[k] == "--help" ||
1032  args[k] == "--logdomains" ||
1033  args[k] == "--path" ||
1034  args[k] == "--render-image" ||
1035  args[k] == "--report" ||
1036  args[k] == "-R" ||
1037  args[k] == "--screenshot" ||
1038  args[k] == "--data-path" ||
1039  args[k] == "--userdata-path" ||
1040  args[k] == "--userconfig-path" ||
1041  args[k] == "--validate" ||
1042  args[k] == "--version"
1043  ) {
1045  break;
1046  }
1047  }
1048 
1050 #else
1051  std::vector<std::string> args;
1052  for(int i = 0; i < argc; ++i) {
1053  args.push_back(std::string(argv[i]));
1054  }
1055 #endif
1056 
1057  assert(!args.empty());
1058 
1059  filesystem::init();
1060 
1061  if(SDL_Init(SDL_INIT_TIMER) < 0) {
1062  fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
1063  return (1);
1064  }
1065 
1066 #ifndef _WIN32
1067  struct sigaction terminate_handler;
1068  terminate_handler.sa_handler = wesnoth_terminate_handler;
1069  terminate_handler.sa_flags = 0;
1070 
1071  sigemptyset(&terminate_handler.sa_mask);
1072  sigaction(SIGTERM, &terminate_handler, nullptr);
1073  sigaction(SIGINT, &terminate_handler, nullptr);
1074 #endif
1075 
1076  // Mac's touchpad generates touch events too.
1077  // Ignore them until Macs have a touchscreen: https://forums.libsdl.org/viewtopic.php?p=45758
1078 #if defined(__APPLE__) && !defined(__IPHONEOS__)
1079  SDL_EventState(SDL_FINGERMOTION, SDL_DISABLE);
1080  SDL_EventState(SDL_FINGERDOWN, SDL_DISABLE);
1081  SDL_EventState(SDL_FINGERUP, SDL_DISABLE);
1082 #endif
1083 
1084  // declare this here so that it will always be at the front of the event queue.
1085  events::event_context global_context;
1086 
1087  SDL_StartTextInput();
1088 
1089  try {
1090  std::cerr << "Battle for Wesnoth v" << game_config::revision << '\n';
1091  const std::time_t t = std::time(nullptr);
1092  std::cerr << "Started on " << ctime(&t) << "\n";
1093 
1094  const std::string& exe_dir = filesystem::get_exe_dir();
1095  if(!exe_dir.empty()) {
1096  // Try to autodetect the location of the game data dir. Note that
1097  // the root of the source tree currently doubles as the data dir.
1098  std::string auto_dir;
1099 
1100  // scons leaves the resulting binaries at the root of the source
1101  // tree by default.
1102  if(filesystem::file_exists(exe_dir + "/data/_main.cfg")) {
1103  auto_dir = exe_dir;
1104  }
1105  // cmake encourages creating a subdir at the root of the source
1106  // tree for the build, and the resulting binaries are found in it.
1107  else if(filesystem::file_exists(exe_dir + "/../data/_main.cfg")) {
1108  auto_dir = filesystem::normalize_path(exe_dir + "/..");
1109  }
1110  // In Windows debug builds, the EXE is placed away from the game data dir
1111  // (in projectfiles\VCx\Debug), but the working directory is set to the
1112  // game data dir. Thus, check if the working dir is the game data dir.
1113  else if(filesystem::file_exists(filesystem::get_cwd() + "/data/_main.cfg")) {
1114  auto_dir = filesystem::get_cwd();
1115  }
1116 
1117  if(!auto_dir.empty()) {
1118  std::cerr << "Automatically found a possible data directory at " << filesystem::sanitize_path(auto_dir) << '\n';
1119  game_config::path = auto_dir;
1120  }
1121  }
1122 
1123  const int res = do_gameloop(args);
1124  safe_exit(res);
1125  } catch(const boost::program_options::error& e) {
1126  std::cerr << "Error in command line: " << e.what() << '\n';
1127  error_exit(1);
1128  } catch(const CVideo::error& e) {
1129  std::cerr << "Could not initialize video.\n\n" << e.what() << "\n\nExiting.\n";
1130  error_exit(1);
1131  } catch(const font::error& e) {
1132  std::cerr << "Could not initialize fonts.\n\n" << e.what() << "\n\nExiting.\n";
1133  error_exit(1);
1134  } catch(const config::error& e) {
1135  std::cerr << e.message << "\n";
1136  error_exit(1);
1137  } catch(const gui::button::error&) {
1138  std::cerr << "Could not create button: Image could not be found\n";
1139  error_exit(1);
1140  } catch(const CVideo::quit&) {
1141  // just means the game should quit
1142  } catch(const return_to_play_side_exception&) {
1143  std::cerr << "caught return_to_play_side_exception, please report this bug (quitting)\n";
1144  } catch(const quit_game_exception&) {
1145  std::cerr << "caught quit_game_exception (quitting)\n";
1146  } catch(const wml_exception& e) {
1147  std::cerr << "WML exception:\nUser message: " << e.user_message << "\nDev message: " << e.dev_message << '\n';
1148  error_exit(1);
1149  } catch(const wfl::formula_error& e) {
1150  std::cerr << e.what() << "\n\nGame will be aborted.\n";
1151  error_exit(1);
1152  } catch(const sdl::exception& e) {
1153  std::cerr << e.what();
1154  error_exit(1);
1155  } catch(const game::error&) {
1156  // A message has already been displayed.
1157  error_exit(1);
1158  } catch(const std::bad_alloc&) {
1159  std::cerr << "Ran out of memory. Aborted.\n";
1160  error_exit(ENOMEM);
1161 #if !defined(NO_CATCH_AT_GAME_END)
1162  } catch(const std::exception& e) {
1163  // Try to catch unexpected exceptions.
1164  std::cerr << "Caught general '" << typeid(e).name() << "' exception:\n" << e.what() << std::endl;
1165  error_exit(1);
1166  } catch(const std::string& e) {
1167  std::cerr << "Caught a string thrown as an exception:\n" << e << std::endl;
1168  error_exit(1);
1169  } catch(const char* e) {
1170  std::cerr << "Caught a string thrown as an exception:\n" << e << std::endl;
1171  error_exit(1);
1172  } catch(...) {
1173  // Ensure that even when we terminate with `throw 42`, the exception
1174  // is caught and all destructors are actually called. (Apparently,
1175  // some compilers will simply terminate without calling destructors if
1176  // the exception isn't caught.)
1177  std::cerr << "Caught unspecified general exception. Terminating." << std::endl;
1178  error_exit(1);
1179 #endif
1180  }
1181 
1182  return 0;
1183 } // end main
void empty_playlist()
Definition: sound.cpp:574
Exception used to escape form the ai or ui code to playsingle_controller::play_side.
bool log_precise_timestamps
True if –log-precise was given on the command line. Shows timestamps in log with more precision...
#define error_exit(res)
Definition: wesnoth.cpp:1007
static void wesnoth_terminate_handler(int)
Definition: wesnoth.cpp:991
void set_callback(const std::string &name, callback_function)
Definition: context.cpp:51
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:423
static int handle_validate_command(const std::string &file, abstract_validator &validator, const std::vector< std::string > &defines)
Definition: wesnoth.cpp:336
void bind_textdomain(const char *domain, const char *directory, const char *)
Definition: gettext.cpp:432
const_all_children_itors all_children_range() const
In-order iteration over all children.
Definition: config.cpp:923
bool using_own_console()
Returns true if a console was allocated by the Wesnoth process.
void stop_music()
Definition: sound.cpp:519
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
Definition: cursor.cpp:173
std::string library_versions_report()
Produce a plain-text report of library versions suitable for stdout/stderr.
Definition: build_info.cpp:371
static void bzip2_encode(const std::string &input_file, const std::string &output_file)
Definition: wesnoth.cpp:207
static void bzip2_decode(const std::string &input_file, const std::string &output_file)
Definition: wesnoth.cpp:212
Interfaces for manipulating version numbers of engine, add-ons, etc.
boost::optional< std::string > bzip2
Non-empty if –bzip2 was given on the command line. Compresses a file to .bz2 and exits...
static lg::log_domain log_preprocessor("preprocessor")
void set_team_colors(const std::vector< std::string > *colors)
set the team colors used by the TC image modification use a vector with one string for each team usin...
Definition: picture.cpp:861
Add a special kind of assert to validate whether the input from WML doesn&#39;t contain any problems that...
std::string optional_features_report()
Produce a plain-text report of features suitable for stdout/stderr.
Definition: build_info.cpp:411
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:39
void set_user_data_dir(std::string newprefdir)
Definition: filesystem.cpp:584
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:280
child_itors child_range(config_key_type key)
Definition: config.cpp:366
bool userdata_path
True if –userdata-path was given on the command line. Prints path to user data directory and exits...
static void gzip_decode(const std::string &input_file, const std::string &output_file)
Definition: wesnoth.cpp:202
static void progress(loading_stage stage=loading_stage::none)
filesystem::scoped_istream istream_file(const std::string &fname, bool treat_failure_as_error)
Definition: filesystem.cpp:882
std::string user_message
The message for the user explaining what went wrong.
This class implements the title screen.
boost::optional< std::string > gunzip
Non-empty if –gunzip was given on the command line. Uncompresses a .gz file and exits.
void init()
Some tasks to run on startup.
Definition: filesystem.cpp:239
void fresh_stats()
Definition: statistics.cpp:640
Type that can be thrown as an exception to quit to desktop.
Definition: video.hpp:228
void early_log_file_setup()
Sets up the initial temporary log file.
boost::optional< unsigned int > rng_seed
RNG seed specified by –rng-seed option. Initializes RNG with given seed.
void preprocess_resource(const std::string &res_name, preproc_map *defines_map, bool write_cfg, bool write_plain_cfg, const std::string &parent_directory)
boost::optional< std::string > data_dir
Non-empty if –data-dir was given on the command line. Sets the config dir to the specified one...
Don&#39;t reload if the previous defines equal the new defines.
static void safe_exit(int res)
Definition: wesnoth.cpp:142
std::string normalize_path(const std::string &fpath, bool normalize_separators, bool resolve_dot_entries)
Returns the absolute path of a file.
Contains the exception interfaces used to signal completion of a scenario, campaign or turn...
bool show(const unsigned auto_close_time=0)
Shows the window.
-file util.hpp
Definitions for the interface to Wesnoth Markup Language (WML).
static void decode(const std::string &input_file, const std::string &output_file)
Definition: wesnoth.cpp:178
bool preprocess
True if –preprocess was given on the command line. Starts Wesnoth in preprocessor-only mode...
bool play_multiplayer(mp_selection res)
std::string get_cwd()
Definition: filesystem.cpp:771
One of the realizations of serialization/validator.hpp abstract validator.
unsigned in
If equal to search_counter, the node is off the list.
static const char * name(const std::vector< SDL_Joystick *> &joysticks, const std::size_t index)
Definition: joystick.cpp:48
Used in parsing config file.
Definition: validator.hpp:35
boost::optional< std::string > validate_schema
Non-empty if –validate-schema was given on the command line. Makes Wesnoth validate a WML schema...
static void warn_early_init_failure()
Print an alert and instructions to stderr about early initialization errors.
Definition: wesnoth.cpp:559
bool joystick_support_enabled()
Definition: general.cpp:721
boost::optional< std::string > userconfig_dir
Non-empty if –userconfig-dir was given on the command line. Sets the user config dir to the specifie...
bool report
True if –report was given on the command line. Prints a bug report-style info dump and exits...
static void check_fpu()
Definition: wesnoth.cpp:632
void read(config &cfg, std::istream &in, abstract_validator *validator)
Definition: parser.cpp:615
Class for writing a config out to a file in pieces.
std::string get_user_data_dir()
Definition: filesystem.cpp:737
std::string get_intl_dir()
static lg::log_domain log_config("config")
bool strict_validation_enabled
Definition: validator.cpp:19
void init()
Initializes the GUI subsystems.
Definition: gui.cpp:35
boost::optional< std::string > logdomains
Non-empty if –logdomains was given on the command line. Prints possible logdomains filtered by given...
#define LOG_GENERAL
Definition: wesnoth.cpp:134
boost::optional< std::string > userdata_dir
Non-empty if –userdata-dir was given on the command line. Sets the user data dir to the specified on...
boost::optional< std::string > gzip
Non-empty if –gzip was given on the command line. Compresses a file to .gz and exits.
void enable_native_console_output()
Switches to using a native console instead of log file redirection.
bool is_directory(const std::string &fname)
Returns true if the given file is a directory.
Definition: filesystem.cpp:972
std::unique_ptr< std::istream > scoped_istream
Definition: filesystem.hpp:39
std::string path
Definition: game_config.cpp:39
boost::optional< std::string > preprocess_output_macros
Non-empty if –preprocess-output-macros was given on the command line. Outputs all preprocessed macro...
void set_default_textdomain(const char *domain)
Definition: gettext.cpp:441
void refresh_addon_version_info_cache()
Refreshes the per-session cache of add-on&#39;s version information structs.
Definition: manager.cpp:283
std::string sanitize_path(const std::string &path)
Sanitizes a path to remove references to the user&#39;s name.
const char * what() const noexcept
Definition: exceptions.hpp:37
bool userconfig_path
True if –userconfig-path was given on the command line. Prints path to user config directory and exi...
static void handle_preprocess_command(const commandline_options &cmdline_opts)
Definition: wesnoth.cpp:217
bool path
True if –path was given on the command line. Prints the path to data directory and exits...
boost::optional< std::vector< std::pair< int, std::string > > > log
Contains parsed arguments of –log-* (e.g.
boost::optional< std::string > render_image
Image path to render. First parameter after –render-image.
int main(int argc, char **argv)
Definition: wesnoth.cpp:1014
bool load_font_config()
#define PACKAGE
Definition: wesconfig.h:23
Helper class, don&#39;t construct this directly.
static int do_gameloop(const std::vector< std::string > &args)
Setups the game environment and enters the titlescreen or game loops.
Definition: wesnoth.cpp:661
std::string dev_message
The message for developers telling which problem was triggered, this shouldn&#39;t be translated...
static void gzip_encode(const std::string &input_file, const std::string &output_file)
Definition: wesnoth.cpp:197
std::unique_ptr< std::ostream > scoped_ostream
Definition: filesystem.hpp:40
bool is_gzip_file(const std::string &filename)
Returns true if the file ends with &#39;.gz&#39;.
Definition: filesystem.cpp:993
Some defines: VERSION, PACKAGE, MIN_SAVEGAME_VERSION.
#define UNUSED(x)
Definition: global.hpp:34
boost::optional< std::string > validate_wml
Non-empty if –validate was given on the command line. Makes Wesnoth validate a WML file against a sc...
static void handle_lua_script_args(game_launcher *game, commandline_options &)
Handles the lua script command line arguments if present.
Definition: wesnoth.cpp:572
std::string get_exe_dir()
Definition: filesystem.cpp:783
boost::optional< std::string > preprocess_target
Target (output) path that was given to the –preprocess option.
static void init_locale()
I would prefer to setup locale first so that early error messages can get localized, but we need the game_launcher initialized to have filesystem::get_intl_dir() to work.
Definition: wesnoth.cpp:535
Log file control routines for Windows.
std::size_t i
Definition: function.cpp:933
void set_user_config_dir(const std::string &newconfigdir)
Definition: filesystem.cpp:694
bool debug_lua
True if –debug-lua was given in the commandline. Enables some Lua debugging mechanisms.
std::string get_wml_location(const std::string &filename, const std::string &current_dir)
Returns a complete path to the actual WML file or directory or an empty string if the file isn&#39;t pres...
const std::string revision
boost::optional< std::string > preprocess_path
Path to parse that was given to the –preprocess option.
static int process_command_args(const commandline_options &cmdline_opts)
Process commandline-arguments.
Definition: wesnoth.cpp:355
An exception object used when an IO error occurs.
Definition: filesystem.hpp:48
boost::optional< std::string > bunzip2
Non-empty if –bunzip2 was given on the command line. Uncompresses a .bz2 file and exits...
structure which will hide all current floating labels, and cause floating labels instantiated after i...
std::string title_music
Declarations for File-IO.
static int writer(lua_State *L, const void *b, size_t size, void *B)
Definition: lstrlib.cpp:182
Contains a basic exception class for SDL operations.
const version_info wesnoth_version(VERSION)
bool set_log_domain_severity(const std::string &name, int severity)
Definition: log.cpp:118
#define next(ls)
Definition: llex.cpp:32
bool data_path
True if –data-path was given on the command line. Prints path to data directory and exits...
std::string get_user_config_dir()
Definition: filesystem.cpp:708
bool screenshot
True if –screenshot was given on the command line. Starts Wesnoth in screenshot mode.
bool is_bzip2_file(const std::string &filename)
Returns true if the file ends with &#39;.bz2&#39;.
Definition: filesystem.cpp:998
static void display(std::function< void()> f)
#define LOG_PREPROC
Definition: wesnoth.cpp:137
Contains the SDL_Rect helper code.
double t
Definition: astarsearch.cpp:64
Base class for all the errors encountered by the engine.
Definition: exceptions.hpp:29
void play_music_config(const config &music_node, bool allow_interrupt_current_track, int i)
Definition: sound.cpp:666
std::string list_logdomains(const std::string &filter)
Definition: log.cpp:151
bool version
True if –version was given on the command line. Prints version and exits.
#define LOG_CONFIG
Definition: wesnoth.cpp:132
Standard logging facilities (interface).
std::string str() const
Serializes the version number into string form.
std::string message
Definition: exceptions.hpp:31
EXIT_STATUS start(const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
Definition: editor_main.cpp:28
bool strict_validation
True if –strict-validation was given on the command line. Makes Wesnoth trust validation errors as f...
boost::optional< std::vector< std::string > > preprocess_defines
Defines that were given to the –preprocess option.
std::map< std::string, struct preproc_define > preproc_map
#define e
static void encode(const std::string &input_file, const std::string &output_file)
Definition: wesnoth.cpp:150
Realization of serialization/validator.hpp abstract validator.
boost::optional< std::string > preprocess_input_macros
Non-empty if –preprocess-input-macros was given on the command line. Specifies a file that contains ...
bool update_from_preferences()
initialize any private data, e.g. algorithm choices from preferences
Definition: picture.cpp:1328
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
filesystem::scoped_istream preprocess_file(const std::string &fname, preproc_map *defines)
static preproc_map::value_type read_pair(const config &)
int wesnoth_main(int argc, char **argv)
bool help
True if –help was given on the command line. Prints help and exits.
bool init_lua_script()
std::string directory_name(const std::string &file)
Returns the directory name of a file, with filename stripped.
boost::optional< std::string > validate_with
Non-empty if –use-schema was given on the command line. Specifies the schema for use with –validate...
std::string full_build_report()
Produce a bug report-style info dump.
Definition: build_info.cpp:443
std::string wesnoth_program_dir
Definition: game_config.cpp:48
void precise_timestamps(bool pt)
Definition: log.cpp:76
void set_debug(bool new_debug)
void play_slice()
Definition: context.cpp:96
filesystem::scoped_ostream ostream_file(const std::string &fname, bool create_directory)
Definition: filesystem.cpp:920