The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
synced_user_choice.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2015 - 2025
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 "gettext.hpp"
18#include "config.hpp"
19#include "events.hpp"
20#include "generic_event.hpp"
21
22#include <map>
23#include <set>
24
25namespace mp_sync
26{
27
28/**
29 * Interface for querying local choices.
30 * It has to support querying the user and making a random choice
31 */
33{
34 virtual ~user_choice() {}
35 virtual config query_user(int side) const = 0;
36 virtual config random_choice(int side) const = 0;
37 /**
38 * whether the choice is visible for the user like an advancement choice
39 * a non-visible choice is for example get_global_variable
40 */
41 virtual bool is_visible() const { return true; }
42 // TRANSLATORS: In networked games, this text is shown for other clients,
43 // while they wait for an action from another player.
44 // This text will be embedded into a sentence.
45 virtual std::string description() const { return _("waiting for^input"); }
46};
47
48/**
49 * Performs a choice for WML events.
50 *
51 * The choice is synchronized across all the multiplayer clients and
52 * stored into the replay. The function object is called if the local
53 * client is responsible for making the choice.
54 * otherwise this function waits for a remote choice and returns it when it is received.
55 * information about the choice made is saved in replay with dependent=true
56 *
57 * @param name Tag used for storing the choice into the replay.
58 * @param side The number of the side responsible for making the choice.
59 * If zero, it defaults to the currently active side.
60 *
61 * @note In order to prevent issues with sync, crash, or infinite loop, a
62 * number of precautions must be taken when getting a choice from a
63 * specific side.
64 * - The server must recognize @name replay commands as legal from
65 * non-active players. Preferably the server should be notified
66 * about which player the data is expected from, and discard data
67 * from unexpected players.
68 */
69config get_user_choice(const std::string &name, const user_choice &uch,
70 int side = 0);
71/**
72 * Performs a choice for multiple sides for WML events.
73 * 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)
74 * and after all calls are executed the results are returned.
75 */
76std::map<int, config> get_user_choice_multiple_sides(const std::string &name, const user_choice &uch,
77 std::set<int> sides);
78
79}
80
82{
83 // The sides which should execute this local choice
84 std::set<int> required_;
85 // The results
86 std::map<int, config> res_;
87 // The side for which we should do a choice locally (0 if no such side exists)
88 // 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
90 // the message displayed for sides which currently don't have to do a choice.
91 std::string wait_message_;
92 // If we failed to read the remote choices this flag is when which indicated that we should do all choices locally
93 bool oos_;
94
96 const std::string& tagname_;
97 const int current_side_;
98 // private constructor, this object is only constructed by user_choice_manager::get_user_choice_internal
99 user_choice_manager(const std::string &name, const mp_sync::user_choice &uch, const std::set<int>& sides);
101 void search_in_replay();
102public:
103 void pull();
104 bool finished() const
105 { return required_.size() == res_.size(); }
106 bool has_local_choice() const
107 { return local_choice_ != 0; }
108 /** Note: currently finished() does not imply !waiting() so you may need to check both. */
109 bool waiting() const
110 { return local_choice_ == 0 && !oos_; }
111 void update_local_choice();
112 void ask_local_choice();
113 void fix_oos();
114 const std::string& wait_message() const { return wait_message_; }
115 /**
116 * @param name the tagname for this user choice in the replay
117 * @param uch the choice made
118 * @param sides an array of team numbers (beginning with 1). the specified sides may not have an empty controller.
119 */
120 static std::map<int, config> get_user_choice_internal(const std::string &name, const mp_sync::user_choice &uch, const std::set<int>& sides);
121 /** Inherited from events::pump_monitor */
122 void process();
124};
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
events::generic_event changed_event_
bool waiting() const
Note: currently finished() does not imply !waiting() so you may need to check both.
const std::string & wait_message() const
const mp_sync::user_choice & uch_
void process()
Inherited from events::pump_monitor.
static std::map< int, config > get_user_choice_internal(const std::string &name, const mp_sync::user_choice &uch, const std::set< int > &sides)
std::map< int, config > res_
const std::string & tagname_
Definitions for the interface to Wesnoth Markup Language (WML).
static std::string _(const char *str)
Definition gettext.hpp:100
config get_user_choice(const std::string &name, const user_choice &uch, int side=0)
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.
Interface for querying local choices.
virtual config query_user(int side) const =0
virtual std::string description() const
virtual bool is_visible() const
whether the choice is visible for the user like an advancement choice a non-visible choice is for exa...
virtual config random_choice(int side) const =0