46 #define DBG_REPLAY LOG_STREAM(debug, log_replay)
47 #define LOG_REPLAY LOG_STREAM(info, log_replay)
48 #define WRN_REPLAY LOG_STREAM(warn, log_replay)
49 #define ERR_REPLAY LOG_STREAM(err, log_replay)
52 #define DBG_RND LOG_STREAM(debug, log_random)
53 #define LOG_RND LOG_STREAM(info, log_random)
54 #define WRN_RND LOG_STREAM(warn, log_random)
55 #define ERR_RND LOG_STREAM(err, log_random)
61 std::stringstream errbuf;
64 const std::size_t nunits = cfg[
"num_units"].to_size_t();
65 if(nunits != units.
size()) {
66 errbuf <<
"SYNC VERIFICATION FAILED: number of units from data source differ: "
67 << nunits <<
" according to data source. " << units.
size() <<
" locally\n";
69 std::set<map_location> locs;
75 if(units.
count(loc) == 0) {
76 errbuf <<
"data source says there is a unit at "
77 << loc <<
" but none found locally\n";
82 if (locs.count(j->get_location()) == 0) {
83 errbuf <<
"local unit at " << j->get_location()
84 <<
" but none in data source\n";
95 if(u == units.
end()) {
96 errbuf <<
"SYNC VERIFICATION FAILED: data source says there is a '"
97 << un[
"type"] <<
"' (side " << un[
"side"] <<
") at "
98 << loc <<
" but there is no local record of it\n";
108 using namespace std::literals::string_literals;
109 static const std::array fields{
"type"s,
"hitpoints"s,
"experience"s,
"side"s};
111 for(
const std::string& field : fields) {
112 if (u_cfg[field] != un[field]) {
113 errbuf <<
"ERROR IN FIELD '" << field <<
"' for unit at "
114 << loc <<
" data source: '" << un[field]
115 <<
"' local: '" << u_cfg[field] <<
"'\n";
121 errbuf <<
"(SYNC VERIFICATION FAILED)\n";
133 if (!speak[
"time"].empty())
135 std::stringstream ss(speak[
"time"].str());
141 time = std::time(
nullptr);
149 , text_(cfg[
"message"].str())
151 if(cfg[
"team_name"].empty() && cfg[
"to_sides"].empty())
153 nick_ = cfg[
"id"].str();
155 nick_ =
"*"+cfg[
"id"].str()+
"*";
157 int side = cfg[
"side"].to_int(0);
183 , message_locations()
242 val[
"value"] = value;
244 cmd.
add_child(
"countdown_update", std::move(val));
259 cmd[
"dependent"] =
true;
262 cmd[
"from_side"] =
"server";
266 cmd[
"from_side"] = from_side;
287 val[
"team_name"] = team_name;
288 val[
"force"] = force;
289 cmd.
add_child(
"clear_labels", std::move(val));
308 end_turn[
"next_player_number"] = next_player_number;
367 std::vector<int>::reverse_iterator loc_it;
381 std::vector<int>::const_iterator loc_it;
382 int last_location = 0;
383 std::back_insert_iterator<std::vector < chat_msg >> chat_log_appender( back_inserter(
message_log));
386 last_location = *loc_it;
399 for (
int cmd = cmd_start; cmd < cmd_end; ++cmd)
404 if ((data_type ==
ALL_DATA || !cc[
"undo"].to_bool(
true)) && !cc[
"sent"].to_bool(
false))
437 for (
int cmd_num =
base_->
get_pos() - 1; cmd_num >= 0; --cmd_num)
441 if (cc[
"dependent"].to_bool(
false) || !cc[
"undo"].to_bool(
true) || cc[
"async"].to_bool(
false))
447 ERR_REPLAY <<
"replay::get_last_real_command called with no existent command.";
448 assert(
false &&
"replay::get_last_real_command called with no existent command.");
449 throw "replay::get_last_real_command called with no existent command.";
457 if (
const auto child =
c.optional_child(
"move"))
461 std::vector<map_location> steps;
466 WRN_REPLAY <<
"Warning: Path data contained something which could not be parsed to a sequence of locations:" <<
"\n config = " << child->debug();
470 ERR_REPLAY <<
"trying to undo a move using an empty path";
476 if (dst == aloc) src.
write(async_child);
481 auto loc =
c.optional_child(
"recruit");
483 loc =
c.optional_child(
"recall");
507 for (; cmd_index >= 0; --cmd_index)
514 if(
c[
"undo"].to_bool(
true) && !
c[
"async"].to_bool(
false) && !
c[
"dependent"].to_bool(
false))
516 if(
c[
"sent"].to_bool(
false))
518 ERR_REPLAY <<
"trying to undo a command that was already sent.";
530 ERR_REPLAY <<
"trying to undo a command but no command was found.";
538 if(!cc[
"undo"].to_bool(
true))
542 else if(cc[
"async"].to_bool(
false))
544 if(
auto rename =
c.optional_child(
"rename"))
553 else if(cc[
"dependent"].to_bool(
false) ||
i == cmd_index)
561 ERR_REPLAY <<
"Couldn't handle command:\n" << cc <<
"\nwhen undoing.";
596 const bool was_at_end =
at_end();
602 assert(was_at_end ==
at_end());
654 cmd_cfg[
"sent"] =
true;
657 cmd_cfg[
"undo"] =
false;
711 DBG_REPLAY <<
"in do replay with is_synced=" << is_synced <<
"is_unsynced=" << is_unsynced;
726 if (ch_itors.empty() || cfg->
has_child(
"start"))
735 const std::string &team_name = speak[
"to_sides"];
736 const std::string &speaker_name = speak[
"id"];
737 const std::string &message = speak[
"message"];
739 bool is_whisper = (speaker_name.find(
"whisper: ") == 0);
741 DBG_REPLAY <<
"tried to add a chat message twice.";
743 int side = speak[
"side"];
772 const std::string &name = rename[
"name"];
775 if (u.
valid() && !u->unrenamable()) {
784 WRN_REPLAY <<
"attempt to rename unit at location: "
785 << loc << (u.
valid() ?
", which is unrenamable" :
", where none exists (anymore)");
821 if(
int npn = end_turn[
"next_player_number"].to_int(0); npn > 0) {
828 else if (
auto countdown_update = cfg->
optional_child(
"countdown_update"))
830 int val = countdown_update[
"value"];
831 int tval = countdown_update[
"team"];
833 std::stringstream errbuf;
834 errbuf <<
"Illegal countdown update \n"
835 <<
"Received update for :" << tval <<
" Current user :"
836 << side_num <<
"\n" <<
" Updated value :" << val;
843 else if ((*cfg)[
"dependent"].to_bool(
false))
857 DBG_REPLAY <<
"got an dependent action name = " << child_name;
875 LOG_REPLAY <<
"found commandname " << commandname <<
"in replay";
880 else if((*cfg)[
"side_invalid"].to_bool(
false)) {
881 ERR_REPLAY <<
"received a synced [command] from side " << (*cfg)[
"from_side"].to_int(0) <<
". Sent from wrong client.";
920 if(
data.empty() ==
false) {
934 if(
data.empty() ==
false) {
chat_msg(const config &cfg)
A config object defines a single node in a WML file, with access to child nodes.
const_all_children_iterator ordered_begin() const
boost::iterator_range< const_all_children_iterator > const_all_children_itors
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.
config & add_child_at(config_key_type key, const config &val, std::size_t index)
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
const_all_children_itors all_children_range() const
In-order iteration over all children.
child_itors child_range(config_key_type key)
config & child_or_add(config_key_type key)
Returns a reference to the first child with the given key.
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 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)
void recalculate_minimap()
Schedule the minimap for recalculation.
static display * get_singleton()
Returns the display object if a display object exists.
virtual const unit_map & units() const override
void set_phase(PHASE phase)
@ 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()
const terrain_label * set_label(const map_location &loc, const t_string &text, const int creator=-1, const std::string &team="", const color_t color=font::NORMAL_COLOR, const bool visible_in_fog=true, const bool visible_in_shroud=false, const bool immutable=false, const std::string &category="", const t_string &tooltip="")
void clear(const std::string &, bool force)
virtual void process_oos(const std::string &msg) const
Asks the user whether to continue on an OOS error.
virtual void send_to_wesnothd(const config &, const std::string &="unknown") const
void do_init_side()
Called by replay handler or init_side() to do actual work for turn change.
int current_side() const
Returns the number of the side whose turn it is.
replay_network_sender(replay &obj)
void delete_upcoming_commands()
config & get_upload_log()
config & get_command_at(int pos)
config & insert_command(int index)
void remove_command(int index)
void add_rename(const std::string &name, const map_location &loc)
config & add_nonundoable_command()
adds a new command to the command list at the current position.
bool add_start_if_not_there_yet()
void undo_cut(config &dst)
config & get_last_real_command()
void add_config(const config &cfg, MARK_SENT mark=MARK_AS_UNSENT)
void add_label(const terrain_label *)
void add_synced_command(const std::string &name, const config &command)
void end_turn(int next_player_number)
void add_surrender(int side_number)
void speak(const config &cfg)
void clear_labels(const std::string &, bool)
const std::vector< chat_msg > & build_chat_log() const
config & command(int) const
replay(replay_recorder_base &base)
void user_input(const std::string &name, const config &input, int from_side)
adds a user_input to the replay
void redo(const config &dst, bool set_to_end=false)
config get_data_range(int cmd_start, int cmd_end, DATA_TYPE data_type=ALL_DATA) const
void add_unit_checksum(const map_location &loc, config &cfg)
std::vector< int > message_locations
static void process_error(const std::string &msg)
void delete_upcoming_commands()
void add_countdown_update(int value, int team)
replay_recorder_base * base_
bool add_chat_message_location()
adds a chat message if it wasn't added yet.
void add_chat_log_entry(const config &speak, std::back_insert_iterator< std::vector< chat_msg >> &i) const
void add_log_data(const std::string &key, const std::string &var)
config & add_command()
Adds a new empty command to the command list at the end.
config * get_next_action()
static synced_state get_synced_state()
static bool run(const std::string &commandname, const config &data, bool use_undo=true, bool show=true, synced_command::error_handler_function error_handler=default_error_function)
Sets the context to 'synced', initialises random context, and calls the given function.
This class stores all the data for a single 'side' (in game nomenclature).
static std::string get_side_highlight_pango(int side)
void set_countdown_time(const int amount) const
To store label data Class implements logic for rendering.
Container associating units to locations.
std::size_t count(const map_location &loc) const
unit_iterator find(std::size_t id)
std::string label
What to show in the filter's drop-down list.
New lexcical_cast header.
void read_locations(const config &cfg, std::vector< map_location > &locs)
Parse x,y keys of a config into a vector of locations.
Standard logging facilities (interface).
#define log_scope(description)
bool is_ignored(const std::string &nick)
bool parse_should_show_lobby_join(const std::string &sender, const std::string &message)
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.
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
static void show_oos_error_error_function(const std::string &message)
static bool fix_rename_command(const config &c, config &async_child)
fixes a rename command when undoing a earlier command.
REPLAY_RETURN do_replay_handle(bool one_move)
static lg::log_domain log_replay("replay")
REPLAY_RETURN do_replay(bool one_move)
static lg::log_domain log_random("random")
static void verify(const unit_map &units, const config &cfg)
static std::time_t get_time(const config &speak)
static std::vector< chat_msg > message_log
Thrown when a lexical_cast fails.
Encapsulates the map of the game.
void write(config &cfg) const
static map_location::DIRECTION n
static map_location::DIRECTION s
Various functions that implement the undoing (and redoing) of in-game commands.
std::string get_checksum(const unit &u, backwards_compatibility::unit_checksum_version version)
Gets a checksum for a unit.