The Battle for Wesnoth  1.15.1+dev
synced_context.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2018 by David White <dave@whitevine.net>
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 "utils/functional.hpp"
18 #include "synced_commands.hpp"
19 #include "synced_checkup.hpp"
20 #include "replay.hpp"
21 #include "random.hpp"
22 #include "random_synced.hpp"
23 #include "game_events/pump.hpp" // for queued_event
24 #include "generic_event.hpp"
25 #include "mouse_handler_base.hpp"
26 #include <deque>
27 
28 class config;
29 
30 //only static methods.
32 {
33 public:
35  {
39  };
40  /**
41 
42  Sets the context to 'synced', initialises random context, and calls the given function.
43  The plan is that in replay and in real game the same function is called.
44  however, if you cannot call this function you can also use set_scontext_synced directly (use it like it's used in this method).
45 
46  movement commands are currently treated specially,
47  that's because actions::move_unit returns a value and some function use that value.
48  maybe i should add a way here to return a value.
49 
50  ai's attacks are also treated special because the ai wants to pass advancement_aspects.
51 
52 
53  redoing does normally not take place in a synced context, because we saved the dependent=true replaycommands in the replaystack data.
54  also there are no events of similar fired when redoing an action (in most cases).
55 
56  @param use_undo this parameter is used to ignore undos during an ai move to optimize.
57  @param error_handler an error handler for the case that data contains invalid data.
58 
59  @return true if the action was successful.
60 
61 
62 
63  */
64  static bool run(const std::string& commandname, const config& data, bool use_undo = true, bool show = true, synced_command::error_handler_function error_handler = default_error_function);
65  static bool run_and_store(const std::string& commandname, const config& data, bool use_undo = true, bool show = true, synced_command::error_handler_function error_handler = default_error_function);
66  static bool run_and_throw(const std::string& commandname, const config& data, bool use_undo = true, bool show = true, synced_command::error_handler_function error_handler = default_error_function);
67  /**
68  checks whether we are currently running in a synced context, and if not we enters it.
69  this is never called from so_replay_handle.
70  */
71  static bool run_in_synced_context_if_not_already(const std::string& commandname,const config& data, bool use_undo = true, bool show = true , synced_command::error_handler_function error_handler = default_error_function);
72  /**
73  @return whether we are currently executing a synced action like recruit, start, recall, disband, movement, attack, init_side, end_turn, fire_event, lua_ai, auto_shroud or similar.
74  */
76  /**
77  @return whether we are currently executing a synced action like recruit, start, recall, disband, movement, attack, init_side, end_turn, fire_event, lua_ai, auto_shroud or similar.
78  */
79  static bool is_synced();
80  /**
81  @return whether we are not currently executing a synced action like recruit, start, recall, disband, movement, attack, init_side, end_turn, fire_event, lua_ai, auto_shroud or similar. and not doing a local choice.
82  */
83  static bool is_unsynced();
84  /*
85  should only be called form set_scontext_synced, set_scontext_local_choice
86  */
87  static void set_synced_state(synced_state newstate);
88  /*
89  Generates a new seed for a synced event, by asking the 'server'
90  */
91  static std::string generate_random_seed();
92  /**
93  called from get_user_choice while waiting for a remove user choice.
94  */
95  static void pull_remote_user_input();
96  /**
97  called from get_user_choice to send a recently made choice to the other clients.
98  Does not receive any data from the network any sends data.
99  */
100  static void send_user_choice();
101  /**
102  a function to be passed to run_in_synced_context to assert false on error (the default).
103  */
104  static void default_error_function(const std::string& message, bool heavy);
105  /**
106  a function to be passed to run_in_synced_context to log the error.
107  */
108  static void just_log_error_function(const std::string& message, bool heavy);
109  /**
110  a function to be passed to run_in_synced_context to ignore the error.
111  */
112  static void ignore_error_function(const std::string& message, bool heavy);
113  /**
114  @return a rng_deterministic if in determinsic mode otherwise a rng_synced.
115  */
116  static std::shared_ptr<randomness::rng> get_rng_for_action();
117  /**
118  @return whether we already sent data about the current action to other clients. which means we cannot undo it.
119  returns is_simultaneously_
120  */
121  static bool is_simultaneously();
122  /*
123  sets is_simultaneously_ = false, called when entering the synced context.
124  */
125  static void reset_is_simultaneously();
126  /*
127  sets is_simultaneously_ = true, called using a user choice that is not the currently plaing side.
128  */
129  static void set_is_simultaneously();
130  /**
131  @return whether there were recently no methods called that prevent undoing.
132  */
133  static bool can_undo();
134  static void set_last_unit_id(int id);
135  static int get_unit_id_diff();
136 
138  {
139  public:
140  virtual ~server_choice(){}
141  /// We are in a game with no mp server and need to do this choice locally
142  virtual config local_choice() const = 0;
143  /// the request which is sent to the mp server.
144  virtual config request() const = 0;
145  virtual const char* name() const = 0;
146  void send_request() const;
147  };
148  /*
149  if we are in a mp game, ask the server, otherwise generate the answer ourselves.
150  */
151  static config ask_server_choice(const server_choice&);
152 
153  typedef std::deque<std::pair<config,game_events::queued_event>> event_list;
154  static event_list& get_undo_commands() { return undo_commands_; }
155  static void add_undo_commands(const config& commands, const game_events::queued_event& ctx);
156  static void reset_undo_commands();
157 private:
158  /*
159  weather we are in a synced move, in a user_choice, or none of them
160  */
162  /*
163  As soon as get_user_choice is used with side != current_side (for example in generate_random_seed) other sides execute the command simultaneously and is_simultaneously is set to true.
164  It's impossible to undo data that has been sent over the network.
165 
166  false = we are on a local turn and haven't sent anything yet.
167 
168  TODO: it would be better if the following variable were not static.
169  */
170  static bool is_simultaneously_;
171  /**
172  Used to restore the unit id manager when undoing.
173  */
174  static int last_unit_id_;
175  /**
176  Actions wml to be executed when the current action is undone.
177  */
178  static event_list undo_commands_;
179 };
180 
181 
183 {
184 public:
187 protected:
188  std::shared_ptr<randomness::rng> new_rng_;
190 };
191 /*
192  a RAII object to enter the synced context, cannot be called if we are already in a synced context.
193 */
195 {
196 public:
198  /*
199  use this constructor if you have multiple synced_context but only one replay entry.
200  */
201  set_scontext_synced(int num);
203  int get_random_calls();
204  void do_final_checkup(bool dont_throw = false);
205 private:
206  //only called by constructors.
207  void init();
208  static checkup* generate_checkup(const std::string& tagname);
210  const std::unique_ptr<checkup> new_checkup_;
213 };
214 
215 /*
216  a RAII object to temporary leave the synced context like in wesnoth.synchronize_choice. Can only be used from inside a synced context.
217 */
218 
220 {
221 public:
224 private:
226 };
227 
228 /**
229  an object to leave the synced context during draw or unsynced wml items when we don’t know whether we are in a synced context or not.
230  if we are in a synced context we leave the synced context, otherwise it has no effect.
231  we need this because we might call lua's wesnoth.theme_items during draw and we don’t want to have that an effect on the gamestate in this case.
232 */
234 {
235 public:
237 private:
238  const std::unique_ptr<leave_synced_context> leaver_;
239 };
static void add_undo_commands(const config &commands, const game_events::queued_event &ctx)
static bool run_and_store(const std::string &commandname, const config &data, bool use_undo=true, bool show=true, synced_command::error_handler_function error_handler=default_error_function)
static bool run(const std::string &commandname, const config &data, bool use_undo=true, bool show=true, synced_command::error_handler_function error_handler=default_error_function)
Sets the context to &#39;synced&#39;, initialises random context, and calls the given function.
static std::string generate_random_seed()
static bool is_unsynced()
virtual config local_choice() const =0
We are in a game with no mp server and need to do this choice locally.
randomness::rng * old_rng_
Replay control code.
an object to leave the synced context during draw or unsynced wml items when we don’t know whether w...
static synced_state get_synced_state()
static event_list undo_commands_
Actions wml to be executed when the current action is undone.
static void reset_is_simultaneously()
static void set_last_unit_id(int id)
std::shared_ptr< randomness::rng > new_rng_
struct utils::detail::formula_initer init
static synced_state state_
static void just_log_error_function(const std::string &message, bool heavy)
a function to be passed to run_in_synced_context to log the error.
virtual const char * name() const =0
static void ignore_error_function(const std::string &message, bool heavy)
a function to be passed to run_in_synced_context to ignore the error.
events::command_disabler disabler_
static bool can_undo()
std::deque< std::pair< config, game_events::queued_event > > event_list
static void send_user_choice()
called from get_user_choice to send a recently made choice to the other clients.
static void pull_remote_user_input()
called from get_user_choice while waiting for a remove user choice.
static int last_unit_id_
Used to restore the unit id manager when undoing.
static bool is_simultaneously()
const std::unique_ptr< leave_synced_context > leaver_
A class to check whether the results that were calculated in the replay match the results calculated ...
static int get_unit_id_diff()
randomness::rng * old_rng_
Define the game&#39;s event mechanism.
static void reset_undo_commands()
const std::unique_ptr< checkup > new_checkup_
static bool run_and_throw(const std::string &commandname, const config &data, bool use_undo=true, bool show=true, synced_command::error_handler_function error_handler=default_error_function)
static bool run_in_synced_context_if_not_already(const std::string &commandname, const config &data, bool use_undo=true, bool show=true, synced_command::error_handler_function error_handler=default_error_function)
checks whether we are currently running in a synced context, and if not we enters it...
static void set_synced_state(synced_state newstate)
static void default_error_function(const std::string &message, bool heavy)
a function to be passed to run_in_synced_context to assert false on error (the default).
static std::shared_ptr< randomness::rng > get_rng_for_action()
std::function< void(const std::string &, bool)> error_handler_function
static void set_is_simultaneously()
static event_list & get_undo_commands()
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
virtual config request() const =0
the request which is sent to the mp server.
static bool is_synced()
static config ask_server_choice(const server_choice &)
void show(const std::string &window_id, const t_string &message, const point &mouse, const SDL_Rect &source_rect)
Shows a tip.
Definition: tooltip.cpp:154
this class does not give synced random results derived classes might do.
Definition: random.hpp:27
static bool is_simultaneously_