44 #include <boost/lexical_cast.hpp>
49 #define DBG_REPLAY LOG_STREAM(debug, log_replay)
50 #define LOG_REPLAY LOG_STREAM(info, log_replay)
51 #define WRN_REPLAY LOG_STREAM(warn, log_replay)
52 #define ERR_REPLAY LOG_STREAM(err, log_replay)
55 #define DBG_RND LOG_STREAM(debug, log_random)
56 #define LOG_RND LOG_STREAM(info, log_random)
57 #define WRN_RND LOG_STREAM(warn, log_random)
58 #define ERR_RND LOG_STREAM(err, log_random)
64 std::stringstream errbuf;
67 const size_t nunits = cfg[
"num_units"].to_size_t();
68 if(nunits != units.
size()) {
69 errbuf <<
"SYNC VERIFICATION FAILED: number of units from data source differ: "
70 << nunits <<
" according to data source. " << units.
size() <<
" locally\n";
72 std::set<map_location> locs;
78 if(units.
count(loc) == 0) {
79 errbuf <<
"data source says there is a unit at "
80 << loc <<
" but none found locally\n";
85 if (locs.count(j->get_location()) == 0) {
86 errbuf <<
"local unit at " << j->get_location()
87 <<
" but none in data source\n";
98 if(u == units.
end()) {
99 errbuf <<
"SYNC VERIFICATION FAILED: data source says there is a '"
100 << un[
"type"] <<
"' (side " << un[
"side"] <<
") at "
101 << loc <<
" but there is no local record of it\n";
110 static const std::string fields[] = {
"type",
"hitpoints",
"experience",
"side",
""};
111 for(
const std::string* str = fields; str->empty() ==
false; ++str) {
112 if (cfg[*str] != un[*str]) {
113 errbuf <<
"ERROR IN FIELD '" << *str <<
"' for unit at "
114 << loc <<
" data source: '" << un[*str]
115 <<
"' local: '" << cfg[*str] <<
"'\n";
121 errbuf <<
"(SYNC VERIFICATION FAILED)\n";
133 if (!speak[
"time"].empty())
135 std::stringstream ss(speak[
"time"].str());
141 time = ::time(
nullptr);
149 ,
text_(cfg[
"message"].str())
154 nick_ = cfg[
"id"].str();
156 nick_ =
"*"+cfg[
"id"].str()+
"*";
158 int side = cfg[
"side"].to_int(0);
159 LOG_REPLAY <<
"side in message: " << side << std::endl;
184 , message_locations()
237 val[
"value"] =
value;
254 cmd[
"dependent"] =
true;
257 cmd[
"from_side"] =
"server";
261 cmd[
"from_side"] = from_side;
282 val[
"team_name"] = team_name;
283 val[
"force"] = force;
362 std::vector<int>::reverse_iterator loc_it;
377 int last_location = 0;
378 std::back_insert_iterator<std::vector < chat_msg > > chat_log_appender( back_inserter(message_log));
381 last_location = *loc_it;
395 for (
int cmd = cmd_start; cmd < cmd_end; ++cmd)
400 if ((data_type ==
ALL_DATA || !cc[
"undo"].to_bool(
true)) && !cc[
"sent"].to_bool(
false))
425 for (
int cmd_num =
base_->
get_pos() - 1; cmd_num >= 0; --cmd_num)
429 if (cc[
"dependent"].to_bool(
false) || !cc[
"undo"].to_bool(
true) || cc[
"async"].to_bool(
false))
435 ERR_REPLAY <<
"replay::get_last_real_command called with no existent command." << std::endl;
436 assert(
false &&
"replay::get_last_real_command called with no existent command.");
437 throw "replay::get_last_real_command called with no existent command.";
447 std::vector<map_location> steps;
452 WRN_REPLAY <<
"Warning: Path data contained something which could not be parsed to a sequence of locations:" <<
"\n config = " << child.debug() << std::endl;
456 ERR_REPLAY <<
"trying to undo a move using an empty path";
462 if (dst == aloc) src.
write(async_child);
468 if (!*chld) chld = &c.
child(
"recall");
490 for (; cmd_index >= 0; --cmd_index)
497 if(c[
"undo"].to_bool(
true) && !c[
"async"].to_bool(
false) && !c[
"dependent"].to_bool(
false))
499 if(c[
"sent"].to_bool(
false))
501 ERR_REPLAY <<
"trying to undo a command that was already sent.\n";
513 ERR_REPLAY <<
"trying to undo a command but no command was found.\n";
521 if(!cc[
"undo"].to_bool(
true))
525 else if(cc[
"async"].to_bool(
false))
536 else if(cc[
"dependent"].to_bool(
false) ||
i == cmd_index)
544 ERR_REPLAY <<
"Coudn't handle command:\n" << cc <<
"\nwhen undoing.\n";
688 DBG_REPLAY <<
"in do replay with is_synced=" << is_synced <<
"\n";
692 DBG_REPLAY <<
"Replay data:\n" << *cfg <<
"\n";
703 if (ch_itors.first == ch_itors.second || cfg->
has_child(
"start"))
710 else if (
const config &child = cfg->
child(
"speak"))
716 bool is_whisper = (speaker_name.find(
"whisper: ") == 0);
718 DBG_REPLAY <<
"tried to add a chat message twice.\n";
720 int side = child[
"side"];
728 else if (
const config &child = cfg->
child(
"label"))
738 else if (
const config &child = cfg->
child(
"clear_labels"))
742 else if (
const config &child = cfg->
child(
"rename"))
748 if (u.
valid() && !u->unrenamable()) {
757 WRN_REPLAY <<
"attempt to rename unit at location: "
758 << loc << (u.
valid() ?
", which is unrenamable" :
", where none exists (anymore)") <<
"\n";
762 else if (cfg->
child(
"init_side"))
781 else if (cfg->
child(
"end_turn"))
798 else if (
const config &child = cfg->
child(
"countdown_update"))
800 int val = child[
"value"];
801 int tval = child[
"team"];
803 std::stringstream errbuf;
804 errbuf <<
"Illegal countdown update \n"
805 <<
"Received update for :" << tval <<
" Current user :"
806 << side_num <<
"\n" <<
" Updated value :" <<
val;
810 (*resources::teams)[tval - 1].set_countdown_time(val);
813 else if ((*cfg)[
"dependent"].to_bool(
false))
827 DBG_REPLAY <<
"got an dependent action name = " << child_name <<
"\n";
845 LOG_REPLAY <<
"found commandname " << commandname <<
"in replay";
850 else if((*cfg)[
"side_invalid"].to_bool(
false)) {
851 ERR_REPLAY <<
"recieved a synced [command] from side " << (*cfg)[
"from_side"].to_int(0) <<
". Sent from wrong client.\n";
890 if(data.
empty() ==
false) {
904 if(data.
empty() ==
false) {
play_controller * controller
child_itors child_range(const std::string &key)
void delete_upcoming_commands()
void read_locations(const config &cfg, std::vector< map_location > &locs)
Parse x,y keys of a config into a vector of locations.
virtual void send_to_wesnothd(const config &, const std::string &="unknown") const
replay(replay_recorder_base &base)
replay_network_sender(replay &obj)
void add_countdown_update(int value, int team)
config & get_upload_log()
void speak(const config &cfg)
bool add_chat_message_location()
adds a chat message if it wasn't added yet.
size_t count(const map_location &loc) const
virtual void process_oos(const std::string &msg) const
Asks the user whether to continue on an OOS error.
void add_log_data(const std::string &key, const std::string &var)
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.
config & child_or_add(const std::string &key)
Returns a reference to the first child with the given key.
const map_location & location() const
GLenum GLenum GLenum input
config & insert_command(int index)
GLuint const GLfloat * val
REPLAY_RETURN do_replay(bool one_move)
std::string debug() const
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
config & get_last_real_command()
tformula< t_string > text_
The text to draw.
replay_recorder_base * base_
void add_synced_command(const std::string &name, const config &command)
static std::string get_side_highlight_pango(int side)
const terrain_label * set_label(const map_location &loc, const t_string &text, const int creator=-1, const std::string &team="", const SDL_Color 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="")
const std::string & team_name() const
static time_t get_time(const config &speak)
bool has_child(const std::string &key) const
Determine whether a config has a child or not.
static void show_oos_error_error_function(const std::string &message, bool)
const SDL_Color & color() const
static void verify(const unit_map &units, const config &cfg)
This class stores all the data for a single 'side' (in game nomenclature).
const t_string & text() const
void redo(const config &dst)
int current_side() const
Returns the number of the side whose turn it is.
bool add_start_if_not_there_yet()
std::vector< team > * teams
void remove_command(int index)
void clear(const std::string &, bool force)
void recalculate_minimap()
Schedule the minimap for recalculation.
GLsizei const GLfloat * value
all_children_itors all_children_range() const
In-order iteration over all children.
std::pair< all_children_iterator, all_children_iterator > all_children_itors
config & add_child(const std::string &key)
void add_rename(const std::string &name, const map_location &loc)
void add_chat_log_entry(const config &speak, std::back_insert_iterator< std::vector< chat_msg > > &i) const
bool is_ignored(const std::string &nick)
void write(config &cfg) const
static std::vector< chat_msg > message_log
void add_unit_checksum(const map_location &loc, config &cfg)
config & get_command_at(int pos)
void do_init_side()
Called by replay handler or init_side() to do actual work for turn change.
Encapsulates the map of the game.
static void process_error(const std::string &msg)
std::string get_checksum(const unit &u)
Gets a checksum for a unit.
#define log_scope(description)
static std::string flush(std::ostringstream &s)
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
const std::vector< chat_msg > & build_chat_log()
GLdouble GLdouble GLdouble r
void write(config &res) const
GLuint const GLchar * name
display_chat_manager & get_chat_manager()
To store label data Class implements logic for rendering.
config & add_nonundoable_command()
adds a new command to the command list at the current position.
static lg::log_domain log_replay("replay")
bool find(E event, F functor)
Tests whether an event handler is available.
void add_config(const config &cfg, MARK_SENT mark=MARK_AS_UNSENT)
std::vector< int > message_locations
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
unsigned all_children_count() const
Various functions that implement the undoing (and redoing) of in-game commands.
void undo_cut(config &dst)
Standard logging facilities (interface).
Container associating units to locations.
config * get_next_action()
void delete_upcoming_commands()
GLsizei GLenum GLuint GLuint GLsizei char * message
bool parse_should_show_lobby_join(const std::string &sender, const std::string &message)
boost::shared_ptr< wb::manager > whiteboard
config & add_command()
Adds a new empty command to the command list at the end.
config get_data_range(int cmd_start, int cmd_end, DATA_TYPE data_type=ALL_DATA)
unit_iterator find(size_t id)
static lg::log_domain log_random("random")
void user_input(const std::string &, const config &, int from_side)
adds a user_input to the replay
A config object defines a single node in a WML file, with access to child nodes.
void add_chat_message(const time_t &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
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)
Thrown when a lexical_cast fails.
void clear_labels(const std::string &, bool)
GLsizei const GLcharARB ** string
config & add_child_at(const std::string &key, const config &val, unsigned index)
chat_msg(const config &cfg)
all_children_iterator ordered_begin() const
void add_label(const terrain_label *)