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