The Battle for Wesnoth  1.17.0-dev
mp_game_utils.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2013 - 2021
3  by Andrius Silinskas <silinskas.andrius@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
17 
18 #include "config.hpp"
19 #include "formula/string_utils.hpp"
20 #include "game_config_manager.hpp"
21 #include "gettext.hpp"
22 #include "log.hpp"
23 #include "saved_game.hpp"
24 
25 static lg::log_domain log_engine("engine");
26 #define LOG_NG LOG_STREAM(info, log_engine)
27 #define ERR_NG LOG_STREAM(err, log_engine)
28 
29 static lg::log_domain log_config("config");
30 #define LOG_CF LOG_STREAM(info, log_config)
31 #define WRN_CF LOG_STREAM(warn, log_config)
32 #define ERR_CF LOG_STREAM(err, log_config)
33 
34 static lg::log_domain log_network("network");
35 #define LOG_NW LOG_STREAM(info, log_network)
36 #define ERR_NW LOG_STREAM(err, log_network)
37 
38 namespace mp
39 {
40 // This is for the wesnothd server, it expects a more detailed summary in [multiplayer]
41 static void add_multiplayer_classification(config& multiplayer, saved_game& state)
42 {
43  multiplayer["mp_scenario"] = state.get_scenario_id();
44  multiplayer["mp_scenario_name"] = state.get_starting_point()["name"];
45  multiplayer["difficulty_define"] = state.classification().difficulty;
46  multiplayer["mp_campaign"] = state.classification().campaign;
47  multiplayer["mp_campaign_name"] = state.classification().campaign_name;
48  multiplayer["mp_era"] = state.classification().era_id;
49  multiplayer["active_mods"] = utils::join(state.classification().active_mods, ",");
50 }
51 
53 {
54  const mp_game_settings& params = state.mp_settings();
55  state.set_defaults();
56 
57  // Also impliers state.expand_scenario()
58  // We need to call this before expand_mp_events/options otherwise they might be overwritten.
59  state.expand_random_scenario();
60  state.expand_mp_events();
61  state.expand_mp_options();
62 
63  if(!state.valid()) {
64  throw config::error("Failed to load the scenario");
65  }
66 
67  config& scenario = state.get_starting_point();
68  if(state.mp_settings().saved_game == mp_game_settings::SAVED_GAME_MODE::NONE) {
69  state.set_random_seed();
70  }
71 
72  if(scenario["objectives"].empty()) {
73  // Generic victory objectives.
74  std::ostringstream ss;
75  ss << "<big>";
76  ss << t_string(N_("Victory:"), "wesnoth") << "</big>\n";
77  ss << "<span color='#00ff00'>" << font::unicode_bullet << " ";
78  ss << t_string(N_("Defeat enemy leader(s)"), "wesnoth") << "</span>";
79 
80  scenario["objectives"] = ss.str();
81  }
82 
83  config level = state.to_config();
84  add_multiplayer_classification(level.child_or_add("multiplayer"), state);
85 
86  // [multiplayer] mp_era= should be persistent over saves.
87  std::string era = state.classification().era_id;
88 
89  /**
90  * [era] and [modification]s are toplevel tags here.
91  * They are not part of the saved_game and are only used during mp_staging/mp_join_game.
92  *
93  * @todo: see if all the comments ai algorithms are still up-to-date and relevant.
94  *
95  * -- vultraz, 2017-11-24
96  */
97 
99  const config& era_cfg = game_config.find_child("era", "id", era);
100 
101  if(!era_cfg) {
102  if(params.saved_game == mp_game_settings::SAVED_GAME_MODE::NONE) {
103  throw config::error(VGETTEXT("Cannot find era '$era'", {{"era", era}}));
104  }
105 
106  // FIXME: @todo We should tell user about missing era but still load game...
107  WRN_CF << "Missing era in MP load game '" << era << "'" << std::endl;
108 
109  } else {
110  level.add_child("era", era_cfg);
111 
112  // Initialize the list of sides available for the current era.
113  // We also need this so not to get a segfault in mp_staging for ai configuration.
114  const config& custom_side = game_config.find_child("multiplayer_side", "id", "Custom");
115  level.child("era").add_child_at("multiplayer_side", custom_side, 0);
116  }
117 
118  // Add modifications, needed for ai algorithms which are applied in mp_staging.
119  const std::vector<std::string>& mods = state.classification().active_mods;
120 
121  for(unsigned i = 0; i < mods.size(); ++i) {
122  if(const config& mod_cfg = game_config.find_child("modification", "id", mods[i])) {
123  level.add_child("modification", mod_cfg);
124  }
125  }
126 
127  // This will force connecting clients to be using the same version number as us.
128  level["version"] = game_config::wesnoth_version.str();
129  return level;
130 }
131 
133 {
134  game_classification::CAMPAIGN_TYPE type = state.classification().campaign_type;
135  state = saved_game(level);
136  state.classification().campaign_type = type;
137 }
138 
139 } // end namespace mp
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:402
std::string era()
Definition: game.cpp:695
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
static lg::log_domain log_config("config")
void set_defaults()
does some post loading stuff must be used before passing the data to connect_engine ...
Definition: saved_game.cpp:216
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:40
config initial_level_config(saved_game &state)
void expand_random_scenario()
takes care of generate_map=, generate_scenario=, map= attributes This should be called before expandi...
Definition: saved_game.cpp:476
std::string campaign_name
The name of the campaign being played.
bool valid() const
Definition: saved_game.cpp:553
config & child_or_add(config_key_type key)
Returns a reference to the first child with the given key.
Definition: config.cpp:478
void level_to_gamestate(const config &level, saved_game &state)
Definitions for the interface to Wesnoth Markup Language (WML).
#define WRN_CF
std::string get_scenario_id() const
Definition: saved_game.cpp:648
Main entry points of multiplayer mode.
Definition: lobby_data.cpp:52
static game_config_manager * get()
void set_random_seed()
sets the random seed if that didn&#39;t already happen.
Definition: saved_game.cpp:167
std::vector< std::string > active_mods
void expand_mp_options()
adds values of [option]s into [carryover_sides_start][variables] so that they are applied in the next...
Definition: saved_game.cpp:412
config & add_child_at(config_key_type key, const config &val, unsigned index)
Definition: config.cpp:546
const game_config_view & game_config() const
config & get_starting_point()
Definition: saved_game.cpp:582
std::string campaign
The id of the campaign being played.
std::size_t i
Definition: function.cpp:967
Default, unset return value.
Definition: retval.hpp:32
Game configuration data as global variables.
Definition: build_info.cpp:59
void expand_mp_events()
adds [event]s from [era] and [modification] into this scenario does NOT expand [option]s because vari...
Definition: saved_game.cpp:371
#define N_(String)
Definition: gettext.hpp:101
const std::string unicode_bullet
Definition: constants.cpp:47
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
const version_info wesnoth_version(VERSION)
config & add_child(config_key_type key)
Definition: config.cpp:514
const config & find_child(config_key_type key, const std::string &name, const std::string &value) const
std::string difficulty
The difficulty level the game is being played on.
game_classification & classification()
Definition: saved_game.hpp:55
Standard logging facilities (interface).
std::string str() const
Serializes the version number into string form.
config to_config() const
Definition: saved_game.cpp:625
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:61
mp_game_settings & mp_settings()
Multiplayer parameters for this game.
Definition: saved_game.hpp:59
static lg::log_domain log_network("network")
static lg::log_domain log_engine("engine")
static void add_multiplayer_classification(config &multiplayer, saved_game &state)