use synced context: sync the turn ... events and prestart events.

by using set_scontext_synced and recording brefore doing that.

we split fire_prestart and fire_preload becasue prestart runs in a synced context and fire preload not.

we also dont need recorder.pre_replay anymore becasue of the changes to the rng.

the line synced_context::run_in_synced_context("auto_shroud", replay_helper::get_auto_shroud(true));
was accidently placed in this commit and should rather be in the commit called "use synced_context in undo and rest"
this commit is part of pr 121.
This commit is contained in:
gfgtdf 2014-03-24 19:59:36 +01:00
parent 1f794e03d8
commit 7d3a42c7fa
5 changed files with 90 additions and 28 deletions

View File

@ -42,7 +42,9 @@
#include "save_blocker.hpp"
#include "preferences_display.hpp"
#include "replay.hpp"
#include "random_new_deterministic.hpp"
#include "soundsource.hpp"
#include "synced_context.hpp"
#include "tooltips.hpp"
#include "wml_exception.hpp"
#include "ai/manager.hpp"
@ -174,13 +176,8 @@ void play_controller::init(CVideo& video){
}
loadscreen::start_stage("load level");
// If the recorder has no event, adds an "game start" event
// to the recorder, whose only goal is to initialize the RNG
if(recorder.empty()) {
recorder.add_start();
} else {
recorder.pre_replay();
}
// i currently assume that no random calls take place before the "prestart" event
// If i am wrong, use random_new_deterministic
recorder.set_skip(false);
bool snapshot = level_["snapshot"].to_bool();
@ -545,14 +542,16 @@ void play_controller::search(){
menu_handler_.search();
}
void play_controller::fire_prestart(bool execute)
void play_controller::fire_preload()
{
// Run initialization scripts, even if loading from a snapshot.
gamedata_.set_phase(game_data::PRELOAD);
resources::lua_kernel->initialize();
gamedata_.get_variable("turn_number") = int(turn());
game_events::fire("preload");
}
void play_controller::fire_prestart(bool execute)
{
// pre-start events must be executed before any GUI operation,
// as those may cause the display to be refreshed.
if (execute){
@ -622,8 +621,11 @@ void play_controller::maybe_do_init_side(const unsigned int team_index, bool is_
}
if (!loading_game_) recorder.init_side();
LOG_NG << "set_scontext_synced sync from maybe_do_init_side";
set_scontext_synced sync;
do_init_side(team_index, is_replay);
LOG_NG << "set_scontext_synced sync from maybe_do_init_side end ";
}
/**
@ -787,11 +789,15 @@ void play_controller::finish_side_turn(){
const std::string turn_num = str_cast(turn());
const std::string side_num = str_cast(player_number_);
if(true) //RAII block
{
set_scontext_synced sync(1);
//random_new::set_random_determinstic deterministic(resources::gamedata->rng());
game_events::fire("side turn end");
game_events::fire("side "+ side_num + " turn end");
game_events::fire("side turn " + turn_num + " end");
game_events::fire("side " + side_num + " turn " + turn_num + " end");
}
// This is where we refog, after all of a side's events are done.
actions::recalculate_fog(player_number_);
@ -809,6 +815,8 @@ void play_controller::finish_side_turn(){
void play_controller::finish_turn()
{
set_scontext_synced sync(2);
//random_new::set_random_determinstic deterministic(resources::gamedata->rng());
const std::string turn_num = str_cast(turn());
game_events::fire("turn end");
game_events::fire("turn " + turn_num + " end");

View File

@ -189,6 +189,8 @@ protected:
bool in_context_menu(hotkey::HOTKEY_COMMAND command) const;
void init_managers();
///preload events cannot be synced
void fire_preload();
void fire_prestart(bool execute);
void fire_start(bool execute);
virtual void init_gui();

View File

@ -35,8 +35,11 @@
#include "marked-up_text.hpp"
#include "playturn.hpp"
#include "resources.hpp"
#include "random_new_deterministic.hpp"
#include "replay_helper.hpp"
#include "savegame.hpp"
#include "sound.hpp"
#include "synced_context.hpp"
#include "formula_string_utils.hpp"
#include "events.hpp"
#include "save_blocker.hpp"
@ -371,20 +374,48 @@ LEVEL_RESULT playsingle_controller::play_scenario(
gamestate_.replay_start() = to_config();
gamestate_.write_snapshot(gamestate_.replay_start(), gui_.get());
}
fire_prestart(!loading_game_);
init_gui();
past_prestart = true;
LOG_NG << "first_time..." << (recorder.is_skipping() ? "skipping" : "no skip") << "\n";
events::raise_draw_event();
fire_start(!loading_game_);
gui_->recalculate_minimap();
fire_preload();
replaying_ = (recorder.at_end() == false);
if(!loading_game_ )
{
if(replaying_)
{
//can this codepath be reached ?
//note this when we are entering an mp game and see the 'replay' of the game
//this path is not reached because we receive the replay later
config* pstart = recorder.get_next_action();
assert(pstart->has_child("start"));
}
else
{
assert(recorder.empty());
recorder.add_start();
recorder.get_next_action();
}
//we can only use a set_scontext_synced with a non empty recorder.
set_scontext_synced sync;
fire_prestart(true);
init_gui();
past_prestart = true;
LOG_NG << "first_time..." << (recorder.is_skipping() ? "skipping" : "no skip") << "\n";
events::raise_draw_event();
fire_start(true);
gui_->recalculate_minimap();
}
else
{
init_gui();
past_prestart = true;
events::raise_draw_event();
fire_start(false);
gui_->recalculate_minimap();
}
LOG_NG << "starting main loop\n" << (SDL_GetTicks() - ticks_) << "\n";
// Initialize countdown clock.
@ -891,8 +922,7 @@ void playsingle_controller::play_ai_turn(){
if ( !cur_team.auto_shroud_updates() ) {
// We just took control, so the undo stack is empty. We still need
// to record this change for the replay though.
recorder.add_auto_shroud(true);
cur_team.set_auto_shroud_updates(true);
synced_context::run_in_synced_context("auto_shroud", replay_helper::get_auto_shroud(true));
}
turn_info turn_data(player_number_, replay_sender_);

View File

@ -94,6 +94,7 @@ protected:
const cursor::setter cursor_setter;
std::deque<config> data_backlog_;
gui::floating_textbox textbox_info_;
replay_network_sender replay_sender_;
bool end_turn_;

View File

@ -22,9 +22,11 @@
#include "log.hpp"
#include "map_label.hpp"
#include "replay.hpp"
#include "random_new_deterministic.hpp"
#include "replay_controller.hpp"
#include "resources.hpp"
#include "savegame.hpp"
#include "synced_context.hpp"
#include <boost/foreach.hpp>
@ -286,9 +288,28 @@ void replay_controller::reset_replay(){
}
// Scenario initialization. (c.f. playsingle_controller::play_scenario())
fire_prestart(true);
init_gui();
fire_start(true);
fire_preload();
if(true){
config* pstart = recorder.get_next_action();
assert(pstart->has_child("start"));
/*
use this after recorder.add_synced_command
because set_scontext_synced sets the checkup to the last added command
*/
set_scontext_synced sync;
//block for RAII
// if we use set_scontext_synced we need to have fire_prestart and fire_start in the same set_scontext_synced block because
// we can only have one set_scontext_synced per replay command (here it is the "start" replay command).
// and there is no replay command between them.
// EDIT: if the server dont allow require_random form other sides this comment is outdated.
DBG_REPLAY << "set_random_determinstic sync in replay_controller::reset_replay()\n";
fire_prestart(true);
init_gui();
fire_start(true);
DBG_REPLAY << "set_scontext_synced sync in replay_controller::reset_replay() end\n";
}
// Since we did not fire the start event, it_is_a_new_turn_ has the wrong value.
it_is_a_new_turn_ = true;
update_gui();