1 /*
2    Copyright (C) 2017-2018 the Battle for Wesnoth Project https://www.wesnoth.org/
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY.
10 
11    See the COPYING file for more details.
12 */
13 
14 #pragma once
15 
16 #include "vision.hpp"
17 #include "map/location.hpp"
18 #include "units/ptr.hpp"
19 #include "synced_context.hpp"
20 #include "game_events/pump.hpp" // for queued_event
21 #include "config.hpp"
22 
23 namespace actions {
24 	class undo_list;
25 
26 	struct undo_event {
27 		config commands, data;
28 		map_location loc1, loc2, filter_loc1, filter_loc2;
29 		size_t uid1, uid2;
30 		std::string id1, id2;
31 		undo_event(const config& cmds, const game_events::queued_event& ctx);
32 		undo_event(const config& first, const config& second, const config& weapons, const config& cmds);
33 	};
34 
35 	/// Records information to be able to undo an action.
36 	/// Each type of action gets its own derived type.
37 	/// Base class for all entries in the undo stack, also contains non undoable actions like update_shroud or auto_shroud.
38 	struct undo_action_base
39 	{
40 		undo_action_base(const undo_action_base&) = delete;
41 		undo_action_base& operator=(const undo_action_base&) = delete;
42 
43 		/// Default constructor.
44 		/// This is the only way to get nullptr view_info.
undo_action_baseactions::undo_action_base45 		undo_action_base()
46 		{ }
47 		// Virtual destructor to support derived classes.
~undo_action_baseactions::undo_action_base48 		virtual ~undo_action_base() {}
49 
50 		/// Writes this into the provided config.
writeactions::undo_action_base51 		virtual void write(config & cfg) const
52 		{
53 			cfg["type"] = this->get_type();
54 		}
55 
56 		virtual const char* get_type() const = 0;
57 	};
58 
59 	/// actions that are undoable (this does not include update_shroud and auto_shroud)
60 	struct undo_action : undo_action_base
61 	{
62 		/// Default constructor.
63 		/// It is assumed that undo actions are constructed after the action is performed
64 		/// so that the unit id diff does not change after this constructor.
65 		undo_action();
66 		undo_action(const config& cfg);
67 		// Virtual destructor to support derived classes.
~undo_actionactions::undo_action68 		virtual ~undo_action() {}
69 
70 		/// Writes this into the provided config.
71 		virtual void write(config & cfg) const;
72 
73 		/// Undoes this action.
74 		/// @return true on success; false on an error.
75 		virtual bool undo(int side) = 0;
76 		/// the difference in the unit ids
77 		/// TODO: does it really make sense to allow undoing if the unit id counter has changed?
78 		int unit_id_diff;
79 		/// actions wml (specified by wml) that should be executed when undoing this command.
80 		typedef std::vector<undo_event> event_vector;
81 		event_vector umc_commands_undo;
82 		void execute_undo_umc_wml();
83 
84 		static void read_event_vector(event_vector& vec, const config& cfg, const std::string& tag);
85 		static void write_event_vector(const event_vector& vec, config& cfg, const std::string& tag);
86 	};
87 
88 	/// entry for player actions that do not need any special code to be performed when undoing such as right-click menu items.
89 	struct undo_dummy_action : undo_action
90 	{
undo_dummy_actionactions::undo_dummy_action91 		undo_dummy_action ()
92 			: undo_action()
93 		{
94 		}
undo_dummy_actionactions::undo_dummy_action95 		explicit undo_dummy_action (const config & cfg)
96 			: undo_action(cfg)
97 		{
98 		}
get_typeactions::undo_dummy_action99 		virtual const char* get_type() const { return "dummy"; }
~undo_dummy_actionactions::undo_dummy_action100 		virtual ~undo_dummy_action () {}
101 		/// Undoes this action.
undoactions::undo_dummy_action102 		virtual bool undo(int)
103 		{
104 			execute_undo_umc_wml();
105 			return true;
106 		}
107 	};
108 
109 }
110