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  std::cout << "Validating " << file << " against schema " << validator.name_ << std::endl;
349  filesystem::scoped_istream stream = preprocess_file(file, &defines_map);
350  config result;
351  read(result, *stream, &validator);
352  if(lg::broke_strict()) {
353  std::cout << "validation failed\n";
354  } else {
355  std::cout << "validation succeeded\n";
356  }
357  return lg::broke_strict();
358 }
359 
360 /** Process commandline-arguments */
361 static int process_command_args(const commandline_options& cmdline_opts)
362 {
363  // Options that don't change behavior based on any others should be checked alphabetically below.
364 
365  if(cmdline_opts.userconfig_dir) {
367  }
368 
369  if(cmdline_opts.userconfig_path) {
370  std::cout << filesystem::get_user_config_dir() << '\n';
371  return 0;
372  }
373 
374  if(cmdline_opts.userdata_dir) {
376  }
377 
378  if(cmdline_opts.userdata_path) {
379  std::cout << filesystem::get_user_data_dir() << '\n';
380  return 0;
381  }
382 
383  if(cmdline_opts.data_dir) {
384  const std::string datadir = *cmdline_opts.data_dir;
385 #ifdef _WIN32
386  // use c_str to ensure that index 1 points to valid element since c_str() returns null-terminated string
387  if(datadir.c_str()[1] == ':') {
388 #else
389  if(datadir[0] == '/') {
390 #endif
391  game_config::path = datadir;
392  } else {
393  game_config::path = filesystem::get_cwd() + '/' + datadir;
394  }
395 
397  std::cerr << "Overriding data directory with " << game_config::path << std::endl;
398 
400  std::cerr << "Could not find directory '" << game_config::path << "'\n";
401  throw config::error("directory not found");
402  }
403 
404  // don't update font as we already updating it in game ctor
405  // font_manager_.update_font_path();
406  }
407 
408  if(cmdline_opts.data_path) {
409  std::cout << game_config::path << '\n';
410  return 0;
411  }
412 
413  if(cmdline_opts.debug_lua) {
414  game_config::debug_lua = true;
415  }
416 
417  if(cmdline_opts.gunzip) {
418  const std::string input_file(*cmdline_opts.gunzip);
419  if(!filesystem::is_gzip_file(input_file)) {
420  std::cerr << "file '" << input_file << "'isn't a .gz file\n";
421  return 2;
422  }
423 
424  const std::string output_file(input_file, 0, input_file.length() - 3);
425  gzip_decode(input_file, output_file);
426  }
427 
428  if(cmdline_opts.bunzip2) {
429  const std::string input_file(*cmdline_opts.bunzip2);
430  if(!filesystem::is_bzip2_file(input_file)) {
431  std::cerr << "file '" << input_file << "'isn't a .bz2 file\n";
432  return 2;
433  }
434 
435  const std::string output_file(input_file, 0, input_file.length() - 4);
436  bzip2_decode(input_file, output_file);
437  }
438 
439  if(cmdline_opts.gzip) {
440  const std::string input_file(*cmdline_opts.gzip);
441  const std::string output_file(*cmdline_opts.gzip + ".gz");
442  gzip_encode(input_file, output_file);
443  }
444 
445  if(cmdline_opts.bzip2) {
446  const std::string input_file(*cmdline_opts.bzip2);
447  const std::string output_file(*cmdline_opts.bzip2 + ".bz2");
448  bzip2_encode(input_file, output_file);
449  }
450 
451  if(cmdline_opts.help) {
452  std::cout << cmdline_opts;
453  return 0;
454  }
455 
456  if(cmdline_opts.log) {
457  for(const auto& log_pair : cmdline_opts.log.get()) {
458  const std::string log_domain = log_pair.second;
459  const int severity = log_pair.first;
460  if(!lg::set_log_domain_severity(log_domain, severity)) {
461  std::cerr << "unknown log domain: " << log_domain << '\n';
462  return 2;
463  }
464  }
465  }
466 
467  if(cmdline_opts.logdomains) {
468  std::cout << lg::list_logdomains(*cmdline_opts.logdomains);
469  return 0;
470  }
471 
472  if(cmdline_opts.log_precise_timestamps) {
474  }
475 
476  if(cmdline_opts.rng_seed) {
477  srand(*cmdline_opts.rng_seed);
478  }
479 
480  if(cmdline_opts.screenshot || cmdline_opts.render_image) {
481  SDL_setenv("SDL_VIDEODRIVER", "dummy", 1);
482  }
483 
484  if(cmdline_opts.strict_validation) {
486  }
487 
488  if(cmdline_opts.version) {
489  std::cout << "Battle for Wesnoth" << " " << game_config::wesnoth_version.str() << "\n\n";
490  std::cout << "Library versions:\n" << game_config::library_versions_report() << '\n';
491  std::cout << "Optional features:\n" << game_config::optional_features_report();
492 
493  return 0;
494  }
495 
496  if(cmdline_opts.report) {
497  std::cout << "\n========= BUILD INFORMATION =========\n\n" << game_config::full_build_report();
498  return 0;
499  }
500 
501  if(cmdline_opts.validate_schema) {
503  validator.set_create_exceptions(false); // Don't crash if there's an error, just go ahead anyway
504  return handle_validate_command(*cmdline_opts.validate_schema, validator, {});
505  }
506 
507  // Options changing their behavior dependent on some others should be checked below.
508 
509  if(cmdline_opts.preprocess) {
510  handle_preprocess_command(cmdline_opts);
511  return 0;
512  }
513 
514  if(cmdline_opts.validate_wml) {
515  std::string schema_path;
516  if(cmdline_opts.validate_with) {
517  schema_path = *cmdline_opts.validate_with;
518  } else {
519  schema_path = filesystem::get_wml_location("schema/game_config.cfg");
520  }
521  schema_validation::schema_validator validator(schema_path);
522  validator.set_create_exceptions(false); // Don't crash if there's an error, just go ahead anyway
523  return handle_validate_command(*cmdline_opts.validate_wml, validator, boost::get_optional_value_or(cmdline_opts.preprocess_defines, {}));
524  }
525 
526  // Not the most intuitive solution, but I wanted to leave current semantics for now
527  return -1;
528 }
529 
530 /**
531  * I would prefer to setup locale first so that early error
532  * messages can get localized, but we need the game_launcher
533  * initialized to have filesystem::get_intl_dir() to work. Note: setlocale()
534  * does not take GUI language setting into account.
535  */
536 static void init_locale()
537 {
538 #if defined _WIN32 || defined __APPLE__
539  setlocale(LC_ALL, "English");
540 #else
541  std::setlocale(LC_ALL, "C");
542 #endif
543 
544  const std::string& intl_dir = filesystem::get_intl_dir();
545 
546  translation::bind_textdomain(PACKAGE, intl_dir.c_str(), "UTF-8");
547  translation::bind_textdomain(PACKAGE "-lib", intl_dir.c_str(), "UTF-8");
549 }
550 
551 /**
552  * Print an alert and instructions to stderr about early initialization errors.
553  *
554  * This is provided as an aid for users dealing with potential data dir
555  * configuration issues. The first code to read core WML *has* the
556  * responsibility to call this function in the event of a problem, to inform
557  * the user of the most likely possible cause and suggest a course of action
558  * to solve the issue.
559  */
561 {
562  // NOTE: wrap output to 80 columns.
563  std::cerr << '\n'
564  << "An error at this point during initialization usually indicates that the data\n"
565  << "directory above was not correctly set or detected. Try passing the correct path\n"
566  << "in the command line with the --data-dir switch or as the only argument.\n";
567 }
568 
569 /**
570  * Handles the lua script command line arguments if present.
571  * This function will only run once.
572  */
574 {
575  static bool first_time = true;
576 
577  if(!first_time) {
578  return;
579  }
580 
581  first_time = false;
582 
583  if(!game->init_lua_script()) {
584  // std::cerr << "error when loading lua scripts at startup\n";
585  // std::cerr << "could not load lua script: " << *cmdline_opts.script_file << std::endl;
586  }
587 }
588 
589 #ifdef _MSC_VER
590 static void check_fpu()
591 {
592  uint32_t f_control;
593 
594  if(_controlfp_s(&f_control, 0, 0) == 0) {
595  uint32_t unused;
596  uint32_t rounding_mode = f_control & _MCW_RC;
597  uint32_t precision_mode = f_control & _MCW_PC;
598 
599  if(rounding_mode != _RC_NEAR) {
600  std::cerr << "Floating point rounding mode is currently '"
601  << ((rounding_mode == _RC_CHOP)
602  ? "chop"
603  : (rounding_mode == _RC_UP)
604  ? "up"
605  : (rounding_mode == _RC_DOWN)
606  ? "down"
607  : (rounding_mode == _RC_NEAR) ? "near" : "unknown")
608  << "' setting to 'near'\n";
609 
610  if(_controlfp_s(&unused, _RC_NEAR, _MCW_RC)) {
611  std::cerr << "failed to set floating point rounding type to 'near'\n";
612  }
613  }
614 
615  if(precision_mode != _PC_53) {
616  std::cerr << "Floating point precision mode is currently '"
617  << ((precision_mode == _PC_53)
618  ? "double"
619  : (precision_mode == _PC_24)
620  ? "single"
621  : (precision_mode == _PC_64) ? "double extended" : "unknown")
622  << "' setting to 'double'\n";
623 
624  if(_controlfp_s(&unused, _PC_53, _MCW_PC)) {
625  std::cerr << "failed to set floating point precision type to 'double'\n";
626  }
627  }
628  } else {
629  std::cerr << "_controlfp_s failed.\n";
630  }
631 }
632 #else
633 static void check_fpu()
634 {
635  switch(fegetround()) {
636  case FE_TONEAREST:
637  break;
638  case FE_DOWNWARD:
639  std::cerr << "Floating point precision mode is currently 'downward'";
640  goto reset_fpu;
641  case FE_TOWARDZERO:
642  std::cerr << "Floating point precision mode is currently 'toward-zero'";
643  goto reset_fpu;
644  case FE_UPWARD:
645  std::cerr << "Floating point precision mode is currently 'upward'";
646  goto reset_fpu;
647  default:
648  std::cerr << "Floating point precision mode is currently 'unknown'";
649  goto reset_fpu;
650  reset_fpu:
651  std::cerr << "setting to 'nearest'";
652  fesetround(FE_TONEAREST);
653  break;
654  }
655 }
656 #endif
657 
658 /**
659  * Setups the game environment and enters
660  * the titlescreen or game loops.
661  */
662 static int do_gameloop(const std::vector<std::string>& args)
663 {
664  srand(std::time(nullptr));
665 
666  commandline_options cmdline_opts = commandline_options(args);
668 
669  int finished = process_command_args(cmdline_opts);
670  if(finished != -1) {
671 #ifdef _WIN32
672  if(lg::using_own_console()) {
673  std::cerr << "Press enter to continue..." << std::endl;
674  std::cin.get();
675  }
676 #endif
677 
678  return finished;
679  }
680 
681  const auto game = std::make_unique<game_launcher>(cmdline_opts, args[0].c_str());
682  const int start_ticks = SDL_GetTicks();
683 
684  init_locale();
685 
686  bool res;
687 
688  // Do initialize fonts before reading the game config, to have game
689  // config error messages displayed. fonts will be re-initialized later
690  // when the language is read from the game config.
691  res = font::load_font_config();
692  if(res == false) {
693  std::cerr << "could not initialize fonts\n";
694  // The most common symptom of a bogus data dir path -- warn the user.
696  return 1;
697  }
698 
699  res = game->init_language();
700  if(res == false) {
701  std::cerr << "could not initialize the language\n";
702  return 1;
703  }
704 
705  res = game->init_video();
706  if(res == false) {
707  std::cerr << "could not initialize display\n";
708  return 1;
709  }
710 
712  if(res == false) {
713  std::cerr << "could not initialize image preferences\n";
714  return 1;
715  }
716 
718  res = game->init_joystick();
719  if(res == false) {
720  std::cerr << "could not initialize joystick\n";
721  }
722  }
723 
724  check_fpu();
725  const cursor::manager cursor_manager;
727 
728 #if(defined(_X11) && !defined(__APPLE__)) || defined(_WIN32)
729  SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
730 #endif
731 
732  gui2::init();
733  const gui2::event::manager gui_event_manager;
734 
735  game_config_manager config_manager(cmdline_opts, game->jump_to_editor());
736 
737  gui2::dialogs::loading_screen::display([&res, &config_manager]() {
739  res = config_manager.init_game_config(game_config_manager::NO_FORCE_RELOAD);
740 
741  if(res == false) {
742  std::cerr << "could not initialize game config\n";
743  return;
744  }
745 
747 
748  res = font::load_font_config();
749  if(res == false) {
750  std::cerr << "could not re-initialize fonts for the current language\n";
751  return;
752  }
753 
755 
757  });
758 
759  if(res == false) {
760  return 1;
761  }
762 
763  LOG_CONFIG << "time elapsed: " << (SDL_GetTicks() - start_ticks) << " ms\n";
764 
765  plugins_manager plugins_man(new application_lua_kernel);
766 
767  plugins_context::Reg const callbacks[] {
768  {"play_multiplayer", std::bind(&game_launcher::play_multiplayer, game.get(), game_launcher::MP_CONNECT)},
769  };
770 
771  plugins_context::aReg const accessors[] {
772  {"command_line", std::bind(&commandline_options::to_config, &cmdline_opts)},
773  };
774 
775  plugins_context plugins("titlescreen", callbacks, accessors);
776 
777  plugins.set_callback("exit", [](const config& cfg) { safe_exit(cfg["code"].to_int(0)); }, false);
778 
779  for(;;) {
780  // reset the TC, since a game can modify it, and it may be used
781  // by images in add-ons or campaigns dialogs
783 
785 
786  if(!game->is_loading()) {
787  const config& cfg = config_manager.game_config().child("titlescreen_music");
788  if(cfg) {
789  for(const config& i : cfg.child_range("music")) {
791  }
792 
793  config title_music_config;
794  title_music_config["name"] = game_config::title_music;
795  title_music_config["append"] = true;
796  title_music_config["immediate"] = true;
797  sound::play_music_config(title_music_config);
798  } else {
801  }
802  }
803 
804  handle_lua_script_args(&*game, cmdline_opts);
805 
806  plugins.play_slice();
807  plugins.play_slice();
808 
809  if(cmdline_opts.unit_test) {
810  if(cmdline_opts.timeout) {
811  std::cerr << "The wesnoth built-in timeout feature has been removed.\n" << std::endl;
812  std::cerr << "Please use a platform-specific script which will kill the overtime process instead.\n"
813  << std::endl;
814  std::cerr << "For examples in bash, or in windows cmd, see the forums, or the wesnoth repository."
815  << std::endl;
816  std::cerr
817  << "The bash script is called `run_wml_tests`, the windows script is part of the VC project.\n"
818  << std::endl;
819  }
820 
821  int worker_result = game->unit_test();
822  std::cerr << ((worker_result == 0) ? "PASS TEST " : "FAIL TEST ")
823  << ((worker_result == 3) ? "(INVALID REPLAY)" : "")
824  << ((worker_result == 4) ? "(ERRORED REPLAY)" : "") << ": " << *cmdline_opts.unit_test
825  << std::endl;
826  return worker_result;
827  }
828 
829  if(game->play_test() == false) {
830  return 0;
831  }
832 
833  if(game->play_screenshot_mode() == false) {
834  return 0;
835  }
836 
837  if(game->play_render_image_mode() == false) {
838  return 0;
839  }
840 
841  // Start directly a campaign
842  if(game->goto_campaign() == false) {
843  if(game->jump_to_campaign_id().empty())
844  continue; // Go to main menu
845  else
846  return 1; // we got an error starting the campaign from command line
847  }
848 
849  // Start directly a multiplayer
850  // Eventually with a specified server
851  if(game->goto_multiplayer() == false) {
852  continue; // Go to main menu
853  }
854 
855  // Start directly a commandline multiplayer game
856  if(game->play_multiplayer_commandline() == false) {
857  return 0;
858  }
859 
860  if(game->goto_editor() == false) {
861  return 0;
862  }
863 
864  const font::floating_label_context label_manager;
865 
867 
869 
870  // If loading a game, skip the titlescreen entirely
871  if(game->is_loading()) {
872  if(!game->load_game()) {
873  game->clear_loaded_game();
874  }
875 
876  game->launch_game(should_reload);
877  continue;
878  }
879 
881 
882  /*
883  * Quick explanation of the titlscreen loop:
884  *
885  * The dialog's redraw_background_ flag is initialized as true in the constructor, so the dialog will always
886  * display at least once when this loop is executed. Each time it's opened, the aforementioned flag is set to
887  * false, and any selection that results in leaving the dialog simply sets the window's retval and proceeds to
888  * the appropriate action.
889  *
890  * Certain actions (such as window resizing) set the flag to true, which allows the dialog to reopen with any
891  * layout changes such as those dictated by window resolution.
892  */
894  dlg.show();
895  }
896 
897  switch(dlg.get_retval()) {
899  LOG_GENERAL << "quitting game...\n";
900  return 0;
903  if(!game->play_multiplayer(game_launcher::MP_CONNECT)) {
904  continue;
905  }
906  break;
909  if(!game->play_multiplayer(game_launcher::MP_HOST)) {
910  continue;
911  }
912  break;
915  if(!game->play_multiplayer(game_launcher::MP_LOCAL)) {
916  continue;
917  }
918  break;
920  gui2::dialogs::loading_screen::display([&config_manager]() {
921  config_manager.reload_changed_game_config();
922  });
923  break;
925  game->start_editor();
926  break;
928  gui2::dialogs::end_credits::display();
929  break;
931  game->launch_game(should_reload);
932  break;
934  break;
935  }
936  }
937 }
938 
939 #ifdef _WIN32
940 static bool parse_commandline_argument(const char*& next, const char* end, std::string& res)
941 {
942  // strip leading whitespace
943  while(next != end && *next == ' ') {
944  ++next;
945  }
946 
947  if(next == end) {
948  return false;
949  }
950 
951  bool is_excaped = false;
952 
953  for(; next != end; ++next) {
954  if(*next == ' ' && !is_excaped) {
955  break;
956  } else if(*next == '"' && !is_excaped) {
957  is_excaped = true;
958  continue;
959  } else if(*next == '"' && is_excaped && next + 1 != end && *(next + 1) == '"') {
960  res.push_back('"');
961  ++next;
962  continue;
963  } else if(*next == '"' && is_excaped) {
964  is_excaped = false;
965  continue;
966  } else {
967  res.push_back(*next);
968  }
969  }
970 
971  return true;
972 }
973 
974 static std::vector<std::string> parse_commandline_arguments(std::string input)
975 {
976  const char* start = &input[0];
977  const char* end = start + input.size();
978 
979  std::string buffer;
980  std::vector<std::string> res;
981 
982  while(parse_commandline_argument(start, end, buffer)) {
983  res.emplace_back();
984  res.back().swap(buffer);
985  }
986 
987  return res;
988 }
989 #endif
990 
991 #ifndef _WIN32
993 {
994  exit(0);
995 }
996 #endif
997 
998 #ifdef _WIN32
999 #define error_exit(res) \
1000  do { \
1001  if(lg::using_own_console()) { \
1002  std::cerr << "Press enter to continue..." << std::endl; \
1003  std::cin.get(); \
1004  } \
1005  return res; \
1006  } while(false)
1007 #else
1008 #define error_exit(res) return res
1009 #endif
1010 
1011 #ifdef __APPLE__
1012 extern "C" int wesnoth_main(int argc, char** argv);
1013 int wesnoth_main(int argc, char** argv)
1014 #else
1015 int main(int argc, char** argv)
1016 #endif
1017 {
1018 #ifdef _WIN32
1019  UNUSED(argc);
1020  UNUSED(argv);
1021 
1022  // windows argv is ansi encoded by default
1023  std::vector<std::string> args =
1024  parse_commandline_arguments(unicode_cast<std::string>(std::wstring(GetCommandLineW())));
1025 
1026  // HACK: we don't parse command line arguments using program_options until
1027  // the startup banner is printed. We need to get a console up and
1028  // running before then if requested, so just perform a trivial search
1029  // here and let program_options ignore the switch later.
1030  for(std::size_t k = 0; k < args.size(); ++k) {
1031  if(args[k] == "--wconsole" ||
1032  args[k] == "--help" ||
1033  args[k] == "--logdomains" ||
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].compare(0, 11, "--validate=") == 0 ||
1042  args[k].compare(0, 17, "--validate-schema") == 0 ||
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  filesystem::init();
1061 
1062  if(SDL_Init(SDL_INIT_TIMER) < 0) {
1063  fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
1064  return (1);
1065  }
1066 
1067 #ifndef _WIN32
1068  struct sigaction terminate_handler;
1069  terminate_handler.sa_handler = wesnoth_terminate_handler;
1070  terminate_handler.sa_flags = 0;
1071 
1072  sigemptyset(&terminate_handler.sa_mask);
1073  sigaction(SIGTERM, &terminate_handler, nullptr);
1074  sigaction(SIGINT, &terminate_handler, nullptr);
1075 #endif
1076 
1077  // Mac's touchpad generates touch events too.
1078  // Ignore them until Macs have a touchscreen: https://forums.libsdl.org/viewtopic.php?p=45758
1079 #if defined(__APPLE__) && !defined(__IPHONEOS__)
1080  SDL_EventState(SDL_FINGERMOTION, SDL_DISABLE);
1081  SDL_EventState(SDL_FINGERDOWN, SDL_DISABLE);
1082  SDL_EventState(SDL_FINGERUP, SDL_DISABLE);
1083 #endif
1084 
1085  // declare this here so that it will always be at the front of the event queue.
1086  events::event_context global_context;
1087 
1088  SDL_StartTextInput();
1089 
1090  try {
1091  std::cerr << "Battle for Wesnoth v" << game_config::revision << '\n';
1092  const std::time_t t = std::time(nullptr);
1093  std::cerr << "Started on " << ctime(&t) << "\n";
1094 
1095  const std::string& exe_dir = filesystem::get_exe_dir();
1096  if(!exe_dir.empty()) {
1097  // Try to autodetect the location of the game data dir. Note that
1098  // the root of the source tree currently doubles as the data dir.
1099  std::string auto_dir;
1100 
1101  // scons leaves the resulting binaries at the root of the source
1102  // tree by default.
1103  if(filesystem::file_exists(exe_dir + "/data/_main.cfg")) {
1104  auto_dir = exe_dir;
1105  }
1106  // cmake encourages creating a subdir at the root of the source
1107  // tree for the build, and the resulting binaries are found in it.
1108  else if(filesystem::file_exists(exe_dir + "/../data/_main.cfg")) {
1109  auto_dir = filesystem::normalize_path(exe_dir + "/..");
1110  }
1111  // In Windows debug builds, the EXE is placed away from the game data dir
1112  // (in projectfiles\VCx\Debug), but the working directory is set to the
1113  // game data dir. Thus, check if the working dir is the game data dir.
1114  else if(filesystem::file_exists(filesystem::get_cwd() + "/data/_main.cfg")) {
1115  auto_dir = filesystem::get_cwd();
1116  }
1117 
1118  if(!auto_dir.empty()) {
1119  std::cerr << "Automatically found a possible data directory at " << filesystem::sanitize_path(auto_dir) << '\n';
1120  game_config::path = auto_dir;
1121  }
1122  }
1123 
1124  const int res = do_gameloop(args);
1125  safe_exit(res);
1126  } catch(const boost::program_options::error& e) {
1127  std::cerr << "Error in command line: " << e.what() << '\n';
1128  error_exit(1);
1129  } catch(const CVideo::error& e) {
1130  std::cerr << "Could not initialize video.\n\n" << e.what() << "\n\nExiting.\n";
1131  error_exit(1);
1132  } catch(const font::error& e) {
1133  std::cerr << "Could not initialize fonts.\n\n" << e.what() << "\n\nExiting.\n";
1134  error_exit(1);
1135  } catch(const config::error& e) {
1136  std::cerr << e.message << "\n";
1137  error_exit(1);
1138  } catch(const gui::button::error&) {
1139  std::cerr << "Could not create button: Image could not be found\n";
1140  error_exit(1);
1141  } catch(const CVideo::quit&) {
1142  // just means the game should quit
1143  } catch(const return_to_play_side_exception&) {
1144  std::cerr << "caught return_to_play_side_exception, please report this bug (quitting)\n";
1145  } catch(const quit_game_exception&) {
1146  std::cerr << "caught quit_game_exception (quitting)\n";
1147  } catch(const wml_exception& e) {
1148  std::cerr << "WML exception:\nUser message: " << e.user_message << "\nDev message: " << e.dev_message << '\n';
1149  error_exit(1);
1150  } catch(const wfl::formula_error& e) {
1151  std::cerr << e.what() << "\n\nGame will be aborted.\n";
1152  error_exit(1);
1153  } catch(const sdl::exception& e) {
1154  std::cerr << e.what();
1155  error_exit(1);
1156  } catch(const game::error&) {
1157  // A message has already been displayed.
1158  error_exit(1);
1159  } catch(const std::bad_alloc&) {
1160  std::cerr << "Ran out of memory. Aborted.\n";
1161  error_exit(ENOMEM);
1162 #if !defined(NO_CATCH_AT_GAME_END)
1163  } catch(const std::exception& e) {
1164  // Try to catch unexpected exceptions.
1165  std::cerr << "Caught general '" << typeid(e).name() << "' exception:\n" << e.what() << std::endl;
1166  error_exit(1);
1167  } catch(const std::string& e) {
1168  std::cerr << "Caught a string thrown as an exception:\n" << e << std::endl;
1169  error_exit(1);
1170  } catch(const char* e) {
1171  std::cerr << "Caught a string thrown as an exception:\n" << e << std::endl;
1172  error_exit(1);
1173  } catch(...) {
1174  // Ensure that even when we terminate with `throw 42`, the exception
1175  // is caught and all destructors are actually called. (Apparently,
1176  // some compilers will simply terminate without calling destructors if
1177  // the exception isn't caught.)
1178  std::cerr << "Caught unspecified general exception. Terminating." << std::endl;
1179  error_exit(1);
1180 #endif
1181  }
1182 
1183  return 0;
1184 } // 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:1008
static void wesnoth_terminate_handler(int)
Definition: wesnoth.cpp:992
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:420
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:921
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:620
int compare(const std::string &s1, const std::string &s2)
Case-sensitive lexicographical comparison.
Definition: gettext.cpp:458
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:280
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: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:918
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
const std::string name_
Definition: validator.hpp:96
bool preprocess
True if –preprocess was given on the command line. Starts Wesnoth in preprocessor-only mode...
bool broke_strict()
Definition: log.cpp:171
bool play_multiplayer(mp_selection res)
std::string get_cwd()
Definition: filesystem.cpp:807
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:560
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:633
void read(config &cfg, std::istream &in, abstract_validator *validator)
Definition: parser.cpp:625
Class for writing a config out to a file in pieces.
std::string get_user_data_dir()
Definition: filesystem.cpp:773
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.
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
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:1015
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:662
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;.
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:573
std::string get_exe_dir()
Definition: filesystem.cpp:819
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:536
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:730
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.
void set_strict_severity(int severity)
Definition: log.cpp:161
static int process_command_args(const commandline_options &cmdline_opts)
Process commandline-arguments.
Definition: wesnoth.cpp:361
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:744
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;.
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:956