From d9c6d18a63fad6027a26d1790d946c46ea82f740 Mon Sep 17 00:00:00 2001 From: gfgtdf Date: Sat, 14 Jun 2014 02:00:25 +0200 Subject: [PATCH] fix [option]s/[events]s in [modification]s and [era] this was broken by a commite earlier by me. We now add them to teh scenario in saved_game.cpp and not in the mp code. The reason is that we stil want them to work if a mp campaign game was reloaded in sp. --- src/mp_game_utils.cpp | 40 +++++++------------ src/playcampaign.cpp | 11 ++++++ src/saved_game.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++ src/saved_game.hpp | 8 ++++ 4 files changed, 124 insertions(+), 26 deletions(-) diff --git a/src/mp_game_utils.cpp b/src/mp_game_utils.cpp index 2f3843fbf253..d1f894527023 100644 --- a/src/mp_game_utils.cpp +++ b/src/mp_game_utils.cpp @@ -58,9 +58,10 @@ static void add_multiplayer_classification(config& multiplayer, saved_game& stat config initial_level_config(saved_game& state) { const mp_game_settings& params = state.mp_settings(); - //Shall we do this here or in create_engine ? Idk so just call it twice. - state.expand_scenario(); - + //Also impliers state.expand_scenario() + state.expand_mp_events(); + state.expand_mp_options(); + config& scenario = state.get_starting_pos(); if(!state.mp_settings().saved_game) { @@ -71,10 +72,6 @@ config initial_level_config(saved_game& state) } scenario["turns"] = params.num_turns; - // Convert options to events - scenario.add_child_at("event", options::to_event(params.options.find_child( - "multiplayer", "id", params.mp_scenario)), 0); - if (params.random_start_time) { if (!tod_manager::is_start_ToD(scenario["random_start_time"])) @@ -100,14 +97,11 @@ config initial_level_config(saved_game& state) add_multiplayer_classification(level.child_or_add("multiplayer"), state); std::string era = params.mp_era; - if (params.saved_game) { - //if (const config &c = level.child("snapshot").child("era")) - // era = c["id"].str(); - if (const config &c = level.child("era")) - era = c["id"].str(); - } - //[era] as a toplevel tag ? fine for me. + //[multiplayer] mp_era= shoudl be psersistent over saves. + + //[era], [modification]s are toplevel tags here, they are not part of teh saved_game and only used during mp_connect/mp_wait // Initialize the list of sides available for the current era. + // We also need this no not get a segfault in mp_connect for ai configuation const config &era_cfg = resources::config_manager->game_config().find_child("era", "id", era); if (!era_cfg) { @@ -119,31 +113,25 @@ config initial_level_config(saved_game& state) } // FIXME: @todo We should tell user about missing era but still load game WRN_CF << "Missing era in MP load game " << era << std::endl; + //Otherwise we get an error when qwhen we try to add ai algirithms in moultiplayer_connect + level.add_child("era"); } else { - config& cfg = level.add_child("era", era_cfg); + /*config& cfg = */level.add_child("era", era_cfg); const config& custom_side = resources::config_manager-> game_config().find_child("multiplayer_side", "id", "Custom"); level.child("era").add_child_at("multiplayer_side", custom_side, 0); - // Convert options to event - cfg.add_child_at("event", options::to_event( - params.options.find_child("era", "id", era)), 0); } - - //TODO: move to saved_game. - // Add modifications + // Add modifications, needed for ai aglorithms which are applied in mp_connect + const std::vector& mods = params.active_mods; for (unsigned i = 0; i < mods.size(); i++) { - config& cfg = level.add_child("modification", + /*config& cfg = */level.add_child("modification", resources::config_manager-> game_config().find_child("modification", "id", mods[i])); - - // Convert options to event - cfg.add_child_at("event", options::to_event( - params.options.find_child("modification", "id", mods[i])), 0); } diff --git a/src/playcampaign.cpp b/src/playcampaign.cpp index 3fbe718c3bd6..11fd25e389fe 100644 --- a/src/playcampaign.cpp +++ b/src/playcampaign.cpp @@ -350,6 +350,10 @@ LEVEL_RESULT play_game(game_display& disp, saved_game& gamestate, generate_map(tmp); } + //In case this an mp scenario reloaded by sp this was not already done yet. + //We don't need to expand [option]s because [variables] are persitent + gamestate.expand_mp_events(); + sound::empty_playlist(); switch (io_type){ @@ -506,6 +510,13 @@ LEVEL_RESULT play_game(game_display& disp, saved_game& gamestate, generate_map(scenario); }*/ } + else if (io_type == IO_NONE && gamestate.valid()) + { + //In case this an mp scenario reloaded by sp this was not already done yet. + //We don't need to expand [option]s because [variables] are persitent + gamestate.expand_mp_events(); + + } } if(gamestate.valid()) { diff --git a/src/saved_game.cpp b/src/saved_game.cpp index cbba50b7e543..74d71b26f819 100644 --- a/src/saved_game.cpp +++ b/src/saved_game.cpp @@ -44,6 +44,8 @@ #include "serialization/binary_or_text.hpp" #include "util.hpp" +#include +#include #include #include @@ -219,6 +221,90 @@ void saved_game::expand_scenario() } } +//helper objects for saved_game::expand_mp_events() +struct modevents_entry +{ + modevents_entry(const std::string& _type, const std::string& _id) : type(_type), id(_id) {} + std::string type; + std::string id; +}; +struct modevents_entry_for +{ + //this typedef is used by boost. + typedef modevents_entry result_type; + modevents_entry_for(const std::string& type ) : type_(type) {} + modevents_entry operator()(const std::string& id) const + { + return modevents_entry(type_, id); + } +private: + std::string type_; +}; + +void saved_game::expand_mp_events() +{ + expand_scenario(); + if(this->starting_pos_type_ == STARTINGPOS_SCENARIO && !this->starting_pos_["has_mod_events"].to_bool(false)) + { + std::vector mods; + + boost::copy( mp_settings_.active_mods + | boost::adaptors::transformed(modevents_entry_for("modification")) + , std::back_inserter(mods) ); + if(mp_settings_.mp_era != "") //We don't want the error message below if there is no era (= if this is a sp game) + { mods.push_back(modevents_entry("era", mp_settings_.mp_era)); } + + BOOST_FOREACH(modevents_entry& mod, mods) + { + if(const config& cfg = resources::config_manager-> + game_config().find_child(mod.type, "id", mod.id)) + { + BOOST_FOREACH(const config& modevent, cfg.child_range("event")) + { + this->starting_pos_.add_child("event", modevent); + } + } + else + { + //TODO: A user message instead? + ERR_NG << "Couldn't find [" << mod.type<< "] with id=" << mod.id <starting_pos_["has_mod_events"] = true; + } +} + +void saved_game::expand_mp_options() +{ + if(this->starting_pos_type_ == STARTINGPOS_SCENARIO && !this->carryover_sides_start.empty()) + { + std::vector mods; + + boost::copy( mp_settings_.active_mods + | boost::adaptors::transformed(modevents_entry_for("modification")) + , std::back_inserter(mods) ); + mods.push_back(modevents_entry("era", mp_settings_.mp_era)); + mods.push_back(modevents_entry("multiplayer", get_scenario_id())); + + config& variables = this->carryover_sides_start.child_or_add("variables"); + BOOST_FOREACH(modevents_entry& mod, mods) + { + if(const config& cfg = this->mp_settings().options.find_child(mod.type, "id", mod.id)) + { + BOOST_FOREACH(const config& option, cfg.child_range("option")) + { + variables[option["id"]] = option["value"]; + } + } + else + { + LOG_NG << "Couldn't find [" << mod.type<< "] with id=" << mod.id << " for [option]s" << std::endl; + } + } + } +} + void saved_game::expand_carryover() { expand_scenario(); @@ -253,6 +339,11 @@ void saved_game::set_scenario(const config& scenario) { this->starting_pos_type_ = STARTINGPOS_SCENARIO; this->starting_pos_ = scenario; + //By default we treat the game as 'carryover not expanded yet' + if(this->carryover_sides.empty()) + { + this->carryover_sides_start.child_or_add("variables"); + } } void saved_game::remove_snapshot() diff --git a/src/saved_game.hpp b/src/saved_game.hpp index 43a522510346..7abf26391888 100644 --- a/src/saved_game.hpp +++ b/src/saved_game.hpp @@ -43,6 +43,14 @@ class saved_game ///merges [carryover_sides_start] into [scenario] and saves the rest into [carryover_sides] ///Removes [carryover_sides_start] afterwards void expand_carryover(); + /// adds [event]s from [era] and [modification] into this scenario + /// does NOT expand [option]s because variables are persitent anyway to we don't need it + /// should be called after expand_scenario() but before expand_carryover() + void expand_mp_events(); + /// adds values of [option]s inte [carryover_sides_start][variables] so that they are applied in the next level. + /// Note that since [variabels] are persistent we only use this once at the beginning + /// of a campaign but callings it multiple times is no harm eigher + void expand_mp_options(); bool valid(); void set_snapshot(const config& snapshot); void set_scenario(const config& scenario);