The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
undo_action.cpp
Go to the documentation of this file.
1 #include "undo_action.hpp"
3 #include "resources.hpp"
4 #include "variable.hpp" // vconfig
5 #include "game_data.hpp"
6 #include "units/unit.hpp"
7 
8 #include <cassert>
9 #include <iterator>
10 #include <algorithm>
11 
12 namespace actions
13 {
14 
16  : commands(cmds)
17  , data(ctx.data)
18  , loc1(ctx.loc1)
19  , loc2(ctx.loc2)
20  , filter_loc1(ctx.loc1.filter_x(), ctx.loc1.filter_y())
21  , filter_loc2(ctx.loc2.filter_x(), ctx.loc2.filter_y())
22  , uid1(), uid2()
23 {
24  unit_const_ptr u1 = ctx.loc1.get_unit(), u2 = ctx.loc2.get_unit();
25  if(u1) {
26  id1 = u1->id();
27  uid1 = u1->underlying_id();
28  }
29  if(u2) {
30  id2 = u2->id();
31  uid2 = u2->underlying_id();
32  }
33 }
34 
35 undo_event::undo_event(const config& first, const config& second, const config& weapons, const config& cmds)
36  : commands(cmds)
37  , data(weapons)
38  , loc1(first["x"], first["y"])
39  , loc2(second["x"], second["y"])
40  , filter_loc1(first["filter_x"], first["filter_y"])
41  , filter_loc2(second["filter_x"], second["filter_y"])
42  , uid1(first["underlying_id"])
43  , uid2(second["underlying_id"])
44  , id1(first["id"])
45  , id2(second["id"])
46 {
47 }
48 
51  , replay_data()
52  , unit_id_diff(synced_context::get_unit_id_diff())
53 {
56  auto command_transformer = [](const std::pair<config, game_events::queued_event>& p) {
57  return undo_event(p.first, p.second);
58  };
59  std::transform(undo.begin(), undo.end(), std::back_inserter(umc_commands_undo), command_transformer);
60  std::transform(redo.begin(), redo.end(), std::back_inserter(umc_commands_redo), command_transformer);
61  undo.clear();
62  redo.clear();
63 }
64 
67  , replay_data(cfg.child_or_empty("replay_data"))
68  , unit_id_diff(cfg["unit_id_diff"])
69 {
70  read_event_vector(umc_commands_undo, cfg, "undo_actions");
71  read_event_vector(umc_commands_redo, cfg, "redo_actions");
72 }
73 
74 namespace {
75  unit_ptr get_unit(size_t uid, const std::string& id) {
76  assert(resources::units);
77  auto iter = resources::units->find(uid);
78  if(!iter.valid() || iter->id() != id) {
79  return nullptr;
80  }
81  return iter.get_shared_ptr();
82  }
83  void execute_event(const undo_event& e, std::string tag) {
84  assert(resources::lua_kernel);
85  assert(resources::gamedata);
86 
91  int oldx1 = x1, oldy1 = y1, oldx2 = x2, oldy2 = y2;
92  x1 = e.filter_loc1.x + 1; y1 = e.filter_loc1.y + 1;
93  x2 = e.filter_loc2.x + 1; y2 = e.filter_loc2.y + 1;
94 
95  int realx1 = 0, realy1 = 0, realx2 = 0, realy2 = 0;
96  boost::scoped_ptr<scoped_xy_unit> u1, u2;
97  if(unit_ptr who = get_unit(e.uid1, e.id1)) {
98  realx1 = who->get_location().x;
99  realy1 = who->get_location().y;
100  who->set_location(e.loc1);
101  u1.reset(new scoped_xy_unit("unit", realx1, realy1, *resources::units));
102  }
103  if(unit_ptr who = get_unit(e.uid2, e.id2)) {
104  realx2 = who->get_location().x;
105  realy2 = who->get_location().y;
106  who->set_location(e.loc2);
107  u2.reset(new scoped_xy_unit("unit", realx2, realy2, *resources::units));
108  }
109 
110  scoped_weapon_info w1("weapon", e.data.child("first"));
111  scoped_weapon_info w2("second_weapon", e.data.child("second"));
112 
113  game_events::queued_event q(tag, map_location(x1, y1), map_location(x2, y2), e.data);
114  resources::lua_kernel->run_wml_action("command", vconfig(e.commands), q);
115 
116  if(u1) {
117  unit_ptr who = get_unit(e.uid1, e.id1);
118  who->set_location(map_location(realx1, realy1));
119  }
120  if(u2) {
121  unit_ptr who = get_unit(e.uid2, e.id2);
122  who->set_location(map_location(realx2, realy2));
123  }
124 
125  x1 = oldx1; y1 = oldy1;
126  x2 = oldx2; y2 = oldy2;
127  }
128 }
129 
131 {
132  for(const undo_event& e : umc_commands_undo)
133  {
134  execute_event(e, "undo");
135  }
136 }
137 
139 {
140  assert(resources::lua_kernel);
141  assert(resources::gamedata);
142  for(const undo_event& e : umc_commands_redo)
143  {
144  execute_event(e, "redo");
145  }
146 }
147 
148 void undo_action::write(config & cfg) const
149 {
150  cfg.add_child("replay_data", replay_data);
151  cfg["unit_id_diff"] = unit_id_diff;
152  write_event_vector(umc_commands_undo, cfg, "undo_actions");
153  write_event_vector(umc_commands_redo, cfg, "redo_actions");
155 }
156 
158 {
159  for(auto c : cfg.child_range(tag)) {
160  vec.emplace_back(c.child("filter"), c.child("filter_second"), c.child("filter_weapons"), c.child("commands"));
161  }
162 }
163 
165 {
166  for(const auto& evt : vec)
167  {
168  config& entry = cfg.add_child(tag);
169  config& first = entry.add_child("filter");
170  config& second = entry.add_child("filter_second");
171  entry.add_child("filter_weapons", evt.data);
172  entry.add_child("command", evt.commands);
173  // First location
174  first["filter_x"] = evt.filter_loc1.x;
175  first["filter_y"] = evt.filter_loc1.y;
176  first["underlying_id"] = evt.uid1;
177  first["id"] = evt.id1;
178  first["x"] = evt.loc1.x;
179  first["y"] = evt.loc1.y;
180  // Second location
181  second["filter_x"] = evt.filter_loc2.x;
182  second["filter_y"] = evt.filter_loc2.y;
183  second["underlying_id"] = evt.uid2;
184  second["id"] = evt.id2;
185  second["x"] = evt.loc2.x;
186  second["y"] = evt.loc2.y;
187  }
188 }
189 
190 }
virtual void write(config &cfg) const
Writes this into the provided config.
Definition: undo_action.hpp:38
child_itors child_range(const std::string &key)
Definition: config.cpp:613
entity_location loc2
Definition: pump.hpp:56
unit_const_ptr get_unit() const
const GLfloat * c
Definition: glew.h:12741
bool run_wml_action(std::string const &, vconfig const &, game_events::queued_event const &)
Runs a command from an event handler.
undo_event(const config &cmds, const game_events::queued_event &ctx)
Definition: undo_action.cpp:15
GLuint GLdouble u1
Definition: glew.h:2972
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
Definition: glew.h:1347
Variant for storing WML attributes.
Definition: config.hpp:223
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:70
Records information to be able to undo an action.
Definition: undo_action.hpp:28
event_vector umc_commands_undo
Definition: undo_action.hpp:75
std::vector< undo_event > event_vector
actions wml (specified by wml) that should be executed when undoing this command. ...
Definition: undo_action.hpp:74
static void read_event_vector(event_vector &vec, const config &cfg, const std::string &tag)
GLuint GLenum GLenum transform
Definition: glew.h:11418
GLdouble GLdouble GLdouble GLdouble q
Definition: glew.h:1382
GLuint id
Definition: glew.h:1647
pointer get_shared_ptr() const
Definition: map.hpp:180
event_vector umc_commands_redo
Definition: undo_action.hpp:76
config & add_child(const std::string &key)
Definition: config.cpp:743
static event_list & get_redo_commands()
GLfloat GLfloat p
Definition: glew.h:12766
Encapsulates the map of the game.
Definition: location.hpp:38
virtual void write(config &cfg) const
Writes this into the provided config.
static void write_event_vector(const event_vector &vec, config &cfg, const std::string &tag)
virtual bool redo(int side)=0
Redoes this action.
undo_action()
Default constructor.
Definition: undo_action.cpp:49
entity_location loc1
Definition: pump.hpp:55
A variable-expanding proxy for the config class.
Definition: variable.hpp:36
GLint * first
Definition: glew.h:1496
game_lua_kernel * lua_kernel
Definition: resources.cpp:25
#define e
unit_iterator find(size_t id)
Definition: map.cpp:285
GLuint GLdouble GLdouble u2
Definition: glew.h:2972
static event_list & get_undo_commands()
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
int unit_id_diff
the difference in the unit ids TODO: does it really make sense to allow undoing if the unit id counte...
Definition: undo_action.hpp:72
config replay_data
the replay data to do this action, this is only !empty() when this action is on the redo stack we nee...
Definition: undo_action.hpp:69
GLsizei const GLcharARB ** string
Definition: glew.h:4503
unit_map * units
Definition: resources.cpp:35
virtual bool undo(int side)=0
Undoes this action.