add a synced_context::block_undo() function

Using this function lets te synced context know that the current
action cannot be undone, so that it will in particular send the
actions too all players as soon as possible. The intention is
less delay in networked games.

Currently there is some redundance between is_simultanious_
and is_undo_blocked_, maybe one of these will be removed
later.
This commit is contained in:
gfgtdf 2023-03-31 20:15:08 +02:00
parent f2bf2dd465
commit 79a88266e4
3 changed files with 16 additions and 5 deletions

View file

@ -323,8 +323,6 @@ SYNCED_COMMAND_HANDLER_FUNCTION(move, child, use_undo, show, error_handler)
SYNCED_COMMAND_HANDLER_FUNCTION(fire_event, child, use_undo, /*show*/, /*error_handler*/)
{
bool undoable = true;
if(const auto last_select = child.optional_child("last_select"))
{
//the select event cannot clear the undo stack.
@ -332,14 +330,14 @@ SYNCED_COMMAND_HANDLER_FUNCTION(fire_event, child, use_undo, /*show*/, /*error_
}
const std::string &event_name = child["raise"];
if (const auto source = child.optional_child("source")) {
undoable = undoable & !std::get<0>(resources::game_events->pump().fire(event_name, map_location(source.value(), resources::gamedata)));
synced_context::block_undo(std::get<0>(resources::game_events->pump().fire(event_name, map_location(source.value(), resources::gamedata))));
} else {
undoable = undoable & !std::get<0>(resources::game_events->pump().fire(event_name));
synced_context::block_undo(std::get<0>(resources::game_events->pump().fire(event_name)));
}
// Not clearing the undo stack here causes OOS because we added an entry to the replay but no entry to the undo stack.
if(use_undo) {
if(!undoable || synced_context::undo_blocked()) {
if(synced_context::undo_blocked()) {
resources::undo_stack->clear();
} else {
resources::undo_stack->add_dummy();

View file

@ -204,6 +204,11 @@ void synced_context::set_is_simultaneous()
is_simultaneous_ = true;
}
void synced_context::block_undo(bool do_block)
{
is_undo_blocked_ |= do_block;
}
bool synced_context::undo_blocked()
{
// this method should only works in a synced context.
@ -213,6 +218,7 @@ bool synced_context::undo_blocked()
// if the game has ended, undoing is blocked.
// if the turn has ended undoing is blocked.
return is_simultaneous_
|| is_undo_blocked_
|| (randomness::generator->get_random_calls() != 0)
|| resources::controller->is_regular_game_end()
|| resources::gamedata->end_turn_forced();
@ -382,6 +388,7 @@ set_scontext_synced_base::set_scontext_synced_base()
synced_context::set_synced_state(synced_context::SYNCED);
synced_context::reset_is_simultaneous();
synced_context::reset_block_undo();
synced_context::set_last_unit_id(resources::gameboard->unit_id_manager().get_save_id());
synced_context::reset_undo_commands();

View file

@ -152,6 +152,11 @@ public:
/** Sets is_simultaneous_ = true, called using a user choice that is not the currently playing side. */
static void set_is_simultaneous();
static void block_undo(bool do_block = true);
static void reset_block_undo()
{
is_undo_blocked_ = false;
}
/** @return Whether we tracked something that can never be undone. */
static bool undo_blocked();
@ -224,6 +229,7 @@ private:
* TODO: it would be better if the following variable were not static.
*/
static inline bool is_simultaneous_ = false;
static inline bool is_undo_blocked_ = false;
/** Used to restore the unit id manager when undoing. */
static inline int last_unit_id_ = 0;