Deploy and refactor config::optional_child
Previously the config class had an operator bool and it was a common pattern to use if(const config& = cfg.child(..)). While this pattern was nice to use. It has severe drawbacks, in particular it was unclear whether a function that took a config& parameter allowed "invalid" configs, while most functions did not, there were some that did. Furtheremore it lead to a few buggy codes that were unconvered by this change (Not fixed though!), in particular codes that tested local config objects that were not references to being invalid, which could never be the case. This commits replaces those with just `true` in order to not change behaviour. Some obvious cases were also removed including for example things like `assert(config());` There is ony case in the ai code that i'm not 100% sure of where one implementation of a virtual function checked for an invalid config and another one that didn't. With this, all code that check for a config child to be present now uses config::optional_child which returns an object that behaves similar to optional<(const) config&>, so it throws on invalid dereferencing. But it also has operator[string] for convinience, in particular to make is similary easy to use the the previous `if (config& = .. child())`. Also it has a tool DEBUG_CONFIG which tests whether all optional_config values are checked before they are derefereneced. Another method manditory_child was added that throws when the key is not found, which replaces all occurances of child() that did not check whether the result was valid. This was neccecary (this= adding a new method instead of renaming .child) to keep track of converted changes, and be sure no occurances of child() were accidentally changed to the throwing version. We might want to rename one of mandatory_child or optional_child to just child later. Not sure which one yet. I think it's better to keep it in the current state (no config::child() ) for a while though, so that people that currently used child() in their open prs or other work get an error and not wrongly rely on the previous behviour of config::child. The interface of vconfig was not changed in this commit.
This commit is contained in:
parent
231f9ea905
commit
f8bd32eb15
150 changed files with 918 additions and 999 deletions
|
@ -32,7 +32,7 @@ tprogress_bar_definition::tresolution::tresolution(const config& cfg) /*@ \label
|
|||
* * state_enabled, the progress bar is enabled.
|
||||
*/
|
||||
// Note the order should be the same as the enum tstate is progress_bar.hpp.
|
||||
state.push_back(tstate_definition(cfg.child("state_enabled")));
|
||||
state.push_back(state_definition(cfg.optional_child("state_enabled")));
|
||||
}
|
||||
|
||||
} // namespace gui2
|
||||
|
|
|
@ -86,7 +86,7 @@ undo_action_base * undo_list::create_action(const config & cfg)
|
|||
|
||||
else if ( str == "recruit" ) {
|
||||
// Validate the unit type.
|
||||
const config & child = cfg.child("unit");
|
||||
const config & child = cfg.mandatory_child("unit");
|
||||
const unit_type * u_type = unit_types.find(child["type"]);
|
||||
|
||||
if ( !u_type ) {
|
||||
|
@ -102,7 +102,7 @@ undo_action_base * undo_list::create_action(const config & cfg)
|
|||
res = new undo::recall_action(cfg, map_location(cfg.child_or_empty("leader"), nullptr));
|
||||
|
||||
else if ( str == "dismiss" )
|
||||
res = new undo::dismiss_action(cfg, cfg.child("unit"));
|
||||
res = new undo::dismiss_action(cfg, cfg.mandatory_child("unit"));
|
||||
|
||||
else if ( str == "auto_shroud" )
|
||||
res = new undo::auto_shroud_action(cfg["active"].to_bool());
|
||||
|
@ -403,8 +403,7 @@ void undo_list::redo()
|
|||
auto action = std::move(redos_.back());
|
||||
redos_.pop_back();
|
||||
|
||||
|
||||
auto [commandname, data] = action->child("command").all_children_range().front();
|
||||
auto [commandname, data] = action->mandatory_child("command").all_children_range().front();
|
||||
|
||||
// Note that this might add more than one [command]
|
||||
resources::recorder->redo(*action);
|
||||
|
|
|
@ -111,8 +111,8 @@ namespace {
|
|||
u2.reset(new scoped_xy_unit("unit", who->get_location(), resources::gameboard->units()));
|
||||
}
|
||||
|
||||
scoped_weapon_info w1("weapon", e.data.child("first"));
|
||||
scoped_weapon_info w2("second_weapon", e.data.child("second"));
|
||||
scoped_weapon_info w1("weapon", e.data.optional_child("first"));
|
||||
scoped_weapon_info w2("second_weapon", e.data.optional_child("second"));
|
||||
|
||||
game_events::queued_event q(tag, "", map_location(x1, y1, wml_loc()), map_location(x2, y2, wml_loc()), e.data);
|
||||
resources::lua_kernel->run_wml_action("command", vconfig(e.commands), q);
|
||||
|
|
|
@ -56,7 +56,7 @@ void move_action::write(config & cfg) const
|
|||
shroud_clearing_action::write(cfg);
|
||||
cfg["starting_direction"] = map_location::write_direction(starting_dir);
|
||||
cfg["starting_moves"] = starting_moves;
|
||||
config & child = cfg.child("unit");
|
||||
config & child = cfg.mandatory_child("unit");
|
||||
child["goto_x"] = goto_hex.wml_x();
|
||||
child["goto_y"] = goto_hex.wml_y();
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ void recruit_action::write(config & cfg) const
|
|||
shroud_clearing_action::write(cfg);
|
||||
|
||||
recruit_from.write(cfg.add_child("leader"));
|
||||
config & child = cfg.child("unit");
|
||||
config & child = cfg.mandatory_child("unit");
|
||||
child["type"] = u_type.parent_id();
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ void addons_client::connect()
|
|||
wait_for_transfer_done(msg);
|
||||
|
||||
if(!update_last_error(response_buf)) {
|
||||
if(const auto& info = response_buf.child("server_id")) {
|
||||
if(auto info = response_buf.optional_child("server_id")) {
|
||||
server_id_ = info["id"].str();
|
||||
server_version_ = info["version"].str();
|
||||
|
||||
|
@ -127,7 +127,7 @@ bool addons_client::request_addons_list(config& cfg)
|
|||
send_simple_request("request_campaign_list", response_buf);
|
||||
wait_for_transfer_done(_("Downloading list of add-ons..."));
|
||||
|
||||
std::swap(cfg, response_buf.child("campaigns"));
|
||||
std::swap(cfg, response_buf.mandatory_child("campaigns"));
|
||||
|
||||
return !update_last_error(response_buf);
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ bool addons_client::request_distribution_terms(std::string& terms)
|
|||
send_simple_request("request_terms", response_buf);
|
||||
wait_for_transfer_done(_("Requesting distribution terms..."));
|
||||
|
||||
if(const config& msg_cfg = response_buf.child("message")) {
|
||||
if(auto msg_cfg = response_buf.optional_child("message")) {
|
||||
terms = msg_cfg["message"].str();
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ bool addons_client::upload_addon(const std::string& id, std::string& response_me
|
|||
wait_for_transfer_done(_("Requesting file index..."));
|
||||
|
||||
// A silent error check
|
||||
if(!hashlist.child("error")) {
|
||||
if(!hashlist.has_child("error")) {
|
||||
if(!contains_hashlist(addon_data, hashlist) || !contains_hashlist(hashlist, addon_data)) {
|
||||
LOG_ADDONS << "making an update pack for the add-on " << id;
|
||||
config updatepack;
|
||||
|
@ -240,7 +240,7 @@ bool addons_client::upload_addon(const std::string& id, std::string& response_me
|
|||
wait_for_transfer_done(VGETTEXT("Sending an update pack for the add-on <i>$addon_title</i>...", i18n_symbols
|
||||
), transfer_mode::upload);
|
||||
|
||||
if(const config& message_cfg = response_buf.child("message")) {
|
||||
if(auto message_cfg = response_buf.optional_child("message")) {
|
||||
response_message = message_cfg["message"].str();
|
||||
LOG_ADDONS << "server response: " << response_message;
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ bool addons_client::upload_addon(const std::string& id, std::string& response_me
|
|||
wait_for_transfer_done(VGETTEXT("Sending add-on <i>$addon_title</i>...", i18n_symbols
|
||||
), transfer_mode::upload);
|
||||
|
||||
if(const config& message_cfg = response_buf.child("message")) {
|
||||
if(auto message_cfg = response_buf.optional_child("message")) {
|
||||
response_message = message_cfg["message"].str();
|
||||
LOG_ADDONS << "server response: " << response_message;
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ bool addons_client::delete_remote_addon(const std::string& id, std::string& resp
|
|||
send_request(request_buf, response_buf);
|
||||
wait_for_transfer_done(VGETTEXT("Removing add-on <i>$addon_title</i> from the server...", i18n_symbols));
|
||||
|
||||
if(const config& message_cfg = response_buf.child("message")) {
|
||||
if(auto message_cfg = response_buf.optional_child("message")) {
|
||||
response_message = message_cfg["message"].str();
|
||||
LOG_ADDONS << "server response: " << response_message;
|
||||
}
|
||||
|
@ -599,15 +599,15 @@ addons_client::install_result addons_client::install_addon_with_checks(const add
|
|||
|
||||
bool addons_client::update_last_error(config& response_cfg)
|
||||
{
|
||||
if(const config& error = response_cfg.child("error")) {
|
||||
if(error.has_attribute("status_code")) {
|
||||
if(auto error = response_cfg.optional_child("error")) {
|
||||
if(error->has_attribute("status_code")) {
|
||||
const auto& status_msg = translated_addon_check_status(error["status_code"].to_unsigned());
|
||||
last_error_ = font::escape_text(status_msg);
|
||||
} else {
|
||||
last_error_ = font::escape_text(error["message"].str());
|
||||
}
|
||||
last_error_data_ = font::escape_text(error["extra_data"].str());
|
||||
ERR_ADDONS << "server error: " << error;
|
||||
ERR_ADDONS << "server error: " << *error;
|
||||
return true;
|
||||
} else {
|
||||
last_error_.clear();
|
||||
|
|
|
@ -113,8 +113,8 @@ void get_addon_install_info(const std::string& addon_name, config& cfg)
|
|||
cfg.clear();
|
||||
config envelope;
|
||||
read(envelope, *stream);
|
||||
if(config& info = envelope.child("info")) {
|
||||
cfg = std::move(info);
|
||||
if(auto info = envelope.optional_child("info")) {
|
||||
cfg = std::move(*info);
|
||||
}
|
||||
} catch(const config::error& e) {
|
||||
ERR_CFG << "Failed to read add-on installation information for '"
|
||||
|
|
|
@ -57,10 +57,6 @@ bool get_addons_list(addons_client& client, addons_list& list)
|
|||
config cfg;
|
||||
client.request_addons_list(cfg);
|
||||
|
||||
if(!cfg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
read_addons_list(cfg, list);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -301,9 +301,9 @@ bool contains_hashlist(const config& from, const config& to)
|
|||
}
|
||||
|
||||
for(const config& d : to.child_range("dir")) {
|
||||
const config& origin_dir = from.find_child("dir", "name", d["name"]);
|
||||
auto origin_dir = from.find_child("dir", "name", d["name"]);
|
||||
if(origin_dir) {
|
||||
if(!contains_hashlist(origin_dir, d)) {
|
||||
if(!contains_hashlist(*origin_dir, d)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
@ -343,10 +343,10 @@ static bool write_difference(config& pack, const config& from, const config& to,
|
|||
}
|
||||
|
||||
for(const config& d : to.child_range("dir")) {
|
||||
const config& origin_dir = from.find_child("dir", "name", d["name"]);
|
||||
auto origin_dir = from.find_child("dir", "name", d["name"]);
|
||||
config dir;
|
||||
if(origin_dir) {
|
||||
if(write_difference(dir, origin_dir, d, with_content)) {
|
||||
if(write_difference(dir, *origin_dir, d, with_content)) {
|
||||
pack.add_child("dir", dir);
|
||||
has_changes = true;
|
||||
}
|
||||
|
|
|
@ -250,8 +250,9 @@ public:
|
|||
add_facet(-1,cfg_element);
|
||||
}
|
||||
|
||||
config _default = this->cfg_.child("default");
|
||||
if (_default) {
|
||||
config _default = this->cfg_.mandatory_child("default");
|
||||
// TODO: this was a faulty invalid config test.
|
||||
if ((true)) {
|
||||
_default["id"] = "default_facet";
|
||||
std::vector< aspect_ptr > default_aspects;
|
||||
engine::parse_aspect_from_config(*this,_default,parent_id_,std::back_inserter(default_aspects));
|
||||
|
|
|
@ -185,11 +185,11 @@ bool component_manager::add_component(component *root, const std::string &path,
|
|||
if (c==nullptr) {
|
||||
return false;
|
||||
}
|
||||
const config &ch = cfg.child(tail.property);
|
||||
auto ch = cfg.optional_child(tail.property);
|
||||
if (!ch) {
|
||||
return false;
|
||||
}
|
||||
return c->add_child(tail, ch);
|
||||
return c->add_child(tail, *ch);
|
||||
|
||||
}
|
||||
|
||||
|
@ -200,11 +200,11 @@ bool component_manager::change_component(component *root, const std::string &pat
|
|||
if (c==nullptr) {
|
||||
return false;
|
||||
}
|
||||
const config &ch = cfg.child(tail.property);
|
||||
auto ch = cfg.optional_child(tail.property);
|
||||
if (!ch) {
|
||||
return false;
|
||||
}
|
||||
return c->change_child(tail,ch);
|
||||
return c->change_child(tail, *ch);
|
||||
}
|
||||
|
||||
bool component_manager::delete_component(component *root, const std::string &path)
|
||||
|
|
|
@ -130,11 +130,11 @@ void target_unit_goal::add_targets(std::back_insert_iterator< std::vector< targe
|
|||
return;
|
||||
}
|
||||
|
||||
const config &criteria = cfg_.child("criteria");
|
||||
auto criteria = cfg_.optional_child("criteria");
|
||||
if (!criteria) return;
|
||||
|
||||
//find the enemy leaders and explicit targets
|
||||
const unit_filter ufilt{ vconfig(criteria) };
|
||||
const unit_filter ufilt{ vconfig(*criteria) };
|
||||
for (const unit &u : resources::gameboard->units()) {
|
||||
if (ufilt( u )) {
|
||||
LOG_AI_GOAL << "found explicit target unit at ... " << u.get_location() << " with value: " << value();
|
||||
|
@ -161,9 +161,9 @@ void target_location_goal::on_create()
|
|||
if (cfg_.has_attribute("value")) {
|
||||
value_ = cfg_["value"].to_double(0);
|
||||
}
|
||||
const config &criteria = cfg_.child("criteria");
|
||||
auto criteria = cfg_.optional_child("criteria");
|
||||
if (criteria) {
|
||||
filter_ptr_.reset(new terrain_filter(vconfig(criteria),resources::filter_con, false));
|
||||
filter_ptr_.reset(new terrain_filter(vconfig(*criteria),resources::filter_con, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,9 +210,9 @@ void protect_goal::on_create()
|
|||
if (radius_<1) {
|
||||
radius_=20;
|
||||
}
|
||||
const config &criteria = cfg_.child("criteria");
|
||||
auto criteria = cfg_.optional_child("criteria");
|
||||
if (criteria) {
|
||||
filter_ptr_.reset(new terrain_filter(vconfig(criteria), resources::filter_con, false));
|
||||
filter_ptr_.reset(new terrain_filter(vconfig(*criteria), resources::filter_con, false));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -231,19 +231,19 @@ void protect_goal::add_targets(std::back_insert_iterator< std::vector< target >>
|
|||
return;
|
||||
}
|
||||
|
||||
const config &criteria = cfg_.child("criteria");
|
||||
auto criteria = cfg_.optional_child("criteria");
|
||||
if (!criteria) {
|
||||
LOG_AI_GOAL << "skipping " << goal_type << " goal - no criteria given";
|
||||
return;
|
||||
} else {
|
||||
DBG_AI_GOAL << "side " << get_side() << ": "<< goal_type << " goal with criteria" << std::endl << cfg_.child("criteria");
|
||||
DBG_AI_GOAL << "side " << get_side() << ": "<< goal_type << " goal with criteria" << std::endl << cfg_.mandatory_child("criteria");
|
||||
}
|
||||
|
||||
unit_map &units = resources::gameboard->units();
|
||||
|
||||
std::set<map_location> items;
|
||||
if (protect_unit_) {
|
||||
const unit_filter ufilt{ vconfig(criteria) };
|
||||
const unit_filter ufilt{ vconfig(*criteria) };
|
||||
for (const unit &u : units)
|
||||
{
|
||||
// 'protect_unit' can be set to any unit of any side -> exclude hidden units
|
||||
|
|
|
@ -40,8 +40,8 @@ candidate_action::candidate_action(rca_context &context, const config &cfg):
|
|||
max_score_(cfg["max_score"].to_double(HIGH_SCORE)),
|
||||
id_(cfg["id"]), name_(cfg["name"]), type_(cfg["type"]), to_be_removed_(false)
|
||||
{
|
||||
if (const config &filter_own = cfg.child("filter_own")) {
|
||||
vconfig vcfg(filter_own);
|
||||
if (auto filter_own = cfg.optional_child("filter_own")) {
|
||||
vconfig vcfg(*filter_own);
|
||||
vcfg.make_safe();
|
||||
filter_own_.reset(new unit_filter(vcfg));
|
||||
}
|
||||
|
|
|
@ -192,8 +192,8 @@ public:
|
|||
|
||||
static void cfg_to_value(const config &cfg, config &value)
|
||||
{
|
||||
if (const config &v = cfg.child("value")) {
|
||||
value = v;
|
||||
if (auto v = cfg.optional_child("value")) {
|
||||
value = *v;
|
||||
} else {
|
||||
value.clear();
|
||||
}
|
||||
|
@ -223,8 +223,8 @@ public:
|
|||
|
||||
static terrain_filter cfg_to_value(const config &cfg)
|
||||
{
|
||||
if (const config &v = cfg.child("value")) {
|
||||
return terrain_filter(vconfig(v), resources::filter_con, false);
|
||||
if (auto v = cfg.optional_child("value")) {
|
||||
return terrain_filter(vconfig(*v), resources::filter_con, false);
|
||||
}
|
||||
static config c("not");
|
||||
return terrain_filter(vconfig(c),resources::filter_con, false);
|
||||
|
|
|
@ -48,9 +48,10 @@ void configuration::init(const game_config_view &game_config)
|
|||
era_ai_configurations_.clear();
|
||||
mod_ai_configurations_.clear();
|
||||
|
||||
const config &ais = game_config.child("ais");
|
||||
default_config_ = ais.child("default_config");
|
||||
if (!default_config_) {
|
||||
const config &ais = game_config.mandatory_child("ais");
|
||||
default_config_ = ais.mandatory_child("default_config");
|
||||
// TODO: this was a faulty invalid config test.
|
||||
if ((false)) {
|
||||
ERR_AI_CONFIGURATION << "Missing AI [default_config]. Therefore, default_config_ set to empty.";
|
||||
default_config_.clear();
|
||||
}
|
||||
|
@ -217,7 +218,8 @@ bool configuration::parse_side_config(side_number side, const config& original_c
|
|||
DBG_AI_CONFIGURATION << "side " << side << ": config contains:"<< std::endl << cfg;
|
||||
|
||||
//insert default config at the beginning
|
||||
if (default_config_) {
|
||||
// TODO: this was a faulty invalid config test.
|
||||
if ((true)) {
|
||||
DBG_AI_CONFIGURATION << "side "<< side <<": applying default configuration";
|
||||
cfg.add_child_at("ai",default_config_,0);
|
||||
} else {
|
||||
|
@ -246,12 +248,12 @@ bool configuration::parse_side_config(side_number side, const config& original_c
|
|||
// No point in warning about Lua or standard aspects lacking [default]
|
||||
continue;
|
||||
}
|
||||
if (!aspect_cfg.child("default")) {
|
||||
if (!aspect_cfg.has_child("default")) {
|
||||
WRN_AI_CONFIGURATION << "side "<< side <<": aspect with id=["<<aspect_cfg["id"]<<"] lacks default config facet!";
|
||||
continue;
|
||||
}
|
||||
aspect_cfg.merge_children("default");
|
||||
config& dflt = aspect_cfg.child("default");
|
||||
config& dflt = aspect_cfg.mandatory_child("default");
|
||||
if (dflt.has_child("value")) {
|
||||
while (dflt.child_count("value") > 1) {
|
||||
dflt.remove_child("value", 0);
|
||||
|
|
|
@ -53,14 +53,14 @@ aspect_attacks::aspect_attacks(readonly_context& context, const config& cfg, con
|
|||
, filter_own_()
|
||||
, filter_enemy_()
|
||||
{
|
||||
if(const config& filter_own = cfg.child("filter_own")) {
|
||||
vconfig vcfg(filter_own);
|
||||
if(auto filter_own = cfg.optional_child("filter_own")) {
|
||||
vconfig vcfg(*filter_own);
|
||||
vcfg.make_safe();
|
||||
filter_own_.reset(new unit_filter(vcfg));
|
||||
}
|
||||
|
||||
if(const config& filter_enemy = cfg.child("filter_enemy")) {
|
||||
vconfig vcfg(filter_enemy);
|
||||
if(auto filter_enemy = cfg.optional_child("filter_enemy")) {
|
||||
vconfig vcfg(*filter_enemy);
|
||||
vcfg.make_safe();
|
||||
filter_enemy_.reset(new unit_filter(vcfg));
|
||||
}
|
||||
|
|
|
@ -277,9 +277,10 @@ move_leader_to_goals_phase::~move_leader_to_goals_phase()
|
|||
double move_leader_to_goals_phase::evaluate()
|
||||
{
|
||||
|
||||
const config &goal = get_leader_goal();
|
||||
config goal = get_leader_goal();
|
||||
//passive leader can reach a goal
|
||||
if (!goal) {
|
||||
// TODO: this was a faulty invalid config test.
|
||||
if ((false)) {
|
||||
LOG_AI_TESTING_AI_DEFAULT << get_name() << "No goal found";
|
||||
return BAD_SCORE;
|
||||
}
|
||||
|
|
|
@ -1817,7 +1817,7 @@ void recruitment::recruit_situation_change_observer::reset_gamestate_changed() {
|
|||
recruitment_aspect::recruitment_aspect(readonly_context &context, const config &cfg, const std::string &id)
|
||||
: standard_aspect<config>(context, cfg, id)
|
||||
{
|
||||
config parsed_cfg(cfg.has_child("value") ? cfg.child("value") : cfg);
|
||||
config parsed_cfg(cfg.has_child("value") ? cfg.mandatory_child("value") : cfg);
|
||||
// First, transform simplified tags into [recruit] tags.
|
||||
for (config pattern : parsed_cfg.child_range("pattern")) {
|
||||
parsed_cfg["pattern"] = true;
|
||||
|
|
|
@ -755,10 +755,6 @@ bool formula_ai::gamestate_change_observer::continue_check() {
|
|||
|
||||
config formula_ai::to_config() const
|
||||
{
|
||||
if (!cfg_)
|
||||
{
|
||||
return config();
|
||||
}
|
||||
DBG_AI << "formula_ai::to_config(): "<< cfg_;
|
||||
config cfg = cfg_;
|
||||
|
||||
|
|
|
@ -62,10 +62,10 @@ candidate_action_with_filters::candidate_action_with_filters(
|
|||
: base_candidate_action(name, type, cfg, function_table)
|
||||
, filter_map_()
|
||||
{
|
||||
const config & filter_params = cfg.child("filter");
|
||||
auto filter_params = cfg.optional_child("filter");
|
||||
|
||||
if( filter_params ) {
|
||||
for(const config::attribute& filter_param : filter_params.attribute_range())
|
||||
for(const config::attribute& filter_param : filter_params->attribute_range())
|
||||
{
|
||||
const_formula_ptr filter_formula(
|
||||
new formula(filter_param.second, function_table));
|
||||
|
|
|
@ -91,9 +91,7 @@ void engine_fai::do_parse_candidate_action_from_config( rca_context &context, co
|
|||
|
||||
void engine_fai::do_parse_stage_from_config( ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr >> b )
|
||||
{
|
||||
if (!cfg) {
|
||||
return;
|
||||
}
|
||||
// This checekd for !cfg but oter implementation of do_parse_stage_from_config didn't.
|
||||
const std::string &name = cfg["name"];
|
||||
stage_ptr st_ptr;
|
||||
|
||||
|
|
|
@ -303,11 +303,8 @@ void engine_lua::push_ai_table()
|
|||
}
|
||||
}
|
||||
|
||||
void engine_lua::do_parse_candidate_action_from_config( rca_context &context, const config &cfg, std::back_insert_iterator<std::vector< candidate_action_ptr > > b ){
|
||||
if (!cfg) {
|
||||
return;
|
||||
}
|
||||
|
||||
void engine_lua::do_parse_candidate_action_from_config( rca_context &context, const config &cfg, std::back_insert_iterator<std::vector< candidate_action_ptr > > b )
|
||||
{
|
||||
if (!lua_ai_context_) {
|
||||
return;
|
||||
}
|
||||
|
@ -333,10 +330,6 @@ void engine_lua::do_parse_candidate_action_from_config( rca_context &context, co
|
|||
|
||||
void engine_lua::do_parse_stage_from_config( ai_context &context, const config &cfg, std::back_insert_iterator<std::vector< stage_ptr > > b )
|
||||
{
|
||||
if (!cfg) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lua_ai_context_) {
|
||||
return;
|
||||
}
|
||||
|
|
255
src/config.cpp
255
src/config.cpp
|
@ -71,62 +71,10 @@ int map_erase_key(Map& map, Key&& key)
|
|||
|
||||
}
|
||||
|
||||
struct config_implementation
|
||||
{
|
||||
/**
|
||||
* Implementation for the wrappers for
|
||||
* [const] config& child(const std::string& key, const std::string& parent);
|
||||
*
|
||||
* @tparam T A pointer to the config.
|
||||
*/
|
||||
template<class T>
|
||||
static utils::const_clone_ref<config, T> child(T config, config_key_type key, const std::string& parent)
|
||||
{
|
||||
config->check_valid();
|
||||
|
||||
assert(!parent.empty());
|
||||
assert(parent.front() == '[');
|
||||
assert(parent.back() == ']');
|
||||
|
||||
if(config->has_child(key)) {
|
||||
return *(config->children_.find(key)->second.front());
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Implement a proper wml_exception here.
|
||||
*
|
||||
* at the moment there seem to be dependency issues, which i don't want
|
||||
* to fix right now.
|
||||
*/
|
||||
// FAIL(missing_mandatory_wml_section(parent, key));
|
||||
|
||||
std::stringstream sstr;
|
||||
sstr << "Mandatory WML child »[" << key << "]« missing in »" << parent << "«. Please report this bug.";
|
||||
|
||||
throw config::error(sstr.str());
|
||||
}
|
||||
};
|
||||
|
||||
/* ** config implementation ** */
|
||||
|
||||
config config::invalid;
|
||||
|
||||
const char* config::diff_track_attribute = "__diff_track";
|
||||
|
||||
void config::check_valid() const
|
||||
{
|
||||
if(!*this) {
|
||||
throw error("Mandatory WML child missing yet untested for. Please report.");
|
||||
}
|
||||
}
|
||||
|
||||
void config::check_valid(const config& cfg) const
|
||||
{
|
||||
if(!*this || !cfg) {
|
||||
throw error("Mandatory WML child missing yet untested for. Please report.");
|
||||
}
|
||||
}
|
||||
|
||||
config::config()
|
||||
: values_()
|
||||
, children_()
|
||||
|
@ -210,20 +158,16 @@ bool config::valid_attribute(config_key_type name)
|
|||
|
||||
bool config::has_attribute(config_key_type key) const
|
||||
{
|
||||
check_valid();
|
||||
return values_.find(key) != values_.end();
|
||||
}
|
||||
|
||||
void config::remove_attribute(config_key_type key)
|
||||
{
|
||||
check_valid();
|
||||
map_erase_key(values_, key);
|
||||
}
|
||||
|
||||
void config::append_children(const config& cfg)
|
||||
{
|
||||
check_valid(cfg);
|
||||
|
||||
for(const any_child value : cfg.all_children_range()) {
|
||||
add_child(value.key, value.cfg);
|
||||
}
|
||||
|
@ -231,8 +175,6 @@ void config::append_children(const config& cfg)
|
|||
|
||||
void config::append_children(config&& cfg)
|
||||
{
|
||||
check_valid(cfg);
|
||||
|
||||
#if 0
|
||||
//For some unknown reason this doesn't compile.
|
||||
if(children_.empty()) {
|
||||
|
@ -251,7 +193,6 @@ void config::append_children(config&& cfg)
|
|||
|
||||
void config::append_attributes(const config& cfg)
|
||||
{
|
||||
check_valid(cfg);
|
||||
for(const attribute& v : cfg.values_) {
|
||||
values_[v.first] = v.second;
|
||||
}
|
||||
|
@ -259,8 +200,6 @@ void config::append_attributes(const config& cfg)
|
|||
|
||||
void config::append_children(const config& cfg, const std::string& key)
|
||||
{
|
||||
check_valid(cfg);
|
||||
|
||||
for(const config& value : cfg.child_range(key)) {
|
||||
add_child(key, value);
|
||||
}
|
||||
|
@ -293,8 +232,6 @@ void config::append(config&& cfg)
|
|||
|
||||
void config::append_children_by_move(config& cfg, const std::string& key)
|
||||
{
|
||||
check_valid(cfg);
|
||||
|
||||
// DO note this leaves the tags empty in the source config. Not sure if
|
||||
// that should be changed.
|
||||
for(config& value : cfg.child_range(key)) {
|
||||
|
@ -306,8 +243,6 @@ void config::append_children_by_move(config& cfg, const std::string& key)
|
|||
|
||||
void config::merge_children(const std::string& key)
|
||||
{
|
||||
check_valid();
|
||||
|
||||
if(child_count(key) < 2) {
|
||||
return;
|
||||
}
|
||||
|
@ -323,8 +258,6 @@ void config::merge_children(const std::string& key)
|
|||
|
||||
void config::merge_children_by_attribute(const std::string& key, const std::string& attribute)
|
||||
{
|
||||
check_valid();
|
||||
|
||||
if(child_count(key) < 2) {
|
||||
return;
|
||||
}
|
||||
|
@ -343,8 +276,6 @@ void config::merge_children_by_attribute(const std::string& key, const std::stri
|
|||
|
||||
config::child_itors config::child_range(config_key_type key)
|
||||
{
|
||||
check_valid();
|
||||
|
||||
child_map::iterator i = children_.find(key);
|
||||
static child_list dummy;
|
||||
child_list* p = &dummy;
|
||||
|
@ -357,8 +288,6 @@ config::child_itors config::child_range(config_key_type key)
|
|||
|
||||
config::const_child_itors config::child_range(config_key_type key) const
|
||||
{
|
||||
check_valid();
|
||||
|
||||
child_map::const_iterator i = children_.find(key);
|
||||
static child_list dummy;
|
||||
const child_list* p = &dummy;
|
||||
|
@ -371,8 +300,6 @@ config::const_child_itors config::child_range(config_key_type key) const
|
|||
|
||||
unsigned config::child_count(config_key_type key) const
|
||||
{
|
||||
check_valid();
|
||||
|
||||
child_map::const_iterator i = children_.find(key);
|
||||
if(i != children_.end()) {
|
||||
return i->second.size();
|
||||
|
@ -393,25 +320,19 @@ unsigned config::attribute_count() const
|
|||
|
||||
bool config::has_child(config_key_type key) const
|
||||
{
|
||||
check_valid();
|
||||
|
||||
child_map::const_iterator i = children_.find(key);
|
||||
return i != children_.end() && !i->second.empty();
|
||||
}
|
||||
|
||||
config& config::child(config_key_type key, int n)
|
||||
namespace {
|
||||
template<class Tchildren>
|
||||
auto get_child_impl(Tchildren& children, config_key_type key, int n) -> optional_config_impl<std::remove_reference_t<decltype(**(*children.begin()).second.begin())>>
|
||||
{
|
||||
check_valid();
|
||||
|
||||
const child_map::const_iterator i = children_.find(key);
|
||||
if(i == children_.end()) {
|
||||
auto i = children.find(key);
|
||||
if(i == children.end()) {
|
||||
DBG_CF << "The config object has no child named »" << key << "«.";
|
||||
|
||||
if(throw_when_child_not_found::do_throw()) {
|
||||
throw error("Child not found");
|
||||
} else {
|
||||
return invalid;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if(n < 0) {
|
||||
|
@ -423,50 +344,61 @@ config& config::child(config_key_type key, int n)
|
|||
} catch(const std::out_of_range&) {
|
||||
DBG_CF << "The config object has only »" << i->second.size() << "« children named »" << key
|
||||
<< "«; request for the index »" << n << "« cannot be honored.";
|
||||
|
||||
if(throw_when_child_not_found::do_throw()) {
|
||||
throw error("Child at index not found");
|
||||
} else {
|
||||
return invalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config& config::child(config_key_type key, const std::string& parent)
|
||||
{
|
||||
return config_implementation::child(this, key, parent);
|
||||
}
|
||||
|
||||
const config& config::child(config_key_type key, const std::string& parent) const
|
||||
{
|
||||
return config_implementation::child(this, key, parent);
|
||||
}
|
||||
|
||||
utils::optional_reference<config> config::optional_child(config_key_type key, int n)
|
||||
{
|
||||
try {
|
||||
throw_when_child_not_found raii_helper{};
|
||||
return child(key, n);
|
||||
} catch(const error&) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
utils::optional_reference<const config> config::optional_child(config_key_type key, int n) const
|
||||
}
|
||||
|
||||
config& config::mandatory_child(config_key_type key, const std::string& parent)
|
||||
{
|
||||
try {
|
||||
throw_when_child_not_found raii_helper{};
|
||||
return child(key, n);
|
||||
} catch(const error&) {
|
||||
return std::nullopt;
|
||||
if(auto res = get_child_impl(children_, key, 0)) {
|
||||
return *res;
|
||||
} else {
|
||||
throw error("Mandatory WML child »[" + std::string(key) + "]« missing in »" + parent + "«. Please report this bug.");
|
||||
}
|
||||
}
|
||||
|
||||
const config& config::mandatory_child(config_key_type key, const std::string& parent) const
|
||||
{
|
||||
if(auto res = get_child_impl(children_, key, 0)) {
|
||||
return *res;
|
||||
} else {
|
||||
throw error("Mandatory WML child »[" + std::string(key) + "]« missing in »" + parent + "«. Please report this bug.");
|
||||
}
|
||||
}
|
||||
|
||||
config& config::mandatory_child(config_key_type key, int n)
|
||||
{
|
||||
if(auto res = get_child_impl(children_, key, n)) {
|
||||
return *res;
|
||||
} else {
|
||||
throw error("Child [" + std::string(key) + "] at index " + std::to_string(n) + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
const config& config::mandatory_child(config_key_type key, int n) const
|
||||
{
|
||||
if(auto res = get_child_impl(children_, key, n)) {
|
||||
return *res;
|
||||
} else {
|
||||
throw error("Child [" + std::string(key) + "] at index " + std::to_string(n) + " not found");
|
||||
}
|
||||
}
|
||||
|
||||
optional_config config::optional_child(config_key_type key, int n)
|
||||
{
|
||||
return get_child_impl(children_, key, n);
|
||||
}
|
||||
|
||||
optional_const_config config::optional_child(config_key_type key, int n) const
|
||||
{
|
||||
return get_child_impl(children_, key, n);
|
||||
}
|
||||
|
||||
const config& config::child_or_empty(config_key_type key) const
|
||||
{
|
||||
static const config empty_cfg;
|
||||
check_valid();
|
||||
|
||||
child_map::const_iterator i = children_.find(key);
|
||||
if(i != children_.end() && !i->second.empty()) {
|
||||
return *i->second.front();
|
||||
|
@ -485,20 +417,19 @@ config& config::child_or_add(config_key_type key)
|
|||
return add_child(key);
|
||||
}
|
||||
|
||||
utils::optional_reference<const config> config::get_deprecated_child(config_key_type old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const {
|
||||
check_valid();
|
||||
|
||||
if(auto i = children_.find(old_key); i != children_.end() && !i->second.empty()) {
|
||||
optional_config_impl<const config> config::get_deprecated_child(config_key_type old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const
|
||||
{
|
||||
if(auto res = optional_child(old_key)) {
|
||||
const std::string what = formatter() << "[" << in_tag << "][" << old_key << "]";
|
||||
deprecated_message(what, level, "", message);
|
||||
return *i->second.front();
|
||||
return res;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
config::const_child_itors config::get_deprecated_child_range(config_key_type old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const {
|
||||
check_valid();
|
||||
config::const_child_itors config::get_deprecated_child_range(config_key_type old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const
|
||||
{
|
||||
static child_list dummy;
|
||||
const child_list* p = &dummy;
|
||||
|
||||
|
@ -513,8 +444,6 @@ config::const_child_itors config::get_deprecated_child_range(config_key_type old
|
|||
|
||||
config& config::add_child(config_key_type key)
|
||||
{
|
||||
check_valid();
|
||||
|
||||
child_list& v = map_get(children_, key);
|
||||
v.emplace_back(new config());
|
||||
ordered_children.emplace_back(children_.find(key), v.size() - 1);
|
||||
|
@ -523,8 +452,6 @@ config& config::add_child(config_key_type key)
|
|||
|
||||
config& config::add_child(config_key_type key, const config& val)
|
||||
{
|
||||
check_valid(val);
|
||||
|
||||
child_list& v = map_get(children_, key);
|
||||
v.emplace_back(new config(val));
|
||||
ordered_children.emplace_back(children_.find(key), v.size() - 1);
|
||||
|
@ -534,8 +461,6 @@ config& config::add_child(config_key_type key, const config& val)
|
|||
|
||||
config& config::add_child(config_key_type key, config&& val)
|
||||
{
|
||||
check_valid(val);
|
||||
|
||||
child_list& v = map_get(children_, key);
|
||||
v.emplace_back(new config(std::move(val)));
|
||||
ordered_children.emplace_back(children_.find(key), v.size() - 1);
|
||||
|
@ -545,8 +470,6 @@ config& config::add_child(config_key_type key, config&& val)
|
|||
|
||||
config& config::add_child_at(config_key_type key, const config& val, unsigned index)
|
||||
{
|
||||
check_valid(val);
|
||||
|
||||
child_list& v = map_get(children_, key);
|
||||
if(index > v.size()) {
|
||||
throw error("illegal index to add child at");
|
||||
|
@ -648,8 +571,6 @@ private:
|
|||
|
||||
void config::clear_children_impl(config_key_type key)
|
||||
{
|
||||
check_valid();
|
||||
|
||||
child_map::iterator i = children_.find(key);
|
||||
if(i == children_.end())
|
||||
return;
|
||||
|
@ -663,8 +584,6 @@ void config::clear_children_impl(config_key_type key)
|
|||
|
||||
void config::splice_children(config& src, const std::string& key)
|
||||
{
|
||||
check_valid(src);
|
||||
|
||||
child_map::iterator i_src = src.children_.find(key);
|
||||
if(i_src == src.children_.end()) {
|
||||
return;
|
||||
|
@ -689,8 +608,6 @@ void config::splice_children(config& src, const std::string& key)
|
|||
|
||||
void config::recursive_clear_value(config_key_type key)
|
||||
{
|
||||
check_valid();
|
||||
|
||||
map_erase_key(values_, key);
|
||||
|
||||
for(std::pair<const std::string, child_list>& p : children_) {
|
||||
|
@ -731,8 +648,6 @@ config::all_children_iterator config::erase(const config::all_children_iterator&
|
|||
|
||||
void config::remove_child(config_key_type key, unsigned index)
|
||||
{
|
||||
check_valid();
|
||||
|
||||
child_map::iterator i = children_.find(key);
|
||||
if(i == children_.end() || index >= i->second.size()) {
|
||||
ERR_CF << "Error: attempting to delete non-existing child: " << key << "[" << index << "]";
|
||||
|
@ -744,8 +659,6 @@ void config::remove_child(config_key_type key, unsigned index)
|
|||
|
||||
void config::remove_children(config_key_type key, std::function<bool(const config&)> p)
|
||||
{
|
||||
check_valid();
|
||||
|
||||
child_map::iterator pos = children_.find(key);
|
||||
if(pos == children_.end()) {
|
||||
return;
|
||||
|
@ -766,8 +679,6 @@ void config::remove_children(config_key_type key, std::function<bool(const confi
|
|||
|
||||
const config::attribute_value& config::operator[](config_key_type key) const
|
||||
{
|
||||
check_valid();
|
||||
|
||||
const attribute_map::const_iterator i = values_.find(key);
|
||||
if(i != values_.end()) {
|
||||
return i->second;
|
||||
|
@ -779,15 +690,12 @@ const config::attribute_value& config::operator[](config_key_type key) const
|
|||
|
||||
const config::attribute_value* config::get(config_key_type key) const
|
||||
{
|
||||
check_valid();
|
||||
attribute_map::const_iterator i = values_.find(key);
|
||||
return i != values_.end() ? &i->second : nullptr;
|
||||
}
|
||||
|
||||
config::attribute_value& config::operator[](config_key_type key)
|
||||
{
|
||||
check_valid();
|
||||
|
||||
auto res = values_.lower_bound(key);
|
||||
|
||||
if(res == values_.end() || key != res->first) {
|
||||
|
@ -799,8 +707,6 @@ config::attribute_value& config::operator[](config_key_type key)
|
|||
|
||||
const config::attribute_value& config::get_old_attribute(config_key_type key, const std::string& old_key, const std::string& in_tag, const std::string& message) const
|
||||
{
|
||||
check_valid();
|
||||
|
||||
if(has_attribute(old_key)) {
|
||||
const std::string what = formatter() << "[" << in_tag << "]" << old_key << "=";
|
||||
const std::string msg = formatter() << "Use " << key << "= instead. " << message;
|
||||
|
@ -821,9 +727,8 @@ const config::attribute_value& config::get_old_attribute(config_key_type key, co
|
|||
return empty_attribute;
|
||||
}
|
||||
|
||||
const config::attribute_value& config::get_deprecated_attribute(config_key_type old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const {
|
||||
check_valid();
|
||||
|
||||
const config::attribute_value& config::get_deprecated_attribute(config_key_type old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const
|
||||
{
|
||||
if(auto i = values_.find(old_key); i != values_.end()) {
|
||||
const std::string what = formatter() << "[" << in_tag << "]" << old_key << "=";
|
||||
deprecated_message(what, level, "", message);
|
||||
|
@ -836,8 +741,6 @@ const config::attribute_value& config::get_deprecated_attribute(config_key_type
|
|||
|
||||
void config::merge_attributes(const config& cfg)
|
||||
{
|
||||
check_valid(cfg);
|
||||
|
||||
assert(this != &cfg);
|
||||
for(const attribute& v : cfg.values_) {
|
||||
std::string key = v.first;
|
||||
|
@ -857,8 +760,6 @@ void config::merge_attributes(const config& cfg)
|
|||
|
||||
config::const_attr_itors config::attribute_range() const
|
||||
{
|
||||
check_valid();
|
||||
|
||||
const_attr_itors range(const_attribute_iterator(values_.begin()), const_attribute_iterator(values_.end()));
|
||||
|
||||
// Ensure the first element is not blank, as a few places assume this
|
||||
|
@ -871,7 +772,6 @@ config::const_attr_itors config::attribute_range() const
|
|||
|
||||
config::attr_itors config::attribute_range()
|
||||
{
|
||||
check_valid();
|
||||
attr_itors range(attribute_iterator(values_.begin()), attribute_iterator(values_.end()));
|
||||
|
||||
// Ensure the first element is not blank, as a few places assume this
|
||||
|
@ -882,19 +782,14 @@ config::attr_itors config::attribute_range()
|
|||
return range;
|
||||
}
|
||||
|
||||
config& config::find_child(config_key_type key, const std::string& name, const std::string& value)
|
||||
optional_config config::find_child(config_key_type key, const std::string& name, const std::string& value)
|
||||
{
|
||||
check_valid();
|
||||
|
||||
const child_map::iterator i = children_.find(key);
|
||||
if(i == children_.end()) {
|
||||
DBG_CF << "Key »" << name << "« value »" << value << "« pair not found as child of key »" << key << "«.";
|
||||
|
||||
if(throw_when_child_not_found::do_throw()) {
|
||||
throw error("Child not found");
|
||||
} else {
|
||||
return invalid;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const child_list::iterator j = std::find_if(i->second.begin(), i->second.end(),
|
||||
|
@ -910,11 +805,7 @@ config& config::find_child(config_key_type key, const std::string& name, const s
|
|||
|
||||
DBG_CF << "Key »" << name << "« value »" << value << "« pair not found as child of key »" << key << "«.";
|
||||
|
||||
if(throw_when_child_not_found::do_throw()) {
|
||||
throw error("Child not found");
|
||||
} else {
|
||||
return invalid;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void config::clear()
|
||||
|
@ -940,8 +831,6 @@ void config::clear_attributes()
|
|||
|
||||
bool config::empty() const
|
||||
{
|
||||
check_valid();
|
||||
|
||||
return children_.empty() && values_.empty();
|
||||
}
|
||||
|
||||
|
@ -1003,8 +892,6 @@ config::all_children_itors config::all_children_range()
|
|||
|
||||
config config::get_diff(const config& c) const
|
||||
{
|
||||
check_valid(c);
|
||||
|
||||
config res;
|
||||
get_diff(c, res);
|
||||
return res;
|
||||
|
@ -1012,9 +899,6 @@ config config::get_diff(const config& c) const
|
|||
|
||||
void config::get_diff(const config& c, config& res) const
|
||||
{
|
||||
check_valid(c);
|
||||
check_valid(res);
|
||||
|
||||
config* inserts = nullptr;
|
||||
|
||||
for(const auto& v : values_) {
|
||||
|
@ -1124,8 +1008,6 @@ void config::get_diff(const config& c, config& res) const
|
|||
|
||||
void config::apply_diff(const config& diff, bool track /* = false */)
|
||||
{
|
||||
check_valid(diff);
|
||||
|
||||
if(track) {
|
||||
values_[diff_track_attribute] = "modified";
|
||||
}
|
||||
|
@ -1223,8 +1105,6 @@ void config::clear_diff_track(const config& diff)
|
|||
*/
|
||||
void config::merge_with(const config& c)
|
||||
{
|
||||
check_valid(c);
|
||||
|
||||
std::vector<child_pos> to_remove;
|
||||
std::map<std::string, unsigned> visitations;
|
||||
|
||||
|
@ -1288,7 +1168,6 @@ void config::inherit_from(const config& c)
|
|||
*/
|
||||
void config::inherit_attributes(const config& cfg)
|
||||
{
|
||||
check_valid(cfg);
|
||||
for(const attribute& v : cfg.values_) {
|
||||
attribute_value& v2 = values_[v.first];
|
||||
if(v2.blank()) {
|
||||
|
@ -1298,8 +1177,6 @@ void config::inherit_attributes(const config& cfg)
|
|||
}
|
||||
bool config::matches(const config& filter) const
|
||||
{
|
||||
check_valid(filter);
|
||||
|
||||
bool result = true;
|
||||
|
||||
for(const attribute& i : filter.attribute_range()) {
|
||||
|
@ -1346,8 +1223,6 @@ bool config::matches(const config& filter) const
|
|||
|
||||
std::string config::debug() const
|
||||
{
|
||||
check_valid();
|
||||
|
||||
std::ostringstream outstream;
|
||||
outstream << *this;
|
||||
return outstream.str();
|
||||
|
@ -1391,8 +1266,6 @@ std::ostream& operator<<(std::ostream& outstream, const config& cfg)
|
|||
|
||||
std::string config::hash() const
|
||||
{
|
||||
check_valid();
|
||||
|
||||
static const unsigned int hash_length = 128;
|
||||
static const char hash_string[] = "+-,.<>0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
char hash_str[hash_length + 1];
|
||||
|
@ -1446,8 +1319,6 @@ std::string config::hash() const
|
|||
|
||||
void config::swap(config& cfg)
|
||||
{
|
||||
check_valid(cfg);
|
||||
|
||||
values_.swap(cfg.values_);
|
||||
children_.swap(cfg.children_);
|
||||
ordered_children.swap(cfg.ordered_children);
|
||||
|
@ -1474,8 +1345,6 @@ bool config::validate_wml() const
|
|||
|
||||
bool operator==(const config& a, const config& b)
|
||||
{
|
||||
a.check_valid(b);
|
||||
|
||||
if(a.values_ != b.values_) {
|
||||
return false;
|
||||
}
|
||||
|
|
182
src/config.hpp
182
src/config.hpp
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "config_attribute_value.hpp"
|
||||
#include "exceptions.hpp"
|
||||
#include "utils/const_clone.hpp"
|
||||
#include "utils/optional_reference.hpp"
|
||||
|
||||
#include <climits>
|
||||
|
@ -52,6 +53,105 @@ enum class DEP_LEVEL : uint8_t;
|
|||
|
||||
class config;
|
||||
|
||||
template<class T>
|
||||
class optional_config_impl
|
||||
{
|
||||
public:
|
||||
optional_config_impl() = default;
|
||||
|
||||
optional_config_impl(T& ref)
|
||||
: opt_(&ref)
|
||||
{
|
||||
}
|
||||
|
||||
optional_config_impl(std::nullopt_t)
|
||||
: opt_()
|
||||
{
|
||||
}
|
||||
|
||||
T& value() const
|
||||
{
|
||||
if(opt_) {
|
||||
return *opt_;
|
||||
} else {
|
||||
// We're going to drop this codepath once we can use optional::value anyway, but just
|
||||
// noting we want this function to ultimately throw std::bad_optional_access.
|
||||
throw std::runtime_error("Optional reference has no value");
|
||||
}
|
||||
}
|
||||
|
||||
optional_config_impl<T>& operator=(T& new_ref)
|
||||
{
|
||||
opt_ = &new_ref;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool has_value() const
|
||||
{
|
||||
#ifdef DEBUG_CONFIG
|
||||
tested_ = true;
|
||||
#endif
|
||||
return opt_ != nullptr;
|
||||
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return has_value();
|
||||
}
|
||||
|
||||
operator optional_config_impl<const T>() const
|
||||
{
|
||||
return opt_ ? optional_config_impl<const T>(*opt_) : optional_config_impl<const T>();
|
||||
}
|
||||
|
||||
/** Returns a pointer to the referenced object or nullptr if no reference is held. */
|
||||
T* ptr() const
|
||||
{
|
||||
if(opt_) {
|
||||
return &value();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
T* operator->() const
|
||||
{
|
||||
assert(tested());
|
||||
return &value();
|
||||
}
|
||||
|
||||
T& operator*() const
|
||||
{
|
||||
assert(tested());
|
||||
return value();
|
||||
}
|
||||
|
||||
utils::const_clone_t<config_attribute_value, T>& operator[](config_key_type key)
|
||||
{
|
||||
assert(tested());
|
||||
return value()[key];
|
||||
}
|
||||
|
||||
operator utils::optional_reference<T>() const
|
||||
{
|
||||
return has_value() ? utils::optional_reference<T>(value()) : utils::optional_reference<T>();
|
||||
}
|
||||
bool tested() const
|
||||
{
|
||||
#ifdef DEBUG_CONFIG
|
||||
return tested_;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
T* opt_;
|
||||
#ifdef DEBUG_CONFIG
|
||||
mutable bool tested_;
|
||||
#endif
|
||||
};
|
||||
|
||||
bool operator==(const config &, const config &);
|
||||
inline bool operator!=(const config &a, const config &b) { return !operator==(a, b); }
|
||||
std::ostream &operator << (std::ostream &, const config &);
|
||||
|
@ -60,20 +160,6 @@ std::ostream &operator << (std::ostream &, const config &);
|
|||
class config
|
||||
{
|
||||
friend bool operator==(const config& a, const config& b);
|
||||
friend struct config_implementation;
|
||||
|
||||
static config invalid;
|
||||
|
||||
/**
|
||||
* Raises an exception if @a this is not valid.
|
||||
*/
|
||||
void check_valid() const;
|
||||
|
||||
/**
|
||||
* Raises an exception if @a this or @a cfg is not valid.
|
||||
*/
|
||||
void check_valid(const config &cfg) const;
|
||||
|
||||
public:
|
||||
// Create an empty node.
|
||||
config();
|
||||
|
@ -105,12 +191,6 @@ public:
|
|||
// Verifies that the string can be used as an attribute name
|
||||
static bool valid_attribute(config_key_type name);
|
||||
|
||||
explicit operator bool() const
|
||||
{ return this != &invalid; }
|
||||
|
||||
static config& get_invalid()
|
||||
{ return invalid; }
|
||||
|
||||
typedef std::vector<std::unique_ptr<config>> child_list;
|
||||
typedef std::map<std::string, child_list, std::less<>> child_map;
|
||||
|
||||
|
@ -302,60 +382,27 @@ public:
|
|||
*/
|
||||
const config & child_or_empty(config_key_type key) const;
|
||||
|
||||
/**
|
||||
* An object of this type will cause the following functions to throw a config::error instead
|
||||
* of returning a reference to the invalid config for the duration of its lfetime. If multiple
|
||||
* instances exist simultaneously, this behavior will persist until all objects are destroyed.
|
||||
*
|
||||
* - @c child
|
||||
* - @c find_child
|
||||
*/
|
||||
class throw_when_child_not_found
|
||||
{
|
||||
public:
|
||||
friend class config;
|
||||
|
||||
throw_when_child_not_found()
|
||||
{
|
||||
instances++;
|
||||
}
|
||||
|
||||
~throw_when_child_not_found()
|
||||
{
|
||||
instances--;
|
||||
}
|
||||
|
||||
static bool do_throw()
|
||||
{
|
||||
return instances > 0;
|
||||
}
|
||||
|
||||
private:
|
||||
static inline unsigned instances = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the nth child with the given @a key, or
|
||||
* a reference to an invalid config if there is none.
|
||||
* throws an error if there is none.
|
||||
* @note A negative @a n accesses from the end of the object.
|
||||
* For instance, -1 is the index of the last child.
|
||||
*/
|
||||
config& child(config_key_type key, int n = 0);
|
||||
|
||||
config& mandatory_child(config_key_type key, int n = 0);
|
||||
/**
|
||||
* Returns the nth child with the given @a key, or
|
||||
* a reference to an invalid config if there is none.
|
||||
* throws an error if there is none.
|
||||
* @note A negative @a n accesses from the end of the object.
|
||||
* For instance, -1 is the index of the last child.
|
||||
*/
|
||||
const config& child(config_key_type key, int n = 0) const
|
||||
{ return const_cast<config*>(this)->child(key, n); }
|
||||
const config& mandatory_child(config_key_type key, int n = 0) const;
|
||||
|
||||
/** Euivalent to @ref child, but returns an empty optional if the nth child was not found. */
|
||||
utils::optional_reference<config> optional_child(config_key_type key, int n = 0);
|
||||
/** Euivalent to @ref mandatory_child, but returns an empty optional if the nth child was not found. */
|
||||
optional_config_impl<config> optional_child(config_key_type key, int n = 0);
|
||||
|
||||
/** Euivalent to @ref child, but returns an empty optional if the nth child was not found. */
|
||||
utils::optional_reference<const config> optional_child(config_key_type key, int n = 0) const;
|
||||
/** Euivalent to @ref mandatory_child, but returns an empty optional if the nth child was not found. */
|
||||
optional_config_impl<const config> optional_child(config_key_type key, int n = 0) const;
|
||||
|
||||
/**
|
||||
* Returns a mandatory child node.
|
||||
|
@ -371,7 +418,7 @@ public:
|
|||
*
|
||||
* @returns The wanted child node.
|
||||
*/
|
||||
config& child(config_key_type key, const std::string& parent);
|
||||
config& mandatory_child(config_key_type key, const std::string& parent);
|
||||
|
||||
/**
|
||||
* Returns a mandatory child node.
|
||||
|
@ -387,7 +434,7 @@ public:
|
|||
*
|
||||
* @returns The wanted child node.
|
||||
*/
|
||||
const config& child(config_key_type key, const std::string& parent) const;
|
||||
const config& mandatory_child(config_key_type key, const std::string& parent) const;
|
||||
|
||||
/**
|
||||
* Get a deprecated child and log a deprecation message
|
||||
|
@ -397,7 +444,7 @@ public:
|
|||
* @param message An explanation of the deprecation, possibly mentioning an alternative
|
||||
* @note The deprecation message will be a level 3 deprecation.
|
||||
*/
|
||||
utils::optional_reference<const config> get_deprecated_child(config_key_type old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const;
|
||||
optional_config_impl<const config> get_deprecated_child(config_key_type old_key, const std::string& in_tag, DEP_LEVEL level, const std::string& message) const;
|
||||
|
||||
/**
|
||||
* Get a deprecated child rangw and log a deprecation message
|
||||
|
@ -569,10 +616,10 @@ public:
|
|||
* Returns the first child of tag @a key with a @a name attribute
|
||||
* containing @a value.
|
||||
*/
|
||||
config& find_child(config_key_type key, const std::string &name,
|
||||
optional_config_impl<config> find_child(config_key_type key, const std::string &name,
|
||||
const std::string &value);
|
||||
|
||||
const config& find_child(config_key_type key, const std::string &name,
|
||||
optional_config_impl<const config> find_child(config_key_type key, const std::string &name,
|
||||
const std::string &value) const
|
||||
{ return const_cast<config *>(this)->find_child(key, name, value); }
|
||||
|
||||
|
@ -870,6 +917,9 @@ private:
|
|||
std::vector<child_pos> ordered_children;
|
||||
};
|
||||
|
||||
|
||||
using optional_config = optional_config_impl<config>;
|
||||
using optional_const_config = optional_config_impl<const config>;
|
||||
/** Implement non-member swap function for std::swap (calls @ref config::swap). */
|
||||
void swap(config& lhs, config& rhs);
|
||||
|
||||
|
|
|
@ -144,8 +144,8 @@ inline std::string pretty_path(const std::string& path)
|
|||
|
||||
inline config get_bookmarks_config()
|
||||
{
|
||||
const config& cfg = preferences::get_child("dir_bookmarks");
|
||||
return cfg ? cfg : config{};
|
||||
auto cfg = preferences::get_child("dir_bookmarks");
|
||||
return cfg ? *cfg : config{};
|
||||
}
|
||||
|
||||
inline void commit_bookmarks_config(config& cfg)
|
||||
|
|
|
@ -2924,13 +2924,13 @@ void display::refresh_report(const std::string& report_name, const config * new_
|
|||
if (!str.empty()) {
|
||||
config &e = report.add_child_at("element", config(), 0);
|
||||
e["text"] = str;
|
||||
e["tooltip"] = report.child("element")["tooltip"];
|
||||
e["tooltip"] = report.mandatory_child("element")["tooltip"];
|
||||
}
|
||||
str = item->postfix();
|
||||
if (!str.empty()) {
|
||||
config &e = report.add_child("element");
|
||||
e["text"] = str;
|
||||
e["tooltip"] = report.child("element", -1)["tooltip"];
|
||||
e["tooltip"] = report.mandatory_child("element", -1)["tooltip"];
|
||||
}
|
||||
|
||||
// Do a fake run of drawing the report, so tooltips can be determined.
|
||||
|
|
|
@ -953,27 +953,27 @@ void context_manager::revert_map()
|
|||
|
||||
void context_manager::new_map(int width, int height, const t_translation::terrain_code& fill, bool new_context)
|
||||
{
|
||||
const config& default_schedule = game_config_.find_child("editor_times", "id", "empty");
|
||||
auto default_schedule = game_config_.find_child("editor_times", "id", "empty");
|
||||
editor_map m(width, height, fill);
|
||||
|
||||
if(new_context) {
|
||||
int new_id = add_map_context(m, true, default_schedule);
|
||||
int new_id = add_map_context(m, true, *default_schedule);
|
||||
switch_context(new_id);
|
||||
} else {
|
||||
replace_map_context(m, true, default_schedule);
|
||||
replace_map_context(m, true, *default_schedule);
|
||||
}
|
||||
}
|
||||
|
||||
void context_manager::new_scenario(int width, int height, const t_translation::terrain_code& fill, bool new_context)
|
||||
{
|
||||
const config& default_schedule = game_config_.find_child("editor_times", "id", "empty");
|
||||
auto default_schedule = game_config_.find_child("editor_times", "id", "empty");
|
||||
editor_map m(width, height, fill);
|
||||
|
||||
if(new_context) {
|
||||
int new_id = add_map_context(m, false, default_schedule);
|
||||
int new_id = add_map_context(m, false, *default_schedule);
|
||||
switch_context(new_id);
|
||||
} else {
|
||||
replace_map_context(m, false, default_schedule);
|
||||
replace_map_context(m, false, *default_schedule);
|
||||
}
|
||||
|
||||
// Give the new scenario an initial side.
|
||||
|
@ -1019,8 +1019,8 @@ void context_manager::create_default_context()
|
|||
t_translation::terrain_code default_terrain =
|
||||
t_translation::read_terrain_code(game_config::default_terrain);
|
||||
|
||||
const config& default_schedule = game_config_.find_child("editor_times", "id", "empty");
|
||||
add_map_context(editor_map(44, 33, default_terrain), true, default_schedule);
|
||||
auto default_schedule = game_config_.find_child("editor_times", "id", "empty");
|
||||
add_map_context(editor_map(44, 33, default_terrain), true, *default_schedule);
|
||||
} else {
|
||||
for(const std::string& filename : saved_windows_) {
|
||||
add_map_context(game_config_, filename);
|
||||
|
|
|
@ -112,7 +112,7 @@ map_context::map_context(const game_config_view& game_config, const std::string&
|
|||
, labels_(nullptr)
|
||||
, units_()
|
||||
, teams_()
|
||||
, tod_manager_(new tod_manager(game_config.find_child("editor_times", "id", "empty")))
|
||||
, tod_manager_(new tod_manager(*game_config.find_child("editor_times", "id", "empty")))
|
||||
, mp_settings_()
|
||||
, game_classification_()
|
||||
, music_tracks_()
|
||||
|
|
|
@ -103,7 +103,7 @@ bool load_font_config()
|
|||
return false;
|
||||
}
|
||||
|
||||
const config &fonts_config = cfg.child("fonts");
|
||||
auto fonts_config = cfg.optional_child("fonts");
|
||||
if (!fonts_config)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -970,12 +970,12 @@ variant event_callable::get_value(const std::string &key) const
|
|||
}
|
||||
} else if(key == "weapon") {
|
||||
if(event_info.data.has_child("first")) {
|
||||
first_weapon = std::make_shared<attack_type>(event_info.data.child("first"));
|
||||
first_weapon = std::make_shared<attack_type>(event_info.data.mandatory_child("first"));
|
||||
return variant(std::make_shared<attack_type_callable>(*first_weapon));
|
||||
}
|
||||
} else if(key == "second_weapon") {
|
||||
if(event_info.data.has_child("second")) {
|
||||
second_weapon = std::make_shared<attack_type>(event_info.data.child("second"));
|
||||
second_weapon = std::make_shared<attack_type>(event_info.data.mandatory_child("second"));
|
||||
return variant(std::make_shared<attack_type_callable>(*second_weapon));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,11 +142,11 @@ std::set<std::string> game_classification::active_addons(const std::string& scen
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if(const config& cfg = game_config_manager::get()->game_config().find_child(current.type, "id", current.id)) {
|
||||
if(auto cfg = game_config_manager::get()->game_config().find_child(current.type, "id", current.id)) {
|
||||
if(!cfg["addon_id"].empty()) {
|
||||
res.insert(cfg["addon_id"]);
|
||||
}
|
||||
for (const config& load_res : cfg.child_range("load_resource")) {
|
||||
for (const config& load_res : cfg->child_range("load_resource")) {
|
||||
mods.emplace_back("resource", load_res["id"].str());
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -306,7 +306,7 @@ void load_config(const config &v)
|
|||
default_victory_music = utils::split(v["default_victory_music"].str());
|
||||
default_defeat_music = utils::split(v["default_defeat_music"].str());
|
||||
|
||||
if(const config& i = v.child("colors")){
|
||||
if(auto i = v.optional_child("colors")){
|
||||
using namespace game_config::colors;
|
||||
|
||||
moved_orb_color = i["moved_orb_color"].str();
|
||||
|
@ -324,7 +324,7 @@ void load_config(const config &v)
|
|||
show_unmoved_orb = v["show_unmoved_orb"].to_bool(true);
|
||||
show_disengaged_orb = v["show_disengaged_orb"].to_bool(true);
|
||||
|
||||
if(const config& i = v.child("images")){
|
||||
if(auto i = v.optional_child("images")){
|
||||
using namespace game_config::images;
|
||||
|
||||
game_title = i["game_title"].str();
|
||||
|
@ -416,7 +416,7 @@ void load_config(const config &v)
|
|||
server_list.push_back(sinf);
|
||||
}
|
||||
|
||||
if(const config& s = v.child("sounds")) {
|
||||
if(auto s = v.optional_child("sounds")) {
|
||||
using namespace game_config::sounds;
|
||||
|
||||
const auto load_attribute = [](const config& c, const std::string& key, std::string& member) {
|
||||
|
@ -425,26 +425,26 @@ void load_config(const config &v)
|
|||
}
|
||||
};
|
||||
|
||||
load_attribute(s, "turn_bell", turn_bell);
|
||||
load_attribute(s, "timer_bell", timer_bell);
|
||||
load_attribute(s, "public_message", public_message);
|
||||
load_attribute(s, "private_message", private_message);
|
||||
load_attribute(s, "friend_message", friend_message);
|
||||
load_attribute(s, "server_message", server_message);
|
||||
load_attribute(s, "player_joins", player_joins);
|
||||
load_attribute(s, "player_leaves", player_leaves);
|
||||
load_attribute(s, "game_created", game_created);
|
||||
load_attribute(s, "game_user_arrive", game_user_arrive);
|
||||
load_attribute(s, "game_user_leave", game_user_leave);
|
||||
load_attribute(s, "ready_for_start", ready_for_start);
|
||||
load_attribute(s, "game_has_begun", game_has_begun);
|
||||
load_attribute(*s, "turn_bell", turn_bell);
|
||||
load_attribute(*s, "timer_bell", timer_bell);
|
||||
load_attribute(*s, "public_message", public_message);
|
||||
load_attribute(*s, "private_message", private_message);
|
||||
load_attribute(*s, "friend_message", friend_message);
|
||||
load_attribute(*s, "server_message", server_message);
|
||||
load_attribute(*s, "player_joins", player_joins);
|
||||
load_attribute(*s, "player_leaves", player_leaves);
|
||||
load_attribute(*s, "game_created", game_created);
|
||||
load_attribute(*s, "game_user_arrive", game_user_arrive);
|
||||
load_attribute(*s, "game_user_leave", game_user_leave);
|
||||
load_attribute(*s, "ready_for_start", ready_for_start);
|
||||
load_attribute(*s, "game_has_begun", game_has_begun);
|
||||
|
||||
if(const config & ss = s.child("status")) {
|
||||
if(auto ss = s->optional_child("status")) {
|
||||
using namespace game_config::sounds::status;
|
||||
|
||||
load_attribute(ss, "poisoned", poisoned);
|
||||
load_attribute(ss, "slowed", slowed);
|
||||
load_attribute(ss, "petrified", petrified);
|
||||
load_attribute(*ss, "poisoned", poisoned);
|
||||
load_attribute(*ss, "slowed", slowed);
|
||||
load_attribute(*ss, "petrified", petrified);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ bool game_config_manager::init_game_config(FORCE_RELOAD_CONFIG force_reload)
|
|||
|
||||
load_game_config_with_loadscreen(force_reload, nullptr, "");
|
||||
|
||||
game_config::load_config(game_config().child("game_config"));
|
||||
game_config::load_config(game_config().mandatory_child("game_config"));
|
||||
|
||||
// It's necessary to block the event thread while load_hotkeys() runs, otherwise keyboard input
|
||||
// can cause a crash by accessing the list of hotkeys while it's being modified.
|
||||
|
@ -250,7 +250,7 @@ void game_config_manager::load_game_config(bool reload_everything, const game_cl
|
|||
continue;
|
||||
}
|
||||
|
||||
if(*&valid_cores.find_child("core", "id", id)) {
|
||||
if(valid_cores.find_child("core", "id", id)) {
|
||||
events::call_in_main_thread([&]() {
|
||||
gui2::dialogs::wml_error::display(
|
||||
_("Error validating data core."),
|
||||
|
|
|
@ -49,27 +49,35 @@ config_array_view game_config_view::child_range(config_key_type key) const
|
|||
return res;
|
||||
}
|
||||
|
||||
const config& game_config_view::find_child(config_key_type key, const std::string &name, const std::string &value) const
|
||||
optional_const_config game_config_view::find_child(config_key_type key, const std::string &name, const std::string &value) const
|
||||
{
|
||||
for(const config& cfg : cfgs_) {
|
||||
if(const config& res = cfg.find_child(key, name, value)) {
|
||||
if(optional_const_config res = cfg.find_child(key, name, value)) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
LOG_CONFIG << "gcv : cannot find [" << key << "] with " << name << "=" << value << ", count = " << cfgs_.size();
|
||||
const config cfg;
|
||||
return cfg.child("invalid");
|
||||
return optional_const_config();
|
||||
}
|
||||
|
||||
const config& game_config_view::child(config_key_type key) const
|
||||
const config& game_config_view::mandatory_child(config_key_type key) const
|
||||
{
|
||||
for(const config& cfg : cfgs_) {
|
||||
if(const auto res = cfg.optional_child(key)) {
|
||||
return res.value();
|
||||
}
|
||||
}
|
||||
const config cfg;
|
||||
return cfg.child("invalid");
|
||||
throw config::error("missing WML tag [" + std::string(key) + "]");
|
||||
}
|
||||
|
||||
optional_const_config game_config_view::optional_child(config_key_type key) const
|
||||
{
|
||||
for(const config& cfg : cfgs_) {
|
||||
if(const auto res = cfg.optional_child(key)) {
|
||||
return res.value();
|
||||
}
|
||||
}
|
||||
return optional_const_config();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -36,9 +36,11 @@ public:
|
|||
|
||||
config_array_view child_range(config_key_type key) const;
|
||||
|
||||
const config& find_child(config_key_type key, const std::string &name, const std::string &value) const;
|
||||
optional_const_config find_child(config_key_type key, const std::string &name, const std::string &value) const;
|
||||
|
||||
const config& child(config_key_type key) const;
|
||||
// const config& child(config_key_type key) const;
|
||||
const config& mandatory_child(config_key_type key) const;
|
||||
optional_const_config optional_child(config_key_type key) const;
|
||||
|
||||
const config& child_or_empty(config_key_type key) const;
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ bool conditional_passed(const vconfig& cond)
|
|||
return matches;
|
||||
}
|
||||
|
||||
bool matches_special_filter(const config &cfg, const vconfig& filter)
|
||||
bool matches_special_filter(optional_const_config cfg, const vconfig& filter)
|
||||
{
|
||||
if (!cfg) {
|
||||
WRN_NG << "attempt to filter attack for an event with no attack data.";
|
||||
|
@ -221,7 +221,7 @@ bool matches_special_filter(const config &cfg, const vconfig& filter)
|
|||
}
|
||||
// Though it may seem wasteful to put this on the heap, it's necessary.
|
||||
// matches_filter() could potentially call a WFL formula, which would call shared_from_this().
|
||||
auto attack = std::make_shared<const attack_type>(cfg);
|
||||
auto attack = std::make_shared<const attack_type>(*cfg);
|
||||
return attack->matches_filter(filter.get_parsed_config());
|
||||
}
|
||||
|
||||
|
|
|
@ -21,14 +21,14 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
class config;
|
||||
class vconfig;
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
namespace game_events
|
||||
{
|
||||
bool conditional_passed(const vconfig& cond);
|
||||
bool matches_special_filter(const config &cfg, const vconfig& filter);
|
||||
bool matches_special_filter(optional_const_config cfg, const vconfig& filter);
|
||||
|
||||
namespace builtin_conditions {
|
||||
bool have_unit(const vconfig& cfg);
|
||||
|
|
|
@ -243,7 +243,7 @@ struct filter_attack : public event_filter {
|
|||
const auto& loc = first_ ? event_info.loc1 : event_info.loc2;
|
||||
auto unit = units.find(loc);
|
||||
if(unit != units.end() && loc.matches_unit(unit)) {
|
||||
const config& attack = event_info.data.child(first_ ? "first" : "second");
|
||||
auto attack = event_info.data.optional_child(first_ ? "first" : "second");
|
||||
return swf_.empty() || matches_special_filter(attack, swf_);
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -208,8 +208,8 @@ void wml_event_pump::process_event(handler_ptr& handler_p, const queued_event& e
|
|||
unit_map& units = resources::gameboard->units();
|
||||
scoped_xy_unit first_unit("unit", ev.loc1, units);
|
||||
scoped_xy_unit second_unit("second_unit", ev.loc2, units);
|
||||
scoped_weapon_info first_weapon("weapon", ev.data.child("first"));
|
||||
scoped_weapon_info second_weapon("second_weapon", ev.data.child("second"));
|
||||
scoped_weapon_info first_weapon("weapon", ev.data.optional_child("first"));
|
||||
scoped_weapon_info second_weapon("second_weapon", ev.data.optional_child("second"));
|
||||
|
||||
if(!handler_p->filter_event(ev)) {
|
||||
return;
|
||||
|
|
|
@ -92,8 +92,8 @@ connect_engine::connect_engine(saved_game& state, const bool first_scenario, mp_
|
|||
config::child_itors sides = current_config()->child_range("side");
|
||||
|
||||
// AI algorithms.
|
||||
if(const config& era = level_.child("era")) {
|
||||
ai::configuration::add_era_ai_from_config(era);
|
||||
if(auto era = level_.optional_child("era")) {
|
||||
ai::configuration::add_era_ai_from_config(*era);
|
||||
}
|
||||
ai::configuration::add_mod_ai_from_config(level_.child_range("modification"));
|
||||
|
||||
|
@ -174,7 +174,7 @@ connect_engine::connect_engine(saved_game& state, const bool first_scenario, mp_
|
|||
}
|
||||
|
||||
// Selected era's factions.
|
||||
for(const config& era : level_.child("era").child_range("multiplayer_side")) {
|
||||
for(const config& era : level_.mandatory_child("era").child_range("multiplayer_side")) {
|
||||
era_factions_.push_back(&era);
|
||||
}
|
||||
|
||||
|
@ -225,11 +225,7 @@ connect_engine::connect_engine(saved_game& state, const bool first_scenario, mp_
|
|||
|
||||
|
||||
config* connect_engine::current_config() {
|
||||
if(config& s = scenario()) {
|
||||
return &s;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return &scenario();
|
||||
}
|
||||
|
||||
void connect_engine::import_user(const std::string& name, const bool observer, int side_taken)
|
||||
|
@ -422,7 +418,7 @@ void connect_engine::start_game()
|
|||
|
||||
// Shuffle sides (check settings and if it is a re-loaded game).
|
||||
// Must be done after resolve_random() or shuffle sides, or they won't work.
|
||||
if(state_.mp_settings().shuffle_sides && !force_lock_settings_ && !(level_.child("snapshot") && level_.child("snapshot").child("side"))) {
|
||||
if(state_.mp_settings().shuffle_sides && !force_lock_settings_ && !(level_.has_child("snapshot") && level_.mandatory_child("snapshot").has_child("side"))) {
|
||||
|
||||
// Only playable sides should be shuffled.
|
||||
std::vector<int> playable_sides;
|
||||
|
@ -506,7 +502,7 @@ void connect_engine::start_game_commandline(const commandline_options& cmdline_o
|
|||
|
||||
// Set AI algorithm to default for all sides,
|
||||
// then override if commandline option was given.
|
||||
std::string ai_algorithm = game_config.child("ais")["default_ai_algorithm"].str();
|
||||
std::string ai_algorithm = game_config.mandatory_child("ais")["default_ai_algorithm"].str();
|
||||
side->set_ai_algorithm(ai_algorithm);
|
||||
|
||||
if(cmdline_opts.multiplayer_algorithm) {
|
||||
|
@ -578,13 +574,13 @@ std::pair<bool, bool> connect_engine::process_network_data(const config& data)
|
|||
{
|
||||
std::pair<bool, bool> result(false, true);
|
||||
|
||||
if(data.child("leave_game")) {
|
||||
if(data.has_child("leave_game")) {
|
||||
result.first = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
// A side has been dropped.
|
||||
if(const config& side_drop = data.child("side_drop")) {
|
||||
if(auto side_drop = data.optional_child("side_drop")) {
|
||||
unsigned side_index = side_drop["side_num"].to_int() - 1;
|
||||
|
||||
if(side_index < side_engines_.size()) {
|
||||
|
@ -691,20 +687,20 @@ std::pair<bool, bool> connect_engine::process_network_data(const config& data)
|
|||
}
|
||||
}
|
||||
|
||||
if(const config& change_faction = data.child("change_faction")) {
|
||||
if(auto change_faction = data.optional_child("change_faction")) {
|
||||
int side_taken = find_user_side_index_by_id(change_faction["name"]);
|
||||
if(side_taken != -1 || !first_scenario_) {
|
||||
import_user(change_faction, false, side_taken);
|
||||
import_user(*change_faction, false, side_taken);
|
||||
update_and_send_diff();
|
||||
}
|
||||
}
|
||||
|
||||
if(const config& observer = data.child("observer")) {
|
||||
import_user(observer, true);
|
||||
if(auto observer = data.optional_child("observer")) {
|
||||
import_user(*observer, true);
|
||||
update_and_send_diff();
|
||||
}
|
||||
|
||||
if(const config& observer = data.child("observer_quit")) {
|
||||
if(auto observer = data.optional_child("observer_quit")) {
|
||||
const std::string& observer_name = observer["name"];
|
||||
|
||||
if(connected_users().find(observer_name) != connected_users().end()) {
|
||||
|
@ -773,12 +769,12 @@ void connect_engine::save_reserved_sides_information()
|
|||
}
|
||||
}
|
||||
|
||||
level_.child("multiplayer")["side_users"] = utils::join_map(side_users);
|
||||
level_.mandatory_child("multiplayer")["side_users"] = utils::join_map(side_users);
|
||||
}
|
||||
|
||||
void connect_engine::load_previous_sides_users()
|
||||
{
|
||||
std::map<std::string, std::string> side_users = utils::map_split(level_.child("multiplayer")["side_users"]);
|
||||
std::map<std::string, std::string> side_users = utils::map_split(level_.mandatory_child("multiplayer")["side_users"]);
|
||||
std::set<std::string> names;
|
||||
for(side_engine_ptr side : side_engines_) {
|
||||
const std::string& save_id = side->previous_save_id();
|
||||
|
@ -942,7 +938,7 @@ side_engine::side_engine(const config& cfg, connect_engine& parent_engine, const
|
|||
}
|
||||
|
||||
// Initialize ai algorithm.
|
||||
if(const config& ai = cfg.child("ai")) {
|
||||
if(auto ai = cfg.optional_child("ai")) {
|
||||
ai_algorithm_ = ai["ai_algorithm"].str();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,10 +82,10 @@ public:
|
|||
const config& level() const { return level_; }
|
||||
config& scenario()
|
||||
{
|
||||
if(config& scenario = level_.child("scenario"))
|
||||
return scenario;
|
||||
else if(config& snapshot = level_.child("snapshot"))
|
||||
return snapshot;
|
||||
if(auto scenario = level_.optional_child("scenario"))
|
||||
return *scenario;
|
||||
else if(auto snapshot = level_.optional_child("snapshot"))
|
||||
return *snapshot;
|
||||
else
|
||||
throw "No scenariodata found";
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ random_map::random_map(const config& data)
|
|||
data_["description"] = "Error: Random map found with missing generator information. Scenario should have a [generator] child.";
|
||||
data_["error_message"] = "missing [generator] tag";
|
||||
} else {
|
||||
generator_data_ = data.child("generator");
|
||||
generator_data_ = data.mandatory_child("generator");
|
||||
}
|
||||
|
||||
if(!data.has_attribute("scenario_generation") && !data.has_attribute("map_generation")) {
|
||||
|
@ -646,8 +646,8 @@ const mp_game_settings& create_engine::get_parameters()
|
|||
|
||||
void create_engine::init_all_levels()
|
||||
{
|
||||
if(const config& generic_multiplayer = game_config_.child("generic_multiplayer")) {
|
||||
config gen_mp_data = generic_multiplayer;
|
||||
if(auto generic_multiplayer = game_config_.optional_child("generic_multiplayer")) {
|
||||
config gen_mp_data = *generic_multiplayer;
|
||||
|
||||
// User maps.
|
||||
int dep_index_offset = 0;
|
||||
|
|
|
@ -155,7 +155,7 @@ bool manager::exists(const elem& e) const
|
|||
|
||||
std::string manager::find_name_for(const elem& e) const
|
||||
{
|
||||
const config& cfg = depinfo_.find_child(e.type, "id", e.id);
|
||||
auto cfg = depinfo_.find_child(e.type, "id", e.id);
|
||||
return cfg["name"];
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ std::vector<std::string> manager::get_required(const elem& e) const
|
|||
return result;
|
||||
}
|
||||
|
||||
config data = depinfo_.find_child(e.type, "id", e.id);
|
||||
config data = *depinfo_.find_child(e.type, "id", e.id);
|
||||
|
||||
if(data.has_attribute("force_modification")) {
|
||||
result = utils::split(data["force_modification"].str(), ',');
|
||||
|
@ -230,8 +230,8 @@ bool manager::does_conflict(const elem& elem1, const elem& elem2, bool directonl
|
|||
return false;
|
||||
}
|
||||
|
||||
config data1 = depinfo_.find_child(elem1.type, "id", elem1.id);
|
||||
config data2 = depinfo_.find_child(elem2.type, "id", elem2.id);
|
||||
config data1 = *depinfo_.find_child(elem1.type, "id", elem1.id);
|
||||
config data2 = *depinfo_.find_child(elem2.type, "id", elem2.id);
|
||||
|
||||
// Whether we should skip the check entirely
|
||||
if(data1.has_attribute("ignore_incompatible_" + elem2.type)) {
|
||||
|
@ -323,7 +323,7 @@ bool manager::does_require(const elem& elem1, const elem& elem2) const
|
|||
return false;
|
||||
}
|
||||
|
||||
config data = depinfo_.find_child(elem1.type, "id", elem1.id);
|
||||
config data = *depinfo_.find_child(elem1.type, "id", elem1.id);
|
||||
|
||||
if(data.has_attribute("force_modification")) {
|
||||
std::vector<std::string> required = utils::split(data["force_modification"]);
|
||||
|
@ -369,7 +369,7 @@ void manager::try_modifications(const std::vector<std::string>& ids, bool force)
|
|||
|
||||
void manager::try_modification_by_index(int index, bool activate, bool force)
|
||||
{
|
||||
std::string id = depinfo_.child("modification", index)["id"];
|
||||
std::string id = depinfo_.mandatory_child("modification", index)["id"];
|
||||
std::vector<std::string> mods_copy = mods_;
|
||||
|
||||
if(activate) {
|
||||
|
@ -388,12 +388,12 @@ void manager::try_modification_by_index(int index, bool activate, bool force)
|
|||
|
||||
void manager::try_era_by_index(int index, bool force)
|
||||
{
|
||||
try_era(depinfo_.child("era", index)["id"], force);
|
||||
try_era(depinfo_.mandatory_child("era", index)["id"], force);
|
||||
}
|
||||
|
||||
void manager::try_scenario_by_index(int index, bool force)
|
||||
{
|
||||
try_scenario(depinfo_.child("scenario", index)["id"], force);
|
||||
try_scenario(depinfo_.mandatory_child("scenario", index)["id"], force);
|
||||
}
|
||||
|
||||
int manager::get_era_index() const
|
||||
|
@ -427,7 +427,7 @@ int manager::get_scenario_index() const
|
|||
|
||||
bool manager::is_modification_active(int index) const
|
||||
{
|
||||
std::string id = depinfo_.child("modification", index)["id"];
|
||||
std::string id = depinfo_.mandatory_child("modification", index)["id"];
|
||||
return std::find(mods_.begin(), mods_.end(), id) != mods_.end();
|
||||
}
|
||||
|
||||
|
|
|
@ -62,8 +62,8 @@ flg_manager::flg_manager(const std::vector<const config*>& era_factions,
|
|||
const std::string& leader_id = side["id"];
|
||||
if(!leader_id.empty()) {
|
||||
// Check if leader was carried over and now is in [unit] tag.
|
||||
default_leader_cfg_ = &side.find_child("unit", "id", leader_id);
|
||||
if(*default_leader_cfg_) {
|
||||
default_leader_cfg_ = side.find_child("unit", "id", leader_id).ptr();
|
||||
if(default_leader_cfg_) {
|
||||
default_leader_type_ = (*default_leader_cfg_)["type"].str();
|
||||
default_leader_gender_ = (*default_leader_cfg_)["gender"].str();
|
||||
} else {
|
||||
|
@ -546,8 +546,8 @@ void flg_manager::set_current_gender(const std::string& gender)
|
|||
|
||||
const config& flg_manager::get_default_faction(const config& cfg)
|
||||
{
|
||||
if(const config& df = cfg.child("default_faction")) {
|
||||
return df;
|
||||
if(auto df = cfg.optional_child("default_faction")) {
|
||||
return *df;
|
||||
} else {
|
||||
return cfg;
|
||||
}
|
||||
|
|
|
@ -175,13 +175,13 @@ game_info::game_info(const config& game, const std::vector<std::string>& install
|
|||
}
|
||||
|
||||
if(!game["mp_era"].empty()) {
|
||||
const config& era_cfg = game_config.find_child("era", "id", game["mp_era"]);
|
||||
auto era_cfg = game_config.find_child("era", "id", game["mp_era"]);
|
||||
const bool require = game["require_era"].to_bool(true);
|
||||
if(era_cfg) {
|
||||
era = era_cfg["name"].str();
|
||||
|
||||
if(require) {
|
||||
addon_req result = check_addon_version_compatibility(era_cfg, game);
|
||||
addon_req result = check_addon_version_compatibility(*era_cfg, game);
|
||||
addons_outcome = std::max(addons_outcome, result); // Elevate to most severe error level encountered so far
|
||||
}
|
||||
} else {
|
||||
|
@ -206,8 +206,8 @@ game_info::game_info(const config& game, const std::vector<std::string>& install
|
|||
info_stream << ' ' << mod_info.back().first;
|
||||
|
||||
if(cfg["require_modification"].to_bool(false)) {
|
||||
if(const config& mod = game_config.find_child("modification", "id", cfg["id"])) {
|
||||
addon_req result = check_addon_version_compatibility(mod, game);
|
||||
if(auto mod = game_config.find_child("modification", "id", cfg["id"])) {
|
||||
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 {
|
||||
have_all_mods = false;
|
||||
|
@ -252,15 +252,15 @@ game_info::game_info(const config& game, const std::vector<std::string>& install
|
|||
//
|
||||
if(!game["mp_scenario"].empty() && game["mp_campaign"].empty()) {
|
||||
// Check if it's a multiplayer scenario
|
||||
const config* level_cfg = &game_config.find_child("multiplayer", "id", game["mp_scenario"]);
|
||||
const config* level_cfg = game_config.find_child("multiplayer", "id", game["mp_scenario"]).ptr();
|
||||
const bool require = game["require_scenario"].to_bool(false);
|
||||
|
||||
// Check if it's a user map
|
||||
if(!*level_cfg) {
|
||||
level_cfg = &game_config.find_child("generic_multiplayer", "id", game["mp_scenario"]);
|
||||
if(level_cfg) {
|
||||
level_cfg = game_config.find_child("generic_multiplayer", "id", game["mp_scenario"]).ptr();
|
||||
}
|
||||
|
||||
if(*level_cfg) {
|
||||
if(level_cfg) {
|
||||
type_marker = make_game_type_marker(_("scenario_abbreviation^S"), false);
|
||||
scenario = (*level_cfg)["name"].str();
|
||||
info_stream << scenario;
|
||||
|
@ -268,10 +268,10 @@ game_info::game_info(const config& game, const std::vector<std::string>& install
|
|||
// Reloaded games do not match the original scenario hash, so it makes no sense
|
||||
// to test them, since they always would appear as remote scenarios
|
||||
if(!reloaded) {
|
||||
if(const config& hashes = game_config.child("multiplayer_hashes")) {
|
||||
if(auto hashes = game_config.optional_child("multiplayer_hashes")) {
|
||||
std::string hash = game["hash"];
|
||||
bool hash_found = false;
|
||||
for(const auto & i : hashes.attribute_range()) {
|
||||
for(const auto & i : hashes->attribute_range()) {
|
||||
if(i.first == game["mp_scenario"] && i.second == hash) {
|
||||
hash_found = true;
|
||||
break;
|
||||
|
@ -301,7 +301,7 @@ game_info::game_info(const config& game, const std::vector<std::string>& install
|
|||
verified = false;
|
||||
}
|
||||
} else if(!game["mp_campaign"].empty()) {
|
||||
if(const config& campaign_cfg = game_config.find_child("campaign", "id", game["mp_campaign"])) {
|
||||
if(auto campaign_cfg = game_config.find_child("campaign", "id", game["mp_campaign"])) {
|
||||
type_marker = make_game_type_marker(_("campaign_abbreviation^C"), false);
|
||||
|
||||
std::stringstream campaign_text;
|
||||
|
@ -310,7 +310,7 @@ game_info::game_info(const config& game, const std::vector<std::string>& install
|
|||
<< game["mp_scenario_name"];
|
||||
|
||||
// Difficulty
|
||||
config difficulties = gui2::dialogs::generate_difficulty_config(campaign_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 << spaced_em_dash() << difficulty["description"];
|
||||
|
@ -324,7 +324,7 @@ game_info::game_info(const config& game, const std::vector<std::string>& install
|
|||
|
||||
// TODO: should we have this?
|
||||
//if(game["require_scenario"].to_bool(false)) {
|
||||
addon_req result = check_addon_version_compatibility(campaign_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 {
|
||||
|
@ -412,7 +412,7 @@ game_info::addon_req game_info::check_addon_version_compatibility(const config&
|
|||
return addon_req::SATISFIED;
|
||||
}
|
||||
|
||||
if(const config& game_req = game.find_child("addon", "id", local_item["addon_id"])) {
|
||||
if(auto game_req = game.find_child("addon", "id", local_item["addon_id"])) {
|
||||
if(!game_req["require"].to_bool(false)) {
|
||||
return addon_req::SATISFIED;
|
||||
}
|
||||
|
@ -429,7 +429,7 @@ game_info::addon_req game_info::check_addon_version_compatibility(const config&
|
|||
|
||||
// Remote version
|
||||
const version_info remote_ver(game_req["version"].str());
|
||||
version_info remote_min_ver(game_req.has_attribute("min_version") ? game_req["min_version"] : game_req["version"]);
|
||||
version_info remote_min_ver(game_req->has_attribute("min_version") ? game_req["min_version"] : game_req["version"]);
|
||||
|
||||
remote_min_ver = std::min(remote_min_ver, remote_ver);
|
||||
|
||||
|
|
|
@ -126,13 +126,13 @@ void lobby_info::process_gamelist(const config& data)
|
|||
|
||||
games_by_id_.clear();
|
||||
|
||||
for(const auto& c : gamelist_.child("gamelist").child_range("game")) {
|
||||
for(const auto& c : gamelist_.mandatory_child("gamelist").child_range("game")) {
|
||||
game_info game(c, installed_addons_);
|
||||
games_by_id_.emplace(game.id, std::move(game));
|
||||
}
|
||||
|
||||
DBG_LB << dump_games_map(games_by_id_);
|
||||
DBG_LB << dump_games_config(gamelist_.child("gamelist"));
|
||||
DBG_LB << dump_games_config(gamelist_.mandatory_child("gamelist"));
|
||||
|
||||
process_userlist();
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ bool lobby_info::process_gamelist_diff_impl(const config& data)
|
|||
return false;
|
||||
}
|
||||
|
||||
DBG_LB << "prediff " << dump_games_config(gamelist_.child("gamelist"));
|
||||
DBG_LB << "prediff " << dump_games_config(gamelist_.mandatory_child("gamelist"));
|
||||
|
||||
try {
|
||||
gamelist_.apply_diff(data, true);
|
||||
|
@ -164,10 +164,10 @@ bool lobby_info::process_gamelist_diff_impl(const config& data)
|
|||
return false;
|
||||
}
|
||||
|
||||
DBG_LB << "postdiff " << dump_games_config(gamelist_.child("gamelist"));
|
||||
DBG_LB << "postdiff " << dump_games_config(gamelist_.mandatory_child("gamelist"));
|
||||
DBG_LB << dump_games_map(games_by_id_);
|
||||
|
||||
for(config& c : gamelist_.child("gamelist").child_range("game")) {
|
||||
for(config& c : gamelist_.mandatory_child("gamelist").child_range("game")) {
|
||||
DBG_LB << "data process: " << c["id"] << " (" << c[config::diff_track_attribute] << ")";
|
||||
|
||||
const int game_id = c["id"];
|
||||
|
@ -219,7 +219,7 @@ bool lobby_info::process_gamelist_diff_impl(const config& data)
|
|||
return false;
|
||||
}
|
||||
|
||||
DBG_LB << "postclean " << dump_games_config(gamelist_.child("gamelist"));
|
||||
DBG_LB << "postclean " << dump_games_config(gamelist_.mandatory_child("gamelist"));
|
||||
|
||||
process_userlist();
|
||||
return true;
|
||||
|
|
|
@ -96,7 +96,7 @@ config initial_level_config(saved_game& state)
|
|||
*/
|
||||
|
||||
const game_config_view& game_config = game_config_manager::get()->game_config();
|
||||
const config& era_cfg = game_config.find_child("era", "id", era);
|
||||
auto era_cfg = game_config.find_child("era", "id", era);
|
||||
|
||||
if(!era_cfg) {
|
||||
if(params.saved_game == saved_game_mode::type::no) {
|
||||
|
@ -107,20 +107,20 @@ config initial_level_config(saved_game& state)
|
|||
WRN_CF << "Missing era in MP load game '" << era << "'";
|
||||
|
||||
} else {
|
||||
level.add_child("era", era_cfg);
|
||||
level.add_child("era", *era_cfg);
|
||||
|
||||
// Initialize the list of sides available for the current era.
|
||||
// We also need this so not to get a segfault in mp_staging for ai configuration.
|
||||
const config& custom_side = game_config.find_child("multiplayer_side", "id", "Custom");
|
||||
level.child("era").add_child_at("multiplayer_side", custom_side, 0);
|
||||
auto custom_side = game_config.find_child("multiplayer_side", "id", "Custom");
|
||||
level.mandatory_child("era").add_child_at("multiplayer_side", *custom_side, 0);
|
||||
}
|
||||
|
||||
// Add modifications, needed for ai algorithms which are applied in mp_staging.
|
||||
const std::vector<std::string>& mods = state.classification().active_mods;
|
||||
|
||||
for(unsigned i = 0; i < mods.size(); ++i) {
|
||||
if(const config& mod_cfg = game_config.find_child("modification", "id", mods[i])) {
|
||||
level.add_child("modification", mod_cfg);
|
||||
if(auto mod_cfg = game_config.find_child("modification", "id", mods[i])) {
|
||||
level.add_child("modification", *mod_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -520,8 +520,8 @@ bool mp_manager::enter_lobby_mode()
|
|||
|
||||
// We use a loop here to allow returning to the lobby if you, say, cancel game creation.
|
||||
while(true) {
|
||||
if(const config& cfg = game_config_manager::get()->game_config().child("lobby_music")) {
|
||||
for(const config& i : cfg.child_range("music")) {
|
||||
if(auto cfg = game_config_manager::get()->game_config().optional_child("lobby_music")) {
|
||||
for(const config& i : cfg->child_range("music")) {
|
||||
sound::play_music_config(i);
|
||||
}
|
||||
|
||||
|
@ -739,7 +739,7 @@ void start_local_game_commandline(const commandline_options& cmdline_opts)
|
|||
state.classification().era_id = *cmdline_opts.multiplayer_era;
|
||||
}
|
||||
|
||||
if(const config& cfg_era = game_config.find_child("era", "id", state.classification().era_id)) {
|
||||
if(auto cfg_era = game_config.find_child("era", "id", state.classification().era_id)) {
|
||||
state.classification().era_define = cfg_era["define"].str();
|
||||
} else {
|
||||
PLAIN_LOG << "Could not find era '" << state.classification().era_id << "'";
|
||||
|
@ -751,7 +751,7 @@ void start_local_game_commandline(const commandline_options& cmdline_opts)
|
|||
parameters.name = *cmdline_opts.multiplayer_scenario;
|
||||
}
|
||||
|
||||
if(const config& cfg_multiplayer = game_config.find_child("multiplayer", "id", parameters.name)) {
|
||||
if(auto cfg_multiplayer = game_config.find_child("multiplayer", "id", parameters.name)) {
|
||||
state.classification().scenario_define = cfg_multiplayer["define"].str();
|
||||
} else {
|
||||
PLAIN_LOG << "Could not find [multiplayer] '" << parameters.name << "'";
|
||||
|
|
|
@ -63,9 +63,9 @@ game_state::game_state(const config& level, play_controller& pc)
|
|||
, first_human_team_(-1)
|
||||
{
|
||||
lua_kernel_->load_core();
|
||||
if(const config& endlevel_cfg = level.child("end_level_data")) {
|
||||
if(auto endlevel_cfg = level.optional_child("end_level_data")) {
|
||||
end_level_data el_data;
|
||||
el_data.read(endlevel_cfg);
|
||||
el_data.read(*endlevel_cfg);
|
||||
el_data.transient.carryover_report = false;
|
||||
end_level_data_ = el_data;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ cave_map_generator::cave_map_generator(const config &cfg) :
|
|||
village_(t_translation::UNDERGROUND_VILLAGE),
|
||||
castle_(t_translation::DWARVEN_CASTLE),
|
||||
keep_(t_translation::DWARVEN_KEEP),
|
||||
cfg_(cfg ? cfg : config()),
|
||||
cfg_(cfg),
|
||||
width_(50),
|
||||
height_(50),
|
||||
village_density_(0),
|
||||
|
@ -193,8 +193,8 @@ void cave_map_generator::cave_map_generator_job::generate_chambers()
|
|||
new_chamber.center = map_location(x,y);
|
||||
build_chamber(new_chamber.center,new_chamber.locs,chamber_size,jagged_edges);
|
||||
|
||||
const config &items = ch.child("items");
|
||||
new_chamber.items = items ? &items : nullptr;
|
||||
auto items = ch.optional_child("items");
|
||||
new_chamber.items = items ? &*items : nullptr;
|
||||
|
||||
const std::string &id = ch["id"];
|
||||
if (!id.empty()) {
|
||||
|
@ -231,11 +231,12 @@ void cave_map_generator::cave_map_generator_job::place_chamber(const chamber& c)
|
|||
for (const config::any_child it : c.items->all_children_range())
|
||||
{
|
||||
config cfg = it.cfg;
|
||||
config &filter = cfg.child("filter");
|
||||
auto filter = cfg.optional_child("filter");
|
||||
config* object_filter = nullptr;
|
||||
if (config &object = cfg.child("object")) {
|
||||
if (config &of = object.child("filter"))
|
||||
object_filter = &of;
|
||||
if (auto object = cfg.optional_child("object")) {
|
||||
if (auto of = object->optional_child("filter")) {
|
||||
object_filter = &*of;
|
||||
}
|
||||
}
|
||||
|
||||
if (!it.cfg["same_location_as_previous"].to_bool()) {
|
||||
|
|
|
@ -67,7 +67,7 @@ std::string default_map_generator::name() const { return "default"; }
|
|||
|
||||
std::string default_map_generator::config_name() const
|
||||
{
|
||||
if (const config &c = cfg_.child("scenario"))
|
||||
if (auto c = cfg_.optional_child("scenario"))
|
||||
return c["name"];
|
||||
|
||||
return std::string();
|
||||
|
|
|
@ -109,7 +109,7 @@ namespace {
|
|||
static std::string terrain;
|
||||
terrain = t_translation::write_terrain_code(c);
|
||||
double res = getNoPathValue();
|
||||
if(const config &child = cfg_.find_child("road_cost", "terrain", terrain)) {
|
||||
if(auto child = cfg_.find_child("road_cost", "terrain", terrain)) {
|
||||
res = child["cost"].to_double();
|
||||
}
|
||||
|
||||
|
@ -628,7 +628,7 @@ static map_location place_village(const t_translation::ter_map& map,
|
|||
|
||||
const t_translation::terrain_code t = map[i.x][i.y];
|
||||
const std::string str = t_translation::write_terrain_code(t);
|
||||
if(const config &child = cfg.find_child("village", "terrain", str)) {
|
||||
if(auto child = cfg.find_child("village", "terrain", str)) {
|
||||
tcode_list_cache::iterator l = adj_liked_cache.find(t);
|
||||
t_translation::ter_list *adjacent_liked;
|
||||
if(l != adj_liked_cache.end()) {
|
||||
|
@ -707,7 +707,7 @@ std::string default_map_generator_job::default_generate_map(generator_data data,
|
|||
VALIDATE(is_even(data.width), _("Random maps with an odd width aren't supported."));
|
||||
|
||||
// Try to find configuration for castles
|
||||
const config& castle_config = cfg.child("castle");
|
||||
auto castle_config = cfg.optional_child("castle");
|
||||
|
||||
int ticks = SDL_GetTicks();
|
||||
|
||||
|
@ -721,8 +721,8 @@ std::string default_map_generator_job::default_generate_map(generator_data data,
|
|||
config naming;
|
||||
|
||||
if(cfg.has_child("naming")) {
|
||||
naming = game_config_.child("naming");
|
||||
naming.append_attributes(cfg.child("naming"));
|
||||
naming = game_config_.mandatory_child("naming");
|
||||
naming.append_attributes(cfg.mandatory_child("naming"));
|
||||
}
|
||||
|
||||
// If the [naming] child is empty, we cannot provide good names.
|
||||
|
@ -1055,8 +1055,8 @@ std::string default_map_generator_job::default_generate_map(generator_data data,
|
|||
}
|
||||
|
||||
// Find the configuration which tells us what to convert this tile to, to make it into a road.
|
||||
const config& child = cfg.find_child("road_cost", "terrain", t_translation::write_terrain_code(terrain[x][y]));
|
||||
if(child.empty()){
|
||||
auto child = cfg.find_child("road_cost", "terrain", t_translation::write_terrain_code(terrain[x][y]));
|
||||
if(!child || child->empty()){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1255,10 +1255,10 @@ std::string default_map_generator_job::default_generate_map(generator_data data,
|
|||
std::set<std::string> used_names;
|
||||
tcode_list_cache adj_liked_cache;
|
||||
|
||||
config village_naming = game_config_.child("village_naming");
|
||||
config village_naming = game_config_.mandatory_child("village_naming");
|
||||
|
||||
if(cfg.has_child("village_naming")) {
|
||||
village_naming.append_attributes(cfg.child("village_naming"));
|
||||
village_naming.append_attributes(cfg.mandatory_child("village_naming"));
|
||||
}
|
||||
|
||||
// If the [village_naming] child is empty, we cannot provide good names.
|
||||
|
|
|
@ -122,7 +122,7 @@ gui_definition::gui_definition(const config& cfg)
|
|||
* - Override the default and above per instance of the widget, some buttons
|
||||
* can give a different sound.
|
||||
*/
|
||||
const config& settings = cfg.child("settings");
|
||||
const config& settings = cfg.mandatory_child("settings");
|
||||
|
||||
popup_show_delay_ = settings["popup_show_delay"];
|
||||
popup_show_time_ = settings["popup_show_time"];
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
namespace gui2
|
||||
{
|
||||
|
||||
state_definition::state_definition(const config& cfg)
|
||||
: canvas_cfg_(cfg ? cfg.child("draw") : cfg)
|
||||
state_definition::state_definition(optional_const_config cfg)
|
||||
: canvas_cfg_(cfg ? cfg->child_or_empty("draw") : config())
|
||||
{
|
||||
VALIDATE(canvas_cfg_, _("No state or draw section defined."));
|
||||
VALIDATE(cfg && cfg->has_child("draw"), _("No state or draw section defined."));
|
||||
}
|
||||
|
||||
resolution_definition::resolution_definition(const config& cfg)
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace gui2
|
|||
*/
|
||||
struct state_definition
|
||||
{
|
||||
explicit state_definition(const config& cfg);
|
||||
explicit state_definition(optional_const_config cfg);
|
||||
|
||||
config canvas_cfg_;
|
||||
};
|
||||
|
|
|
@ -162,11 +162,11 @@ builder_window::window_resolution::window_resolution(const config& cfg)
|
|||
wfl::formula(cfg["functions"], &functions).evaluate();
|
||||
}
|
||||
|
||||
const config& c = cfg.child("grid");
|
||||
auto c = cfg.optional_child("grid");
|
||||
|
||||
VALIDATE(c, _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<builder_grid>(c);
|
||||
grid = std::make_shared<builder_grid>(*c);
|
||||
|
||||
if(!automatic_placement) {
|
||||
VALIDATE(width.has_formula() || width(), missing_mandatory_wml_key("resolution", "width"));
|
||||
|
|
|
@ -545,7 +545,8 @@ void addon_manager::toggle_details(button& btn, stacked_widget& stk)
|
|||
void addon_manager::fetch_addons_list()
|
||||
{
|
||||
client_.request_addons_list(cfg_);
|
||||
if(!cfg_) {
|
||||
// TODO: this was a faulty invalid config test.
|
||||
if((false)) {
|
||||
gui2::show_error_message(_("An error occurred while downloading the add-ons list from the server."));
|
||||
get_window()->close();
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ void campaign_difficulty::post_show(window& window)
|
|||
{
|
||||
if(get_retval() == retval::OK) {
|
||||
listbox& list = find_widget<listbox>(&window, "listbox", false);
|
||||
selected_difficulty_ = difficulties_.child("difficulty", list.get_selected_row())["define"].str();
|
||||
selected_difficulty_ = difficulties_.mandatory_child("difficulty", list.get_selected_row())["define"].str();
|
||||
}
|
||||
}
|
||||
} // namespace dialogs
|
||||
|
|
|
@ -370,8 +370,8 @@ void game_load::evaluate_summary_string(std::stringstream& str, const config& cf
|
|||
case campaign_type::type::scenario: {
|
||||
const config* campaign = nullptr;
|
||||
if(!campaign_id.empty()) {
|
||||
if(const config& c = cache_config_.find_child("campaign", "id", campaign_id)) {
|
||||
campaign = &c;
|
||||
if(auto c = cache_config_.find_child("campaign", "id", campaign_id)) {
|
||||
campaign = c.ptr();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -421,8 +421,8 @@ void game_load::evaluate_summary_string(std::stringstream& str, const config& cf
|
|||
case campaign_type::type::multiplayer: {
|
||||
const config* campaign = nullptr;
|
||||
if (!campaign_id.empty()) {
|
||||
if (const config& c = cache_config_.find_child("campaign", "id", campaign_id)) {
|
||||
campaign = &c;
|
||||
if (auto c = cache_config_.find_child("campaign", "id", campaign_id)) {
|
||||
campaign = c.ptr();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -433,7 +433,7 @@ void game_load::evaluate_summary_string(std::stringstream& str, const config& cf
|
|||
if (campaign != nullptr) {
|
||||
str << "\n" << _("Difficulty: ");
|
||||
try {
|
||||
const config& difficulty = campaign->find_child("difficulty", "define", cfg_summary["difficulty"]);
|
||||
auto difficulty = campaign->find_child("difficulty", "define", cfg_summary["difficulty"]);
|
||||
std::ostringstream ss;
|
||||
ss << difficulty["label"] << " (" << difficulty["description"] << ")";
|
||||
str << ss.str();
|
||||
|
|
|
@ -550,7 +550,7 @@ void variable_mode_controller::show_array(tree_view_node& node)
|
|||
std::size_t n_start = var.find_last_of('[') + 1;
|
||||
std::size_t n_len = var.size() - n_start - 1;
|
||||
int n = std::stoi(var.substr(n_start, n_len));
|
||||
model().set_data(config_to_string(vars().child(var.substr(1, n_start - 3), n)));
|
||||
model().set_data(config_to_string(vars().mandatory_child(var.substr(1, n_start - 3), n)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -585,7 +585,7 @@ void event_mode_controller::show_list(tree_view_node& node, bool is_wmi)
|
|||
void event_mode_controller::show_event(tree_view_node& node, bool is_wmi)
|
||||
{
|
||||
int n = node.describe_path().back();
|
||||
model().set_data(config_to_string(events.child(is_wmi ? "menu_item" : "event", n)));
|
||||
model().set_data(config_to_string(events.mandatory_child(is_wmi ? "menu_item" : "event", n)));
|
||||
}
|
||||
|
||||
static stuff_list_adder add_unit_entry(stuff_list_adder& progress, const unit& u, const display_context& dc)
|
||||
|
@ -705,7 +705,7 @@ void unit_mode_controller::show_array(tree_view_node& node)
|
|||
std::size_t n_start = var.find_last_of('[') + 1;
|
||||
std::size_t n_len = var.size() - n_start - 1;
|
||||
int n = std::stoi(var.substr(n_start, n_len));
|
||||
model().set_data(config_to_string(u->variables().child(var.substr(1, n_start - 3), n)));
|
||||
model().set_data(config_to_string(u->variables().mandatory_child(var.substr(1, n_start - 3), n)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -907,7 +907,7 @@ void team_mode_controller::show_array(tree_view_node& node, int side)
|
|||
std::size_t n_start = var.find_last_of('[') + 1;
|
||||
std::size_t n_len = var.size() - n_start - 1;
|
||||
int n = std::stoi(var.substr(n_start, n_len));
|
||||
model().set_data(config_to_string(t.variables().child(var.substr(1, n_start - 3), n)));
|
||||
model().set_data(config_to_string(t.variables().mandatory_child(var.substr(1, n_start - 3), n)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ REGISTER_DIALOG(help_browser)
|
|||
help_browser::help_browser()
|
||||
: modal_dialog(window_id())
|
||||
, initial_topic_("introduction")
|
||||
, help_cfg_(game_config_manager::get()->game_config().child("help"))
|
||||
, help_cfg_(game_config_manager::get()->game_config().mandatory_child("help"))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -752,13 +752,13 @@ void mp_lobby::network_handler()
|
|||
|
||||
void mp_lobby::process_network_data(const config& data)
|
||||
{
|
||||
if(const config& error = data.child("error")) {
|
||||
if(auto error = data.optional_child("error")) {
|
||||
throw wesnothd_error(error["message"]);
|
||||
} else if(data.child("gamelist")) {
|
||||
} else if(data.has_child("gamelist")) {
|
||||
process_gamelist(data);
|
||||
} else if(const config& gamelist_diff = data.child("gamelist_diff")) {
|
||||
process_gamelist_diff(gamelist_diff);
|
||||
} else if(const config& info = data.child("message")) {
|
||||
} else if(auto gamelist_diff = data.optional_child("gamelist_diff")) {
|
||||
process_gamelist_diff(*gamelist_diff);
|
||||
} else if(auto info = data.optional_child("message")) {
|
||||
if(info["type"] == "server_info") {
|
||||
server_information_ = info["message"].str();
|
||||
return;
|
||||
|
|
|
@ -103,20 +103,20 @@ bool mp_join_game::fetch_game_config()
|
|||
network_connection_.wait_and_receive_data(revc);
|
||||
});
|
||||
|
||||
if(const config& err = revc.child("error")) {
|
||||
if(auto err = revc.optional_child("error")) {
|
||||
throw wesnothd_error(err["message"]);
|
||||
} else if(revc.child("leave_game")) {
|
||||
} else if(revc.has_child("leave_game")) {
|
||||
return false;
|
||||
} else if(config& next_scenario = revc.child("next_scenario")) {
|
||||
level_.swap(next_scenario);
|
||||
} else if(auto next_scenario = revc.optional_child("next_scenario")) {
|
||||
level_.swap(*next_scenario);
|
||||
} else if(revc.has_attribute("version")) {
|
||||
level_.swap(revc);
|
||||
|
||||
has_scenario_and_controllers = true;
|
||||
} else if(config& controllers = revc.child("controllers")) {
|
||||
} else if(auto controllers = revc.optional_child("controllers")) {
|
||||
int index = 0;
|
||||
for(const config& controller : controllers.child_range("controller")) {
|
||||
if(config& side = get_scenario().child("side", index)) {
|
||||
for(const config& controller : controllers->child_range("controller")) {
|
||||
if(auto side = get_scenario().optional_child("side", index)) {
|
||||
side["is_local"] = controller["is_local"];
|
||||
}
|
||||
++index;
|
||||
|
@ -140,7 +140,7 @@ bool mp_join_game::fetch_game_config()
|
|||
// since add-ons are now only enabled when used, the scenario ID may still not be known
|
||||
// so check in the MP info sent from the server for the scenario ID if that's the case
|
||||
if(scenario_id == "") {
|
||||
for(const auto& addon : level_.child("multiplayer").child_range("addon")) {
|
||||
for(const auto& addon : level_.mandatory_child("multiplayer").child_range("addon")) {
|
||||
for(const auto& content : addon.child_range("content")) {
|
||||
if(content["type"] == "scenario") {
|
||||
scenario_id = content["id"].str();
|
||||
|
@ -245,7 +245,7 @@ void mp_join_game::pre_show(window& window)
|
|||
//
|
||||
label& title = find_widget<label>(&window, "title", false);
|
||||
// FIXME: very hacky way to get the game name...
|
||||
title.set_label((formatter() << level_.child("multiplayer")["scenario"] << " " << font::unicode_em_dash << " " << get_scenario()["name"].t_str()).str());
|
||||
title.set_label((formatter() << level_.mandatory_child("multiplayer")["scenario"] << " " << font::unicode_em_dash << " " << get_scenario()["name"].t_str()).str());
|
||||
|
||||
//
|
||||
// Set up sides list
|
||||
|
@ -283,18 +283,18 @@ void mp_join_game::pre_show(window& window)
|
|||
|
||||
bool mp_join_game::show_flg_select(int side_num, bool first_time)
|
||||
{
|
||||
if(const config& side_choice = get_scenario().child("side", side_num - 1)) {
|
||||
if(auto side_choice = get_scenario().optional_child("side", side_num - 1)) {
|
||||
if(!side_choice["allow_changes"].to_bool(true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const config& era = level_.child("era");
|
||||
auto era = level_.optional_child("era");
|
||||
if(!era) {
|
||||
ERR_MP << "no era information";
|
||||
return false;
|
||||
}
|
||||
|
||||
config::const_child_itors possible_sides = era.child_range("multiplayer_side");
|
||||
config::const_child_itors possible_sides = era->child_range("multiplayer_side");
|
||||
if(possible_sides.empty()) {
|
||||
WRN_MP << "no [multiplayer_side] found in era '" << era["id"] << "'.";
|
||||
return false;
|
||||
|
@ -312,10 +312,10 @@ bool mp_join_game::show_flg_select(int side_num, bool first_time)
|
|||
|
||||
const bool is_mp = state_.classification().is_normal_mp_game();
|
||||
const bool lock_settings = get_scenario()["force_lock_settings"].to_bool(!is_mp);
|
||||
const bool use_map_settings = level_.child("multiplayer")["mp_use_map_settings"].to_bool();
|
||||
const saved_game_mode::type saved_game = saved_game_mode::get_enum(level_.child("multiplayer")["savegame"].str()).value_or(saved_game_mode::type::no);
|
||||
const bool use_map_settings = level_.mandatory_child("multiplayer")["mp_use_map_settings"].to_bool();
|
||||
const saved_game_mode::type saved_game = saved_game_mode::get_enum(level_.mandatory_child("multiplayer")["savegame"].str()).value_or(saved_game_mode::type::no);
|
||||
|
||||
ng::flg_manager flg(era_factions, side_choice, lock_settings, use_map_settings, saved_game == saved_game_mode::type::midgame);
|
||||
ng::flg_manager flg(era_factions, *side_choice, lock_settings, use_map_settings, saved_game == saved_game_mode::type::midgame);
|
||||
|
||||
{
|
||||
gui2::dialogs::faction_select flg_dialog(flg, color, side_num);
|
||||
|
@ -515,34 +515,34 @@ void mp_join_game::network_handler()
|
|||
close_faction_select_dialog_if_open();
|
||||
|
||||
set_retval(retval::CANCEL);
|
||||
} else if(data.child("start_game")) {
|
||||
} else if(data.has_child("start_game")) {
|
||||
close_faction_select_dialog_if_open();
|
||||
|
||||
level_["started"] = true;
|
||||
set_retval(retval::OK);
|
||||
} else if(data.child("leave_game")) {
|
||||
} else if(data.has_child("leave_game")) {
|
||||
close_faction_select_dialog_if_open();
|
||||
|
||||
set_retval(retval::CANCEL);
|
||||
}
|
||||
|
||||
if(data.child("stop_updates")) {
|
||||
if(data.has_child("stop_updates")) {
|
||||
stop_updates_ = true;
|
||||
} else if(const config& c = data.child("scenario_diff")) {
|
||||
} else if(auto c = data.optional_child("scenario_diff")) {
|
||||
// TODO: We should catch config::error and then leave the game.
|
||||
level_.apply_diff(c);
|
||||
level_.apply_diff(*c);
|
||||
|
||||
generate_side_list();
|
||||
} else if(const config& change = data.child("change_controller")) {
|
||||
if(config& side_to_change = get_scenario().find_child("side", "side", change["side"])) {
|
||||
side_to_change.merge_with(change);
|
||||
} else if(auto change = data.optional_child("change_controller")) {
|
||||
if(auto side_to_change = get_scenario().find_child("side", "side", change["side"])) {
|
||||
side_to_change->merge_with(*change);
|
||||
}
|
||||
|
||||
if(flg_dialog_ && flg_dialog_->get_side_num() == change["side"].to_int()) {
|
||||
close_faction_select_dialog_if_open();
|
||||
}
|
||||
} else if(data.has_child("scenario") || data.has_child("snapshot") || data.child("next_scenario")) {
|
||||
level_ = first_scenario_ ? data : data.child("next_scenario");
|
||||
} else if(data.has_child("scenario") || data.has_child("snapshot") || data.has_child("next_scenario")) {
|
||||
level_ = first_scenario_ ? data : data.mandatory_child("next_scenario");
|
||||
|
||||
generate_side_list();
|
||||
}
|
||||
|
@ -559,10 +559,10 @@ void mp_join_game::network_handler()
|
|||
|
||||
config& mp_join_game::get_scenario()
|
||||
{
|
||||
if(config& scenario = level_.child("scenario")) {
|
||||
return scenario;
|
||||
} else if(config& snapshot = level_.child("snapshot")) {
|
||||
return snapshot;
|
||||
if(auto scenario = level_.optional_child("scenario")) {
|
||||
return *scenario;
|
||||
} else if(auto snapshot = level_.optional_child("snapshot")) {
|
||||
return *snapshot;
|
||||
}
|
||||
|
||||
return level_;
|
||||
|
@ -576,9 +576,9 @@ void mp_join_game::post_show(window& window)
|
|||
}
|
||||
|
||||
if(window.get_retval() == retval::OK) {
|
||||
if(const config& stats = level_.child("statistics")) {
|
||||
if(auto stats = level_.optional_child("statistics")) {
|
||||
statistics::fresh_stats();
|
||||
statistics::read_stats(stats);
|
||||
statistics::read_stats(*stats);
|
||||
}
|
||||
|
||||
mp::level_to_gamestate(level_, state_);
|
||||
|
|
|
@ -427,10 +427,10 @@ addon_list_definition::resolution::resolution(const config& cfg)
|
|||
static config dummy("draw");
|
||||
state.emplace_back(dummy);
|
||||
|
||||
const config& child = cfg.child("grid");
|
||||
auto child = cfg.optional_child("grid");
|
||||
VALIDATE(child, _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<builder_grid>(child);
|
||||
grid = std::make_shared<builder_grid>(*child);
|
||||
}
|
||||
|
||||
namespace implementation
|
||||
|
|
|
@ -159,10 +159,10 @@ button_definition::resolution::resolution(const config& cfg)
|
|||
: resolution_definition(cfg)
|
||||
{
|
||||
// Note the order should be the same as the enum state_t in button.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.child("state_disabled"));
|
||||
state.emplace_back(cfg.child("state_pressed"));
|
||||
state.emplace_back(cfg.child("state_focused"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_disabled"));
|
||||
state.emplace_back(cfg.optional_child("state_pressed"));
|
||||
state.emplace_back(cfg.optional_child("state_focused"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
|
|
@ -653,13 +653,13 @@ chatbox_definition::chatbox_definition(const config& cfg)
|
|||
chatbox_definition::resolution::resolution(const config& cfg)
|
||||
: resolution_definition(cfg), grid()
|
||||
{
|
||||
state.emplace_back(cfg.child("background"));
|
||||
state.emplace_back(cfg.child("foreground"));
|
||||
state.emplace_back(cfg.optional_child("background"));
|
||||
state.emplace_back(cfg.optional_child("foreground"));
|
||||
|
||||
const config& child = cfg.child("grid");
|
||||
auto child = cfg.optional_child("grid");
|
||||
VALIDATE(child, _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<builder_grid>(child);
|
||||
grid = std::make_shared<builder_grid>(*child);
|
||||
}
|
||||
// }---------- BUILDER -----------{
|
||||
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include "gui/core/register_widget.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
|
||||
#include "gettext.hpp"
|
||||
#include "wml_exception.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace gui2
|
||||
|
@ -113,7 +116,7 @@ builder_drawing::builder_drawing(const config& cfg)
|
|||
: builder_styled_widget(cfg)
|
||||
, width(cfg["width"])
|
||||
, height(cfg["height"])
|
||||
, draw(cfg.child("draw"))
|
||||
, draw(VALIDATE_WML_CHILD(cfg, "draw", _("Missing [draw] in drawing")))
|
||||
{
|
||||
assert(!draw.empty());
|
||||
}
|
||||
|
|
|
@ -129,10 +129,10 @@ horizontal_scrollbar_definition::resolution::resolution(const config& cfg)
|
|||
"minimum_positioner_length"));
|
||||
|
||||
// Note the order should be the same as the enum state_t is scrollbar.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.child("state_disabled"));
|
||||
state.emplace_back(cfg.child("state_pressed"));
|
||||
state.emplace_back(cfg.child("state_focused"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_disabled"));
|
||||
state.emplace_back(cfg.optional_child("state_pressed"));
|
||||
state.emplace_back(cfg.optional_child("state_focused"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
|
|
@ -110,7 +110,7 @@ image_definition::resolution::resolution(const config& cfg)
|
|||
: resolution_definition(cfg)
|
||||
{
|
||||
// Note the order should be the same as the enum state_t in image.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
|
|
@ -237,8 +237,8 @@ label_definition::resolution::resolution(const config& cfg)
|
|||
, link_color(cfg["link_color"].empty() ? color_t::from_hex_string("ffff00") : color_t::from_rgba_string(cfg["link_color"].str()))
|
||||
{
|
||||
// Note the order should be the same as the enum state_t is label.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.child("state_disabled"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_disabled"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
|
|
@ -706,11 +706,10 @@ listbox_definition::resolution::resolution(const config& cfg)
|
|||
, grid(nullptr)
|
||||
{
|
||||
// Note the order should be the same as the enum state_t in listbox.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.child("state_disabled"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_disabled"));
|
||||
|
||||
const config& child = cfg.child("grid");
|
||||
VALIDATE(child, _("No grid defined."));
|
||||
auto child = VALIDATE_WML_CHILD(cfg, "grid", _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<builder_grid>(child);
|
||||
}
|
||||
|
@ -759,25 +758,25 @@ builder_listbox::builder_listbox(const config& cfg)
|
|||
, has_minimum_(cfg["has_minimum"].to_bool(true))
|
||||
, has_maximum_(cfg["has_maximum"].to_bool(true))
|
||||
{
|
||||
if(const config& h = cfg.child("header")) {
|
||||
header = std::make_shared<builder_grid>(h);
|
||||
if(auto h = cfg.optional_child("header")) {
|
||||
header = std::make_shared<builder_grid>(*h);
|
||||
}
|
||||
|
||||
if(const config& f = cfg.child("footer")) {
|
||||
footer = std::make_shared<builder_grid>(f);
|
||||
if(auto f = cfg.optional_child("footer")) {
|
||||
footer = std::make_shared<builder_grid>(*f);
|
||||
}
|
||||
|
||||
const config& l = cfg.child("list_definition");
|
||||
auto l = cfg.optional_child("list_definition");
|
||||
|
||||
VALIDATE(l, _("No list defined."));
|
||||
|
||||
list_builder = std::make_shared<builder_grid>(l);
|
||||
list_builder = std::make_shared<builder_grid>(*l);
|
||||
assert(list_builder);
|
||||
|
||||
VALIDATE(list_builder->rows == 1, _("A 'list_definition' should contain one row."));
|
||||
|
||||
if(cfg.has_child("list_data")) {
|
||||
list_data = parse_list_data(cfg.child("list_data"), list_builder->cols);
|
||||
list_data = parse_list_data(cfg.mandatory_child("list_data"), list_builder->cols);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -810,17 +809,17 @@ builder_horizontal_listbox::builder_horizontal_listbox(const config& cfg)
|
|||
, has_minimum_(cfg["has_minimum"].to_bool(true))
|
||||
, has_maximum_(cfg["has_maximum"].to_bool(true))
|
||||
{
|
||||
const config& l = cfg.child("list_definition");
|
||||
auto l = cfg.optional_child("list_definition");
|
||||
|
||||
VALIDATE(l, _("No list defined."));
|
||||
|
||||
list_builder = std::make_shared<builder_grid>(l);
|
||||
list_builder = std::make_shared<builder_grid>(*l);
|
||||
assert(list_builder);
|
||||
|
||||
VALIDATE(list_builder->rows == 1, _("A 'list_definition' should contain one row."));
|
||||
|
||||
if(cfg.has_child("list_data")) {
|
||||
list_data = parse_list_data(cfg.child("list_data"), list_builder->cols);
|
||||
list_data = parse_list_data(cfg.mandatory_child("list_data"), list_builder->cols);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -853,17 +852,17 @@ builder_grid_listbox::builder_grid_listbox(const config& cfg)
|
|||
, has_minimum_(cfg["has_minimum"].to_bool(true))
|
||||
, has_maximum_(cfg["has_maximum"].to_bool(true))
|
||||
{
|
||||
const config& l = cfg.child("list_definition");
|
||||
auto l = cfg.optional_child("list_definition");
|
||||
|
||||
VALIDATE(l, _("No list defined."));
|
||||
|
||||
list_builder = std::make_shared<builder_grid>(l);
|
||||
list_builder = std::make_shared<builder_grid>(*l);
|
||||
assert(list_builder);
|
||||
|
||||
VALIDATE(list_builder->rows == 1, _("A 'list_definition' should contain one row."));
|
||||
|
||||
if(cfg.has_child("list_data")) {
|
||||
list_data = parse_list_data(cfg.child("list_data"), list_builder->cols);
|
||||
list_data = parse_list_data(cfg.mandatory_child("list_data"), list_builder->cols);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "gui/widgets/matrix.hpp"
|
||||
|
||||
#include "gettext.hpp"
|
||||
#include "gui/auxiliary/find_widget.hpp"
|
||||
#include "gui/auxiliary/iterator/walker.hpp"
|
||||
#include "gui/core/log.hpp"
|
||||
|
@ -184,11 +185,11 @@ matrix_definition::matrix_definition(const config& cfg)
|
|||
|
||||
matrix_definition::resolution::resolution(const config& cfg)
|
||||
: resolution_definition(cfg)
|
||||
, content(new builder_grid(cfg.child("content", "[matrix_definition]")))
|
||||
, content(new builder_grid(VALIDATE_WML_CHILD(cfg, "content", _("Missing [content] in [matrix_definition]"))))
|
||||
{
|
||||
// Note the order should be the same as the enum state_t in matrix.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.child("state_disabled"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_disabled"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
@ -206,22 +207,22 @@ builder_matrix::builder_matrix(const config& cfg)
|
|||
, builder_bottom(nullptr)
|
||||
, builder_left(nullptr)
|
||||
, builder_right(nullptr)
|
||||
, builder_main(create_widget_builder(cfg.child("main", "[matrix]")))
|
||||
, builder_main(create_widget_builder(VALIDATE_WML_CHILD(cfg, "main", _("Missing [main] in [matrix]"))))
|
||||
{
|
||||
if(const config& top = cfg.child("top")) {
|
||||
builder_top = std::make_shared<builder_grid>(top);
|
||||
if(auto top = cfg.optional_child("top")) {
|
||||
builder_top = std::make_shared<builder_grid>(*top);
|
||||
}
|
||||
|
||||
if(const config& bottom = cfg.child("bottom")) {
|
||||
builder_bottom = std::make_shared<builder_grid>(bottom);
|
||||
if(auto bottom = cfg.optional_child("bottom")) {
|
||||
builder_bottom = std::make_shared<builder_grid>(*bottom);
|
||||
}
|
||||
|
||||
if(const config& left = cfg.child("left")) {
|
||||
builder_left = std::make_shared<builder_grid>(left);
|
||||
if(auto left = cfg.optional_child("left")) {
|
||||
builder_left = std::make_shared<builder_grid>(*left);
|
||||
}
|
||||
|
||||
if(const config& right = cfg.child("right")) {
|
||||
builder_right = std::make_shared<builder_grid>(right);
|
||||
if(auto right = cfg.optional_child("right")) {
|
||||
builder_right = std::make_shared<builder_grid>(*right);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -229,10 +229,10 @@ menu_button_definition::resolution::resolution(const config& cfg)
|
|||
: resolution_definition(cfg)
|
||||
{
|
||||
// Note the order should be the same as the enum state_t in menu_button.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.child("state_disabled"));
|
||||
state.emplace_back(cfg.child("state_pressed"));
|
||||
state.emplace_back(cfg.child("state_focused"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_disabled"));
|
||||
state.emplace_back(cfg.optional_child("state_pressed"));
|
||||
state.emplace_back(cfg.optional_child("state_focused"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
|
|
@ -112,7 +112,7 @@ minimap_definition::resolution::resolution(const config& cfg)
|
|||
: resolution_definition(cfg)
|
||||
{
|
||||
// Note the order should be the same as the enum state_t in minimap.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
|
|
@ -172,10 +172,10 @@ multi_page_definition::multi_page_definition(const config& cfg)
|
|||
multi_page_definition::resolution::resolution(const config& cfg)
|
||||
: resolution_definition(cfg), grid(nullptr)
|
||||
{
|
||||
const config& child = cfg.child("grid");
|
||||
auto child = cfg.optional_child("grid");
|
||||
VALIDATE(child, _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<builder_grid>(child);
|
||||
grid = std::make_shared<builder_grid>(*child);
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
@ -195,13 +195,13 @@ builder_multi_page::builder_multi_page(const config& cfg)
|
|||
VALIDATE(!builders.empty(), _("No page defined."));
|
||||
|
||||
/** @todo This part is untested. */
|
||||
const config& d = cfg.child("page_data");
|
||||
auto d = cfg.optional_child("page_data");
|
||||
if(!d) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto builder = builders.begin()->second;
|
||||
for(const auto & row : d.child_range("row"))
|
||||
for(const auto & row : d->child_range("row"))
|
||||
{
|
||||
unsigned col = 0;
|
||||
|
||||
|
|
|
@ -252,10 +252,10 @@ multimenu_button_definition::resolution::resolution(const config& cfg)
|
|||
: resolution_definition(cfg)
|
||||
{
|
||||
// Note the order should be the same as the enum state_t in multimenu_button.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.child("state_disabled"));
|
||||
state.emplace_back(cfg.child("state_pressed"));
|
||||
state.emplace_back(cfg.child("state_focused"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_disabled"));
|
||||
state.emplace_back(cfg.optional_child("state_pressed"));
|
||||
state.emplace_back(cfg.optional_child("state_focused"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
|
|
@ -358,7 +358,7 @@ builder_pane::builder_pane(const config& cfg)
|
|||
: builder_widget(cfg)
|
||||
, grow_dir(*grow_direction::get_enum(cfg["grow_direction"].str()))
|
||||
, parallel_items(cfg["parallel_items"])
|
||||
, item_definition(new builder_grid(cfg.child("item_definition", "[pane]")))
|
||||
, item_definition(new builder_grid(VALIDATE_WML_CHILD(cfg, "item_definition", _("Missing [item_definition] in [pane]"))))
|
||||
{
|
||||
VALIDATE(parallel_items > 0, _("Need at least 1 parallel item."));
|
||||
}
|
||||
|
|
|
@ -108,8 +108,8 @@ panel_definition::resolution::resolution(const config& cfg)
|
|||
, right_border(cfg["right_border"])
|
||||
{
|
||||
// The panel needs to know the order.
|
||||
state.emplace_back(cfg.child("background"));
|
||||
state.emplace_back(cfg.child("foreground"));
|
||||
state.emplace_back(cfg.optional_child("background"));
|
||||
state.emplace_back(cfg.optional_child("foreground"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
@ -120,11 +120,11 @@ namespace implementation
|
|||
builder_panel::builder_panel(const config& cfg)
|
||||
: builder_styled_widget(cfg), grid(nullptr)
|
||||
{
|
||||
const config& c = cfg.child("grid");
|
||||
auto c = cfg.optional_child("grid");
|
||||
|
||||
VALIDATE(c, _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<builder_grid>(c);
|
||||
grid = std::make_shared<builder_grid>(*c);
|
||||
}
|
||||
|
||||
std::unique_ptr<widget> builder_panel::build() const
|
||||
|
|
|
@ -91,7 +91,7 @@ progress_bar_definition::resolution::resolution(const config& cfg)
|
|||
: resolution_definition(cfg)
|
||||
{
|
||||
// Note the order should be the same as the enum state_t in progress_bar.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
|
|
@ -179,10 +179,10 @@ repeating_button_definition::resolution::resolution(const config& cfg)
|
|||
{
|
||||
// Note the order should be the same as the enum state_t in
|
||||
// repeating_button.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.child("state_disabled"));
|
||||
state.emplace_back(cfg.child("state_pressed"));
|
||||
state.emplace_back(cfg.child("state_focused"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_disabled"));
|
||||
state.emplace_back(cfg.optional_child("state_pressed"));
|
||||
state.emplace_back(cfg.optional_child("state_focused"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
|
|
@ -176,13 +176,13 @@ scroll_label_definition::resolution::resolution(const config& cfg)
|
|||
: resolution_definition(cfg), grid(nullptr)
|
||||
{
|
||||
// Note the order should be the same as the enum state_t is scroll_label.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.child("state_disabled"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_disabled"));
|
||||
|
||||
const config& child = cfg.child("grid");
|
||||
auto child = cfg.optional_child("grid");
|
||||
VALIDATE(child, _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<builder_grid>(child);
|
||||
grid = std::make_shared<builder_grid>(*child);
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
|
|
@ -67,13 +67,13 @@ scrollbar_panel_definition::resolution::resolution(const config& cfg)
|
|||
: resolution_definition(cfg), grid()
|
||||
{
|
||||
// The panel needs to know the order.
|
||||
state.emplace_back(cfg.child("background"));
|
||||
state.emplace_back(cfg.child("foreground"));
|
||||
state.emplace_back(cfg.optional_child("background"));
|
||||
state.emplace_back(cfg.optional_child("foreground"));
|
||||
|
||||
const config& child = cfg.child("grid");
|
||||
auto child = cfg.optional_child("grid");
|
||||
VALIDATE(child, _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<builder_grid>(child);
|
||||
grid = std::make_shared<builder_grid>(*child);
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
@ -89,10 +89,10 @@ builder_scrollbar_panel::builder_scrollbar_panel(const config& cfg)
|
|||
get_scrollbar_mode(cfg["horizontal_scrollbar_mode"]))
|
||||
, grid_(nullptr)
|
||||
{
|
||||
const config& grid_definition = cfg.child("definition");
|
||||
auto grid_definition = cfg.optional_child("definition");
|
||||
|
||||
VALIDATE(grid_definition, _("No list defined."));
|
||||
grid_ = std::make_shared<builder_grid>(grid_definition);
|
||||
grid_ = std::make_shared<builder_grid>(*grid_definition);
|
||||
assert(grid_);
|
||||
}
|
||||
|
||||
|
|
|
@ -107,10 +107,10 @@ size_lock_definition::resolution::resolution(const config& cfg)
|
|||
static config dummy("draw");
|
||||
state.emplace_back(dummy);
|
||||
|
||||
const config& child = cfg.child("grid");
|
||||
auto child = cfg.optional_child("grid");
|
||||
VALIDATE(child, _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<builder_grid>(child);
|
||||
grid = std::make_shared<builder_grid>(*child);
|
||||
}
|
||||
|
||||
namespace implementation
|
||||
|
@ -122,7 +122,7 @@ builder_size_lock::builder_size_lock(const config& cfg)
|
|||
, content_(nullptr)
|
||||
{
|
||||
VALIDATE(cfg.has_child("widget"), _("No widget defined."));
|
||||
content_ = create_widget_builder(cfg.child("widget"));
|
||||
content_ = create_widget_builder(cfg.mandatory_child("widget"));
|
||||
}
|
||||
|
||||
std::unique_ptr<widget> builder_size_lock::build() const
|
||||
|
|
|
@ -310,10 +310,10 @@ slider_definition::resolution::resolution(const config& cfg)
|
|||
VALIDATE(positioner_length, missing_mandatory_wml_key("resolution", "minimum_positioner_length"));
|
||||
|
||||
// Note the order should be the same as the enum state_t is slider.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.child("state_disabled"));
|
||||
state.emplace_back(cfg.child("state_pressed"));
|
||||
state.emplace_back(cfg.child("state_focused"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_disabled"));
|
||||
state.emplace_back(cfg.optional_child("state_pressed"));
|
||||
state.emplace_back(cfg.optional_child("state_focused"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
@ -331,12 +331,12 @@ builder_slider::builder_slider(const config& cfg)
|
|||
, maximum_value_label_(cfg["maximum_value_label"].t_str())
|
||||
, value_labels_()
|
||||
{
|
||||
const config& labels = cfg.child("value_labels");
|
||||
auto labels = cfg.optional_child("value_labels");
|
||||
if(!labels) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(const auto& label : labels.child_range("value")) {
|
||||
for(const auto& label : labels->child_range("value")) {
|
||||
value_labels_.push_back(label["label"]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -221,10 +221,10 @@ stacked_widget_definition::resolution::resolution(const config& cfg)
|
|||
static config dummy("draw");
|
||||
state.emplace_back(dummy);
|
||||
|
||||
const config& child = cfg.child("grid");
|
||||
auto child = cfg.optional_child("grid");
|
||||
VALIDATE(child, _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<builder_grid>(child);
|
||||
grid = std::make_shared<builder_grid>(*child);
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
@ -235,7 +235,7 @@ namespace implementation
|
|||
builder_stacked_widget::builder_stacked_widget(const config& real_cfg)
|
||||
: builder_styled_widget(real_cfg), stack()
|
||||
{
|
||||
const config& cfg = real_cfg.has_child("stack") ? real_cfg.child("stack") : real_cfg;
|
||||
const config& cfg = real_cfg.has_child("stack") ? real_cfg.mandatory_child("stack") : real_cfg;
|
||||
if(&cfg != &real_cfg) {
|
||||
lg::log_to_chat() << "Stacked widgets no longer require a [stack] tag. Instead, place [layer] tags directly in the widget definition.\n";
|
||||
ERR_WML << "Stacked widgets no longer require a [stack] tag. Instead, place [layer] tags directly in the widget definition.";
|
||||
|
|
|
@ -273,8 +273,6 @@ void text_box::handle_mouse_selection(point mouse, const bool start_selection)
|
|||
|
||||
void text_box::update_offsets()
|
||||
{
|
||||
assert(config());
|
||||
|
||||
const auto conf = cast_config_to<text_box_definition>();
|
||||
assert(conf);
|
||||
|
||||
|
@ -408,10 +406,10 @@ text_box_definition::resolution::resolution(const config& cfg)
|
|||
, text_y_offset(cfg["text_y_offset"])
|
||||
{
|
||||
// Note the order should be the same as the enum state_t in text_box.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.child("state_disabled"));
|
||||
state.emplace_back(cfg.child("state_focused"));
|
||||
state.emplace_back(cfg.child("state_hovered"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_disabled"));
|
||||
state.emplace_back(cfg.optional_child("state_focused"));
|
||||
state.emplace_back(cfg.optional_child("state_hovered"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
|
|
@ -209,9 +209,9 @@ toggle_button_definition::resolution::resolution(const config& cfg)
|
|||
// toggle_button.hpp.
|
||||
for(const auto& c : cfg.child_range("state"))
|
||||
{
|
||||
state.emplace_back(c.child("enabled"));
|
||||
state.emplace_back(c.child("disabled"));
|
||||
state.emplace_back(c.child("focused"));
|
||||
state.emplace_back(c.optional_child("enabled"));
|
||||
state.emplace_back(c.optional_child("disabled"));
|
||||
state.emplace_back(c.optional_child("focused"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -299,9 +299,9 @@ toggle_panel_definition::resolution::resolution(const config& cfg)
|
|||
// Note the order should be the same as the enum state_t in toggle_panel.hpp.
|
||||
for(const auto& c : cfg.child_range("state"))
|
||||
{
|
||||
state.emplace_back(c.child("enabled"));
|
||||
state.emplace_back(c.child("disabled"));
|
||||
state.emplace_back(c.child("focused"));
|
||||
state.emplace_back(c.optional_child("enabled"));
|
||||
state.emplace_back(c.optional_child("disabled"));
|
||||
state.emplace_back(c.optional_child("focused"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,11 +316,11 @@ builder_toggle_panel::builder_toggle_panel(const config& cfg)
|
|||
, retval_id_(cfg["return_value_id"])
|
||||
, retval_(cfg["return_value"])
|
||||
{
|
||||
const config& c = cfg.child("grid");
|
||||
auto c = cfg.optional_child("grid");
|
||||
|
||||
VALIDATE(c, _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<builder_grid>(c);
|
||||
grid = std::make_shared<builder_grid>(*c);
|
||||
}
|
||||
|
||||
std::unique_ptr<widget> builder_toggle_panel::build() const
|
||||
|
|
|
@ -265,13 +265,13 @@ tree_view_definition::resolution::resolution(const config& cfg)
|
|||
, grid(nullptr)
|
||||
{
|
||||
// Note the order should be the same as the enum state_t is listbox.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.child("state_disabled"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_disabled"));
|
||||
|
||||
const config& child = cfg.child("grid");
|
||||
auto child = cfg.optional_child("grid");
|
||||
VALIDATE(child, _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<builder_grid>(child);
|
||||
grid = std::make_shared<builder_grid>(*child);
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
@ -326,11 +326,11 @@ tree_node::tree_node(const config& cfg)
|
|||
// TODO: interpolate this value into the error message
|
||||
VALIDATE(id != tree_view::root_node_id, _("[node]id 'root' is reserved for the implementation."));
|
||||
|
||||
const config& node_definition = cfg.child("node_definition");
|
||||
auto node_definition = cfg.optional_child("node_definition");
|
||||
|
||||
VALIDATE(node_definition, _("No node defined."));
|
||||
|
||||
builder = std::make_shared<builder_grid>(node_definition);
|
||||
builder = std::make_shared<builder_grid>(*node_definition);
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
|
|
|
@ -608,13 +608,13 @@ unit_preview_pane_definition::unit_preview_pane_definition(const config& cfg)
|
|||
unit_preview_pane_definition::resolution::resolution(const config& cfg)
|
||||
: resolution_definition(cfg), grid()
|
||||
{
|
||||
state.emplace_back(cfg.child("background"));
|
||||
state.emplace_back(cfg.child("foreground"));
|
||||
state.emplace_back(cfg.optional_child("background"));
|
||||
state.emplace_back(cfg.optional_child("foreground"));
|
||||
|
||||
const config& child = cfg.child("grid");
|
||||
auto child = cfg.optional_child("grid");
|
||||
VALIDATE(child, _("No grid defined."));
|
||||
|
||||
grid = std::make_shared<builder_grid>(child);
|
||||
grid = std::make_shared<builder_grid>(*child);
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
|
|
@ -119,10 +119,10 @@ vertical_scrollbar_definition::resolution::resolution(const config& cfg)
|
|||
"minimum_positioner_length"));
|
||||
|
||||
// Note the order should be the same as the enum state_t in scrollbar.hpp.
|
||||
state.emplace_back(cfg.child("state_enabled"));
|
||||
state.emplace_back(cfg.child("state_disabled"));
|
||||
state.emplace_back(cfg.child("state_pressed"));
|
||||
state.emplace_back(cfg.child("state_focused"));
|
||||
state.emplace_back(cfg.optional_child("state_enabled"));
|
||||
state.emplace_back(cfg.optional_child("state_disabled"));
|
||||
state.emplace_back(cfg.optional_child("state_pressed"));
|
||||
state.emplace_back(cfg.optional_child("state_focused"));
|
||||
}
|
||||
|
||||
// }---------- BUILDER -----------{
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
#include "gui/auxiliary/iterator/walker.hpp"
|
||||
#include "gui/core/log.hpp"
|
||||
#include "config.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "utils/const_clone.hpp"
|
||||
#include "wml_exception.hpp"
|
||||
|
||||
#define LOG_SCOPE_HEADER "viewport [" + id() + "] " + __func__
|
||||
#define LOG_HEADER LOG_SCOPE_HEADER + ':'
|
||||
|
@ -167,7 +169,7 @@ namespace implementation
|
|||
|
||||
builder_viewport::builder_viewport(const config& cfg)
|
||||
: builder_widget(cfg)
|
||||
, widget_(create_widget_builder(cfg.child("widget", "[viewport]")))
|
||||
, widget_(create_widget_builder(VALIDATE_WML_CHILD(cfg, "widget", _("Missing [widget] in [viewport]"))))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1308,12 +1308,12 @@ window_definition::window_definition(const config& cfg)
|
|||
window_definition::resolution::resolution(const config& cfg)
|
||||
: panel_definition::resolution(cfg), grid(nullptr)
|
||||
{
|
||||
const config& child = cfg.child("grid");
|
||||
auto child = cfg.optional_child("grid");
|
||||
// VALIDATE(child, _("No grid defined."));
|
||||
|
||||
/** @todo Evaluate whether the grid should become mandatory. */
|
||||
if(child) {
|
||||
grid = std::make_shared<builder_grid>(child);
|
||||
grid = std::make_shared<builder_grid>(*child);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ static bool is_cjk_char(const char32_t ch)
|
|||
|
||||
bool section_is_referenced(const std::string §ion_id, const config &cfg)
|
||||
{
|
||||
if (const config &toplevel = cfg.child("toplevel"))
|
||||
if (auto toplevel = cfg.optional_child("toplevel"))
|
||||
{
|
||||
const std::vector<std::string> toplevel_refs
|
||||
= utils::quoted_split(toplevel["sections"]);
|
||||
|
@ -174,7 +174,7 @@ bool section_is_referenced(const std::string §ion_id, const config &cfg)
|
|||
|
||||
bool topic_is_referenced(const std::string &topic_id, const config &cfg)
|
||||
{
|
||||
if (const config &toplevel = cfg.child("toplevel"))
|
||||
if (auto toplevel = cfg.optional_child("toplevel"))
|
||||
{
|
||||
const std::vector<std::string> toplevel_refs
|
||||
= utils::quoted_split(toplevel["topics"]);
|
||||
|
@ -218,10 +218,10 @@ void parse_config_internal(const config *help_cfg, const config *section_cfg,
|
|||
std::vector<std::string>::const_iterator it;
|
||||
// Find all child sections.
|
||||
for (it = sections.begin(); it != sections.end(); ++it) {
|
||||
if (const config &child_cfg = help_cfg->find_child("section", "id", *it))
|
||||
if (auto child_cfg = help_cfg->find_child("section", "id", *it))
|
||||
{
|
||||
section child_section;
|
||||
parse_config_internal(help_cfg, &child_cfg, child_section, level + 1);
|
||||
parse_config_internal(help_cfg, child_cfg.ptr(), child_section, level + 1);
|
||||
sec.add_section(child_section);
|
||||
}
|
||||
else {
|
||||
|
@ -263,7 +263,7 @@ void parse_config_internal(const config *help_cfg, const config *section_cfg,
|
|||
|
||||
// Find all topics in this section.
|
||||
for (it = topics_id.begin(); it != topics_id.end(); ++it) {
|
||||
if (const config &topic_cfg = help_cfg->find_child("topic", "id", *it))
|
||||
if (auto topic_cfg = help_cfg->find_child("topic", "id", *it))
|
||||
{
|
||||
std::string text = topic_cfg["text"];
|
||||
text += generate_topic_text(topic_cfg["generator"], help_cfg, sec, generated_topics);
|
||||
|
@ -304,8 +304,8 @@ section parse_config(const config *cfg)
|
|||
{
|
||||
section sec;
|
||||
if (cfg != nullptr) {
|
||||
const config& toplevel_cfg = cfg->child("toplevel");
|
||||
parse_config_internal(cfg, toplevel_cfg ? &toplevel_cfg : nullptr, sec);
|
||||
auto toplevel_cfg = cfg->optional_child("toplevel");
|
||||
parse_config_internal(cfg, toplevel_cfg.ptr(), sec);
|
||||
}
|
||||
return sec;
|
||||
}
|
||||
|
@ -483,7 +483,7 @@ std::vector<topic> generate_weapon_special_topics(const bool sort_generated)
|
|||
for(config adv : type.modification_advancements()) {
|
||||
for(config effect : adv.child_range("effect")) {
|
||||
if(effect["apply_to"] == "new_attack" && effect.has_child("specials")) {
|
||||
for(config::any_child spec : effect.child("specials").all_children_range()) {
|
||||
for(config::any_child spec : effect.mandatory_child("specials").all_children_range()) {
|
||||
if(!spec.cfg["name"].empty()) {
|
||||
special_description.emplace(spec.cfg["name"].t_str(), spec.cfg["description"].t_str());
|
||||
if(!type.hide_help()) {
|
||||
|
@ -500,7 +500,7 @@ std::vector<topic> generate_weapon_special_topics(const bool sort_generated)
|
|||
}
|
||||
}
|
||||
} else if(effect["apply_to"] == "attack" && effect.has_child("set_specials")) {
|
||||
for(config::any_child spec : effect.child("set_specials").all_children_range()) {
|
||||
for(config::any_child spec : effect.mandatory_child("set_specials").all_children_range()) {
|
||||
if(!spec.cfg["name"].empty()) {
|
||||
special_description.emplace(spec.cfg["name"].t_str(), spec.cfg["description"].t_str());
|
||||
if(!type.hide_help()) {
|
||||
|
@ -611,9 +611,9 @@ std::vector<topic> generate_era_topics(const bool sort_generated, const std::str
|
|||
{
|
||||
std::vector<topic> topics;
|
||||
|
||||
const config & era = game_cfg->find_child("era","id", era_id);
|
||||
auto era = game_cfg->find_child("era","id", era_id);
|
||||
if(era && !era["hide_help"].to_bool()) {
|
||||
topics = generate_faction_topics(era, sort_generated);
|
||||
topics = generate_faction_topics(*era, sort_generated);
|
||||
|
||||
std::vector<std::string> faction_links;
|
||||
for (const topic & t : topics) {
|
||||
|
@ -1200,7 +1200,7 @@ UNIT_DESCRIPTION_TYPE description_type(const unit_type &type)
|
|||
|
||||
std::string generate_contents_links(const std::string& section_name, config const *help_cfg)
|
||||
{
|
||||
const config& section_cfg = help_cfg->find_child("section", "id", section_name);
|
||||
auto section_cfg = help_cfg->find_child("section", "id", section_name);
|
||||
if (!section_cfg) {
|
||||
return std::string();
|
||||
}
|
||||
|
@ -1216,7 +1216,7 @@ std::string generate_contents_links(const std::string& section_name, config cons
|
|||
std::vector<std::string>::iterator t;
|
||||
// Find all topics in this section.
|
||||
for (t = topics.begin(); t != topics.end(); ++t) {
|
||||
if (const config& topic_cfg = help_cfg->find_child("topic", "id", *t)) {
|
||||
if (auto topic_cfg = help_cfg->find_child("topic", "id", *t)) {
|
||||
std::string id = topic_cfg["id"];
|
||||
if (is_visible_id(id))
|
||||
topics_links.emplace_back(topic_cfg["title"], id);
|
||||
|
|
|
@ -133,8 +133,8 @@ void help_text_area::set_items()
|
|||
read(cfg, stream);
|
||||
|
||||
#define TRY(name) do { \
|
||||
if (config &child = cfg.child(#name)) \
|
||||
handle_##name##_cfg(child); \
|
||||
if (auto child = cfg.optional_child(#name)) \
|
||||
handle_##name##_cfg(*child); \
|
||||
} while (0)
|
||||
|
||||
TRY(ref);
|
||||
|
|
|
@ -686,7 +686,7 @@ std::string unit_topic_generator::operator()() const {
|
|||
for (const config & t : traits) {
|
||||
if (t["availability"].str() == "musthave") {
|
||||
for (const config & effect : t.child_range("effect")) {
|
||||
if (!effect.child("filter") // If this is musthave but has a unit filter, it might not always apply, so don't apply it in the help.
|
||||
if (!effect.has_child("filter") // If this is musthave but has a unit filter, it might not always apply, so don't apply it in the help.
|
||||
&& movetype::effects.find(effect["apply_to"].str()) != movetype::effects.end()) {
|
||||
movement_type.merge(effect, effect["replace"].to_bool());
|
||||
}
|
||||
|
|
|
@ -1316,8 +1316,8 @@ protected:
|
|||
"whiteboard_options", &console_handler::do_whiteboard_options, _("Access whiteboard options dialog."));
|
||||
register_alias("whiteboard_options", "wbo");
|
||||
|
||||
if(const config& alias_list = preferences::get_alias()) {
|
||||
for(const config::attribute& a : alias_list.attribute_range()) {
|
||||
if(auto alias_list = preferences::get_alias()) {
|
||||
for(const config::attribute& a : alias_list->attribute_range()) {
|
||||
register_alias(a.second, a.first);
|
||||
}
|
||||
}
|
||||
|
@ -1817,7 +1817,7 @@ void console_handler::do_choose_level()
|
|||
// find scenarios of multiplayer campaigns
|
||||
// (assumes that scenarios are ordered properly in the game_config)
|
||||
std::string scenario_id = menu_handler_.pc_.get_mp_settings().mp_scenario;
|
||||
if(const config& this_scenario = menu_handler_.game_config_.find_child(tag, "id", scenario_id)) {
|
||||
if(auto this_scenario = menu_handler_.game_config_.find_child(tag, "id", scenario_id)) {
|
||||
std::string addon_id = this_scenario["addon_id"].str();
|
||||
for(const config& sc : menu_handler_.game_config_.child_range(tag)) {
|
||||
if(sc["addon_id"] == addon_id) {
|
||||
|
|
|
@ -276,7 +276,7 @@ const teleport_map get_teleport_locations(const unit &u,
|
|||
for (const unit_ability & teleport : u.get_abilities("teleport")) {
|
||||
const int tunnel_count = (teleport.ability_cfg)->child_count("tunnel");
|
||||
for(int i = 0; i < tunnel_count; ++i) {
|
||||
config teleport_group_cfg = (teleport.ability_cfg)->child("tunnel", i);
|
||||
config teleport_group_cfg = (teleport.ability_cfg)->mandatory_child("tunnel", i);
|
||||
groups.emplace_back(vconfig(teleport_group_cfg, true), false);
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +290,7 @@ const teleport_map get_teleport_locations(const unit &u,
|
|||
manager::manager(const config &cfg) : tunnels_(), id_(cfg["next_teleport_group_id"].to_int(0)) {
|
||||
const int tunnel_count = cfg.child_count("tunnel");
|
||||
for(int i = 0; i < tunnel_count; ++i) {
|
||||
const config& t = cfg.child("tunnel", i);
|
||||
const config& t = cfg.mandatory_child("tunnel", i);
|
||||
if(!t["saved"].to_bool()) {
|
||||
lg::log_to_chat() << "Do not use [tunnel] directly in a [scenario]. Use it in an [event] or [abilities] tag.\n";
|
||||
ERR_WML << "Do not use [tunnel] directly in a [scenario]. Use it in an [event] or [abilities] tag.";
|
||||
|
|
|
@ -70,7 +70,7 @@ bool persist_file_context::clear_var(const std::string &global, bool immediate)
|
|||
|
||||
bool ret = active->has_child("variables");
|
||||
if (ret) {
|
||||
config &cfg = active->child("variables");
|
||||
config &cfg = active->mandatory_child("variables");
|
||||
bool exists = cfg.has_attribute(global);
|
||||
if (!exists) {
|
||||
if (cfg.has_child(global)) {
|
||||
|
@ -100,7 +100,7 @@ bool persist_file_context::clear_var(const std::string &global, bool immediate)
|
|||
name_space prev = working.prev();
|
||||
active = get_node(cfg_, prev);
|
||||
active->clear_children(working.node_);
|
||||
if (active->has_child("variables") && active->child("variables").empty()) {
|
||||
if (active->has_child("variables") && active->mandatory_child("variables").empty()) {
|
||||
active->clear_children("variables");
|
||||
active->remove_attribute("variables");
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ bool persist_file_context::clear_var(const std::string &global, bool immediate)
|
|||
break;
|
||||
}
|
||||
active->clear_children(namespace_.node_);
|
||||
if (active->has_child("variables") && active->child("variables").empty()) {
|
||||
if (active->has_child("variables") && active->mandatory_child("variables").empty()) {
|
||||
active->clear_children("variables");
|
||||
active->remove_attribute("variables");
|
||||
}
|
||||
|
@ -163,11 +163,11 @@ config persist_file_context::get_var(const std::string &global) const
|
|||
config ret;
|
||||
const config *active = get_node(cfg_, namespace_);
|
||||
if (active && (active->has_child("variables"))) {
|
||||
const config &cfg = active->child("variables");
|
||||
const config &cfg = active->mandatory_child("variables");
|
||||
std::size_t arrsize = cfg.child_count(global);
|
||||
if (arrsize > 0) {
|
||||
for (std::size_t i = 0; i < arrsize; i++)
|
||||
ret.add_child(global,cfg.child(global,i));
|
||||
ret.add_child(global, cfg.mandatory_child(global,i));
|
||||
} else {
|
||||
ret = pack_scalar(global,cfg[global]);
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ protected:
|
|||
if (force)
|
||||
return get_node(cfg.child_or_add(next.root_), next, true);
|
||||
else if (cfg.has_child(next.root_))
|
||||
return get_node(cfg.child(next.root_), next);
|
||||
return get_node(cfg.mandatory_child(next.root_), next);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ protected:
|
|||
name_space next = ns.next();
|
||||
if (next) {
|
||||
if (cfg.has_child(next.root_))
|
||||
return get_node(cfg.child(next.root_), next);
|
||||
return get_node(cfg.mandatory_child(next.root_), next);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue