void playmp_controller::wait_for_upload()
{
	// If the host is here we'll never leave since we wait for the host to
	// upload the next scenario.
	assert(!is_host());

	config cfg;
	network_reader_.set_source(playturn_network_adapter::get_source_from_config(cfg));
	while(true) {
		try {
			const bool res =
				mp_info_->connection.fetch_data_with_loading_screen(cfg, loading_stage::next_scenario);

			if(res) {
				if (turn_data_.process_network_data_from_reader() == turn_info::PROCESS_END_LINGER) {
					break;
				}
			}
			else
			{
				throw_quit_game_exception();
			}

		} catch(const quit_game_exception&) {
			network_reader_.set_source([this](config& cfg) { return receive_from_wesnothd(cfg);});
			turn_data_.send_data();
			throw;
		}
	}
	network_reader_.set_source([this](config& cfg) { return receive_from_wesnothd(cfg);});
}
void playmp_controller::wait_for_upload()
{
	// If the host is here we'll never leave since we wait for the host to
	// upload the next scenario.
	assert(!is_host());

	config cfg;
	network_reader_.set_source(playturn_network_adapter::get_source_from_config(cfg));
	while(true) {
		try {
			const network::connection res = dialogs::network_receive_dialog(
				gui_->video(), _("Waiting for next scenario..."), cfg);

			if(res != network::null_connection) {
				if (turn_data_.process_network_data_from_reader() == turn_info::PROCESS_END_LINGER) {
					break;
				}
			}
			else
			{
				throw_quit_game_exception();
			}

		} catch(const quit_game_exception&) {
			network_reader_.set_source(playturn_network_adapter::read_network);
			turn_data_.send_data();
			throw;
		}
	}
	network_reader_.set_source(playturn_network_adapter::read_network);
}
void tsynced_choice_wait::on_btn_quit_game(CVideo& video)
{
	const int res = gui2::show_message(video, _("Quit"),
		_("Do you really want to quit?"), gui2::tmessage::yes_no_buttons);
	if (res != gui2::twindow::CANCEL) {
		throw_quit_game_exception();
	}
}
void key_event(display& disp, const SDL_KeyboardEvent& event, command_executor* executor)
{
	if (!executor) return;
	if(event.keysym.sym == SDLK_ESCAPE && disp.in_game()) {
		LOG_G << "escape pressed..showing quit\n";
		const int res = gui2::show_message(disp.video(), _("Quit"),
				_("Do you really want to quit?"), gui2::tmessage::yes_no_buttons);
		if(res != gui2::twindow::CANCEL) {
			throw_quit_game_exception();
		} else {
			return;
		}
	}

	key_event_execute(disp, event,executor);
}
Exemple #5
0
bool savegame::save_game_interactive(CVideo& video, const std::string& message,
									 gui::DIALOG_TYPE dialog_type)
{
	show_confirmation_ = true;
	create_filename();

	const int res = show_save_dialog(video, message, dialog_type);

	if (res == 2) { 
		throw_quit_game_exception(); //Quit game
	}

	if (res == gui2::twindow::OK && check_overwrite(video)) {
		return save_game(&video);
	}

	return false;
}
Exemple #6
0
turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg)
{
	// the simple wesnothserver implementation in wesnoth was removed years ago.
	assert(cfg.all_children_count() == 1);
	assert(cfg.attribute_range().first == cfg.attribute_range().second);
	if(!resources::recorder->at_end())
	{
		ERR_NW << "processing network data while still having data on the replay." << std::endl;
	}

	if (const config &msg = cfg.child("message"))
	{
		resources::screen->get_chat_manager().add_chat_message(time(nullptr), msg["sender"], msg["side"],
				msg["message"], events::chat_handler::MESSAGE_PUBLIC,
				preferences::message_bell());
	}
	else if (const config &msg = cfg.child("whisper") /*&& is_observer()*/)
	{
		resources::screen->get_chat_manager().add_chat_message(time(nullptr), "whisper: " + msg["sender"].str(), 0,
				msg["message"], events::chat_handler::MESSAGE_PRIVATE,
				preferences::message_bell());
	}
	else if (const config &ob = cfg.child("observer") )
	{
		resources::screen->get_chat_manager().add_observer(ob["name"]);
	}
	else if (const config &ob = cfg.child("observer_quit"))
	{
		resources::screen->get_chat_manager().remove_observer(ob["name"]);
	}
	else if (cfg.child("leave_game")) {
		throw ingame_wesnothd_error("");
	}
	else if (const config &turn = cfg.child("turn"))
	{
		return handle_turn(turn);
	}
	else if (cfg.has_child("whiteboard"))
	{
		resources::whiteboard->process_network_data(cfg);
	}
	else if (const config &change = cfg.child("change_controller"))
	{
		if(change.empty()) {
			ERR_NW << "Bad [change_controller] signal from server, [change_controller] tag was empty." << std::endl;
			return PROCESS_CONTINUE;
		}

		const int side = change["side"].to_int();
		const bool is_local = change["is_local"].to_bool();
		const std::string player = change["player"];
		const size_t index = side - 1;
		if(index >= resources::gameboard->teams().size()) {
			ERR_NW << "Bad [change_controller] signal from server, side out of bounds: " << change.debug() << std::endl;
			return PROCESS_CONTINUE;
		}

		const team & tm = resources::gameboard->teams().at(index);
		const bool was_local = tm.is_local();

		resources::gameboard->side_change_controller(side, is_local, player);

		if (!was_local && tm.is_local()) {
			resources::controller->on_not_observer();
		}

		if (resources::gameboard->is_observer() || (resources::gameboard->teams())[resources::screen->playing_team()].is_local_human()) {
			resources::screen->set_team(resources::screen->playing_team());
			resources::screen->redraw_everything();
			resources::screen->recalculate_minimap();
		} else if (tm.is_local_human()) {
			resources::screen->set_team(side - 1);
			resources::screen->redraw_everything();
			resources::screen->recalculate_minimap();
		}

		resources::whiteboard->on_change_controller(side,tm);

		resources::screen->labels().recalculate_labels();

		const bool restart = resources::screen->playing_side() == side && (was_local || tm.is_local());
		return restart ? PROCESS_RESTART_TURN : PROCESS_CONTINUE;
	}

	else if (const config &side_drop_c = cfg.child("side_drop"))
	{
		const int  side_drop = side_drop_c["side_num"].to_int(0);
		size_t index = side_drop -1;

		bool restart = side_drop == resources::screen->playing_side();

		if (index >= resources::teams->size()) {
			ERR_NW << "unknown side " << side_drop << " is dropping game" << std::endl;
			throw ingame_wesnothd_error("");
		}

		team::CONTROLLER ctrl;
		if(!ctrl.parse(side_drop_c["controller"])) {
			ERR_NW << "unknown controller type issued from server on side drop: " << side_drop_c["controller"] << std::endl;
			throw ingame_wesnothd_error("");
		}
		
		if (ctrl == team::CONTROLLER::AI) {
			resources::gameboard->side_drop_to(side_drop, ctrl);
			return restart ? PROCESS_RESTART_TURN:PROCESS_CONTINUE;
		}
		//null controlled side cannot be dropped becasue they aren't controlled by anyone.
		else if (ctrl != team::CONTROLLER::HUMAN) {
			ERR_NW << "unknown controller type issued from server on side drop: " << ctrl.to_cstring() << std::endl;
			throw ingame_wesnothd_error("");
		}

		int action = 0;
		int first_observer_option_idx = 0;
		int control_change_options = 0;
		bool has_next_scenario = !resources::gamedata->next_scenario().empty() && resources::gamedata->next_scenario() != "null";

		std::vector<std::string> observers;
		std::vector<const team *> allies;
		std::vector<std::string> options;

		const team &tm = resources::gameboard->teams()[index];

		for (const team &t : resources::gameboard->teams()) {
			if (!t.is_enemy(side_drop) && !t.is_local_human() && !t.is_local_ai() && !t.is_network_ai() && !t.is_empty()
				&& t.current_player() != tm.current_player()) {
				allies.push_back(&t);
			}
		}

		// We want to give host chance to decide what to do for side
		if (!resources::controller->is_linger_mode() || has_next_scenario) {
			utils::string_map t_vars;

			//get all allies in as options to transfer control
			for (const team *t : allies) {
				//if this is an ally of the dropping side and it is not us (choose local player
				//if you want that) and not ai or empty and if it is not the dropping side itself,
				//get this team in as well
				t_vars["player"] = t->current_player();
				options.push_back(vgettext("Give control to their ally $player", t_vars));
				control_change_options++;
			}

			first_observer_option_idx = options.size();

			//get all observers in as options to transfer control
			for (const std::string &ob : resources::screen->observers()) {
				t_vars["player"] = ob;
				options.push_back(vgettext("Give control to observer $player", t_vars));
				observers.push_back(ob);
				control_change_options++;
			}

			options.push_back(_("Replace with AI"));
			options.push_back(_("Replace with local player"));
			options.push_back(_("Set side to idle"));
			options.push_back(_("Save and abort game"));

			t_vars["player"] = tm.current_player();
			const std::string msg =  vgettext("$player has left the game. What do you want to do?", t_vars);
			gui2::tsimple_item_selector dlg("", msg, options);
			dlg.set_single_button(true);
			dlg.show(resources::screen->video());
			action = dlg.selected_index();

			// If esc was pressed, default to setting side to idle
			if (action == -1) {
				action = control_change_options + 2;
			}
		} else {
			// Always set leaving side to idle if in linger mode and there is no next scenario
			action = 2;
		}

		if (action < control_change_options) {
			// Grant control to selected ally
			
			{
				// Server thinks this side is ours now so in case of error transferring side we have to make local state to same as what server thinks it is.
				resources::gameboard->side_drop_to(side_drop, team::CONTROLLER::HUMAN, team::PROXY_CONTROLLER::PROXY_IDLE);
			}

			if (action < first_observer_option_idx) {
				change_side_controller(side_drop, allies[action]->current_player());
			} else {
				change_side_controller(side_drop, observers[action - first_observer_option_idx]);
			}

			return restart ? PROCESS_RESTART_TURN : PROCESS_CONTINUE;
		} else {
			action -= control_change_options;

			//make the player an AI, and redo this turn, in case
			//it was the current player's team who has just changed into
			//an AI.
			switch(action) {
				case 0:
					resources::controller->on_not_observer();
					resources::gameboard->side_drop_to(side_drop, team::CONTROLLER::HUMAN, team::PROXY_CONTROLLER::PROXY_AI);

					return restart?PROCESS_RESTART_TURN:PROCESS_CONTINUE;

				case 1:
					resources::controller->on_not_observer();
					resources::gameboard->side_drop_to(side_drop, team::CONTROLLER::HUMAN, team::PROXY_CONTROLLER::PROXY_HUMAN);

					return restart?PROCESS_RESTART_TURN:PROCESS_CONTINUE;
				case 2:
					resources::gameboard->side_drop_to(side_drop, team::CONTROLLER::HUMAN, team::PROXY_CONTROLLER::PROXY_IDLE);

					return restart?PROCESS_RESTART_TURN:PROCESS_CONTINUE;

				case 3:
					//The user pressed "end game". Don't throw a network error here or he will get
					//thrown back to the title screen.
					do_save();
					throw_quit_game_exception();
				default:
					break;
			}
		}
	}

	// The host has ended linger mode in a campaign -> enable the "End scenario" button
	// and tell we did get the notification.
	else if (cfg.child("notify_next_scenario")) {
		gui::button* btn_end = resources::screen->find_action_button("button-endturn");
		if(btn_end) {
			btn_end->enable(true);
		}
		return PROCESS_END_LINGER;
	}

	//If this client becomes the new host, notify the play_controller object about it
	else if (cfg.child("host_transfer")){
		host_transfer_.notify_observers();
	}
	else
	{
		ERR_NW << "found unknown command:\n" << cfg.debug() << std::endl;
	}

	return PROCESS_CONTINUE;
}
void execute_command(display& disp, const hotkey_command& command, command_executor* executor, int index)
{
	const int zoom_amount = 4;
	bool map_screenshot = false;

	if (executor != NULL) {
		if (!executor->can_execute_command(command, index)
				|| executor->execute_command(command, index)) {
			return;
		}
	}
	switch (command.id) {

		case HOTKEY_MINIMAP_DRAW_TERRAIN:
			preferences::toggle_minimap_draw_terrain();
			disp.recalculate_minimap();
			break;
		case HOTKEY_MINIMAP_CODING_TERRAIN:
			preferences::toggle_minimap_terrain_coding();
			disp.recalculate_minimap();
			break;
		case HOTKEY_MINIMAP_CODING_UNIT:
			preferences::toggle_minimap_movement_coding();
			disp.recalculate_minimap();
			break;
		case HOTKEY_MINIMAP_DRAW_UNITS:
			preferences::toggle_minimap_draw_units();
			disp.redraw_minimap();
			break;
		case HOTKEY_MINIMAP_DRAW_VILLAGES:
			preferences::toggle_minimap_draw_villages();
			disp.recalculate_minimap();
			break;
		case HOTKEY_ZOOM_IN:
			disp.set_zoom(zoom_amount);
			break;
		case HOTKEY_ZOOM_OUT:
			disp.set_zoom(-zoom_amount);
			break;
		case HOTKEY_ZOOM_DEFAULT:
			disp.set_default_zoom();
			break;
		case HOTKEY_FULLSCREEN:
			preferences::set_fullscreen(!preferences::fullscreen());
			break;
		case HOTKEY_MAP_SCREENSHOT:
			if (!disp.in_game() && !disp.in_editor()) {
				break;
			}
			map_screenshot = true;
			// intentional fall-through
		case HOTKEY_SCREENSHOT: {
			const std::string name = map_screenshot ? _("Map-Screenshot") : _("Screenshot");
			std::string filename = filesystem::get_screenshot_dir() + "/" + name + "_";
#ifdef HAVE_LIBPNG
			const std::string ext = ".png";
#else
			const std::string ext = ".bmp";
#endif
			filename = filesystem::get_next_filename(filename, ext);
			const bool res = disp.screenshot(filename, map_screenshot);
			if (res) {
				gui2::tscreenshot_notification::display(filename, disp.video());
			} else {
				gui2::show_error_message(disp.video(),
										 _("Screenshot creation failed.\n\n"
										 "Make sure there is enough space on the drive holding Wesnoth’s player resource files and that file permissions are set up correctly."));
			}
			break;
		}
		case HOTKEY_ANIMATE_MAP:
			preferences::set_animate_map(!preferences::animate_map());
			break;
		case HOTKEY_MOUSE_SCROLL:
			preferences::enable_mouse_scroll(!preferences::mouse_scroll_enabled());
			break;
		case HOTKEY_MUTE:
			{
				// look if both is not playing
				static struct before_muted_s
				{
					bool playing_sound,playing_music;
					before_muted_s() : playing_sound(false),playing_music(false){}
				} before_muted;
				if (preferences::music_on() || preferences::sound_on())
				{
					// then remember settings and mute both
					before_muted.playing_sound = preferences::sound_on();
					before_muted.playing_music = preferences::music_on();
					preferences::set_sound(false);
					preferences::set_music(false);
				}
				else
				{
					// then set settings before mute
					preferences::set_sound(before_muted.playing_sound);
					preferences::set_music(before_muted.playing_music);
				}
			}
			break;
		case HOTKEY_QUIT_GAME: {
			if (disp.in_game()) {
				DBG_G << "is in game -- showing quit message\n";
				const int res = gui2::show_message(disp.video(), _("Quit"),
						_("Do you really want to quit?"), gui2::tmessage::yes_no_buttons);
				if (res != gui2::twindow::CANCEL) {
					throw_quit_game_exception();
				}
			}
			break;
		}
		case LUA_CONSOLE: {
			if (!disp.in_game()) {
				//WRN_G << "caution: attempting to interface console with game lua kernel when we are not in game...\n";
				gui2::tlua_interpreter::display(disp.video(), gui2::tlua_interpreter::APP);
			} else {
				gui2::tlua_interpreter::display(disp.video(), gui2::tlua_interpreter::GAME);
			}
			break;
		}
		default:
			DBG_G << "command_executor: unknown command number " << command.id << ", ignoring.\n";
			break;
	}
}
 void operator()(const config&)
 {
     throw_quit_game_exception();
 }