The Battle for Wesnoth  1.19.5+dev
play_controller.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006 - 2024
3  by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
4  Copyright (C) 2003 by David White <dave@whitevine.net>
5  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY.
13 
14  See the COPYING file for more details.
15 */
16 
17 #pragma once
18 
19 #include "controller_base.hpp"
20 #include "game_end_exceptions.hpp"
21 #include "help/help.hpp"
23 #include "menu_events.hpp"
24 #include "mouse_events.hpp"
25 #include "persist_manager.hpp"
26 #include "tod_manager.hpp"
27 #include "game_state.hpp"
28 #include "utils/optimer.hpp"
29 #include "utils/optional_fwd.hpp"
30 
31 #include <set>
32 
33 class team;
34 class replay;
35 class replay_controller;
36 class saved_game;
37 struct mp_game_settings;
40 
41 namespace actions {
42  class undo_list;
43 }
44 
45 namespace font {
46  struct floating_label_context;
47 }
48 
49 namespace game_events {
50  class wml_event_pump;
51 } // namespace game_events
52 
53 class statistics_t;
54 
55 namespace wb {
56  class manager; // whiteboard manager
57 } // namespace wb
58 
59 // Holds gamestate related objects
60 
62 {
63 public:
65  saved_game& state_of_game);
66  virtual ~play_controller();
67 
68  //event handler, overridden from observer
69  //there is nothing to handle in this class actually but that might change in the future
70  virtual void handle_generic_event(const std::string& /*name*/) override {}
71 
72  bool can_undo() const;
73  bool can_redo() const;
74 
75  void undo();
76  void redo();
77 
78  void load_game();
79 
80  void save_game();
81  void save_game_auto(const std::string& filename);
82  void save_replay();
83  void save_replay_auto(const std::string& filename);
84  void save_map();
85  replay& get_replay();
86 
87  void init_side_begin();
88 
89  /**
90  * Called by turn_info::process_network_data() or init_side() to call do_init_side() if necessary.
91  */
92  void maybe_do_init_side();
93 
94  /**
95  * Called by replay handler or init_side() to do actual work for turn change.
96  */
97  void do_init_side();
98 
99  void init_side_end();
100 
101  virtual void force_end_turn() = 0;
102  virtual void check_objectives() = 0;
103 
104  virtual void on_not_observer() = 0;
105 
106  /**
107  * Asks the user whether to continue on an OOS error.
108  *
109  * @throw quit_game_exception If the user wants to abort.
110  */
111  virtual void process_oos(const std::string& msg) const;
112 
113  bool reveal_map_default() const;
114 
116  {
118  }
119 
121  {
122  gamestate().end_level_data_.reset();
123  }
124 
125  bool is_regular_game_end() const
126  {
127  return gamestate().end_level_data_.has_value();
128  }
129 
131  {
132  return *gamestate().end_level_data_;
133  }
134 
135  std::vector<team>& get_teams()
136  {
137  return gamestate().board_.teams();
138  }
139 
140  const std::vector<team>& get_teams() const
141  {
142  return gamestate().board_.teams();
143  }
144 
145  const unit_map& get_units() const
146  {
147  return gamestate().board_.units();
148  }
149 
151  {
152  return gamestate().board_.units();
153  }
154 
155  const gamemap& get_map() const
156  {
157  return gamestate().board_.map();
158  }
159 
161  {
162  return gamestate().tod_manager_;
163  }
164 
165  bool is_observer() const
166  {
167  return gamestate().board_.is_observer();
168  }
169 
170  bool do_healing() const
171  {
172  return gamestate().do_healing_;
173  }
174 
176  {
178  }
179 
181  {
182  return *gamestate_;
183  }
184 
185  const game_state& gamestate() const
186  {
187  return *gamestate_;
188  }
189 
190  /**
191  * Checks to see if a side has won.
192  *
193  * This will also remove control of villages from sides with dead leaders.
194  */
195  void check_victory();
196 
197  std::size_t turn() const {return gamestate().tod_manager_.turn();}
198 
199  /**
200  * Returns the number of the side whose turn it is.
201  *
202  * Numbering starts at one.
203  */
204  int current_side() const { return gamestate_->player_number_; }
205 
206  /**
207  * Builds the snapshot config from members and their respective configs.
208  */
209  config to_config() const;
210 
211  bool is_skipping_replay() const { return skip_replay_; }
212  bool is_skipping_actions() const;
213  void toggle_skipping_replay();
214  void do_autosave();
215 
216  bool is_skipping_story() const { return skip_story_; }
217 
218  void do_consolesave(const std::string& filename);
219 
222 
223  std::shared_ptr<wb::manager> get_whiteboard() const;
228 
230 
231  virtual soundsource::manager* get_soundsource_man() override;
232  virtual plugins_context* get_plugins_context() override;
234 
236 
237  bool is_browsing() const override;
238 
239  class hotkey_handler;
240 
241  virtual replay_controller * get_replay_controller() const { return nullptr; }
242  bool is_replay() const { return get_replay_controller() != nullptr; }
243 
244  replay& recorder() const { return *replay_; }
245 
247  {
248  return level_["name"].t_str();
249  }
250 
251  bool get_disallow_recall() const
252  {
253  return level_["disallow_recall"].to_bool();
254  }
255 
256  std::string get_loaded_resources() const
257  {
258  return level_["loaded_resources"].str();
259  }
260 
261  std::string theme() const
262  {
263  return gamestate_->get_game_data()->get_theme();
264  }
265 
266  virtual bool should_return_to_play_side() const
267  {
268  return is_regular_game_end();
269  }
270 
271  void maybe_throw_return_to_play_side() const;
272 
273  team& current_team();
274  const team& current_team() const;
275 
276  bool can_use_synced_wml_menu() const;
277  std::set<std::string> all_players() const;
278  const auto& timer() const { return timer_; }
279  game_display& get_display() override;
280 
281  void update_savegame_snapshot() const;
282  /**
283  * Changes the UI for this client to the passed side index.
284  */
285  void update_gui_to_player(const int team_index, const bool observe = false);
286 
287  /// Sends replay [command]s to the server
288  virtual void send_actions() { }
289  /// Reads and executes replay [command]s from the server
290  virtual void receive_actions() { }
291 
292  virtual bool is_networked_mp() const { return false; }
293  virtual void send_to_wesnothd(const config&, const std::string& = "unknown") const { }
294  virtual bool receive_from_wesnothd(config&) const { return false; }
295  /** Reevaluate [show_if] conditions and build a new objectives string. */
296  void refresh_objectives() const;
297  void show_objectives() const;
298 
300  {
304  };
305 
307 
309  bool is_during_turn() const;
310  bool is_linger_mode() const;
311 
312 protected:
314  void play_slice_catch();
315  bool have_keyboard_focus() override;
316  void process_focus_keydown_event(const SDL_Event& event) override;
317  void process_keydown_event(const SDL_Event& event) override;
318  void process_keyup_event(const SDL_Event& event) override;
319 
320  void init_managers();
321  /** preload events cannot be synced */
322  void fire_preload();
323  void fire_prestart();
324  void fire_start();
325  void start_game();
326  virtual void init_gui();
328  void finish_turn(); //this should not throw an end turn or end level exception
329  bool enemies_visible() const;
330 
331  void enter_textbox();
332  void textbox_move_vertically(bool up);
333  void tab();
334 
335 public:
336  /** returns 0 if no such team was found. */
337  virtual int find_viewing_side() const = 0;
338 private:
340 
341 protected:
342  //gamestate
343  std::unique_ptr<game_state> gamestate_;
346 
347  //managers
349 
350  //whiteboard manager
351  std::shared_ptr<wb::manager> whiteboard_manager_;
352 
353  //plugins context
354  std::unique_ptr<plugins_context> plugins_context_;
355 
356  //more managers
357  std::unique_ptr<font::floating_label_context> labels_manager_;
361  std::unique_ptr<hotkey_handler> hotkey_handler_;
362  std::unique_ptr<soundsource::manager> soundsources_manager_;
364 
365  //other objects
366  std::unique_ptr<game_display> gui_;
367  const std::unique_ptr<unit_experience_accelerator> xp_mod_;
368  const std::unique_ptr<statistics_t> statistics_context_;
370  const actions::undo_list& undo_stack() const { return *gamestate().undo_stack_; }
371  std::unique_ptr<replay> replay_;
372 
375  /**
376  * Whether we did init sides in this session
377  * (false = we did init sides before we reloaded the game).
378  */
381  //the displayed location when we load a game.
383  // Whether to start with the display faded to black
385 
386  const std::string& select_music(bool victory) const;
387 
388  void reset_gamestate(const config& level, int replay_pos);
389 
390 private:
391 
392  void init(const config& level);
393 
394  /**
395  * This shows a warning dialog if either [scenario]next_scenario or any [endlevel]next_scenario would lead to an "Unknown Scenario" dialog.
396  */
398 
399  std::vector<std::string> victory_music_;
400  std::vector<std::string> defeat_music_;
401 
403 
404 protected:
405  mutable bool ignore_replay_errors_;
406  /// true when the controller of the currently playing side has changed.
407  /// this can mean for example:
408  /// - The currently active side was reassigned from/to another player in a mp game
409  /// - The replay controller was disabled ('continue play' button)
410  /// - The currently active side was droided / undroided.
411  /// - A side was set to idle.
413  virtual void sync_end_turn() {}
414  virtual void check_time_over();
415  virtual void update_viewing_player() = 0;
416 };
Class to store the actions that a player can undo and redo.
Definition: undo.hpp:34
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:172
bool is_observer() const
Check if we are an observer in this game.
virtual const std::vector< team > & teams() const override
Definition: game_board.hpp:80
virtual const unit_map & units() const override
Definition: game_board.hpp:107
virtual const gamemap & map() const override
Definition: game_board.hpp:97
utils::optional< end_level_data > end_level_data_
Definition: game_state.hpp:64
int server_request_number_
Definition: game_state.hpp:66
const std::unique_ptr< actions::undo_list > undo_stack_
undo_stack_ is never nullptr.
Definition: game_state.hpp:56
bool do_healing_
True if healing should be done at the beginning of the next side turn.
Definition: game_state.hpp:60
game_board board_
Definition: game_state.hpp:44
tod_manager tod_manager_
Definition: game_state.hpp:45
Encapsulates the map of the game.
Definition: map.hpp:172
unit_map & get_units()
game_classification & get_classification()
const std::string & select_music(bool victory) const
virtual void handle_generic_event(const std::string &) override
void process_keydown_event(const SDL_Event &event) override
Process keydown (always).
events::menu_handler & get_menu_handler()
void maybe_throw_return_to_play_side() const
config to_config() const
Builds the snapshot config from members and their respective configs.
virtual void on_not_observer()=0
void init(const config &level)
const std::vector< team > & get_teams() const
virtual bool receive_from_wesnothd(config &) const
int get_server_request_number() const
std::vector< team > & get_teams()
std::unique_ptr< hotkey_handler > hotkey_handler_
virtual void init_gui()
virtual replay_controller * get_replay_controller() const
bool have_keyboard_focus() override
Derived classes should override this to return false when arrow keys should not scroll the map,...
std::unique_ptr< game_state > gamestate_
void show_objectives() const
events::menu_handler menu_handler_
void fire_preload()
preload events cannot be synced
std::vector< std::string > victory_music_
void check_victory()
Checks to see if a side has won.
bool is_linger_mode() const
actions::undo_list & undo_stack()
statistics_t & statistics()
virtual soundsource::manager * get_soundsource_man() override
Get (optionally) a soundsources manager a derived class uses.
void check_next_scenario_is_known()
This shows a warning dialog if either [scenario]next_scenario or any [endlevel]next_scenario would le...
bool reveal_map_default() const
actions::undo_list & get_undo_stack()
const unit_map & get_units() const
play_controller(const config &level, saved_game &state_of_game)
bool do_healing() const
void set_end_level_data(const end_level_data &data)
events::mouse_handler & get_mouse_handler_base() override
Get a reference to a mouse handler member a derived class uses.
void update_savegame_snapshot() const
virtual int find_viewing_side() const =0
returns 0 if no such team was found.
void increase_server_request_number()
bool is_observer() const
void set_do_healing(bool do_healing)
const actions::undo_list & undo_stack() const
bool is_skipping_actions() const
bool is_during_turn() const
bool can_use_synced_wml_menu() const
void reset_gamestate(const config &level, int replay_pos)
bool is_skipping_story() const
void do_consolesave(const std::string &filename)
void save_game_auto(const std::string &filename)
void textbox_move_vertically(bool up)
bool is_regular_game_end() const
saved_game & get_saved_game()
tooltips::manager tooltips_manager_
virtual void check_objectives()=0
void save_replay_auto(const std::string &filename)
saved_game & saved_game_
game_state & gamestate()
hotkey::command_executor * get_hotkey_command_executor() override
Optionally get a command executor to handle context menu events.
bool enemies_visible() const
std::unique_ptr< replay > replay_
const std::unique_ptr< statistics_t > statistics_context_
const mp_game_settings & get_mp_settings()
game_display & get_display() override
Get a reference to a display member a derived class uses.
virtual void update_viewing_player()=0
virtual void sync_end_turn()
std::unique_ptr< game_display > gui_
void maybe_do_init_side()
Called by turn_info::process_network_data() or init_side() to call do_init_side() if necessary.
virtual void process_oos(const std::string &msg) const
Asks the user whether to continue on an OOS error.
bool is_browsing() const override
virtual void send_to_wesnothd(const config &, const std::string &="unknown") const
std::unique_ptr< soundsource::manager > soundsources_manager_
const end_level_data & get_end_level_data() const
void do_init_side()
Called by replay handler or init_side() to do actual work for turn change.
std::string theme() const
const tod_manager & get_tod_manager() const
int current_side() const
Returns the number of the side whose turn it is.
virtual bool is_networked_mp() const
bool is_skipping_replay() const
bool get_disallow_recall() const
const hotkey::scope_changer scope_
std::unique_ptr< font::floating_label_context > labels_manager_
std::shared_ptr< wb::manager > get_whiteboard() const
std::vector< std::string > defeat_music_
const gamemap & get_map() const
bool did_autosave_this_turn_
Whether we did init sides in this session (false = we did init sides before we reloaded the game).
bool is_replay() const
bool player_type_changed_
true when the controller of the currently playing side has changed.
std::size_t turn() const
map_location map_start_
virtual bool should_return_to_play_side() const
std::set< std::string > all_players() const
virtual void force_end_turn()=0
void update_gui_to_player(const int team_index, const bool observe=false)
Changes the UI for this client to the passed side index.
events::mouse_handler mouse_handler_
const auto & timer() const
std::unique_ptr< plugins_context > plugins_context_
virtual plugins_context * get_plugins_context() override
Get (optionally) a plugins context a derived class uses.
virtual ~play_controller()
bool can_undo() const
utils::ms_optimer timer_
const std::unique_ptr< unit_experience_accelerator > xp_mod_
void process_focus_keydown_event(const SDL_Event &event) override
Process keydown (only when the general map display does not have focus).
virtual void send_actions()
Sends replay [command]s to the server.
void refresh_objectives() const
Reevaluate [show_if] conditions and build a new objectives string.
bool can_redo() const
game_events::wml_event_pump & pump()
void process_keyup_event(const SDL_Event &event) override
Process keyup (always).
void finish_side_turn_events()
replay & recorder() const
std::string get_loaded_resources() const
help::help_manager help_manager_
const game_state & gamestate() const
persist_manager persist_
virtual void receive_actions()
Reads and executes replay [command]s from the server.
std::shared_ptr< wb::manager > whiteboard_manager_
virtual void check_time_over()
t_string get_scenario_name() const
Implements a quit confirmation dialog.
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:75
int turn() const
Container associating units to locations.
Definition: map.hpp:98
controller_base framework: controller_base is roughly analogous to a "dialog" class in a GUI toolkit ...
Contains the exception interfaces used to signal completion of a scenario, campaign or turn.
Graphical text output.
Domain specific events.
Definition: display.hpp:45
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
std::string_view data
Definition: picture.cpp:178
std::string filename
Filename.
Additional information on the game outcome which can be provided by WML.
The help implementation caches data parsed from the game_config.
Definition: help.hpp:39
Encapsulates the map of the game.
Definition: location.hpp:45
scoped_savegame_snapshot(const play_controller &controller)
Reports time elapsed at the end of an object scope.
Definition: optimer.hpp:37