1 /* 2 Copyright (C) 2013 - 2018 by Andrius Silinskas <silinskas.andrius@gmail.com> 3 Part of the Battle for Wesnoth Project https://www.wesnoth.org/ 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY. 11 12 See the COPYING file for more details. 13 */ 14 15 #pragma once 16 17 #include "commandline_options.hpp" 18 #include "config.hpp" 19 #include "flg_manager.hpp" 20 #include "saved_game.hpp" 21 #include <set> 22 23 namespace randomness { class mt_rng; } 24 struct mp_campaign_info; 25 26 namespace ng { 27 28 enum controller { 29 CNTR_NETWORK = 0, 30 CNTR_LOCAL, 31 CNTR_COMPUTER, 32 CNTR_EMPTY, 33 CNTR_RESERVED, 34 }; 35 36 class connect_engine; 37 class side_engine; 38 39 typedef const std::unique_ptr<connect_engine> connect_engine_ptr; 40 typedef std::shared_ptr<side_engine> side_engine_ptr; 41 typedef std::pair<ng::controller, std::string> controller_option; 42 43 class connect_engine 44 { 45 public: 46 connect_engine(saved_game& state, 47 const bool first_scenario, mp_campaign_info* campaign_info); 48 49 config* current_config(); 50 51 void import_user(const std::string& name, const bool observer, 52 int side_taken = -1); 53 void import_user(const config& data, const bool observer, 54 int side_taken = -1); 55 56 // Returns true if there are still sides available for this game. 57 bool sides_available() const; 58 59 // Import all sides into the level. 60 void update_level(); 61 // Updates the level and sends a diff to the clients. 62 void update_and_send_diff(bool update_time_of_day = false); 63 64 bool can_start_game() const; 65 void start_game(); 66 void start_game_commandline(const commandline_options& cmdline_opts, const config& game_config); 67 68 void leave_game(); 69 70 // Return pair first element specifies whether to leave the game 71 // and second element whether to silently update UI. 72 std::pair<bool, bool> process_network_data(const config& data); 73 74 // Returns the side which is taken by a given user, 75 // or -1 if none was found. 76 int find_user_side_index_by_id(const std::string& id) const; 77 78 79 /* Setters & Getters */ 80 level() const81 const config& level() const { return level_; } scenario()82 config& scenario() 83 { 84 if(config& scenario = level_.child("scenario")) 85 return scenario; 86 else if(config& snapshot = level_.child("snapshot")) 87 return snapshot; 88 else 89 throw "No scenariodata found"; 90 } 91 const std::set<std::string>& connected_users() const; 92 93 struct team_data_pod 94 { 95 std::string team_name; 96 std::string user_team_name; // TODO: use t_string? 97 98 bool is_player_team; 99 }; 100 team_data() const101 const std::vector<team_data_pod>& team_data() const 102 { 103 return team_data_; 104 } 105 side_engines()106 std::vector<side_engine_ptr>& side_engines() { return side_engines_; } params() const107 const mp_game_settings& params() const { return params_; } first_scenario() const108 bool first_scenario() const { return first_scenario_; } force_lock_settings() const109 bool force_lock_settings() const { return force_lock_settings_; } 110 111 bool receive_from_server(config& dst) const; 112 campaign_info() const113 const mp_campaign_info* campaign_info() const 114 { 115 return campaign_info_; 116 } 117 118 private: 119 connect_engine(const connect_engine&) = delete; 120 void operator=(const connect_engine&) = delete; 121 122 void send_level_data() const; 123 124 void save_reserved_sides_information(); 125 void load_previous_sides_users(); 126 127 void update_side_controller_options(); 128 129 friend class side_engine; 130 131 config level_; 132 saved_game& state_; 133 134 const mp_game_settings& params_; 135 136 const ng::controller default_controller_; 137 mp_campaign_info* campaign_info_; 138 const bool first_scenario_; 139 140 bool force_lock_settings_; 141 142 std::vector<side_engine_ptr> side_engines_; 143 std::vector<const config*> era_factions_; 144 std::vector<team_data_pod> team_data_; 145 146 std::set<std::string>& connected_users_rw(); 147 void send_to_server(const config& cfg) const; 148 }; 149 150 class side_engine 151 { 152 public: 153 side_engine(const config& cfg, connect_engine& parent_engine, 154 const int index); 155 156 // An untranslated user_description which is used by other clients 157 // An empty string means the other clients should generate the description on their own 158 // Used by new_config(). 159 std::string user_description() const; 160 161 // Creates a config representing this side. 162 config new_config() const; 163 164 // Returns true, if the player has chosen his/her leader and this side 165 // is ready for the game to start. 166 bool ready_for_start() const; 167 // Returns true if this side is waiting for a network player and 168 // players are allowed. 169 bool available_for_user(const std::string& name = "") const; 170 171 void resolve_random( randomness::mt_rng & rng, const std::vector<std::string> & avoid_faction_ids = std::vector<std::string>()); 172 173 // Resets this side to its default state. 174 void reset(); 175 176 // Place user into this side. 177 void place_user(const std::string& name); 178 void place_user(const config& data, bool contains_selection = false); 179 180 void update_controller_options(); 181 void update_current_controller_index(); 182 bool controller_changed(const int selection); 183 void set_controller(ng::controller controller); 184 185 // Game set up from command line helpers. 186 void set_faction_commandline(const std::string& faction_name); 187 void set_controller_commandline(const std::string& controller_name); 188 189 /* Setters & Getters */ 190 save_id() const191 std::string save_id() const 192 { return (!cfg_["save_id"].empty()) ? cfg_["save_id"] : cfg_["id"]; } 193 // The id of the side of the previous scenario that should control this side. previous_save_id() const194 std::string previous_save_id() const 195 { return (!cfg_["previous_save_id"].empty()) ? cfg_["previous_save_id"] : save_id(); } controller_options() const196 const std::vector<controller_option>& controller_options() const 197 { return controller_options_; } cfg() const198 const config& cfg() const { return cfg_; } controller() const199 ng::controller controller() const { return controller_; } current_controller_index() const200 unsigned current_controller_index() const 201 { return current_controller_index_; } index() const202 int index() const { return index_; } set_index(int index)203 void set_index(int index) { index_ = index; } team() const204 unsigned team() const { return team_; } set_team(unsigned team)205 void set_team(unsigned team) { team_ = team; } 206 std::vector<std::string> get_children_to_swap(); 207 std::multimap<std::string, config> get_side_children(); 208 void set_side_children(std::multimap<std::string, config> children); color() const209 int color() const { return color_; } set_color(int color)210 void set_color(int color) { color_ = color; color_id_ = color_options_[color]; } gold() const211 int gold() const { return gold_; } set_gold(int gold)212 void set_gold(int gold) { gold_ = gold; } income() const213 int income() const { return income_; } set_income(int income)214 void set_income(int income) { income_ = income; } player_id() const215 const std::string& player_id() const { return player_id_; } reserved_for() const216 const std::string& reserved_for() const { return reserved_for_; } set_reserved_for(const std::string & reserved_for)217 void set_reserved_for(const std::string& reserved_for) 218 { reserved_for_ = reserved_for; } ai_algorithm() const219 const std::string& ai_algorithm() const { return ai_algorithm_; } set_ai_algorithm(const std::string & ai_algorithm)220 void set_ai_algorithm(const std::string& ai_algorithm) 221 { ai_algorithm_ = ai_algorithm; } allow_player() const222 bool allow_player() const { return allow_player_; } allow_changes() const223 bool allow_changes() const { return allow_changes_; } waiting_to_choose_faction() const224 bool waiting_to_choose_faction() const { return waiting_to_choose_faction_; } set_waiting_to_choose_status(bool status)225 void set_waiting_to_choose_status(bool status) { waiting_to_choose_faction_ = status;} allow_shuffle() const226 bool allow_shuffle() const { return !disallow_shuffle_;} flg()227 flg_manager& flg() { return flg_; } 228 color_id() const229 const std::string color_id() const { return color_id_; } color_options() const230 const std::vector<std::string>& color_options() const { return color_options_; } 231 team_name() const232 const std::string team_name() const 233 { 234 return parent_.team_data_[team_].team_name; 235 } 236 user_team_name() const237 const std::string user_team_name() const 238 { 239 return t_string::from_serialized(parent_.team_data_[team_].user_team_name); 240 } 241 242 private: 243 side_engine(const side_engine& engine) = delete; 244 void operator=(const side_engine&) = delete; 245 246 void add_controller_option(ng::controller controller, 247 const std::string& name, const std::string& controller_value); 248 249 config cfg_; 250 connect_engine& parent_; 251 252 ng::controller controller_; 253 unsigned current_controller_index_; 254 std::vector<controller_option> controller_options_; 255 256 const bool allow_player_; 257 const bool controller_lock_; 258 259 int index_; 260 unsigned team_; 261 int color_; 262 int gold_; 263 int income_; 264 // set during create_engines constructor never set after that. 265 // the name of the player who is preferred for this side, 266 // if controller_ == reserved only this player can take this side. 267 // can also be a number of a side if this side should be controlled 268 // by the player who controls that side 269 std::string reserved_for_; 270 std::string player_id_; 271 std::string ai_algorithm_; 272 273 bool chose_random_; 274 bool disallow_shuffle_; 275 flg_manager flg_; 276 const bool allow_changes_; 277 bool waiting_to_choose_faction_; 278 279 std::vector<std::string> color_options_; 280 281 std::string color_id_; 282 }; 283 284 } // end namespace ng 285