The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
pump.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2017 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Handles the current state of WML-events. This includes raising and firing,
18  * as well as tracking the context for event firing.
19  */
20 
21 #include "game_events/pump.hpp"
23 #include "game_events/handlers.hpp"
24 
25 #include "display_chat_manager.hpp"
26 #include "game_config.hpp"
27 #include "gettext.hpp"
28 #include "log.hpp"
29 #include "play_controller.hpp"
30 #include "resources.hpp"
32 #include "side_filter.hpp"
33 #include "units/map.hpp"
34 #include "units/unit.hpp"
35 #include "variable.hpp"
36 #include "whiteboard/manager.hpp"
37 
38 #include <iomanip>
39 #include <iostream>
40 
41 static lg::log_domain log_engine("engine");
42 #define DBG_NG LOG_STREAM(debug, log_engine)
43 #define LOG_NG LOG_STREAM(info, log_engine)
44 #define ERR_NG LOG_STREAM(err, log_engine)
45 
46 static lg::log_domain log_wml("wml");
47 #define DBG_WML LOG_STREAM(debug, log_wml)
48 #define LOG_WML LOG_STREAM(info, log_wml)
49 #define WRN_WML LOG_STREAM(warn, log_wml)
50 #define ERR_WML LOG_STREAM(err, log_wml)
51 
52 static lg::log_domain log_event_handler("event_handler");
53 #define DBG_EH LOG_STREAM(debug, log_event_handler)
54 
55 // This file is in the game_events namespace.
56 namespace game_events
57 {
58 namespace context
59 {
60 /// State when processing a particular flight of events or commands.
61 struct state
62 {
66 
67  explicit state(bool s, bool m = true)
68  : undo_disabled(m)
69  , action_canceled(false)
70  , skip_messages(s)
71  {
72  }
73 };
74 
75 class scoped
76 {
77 public:
78  scoped(std::stack<context::state>& contexts, bool m = true);
79  ~scoped();
80 
81 private:
82  std::stack<context::state>& contexts_;
83 };
84 }
85 
86 struct pump_impl
87 {
88  std::vector<queued_event> events_queue;
89 
90  /// The value returned by wml_tracking();
92 
93  std::stringstream wml_messages_stream;
94 
95  std::stack<context::state> contexts_;
96 
97  unsigned instance_count;
98 
100 
102  : events_queue()
103  , internal_wml_tracking(0)
104  , wml_messages_stream()
105  , contexts_()
106  , instance_count(0)
107  , my_manager(&man)
108  {
109  contexts_.emplace(false);
110  }
111 };
112 
113 namespace
114 { // Types
115 class pump_manager
116 {
117 public:
118  pump_manager(pump_impl&);
119  ~pump_manager();
120 
121  /// Allows iteration through the queued events.
122  queued_event& next()
123  {
124  return queue_[pumped_count_++];
125  }
126  /// Indicates the iteration is over.
127  bool done() const
128  {
129  return pumped_count_ >= queue_.size();
130  }
131 
132  unsigned count() const
133  {
134  return impl_.instance_count;
135  }
136 
137 private:
138  pump_impl& impl_;
139  int x1_, x2_, y1_, y2_;
140 
141  /**
142  * Tracks the events to process.
143  * This isolates these events from any events that might be generated during the processing.
144  */
145  std::vector<queued_event> queue_;
146 
147  /** Tracks how many events have been processed. */
149 };
150 } // end anonymous namespace (types)
151 
152 namespace
153 { // Support functions
154 
155 pump_manager::pump_manager(pump_impl& impl)
156  : impl_(impl)
157  , x1_(resources::gamedata->get_variable("x1"))
158  , x2_(resources::gamedata->get_variable("x2"))
159  , y1_(resources::gamedata->get_variable("y1"))
160  , y2_(resources::gamedata->get_variable("y2"))
161  , queue_()
162  , pumped_count_(0) // Filled later with a swap().
163 {
164  queue_.swap(impl_.events_queue);
166 }
167 
168 pump_manager::~pump_manager()
169 {
171 
172  // Not sure what the correct thing to do is here. In princple,
173  // discarding all events (i.e. clearing events_queue) seems like
174  // the right thing to do in the face of an exception. However, the
175  // previous functionality preserved the queue, so for now we will
176  // restore it.
177  if(!done()) {
178  // The remaining events get inserted at the beginning of events_queue.
179  std::vector<queued_event> temp;
180  impl_.events_queue.swap(temp);
181  impl_.events_queue.insert(impl_.events_queue.end(), queue_.begin() + pumped_count_, queue_.end());
182  impl_.events_queue.insert(impl_.events_queue.end(), temp.begin(), temp.end());
183  }
184 
185  // Restore the old values of the game variables.
190 }
191 }
192 
193 /**
194  * Returns true iff the given event passes all its filters.
195  */
197 {
199  unit_map::const_iterator unit1 = units.find(ev.loc1);
200  unit_map::const_iterator unit2 = units.find(ev.loc2);
201  vconfig filters(handler.get_config());
202 
203  for(const vconfig& condition : filters.get_children("filter_condition")) {
204  if(!conditional_passed(condition)) {
205  return false;
206  }
207  }
208 
209  for(const vconfig& f : filters.get_children("filter_side")) {
210  side_filter ssf(f, &resources::controller->gamestate());
212  return false;
213  }
214 
215  for(const vconfig& f : filters.get_children("filter")) {
216  if(!ev.loc1.matches_unit_filter(unit1, f)) {
217  return false;
218  }
219  }
220 
221  vconfig::child_list special_filters = filters.get_children("filter_attack");
222  bool special_matches = special_filters.empty();
223  if(!special_matches && unit1 != units.end()) {
224  const bool matches_unit = ev.loc1.matches_unit(unit1);
225  const config& attack = ev.data.child("first");
226  for(const vconfig& f : special_filters) {
227  if(f.empty()) {
228  special_matches = true;
229  } else if(!matches_unit) {
230  return false;
231  }
232 
233  special_matches = special_matches || matches_special_filter(attack, f);
234  }
235  }
236 
237  if(!special_matches) {
238  return false;
239  }
240 
241  for(const vconfig& f : filters.get_children("filter_second")) {
242  if(!ev.loc2.matches_unit_filter(unit2, f)) {
243  return false;
244  }
245  }
246 
247  special_filters = filters.get_children("filter_second_attack");
248  special_matches = special_filters.empty();
249  if(!special_matches && unit2 != units.end()) {
250  const bool matches_unit = ev.loc2.matches_unit(unit2);
251  const config& attack = ev.data.child("second");
252  for(const vconfig& f : special_filters) {
253  if(f.empty()) {
254  special_matches = true;
255  } else if(!matches_unit) {
256  return false;
257  }
258 
259  special_matches = special_matches || matches_special_filter(attack, f);
260  }
261  }
262 
263  if(!special_matches) {
264  return false;
265  }
266 
267  // All filters passed.
268  return true;
269 }
270 
271 /**
272  * Processes an event through a single event handler.
273  * This includes checking event filters, but not checking that the event
274  * name matches.
275  *
276  * @param[in,out] handler_p The handler to offer the event to.
277  * This may be reset during processing.
278  * @param[in] ev The event information.
279  */
281 {
282  DBG_EH << "processing event " << ev.name << " with id=" << ev.id << "\n";
283 
284  // We currently never pass a null pointer to this function, but to
285  // guard against future modifications:
286  if(!handler_p) {
287  return;
288  }
289 
291  scoped_xy_unit first_unit("unit", ev.loc1, units);
292  scoped_xy_unit second_unit("second_unit", ev.loc2, units);
293  scoped_weapon_info first_weapon("weapon", ev.data.child("first"));
294  scoped_weapon_info second_weapon("second_weapon", ev.data.child("second"));
295 
296  if(!filter_event(*handler_p, ev)) {
297  return;
298  }
299 
300  // The event hasn't been filtered out, so execute the handler.
301  ++impl_->internal_wml_tracking;
302  context::scoped evc(impl_->contexts_);
303  assert(resources::lua_kernel != nullptr);
304  handler_p->handle_event(ev, *resources::lua_kernel);
305  // NOTE: handler_p may be null at this point!
306 
307  if(ev.name == "select") {
309  }
310 
311  if(resources::screen != nullptr) {
313  }
314 }
315 
316 /**
317  * Helper function for show_wml_messages(), which gathers
318  * the messages from a stringstream.
319  */
320 void wml_event_pump::fill_wml_messages_map(std::map<std::string, int>& msg_map, std::stringstream& source)
321 {
322  while(true) {
324  std::getline(source, msg);
325 
326  if(source.eof()) {
327  break;
328  }
329 
330  if(msg.empty()) {
331  continue;
332  }
333 
334  if(msg_map.find(msg) == msg_map.end()) {
335  msg_map[msg] = 1;
336  } else {
337  msg_map[msg]++;
338  }
339  }
340 
341  // Make sure the eof flag is cleared otherwise no new messages are shown
342  source.clear();
343 }
344 
345 /**
346  * Shows a summary of messages/errors generated so far by WML.
347  * Identical messages are shown once, with (between parentheses)
348  * the number of times that message was encountered.
349  * The order in which the messages are shown does not need
350  * to be the order in which these messages are encountered.
351  * Messages are also written to std::cerr if to_cerr is true.
352  */
353 void wml_event_pump::show_wml_messages(std::stringstream& source, const std::string& caption, bool to_cerr)
354 {
355  // Get all unique messages in messages,
356  // with the number of encounters for these messages
357  std::map<std::string, int> messages;
358  fill_wml_messages_map(messages, source);
359 
360  // Show the messages collected
361  for(std::map<std::string, int>::const_iterator itor = messages.begin(); itor != messages.end(); ++itor) {
362  std::stringstream msg;
363  msg << itor->first;
364  if(itor->second > 1) {
365  msg << " (" << itor->second << ")";
366  }
367 
369  time(nullptr), caption, 0, msg.str(), events::chat_handler::MESSAGE_PUBLIC, false);
370 
371  if(to_cerr) {
372  std::cerr << caption << ": " << msg.str() << '\n';
373  }
374  }
375 }
376 
377 /**
378  * Shows a summary of the errors encountered in WML so far,
379  * to avoid a lot of the same messages to be shown.
380  * Identical messages are shown once, with (between parentheses)
381  * the number of times that message was encountered.
382  * The order in which the messages are shown does not need
383  * to be the order in which these messages are encountered.
384  * Messages are always written to std::cerr.
385  */
387 {
388  static const std::string caption("Invalid WML found");
389 
390  show_wml_messages(lg::wml_error(), caption, true);
391 }
392 
393 /**
394  * Shows a summary of the messages generated so far by WML.
395  * Identical messages are shown once, with (between parentheses)
396  * the number of times that message was encountered.
397  * The order in which the messages are shown does not need
398  * to be the order in which these messages are encountered.
399  */
401 {
402  static const std::string caption("WML");
403 
404  show_wml_messages(impl_->wml_messages_stream, caption, false);
405 }
406 
408  lg::logger& logger, const std::string& prefix, const std::string& message, bool in_chat)
409 {
410  logger(log_wml) << message << std::endl;
411  if(in_chat) {
412  impl_->wml_messages_stream << prefix << message << std::endl;
413  }
414 }
415 
416 context::scoped::scoped(std::stack<context::state>& contexts, bool m)
417  : contexts_(contexts)
418 {
419  // The default context at least should always be on the stack
420  assert(contexts_.size() > 0);
421 
422  bool skip_messages = (contexts_.size() > 1) && contexts_.top().skip_messages;
423  contexts_.emplace(skip_messages, m);
424 }
425 
427 {
428  assert(contexts_.size() > 1);
429  bool undo_disabled = contexts_.top().undo_disabled;
430  bool action_canceled = contexts_.top().action_canceled;
431 
432  contexts_.pop();
433  contexts_.top().undo_disabled |= undo_disabled;
434  contexts_.top().action_canceled |= action_canceled;
435 }
436 
438 {
439  assert(impl_->contexts_.size() > 0);
440  return impl_->contexts_.top().undo_disabled;
441 }
442 
444 {
445  assert(impl_->contexts_.size() > 0);
446  impl_->contexts_.top().undo_disabled = b;
447 }
448 
450 {
451  assert(impl_->contexts_.size() > 0);
452  return impl_->contexts_.top().action_canceled;
453 }
454 
456 {
457  assert(impl_->contexts_.size() > 0);
458  impl_->contexts_.top().action_canceled = true;
459 }
460 
461 
463 {
464  assert(impl_->contexts_.size() > 0);
465  return impl_->contexts_.top().skip_messages;
466 }
467 
469 {
470  assert(impl_->contexts_.size() > 0);
471  impl_->contexts_.top().skip_messages = b;
472 }
473 
474 /**
475  * Helper function which determines whether a wml_message text can
476  * really be pushed into the wml_messages_stream, and does it.
477  */
478 void wml_event_pump::put_wml_message(const std::string& logger, const std::string& message, bool in_chat)
479 {
480  if(logger == "err" || logger == "error") {
481  put_wml_message(lg::err(), _("Error: "), message, in_chat);
482  } else if(logger == "warn" || logger == "wrn" || logger == "warning") {
483  put_wml_message(lg::warn(), _("Warning: "), message, in_chat);
484  } else if((logger == "debug" || logger == "dbg") && !lg::debug().dont_log(log_wml)) {
485  put_wml_message(lg::debug(), _("Debug: "), message, in_chat);
486  } else if(!lg::info().dont_log(log_wml)) {
487  put_wml_message(lg::info(), _("Info: "), message, in_chat);
488  }
489 }
490 
492  const std::string& event, const entity_location& loc1, const entity_location& loc2, const config& data)
493 {
494  raise(event, loc1, loc2, data);
495  return (*this)();
496 }
497 
499  const std::string& id,
500  const entity_location& loc1,
501  const entity_location& loc2,
502  const config& data)
503 {
504  raise(event, id, loc1, loc2, data);
505  return (*this)();
506 }
507 
509  const std::string& id,
510  const entity_location& loc1,
511  const entity_location& loc2,
512  const config& data)
513 {
514  if(resources::screen == nullptr)
515  return;
516 
517  DBG_EH << "raising event name=" << event << ", id=" << id << "\n";
518 
519  impl_->events_queue.emplace_back(event, id, loc1, loc2, data);
520 }
521 
523 {
524  // Quick aborts:
525  if(resources::screen == nullptr) {
526  return pump_result_t();
527  }
528 
529  assert(resources::lua_kernel != nullptr);
530  if(impl_->events_queue.empty()) {
531  DBG_EH << "Processing queued events, but none found.\n";
532  return pump_result_t();
533  }
534 
535  if(impl_->instance_count >= game_config::max_loop) {
536  ERR_NG << "game_events pump waiting to process new events because "
537  << "recursion level would exceed maximum: " << game_config::max_loop << '\n';
538  return pump_result_t();
539  }
540 
541  if(!lg::debug().dont_log("event_handler")) {
542  std::stringstream ss;
543  for(const queued_event& ev : impl_->events_queue) {
544  ss << "name=" << ev.name << ", "
545  << "id=" << ev.id << "; ";
546  }
547  DBG_EH << "processing queued events: " << ss.str() << "\n";
548  }
549 
550  const size_t old_wml_track = impl_->internal_wml_tracking;
551 
552  // Ensure the whiteboard doesn't attempt to build its future unit map
553  // while events are being processed.
554  wb::real_map real_unit_map;
555 
556  pump_manager pump_instance(*impl_);
557  context::scoped evc(impl_->contexts_, false);
558  // Loop through the events we need to process.
559  while(!pump_instance.done()) {
560  queued_event& ev = pump_instance.next();
561 
562  if(ev.name.empty() && ev.id.empty()) {
563  continue;
564  }
565 
566  const std::string& event_name = ev.name;
567  const std::string& event_id = ev.id;
568 
569  // Clear the unit cache, since the best clearing time is hard to figure out
570  // due to status changes by WML. Every event will flush the cache.
572 
573  { // Block for context::scoped
574  context::scoped inner_evc(impl_->contexts_, false);
575  if(resources::lua_kernel->run_event(ev)) {
576  // TODO: since feeding was moved to lua we _always_ have a lua on_event handler so
577  // lua_kernel->run_event always returns true. So maybe we should remove this
578  // internal_wml_tracking thing (in particular the 'optimisation' in the movement code)?
579  ++impl_->internal_wml_tracking;
580  }
581  }
582 
583  assert(impl_->my_manager);
584 
589 
590  if(event_id.empty()) {
591  // Handle events of this name.
592  impl_->my_manager->execute_on_events(event_name, [&](game_events::manager&, handler_ptr& ptr) {
593  DBG_EH << "processing event " << event_name << " with id=" << ptr->get_config()["id"] << "\n";
594 
595  // Let this handler process our event.
596  process_event(ptr, ev);
597  });
598  } else {
599  // Get the handler directly via ID
600  handler_ptr cur_handler = impl_->my_manager->get_event_handler_by_id(event_id);
601 
602  if(cur_handler) {
603  DBG_EH << "processing event " << event_name << " with id=" << cur_handler->get_config()["id"] << "\n";
604  process_event(cur_handler, ev);
605  }
606  }
607 
608  // Flush messages when finished iterating over event_handlers.
609  flush_messages();
610  }
611 
612  if(old_wml_track != impl_->internal_wml_tracking) {
613  // Notify the whiteboard of any event.
614  // This is used to track when moves, recruits, etc. happen.
615  resources::whiteboard->on_gamestate_change();
616  }
617 
618  return std::make_tuple(undo_disabled(), action_canceled());
619 }
620 
622 {
623  // Dialogs can only be shown if the display is not locked
624  if(resources::screen && !CVideo::get_singleton().update_locked()) {
625  show_wml_errors();
626  show_wml_messages();
627  }
628 }
629 
630 /**
631  * This function can be used to detect when no WML/Lua has been executed.
632  *
633  * If two calls to this function return the same value, then one can
634  * assume that the usual game mechanics have been followed, and code does
635  * not have to account for all the things WML/Lua can do. If the return
636  * values are different, then something unusual might have happened between
637  * those calls.
638  *
639  * This is not intended as a precise metric. Rather, it is motivated by
640  * how large the number of fired WML events is, compared to the (typical)
641  * number of WML event handlers. It is intended for code that can benefit
642  * from caching some aspect of the game state and that cannot rely on
643  * [allow_undo] not being used when that state changes.
644  */
646 {
647  return impl_->internal_wml_tracking;
648 }
649 
651  : impl_(new pump_impl(man))
652 {
653 }
654 
656 {
657 }
658 
659 } // end namespace game_events
play_controller * controller
Definition: resources.cpp:21
manager * my_manager
Definition: pump.cpp:99
int x2_
Definition: pump.cpp:139
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:400
std::vector< queued_event > queue_
Tracks the events to process.
Definition: pump.cpp:145
virtual const unit_map & units() const
Definition: game_board.hpp:97
unit_iterator end()
Definition: map.hpp:415
std::vector< char_t > string
entity_location loc2
Definition: pump.hpp:65
State when processing a particular flight of events or commands.
Definition: pump.cpp:61
map_location last_selected
the last location where a select event fired.
Definition: game_data.hpp:83
#define ERR_NG
Definition: pump.cpp:44
wml_event_pump(manager &)
Definition: pump.cpp:650
bool match(const team &t) const
logger & info()
Definition: log.cpp:91
game_display * screen
Definition: resources.cpp:27
std::stringstream wml_messages_stream
Definition: pump.cpp:93
static CVideo & get_singleton()
Definition: video.hpp:43
std::string name
Definition: pump.hpp:62
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:110
int wml_y() const
Definition: location.hpp:116
scoped(std::stack< context::state > &contexts, bool m=true)
Definition: pump.cpp:416
bool action_canceled()
Returns whether or not wml wants to abort the currently executed user action.
Definition: pump.cpp:449
game_data * gamedata
Definition: resources.cpp:22
config::attribute_value & get_variable(const std::string &varname)
throws invalid_variablename_exception if varname is no valid variable name.
Definition: game_data.cpp:62
#define b
int x1_
Definition: pump.cpp:139
int y2_
Definition: pump.cpp:139
size_t wml_tracking()
This function can be used to detect when no WML/Lua has been executed.
Definition: pump.cpp:645
static lg::log_domain log_engine("engine")
static void clear_status_caches()
Clear this unit status cache for all units.
Definition: unit.cpp:617
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:89
const map_location & filter_loc() const
int wml_x() const
Definition: location.hpp:115
int current_side() const
Returns the number of the side whose turn it is.
child_list get_children(const std::string &key) const
Definition: variable.cpp:190
void show_wml_messages()
Shows a summary of the messages generated so far by WML.
Definition: pump.cpp:400
pump_impl(manager &man)
Definition: pump.cpp:101
game_board * gameboard
Definition: resources.cpp:20
const size_t max_loop
The maximum number of hexes on a map and items in an array and also used as maximum in wml loops...
bool matches_unit_filter(const unit_map::const_iterator &un_it, const vconfig &filter) const
Determines if un_it matches filter.
std::vector< queued_event > events_queue
Definition: pump.cpp:88
void flush_messages()
Flushes WML messages and errors.
Definition: pump.cpp:621
void show_wml_errors()
Shows a summary of the errors encountered in WML so far, to avoid a lot of the same messages to be sh...
Definition: pump.cpp:386
logger & debug()
Definition: log.cpp:97
static lg::log_domain log_event_handler("event_handler")
const config & get_config() const
Definition: handlers.hpp:64
Domain specific events.
Definition: action_wml.cpp:88
int y1_
Definition: pump.cpp:139
std::shared_ptr< wb::manager > whiteboard
Definition: resources.cpp:35
state(bool s, bool m=true)
Definition: pump.cpp:67
Define conditionals for the game's events mechanism, a.k.a.
void put_wml_message(const std::string &logger, const std::string &message, bool in_chat)
Helper function which determines whether a wml_message text can really be pushed into the wml_message...
Definition: pump.cpp:478
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
Definition: log.cpp:269
logger & err()
Definition: log.cpp:79
void raise(const std::string &event, const std::string &id, const entity_location &loc1=entity_location::null_entity, const entity_location &loc2=entity_location::null_entity, const config &data=config())
Definition: pump.cpp:508
bool undo_disabled()
Context: The general environment within which events are processed.
Definition: pump.cpp:437
bool matches_special_filter(const config &cfg, const vconfig &filter)
void set_action_canceled()
Sets whether or not wml wants to abort the currently executed user action.
Definition: pump.cpp:455
static map_location::DIRECTION s
pump_result_t operator()()
Definition: pump.cpp:522
pump_impl & impl_
Definition: pump.cpp:138
Define the game's event mechanism.
#define DBG_EH
Definition: pump.cpp:53
The game event manager loads the scenario configuration object, and ensures that events are handled a...
Definition: manager.hpp:43
static lg::log_domain log_wml("wml")
void process_event(handler_ptr &handler_p, const queued_event &ev)
Processes an event through a single event handler.
Definition: pump.cpp:280
pump_result_t fire(const std::string &event, const entity_location &loc1=entity_location::null_entity, const entity_location &loc2=entity_location::null_entity, const config &data=config())
Function to fire an event.
Definition: pump.cpp:491
entity_location loc1
Definition: pump.hpp:64
#define next(ls)
Definition: llex.cpp:32
display_chat_manager & get_chat_manager()
bool conditional_passed(const vconfig &cond)
bool matches_unit(const unit_map::const_iterator &un_it) const
Determines if un_it matches (using underlying ID) the unit that was supplied when this was constructe...
const std::unique_ptr< pump_impl > impl_
Definition: pump.hpp:74
Define the handlers for the game's events mechanism.
logger & warn()
Definition: log.cpp:85
#define f
unsigned instance_count
Definition: pump.cpp:97
bool filter_event(const event_handler &handler, const queued_event &ev)
Returns true iff the given event passes all its filters.
Definition: pump.cpp:196
void set_undo_disabled(bool mutated)
[allow_undo] implementation
Definition: pump.cpp:443
A variable-expanding proxy for the config class.
Definition: variable.hpp:42
Standard logging facilities (interface).
game_lua_kernel * lua_kernel
Definition: resources.cpp:25
Container associating units to locations.
Definition: map.hpp:99
void fill_wml_messages_map(std::map< std::string, int > &msg_map, std::stringstream &source)
Helper function for show_wml_messages(), which gathers the messages from a stringstream.
Definition: pump.cpp:320
std::stack< context::state > contexts_
Definition: pump.cpp:95
std::stack< context::state > & contexts_
Definition: pump.cpp:82
unit_iterator find(size_t id)
Definition: map.cpp:311
std::vector< vconfig > child_list
Definition: variable.hpp:78
std::shared_ptr< event_handler > handler_ptr
Definition: fwd.hpp:24
size_t internal_wml_tracking
The value returned by wml_tracking();.
Definition: pump.cpp:91
std::tuple< bool, bool > pump_result_t
Definition: fwd.hpp:28
Ensures that the real unit map is active for the duration of the struct's life.
Definition: manager.hpp:282
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
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)
unit_map * units
Definition: resources.cpp:34
size_t pumped_count_
Tracks how many events have been processed.
Definition: pump.cpp:148
bool maybe_rebuild()
Rebuilds the screen if needs_rebuild(true) was previously called, and resets the flag.
bool context_skip_messages()
Returns whether or not we are skipping messages.
Definition: pump.cpp:462