The Battle for Wesnoth  1.19.7+dev
synced_context.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2024
3  by David White <dave@whitevine.net>
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 
16 #pragma once
17 
18 #include "game_events/pump.hpp" // for queued_event
19 #include "mouse_handler_base.hpp"
20 #include "random.hpp"
21 #include "synced_checkup.hpp"
22 #include "synced_commands.hpp"
23 #include "actions/undo_action.hpp"
24 
25 #include <deque>
26 
27 
28 // only static methods.
30 {
31 public:
33 
34  /**
35  * Sets the context to 'synced', initialises random context, and calls the given function.
36  * The plan is that in replays and in real game the same function is called.
37  * However, if you cannot call this function you can also use set_scontext_synced directly
38  * (use it like it's used in this method).
39  *
40  * @param commandname The command to run.
41  * @param data The data to use with the command.
42  * @param spectator An error handler for the case that data contains invalid data.
43  *
44  * @return True if the action was successful.
45  */
46  static bool run(
47  const std::string& commandname, const config& data, action_spectator& spectator = get_default_spectator());
48 
49  static bool run_and_store(
50  const std::string& commandname, const config& data, action_spectator& spectator = get_default_spectator());
51 
52  static bool run_and_throw(
53  const std::string& commandname, const config& data, action_spectator& spectator = get_default_spectator());
54 
55  /**
56  * Checks whether we are currently running in a synced context, and if not we enters it.
57  * This is never called from so_replay_handle.
58  */
60  const std::string& commandname, const config& data, action_spectator& spectator = get_default_spectator());
61 
62  /**
63  * @return Whether we are currently executing a synced action like recruit, start, recall, disband, movement,
64  * attack, init_side, end_turn, fire_event, lua_ai, auto_shroud or similar.
65  */
67  {
68  return state_;
69  }
70 
71  /**
72  * @return Whether we are currently executing a synced action like recruit, start, recall, disband, movement,
73  * attack, init_side, end_turn, fire_event, lua_ai, auto_shroud or similar.
74  */
75  static bool is_synced()
76  {
77  return get_synced_state() == SYNCED;
78  }
79 
80  /**
81  * @return Whether we are not currently executing a synced action like recruit, start, recall, disband, movement,
82  * attack, init_side, end_turn, fire_event, lua_ai, auto_shroud or similar. and not doing a local choice.
83  */
84  static bool is_unsynced()
85  {
86  return get_synced_state() == UNSYNCED;
87  }
88 
89  /** Should only be called form set_scontext_synced, set_scontext_local_choice */
90  static void set_synced_state(synced_state newstate)
91  {
92  state_ = newstate;
93  }
94 
95  /** Generates a new seed for a synced event, by asking the 'server' */
96  static std::string generate_random_seed();
97 
98  /** called from get_user_choice while waiting for a remove user choice. */
99  static void pull_remote_user_input();
100 
101  /**
102  * called from get_user_choice to send a recently made choice to the other clients.
103  * Does not receive any data from the network any sends data.
104  */
105  static void send_user_choice();
106 
107  /** An object to be passed to run_in_synced_context to assert false on error (the default). */
109 
110  /** @return A rng_deterministic if in determinsic mode otherwise a rng_synced. */
111  static std::shared_ptr<randomness::rng> get_rng_for_action();
112 
113  /**
114  * @a set this to false to prevent clearing the undo stack, this is important when we cannot change the gamestate
115  * becasue with dsu clearing the undo stack changes the gamestate, which we for example don't want during formula
116  * evaluation, when it used the dice operator. TODO: consider removing this parameter when dsu is removed.
117  */
118  static void block_undo(bool do_block = true, bool clear_undo = true);
119  static void reset_block_undo()
120  {
121  is_undo_blocked_ = false;
122  }
123 
124  /** @return Whether we tracked something that can never be undone. */
125  static bool undo_blocked();
126 
127  static void set_last_unit_id(int id)
128  {
129  last_unit_id_ = id;
130  }
131 
132  static int get_unit_id_diff();
133 
135  {
136  public:
137  virtual ~server_choice()
138  {
139  }
140 
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 
144  /** The request which is sent to the mp server. */
145  virtual config request() const = 0;
146 
147  virtual const char* name() const = 0;
148 
149  int request_id() const;
150  void send_request() const;
151  };
152 
153  /** If we are in a mp game, ask the server, otherwise generate the answer ourselves. */
154  static config ask_server_choice(const server_choice&);
155 
156  static bool ignore_undo();
157 private:
158  /** Weather we are in a synced move, in a user_choice, or none of them. */
160 
161  /**
162  * As soon as get_user_choice is used with side != current_side (for example in generate_random_seed) other sides
163  * execute the command simultaneously and is_simultaneously is set to true. It's impossible to undo data that has
164  * been sent over the network.
165  *
166  * false = we are on a local turn and haven't sent anything yet.
167  */
168  static inline bool is_undo_blocked_ = false;
169 
170  /** Used to restore the unit id manager when undoing. */
171  static inline int last_unit_id_ = 0;
172 };
173 
175 {
176 public:
179 
180 protected:
181  std::shared_ptr<randomness::rng> new_rng_;
183 };
184 
185 /** A RAII object to enter the synced context, cannot be called if we are already in a synced context. */
187 {
188 public:
190 
191  /** Use this constructor if you have multiple synced_context but only one replay entry. */
192  set_scontext_synced(int num);
193 
195 
196  int get_random_calls();
197  void do_final_checkup(bool dont_throw = false);
198 
199 private:
200  // only called by constructors.
201  void init();
202  static checkup* generate_checkup(const std::string& tagname);
204  const std::unique_ptr<checkup> new_checkup_;
207 };
208 
209 /**
210  * A RAII object to temporary leave the synced context like in wesnoth.synchronize_choice.
211  * Can only be used from inside a synced context.
212  */
214 {
215 public:
218 
219 private:
221 };
222 
223 /**
224  * An object to leave the synced context during draw or unsynced wml items when we don’t know whether we are in a
225  * synced context or not. if we are in a synced context we leave the synced context, otherwise it has no effect. we need
226  * This because we might call lua's wesnoth.interface.game_display during draw and we don’t want to have that an effect
227  * on the gamestate in this case.
228  */
230 {
231 public:
233 
234 private:
235  const std::unique_ptr<leave_synced_context> leaver_;
236 };
A class to check whether the results that were calculated in the replay match the results calculated ...
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
A RAII object to temporary leave the synced context like in wesnoth.synchronize_choice.
randomness::rng * old_rng_
this class does not give synced random results derived classes might do.
Definition: random.hpp:28
std::shared_ptr< randomness::rng > new_rng_
randomness::rng * old_rng_
A RAII object to enter the synced context, cannot be called if we are already in a synced context.
void do_final_checkup(bool dont_throw=false)
static checkup * generate_checkup(const std::string &tagname)
events::command_disabler disabler_
const std::unique_ptr< checkup > new_checkup_
An object to leave the synced context during draw or unsynced wml items when we don’t know whether we...
const std::unique_ptr< leave_synced_context > leaver_
virtual config request() const =0
The request which is sent to the mp server.
virtual const char * name() const =0
virtual config local_choice() const =0
We are in a game with no mp server and need to do this choice locally.
static void set_last_unit_id(int id)
static bool undo_blocked()
static std::shared_ptr< randomness::rng > get_rng_for_action()
static config ask_server_choice(const server_choice &)
If we are in a mp game, ask the server, otherwise generate the answer ourselves.
static bool run_in_synced_context_if_not_already(const std::string &commandname, const config &data, action_spectator &spectator=get_default_spectator())
Checks whether we are currently running in a synced context, and if not we enters it.
static bool is_undo_blocked_
As soon as get_user_choice is used with side != current_side (for example in generate_random_seed) ot...
static bool run(const std::string &commandname, const config &data, action_spectator &spectator=get_default_spectator())
Sets the context to 'synced', initialises random context, and calls the given function.
static std::string generate_random_seed()
Generates a new seed for a synced event, by asking the 'server'.
static synced_state state_
Weather we are in a synced move, in a user_choice, or none of them.
static int get_unit_id_diff()
static synced_state get_synced_state()
static void pull_remote_user_input()
called from get_user_choice while waiting for a remove user choice.
static void reset_block_undo()
static bool is_unsynced()
static void block_undo(bool do_block=true, bool clear_undo=true)
set this to false to prevent clearing the undo stack, this is important when we cannot change the gam...
static int last_unit_id_
Used to restore the unit id manager when undoing.
static bool is_synced()
static void set_synced_state(synced_state newstate)
Should only be called form set_scontext_synced, set_scontext_local_choice.
static void send_user_choice()
called from get_user_choice to send a recently made choice to the other clients.
static bool run_and_store(const std::string &commandname, const config &data, action_spectator &spectator=get_default_spectator())
static action_spectator & get_default_spectator()
An object to be passed to run_in_synced_context to assert false on error (the default).
static bool ignore_undo()
static bool run_and_throw(const std::string &commandname, const config &data, action_spectator &spectator=get_default_spectator())
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:198
std::string_view data
Definition: picture.cpp:178
Define the game's event mechanism.