add [on_undo]/[on_redo] actionwml
[on_undo]/[on_redo] contains tags that are executed when undoing the current actions.
This commit is contained in:
parent
f01252a42c
commit
6010455f56
9 changed files with 117 additions and 3 deletions
|
@ -1 +1,43 @@
|
|||
#include "undo_action.hpp"
|
||||
#include "scripting/game_lua_kernel.hpp"
|
||||
#include "resources.hpp"
|
||||
#include "variable.hpp" // vconfig
|
||||
#include "game_events/pump.hpp" //game_events::queued_event
|
||||
|
||||
#include <cassert>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
namespace actions
|
||||
{
|
||||
void undo_action::execute_undo_umc_wml()
|
||||
{
|
||||
assert(resources::lua_kernel);
|
||||
BOOST_FOREACH(const config& c, umc_commands_undo)
|
||||
{
|
||||
resources::lua_kernel->run_wml_action("command", vconfig(c), game_events::queued_event("undo", map_location(), map_location(), config()));
|
||||
}
|
||||
}
|
||||
|
||||
void undo_action::execute_redo_umc_wml()
|
||||
{
|
||||
assert(resources::lua_kernel);
|
||||
BOOST_FOREACH(const config& c, umc_commands_redo)
|
||||
{
|
||||
resources::lua_kernel->run_wml_action("command", vconfig(c), game_events::queued_event("redo", map_location(), map_location(), config()));
|
||||
}
|
||||
}
|
||||
|
||||
void undo_action::read_tconfig_vector(tconfig_vector& vec, const config& cfg, const std::string& tag)
|
||||
{
|
||||
config::const_child_itors r = cfg.child_range(tag);
|
||||
vec.insert(vec.end(), r.first, r.second);
|
||||
}
|
||||
void undo_action::write_tconfig_vector(const tconfig_vector& vec, config& cfg, const std::string& tag)
|
||||
{
|
||||
BOOST_FOREACH(const config& c, vec)
|
||||
{
|
||||
cfg.add_child(tag, c);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,12 +44,22 @@ namespace actions {
|
|||
: undo_action_base()
|
||||
, replay_data()
|
||||
, unit_id_diff(synced_context::get_unit_id_diff())
|
||||
{ }
|
||||
, umc_commands_undo()
|
||||
, umc_commands_redo()
|
||||
{
|
||||
umc_commands_undo.swap(synced_context::get_undo_commands());
|
||||
umc_commands_redo.swap(synced_context::get_redo_commands());
|
||||
}
|
||||
undo_action(const config& cfg)
|
||||
: undo_action_base()
|
||||
, replay_data(cfg.child_or_empty("replay_data"))
|
||||
, unit_id_diff(cfg["unit_id_diff"])
|
||||
{ }
|
||||
, umc_commands_undo()
|
||||
, umc_commands_redo()
|
||||
{
|
||||
read_tconfig_vector(umc_commands_undo, cfg, "undo_actions");
|
||||
read_tconfig_vector(umc_commands_redo, cfg, "redo_actions");
|
||||
}
|
||||
// Virtual destructor to support derived classes.
|
||||
virtual ~undo_action() {}
|
||||
|
||||
|
@ -58,6 +68,8 @@ namespace actions {
|
|||
{
|
||||
cfg.add_child("replay_data", replay_data);
|
||||
cfg["unit_id_diff"] = unit_id_diff;
|
||||
write_tconfig_vector(umc_commands_undo, cfg, "undo_actions");
|
||||
write_tconfig_vector(umc_commands_redo, cfg, "redo_actions");
|
||||
undo_action_base::write(cfg);
|
||||
}
|
||||
|
||||
|
@ -71,8 +83,18 @@ namespace actions {
|
|||
/// we need this because we don't recalculate the redos like they would be in real game,
|
||||
/// but even undoable commands can have "dependent" (= user_input) commands, which we save here.
|
||||
config replay_data;
|
||||
|
||||
/// the difference in the unit ids
|
||||
/// TODO: does it really make sense to allow undoing if the unit id counter has changed?
|
||||
int unit_id_diff;
|
||||
/// actions wml (specified by wml) that should be executed when undoing this command.
|
||||
typedef boost::ptr_vector<config> tconfig_vector;
|
||||
tconfig_vector umc_commands_undo;
|
||||
tconfig_vector umc_commands_redo;
|
||||
void execute_undo_umc_wml();
|
||||
void execute_redo_umc_wml();
|
||||
|
||||
static void read_tconfig_vector(tconfig_vector& vec, const config& cfg, const std::string& tag);
|
||||
static void write_tconfig_vector(const tconfig_vector& vec, config& cfg, const std::string& tag);
|
||||
};
|
||||
|
||||
/// entry for player actions that do not need any special code to be performed when undoing such as right-click menu items.
|
||||
|
|
|
@ -26,6 +26,7 @@ bool dismiss_action::undo(int side)
|
|||
team ¤t_team = (*resources::teams)[side-1];
|
||||
|
||||
current_team.recall_list().add(dismissed_unit);
|
||||
execute_undo_umc_wml();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -40,6 +41,7 @@ bool dismiss_action::redo(int side)
|
|||
resources::recorder->redo(replay_data);
|
||||
replay_data.clear();
|
||||
current_team.recall_list().erase_if_matches_id(dismissed_unit->id());
|
||||
execute_redo_umc_wml();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@ bool move_action::undo(int side)
|
|||
u->anim_comp().set_standing();
|
||||
|
||||
gui.invalidate_unit_after_move(rev_route.front(), rev_route.back());
|
||||
execute_undo_umc_wml();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -136,6 +137,7 @@ bool move_action::redo(int side)
|
|||
gui.invalidate_unit_after_move(route.front(), route.back());
|
||||
resources::recorder->redo(replay_data);
|
||||
replay_data.clear();
|
||||
execute_redo_umc_wml();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ bool recall_action::undo(int side)
|
|||
// to also do the overlapped hexes
|
||||
gui.invalidate(recall_loc);
|
||||
units.erase(recall_loc);
|
||||
execute_undo_umc_wml();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ bool recruit_action::undo(int side)
|
|||
// to also do the overlapped hexes
|
||||
gui.invalidate(recruit_loc);
|
||||
units.erase(recruit_loc);
|
||||
execute_undo_umc_wml();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1792,5 +1792,15 @@ WML_HANDLER_FUNCTION(wml_message, /*event_info*/, cfg)
|
|||
handle_wml_log_message( cfg.get_parsed_config() );
|
||||
}
|
||||
|
||||
WML_HANDLER_FUNCTION(on_undo, /*event_info*/, cfg)
|
||||
{
|
||||
synced_context::add_undo_commands(cfg.get_parsed_config());
|
||||
}
|
||||
|
||||
WML_HANDLER_FUNCTION(on_redo, /*event_info*/, cfg)
|
||||
{
|
||||
synced_context::add_redo_commands(cfg.get_parsed_config());
|
||||
}
|
||||
|
||||
} // end namespace game_events
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ static lg::log_domain log_replay("replay");
|
|||
|
||||
synced_context::synced_state synced_context::state_ = synced_context::UNSYNCED;
|
||||
int synced_context::last_unit_id_ = 0;
|
||||
synced_context::tconfig_vector synced_context::undo_commands_ = synced_context::tconfig_vector();
|
||||
synced_context::tconfig_vector synced_context::redo_commands_ = synced_context::tconfig_vector();
|
||||
bool synced_context::is_simultaneously_ = false;
|
||||
|
||||
bool synced_context::run(const std::string& commandname, const config& data, bool use_undo, bool show, synced_command::error_handler_function error_handler)
|
||||
|
@ -388,6 +390,16 @@ config synced_context::ask_server_choice(const server_choice& sch)
|
|||
}
|
||||
}
|
||||
|
||||
void synced_context::add_undo_commands(const config& commands)
|
||||
{
|
||||
undo_commands_.insert(undo_commands_.begin(), new config(commands));
|
||||
}
|
||||
|
||||
void synced_context::add_redo_commands(const config& commands)
|
||||
{
|
||||
redo_commands_.insert(redo_commands_.begin(), new config(commands));
|
||||
}
|
||||
|
||||
set_scontext_synced_base::set_scontext_synced_base()
|
||||
: new_rng_(synced_context::get_rng_for_action())
|
||||
, old_rng_(random_new::generator)
|
||||
|
@ -398,6 +410,8 @@ set_scontext_synced_base::set_scontext_synced_base()
|
|||
synced_context::set_synced_state(synced_context::SYNCED);
|
||||
synced_context::reset_is_simultaneously();
|
||||
synced_context::set_last_unit_id(resources::gameboard->unit_id_manager().get_save_id());
|
||||
synced_context::reset_undo_commands();
|
||||
synced_context::reset_redo_commands();
|
||||
old_rng_ = random_new::generator;
|
||||
random_new::generator = new_rng_.get();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include "mouse_handler_base.hpp"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
|
||||
class config;
|
||||
|
||||
//only static methods.
|
||||
|
@ -144,6 +146,14 @@ public:
|
|||
if we are in a mp game, ask the server, otherwise generate the answer ourselves.
|
||||
*/
|
||||
static config ask_server_choice(const server_choice&);
|
||||
|
||||
typedef boost::ptr_vector<config> tconfig_vector;
|
||||
static tconfig_vector& get_undo_commands() { return undo_commands_; }
|
||||
static tconfig_vector& get_redo_commands() { return redo_commands_; }
|
||||
static void add_undo_commands(const config& commands);
|
||||
static void add_redo_commands(const config& commands);
|
||||
static void reset_undo_commands() { undo_commands_ = tconfig_vector(); }
|
||||
static void reset_redo_commands() { redo_commands_ = tconfig_vector(); }
|
||||
private:
|
||||
/*
|
||||
weather we are in a synced move, in a user_choice, or none of them
|
||||
|
@ -154,12 +164,22 @@ private:
|
|||
It's impossible to undo data that has been sended over the network.
|
||||
|
||||
false = we are on a local turn and haven't sended anything yet.
|
||||
|
||||
TODO: it would be better if the following variable were not static.
|
||||
*/
|
||||
static bool is_simultaneously_;
|
||||
/**
|
||||
Used to restore the unit id manager when undoing.
|
||||
*/
|
||||
static int last_unit_id_;
|
||||
/**
|
||||
Actions wml to be executed when the current actio is undone.
|
||||
*/
|
||||
static tconfig_vector undo_commands_;
|
||||
/**
|
||||
Actions wml to be executed when the current actio is redone.
|
||||
*/
|
||||
static tconfig_vector redo_commands_;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue