46 #define LOG_NG LOG_STREAM(info, log_engine)
47 #define DBG_NG LOG_STREAM(debug, log_engine)
48 #define ERR_NW LOG_STREAM(err, log_network)
52 , network_processing_stopped_(false)
53 , next_scenario_notified_(false)
54 , blindfold_(*gui_, mp_info && mp_info->skip_replay_blindfolded)
61 skip_replay_ = mp_info && mp_info->skip_replay && mp_info->current_turn >
turn();
75 LOG_NG <<
"network processing activated again";
81 LOG_NG <<
"network processing stopped";
91 if(
gui_->is_blindfolded()) {
93 LOG_NG <<
"Taking off the blindfold now";
94 gui_->queue_rerender();
100 LOG_NG <<
"playmp::play_human_turn...";
109 utils::optional<countdown_clock>
timer;
148 bool time_left =
timer->update();
162 LOG_NG <<
"playmp::play_human_turn...";
170 using namespace std::chrono_literals;
171 std::this_thread::sleep_for(1ms);
187 using namespace std::chrono_literals;
188 std::this_thread::sleep_for(10ms);
211 LOG_NG <<
"playmp::after_human_turn...";
219 LOG_NG <<
"is networked...";
234 LOG_NG <<
"finished networked...";
242 info[
"type"] =
"termination";
243 info[
"condition"] =
"out of sync";
246 std::stringstream temp_buf;
247 std::vector<std::string> err_lines =
utils::split(err_msg,
'\n');
248 temp_buf <<
_(
"The game is out of sync, and cannot continue. There are a number of reasons this could happen: this "
249 "can occur if you or another player have modified their game settings. This may mean one of the "
250 "players is attempting to cheat. It could also be due to a bug in the game, but this is less "
251 "likely.\n\nDo you want to save an error log of your game?");
253 if(!err_msg.empty()) {
254 temp_buf <<
" \n \n";
256 temp_buf << *
i <<
'\n';
278 gui_->get_chat_manager().add_chat_message(std::time(
nullptr),
"", 0,
279 _(
"This side is in an idle state. To proceed with the game, it must be assigned to another controller. You may "
280 "use :droid, :control or :give_control for example."),
364 ERR_NW <<
"attempting to process network data while still having data on the replay.";
404 ERR_NW <<
"processing network data while still having data on the replay.";
423 else if (
auto observer_quit = cfg.
optional_child(
"observer_quit"))
451 else if (cfg.
has_child(
"notify_next_scenario")) {
456 else if (cfg.
has_child(
"host_transfer")) {
464 ERR_NW <<
"found unknown command:\n" << cfg.
debug();
473 assert(
t.all_children_count() == 1);
475 if(
auto command =
t.optional_child(
"command")) {
482 ERR_NW <<
"Received a synced remote user action during our own turn";
495 const int side_drop = side_drop_c[
"side_num"].to_int(0);
496 std::size_t
index = side_drop -1;
501 ERR_NW <<
"unknown side " << side_drop <<
" is dropping game";
507 ERR_NW <<
"unknown controller type issued from server on side drop: " << side_drop_c[
"controller"];
511 if (ctrl == side_controller::type::ai) {
516 else if (ctrl != side_controller::type::human) {
522 int first_observer_option_idx = 0;
523 int control_change_options = 0;
526 std::vector<std::string> observers;
527 std::vector<const team *> allies;
528 std::vector<std::string> options;
533 if (!
t.is_enemy(side_drop) && !
t.is_local_human() && !
t.is_local_ai() && !
t.is_network_ai() && !
t.is_empty()
535 allies.push_back(&
t);
544 for (
const team *
t : allies) {
548 t_vars[
"player"] =
t->current_player();
549 options.emplace_back(
VGETTEXT(
"Give control to their ally $player", t_vars));
550 control_change_options++;
553 first_observer_option_idx = options.size();
557 t_vars[
"player"] = screen_observers;
558 options.emplace_back(
VGETTEXT(
"Give control to observer $player", t_vars));
559 observers.push_back(screen_observers);
560 control_change_options++;
563 options.emplace_back(
_(
"Replace with AI"));
564 options.emplace_back(
_(
"Replace with local player"));
565 options.emplace_back(
_(
"Set side to idle"));
566 options.emplace_back(
_(
"Save and abort game"));
569 t_vars[
"side_drop"] = std::to_string(side_drop);
570 const std::string gettext_message =
VGETTEXT(
"$player who controlled side $side_drop has left the game. What do you want to do?", t_vars);
578 action = control_change_options + 2;
585 if (action < control_change_options) {
590 if (action < first_observer_option_idx) {
596 action -= control_change_options;
633 ERR_NW <<
"Bad [change_controller] signal from server, [change_controller] tag was empty.";
637 const int side = change[
"side"].to_int();
638 const bool is_local = change[
"is_local"].to_bool();
639 const std::string player = change[
"player"];
640 const std::string controller_type = change[
"controller"];
641 const std::size_t
index = side - 1;
643 ERR_NW <<
"Bad [change_controller] signal from server, side out of bounds: " << change.
debug();
648 const bool was_local = tm.
is_local();
684 change[
"side"] = side;
685 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)
Equivalent 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()
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)
const team & playing_team() const
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),...
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.
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.
const auto & timer() const
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
void play_slice() 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 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 is_unsynced()
static bool run_and_store(const std::string &commandname, const config &data, action_spectator &spectator=get_default_spectator())
This class stores all the data for a single 'side' (in game nomenclature).
void set_action_bonus_count(const int count)
void set_countdown_time(const std::chrono::milliseconds &amount) const
const std::string & current_player() const
int action_bonus_count() const
std::chrono::milliseconds 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)
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 ...
std::chrono::seconds mp_countdown_reservoir_time
std::chrono::seconds mp_countdown_action_bonus
std::chrono::seconds mp_countdown_turn_bonus
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.
static constexpr utils::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.