refactor synced_context::run
- Removed the now unused 'undo' parameter - Removed the rareley used 'show' parameter, the actions now check whether they should skip in replays Replaced the error handler with the more generic 'spectator' parameter, the idea is to use it also for the move_spectator so that the move action can also go through synced_context::run()
This commit is contained in:
parent
7782c50f83
commit
a6cd4441c9
7 changed files with 123 additions and 144 deletions
|
@ -394,19 +394,20 @@ void undo_list::redo()
|
|||
// Note that this might add more than one [command]
|
||||
resources::recorder->redo(*action);
|
||||
|
||||
auto error_handler = [](const std::string& msg) {
|
||||
auto spectator = action_spectator([](const std::string& msg)
|
||||
{
|
||||
ERR_NG << "Out of sync when redoing: " << msg;
|
||||
gui2::show_transient_message(_("Redo Error"),
|
||||
_("The redo stack is out of sync. This is most commonly caused by a corrupt save file or by faulty WML code in the scenario or era. Details:") + msg);
|
||||
|
||||
};
|
||||
});
|
||||
// synced_context::run readds the undo command with the normal
|
||||
// undo_list::add function which clears the redo stack which would
|
||||
// make redoing of more than one move impossible. To work around
|
||||
// that we save redo stack here and set it later.
|
||||
redos_list temp;
|
||||
temp.swap(redos_);
|
||||
synced_context::run(commandname, data, /*use_undo*/ true, /*show*/ true, error_handler);
|
||||
synced_context::run(commandname, data, spectator);
|
||||
temp.swap(redos_);
|
||||
|
||||
// Screen updates.
|
||||
|
|
|
@ -247,12 +247,6 @@ WML_HANDLER_FUNCTION(clear_global_variable,,pcfg)
|
|||
verify_and_clear_global_variable(pcfg);
|
||||
}
|
||||
|
||||
static void on_replay_error(const std::string& message)
|
||||
{
|
||||
ERR_NG << "Error via [do_command]:";
|
||||
ERR_NG << message;
|
||||
}
|
||||
|
||||
// This tag exposes part of the code path used to handle [command]'s in replays
|
||||
// This allows to perform scripting in WML that will use the same code path as player actions, for example.
|
||||
WML_HANDLER_FUNCTION(do_command,, cfg)
|
||||
|
@ -306,12 +300,14 @@ WML_HANDLER_FUNCTION(do_command,, cfg)
|
|||
|
||||
//Note that this fires related events and everything else that also happens normally.
|
||||
//have to watch out with the undo stack, therefore forbid [auto_shroud] and [update_shroud] here...
|
||||
auto spectator = action_spectator([](const std::string& message) {
|
||||
ERR_NG << "Error via [do_command]:";
|
||||
ERR_NG << message;
|
||||
});
|
||||
synced_context::run_in_synced_context_if_not_already(
|
||||
/*commandname*/ key,
|
||||
/*data*/ child.get_parsed_config(),
|
||||
/*use_undo*/ true,
|
||||
/*show*/ true,
|
||||
/*error_handler*/ &on_replay_error
|
||||
key,
|
||||
child.get_parsed_config(),
|
||||
spectator
|
||||
);
|
||||
ai::manager::get_singleton().raise_gamestate_changed();
|
||||
}
|
||||
|
|
|
@ -689,11 +689,6 @@ bool replay::add_start_if_not_there_yet()
|
|||
}
|
||||
}
|
||||
|
||||
static void show_oos_error_error_function(const std::string& message)
|
||||
{
|
||||
replay::process_error(message);
|
||||
}
|
||||
|
||||
REPLAY_ACTION_TYPE get_replay_action_type(const config& command)
|
||||
{
|
||||
if(command.all_children_count() != 1) {
|
||||
|
@ -912,7 +907,8 @@ REPLAY_RETURN do_replay_handle(bool one_move)
|
|||
/*
|
||||
we need to use the undo stack during replays in order to make delayed shroud updated work.
|
||||
*/
|
||||
synced_context::run(commandname, data, true, !resources::controller->is_skipping_replay(), show_oos_error_error_function);
|
||||
auto spectator = action_spectator([](const std::string& message) { replay::process_error(message); });
|
||||
synced_context::run(commandname, data, spectator);
|
||||
if(resources::controller->is_regular_game_end()) {
|
||||
return REPLAY_FOUND_END_LEVEL;
|
||||
}
|
||||
|
|
|
@ -65,8 +65,9 @@ synced_command::map& synced_command::registry()
|
|||
}
|
||||
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(recruit, child, show, error_handler)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(recruit, child, spectator)
|
||||
{
|
||||
bool show = !resources::controller->is_skipping_replay();
|
||||
int current_team_num = resources::controller->current_side();
|
||||
team ¤t_team = resources::gameboard->get_team(current_team_num);
|
||||
|
||||
|
@ -77,19 +78,19 @@ SYNCED_COMMAND_HANDLER_FUNCTION(recruit, child, show, error_handler)
|
|||
// This will be the case for AI recruits in replays saved
|
||||
// before 1.11.2, so it is not more severe than a warning.
|
||||
// EDIT: we broke compatibility with 1.11.2 anyway so we should give an error.
|
||||
error_handler("Missing leader location for recruitment.\n");
|
||||
spectator.error("Missing leader location for recruitment.\n");
|
||||
}
|
||||
else if ( resources::gameboard->units().find(from) == resources::gameboard->units().end() ) {
|
||||
// Sync problem?
|
||||
std::stringstream errbuf;
|
||||
errbuf << "Recruiting leader not found at " << from << ".\n";
|
||||
error_handler(errbuf.str());
|
||||
spectator.error(errbuf.str());
|
||||
}
|
||||
|
||||
// Get the unit_type ID.
|
||||
std::string type_id = child["type"];
|
||||
if ( type_id.empty() ) {
|
||||
error_handler("Recruitment is missing a unit type.");
|
||||
spectator.error("Recruitment is missing a unit type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -97,7 +98,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(recruit, child, show, error_handler)
|
|||
if (!u_type) {
|
||||
std::stringstream errbuf;
|
||||
errbuf << "Recruiting illegal unit: '" << type_id << "'.\n";
|
||||
error_handler(errbuf.str());
|
||||
spectator.error(errbuf.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -106,7 +107,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(recruit, child, show, error_handler)
|
|||
{
|
||||
std::stringstream errbuf;
|
||||
errbuf << "cannot recruit unit: " << res << "\n";
|
||||
error_handler(errbuf.str());
|
||||
spectator.error(errbuf.str());
|
||||
return false;
|
||||
//we are already oos because the unit wasn't created, no need to keep the bookkeeping right...
|
||||
}
|
||||
|
@ -118,7 +119,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(recruit, child, show, error_handler)
|
|||
std::stringstream errbuf;
|
||||
errbuf << "unit '" << type_id << "' is too expensive to recruit: "
|
||||
<< u_type->cost() << "/" << beginning_gold << "\n";
|
||||
error_handler(errbuf.str());
|
||||
spectator.error(errbuf.str());
|
||||
}
|
||||
|
||||
actions::recruit_unit(*u_type, current_team_num, loc, from, show);
|
||||
|
@ -129,9 +130,9 @@ SYNCED_COMMAND_HANDLER_FUNCTION(recruit, child, show, error_handler)
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(recall, child, show, error_handler)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(recall, child, spectator)
|
||||
{
|
||||
|
||||
bool show = !resources::controller->is_skipping_replay();
|
||||
int current_team_num = resources::controller->current_side();
|
||||
team ¤t_team = resources::gameboard->get_team(current_team_num);
|
||||
|
||||
|
@ -140,26 +141,27 @@ SYNCED_COMMAND_HANDLER_FUNCTION(recall, child, show, error_handler)
|
|||
map_location from(child.child_or_empty("from"), resources::gamedata);
|
||||
|
||||
if(!actions::recall_unit(unit_id, current_team, loc, from, map_location::direction::indeterminate, show)) {
|
||||
error_handler("illegal recall: unit_id '" + unit_id + "' could not be found within the recall list.\n");
|
||||
spectator.error("illegal recall: unit_id '" + unit_id + "' could not be found within the recall list.\n");
|
||||
//when recall_unit returned false nothing happened so we can safety return false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(attack, child, show, error_handler)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(attack, child, spectator)
|
||||
{
|
||||
bool show = !resources::controller->is_skipping_replay();
|
||||
const auto destination = child.optional_child("destination");
|
||||
const auto source = child.optional_child("source");
|
||||
//check_checksums(*cfg);
|
||||
|
||||
if (!destination) {
|
||||
error_handler("no destination found in attack\n");
|
||||
spectator.error("no destination found in attack\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!source) {
|
||||
error_handler("no source found in attack \n");
|
||||
spectator.error("no source found in attack \n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -183,7 +185,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(attack, child, show, error_handler)
|
|||
|
||||
unit_map::iterator u = resources::gameboard->units().find(src);
|
||||
if (!u.valid()) {
|
||||
error_handler("unfound location for source of attack\n");
|
||||
spectator.error("unfound location for source of attack\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -195,7 +197,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(attack, child, show, error_handler)
|
|||
}
|
||||
|
||||
if (static_cast<unsigned>(weapon_num) >= u->attacks().size()) {
|
||||
error_handler("illegal weapon type in attack\n");
|
||||
spectator.error("illegal weapon type in attack\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -204,7 +206,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(attack, child, show, error_handler)
|
|||
if (!tgt.valid()) {
|
||||
std::stringstream errbuf;
|
||||
errbuf << "unfound defender for attack: " << src << " -> " << dst << '\n';
|
||||
error_handler(errbuf.str());
|
||||
spectator.error(errbuf.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -217,7 +219,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(attack, child, show, error_handler)
|
|||
|
||||
if (def_weapon_num >= static_cast<int>(tgt->attacks().size())) {
|
||||
|
||||
error_handler("illegal defender weapon type in attack\n");
|
||||
spectator.error("illegal defender weapon type in attack\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -228,7 +230,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(attack, child, show, error_handler)
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(disband, child, /*show*/, error_handler)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(disband, child, spectator)
|
||||
{
|
||||
|
||||
int current_team_num = resources::controller->current_side();
|
||||
|
@ -240,7 +242,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(disband, child, /*show*/, error_handler)
|
|||
// Find the unit in the recall list.
|
||||
unit_ptr dismissed_unit = current_team.recall_list().find_if_matches_id(unit_id);
|
||||
if (!dismissed_unit) {
|
||||
error_handler("illegal disband\n");
|
||||
spectator.error("illegal disband\n");
|
||||
return false;
|
||||
}
|
||||
//add dismissal to the undo stack
|
||||
|
@ -249,13 +251,13 @@ SYNCED_COMMAND_HANDLER_FUNCTION(disband, child, /*show*/, error_handler)
|
|||
current_team.recall_list().erase_if_matches_id(unit_id);
|
||||
|
||||
if (old_size == current_team.recall_list().size()) {
|
||||
error_handler("illegal disband\n");
|
||||
spectator.error("illegal disband\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(move, child, show, error_handler)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(move, child, spectator)
|
||||
{
|
||||
int current_team_num = resources::controller->current_side();
|
||||
team ¤t_team = resources::gameboard->get_team(current_team_num);
|
||||
|
@ -297,21 +299,15 @@ SYNCED_COMMAND_HANDLER_FUNCTION(move, child, show, error_handler)
|
|||
std::stringstream errbuf;
|
||||
errbuf << "unfound location for source of movement: "
|
||||
<< src << " -> " << dst << '\n';
|
||||
error_handler(errbuf.str());
|
||||
spectator.error(errbuf.str());
|
||||
return false;
|
||||
}
|
||||
bool skip_sighted = false;
|
||||
bool skip_ally_sighted = false;
|
||||
if(child["skip_sighted"] == "all")
|
||||
{
|
||||
skip_sighted = true;
|
||||
}
|
||||
else if(child["skip_sighted"] == "only_ally")
|
||||
{
|
||||
skip_ally_sighted = true;
|
||||
}
|
||||
|
||||
bool show_move = show;
|
||||
bool skip_sighted = child["skip_sighted"] == "all";
|
||||
bool skip_ally_sighted = child["skip_sighted"] == "only_ally";
|
||||
|
||||
bool show_move = !resources::controller->is_skipping_replay() ;
|
||||
|
||||
if ( current_team.is_local_ai() || current_team.is_network_ai())
|
||||
{
|
||||
show_move = show_move && !prefs::get().skip_ai_moves();
|
||||
|
@ -321,7 +317,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(move, child, show, error_handler)
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(fire_event, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(fire_event, child, /*spectator*/)
|
||||
{
|
||||
if(const auto last_select = child.optional_child("last_select"))
|
||||
{
|
||||
|
@ -344,7 +340,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(fire_event, child, /*show*/, /*error_handler*/)
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(custom_command, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(custom_command, child, /*spectator*/)
|
||||
{
|
||||
assert(resources::lua_kernel);
|
||||
resources::lua_kernel->custom_command(child["name"], child.child_or_empty("data"));
|
||||
|
@ -357,7 +353,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(custom_command, child, /*show*/, /*error_handler
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(auto_shroud, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(auto_shroud, child, /*spectator*/)
|
||||
{
|
||||
team ¤t_team = resources::controller->current_team();
|
||||
|
||||
|
@ -372,7 +368,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(auto_shroud, child, /*show*/, /*error_handler*/)
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(update_shroud, /*child*/, /*show*/, error_handler)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(update_shroud, /*child*/, spectator)
|
||||
{
|
||||
// When "updating shroud now" is used.
|
||||
// Updates fog/shroud based on the undo stack, then updates stack as needed.
|
||||
|
@ -380,7 +376,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(update_shroud, /*child*/, /*show*/, error_handle
|
|||
|
||||
team ¤t_team = resources::controller->current_team();
|
||||
if(current_team.auto_shroud_updates()) {
|
||||
error_handler("Team has DSU disabled but we found an explicit shroud update");
|
||||
spectator.error("Team has DSU disabled but we found an explicit shroud update");
|
||||
}
|
||||
bool res = resources::undo_stack->commit_vision();
|
||||
resources::undo_stack->add_update_shroud();
|
||||
|
@ -438,7 +434,7 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_terrain, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_terrain, child, /*spectator*/)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
debug_cmd_notification("terrain");
|
||||
|
@ -456,7 +452,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_terrain, child, /*show*/, /*error_handler*
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_unit, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_unit, child, /*spectator*/)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
debug_cmd_notification("unit");
|
||||
|
@ -525,7 +521,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_unit, child, /*show*/, /*error_handler*/)
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_create_unit, child, /*show*/, error_handler)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_create_unit, child, spectator)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
|
||||
|
@ -536,7 +532,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_create_unit, child, /*show*/, error_handle
|
|||
const unit_race::GENDER gender = string_gender(child["gender"], unit_race::NUM_GENDERS);
|
||||
const unit_type *u_type = unit_types.find(child["type"]);
|
||||
if (!u_type) {
|
||||
error_handler("Invalid unit type");
|
||||
spectator.error("Invalid unit type");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -571,7 +567,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_create_unit, child, /*show*/, error_handle
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_lua, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_lua, child, /*spectator*/)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
debug_cmd_notification("lua");
|
||||
|
@ -581,7 +577,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_lua, child, /*show*/, /*error_handler*/)
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_teleport, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_teleport, child, /*spectator*/)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
debug_cmd_notification("teleport");
|
||||
|
@ -600,7 +596,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_teleport, child, /*show*/, /*error_handler
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_kill, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_kill, child, /*spectator*/)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
debug_cmd_notification("kill");
|
||||
|
@ -627,7 +623,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_kill, child, /*show*/, /*error_handler*/)
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_next_level, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_next_level, child, /*spectator*/)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
|
||||
|
@ -649,7 +645,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_next_level, child, /*show*/, /*error_handl
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_turn_limit, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_turn_limit, child, /*spectator*/)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
|
||||
|
@ -660,7 +656,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_turn_limit, child, /*show*/, /*error_handl
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_turn, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_turn, child, /*spectator*/)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
|
||||
|
@ -674,7 +670,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_turn, child, /*show*/, /*error_handler*/)
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_set_var, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_set_var, child, /*spectator*/)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
|
||||
|
@ -690,7 +686,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_set_var, child, /*show*/, /*error_handler*
|
|||
return true;
|
||||
}
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_gold, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_gold, child, /*spectator*/)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
|
||||
|
@ -702,7 +698,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_gold, child, /*show*/, /*error_handler*/)
|
|||
}
|
||||
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_event, child, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_event, child, /*spectator*/)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
|
||||
|
@ -715,7 +711,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_event, child, /*show*/, /*error_handler*/)
|
|||
}
|
||||
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_fog, /*child*/, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_fog, /*child*/, /*spectator*/)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
|
||||
|
@ -732,7 +728,7 @@ SYNCED_COMMAND_HANDLER_FUNCTION(debug_fog, /*child*/, /*show*/, /*error_handler*
|
|||
}
|
||||
|
||||
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_shroud, /*child*/, /*show*/, /*error_handler*/)
|
||||
SYNCED_COMMAND_HANDLER_FUNCTION(debug_shroud, /*child*/, /*spectator*/)
|
||||
{
|
||||
resources::undo_stack->clear();
|
||||
|
||||
|
|
|
@ -22,6 +22,30 @@
|
|||
|
||||
class config;
|
||||
|
||||
class action_spectator
|
||||
{
|
||||
public:
|
||||
typedef std::function<void(const std::string&)> error_handler_function;
|
||||
action_spectator() = default;
|
||||
action_spectator(error_handler_function eh)
|
||||
: eh_(eh)
|
||||
{
|
||||
}
|
||||
virtual ~action_spectator() = default;
|
||||
/**
|
||||
* Called when synced_context::run received nonsensial data based on the current gamestate.
|
||||
*/
|
||||
virtual void error(const std::string& message)
|
||||
{
|
||||
eh_(message);
|
||||
}
|
||||
error_handler_function eh_;
|
||||
};
|
||||
|
||||
// TODO: it would be nice if we would use some consistent terminology along the codebase
|
||||
// The things that the user invokes are sometimes called "commands" (in particular
|
||||
// in the replay), and sometimes called "actions" (in particular inn the actions/ folder)
|
||||
|
||||
class synced_command {
|
||||
public:
|
||||
/*
|
||||
|
@ -32,7 +56,7 @@ class synced_command {
|
|||
/*
|
||||
returns: true if the action succeeded correctly,
|
||||
*/
|
||||
typedef bool (*handler)(const config &, bool show, error_handler_function error_handler);
|
||||
typedef bool (*handler)(const config&, action_spectator& spectator);
|
||||
typedef std::map<std::string, handler> map;
|
||||
|
||||
|
||||
|
@ -47,7 +71,7 @@ class synced_command {
|
|||
but if you have a good reason feel free to do so.
|
||||
*/
|
||||
|
||||
#define SYNCED_COMMAND_HANDLER_FUNCTION(pname, pcfg, show, error_handler) \
|
||||
static bool synced_command_func_##pname(const config & pcfg, bool show, synced_command::error_handler_function error_handler ); \
|
||||
#define SYNCED_COMMAND_HANDLER_FUNCTION(pname, pcfg, spectator) \
|
||||
static bool synced_command_func_##pname(const config& pcfg, action_spectator& spectator); \
|
||||
static synced_command synced_command_action_##pname(#pname, &synced_command_func_##pname); \
|
||||
static bool synced_command_func_##pname(const config & pcfg, bool show, synced_command::error_handler_function error_handler)
|
||||
static bool synced_command_func_##pname(const config& pcfg, action_spectator& spectator)
|
||||
|
|
|
@ -44,11 +44,7 @@ static lg::log_domain log_replay("replay");
|
|||
#define WRN_REPLAY LOG_STREAM(warn, log_replay)
|
||||
#define ERR_REPLAY LOG_STREAM(err, log_replay)
|
||||
|
||||
bool synced_context::run(const std::string& commandname,
|
||||
const config& data,
|
||||
bool /*use_undo*/,
|
||||
bool show,
|
||||
synced_command::error_handler_function error_handler)
|
||||
bool synced_context::run(const std::string& commandname, const config& data, action_spectator& spectator)
|
||||
{
|
||||
DBG_REPLAY << "run_in_synced_context:" << commandname;
|
||||
|
||||
|
@ -58,9 +54,9 @@ bool synced_context::run(const std::string& commandname,
|
|||
|
||||
synced_command::map::iterator it = synced_command::registry().find(commandname);
|
||||
if(it == synced_command::registry().end()) {
|
||||
error_handler("commandname [" + commandname + "] not found");
|
||||
spectator.error("commandname [" + commandname + "] not found");
|
||||
} else {
|
||||
bool success = it->second(data, show, error_handler);
|
||||
bool success = it->second(data, spectator);
|
||||
if(!success) {
|
||||
return false;
|
||||
}
|
||||
|
@ -83,11 +79,7 @@ bool synced_context::run(const std::string& commandname,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool synced_context::run_and_store(const std::string& commandname,
|
||||
const config& data,
|
||||
bool use_undo,
|
||||
bool show,
|
||||
synced_command::error_handler_function error_handler)
|
||||
bool synced_context::run_and_store(const std::string& commandname, const config& data, action_spectator& spectator)
|
||||
{
|
||||
if(resources::controller->is_replay()) {
|
||||
ERR_REPLAY << "ignored attempt to invoke a synced command during replay";
|
||||
|
@ -96,7 +88,7 @@ bool synced_context::run_and_store(const std::string& commandname,
|
|||
|
||||
assert(resources::recorder->at_end());
|
||||
resources::recorder->add_synced_command(commandname, data);
|
||||
bool success = run(commandname, data, use_undo, show, error_handler);
|
||||
bool success = run(commandname, data, spectator);
|
||||
if(!success) {
|
||||
resources::recorder->undo();
|
||||
}
|
||||
|
@ -104,13 +96,9 @@ bool synced_context::run_and_store(const std::string& commandname,
|
|||
return success;
|
||||
}
|
||||
|
||||
bool synced_context::run_and_throw(const std::string& commandname,
|
||||
const config& data,
|
||||
bool use_undo,
|
||||
bool show,
|
||||
synced_command::error_handler_function error_handler)
|
||||
bool synced_context::run_and_throw(const std::string& commandname, const config& data, action_spectator& spectator)
|
||||
{
|
||||
bool success = run_and_store(commandname, data, use_undo, show, error_handler);
|
||||
bool success = run_and_store(commandname, data, spectator);
|
||||
if(success) {
|
||||
resources::controller->maybe_throw_return_to_play_side();
|
||||
}
|
||||
|
@ -118,15 +106,12 @@ bool synced_context::run_and_throw(const std::string& commandname,
|
|||
return success;
|
||||
}
|
||||
|
||||
bool synced_context::run_in_synced_context_if_not_already(const std::string& commandname,
|
||||
const config& data,
|
||||
bool use_undo,
|
||||
bool show,
|
||||
synced_command::error_handler_function error_handler)
|
||||
bool synced_context::run_in_synced_context_if_not_already(
|
||||
const std::string& commandname, const config& data, action_spectator& spectator)
|
||||
{
|
||||
switch(synced_context::get_synced_state()) {
|
||||
case(synced_context::UNSYNCED): {
|
||||
return run_and_throw(commandname, data, use_undo, show, error_handler);
|
||||
return run_and_throw(commandname, data, spectator);
|
||||
}
|
||||
case(synced_context::LOCAL_CHOICE):
|
||||
ERR_REPLAY << "trying to execute action while being in a local_choice";
|
||||
|
@ -137,10 +122,10 @@ bool synced_context::run_in_synced_context_if_not_already(const std::string& com
|
|||
case(synced_context::SYNCED): {
|
||||
synced_command::map::iterator it = synced_command::registry().find(commandname);
|
||||
if(it == synced_command::registry().end()) {
|
||||
error_handler("commandname [" + commandname + "] not found");
|
||||
spectator.error("commandname [" + commandname + "] not found");
|
||||
return false;
|
||||
} else {
|
||||
return it->second(data, /*use_undo*/ false, show, error_handler);
|
||||
return it->second(data, spectator);
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
@ -149,20 +134,19 @@ bool synced_context::run_in_synced_context_if_not_already(const std::string& com
|
|||
}
|
||||
}
|
||||
|
||||
void synced_context::default_error_function(const std::string& message)
|
||||
action_spectator& synced_context::get_default_spectator()
|
||||
{
|
||||
ERR_REPLAY << "Unexpected Error during synced execution" << message;
|
||||
assert(!"Unexpected Error during synced execution, more info in stderr.");
|
||||
}
|
||||
static class : public action_spectator
|
||||
{
|
||||
public:
|
||||
void error(const std::string& message)
|
||||
{
|
||||
ERR_REPLAY << "Unexpected Error during synced execution" << message;
|
||||
assert(!"Unexpected Error during synced execution, more info in stderr.");
|
||||
}
|
||||
|
||||
void synced_context::just_log_error_function(const std::string& message)
|
||||
{
|
||||
ERR_REPLAY << "Error during synced execution: " << message;
|
||||
}
|
||||
|
||||
void synced_context::ignore_error_function(const std::string& message)
|
||||
{
|
||||
DBG_REPLAY << "Ignored during synced execution: " << message;
|
||||
} res;
|
||||
return res;
|
||||
}
|
||||
|
||||
namespace
|
||||
|
|
|
@ -53,33 +53,21 @@ public:
|
|||
*
|
||||
* @return True if the action was successful.
|
||||
*/
|
||||
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);
|
||||
static bool run(
|
||||
const std::string& commandname, const config& data, action_spectator& observer = get_default_spectator());
|
||||
|
||||
static bool run_and_store(const std::string& commandname,
|
||||
const config& data,
|
||||
bool use_undo = true,
|
||||
bool show = true,
|
||||
synced_command::error_handler_function error_handler = default_error_function);
|
||||
static bool run_and_store(
|
||||
const std::string& commandname, const config& data, action_spectator& observer = get_default_spectator());
|
||||
|
||||
static bool run_and_throw(const std::string& commandname,
|
||||
const config& data,
|
||||
bool use_undo = true,
|
||||
bool show = true,
|
||||
synced_command::error_handler_function error_handler = default_error_function);
|
||||
static bool run_and_throw(
|
||||
const std::string& commandname, const config& data, action_spectator& observer = get_default_spectator());
|
||||
|
||||
/**
|
||||
* Checks whether we are currently running in a synced context, and if not we enters it.
|
||||
* This is never called from so_replay_handle.
|
||||
*/
|
||||
static bool run_in_synced_context_if_not_already(const std::string& commandname,
|
||||
const config& data,
|
||||
bool use_undo = true,
|
||||
bool show = true,
|
||||
synced_command::error_handler_function error_handler = default_error_function);
|
||||
static bool run_in_synced_context_if_not_already(
|
||||
const std::string& commandname, const config& data, action_spectator& observer = get_default_spectator());
|
||||
|
||||
/**
|
||||
* @return Whether we are currently executing a synced action like recruit, start, recall, disband, movement,
|
||||
|
@ -126,14 +114,8 @@ public:
|
|||
*/
|
||||
static void send_user_choice();
|
||||
|
||||
/** A function to be passed to run_in_synced_context to assert false on error (the default). */
|
||||
static void default_error_function(const std::string& message);
|
||||
|
||||
/** A function to be passed to run_in_synced_context to log the error. */
|
||||
static void just_log_error_function(const std::string& message);
|
||||
|
||||
/** A function to be passed to run_in_synced_context to ignore the error. */
|
||||
static void ignore_error_function(const std::string& message);
|
||||
/** An object to be passed to run_in_synced_context to assert false on error (the default). */
|
||||
static action_spectator& get_default_spectator();
|
||||
|
||||
/** @return A rng_deterministic if in determinsic mode otherwise a rng_synced. */
|
||||
static std::shared_ptr<randomness::rng> get_rng_for_action();
|
||||
|
|
Loading…
Add table
Reference in a new issue