void wait::join_game(bool observe) { //if we have got valid side data //the first condition is to make sure that we don't have another //WML message with a side-tag in it while (!level_.has_attribute("version") || !level_.child("side")) { network::connection data_res = dialogs::network_receive_dialog(disp(), _("Getting game data..."), level_); if (!data_res) { set_result(QUIT); return; } check_response(data_res, level_); if(level_.child("leave_game")) { set_result(QUIT); return; } } // Add the map name to the title. append_to_title(": " + level_["name"].t_str()); if (!observe) { //search for an appropriate vacant slot. If a description is set //(i.e. we're loading from a saved game), then prefer to get the side //with the same description as our login. Otherwise just choose the first //available side. const config *side_choice = NULL; int side_num = -1, nb_sides = 0; foreach (const config &sd, level_.child_range("side")) { if (sd["controller"] == "reserved" && sd["current_player"] == preferences::login()) { side_choice = &sd; side_num = nb_sides; break; } if (sd["controller"] == "network" && sd["player_id"].empty()) { if (!side_choice) { // found the first empty side side_choice = &sd; side_num = nb_sides; } if (sd["current_player"] == preferences::login()) { side_choice = &sd; side_num = nb_sides; break; // found the preferred one } } ++nb_sides; } if (!side_choice) { set_result(QUIT); return; } bool allow_changes = (*side_choice)["allow_changes"].to_bool(true); //if the client is allowed to choose their team, instead of having //it set by the server, do that here. std::string leader_choice, gender_choice; if(allow_changes) { events::event_context context; const config &era = level_.child("era"); /** @todo Check whether we have the era. If we don't inform the user. */ if (!era) throw config::error(_("No era information found.")); config::const_child_itors possible_sides = era.child_range("multiplayer_side"); if (possible_sides.first == possible_sides.second) { set_result(QUIT); throw config::error(_("No multiplayer sides found")); return; } int color = side_num; const std::string color_str = (*side_choice)["color"]; if (!color_str.empty()) color = game_config::color_info(color_str).index() - 1; std::vector<const config *> leader_sides; foreach (const config &side, possible_sides) { leader_sides.push_back(&side); } int forced_faction = find_suitable_faction(leader_sides, *side_choice); if (forced_faction >= 0) { const config *f = leader_sides[forced_faction]; leader_sides.clear(); leader_sides.push_back(f); } std::vector<std::string> choices; foreach (const config *s, leader_sides) { const config &side = *s; const std::string &name = side["name"]; const std::string &icon = side["image"]; if (!icon.empty()) { std::string rgb = side["flag_rgb"]; if (rgb.empty()) rgb = "magenta"; choices.push_back(IMAGE_PREFIX + icon + "~RC(" + rgb + ">" + lexical_cast<std::string>(color+1) + ")" + COLUMN_SEPARATOR + name); } else { choices.push_back(name); } } std::vector<gui::preview_pane* > preview_panes; leader_preview_pane leader_selector(disp(), leader_sides, color); preview_panes.push_back(&leader_selector); const int res = gui::show_dialog(disp(), NULL, _("Choose your faction:"), _("Starting position: ") + lexical_cast<std::string>(side_num + 1), gui::OK_CANCEL, &choices, &preview_panes); if(res < 0) { set_result(QUIT); return; } const int faction_choice = res; leader_choice = leader_selector.get_selected_leader(); gender_choice = leader_selector.get_selected_gender(); assert(static_cast<unsigned>(faction_choice) < leader_sides.size()); config faction; config& change = faction.add_child("change_faction"); change["name"] = preferences::login(); change["faction"] = forced_faction >= 0 ? forced_faction : faction_choice; change["leader"] = leader_choice; change["gender"] = gender_choice; network::send_data(faction, 0); } }
void wait::join_game(bool observe) { const bool download_res = download_level_data(); if (!download_res) { DBG_MP << "mp wait: could not download level data, quitting..."; set_result(QUIT); return; } else if (!get_scenario()["allow_new_game"].to_bool(true) && !level_.child_or_empty("multiplayer")["savegame"].to_bool(false)) { set_result(PLAY); return; } if (first_scenario_) { state_ = saved_game(); state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::MULTIPLAYER; const config* campaign = &game_config_manager::get()-> game_config().find_child("campaign", "id", level_.child("multiplayer")["mp_campaign"]); const config* scenario = &game_config_manager::get()-> game_config().find_child("multiplayer", "id", level_.child(lexical_cast<std::string>(game_classification::CAMPAIGN_TYPE::MULTIPLAYER))["id"]); const config* era = &game_config_manager::get()-> game_config().find_child("era", "id", level_.child("era")["id"]); if (*campaign) { state_.classification().difficulty = level_.child("multiplayer")["difficulty_define"].str(); state_.classification().campaign_define = (*campaign)["define"].str(); state_.classification().campaign_xtra_defines = utils::split((*campaign)["extra_defines"]); } if (*scenario) state_.classification().scenario_define = (*scenario)["define"].str(); if (*era) state_.classification().era_define = (*era)["define"].str(); BOOST_FOREACH(const config& mod, level_.child_range("modification")) { const config* modification = &game_config_manager::get()-> game_config().find_child("modification", "id", mod["id"]); if (*modification) { state_.classification().mod_defines.push_back( (*modification)["define"].str()); } } // Make sure that we have the same config as host, if possible. game_config_manager::get()-> load_game_config_for_game(state_.classification()); } // Add the map name to the title. append_to_title(": " + get_scenario()["name"].t_str()); if (!observe) { //search for an appropriate vacant slot. If a description is set //(i.e. we're loading from a saved game), then prefer to get the side //with the same description as our login. Otherwise just choose the first //available side. const config *side_choice = NULL; int side_num = -1, nb_sides = 0; BOOST_FOREACH(const config &sd, get_scenario().child_range("side")) { DBG_MP << "*** side " << nb_sides << "***\n" << sd.debug() << "***\n"; if (sd["controller"] == "reserved" && sd["current_player"] == preferences::login()) { side_choice = &sd; side_num = nb_sides; break; } if (sd["controller"] == "network" && sd["player_id"].empty()) { if (!side_choice) { // found the first empty side side_choice = &sd; side_num = nb_sides; } if (sd["current_player"] == preferences::login()) { side_choice = &sd; side_num = nb_sides; break; // found the preferred one } } ++nb_sides; } if (!side_choice) { size_t count = 0; for(config::child_itors its = get_scenario().child_range("side"); its.second != its.first; ++its.first) { ++count; } DBG_MP << "could not find a side, all " << count << " sides were unsuitable\n"; set_result(QUIT); return; } bool allow_changes = (*side_choice)["allow_changes"].to_bool(true); //if the client is allowed to choose their team, instead of having //it set by the server, do that here. if(allow_changes) { events::event_context context; const config &era = level_.child("era"); /** @todo Check whether we have the era. If we don't inform the user. */ if (!era) throw config::error(_("No era information found.")); config::const_child_itors possible_sides = era.child_range("multiplayer_side"); if (possible_sides.first == possible_sides.second) { set_result(QUIT); throw config::error(_("No multiplayer sides found")); } int color = side_num; const std::string color_str = (*side_choice)["color"]; if (!color_str.empty()) color = game_config::color_info(color_str).index() - 1; std::vector<const config*> era_factions; BOOST_FOREACH(const config &side, possible_sides) { era_factions.push_back(&side); } const bool lock_settings = get_scenario()["force_lock_settings"].to_bool(); const bool use_map_settings = level_.child("multiplayer")["mp_use_map_settings"].to_bool(); const bool saved_game = level_.child("multiplayer")["savegame"].to_bool(); ng::flg_manager flg(era_factions, *side_choice, lock_settings, use_map_settings, saved_game, color); std::vector<std::string> choices; BOOST_FOREACH(const config *s, flg.choosable_factions()) { const config &side = *s; const std::string &name = side["name"]; const std::string &icon = side["image"]; if (!icon.empty()) { std::string rgb = side["flag_rgb"]; if (rgb.empty()) rgb = "magenta"; choices.push_back(IMAGE_PREFIX + icon + "~RC(" + rgb + ">" + lexical_cast<std::string>(color+1) + ")" + COLUMN_SEPARATOR + name); } else { choices.push_back(name); } } std::vector<gui::preview_pane* > preview_panes; leader_preview_pane leader_selector(disp(), flg, color); preview_panes.push_back(&leader_selector); const int faction_choice = gui::show_dialog(disp(), NULL, _("Choose your faction:"), _("Starting position: ") + lexical_cast<std::string>(side_num + 1), gui::OK_CANCEL, &choices, &preview_panes); if(faction_choice < 0) { set_result(QUIT); return; } config faction; config& change = faction.add_child("change_faction"); change["change_faction"] = true; change["name"] = preferences::login(); change["faction"] = flg.current_faction()["id"]; change["leader"] = flg.current_leader(); change["gender"] = flg.current_gender(); network::send_data(faction, 0); } }