/** * Setups the game environment and enters * the titlescreen or game loops. */ static int do_gameloop(const std::vector<std::string>& args) { srand(time(nullptr)); commandline_options cmdline_opts = commandline_options(args); game_config::wesnoth_program_dir = filesystem::directory_name(args[0]); int finished = process_command_args(cmdline_opts); if(finished != -1) { return finished; } boost::scoped_ptr<game_launcher> game( new game_launcher(cmdline_opts,args[0].c_str())); const int start_ticks = SDL_GetTicks(); init_locale(); bool res; // do initialize fonts before reading the game config, to have game // config error messages displayed. fonts will be re-initialized later // when the language is read from the game config. res = font::load_font_config(); if(res == false) { std::cerr << "could not initialize fonts\n"; // The most common symptom of a bogus data dir path -- warn the user. warn_early_init_failure(); return 1; } res = game->init_language(); if(res == false) { std::cerr << "could not initialize the language\n"; return 1; } res = game->init_video(); if(res == false) { std::cerr << "could not initialize display\n"; return 1; } res = image::update_from_preferences(); if(res == false) { std::cerr << "could not initialize image preferences\n"; return 1; } if(preferences::joystick_support_enabled()) { res = game->init_joystick(); if(res == false) { std::cerr << "could not initialize joystick\n"; } } check_fpu(); const cursor::manager cursor_manager; cursor::set(cursor::WAIT); #if (defined(_X11) && !defined(__APPLE__)) || defined(_WIN32) SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); #endif gui2::init(); const gui2::event::tmanager gui_event_manager; game_config_manager config_manager(cmdline_opts, game->video(), game->jump_to_editor()); gui2::tloadscreen::display(game->video(), [&res, &config_manager]() { gui2::tloadscreen::progress("load config"); res = config_manager.init_game_config(game_config_manager::NO_FORCE_RELOAD); if(res == false) { std::cerr << "could not initialize game config\n"; return; } gui2::tloadscreen::progress("init fonts"); res = font::load_font_config(); if(res == false) { std::cerr << "could not re-initialize fonts for the current language\n"; return; } gui2::tloadscreen::progress("refresh addons"); refresh_addon_version_info_cache(); }); if(res == false) { return 1; } config tips_of_day; LOG_CONFIG << "time elapsed: "<< (SDL_GetTicks() - start_ticks) << " ms\n"; plugins_manager plugins_man(new application_lua_kernel(&game->video())); plugins_context::Reg const callbacks[] = { { "play_multiplayer", std::bind(&game_launcher::play_multiplayer, game.get())}, }; plugins_context::aReg const accessors[] = { { "command_line", std::bind(&commandline_options::to_config, &cmdline_opts)}, }; plugins_context plugins("titlescreen", callbacks, accessors); plugins.set_callback("exit", std::bind(&safe_exit, std::bind(get_int, std::placeholders::_1, "code", 0)), false); for (;;) { // reset the TC, since a game can modify it, and it may be used // by images in add-ons or campaigns dialogs image::set_team_colors(); statistics::fresh_stats(); if (!game->is_loading()) { const config &cfg = config_manager.game_config().child("titlescreen_music"); if (cfg) { sound::play_music_repeatedly(game_config::title_music); for (const config &i : cfg.child_range("music")) { sound::play_music_config(i); } sound::commit_music_changes(); } else { sound::empty_playlist(); sound::stop_music(); } } handle_lua_script_args(&*game,cmdline_opts); plugins.play_slice(); plugins.play_slice(); if(cmdline_opts.unit_test) { if(cmdline_opts.timeout) { std::cerr << "The wesnoth built-in timeout feature has been removed.\n" << std::endl; std::cerr << "Please use a platform-specific script which will kill the overtime process instead.\n" << std::endl; std::cerr << "For examples in bash, or in windows cmd, see the forums, or the wesnoth repository." << std::endl; std::cerr << "The bash script is called `run_wml_tests`, the windows script is part of the VC project.\n" << std::endl; } int worker_result = game->unit_test(); std::cerr << ((worker_result == 0) ? "PASS TEST " : "FAIL TEST ") << ((worker_result == 3) ? "(INVALID REPLAY)" : "") << ((worker_result == 4) ? "(ERRORED REPLAY)" : "") << ": "<<*cmdline_opts.unit_test << std::endl; return worker_result; } if(game->play_test() == false) { return 0; } if(game->play_screenshot_mode() == false) { return 0; } if(game->play_render_image_mode() == false) { return 0; } //Start directly a campaign if(game->goto_campaign() == false){ if (game->jump_to_campaign_id().empty()) continue; //Go to main menu else return 1; //we got an error starting the campaign from command line } //Start directly a multiplayer //Eventually with a specified server if(game->goto_multiplayer() == false){ continue; //Go to main menu } //Start directly a commandline multiplayer game if(game->play_multiplayer_commandline() == false) { return 0; } if (game->goto_editor() == false) { return 0; } gui2::ttitle_screen::tresult res = game->is_loading() ? gui2::ttitle_screen::LOAD_GAME : gui2::ttitle_screen::NOTHING; preferences::load_hotkeys(); const font::floating_label_context label_manager; cursor::set(cursor::NORMAL); if(res == gui2::ttitle_screen::NOTHING) { gui2::ttitle_screen dlg; dlg.show(game->video()); res = static_cast<gui2::ttitle_screen::tresult>(dlg.get_retval()); } game_launcher::RELOAD_GAME_DATA should_reload = game_launcher::RELOAD_DATA; if(res == gui2::ttitle_screen::QUIT_GAME) { LOG_GENERAL << "quitting game...\n"; return 0; } else if(res == gui2::ttitle_screen::LOAD_GAME) { if(game->load_game() == false) { game->clear_loaded_game(); res = gui2::ttitle_screen::NOTHING; continue; } should_reload = game_launcher::NO_RELOAD_DATA; } else if(res == gui2::ttitle_screen::TUTORIAL) { game->set_tutorial(); } else if(res == gui2::ttitle_screen::NEW_CAMPAIGN) { if(game->new_campaign() == false) { continue; } should_reload = game_launcher::NO_RELOAD_DATA; } else if(res == gui2::ttitle_screen::MULTIPLAYER) { game_config::debug = game_config::mp_debug; if(game->play_multiplayer() == false) { continue; } } else if(res == gui2::ttitle_screen::CHANGE_LANGUAGE) { try { if (game->change_language()) { tips_of_day.clear(); t_string::reset_translations(); image::flush_cache(); } } catch ( std::runtime_error & e ) { gui2::show_error_message(game->video(), e.what()); } continue; } else if(res == gui2::ttitle_screen::EDIT_PREFERENCES) { game->show_preferences(); continue; } else if(res == gui2::ttitle_screen::SHOW_ABOUT) { about::show_about(game->video()); continue; } else if(res == gui2::ttitle_screen::SHOW_HELP) { help::help_manager help_manager(&config_manager.game_config()); help::show_help(game->video()); continue; } else if(res == gui2::ttitle_screen::GET_ADDONS) { // NOTE: we need the help_manager to get access to the Add-ons // section in the game help! help::help_manager help_manager(&config_manager.game_config()); if(manage_addons(game->video())) { config_manager.reload_changed_game_config(); } continue; } else if(res == gui2::ttitle_screen::CORES) { int current = 0; std::vector<config> cores; for (const config& core : game_config_manager::get()->game_config().child_range("core")) { cores.push_back(core); if (core["id"] == preferences::core_id()) current = cores.size() -1; } gui2::tcore_selection core_dlg(cores, current); if (core_dlg.show(game->video())) { int core_index = core_dlg.get_choice(); const std::string& core_id = cores[core_index]["id"]; preferences::set_core_id(core_id); config_manager.reload_changed_game_config(); } continue; } else if(res == gui2::ttitle_screen::RELOAD_GAME_DATA) { gui2::tloadscreen::display(game->video(), [&config_manager]() { config_manager.reload_changed_game_config(); image::flush_cache(); }); continue; } else if(res == gui2::ttitle_screen::START_MAP_EDITOR) { game->start_editor(); continue; } game->launch_game(should_reload); } }
/** * Setups the game environment and enters * the titlescreen or game loops. */ static int do_gameloop(const std::vector<std::string>& args) { srand(time(nullptr)); commandline_options cmdline_opts = commandline_options(args); game_config::wesnoth_program_dir = filesystem::directory_name(args[0]); int finished = process_command_args(cmdline_opts); if(finished != -1) { #ifdef _WIN32 if(lg::using_own_console()) { std::cerr << "Press enter to continue..." << std::endl; std::cin.get(); } #endif return finished; } const std::unique_ptr<game_launcher> game(new game_launcher(cmdline_opts, args[0].c_str())); const int start_ticks = SDL_GetTicks(); init_locale(); bool res; // Do initialize fonts before reading the game config, to have game // config error messages displayed. fonts will be re-initialized later // when the language is read from the game config. res = font::load_font_config(); if(res == false) { std::cerr << "could not initialize fonts\n"; // The most common symptom of a bogus data dir path -- warn the user. warn_early_init_failure(); return 1; } res = game->init_language(); if(res == false) { std::cerr << "could not initialize the language\n"; return 1; } res = game->init_video(); if(res == false) { std::cerr << "could not initialize display\n"; return 1; } res = image::update_from_preferences(); if(res == false) { std::cerr << "could not initialize image preferences\n"; return 1; } if(preferences::joystick_support_enabled()) { res = game->init_joystick(); if(res == false) { std::cerr << "could not initialize joystick\n"; } } check_fpu(); const cursor::manager cursor_manager; cursor::set(cursor::WAIT); #if(defined(_X11) && !defined(__APPLE__)) || defined(_WIN32) SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); #endif gui2::init(); const gui2::event::manager gui_event_manager; game_config_manager config_manager(cmdline_opts, game->jump_to_editor()); gui2::dialogs::loading_screen::display([&res, &config_manager]() { gui2::dialogs::loading_screen::progress(loading_stage::load_config); res = config_manager.init_game_config(game_config_manager::NO_FORCE_RELOAD); if(res == false) { std::cerr << "could not initialize game config\n"; return; } gui2::dialogs::loading_screen::progress(loading_stage::init_fonts); res = font::load_font_config(); if(res == false) { std::cerr << "could not re-initialize fonts for the current language\n"; return; } gui2::dialogs::loading_screen::progress(loading_stage::refresh_addons); refresh_addon_version_info_cache(); }); if(res == false) { return 1; } LOG_CONFIG << "time elapsed: " << (SDL_GetTicks() - start_ticks) << " ms\n"; plugins_manager plugins_man(new application_lua_kernel); plugins_context::Reg const callbacks[] { {"play_multiplayer", std::bind(&game_launcher::play_multiplayer, game.get(), game_launcher::MP_CONNECT)}, }; plugins_context::aReg const accessors[] { {"command_line", std::bind(&commandline_options::to_config, &cmdline_opts)}, }; plugins_context plugins("titlescreen", callbacks, accessors); plugins.set_callback("exit", [](const config& cfg) { safe_exit(cfg["code"].to_int(0)); }, false); for(;;) { // reset the TC, since a game can modify it, and it may be used // by images in add-ons or campaigns dialogs image::set_team_colors(); statistics::fresh_stats(); if(!game->is_loading()) { const config& cfg = config_manager.game_config().child("titlescreen_music"); if(cfg) { sound::play_music_repeatedly(game_config::title_music); for(const config& i : cfg.child_range("music")) { sound::play_music_config(i); } sound::commit_music_changes(); } else { sound::empty_playlist(); sound::stop_music(); } } handle_lua_script_args(&*game, cmdline_opts); plugins.play_slice(); plugins.play_slice(); if(cmdline_opts.unit_test) { if(cmdline_opts.timeout) { std::cerr << "The wesnoth built-in timeout feature has been removed.\n" << std::endl; std::cerr << "Please use a platform-specific script which will kill the overtime process instead.\n" << std::endl; std::cerr << "For examples in bash, or in windows cmd, see the forums, or the wesnoth repository." << std::endl; std::cerr << "The bash script is called `run_wml_tests`, the windows script is part of the VC project.\n" << std::endl; } int worker_result = game->unit_test(); std::cerr << ((worker_result == 0) ? "PASS TEST " : "FAIL TEST ") << ((worker_result == 3) ? "(INVALID REPLAY)" : "") << ((worker_result == 4) ? "(ERRORED REPLAY)" : "") << ": " << *cmdline_opts.unit_test << std::endl; return worker_result; } if(game->play_test() == false) { return 0; } if(game->play_screenshot_mode() == false) { return 0; } if(game->play_render_image_mode() == false) { return 0; } // Start directly a campaign if(game->goto_campaign() == false) { if(game->jump_to_campaign_id().empty()) continue; // Go to main menu else return 1; // we got an error starting the campaign from command line } // Start directly a multiplayer // Eventually with a specified server if(game->goto_multiplayer() == false) { continue; // Go to main menu } // Start directly a commandline multiplayer game if(game->play_multiplayer_commandline() == false) { return 0; } if(game->goto_editor() == false) { return 0; } preferences::load_hotkeys(); const font::floating_label_context label_manager; cursor::set(cursor::NORMAL); game_launcher::RELOAD_GAME_DATA should_reload = game_launcher::RELOAD_DATA; // If loading a game, skip the titlescreen entirely if(game->is_loading()) { if(!game->load_game()) { game->clear_loaded_game(); } game->launch_game(should_reload); continue; } gui2::dialogs::title_screen dlg(*game); /* * Quick explanation of the titlscreen loop: * * The dialog's redraw_background_ flag is initialized as true in the constructor, so the dialog will always * display at least once when this loop is executed. Each time it's opened, the aforementioned flag is set to * false, and any selection that results in leaving the dialog simply sets the window's retval and proceeds to * the appropriate action. * * Certain actions (such as window resizing) set the flag to true, which allows the dialog to reopen with any * layout changes such as those dictated by window resolution. */ while(dlg.get_retval() == gui2::dialogs::title_screen::REDRAW_BACKGROUND) { dlg.show(); } switch(dlg.get_retval()) { case gui2::dialogs::title_screen::QUIT_GAME: LOG_GENERAL << "quitting game...\n"; return 0; case gui2::dialogs::title_screen::MP_CONNECT: game_config::debug = game_config::mp_debug; if(!game->play_multiplayer(game_launcher::MP_CONNECT)) { continue; } break; case gui2::dialogs::title_screen::MP_HOST: game_config::debug = game_config::mp_debug; if(!game->play_multiplayer(game_launcher::MP_HOST)) { continue; } break; case gui2::dialogs::title_screen::MP_LOCAL: game_config::debug = game_config::mp_debug; if(!game->play_multiplayer(game_launcher::MP_LOCAL)) { continue; } break; case gui2::dialogs::title_screen::RELOAD_GAME_DATA: gui2::dialogs::loading_screen::display([&config_manager]() { config_manager.reload_changed_game_config(); image::flush_cache(); }); break; case gui2::dialogs::title_screen::MAP_EDITOR: game->start_editor(); break; case gui2::dialogs::title_screen::SHOW_ABOUT: gui2::dialogs::end_credits::display(); break; case gui2::dialogs::title_screen::LAUNCH_GAME: game->launch_game(should_reload); break; case gui2::dialogs::title_screen::REDRAW_BACKGROUND: break; } } }