47 #define LOG_NG LOG_STREAM(info, log_engine)
48 #define DBG_NG LOG_STREAM(debug, log_engine)
49 #define ERR_NW LOG_STREAM(err, log_network)
53 , network_processing_stopped_(false)
54 , next_scenario_notified_(false)
55 , blindfold_(*gui_, mp_info && mp_info->skip_replay_blindfolded)
62 skip_replay_ = mp_info && mp_info->skip_replay && mp_info->current_turn >
turn();
76 LOG_NG <<
"network processing activated again";
82 LOG_NG <<
"network processing stopped";
92 if(
gui_->is_blindfolded()) {
94 LOG_NG <<
"Taking off the blindfold now";
95 gui_->queue_rerender();
101 LOG_NG <<
"playmp::play_human_turn...";
148 bool time_left = timer->update();
162 LOG_NG <<
"playmp::play_human_turn...";
209 LOG_NG <<
"playmp::after_human_turn...";
217 LOG_NG <<
"is networked...";
232 LOG_NG <<
"finished networked...";
240 info[
"type"] =
"termination";
241 info[
"condition"] =
"out of sync";
244 std::stringstream temp_buf;
245 std::vector<std::string> err_lines =
utils::split(err_msg,
'\n');
246 temp_buf <<
_(
"The game is out of sync, and cannot continue. There are a number of reasons this could happen: this "
247 "can occur if you or another player have modified their game settings. This may mean one of the "
248 "players is attempting to cheat. It could also be due to a bug in the game, but this is less "
249 "likely.\n\nDo you want to save an error log of your game?");
251 if(!err_msg.empty()) {
252 temp_buf <<
" \n \n";
254 temp_buf << *
i <<
'\n';
276 gui_->get_chat_manager().add_chat_message(std::time(
nullptr),
"", 0,
277 _(
"This side is in an idle state. To proceed with the game, it must be assigned to another controller. You may "
278 "use :droid, :control or :give_control for example."),
362 ERR_NW <<
"attempting to process network data while still having data on the replay.";
402 ERR_NW <<
"processing network data while still having data on the replay.";
421 else if (
auto observer_quit = cfg.
optional_child(
"observer_quit"))
449 else if (cfg.
has_child(
"notify_next_scenario")) {
454 else if (cfg.
has_child(
"host_transfer")) {
462 ERR_NW <<
"found unknown command:\n" << cfg.
debug();
471 assert(
t.all_children_count() == 1);
473 if(
auto command =
t.optional_child(
"command")) {
480 ERR_NW <<
"Received a synced remote user action during our own turn";
493 const int side_drop = side_drop_c[
"side_num"].to_int(0);
494 std::size_t
index = side_drop -1;
499 ERR_NW <<
"unknown side " << side_drop <<
" is dropping game";
505 ERR_NW <<
"unknown controller type issued from server on side drop: " << side_drop_c[
"controller"];
509 if (ctrl == side_controller::type::ai) {
514 else if (ctrl != side_controller::type::human) {
520 int first_observer_option_idx = 0;
521 int control_change_options = 0;
524 std::vector<std::string> observers;
525 std::vector<const team *> allies;
526 std::vector<std::string>
options;
531 if (!
t.is_enemy(side_drop) && !
t.is_local_human() && !
t.is_local_ai() && !
t.is_network_ai() && !
t.is_empty()
533 allies.push_back(&
t);
542 for (
const team *
t : allies) {
546 t_vars[
"player"] =
t->current_player();
547 options.emplace_back(
VGETTEXT(
"Give control to their ally $player", t_vars));
548 control_change_options++;
551 first_observer_option_idx =
options.size();
555 t_vars[
"player"] = screen_observers;
556 options.emplace_back(
VGETTEXT(
"Give control to observer $player", t_vars));
557 observers.push_back(screen_observers);
558 control_change_options++;
561 options.emplace_back(
_(
"Replace with AI"));
562 options.emplace_back(
_(
"Replace with local player"));
563 options.emplace_back(
_(
"Set side to idle"));
564 options.emplace_back(
_(
"Save and abort game"));
567 t_vars[
"side_drop"] = std::to_string(side_drop);
568 const std::string gettext_message =
VGETTEXT(
"$player who controlled side $side_drop has left the game. What do you want to do?", t_vars);
576 action = control_change_options + 2;
583 if (action < control_change_options) {
588 if (action < first_observer_option_idx) {
594 action -= control_change_options;
631 ERR_NW <<
"Bad [change_controller] signal from server, [change_controller] tag was empty.";
635 const int side = change[
"side"].to_int();
636 const bool is_local = change[
"is_local"].to_bool();
637 const std::string player = change[
"player"];
638 const std::string controller_type = change[
"controller"];
639 const std::size_t
index = side - 1;
641 ERR_NW <<
"Bad [change_controller] signal from server, side out of bounds: " << change.
debug();
646 const bool was_local = tm.
is_local();
682 change[
"side"] = side;
683 change[
"player"] = player;
bool can_undo() const
True if there are actions that can be undone.
void clear()
Clears the stack of undoable (and redoable) actions.
void undo()
Undoes the top action on the undo stack.
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)
virtual void play_slice(bool is_delay_enabled=true)
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)
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)
@ TURN_PLAYING
The User is controlling the game and invoking actions The game can be saved here.
@ TURN_ENDED
The turn_end, side_turn_end etc [events] are fired next phase: TURN_STARTING_WAITING (default),...
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 has_next_scenario() const
Checks whether this is not the last scenario (usually of a campaign)
bool in_phase(game_data::PHASE phase) const
static void progress(loading_stage stage=loading_stage::none)
Report what is being loaded to the loading screen.
static void display(std::function< void()> f)
static void spin()
Indicate to the player that loading is progressing.
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.
bool ignore_replay_errors_
std::vector< team > & get_teams()
std::unique_ptr< hotkey_handler > hotkey_handler_
bool is_linger_mode() const
actions::undo_list & undo_stack()
bool is_regular_game_end() const
std::unique_ptr< game_display > gui_
const end_level_data & get_end_level_data() const
int current_side() const
Returns the number of the side whose turn it is.
std::shared_ptr< wb::manager > get_whiteboard() const
bool player_type_changed_
true when the controller of the currently playing side has changed.
replay & recorder() const
void process_network_data(bool unsync_only=false)
void send_actions() override
Sends replay [command]s to the server.
virtual ~playmp_controller()
void process_oos(const std::string &err_msg) const override
Asks the user whether to continue on an OOS error.
void process_network_side_drop_impl(const config &t)
Handle incoming [side_drop] from the multiplayer server.
void send_change_side_controller(int side, const std::string &player)
Send [change_controller] to the multiplayer server.
mp_game_metadata * mp_info_
Information about our connection to the multiplayer server.
virtual bool is_host() const override
void process_network_change_controller_impl(const config &)
Handle incoming [change_controller] from the multiplayer server.
virtual void do_idle_notification() override
Will handle sending a networked notification in descendent classes.
void maybe_linger() override
playturn_network_adapter network_reader_
Helper to preprocess infoming network data.
bool receive_from_wesnothd(config &cfg) const override
virtual void play_idle_loop() override
virtual void handle_generic_event(const std::string &name) override
bool network_processing_stopped_
virtual void play_human_turn() override
void send_to_wesnothd(const config &cfg, const std::string &packet_type="unknown") const override
PROCESS_DATA_RESULT process_network_data_impl(const config &cfg, bool chat_only=false)
Check for and Handle incoming data from the multiplayer server.
virtual void on_not_observer() override
virtual void after_human_turn() override
bool is_networked_mp() const override
PROCESS_DATA_RESULT process_network_turn_impl(const config &t, bool chat_only=false)
Handle incoming [turn] from the multiplayer server.
@ CANNOT_HANDLE
when we couldn't handle the given action currently.
virtual void play_network_turn() override
Will handle networked turns in descendent classes.
void receive_actions() override
Reads and executes replay [command]s from the server.
void surrender(int side_number)
bool next_scenario_notified_
void wait_for_upload()
Wait for the host to upload the next scenario.
playmp_controller(const config &level, saved_game &state_of_game, mp_game_metadata *mp_info)
void play_slice(bool is_delay_enabled=true) override
void end_turn_enable(bool enable)
std::unique_ptr< replay_controller > replay_controller_
non-null when replay mode in active, is used in singleplayer and for the "back to turn" feature in mu...
virtual void check_objectives() override
virtual bool should_return_to_play_side() const override
void update_viewing_player() override
virtual void handle_generic_event(const std::string &name) override
bool end_turn_requested_
true iff the user has pressed the end turn button this turn.
virtual void after_human_turn()
void push_front(config &&cfg)
static config get_update_shroud()
Records that the player has manually updated fog/shroud.
void add_config(const config &cfg, MARK_SENT mark=MARK_AS_UNSENT)
void add_surrender(int side_number)
config get_unsent_commands(DATA_TYPE data_type)
void add_countdown_update(int value, int team)
mp_game_settings & mp_settings()
Multiplayer parameters for this game.
bool save_game_interactive(const std::string &message, DIALOG_TYPE dialog_type)
Save a game interactively through the savegame dialog.
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 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 is_unsynced()
This class stores all the data for a single 'side' (in game nomenclature).
void set_action_bonus_count(const int count)
const std::string & current_player() const
int action_bonus_count() const
void set_countdown_time(const int amount) const
int countdown_time() const
bool receive_data(config &result)
Receives the next pending data pack from the server, if available.
void send_data(const configr_of &request)
Queues the given data to be sent to the server.
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)
An extension of playsingle_controller::hotkey_handler, which has support for MP wesnoth features like...
Standard logging facilities (interface).
const color_t NORMAL_COLOR
void turn_changed(const std::string &player_name)
bool disable_auto_moves()
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::string get_unknown_exception_type()
Utility function for finding the type of thing caught with catch(...).
std::map< std::string, t_string > string_map
std::vector< std::string > split(const config_attribute_value &val)
bool headless()
The game is running headless.
std::string::const_iterator iterator
static lg::log_domain log_engine("engine")
static lg::log_domain log_network("network")
REPLAY_ACTION_TYPE get_replay_action_type(const config &command)
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 ...
int mp_countdown_turn_bonus
int mp_countdown_action_bonus
int mp_countdown_reservoir_time
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.