The Battle for Wesnoth  1.15.12+dev
synced_user_choice.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2015 - 2018 by the Battle for Wesnoth Project
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY.
10 
11  See the COPYING file for more details.
12 */
13 
14 #pragma once
15 
16 #include "gettext.hpp"
17 #include "config.hpp"
18 #include "events.hpp"
19 #include "generic_event.hpp"
20 
21 #include <map>
22 #include <set>
23 
24 namespace mp_sync
25 {
26 
27 /**
28  * Interface for querying local choices.
29  * It has to support querying the user and making a random choice
30  */
32 {
33  virtual ~user_choice() {}
34  virtual config query_user(int side) const = 0;
35  virtual config random_choice(int side) const = 0;
36  /**
37  * whether the choice is visible for the user like an advancement choice
38  * a non-visible choice is for example get_global_variable
39  */
40  virtual bool is_visible() const { return true; }
41  // TRANSLATORS: In networked games, this text is shown for other clients,
42  // while they wait for an action from another player.
43  // This text will be embedded into a sentence.
44  virtual std::string description() const { return _("waiting for^input"); }
45 };
46 
47 /**
48  * Performs a choice for WML events.
49  *
50  * The choice is synchronized across all the multiplayer clients and
51  * stored into the replay. The function object is called if the local
52  * client is responsible for making the choice.
53  * otherwise this function waits for a remote choice and returns it when it is received.
54  * information about the choice made is saved in replay with dependent=true
55  *
56  * @param name Tag used for storing the choice into the replay.
57  * @param side The number of the side responsible for making the choice.
58  * If zero, it defaults to the currently active side.
59  *
60  * @note In order to prevent issues with sync, crash, or infinite loop, a
61  * number of precautions must be taken when getting a choice from a
62  * specific side.
63  * - The server must recognize @name replay commands as legal from
64  * non-active players. Preferably the server should be notified
65  * about which player the data is expected from, and discard data
66  * from unexpected players.
67  */
68 config get_user_choice(const std::string &name, const user_choice &uch,
69  int side = 0);
70 /**
71  * Performs a choice for multiple sides for WML events.
72  * uch is called on all sides specified in sides, this in done simultaneously on all those sides (or one after another if one client controls multiple sides)
73  * and after all calls are executed the results are returned.
74  */
75 std::map<int, config> get_user_choice_multiple_sides(const std::string &name, const user_choice &uch,
76  std::set<int> sides);
77 
78 }
79 
81 {
82  // The sides which should execute this local choice
83  std::set<int> required_;
84  // The results
85  std::map<int, config> res_;
86  // The side for which we should do a choice locally (0 if no such side exists)
87  // Note that even if there is currently no locally choice to do it is still possible that we need to do a local choice later because we took control over a side
89  // the message displayed for sides which currently don't have to do a choice.
90  std::string wait_message_;
91  // If we failed to read the remote choices this flag is when which indicated that we should do all choices locally
92  bool oos_;
93 
95  const std::string& tagname_;
96  const int current_side_;
97  // private constructor, this object is only constructed by user_choice_manager::get_user_choice_internal
98  user_choice_manager(const std::string &name, const mp_sync::user_choice &uch, const std::set<int>& sides);
100  void search_in_replay();
101 public:
102  void pull();
103  bool finished() const
104  { return required_.size() == res_.size(); }
105  bool has_local_choice() const
106  { return local_choice_ != 0; }
107  /** Note: currently finished() does not imply !waiting() so you may need to check both. */
108  bool waiting() const
109  { return local_choice_ == 0 && !oos_; }
110  void update_local_choice();
111  void ask_local_choice();
112  void fix_oos();
113  const std::string& wait_message() const { return wait_message_; }
114  /**
115  * @param name the tagname for this user choice in the replay
116  * @param uch the choice made
117  * @param sides an array of team numbers (beginning with 1). the specified sides may not have an empty controller.
118  */
119  static std::map<int, config> get_user_choice_internal(const std::string &name, const mp_sync::user_choice &uch, const std::set<int>& sides);
120  /** Inherited from events::pump_monitor */
121  void process(events::pump_info&);
123 };
config get_user_choice(const std::string &name, const user_choice &uch, int side=0)
std::set< int > required_
const std::string & tagname_
virtual std::string description() const
static std::string _(const char *str)
Definition: gettext.hpp:92
bool waiting() const
Note: currently finished() does not imply !waiting() so you may need to check both.
Definitions for the interface to Wesnoth Markup Language (WML).
std::map< int, config > get_user_choice_multiple_sides(const std::string &name, const user_choice &uch, std::set< int > sides)
Performs a choice for multiple sides for WML events.
virtual config random_choice(int side) const =0
void process(int mousex, int mousey)
Definition: tooltips.cpp:193
Interface for querying local choices.
events::generic_event changed_event_
const mp_sync::user_choice & uch_
virtual config query_user(int side) const =0
virtual bool is_visible() const
whether the choice is visible for the user like an advancement choice a non-visible choice is for exa...
std::map< int, config > res_
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
const std::string & wait_message() const