40 #include "widgets/button.hpp"
48 #define ERR_NW LOG_STREAM(err, log_network)
51 replay_sender_(replay_sender),
52 host_transfer_(
"host_transfer"),
53 network_reader_(network_reader)
83 if ( !send_everything ) {
93 assert(
t.all_children_count() == 1);
95 if(!
t.child_or_empty(
"command").has_child(
"speak") && chat_only) {
135 ERR_NW <<
"processing network data while still having data on the replay.";
154 else if (
auto observer_quit = cfg.
optional_child(
"observer_quit"))
173 if(change->empty()) {
174 ERR_NW <<
"Bad [change_controller] signal from server, [change_controller] tag was empty.";
178 const int side = change[
"side"].to_int();
179 const bool is_local = change[
"is_local"].to_bool();
180 const std::string player = change[
"player"];
181 const std::string controller_type = change[
"controller"];
182 const std::size_t
index = side - 1;
184 ERR_NW <<
"Bad [change_controller] signal from server, side out of bounds: " << change->debug();
189 const bool was_local = tm.
is_local();
198 auto disp_set_team = [](
int side_index) {
210 disp_set_team(side - 1);
224 const int side_drop = side_drop_c[
"side_num"].to_int(0);
225 std::size_t
index = side_drop -1;
230 ERR_NW <<
"unknown side " << side_drop <<
" is dropping game";
236 ERR_NW <<
"unknown controller type issued from server on side drop: " << side_drop_c[
"controller"];
240 if (ctrl == side_controller::type::ai) {
245 else if (ctrl != side_controller::type::human) {
251 int first_observer_option_idx = 0;
252 int control_change_options = 0;
255 std::vector<std::string> observers;
256 std::vector<const team *> allies;
257 std::vector<std::string>
options;
262 if (!
t.is_enemy(side_drop) && !
t.is_local_human() && !
t.is_local_ai() && !
t.is_network_ai() && !
t.is_empty()
264 allies.push_back(&
t);
273 for (
const team *
t : allies) {
277 t_vars[
"player"] =
t->current_player();
278 options.emplace_back(
VGETTEXT(
"Give control to their ally $player", t_vars));
279 control_change_options++;
282 first_observer_option_idx =
options.size();
286 t_vars[
"player"] = screen_observers;
287 options.emplace_back(
VGETTEXT(
"Give control to observer $player", t_vars));
288 observers.push_back(screen_observers);
289 control_change_options++;
292 options.emplace_back(
_(
"Replace with AI"));
293 options.emplace_back(
_(
"Replace with local player"));
294 options.emplace_back(
_(
"Set side to idle"));
295 options.emplace_back(
_(
"Save and abort game"));
298 t_vars[
"side_drop"] = std::to_string(side_drop);
299 const std::string gettext_message =
VGETTEXT(
"$player who controlled side $side_drop has left the game. What do you want to do?", t_vars);
307 action = control_change_options + 2;
314 if (action < control_change_options) {
322 if (action < first_observer_option_idx) {
330 action -= control_change_options;
365 else if (cfg.
has_child(
"notify_next_scenario")) {
373 else if (cfg.
has_child(
"host_transfer")){
378 ERR_NW <<
"found unknown command:\n" << cfg.
debug();
389 change[
"side"] = side;
390 change[
"player"] = player;
408 throw "found invalid REPLAY_RETURN";
bool can_undo() const
True if there are actions that can be undone.
A config object defines a single node in a WML file, with access to child nodes.
config & mandatory_child(config_key_type key, int n=0)
Returns the nth child with the given key, or throws an error if there is none.
const_attr_itors attribute_range() const
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
bool has_attribute(config_key_type key) const
std::size_t all_children_count() const
std::string debug() const
optional_config_impl< config > optional_child(config_key_type key, int n=0)
Euivalent to mandatory_child, but returns an empty optional if the nth child was not found.
config & add_child(config_key_type key)
void remove_observer(const std::string &name)
void add_observer(const std::string &name)
void add_chat_message(const std::time_t &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
std::size_t viewing_team() const
The viewing team is the team currently viewing the game.
void set_team(std::size_t team, bool observe=false)
Sets the team controlled by the player using the computer.
void queue_rerender()
Marks everything for rendering including all tiles and sidebar.
static display * get_singleton()
Returns the display object if a display object exists.
virtual void notify_observers()
virtual const std::vector< team > & teams() const override
void side_drop_to(int side_num, side_controller::type ctrl, side_proxy_controller::type proxy=side_proxy_controller::type::human)
void side_change_controller(int side_num, bool is_local, const std::string &pname, const std::string &controller_type)
const std::string & next_scenario() const
virtual int playing_side() const override
The playing team is the team whose turn it is.
static game_display * get_singleton()
display_chat_manager & get_chat_manager()
bool show(const unsigned auto_close_time=0)
Shows the window.
A simple one-column listbox with OK and Cancel buttons.
void set_single_button(bool value)
Sets whether the Cancel button should be hidden or not.
int selected_index() const
Returns the selected item index after displaying.
void recalculate_labels()
virtual void on_not_observer()=0
virtual void send_to_wesnothd(const config &, const std::string &="unknown") const
void add_config(const config &cfg, MARK_SENT mark=MARK_AS_UNSENT)
An object to leave the synced context during draw or unsynced wml items when we don’t know whether we...
static bool undo_blocked()
static bool is_unsynced()
This class stores all the data for a single 'side' (in game nomenclature).
const std::string & current_player() const
bool is_local_human() const
events::generic_event host_transfer_
PROCESS_DATA_RESULT handle_turn(const config &t, bool chat_only=false)
static void change_side_controller(int side, const std::string &player)
playturn_network_adapter & network_reader_
static PROCESS_DATA_RESULT replay_to_process_data_result(REPLAY_RETURN replayreturn)
PROCESS_DATA_RESULT sync_network()
@ PROCESS_FOUND_DEPENDENT
When we couldn't process the network data because we found a dependent command, this should only happ...
@ PROCESS_CANNOT_HANDLE
when we couldn't handle the given action currently.
@ PROCESS_END_LINGER
When the host uploaded the next scenario this is returned.
@ PROCESS_END_LEVEL
We found a player action in the replay that caused the game to end.
turn_info(replay_network_sender &network_sender, playturn_network_adapter &network_reader)
replay_network_sender & replay_sender_
PROCESS_DATA_RESULT process_network_data_from_reader()
PROCESS_DATA_RESULT process_network_data(const config &cfg, bool chat_only=false)
Contains the exception interfaces used to signal completion of a scenario, campaign or turn.
void throw_quit_game_exception()
static std::string _(const char *str)
Standard logging facilities (interface).
actions::undo_list * undo_stack
play_controller * controller
std::shared_ptr< wb::manager > whiteboard
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
std::map< std::string, t_string > string_map
static lg::log_domain log_network("network")
REPLAY_RETURN do_replay(bool one_move)
We received invalid data from wesnothd during a game This means we cannot continue with the game but ...
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.
static constexpr std::optional< enum_type > get_enum(const std::string_view value)
Converts a string into its enum equivalent.
Various functions that implement the undoing (and redoing) of in-game commands.