The Battle for Wesnoth  1.13.11+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
game_launcher.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "game_launcher.hpp"
16 #include "game_errors.hpp"
17 
18 #include "ai/manager.hpp" // for manager
20 #include "commandline_options.hpp" // for commandline_options
21 #include "config.hpp" // for config, etc
22 #include "cursor.hpp" // for set, CURSOR_TYPE::NORMAL
23 #include "exceptions.hpp" // for error
24 #include "filesystem.hpp" // for get_user_config_dir, etc
25 #include "game_classification.hpp" // for game_classification, etc
26 #include "game_config.hpp" // for path, no_delay, revision, etc
27 #include "game_config_manager.hpp" // for game_config_manager
28 #include "game_end_exceptions.hpp" // for LEVEL_RESULT, etc
29 #include "generators/map_generator.hpp" // for mapgen_exception
30 #include "gettext.hpp" // for _
32 #include "gui/dialogs/language_selection.hpp" // for language_selection
34 #include "gui/dialogs/message.hpp" //for show error message
36 #include "gui/dialogs/multiplayer/mp_host_game_prompt.hpp" //for host game prompt
38 #include "gui/dialogs/outro.hpp"
40 #include "gui/dialogs/transient_message.hpp" // for show_transient_message
41 #include "gui/dialogs/title_screen.hpp" // for show_debug_clock_button
42 #include "gui/widgets/settings.hpp" // for new_widgets
43 #include "gui/widgets/window.hpp" // for window, etc
44 #include "language.hpp" // for language_def, etc
45 #include "log.hpp" // for LOG_STREAM, logger, general, etc
46 #include "map/exception.hpp"
47 #include "game_initialization/multiplayer.hpp" // for start_client, etc
49 #include "game_initialization/playcampaign.hpp" // for play_game, etc
50 #include "preferences/general.hpp" // for disable_preferences_save, etc
51 #include "preferences/display.hpp"
52 #include "savegame.hpp" // for clean_saves, etc
54 #include "sdl/surface.hpp" // for surface
55 #include "serialization/compression.hpp" // for format::NONE
56 #include "serialization/string_utils.hpp" // for split
57 #include "game_initialization/singleplayer.hpp" // for sp_create_mode
58 #include "statistics.hpp"
59 #include "tstring.hpp" // for operator==, operator!=
60 #include "utils/general.hpp" // for clamp
61 #include "video.hpp" // for CVideo
63 #include "wml_exception.hpp" // for wml_exception
64 
65 #include <algorithm> // for copy, max, min, stable_sort
66 #include <cstdlib> // for system
67 #include <iostream> // for operator<<, basic_ostream, etc
68 #include <new>
69 #include <utility> // for pair
70 #include <SDL.h> // for SDL_INIT_JOYSTICK, etc
71 
72 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
73 #include "gui/widgets/debug.hpp"
74 #endif
75 
76 // For wesnothd launch code.
77 #ifdef _WIN32
78 
79 #define WIN32_LEAN_AND_MEAN
80 #include <windows.h>
81 
82 #endif // _WIN32
83 
85 
86 static lg::log_domain log_config("config");
87 #define ERR_CONFIG LOG_STREAM(err, log_config)
88 #define WRN_CONFIG LOG_STREAM(warn, log_config)
89 #define LOG_CONFIG LOG_STREAM(info, log_config)
90 
91 #define LOG_GENERAL LOG_STREAM(info, lg::general())
92 #define WRN_GENERAL LOG_STREAM(warn, lg::general())
93 #define DBG_GENERAL LOG_STREAM(debug, lg::general())
94 
95 static lg::log_domain log_mp_create("mp/create");
96 #define DBG_MP LOG_STREAM(debug, log_mp_create)
97 
98 static lg::log_domain log_network("network");
99 #define ERR_NET LOG_STREAM(err, log_network)
100 
101 static lg::log_domain log_enginerefac("enginerefac");
102 #define LOG_RG LOG_STREAM(info, log_enginerefac)
103 
104 game_launcher::game_launcher(const commandline_options& cmdline_opts, const char *appname) :
105  cmdline_opts_(cmdline_opts),
106  video_(new CVideo()),
107  font_manager_(),
108  prefs_manager_(),
109  image_manager_(),
110  main_event_context_(),
111  hotkey_manager_(),
112  music_thinker_(),
113  music_muter_(),
114  test_scenario_("test"),
115  screenshot_map_(),
116  screenshot_filename_(),
117  state_(),
118  play_replay_(false),
119  multiplayer_server_(),
120  jump_to_multiplayer_(false),
121  jump_to_campaign_(false, -1, "", ""),
122  jump_to_editor_(false),
123  load_data_()
124 {
125  bool no_music = false;
126  bool no_sound = false;
127 
128  // The path can be hardcoded and it might be a relative path.
129  if(!game_config::path.empty() &&
130 #ifdef _WIN32
131  // use c_str to ensure that index 1 points to valid element since c_str() returns null-terminated string
132  game_config::path.c_str()[1] != ':'
133 #else
134  game_config::path[0] != '/'
135 #endif
136  )
137  {
139  // font_manager_.update_font_path()
140  // To update the font path, destroy and recreate the manager
142  new (&font_manager_) font::manager();
143  }
144 
145  const std::string app_basename = filesystem::base_name(appname);
146  jump_to_editor_ = app_basename.find("editor") != std::string::npos;
147 
148  if (cmdline_opts_.core_id) {
150  }
151  if (cmdline_opts_.campaign) {
152  jump_to_campaign_.jump_ = true;
154  std::cerr << "selected campaign id: [" << jump_to_campaign_.campaign_id_ << "]\n";
155 
158  std::cerr << "selected difficulty: [" << jump_to_campaign_.difficulty_ << "]\n";
159  }
160  else
161  jump_to_campaign_.difficulty_ = -1; // let the user choose the difficulty
162 
165  std::cerr << "selected scenario id: [" << jump_to_campaign_.scenario_id_ << "]\n";
166  }
167  }
168  if (cmdline_opts_.clock)
170  if (cmdline_opts_.debug) {
171  game_config::debug = true;
172  game_config::mp_debug = true;
173  }
174 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
175  if (cmdline_opts_.debug_dot_domain)
176  gui2::tdebug_layout_graph::set_domain (*cmdline_opts_.debug_dot_domain);
177  if (cmdline_opts_.debug_dot_level)
179 #endif
180  if (cmdline_opts_.editor)
181  {
182  jump_to_editor_ = true;
183  if (!cmdline_opts_.editor->empty())
184  load_data_.reset(new savegame::load_game_metadata{ *cmdline_opts_.editor });
185  }
186  if (cmdline_opts_.fps)
189  video().set_fullscreen(true);
190  if (cmdline_opts_.load)
192  if (cmdline_opts_.max_fps) {
193  int fps = utils::clamp(*cmdline_opts_.max_fps, 1, 1000);
194  fps = 1000 / fps;
195  // increase the delay to avoid going above the maximum
196  if(1000 % fps != 0) {
197  ++fps;
198  }
200  }
202  no_sound = true;
204  }
206  gui2::new_widgets = true;
208  game_config::no_delay = true;
210  no_music = true;
212  no_sound = true;
214  const int xres = std::get<0>(*cmdline_opts_.resolution);
215  const int yres = std::get<1>(*cmdline_opts_.resolution);
216  if(xres > 0 && yres > 0) {
217  preferences::_set_resolution(point(xres, yres));
219  }
220  }
222  //TODO it could be simplified to use cmdline_opts_ directly if there is no other way to enter screenshot mode
225  no_sound = true;
227  }
228  if (cmdline_opts_.server){
229  jump_to_multiplayer_ = true;
230  //Do we have any server specified ?
231  if (!cmdline_opts_.server->empty())
233  else //Pick the first server in config
234  {
237  else
238  multiplayer_server_ = "";
239  }
240  if (cmdline_opts_.username) {
243  if (cmdline_opts_.password) {
245  preferences::set_password(*cmdline_opts.server, *cmdline_opts.username, *cmdline_opts_.password);
246  }
247  }
248  }
249  if (cmdline_opts_.test)
250  {
251  if (!cmdline_opts_.test->empty())
252  test_scenario_ = *cmdline_opts_.test;
253  }
254  if (cmdline_opts_.unit_test)
255  {
256  if (!cmdline_opts_.unit_test->empty()) {
257  test_scenario_ = *cmdline_opts_.unit_test;
258  }
259 
260  }
261  if (cmdline_opts_.windowed)
262  video().set_fullscreen(false);
263  if (cmdline_opts_.with_replay && load_data_)
264  load_data_->show_replay = true;
265 
266  std::cerr
267  << "\nData directory: " << game_config::path
268  << "\nUser configuration directory: " << filesystem::get_user_config_dir()
269  << "\nUser data directory: " << filesystem::get_user_data_dir()
270  << "\nCache directory: " << filesystem::get_cache_dir()
271  << '\n';
272  std::cerr << '\n';
273 
274  // disable sound in nosound mode, or when sound engine failed to initialize
275  if (no_sound || ((preferences::sound_on() || preferences::music_on() ||
277  !sound::init_sound())) {
278  preferences::set_sound(false);
279  preferences::set_music(false);
282  }
283  else if (no_music) { // else disable the music in nomusic mode
284  preferences::set_music(false);
285  }
286 }
287 
289 {
291  return false;
292 
293  if(SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
294  if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1)
295  return false;
296 
297  int joysticks = SDL_NumJoysticks();
298  if (joysticks == 0) return false;
299 
300  SDL_JoystickEventState(SDL_ENABLE);
301 
302  bool joystick_found = false;
303  for (int i = 0; i<joysticks; i++) {
304 
305  if (SDL_JoystickOpen(i))
306  joystick_found = true;
307  }
308  return joystick_found;
309 }
310 
312 {
313  if(!::load_language_list())
314  return false;
315 
316  language_def locale;
317  if(cmdline_opts_.language) {
318  std::vector<language_def> langs = get_languages();
319  for(const language_def & def : langs) {
320  if(def.localename == *cmdline_opts_.language) {
321  locale = def;
322  break;
323  }
324  }
325  if(locale.localename.empty()) {
326  std::cerr << "Language symbol '" << *cmdline_opts_.language << "' not found.\n";
327  return false;
328  }
329  } else {
330  locale = get_locale();
331  }
332  ::set_language(locale);
333 
334  return true;
335 }
336 
338 {
339  // Handle special commandline launch flags
342  std::cerr << "--nogui flag is only valid with --multiplayer or --screenshot or --plugin flags\n";
343  return false;
344  }
345  video().make_fake();
346  game_config::no_delay = true;
347  return true;
348  }
349 
350  // Initialize a new window
351  video().init_window();
352 
353  // Set window title and icon
355 
356 #if !(defined(__APPLE__))
357  surface icon(image::get_image("icons/icon-game.png", image::UNSCALED));
358  if(icon != nullptr) {
359 
360  video().set_window_icon(icon);
361  }
362 #endif
363  return true;
364 }
365 
367 {
368  bool error = false;
369 
370  std::cerr << "Checking lua scripts... ";
371 
373  plugins_manager::get()->get_kernel_base()->load_package(); //load the "package" package, so that scripts can get what packages they want
374  }
375 
376  // get the application lua kernel, load and execute script file, if script file is present
378  {
380 
381  if (!sf->fail()) {
382  /* Cancel all "jumps" to editor / campaign / multiplayer */
383  jump_to_multiplayer_ = false;
384  jump_to_editor_ = false;
385  jump_to_campaign_.jump_ = false;
386 
387  std::string full_script((std::istreambuf_iterator<char>(*sf)), std::istreambuf_iterator<char>());
388 
389  std::cerr << "\nRunning lua script: " << *cmdline_opts_.script_file << std::endl;
390 
391  plugins_manager::get()->get_kernel_base()->run(full_script.c_str());
392  } else {
393  std::cerr << "Encountered failure when opening script '" << *cmdline_opts_.script_file << "'\n";
394  error = true;
395  }
396  }
397 
399  {
401 
402  std::cerr << "Loading a plugin file'" << filename << "'...\n";
403 
405 
406  try {
407  if (sf->fail()) {
408  throw std::runtime_error("failed to open plugin file");
409  }
410 
411  /* Cancel all "jumps" to editor / campaign / multiplayer */
412  jump_to_multiplayer_ = false;
413  jump_to_editor_ = false;
414  jump_to_campaign_.jump_ = false;
415 
416  std::string full_plugin((std::istreambuf_iterator<char>(*sf)), std::istreambuf_iterator<char>());
417 
419 
420  size_t i = pm.add_plugin(filename, full_plugin);
421 
422  for (size_t j = 0 ; j < pm.size(); ++j) {
423  std::cerr << j << ": " << pm.get_name(j) << " -- " << pm.get_detailed_status(j) << std::endl;
424  }
425 
426  std::cerr << "Starting a plugin...\n";
427  pm.start_plugin(i);
428 
429  for (size_t j = 0 ; j < pm.size(); ++j) {
430  std::cerr << j << ": " << pm.get_name(j) << " -- " << pm.get_detailed_status(j) << std::endl;
431  }
432 
433  plugins_context pc("init");
434 
435  for (size_t repeat = 0; repeat < 5; ++repeat) {
436  std::cerr << "Playing a slice...\n";
437  pc.play_slice();
438 
439  for (size_t j = 0 ; j < pm.size(); ++j) {
440  std::cerr << j << ": " << pm.get_name(j) << " -- " << pm.get_detailed_status(j) << std::endl;
441  }
442  }
443 
444  return true;
445  } catch (std::exception & e) {
446  gui2::show_error_message(std::string("When loading a plugin, error:\n") + e.what());
447  error = true;
448  }
449  }
450 
451  if (!error) {
452  std::cerr << "ok\n";
453  }
454 
455  return !error;
456 }
457 
459 {
460  state_.clear();
461  state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::TEST;
463 
464  state_.mp_settings().mp_era = "era_default";
465 
467  config {"next_scenario", id}
468  );
469 }
470 
472 {
473  static bool first_time = true;
474 
475  if(!cmdline_opts_.test) {
476  return true;
477  }
478  if(!first_time)
479  return false;
480 
481  first_time = false;
482 
485 
487  load_game_config_for_game(state_.classification());
488 
489  try {
491  ccontroller.play_game();
492  } catch (savegame::load_game_exception &e) {
493  load_data_.reset(new savegame::load_game_metadata(std::move(e.data_)));
494  return true;
495  }
496 
497  return false;
498 }
499 
500 // Same as play_test except that we return the results of play_game.
502 {
503  static bool first_time_unit = true;
504 
505  if(!cmdline_opts_.unit_test) {
506  return 0;
507  }
508  if(!first_time_unit)
509  return 0;
510 
511  first_time_unit = false;
512 
513  state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::TEST;
516  config {"next_scenario", test_scenario_}
517  );
518 
519 
521  load_game_config_for_game(state_.classification());
522 
523  try {
524  campaign_controller ccontroller(state_, game_config_manager::get()->game_config(), game_config_manager::get()->terrain_types(), true);
525  LEVEL_RESULT res = ccontroller.play_game();
526  if (!(res == LEVEL_RESULT::VICTORY) || lg::broke_strict()) {
527  return 1;
528  }
529  } catch(wml_exception& e) {
530  std::cerr << "Caught WML Exception:" << e.dev_message << std::endl;
531  return 1;
532  }
533 
535 
537  return 0; //we passed, huzzah!
538 
540  save.save_game_automatic(false, "unit_test_replay"); //false means don't check for overwrite
541 
542  load_data_.reset(new savegame::load_game_metadata{ "unit_test_replay" , "", true, true, false });
543 
544  if (!load_game()) {
545  std::cerr << "Failed to load the replay!" << std::endl;
546  return 3; //failed to load replay
547  }
548 
549  try {
550  campaign_controller ccontroller(state_, game_config_manager::get()->game_config(), game_config_manager::get()->terrain_types(), true);
551  LEVEL_RESULT res = ccontroller.play_replay();
552  if (!(res == LEVEL_RESULT::VICTORY) || lg::broke_strict()) {
553  std::cerr << "Observed failure on replay" << std::endl;
554  return 4;
555  }
556  } catch(wml_exception& e) {
557  std::cerr << "WML Exception while playing replay: " << e.dev_message << std::endl;
558  return 4; //failed with an error during the replay
559  }
560 
561  return 0; //we passed, huzzah!
562 }
563 
565 {
567  return true;
568  }
569 
571 
573 
576  return false;
577 }
578 
580 {
582  return true;
583  }
584 
585  state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::MULTIPLAYER;
586  DBG_GENERAL << "Current campaign type: " << state_.classification().campaign_type << std::endl;
587 
588  try {
590  load_game_config_for_game(state_.classification());
591  } catch(config::error& e) {
592  std::cerr << "Error loading game config: " << e.what() << std::endl;
593  return false;
594  }
595 
596  // A default output filename
597  std::string outfile = "wesnoth_image.bmp";
598 
599  // If a output path was given as an argument, use that instead
601  outfile = *cmdline_opts_.render_image_dst;
602  }
603 
604  if (!image::save_image(*cmdline_opts_.render_image, outfile)) {
605  exit(1);
606  }
607 
608  return false;
609 }
610 
612 {
613  return !!load_data_;
614 }
615 
617 {
618  assert(game_config_manager::get());
619 
620  DBG_GENERAL << "Current campaign type: " << state_.classification().campaign_type << std::endl;
621 
623  if (load_data_) {
624  std::unique_ptr<savegame::load_game_metadata> load_data = std::move(load_data_);
625  load.data() = std::move(*load_data);
626  }
627 
628  try {
629  if(!load.load_game()) {
630  return false;
631  }
632 
633  try {
635  load_game_config_for_game(state_.classification());
636  } catch(config::error&) {
637  return false;
638  }
639 
640  load.set_gamestate();
641 
642  } catch(config::error& e) {
643  if(e.message.empty()) {
644  gui2::show_error_message(_("The file you have tried to load is corrupt"));
645  }
646  else {
647  gui2::show_error_message(_("The file you have tried to load is corrupt: '") + e.message + '\'');
648  }
649  return false;
650  } catch(wml_exception& e) {
651  e.show();
652  return false;
653  } catch(filesystem::io_exception& e) {
654  if(e.message.empty()) {
655  gui2::show_error_message(_("File I/O Error while reading the game"));
656  } else {
657  gui2::show_error_message(_("File I/O Error while reading the game: '") + e.message + '\'');
658  }
659  return false;
660  } catch(game::error& e) {
661  if(e.message.empty()) {
662  gui2::show_error_message(_("The file you have tried to load is corrupt"));
663  }
664  else {
665  gui2::show_error_message(_("The file you have tried to load is corrupt: '") + e.message + '\'');
666  }
667  return false;
668  }
669 
670  play_replay_ = load.data().show_replay;
671  LOG_CONFIG << "is middle game savefile: " << (state_.is_mid_game_save() ? "yes" : "no") << "\n";
672  LOG_CONFIG << "show replay: " << (play_replay_ ? "yes" : "no") << "\n";
673  // in case load.data().show_replay && !state_.is_mid_game_save()
674  // there won't be any turns to replay, but the
675  // user gets to watch the intro sequence again ...
676 
677  if(state_.is_mid_game_save() && load.data().show_replay)
678  {
680  }
681 
682  if(state_.classification().campaign_type == game_classification::CAMPAIGN_TYPE::MULTIPLAYER) {
684  }
685 
686  if (load.data().cancel_orders) {
688  }
689 
690  return true;
691 }
692 
694 {
695  state_.clear();
696  state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::TUTORIAL;
697  state_.classification().campaign_define = "TUTORIAL";
698  state_.mp_settings().mp_era = "era_default";
700  config {"next_scenario", "tutorial"}
701  );
702 
703 }
704 
705 void game_launcher::mark_completed_campaigns(std::vector<config> &campaigns)
706 {
707  for (config &campaign : campaigns) {
708  campaign["completed"] = preferences::is_campaign_completed(campaign["id"]);
709  }
710 }
711 
713 {
714  state_.clear();
716  play_replay_ = false;
717 
719 }
720 
722 {
724 }
725 
727 {
729  if(new_campaign()) {
730  jump_to_campaign_.jump_ = false;
732  }else{
733  jump_to_campaign_.jump_ = false;
734  return false;
735  }
736  }
737  return true;
738 }
739 
741 {
743  jump_to_multiplayer_ = false;
745  ;
746  }else{
747  return false;
748  }
749  }
750  return true;
751 }
752 
754 {
755  if(jump_to_editor_){
756  jump_to_editor_ = false;
757  std::unique_ptr<savegame::load_game_metadata> load_data = std::move(load_data_);
758  if (start_editor(filesystem::normalize_path(load_data ? load_data->filename : "")) ==
760  {
761  return false;
762  }
763  }
764  return true;
765 }
766 
768 {
769  const std::string wesnothd_program =
772 
773  std::string config = filesystem::get_user_config_dir() + "/lan_server.cfg";
774  if (!filesystem::file_exists(config)) {
775  // copy file if it isn't created yet
777  }
778 
779 #ifndef _WIN32
780  std::string command = "\"" + wesnothd_program +"\" -c \"" + config + "\" -d -t 2 -T 5";
781 #else
782  // start wesnoth as background job
783  std::string command = "cmd /C start \"wesnoth server\" /B \"" + wesnothd_program + "\" -c \"" + config + "\" -t 2 -T 5";
784  // Make sure wesnothd's console output is visible on the console window by
785  // disabling SDL's stdio redirection code for this and future child
786  // processes. No need to bother cleaning this up because it's only
787  // meaningful to SDL applications during pre-main initialization.
788  SetEnvironmentVariableA("SDL_STDIO_REDIRECT", "0");
789 #endif
790  LOG_GENERAL << "Starting wesnothd: "<< command << "\n";
791  if (std::system(command.c_str()) == 0) {
792  // Give server a moment to start up
793  SDL_Delay(50);
794  return;
795  }
797 
798  // Couldn't start server so throw error
799  WRN_GENERAL << "Failed to run server start script" << std::endl;
800  throw game::mp_server_error("Starting MP server failed!");
801 }
802 
804 {
805  state_.clear();
806  state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::MULTIPLAYER;
807 
808  try {
809  if (res == MP_HOST)
810  {
811  try {
812  start_wesnothd();
813  } catch(game::mp_server_error&)
814  {
816 
817  try {
818  start_wesnothd();
819  } catch(game::mp_server_error&)
820  {
821  return false;
822  }
823  }
824 
825 
826  }
827 
828  // If a server address wasn't specified, prompt for it now.
829  if(res != MP_LOCAL && multiplayer_server_.empty()) {
830  if(!gui2::dialogs::mp_connect::execute()) {
831  return false;
832  }
833 
834  // The prompt saves its input to preferences.
836 
837  if(multiplayer_server_ != preferences::server_list().front().address) {
839  }
840  }
841 
842  //create_engine already calls game_config_manager::get()->load_config but maybe its better to have MULTIPLAYER defined while we are in the lobby.
844 
845  events::discard_input(); // prevent the "keylogger" effect
847 
848  if(res == MP_LOCAL) {
851  } else {
854  multiplayer_server_.clear();
855  }
856 
859  } catch(game::mp_server_error& e) {
860  gui2::show_error_message(_("Error while starting server: ") + e.message);
861  } catch(game::load_game_failed& e) {
862  gui2::show_error_message(_("The game could not be loaded: ") + e.message);
863  } catch(game::game_error& e) {
864  gui2::show_error_message(_("Error while playing the game: ") + e.message);
865  } catch (mapgen_exception& e) {
866  gui2::show_error_message(_("Map generator error: ") + e.message);
867  } catch(wesnothd_error& e) {
868  if(!e.message.empty()) {
869  ERR_NET << "caught network error: " << e.message << std::endl;
871  } else {
872  ERR_NET << "caught network error" << std::endl;
873  }
874  } catch(config::error& e) {
875  if(!e.message.empty()) {
876  ERR_CONFIG << "caught config::error: " << e.message << std::endl;
878  } else {
879  ERR_CONFIG << "caught config::error" << std::endl;
880  }
881  } catch(incorrect_map_format_error& e) {
882  gui2::show_error_message(_("The game map could not be loaded: ") + e.message);
883  } catch (savegame::load_game_exception & e) {
884  load_data_.reset(new savegame::load_game_metadata(std::move(e.data_)));
885  //this will make it so next time through the title screen loop, this game is loaded
886  } catch(wml_exception& e) {
887  e.show();
888  } catch (game::error & e) {
889  std::cerr << "caught game::error...\n";
890  gui2::show_error_message(_("Error: ") + e.message);
891  }
892 
893  return false;
894 }
895 
897 {
899  return true;
900  }
901 
902  DBG_MP << "starting multiplayer game from the commandline" << std::endl;
903 
904  // These are all the relevant lines taken literally from play_multiplayer() above
905  state_.clear();
906  state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::MULTIPLAYER;
907 
909  load_game_config_for_game(state_.classification());
910 
911  events::discard_input(); // prevent the "keylogger" effect
913 
916 
917  return false;
918 }
919 
921 {
923  dlg.show();
924  if (dlg.get_retval() != gui2::window::OK) return false;
925 
928  }
929 
930  return true;
931 }
932 
934 {
936 }
937 
939 {
940  assert(!load_data_);
941  if(play_replay_)
942  {
943  play_replay();
944  return;
945  }
946 
947  gui2::dialogs::loading_screen::display([this, reload]() {
948 
950  if(reload == RELOAD_DATA) {
951  try {
953  load_game_config_for_game(state_.classification());
954  } catch(config::error&) {
955  return;
956  }
957  }
958  });
959 
960  try {
962  LEVEL_RESULT result = ccontroller.play_game();
963  ai::manager::singleton_ = nullptr;
964  // don't show The End for multiplayer scenario
965  // change this if MP campaigns are implemented
966  if(result == LEVEL_RESULT::VICTORY && !state_.classification().is_normal_mp_game()) {
968 
969  gui2::dialogs::outro::display(state_.classification().end_text, state_.classification().end_text_duration);
970 
972  gui2::dialogs::end_credits::display(state_.classification().campaign);
973  }
974  }
975  } catch (savegame::load_game_exception &e) {
976  load_data_.reset(new savegame::load_game_metadata(std::move(e.data_)));
977  //this will make it so next time through the title screen loop, this game is loaded
978  } catch(wml_exception& e) {
979  e.show();
980  } catch(mapgen_exception& e) {
981  gui2::show_error_message(_("Map generator error: ") + e.message);
982  }
983 }
984 
986 {
987  assert(!load_data_);
988  try {
990  ccontroller.play_replay();
991  } catch (savegame::load_game_exception &e) {
992  load_data_.reset(new savegame::load_game_metadata(std::move(e.data_)));
993  //this will make it so next time through the title screen loop, this game is loaded
994  } catch(wml_exception& e) {
995  e.show();
996  }
997 }
998 
1000 {
1001  while(true){
1003 
1005 
1007  game_config_manager::get()->game_config(), filename);
1008 
1009  if(res != editor::EXIT_RELOAD_DATA)
1010  return res;
1011 
1013  }
1014  return editor::EXIT_ERROR; // not supposed to happen
1015 }
1016 
1018 {
1019  load_data_.reset();
1020 }
1021 
1023 {
1024  try {
1026  } catch (...) {}
1027 }
boost::optional< std::string > core_id
Non-empty if –core was given on the command line. Chooses the core to be loaded. ...
CVideo & video()
boost::optional< std::string > script_file
File to load lua script from.
An error occurred during when trying to coommunicate with the wesnothd server.
bool new_widgets
Do we wish to use the new library or not.
Definition: settings.cpp:21
surface get_image(const image::locator &i_locator, TYPE type)
function to get the surface corresponding to an image.
Definition: image.cpp:920
unsigned int end_text_duration
for how long the end-of-campaign text is shown
void set_window_icon(surface &icon)
Sets the icon of the main window.
Definition: video.cpp:364
bool set_sound(bool ison)
Definition: general.cpp:665
void close_sound()
Definition: sound.cpp:457
std::string get_program_invocation(const std::string &program_name)
Returns the appropriate invocation for a Wesnoth-related binary, assuming that it is located in the s...
LEVEL_RESULT play_replay()
bool load_game()
Load a game with pre-setting information for the load-game dialog.
Definition: savegame.cpp:156
static lg::log_domain log_mp_create("mp/create")
Dialog is closed with ok button.
Definition: window.hpp:101
bool turn_bell()
Definition: general.cpp:607
void discard_input()
Discards all input events.
Definition: events.cpp:727
bool end_credits
whether to show the standard credits at the end
void start_local_game_commandline(const config &game_config, saved_game &state, const commandline_options &cmdline_opts)
Starts a multiplayer game in single-user mode.
const char * what() const NOEXCEPT
Definition: exceptions.hpp:37
std::vector< char_t > string
Error used when the client is rejected by the MP server.
LEVEL_RESULT play_game()
bool nogui
True if –nogui was given on the command line. Disables GUI.
The class for loading a savefile.
Definition: savegame.hpp:96
bool script_unsafe_mode
Whether to load the "package" package for the scripting environment. (This allows to load arbitrary l...
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
Definition: cursor.cpp:154
void _set_maximized(bool ison)
Definition: general.cpp:407
std::string label
Name of the game (e.g.
void disable_preferences_save()
Definition: general.cpp:248
std::string filename
Name of the savefile to be loaded.
Definition: savegame.hpp:40
size_t add_plugin(const std::string &name, const std::string &prog)
Definition: manager.cpp:118
void set_gamestate()
Generate the gamestate out of the loaded game config.
Definition: savegame.cpp:260
bool cancel_orders
State of the "cancel_orders" checkbox in the load-game dialog.
Definition: savegame.hpp:49
std::vector< game_tip > load(const config &cfg)
Loads the tips from a config.
Definition: tips.cpp:35
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
#define DBG_MP
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:39
Error used when game loading fails.
Definition: game_errors.hpp:30
void show_wesnothd_server_search()
Definition: display.cpp:152
void show_preferences()
Definition: video.hpp:31
bool is_campaign_completed(const std::string &campaign_id)
Definition: game.cpp:319
This file contains the window object, this object is a top level container which has the event manage...
std::string network_host()
Definition: game.cpp:386
void set_language(const std::string &language, const std::vector< std::string > *alternates)
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup, const bool restore_background)
Shows a transient message to the user.
static void progress(loading_stage stage=loading_stage::none)
void unify_controllers()
Definition: saved_game.cpp:611
bool is_mid_game_save() const
Definition: saved_game.hpp:89
const language_def & get_locale()
Definition: language.cpp:249
void _set_resolution(const point &res)
Definition: general.cpp:401
boost::optional< std::string > username
Non-empty if –username was given on the command line. Forces Wesnoth to use this network username...
void mark_completed_campaigns(std::vector< config > &campaigns)
boost::optional< std::string > campaign_scenario
Non-empty if –campaign-scenario was given on the command line. Chooses starting scenario in the camp...
std::string get_default_title_string()
void clear()
Definition: saved_game.cpp:699
boost::optional< int > max_fps
Max FPS specified by –max-fps option.
bool fps
True if –fps was given on the command line. Shows number of fps.
bool change_language()
void set_network_host(const std::string &host)
Definition: game.cpp:396
std::string normalize_path(const std::string &path, bool normalize_separators=false, bool resolve_dot_entries=false)
Returns the absolute path of a file.
bool noreplaycheck
True if –noreplaycheck was given on the command line. Dependent on –unit.
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).
load_game_metadata & data()
Definition: savegame.hpp:115
boost::optional< std::string > plugin_file
File to load a lua plugin (similar to a script) from. Experimental / may replace script.
bool sound_on()
Definition: general.cpp:660
#define DBG_GENERAL
load_game_metadata data_
Definition: savegame.hpp:89
jump_to_campaign_info jump_to_campaign_
boost::optional< std::string > load
Non-empty if –load was given on the command line. Savegame specified to load after start...
bool save_image(const locator &i_locator, const std::string &filename)
Definition: image.cpp:1198
bool init_sound()
Definition: sound.cpp:405
static lg::log_domain log_config("config")
bool broke_strict()
Definition: log.cpp:171
bool play_multiplayer(mp_selection res)
std::string get_cwd()
void set_mp_server_program_name(const std::string &path)
Definition: game.cpp:513
void set_window_title(const std::string &title)
Sets the title of the main window.
Definition: video.cpp:358
bool play_render_image_mode()
bool headless_unit_test
True if –unit is used and –showgui is not present.
static game_config_manager * get()
void make_fake()
Definition: video.cpp:171
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:89
#define ERR_CONFIG
bool joystick_support_enabled()
Definition: general.cpp:723
font::manager font_manager_
filesystem::scoped_istream istream_file(const std::string &fname, bool treat_failure_as_error=true)
static lg::log_domain log_enginerefac("enginerefac")
This file contains the settings handling of the widget library.
bool nodelay
True if –nodelay was given on the command line.
std::string get_user_data_dir()
void write_file(const std::string &fname, const std::string &data)
Throws io_exception if an error occurs.
static lg::log_domain log_network("network")
std::string multiplayer_server_
std::string campaign_define
If there is a define the campaign uses to customize data.
editor::EXIT_STATUS start_editor()
void set_login(const std::string &login)
std::string localename
Definition: language.hpp:46
void load_package()
Loads the package library into lua environment.
boost::optional< std::string > editor
Non-empty if –editor was given on the command line. Goes directly into editor. If string is longer t...
void set_show_fps(bool value)
Definition: general.cpp:970
const std::vector< game_config::server_info > & server_list()
Definition: game.cpp:369
std::unique_ptr< std::istream > scoped_istream
Definition: filesystem.hpp:37
void set_test(const std::string &id)
std::string end_text
end-of-campaign text
void set_password(const std::string &server, const std::string &login, const std::string &key)
void set_core_id(const std::string &core_id)
Definition: general.cpp:321
std::string path
Definition: game_config.cpp:56
boost::optional< std::string > test
Non-empty if –test was given on the command line. Goes directly into test mode, into a scenario...
void init_textdomains(const config &cfg)
Initializes the list of textdomains from a configuration object.
Definition: language.cpp:289
bool multiplayer
True if –multiplayer was given on the command line. Goes directly into multiplayer mode...
Managing the AIs lifecycle - headers.
bool UI_sound_on()
Definition: general.cpp:631
if(win_locale=="af") win_locale
game_launcher(const commandline_options &cmdline_opts, const char *appname)
std::string campaign
The id of the campaign being played.
bool clock
True if –clock was given on the command line. Enables.
static UNUSEDNOWARN std::string gettext(const char *str)
Definition: gettext.hpp:64
Error used for any general game error, e.g.
Definition: game_errors.hpp:46
std::string read_file(const std::string &fname)
Basic disk I/O - read file.
std::string screenshot_map_
std::unique_ptr< savegame::load_game_metadata > load_data_
#define LOG_CONFIG
void set_draw_delay(int value)
Definition: general.cpp:980
boost::optional< std::string > render_image
Image path to render. First parameter after –render-image.
void start_client(const config &game_config, saved_game &state, const std::string &host)
Starts a multiplayer game in client mode.
void show()
Shows the error in a dialog.
void set_level(const std::string &value)
Definition: game.cpp:715
boost::optional< int > campaign_difficulty
Non-empty if –campaign-difficulty was given on the command line. Numerical difficulty of the campaig...
Helper class, don't construct this directly.
bool nomusic
True if –nomusic was given on the command line. Disables music.
void run(char const *prog, int nArgs=0)
Runs a plain script.
std::string dev_message
The message for developers telling which problem was triggered, this shouldn't be translated...
std::string get_detailed_status(size_t idx)
Definition: manager.cpp:83
size_t size(const utf8::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
std::string get_cache_dir()
Exception used to signal that the user has decided to abortt a game, and to load another game instead...
Definition: savegame.hpp:74
static void display(const config &game_cfg, const preferences::PREFERENCE_VIEW initial_view=preferences::VIEW_DEFAULT)
The display function – see modal_dialog for more information.
#define WRN_GENERAL
boost::optional< std::string > password
Non-empty if –password was given on the command line. Forces Wesnoth to use this network password...
std::string jump_to_campaign_id() const
bool debug
True if –debug was given on the command line. Enables debug mode.
void start_local_game(const config &game_config, saved_game &state)
Starts a multiplayer game in single-user mode.
std::string get_mp_server_program_name()
Definition: game.cpp:525
boost::optional< std::string > screenshot_map_file
Map file to make a screenshot of. First parameter given after –screenshot.
std::string get_wml_location(const std::string &filename, const std::string &current_dir=std::string())
Returns a complete path to the actual WML file or directory or an empty string if the file isn't pres...
void clean_saves(const std::string &label)
Delete all autosaves of a certain scenario.
Definition: savegame.cpp:65
void load_game_config_for_create(bool is_mp, bool is_test=false)
Game configuration data as global variables.
Definition: build_info.cpp:53
bool new_widgets
True if –new-widgets was given on the command line. Hidden option to enable the new widget toolkit...
#define ERR_NET
void init_window()
Initializes a new SDL window instance, taking into account any preiously saved states.
Definition: video.cpp:219
EXIT_STATUS start(const config &game_conf, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
Definition: editor_main.cpp:28
An exception object used when an IO error occurs.
Definition: filesystem.hpp:46
bool music_on()
Definition: general.cpp:683
void add_completed_campaign(const std::string &campaign_id, const std::string &difficulty_level)
Definition: game.cpp:315
bool load_language_list()
Definition: language.cpp:91
size_t i
Definition: function.cpp:933
language_list get_languages()
Definition: language.cpp:114
void set_fullscreen(bool ison)
Definition: video.cpp:528
Holds a 2D point.
Definition: point.hpp:23
bool set_UI_sound(bool ison)
Definition: general.cpp:636
bool goto_multiplayer()
Declarations for File-IO.
static void save(LexState *ls, int c)
Definition: llex.cpp:57
void launch_game(RELOAD_GAME_DATA reload=RELOAD_DATA)
Class for replay saves (either manually or automatically).
Definition: savegame.hpp:255
-file mapgen.hpp
std::string get_name(size_t idx)
Definition: manager.cpp:94
std::string difficulty
The difficulty level the game is being played on.
boost::optional< std::string > render_image_dst
Output file to put rendered image path in. Optional second parameter after –render-image.
std::string base_name(const std::string &file, const bool remove_extension=false)
Returns the base filename of a file, with directory name stripped.
static manager * singleton_
Definition: manager.hpp:489
std::string get_user_config_dir()
bool screenshot
True if –screenshot was given on the command line. Starts Wesnoth in screenshot mode.
void cancel_orders()
Definition: saved_game.cpp:594
boost::optional< std::string > unit_test
Non-empty if –unit was given on the command line. Goes directly into unit test mode, into a scenario, if specified.
bool show_replay
State of the "show_replay" checkbox in the load-game dialog.
Definition: savegame.hpp:46
static void display(std::function< void()> f)
const commandline_options & cmdline_opts_
CONSTEXPR const T & clamp(const T &value, const T &min, const T &max)
Definition: general.hpp:31
Base class for all the errors encountered by the engine.
Definition: exceptions.hpp:29
void start_plugin(size_t idx)
Definition: manager.cpp:101
game_classification & classification()
Definition: saved_game.hpp:55
std::string screenshot_filename_
void set_carryover_sides_start(config carryover_sides_start)
Definition: saved_game.cpp:125
saved_game state_
bool set_music(bool ison)
Definition: general.cpp:688
Standard logging facilities (interface).
bool is_loading() const
boost::optional< std::string > screenshot_output_file
Output file to put screenshot in. Second parameter given after –screenshot.
bool set_turn_bell(bool ison)
Definition: general.cpp:612
void clear_loaded_game()
std::string message
Definition: exceptions.hpp:31
bool fullscreen
True if –fullscreen was given on the command line. Starts Wesnoth in fullscreen mode.
void show_error_message(const std::string &msg, bool message_use_markup)
Shows an error message to the user.
Definition: message.cpp:205
boost::optional< std::string > language
Non-empty if –language was given on the command line. Sets the language for this session...
#define e
std::string test_scenario_
bool nosound
True if –nosound was given on the command line. Disables sound.
boost::optional< std::pair< int, int > > resolution
Pair of AxB values specified after –resolution. Changes Wesnoth resolution.
bool play_screenshot_mode()
lua_kernel_base * get_kernel_base()
Definition: manager.cpp:63
boost::optional< std::string > campaign
Non-empty if –campaign was given on the command line. ID of the campaign we want to start...
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
void clear_current_scenario()
Definition: statistics.cpp:646
mp_game_settings & mp_settings()
Multiplayer parameters for this game.
Definition: saved_game.hpp:59
bool enter_create_mode(saved_game &state, jump_to_campaign_info jump_to_campaign)
bool file_exists(const std::string &name)
Returns true if a file or directory with such name already exists.
bool init_lua_script()
std::vector< server_info > server_list
bool save_game_automatic(bool ask_for_overwrite=false, const std::string &filename="")
Saves a game without user interaction, unless the file exists and it should be asked to overwrite it...
Definition: savegame.cpp:335
boost::optional< std::string > server
Non-empty if –server was given on the command line. Connects Wesnoth to specified server...
bool play_multiplayer_commandline()
static plugins_manager * get()
Definition: manager.cpp:58
void play_slice()
Definition: context.cpp:96
#define LOG_GENERAL
bool show_debug_clock_button
Do we wish to show the button for the debug clock.