Backend changes to allow uses of proper display names for missing content in MP Lobby

For Campaigns, I needed to store the campaign name in the classification info.

For Eras, I repurposed the mp_era_addon_id key I added a year ago in d88f591eb5. It wasn't used anywhere
else, and having a better name for missing eras was the original reason to add it. I'm not sure why I
didn't think to use the name directly at the time; I do seem to have used addon_id for mod names too, but
that was changed in 5a55899b83 and again now (see below).

For Modifications, I added the relevant mod name to the server data. Why only this type of content
required a server change I'm not entirely sure. :/ This also finally properly fixes #1794.
This commit is contained in:
Charles Dang 2017-10-26 23:50:00 +11:00
parent e2a6979f60
commit 1bfa170856
9 changed files with 38 additions and 31 deletions

View file

@ -38,6 +38,7 @@ game_classification::game_classification()
, era_define()
, mod_defines()
, campaign()
, campaign_name()
, abbrev()
, end_credits(true)
, end_text()
@ -59,6 +60,7 @@ game_classification::game_classification(const config& cfg)
, era_define(cfg["era_define"])
, mod_defines(utils::split(cfg["mod_defines"]))
, campaign(cfg["campaign"])
, campaign_name(cfg["campaign_name"])
, abbrev(cfg["abbrev"])
, end_credits(cfg["end_credits"].to_bool(true))
, end_text(cfg["end_text"])
@ -79,6 +81,7 @@ game_classification::game_classification(const game_classification& gc)
, era_define(gc.era_define)
, mod_defines(gc.mod_defines)
, campaign(gc.campaign)
, campaign_name(gc.campaign_name)
, abbrev(gc.abbrev)
, end_credits(gc.end_credits)
, end_text(gc.end_text)
@ -101,6 +104,7 @@ config game_classification::to_config() const
cfg["era_define"] = era_define;
cfg["mod_defines"] = utils::join(mod_defines);
cfg["campaign"] = campaign;
cfg["campaign_name"] = campaign_name;
cfg["abbrev"] = abbrev;
cfg["end_credits"] = end_credits;
cfg["end_text"] = end_text;

View file

@ -50,7 +50,8 @@ public:
std::string era_define; /**< If there is a define the era uses to customize data */
std::vector<std::string> mod_defines; /**< If there are defines the modifications use to customize data */
std::string campaign; /**< the campaign being played */
std::string campaign; /**< The id of the campaign being played */
std::string campaign_name; /**< The name of the campaign being played. */
std::string abbrev; /**< the campaign abbreviation */
bool end_credits; /**< whether to show the standard credits at the end */

View file

@ -398,6 +398,7 @@ void create_engine::prepare_for_campaign(const std::string& difficulty)
config& current_level_data = current_level().data();
state_.classification().campaign = current_level_data["id"].str();
state_.classification().campaign_name = current_level_data["name"].str();
state_.classification().abbrev = current_level_data["abbrev"].str();
state_.classification().end_text = current_level_data["end_text"].str();
@ -653,7 +654,7 @@ const mp_game_settings& create_engine::get_parameters()
int era_index = current_level().allow_era_choice() ? current_era_index_ : 0;
state_.mp_settings().mp_era = eras_[era_index]->id;
state_.mp_settings().mp_era_addon_id = (*eras_[era_index]->cfg)["addon_id"].str();
state_.mp_settings().mp_era_name = (*eras_[era_index]->cfg)["name"].str();
return state_.mp_settings();
}

View file

@ -212,9 +212,10 @@ game_info::game_info(const config& game, const config& game_config, const std::v
required_addon r;
r.addon_id = c[id_key].str();
r.outcome = NEED_DOWNLOAD;
r.message = vgettext("Missing addon: $id", {{"id", c[id_key].str()}});
required_addons.push_back(r);
required_addons.push_back(std::move(r));
if(addons_outcome == SATISFIED) {
addons_outcome = NEED_DOWNLOAD;
}
@ -234,7 +235,6 @@ game_info::game_info(const config& game, const config& game_config, const std::v
parse_requirements(mod, "addon_id");
}
std::string turn = game["turn"];
if(!game["mp_era"].empty()) {
const config& era_cfg = game_config.find_child("era", "id", game["mp_era"]);
if(era_cfg) {
@ -248,7 +248,7 @@ game_info::game_info(const config& game, const config& game_config, const std::v
addons_outcome = std::max(addons_outcome, result); // Elevate to most severe error level encountered so far
} else {
have_era = !game["require_era"].to_bool(true);
era = vgettext("Unknown era: $era_id", {{"era_id", game["mp_era_addon_id"].str()}});
era = vgettext("Unknown era: $era_name", {{"era_name", game["mp_era_name"].str()}});
era_short = make_short_name(era);
verified = false;
@ -263,28 +263,23 @@ game_info::game_info(const config& game, const config& game_config, const std::v
std::stringstream info_stream;
info_stream << era;
if(!game.child_or_empty("modification").empty()) {
for(const config& cfg : game.child_range("modification")) {
for(const config& cfg : game.child_range("modification")) {
mod_info += (mod_info.empty() ? "" : ", ") + cfg["name"].str();
if(cfg["require_modification"].to_bool(false)) {
if(const config& mod = game_config.find_child("modification", "id", cfg["id"])) {
mod_info += (mod_info.empty() ? "" : ", ") + mod["name"].str();
if(cfg["require_modification"].to_bool(false)) {
ADDON_REQ result = check_addon_version_compatibility(mod, game);
addons_outcome = std::max(addons_outcome, result); // Elevate to most severe error level encountered so far
}
ADDON_REQ result = check_addon_version_compatibility(mod, game);
addons_outcome = std::max(addons_outcome, result); // Elevate to most severe error level encountered so far
} else {
mod_info += (mod_info.empty() ? "" : ", ") + cfg["id"].str();
have_all_mods = false;
mod_info += " " + _("(missing)");
if(cfg["require_modification"].to_bool(false)) {
have_all_mods = false;
mod_info += " " + _("(missing)");
addons_outcome = NEED_DOWNLOAD;
}
addons_outcome = NEED_DOWNLOAD;
}
}
}
if(map_data.empty()) {
map_data = filesystem::read_map(game["mp_scenario"]);
}
@ -356,15 +351,15 @@ game_info::game_info(const config& game, const config& game_config, const std::v
verified = false;
}
} else if(!game["mp_campaign"].empty()) {
if(const config& level_cfg = game_config.find_child("campaign", "id", game["mp_campaign"])) {
if(const config& campaign_cfg = game_config.find_child("campaign", "id", game["mp_campaign"])) {
std::stringstream campaign_text;
campaign_text
<< "<b>" << _("(C)") << "</b>" << " "
<< level_cfg["name"] << ""
<< campaign_cfg["name"] << ""
<< game["mp_scenario_name"];
// Difficulty
config difficulties = gui2::dialogs::generate_difficulty_config(level_cfg);
config difficulties = gui2::dialogs::generate_difficulty_config(campaign_cfg);
for(const config& difficulty : difficulties.child_range("difficulty")) {
if(difficulty["define"] == game["difficulty_define"]) {
campaign_text << "" << difficulty["description"];
@ -378,11 +373,11 @@ game_info::game_info(const config& game, const config& game_config, const std::v
// TODO: should we have this?
//if(game["require_scenario"].to_bool(false)) {
ADDON_REQ result = check_addon_version_compatibility(level_cfg, game);
ADDON_REQ result = check_addon_version_compatibility(campaign_cfg, game);
addons_outcome = std::max(addons_outcome, result); // Elevate to most severe error level encountered so far
//}
} else {
scenario = vgettext("Unknown campaign: $campaign_id", {{"campaign_id", game["mp_campaign"].str()}});
scenario = vgettext("Unknown campaign: $campaign_id", {{"campaign_id", game["mp_campaign_name"].str()}});
info_stream << scenario;
verified = false;
}
@ -401,6 +396,8 @@ game_info::game_info(const config& game, const config& game_config, const std::v
verified = false;
}
std::string turn = game["turn"];
if(!turn.empty()) {
started = true;
int index = turn.find_first_of('/');
@ -452,7 +449,7 @@ game_info::ADDON_REQ game_info::check_addon_version_compatibility(const config&
version_info local_min_ver(local_item.has_attribute("addon_min_version") ? local_item["addon_min_version"] : local_item["addon_version"]);
// If the UMC didn't specify last compatible version, assume no backwards compatibility.
// Also apply some sanity checking regarding min version; if the min ver doens't make sense, ignore it.
// Also apply some sanity checking regarding min version; if the min ver doesn't make sense, ignore it.
local_min_ver = std::min(local_min_ver, local_ver);
// Remote version

View file

@ -47,6 +47,7 @@ static void add_multiplayer_classification(config& multiplayer, saved_game& stat
multiplayer["mp_scenario_name"] = state.get_starting_pos()["name"];
multiplayer["difficulty_define"] = state.classification().difficulty;
multiplayer["mp_campaign"] = state.classification().campaign;
multiplayer["mp_campaign_name"] = state.classification().campaign_name;
}
config initial_level_config(saved_game& state)

View file

@ -473,6 +473,8 @@ static bool enter_lobby_mode(mp_workflow_helper_ptr helper, const std::vector<st
sound::stop_music();
}
helper->state.clear();
mp::lobby_info li(helper->game_config, installed_addons);
helper->lobby_info = &li;

View file

@ -33,7 +33,7 @@ mp_game_settings::mp_game_settings() :
password(),
hash(),
mp_era(),
mp_era_addon_id(),
mp_era_name(),
mp_scenario(),
mp_scenario_name(),
mp_campaign(),
@ -67,7 +67,7 @@ mp_game_settings::mp_game_settings(const config& cfg)
, password()
, hash(cfg["hash"].str())
, mp_era(cfg["mp_era"].str())
, mp_era_addon_id(cfg["mp_era_addon_id"].str())
, mp_era_name(cfg["mp_era_name"].str())
, mp_scenario(cfg["mp_scenario"].str())
, mp_scenario_name(cfg["mp_scenario_name"].str())
, mp_campaign(cfg["mp_campaign"].str())
@ -109,7 +109,7 @@ config mp_game_settings::to_config() const
cfg["scenario"] = name;
cfg["hash"] = hash;
cfg["mp_era"] = mp_era;
cfg["mp_era_addon_id"] = mp_era_addon_id;
cfg["mp_era_name"] = mp_era_name;
cfg["mp_scenario"] = mp_scenario;
cfg["mp_scenario_name"] = mp_scenario_name;
cfg["mp_campaign"] = mp_campaign;

View file

@ -36,7 +36,7 @@ struct mp_game_settings
std::string password;
std::string hash;
std::string mp_era;
std::string mp_era_addon_id;
std::string mp_era_name;
std::string mp_scenario;
std::string mp_scenario_name;
std::string mp_campaign;

View file

@ -1318,6 +1318,7 @@ void server::handle_player_in_game(socket_ptr socket, std::shared_ptr<simple_wml
for(const simple_wml::node* m : mlist) {
desc.add_child_at("modification", 0);
desc.child("modification")->set_attr_dup("id", m->attr("id"));
desc.child("modification")->set_attr_dup("name", m->attr("name"));
desc.child("modification")->set_attr_dup("addon_id", m->attr("addon_id"));
if (m->attr("require_modification").to_bool(false))
desc.child("modification")->set_attr("require_modification", "yes");