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