Beispiel #1
0
/**
 * 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;
		}
	}
}
Beispiel #2
0
/**
 * 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);
	}
}
namespace mips_private {
    // Cache a local copy so we only have to read /proc/cpuinfo once.
    uint32_t Flags = get_mips_flags();
    bool hasFPU = check_fpu();;
    bool isLoongson = check_loongson();
}