Make new turn, turn X, side turn and turn refresh synchronous (bug #10603)
This commit is contained in:
parent
edb35a09ff
commit
e18bba4b73
12 changed files with 102 additions and 47 deletions
|
@ -9,6 +9,8 @@ Version 1.7.0+svn:
|
|||
* Improved the layout algorithm not to show scrollbars when they make the
|
||||
situation worse
|
||||
* Add a new transient message dialog
|
||||
* Engine:
|
||||
* Make new turn, turn X, side turn and turn refresh synchronous (fr #10603)
|
||||
* Miscellaneous and bugfixes:
|
||||
* Add strict compilation to cmake
|
||||
* Let cmake also use the CXXFLAGS and CFLAGS environment variables
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "terrain_filter.hpp"
|
||||
#include "unit_display.hpp"
|
||||
#include "wml_exception.hpp"
|
||||
#include "play_controller.hpp"
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <algorithm>
|
||||
|
@ -1455,6 +1456,13 @@ WML_HANDLER_FUNCTION(set_variable, /*event_info*/, cfg)
|
|||
|
||||
// Otherwise get the random value from the replay data
|
||||
else {
|
||||
const game_events::resources_t &rsrc = *game_events::resources;
|
||||
/** @todo FIXME: get player_number_ from the play_controller, not from the WML vars. */
|
||||
const t_string& side_str = rsrc.state_of_game->get_variable("side_number");
|
||||
const int side = lexical_cast_default<int>(side_str.base_str(), -1);
|
||||
|
||||
do_replay_handle(*rsrc.screen, *rsrc.game_map, *rsrc.units, *rsrc.teams,
|
||||
side , *rsrc.status_ptr, *rsrc.state_of_game, *rsrc.controller, "random_number");
|
||||
const config* const action = get_replay_source().get_next_action();
|
||||
if(action == NULL || action->get_children("random_number").empty()) {
|
||||
replay::throw_error("random_number expected but none found\n");
|
||||
|
@ -3254,7 +3262,7 @@ WML_HANDLER_FUNCTION(message, event_info, cfg)
|
|||
|
||||
if(!options.empty()) {
|
||||
do_replay_handle(*rsrc.screen, *rsrc.game_map, *rsrc.units, *rsrc.teams,
|
||||
side , *rsrc.status_ptr, *rsrc.state_of_game, "choose");
|
||||
side , *rsrc.status_ptr, *rsrc.state_of_game, *rsrc.controller, "choose");
|
||||
const config* action = get_replay_source().get_next_action();
|
||||
if (!action || !*(action = &action->child("choose"))) {
|
||||
replay::throw_error("choice expected but none found\n");
|
||||
|
@ -3264,7 +3272,7 @@ WML_HANDLER_FUNCTION(message, event_info, cfg)
|
|||
}
|
||||
if(has_text_input) {
|
||||
do_replay_handle(*rsrc.screen, *rsrc.game_map, *rsrc.units, *rsrc.teams,
|
||||
side , *rsrc.status_ptr, *rsrc.state_of_game, "input");
|
||||
side , *rsrc.status_ptr, *rsrc.state_of_game, *rsrc.controller, "input");
|
||||
const config* action = get_replay_source().get_next_action();
|
||||
if (!action || !*(action = &action->child("input"))) {
|
||||
replay::throw_error("input expected but none found\n");
|
||||
|
@ -3708,7 +3716,8 @@ namespace game_events {
|
|||
manager::manager(const config& cfg, gamemap& map_,
|
||||
unit_map& units_,
|
||||
std::vector<team>& teams_,
|
||||
game_state& state_of_game_, gamestatus& status)
|
||||
game_state& state_of_game_, gamestatus& status,
|
||||
play_controller& controller)
|
||||
: resources()
|
||||
, variable_manager(&state_of_game_)
|
||||
{
|
||||
|
@ -3728,6 +3737,7 @@ namespace game_events {
|
|||
resources.state_of_game = &state_of_game_;
|
||||
resources.status_ptr = &status;
|
||||
resources.lua_kernel = new LuaKernel;
|
||||
resources.controller = &controller;
|
||||
game_events::resources = &resources;
|
||||
manager_running = true;
|
||||
|
||||
|
@ -3823,6 +3833,8 @@ namespace game_events {
|
|||
if(!events_init())
|
||||
return;
|
||||
|
||||
LOG_NG << "fire event: " << event << "\n";
|
||||
|
||||
events_queue.push_back(game_events::queued_event(event,loc1,loc2,data));
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ class team;
|
|||
class t_string;
|
||||
class unit;
|
||||
class LuaKernel;
|
||||
class play_controller;
|
||||
|
||||
/**
|
||||
* @file game_events.hpp
|
||||
|
@ -58,6 +59,7 @@ namespace game_events
|
|||
game_state *state_of_game;
|
||||
gamestatus *status_ptr;
|
||||
LuaKernel *lua_kernel;
|
||||
play_controller *controller;
|
||||
};
|
||||
|
||||
extern const resources_t *resources;
|
||||
|
@ -73,7 +75,8 @@ namespace game_events
|
|||
// and must remain valid for the life of the object.
|
||||
manager(const config& scenario_cfg, gamemap& map,
|
||||
unit_map& units, std::vector<team>& teams,
|
||||
game_state& state_of_game, gamestatus& status);
|
||||
game_state& state_of_game, gamestatus& status,
|
||||
play_controller& controller);
|
||||
~manager();
|
||||
void set_gui(game_display&);
|
||||
void set_soundsource(soundsource::manager&);
|
||||
|
|
|
@ -70,7 +70,7 @@ play_controller::play_controller(const config& level, game_state& state_of_game,
|
|||
is_host_(true),
|
||||
skip_replay_(skip_replay),
|
||||
linger_(false),
|
||||
first_turn_(true),
|
||||
previous_turn_(0),
|
||||
savenames_(),
|
||||
wml_commands_(),
|
||||
victory_music_(),
|
||||
|
@ -128,7 +128,7 @@ void play_controller::init(CVideo& video){
|
|||
// as that functions use the manager state_of_game
|
||||
// Has to be done before registering any events!
|
||||
events_manager_.reset(new game_events::manager(level_,map_,
|
||||
units_,teams_, gamestate_,status_));
|
||||
units_,teams_, gamestate_,status_,*this));
|
||||
|
||||
std::set<std::string> seen_save_ids;
|
||||
|
||||
|
@ -397,9 +397,8 @@ void play_controller::fire_start(bool execute){
|
|||
// start event may modify start turn with WML, reflect any changes.
|
||||
start_turn_ = status_.turn();
|
||||
gamestate_.set_variable("turn_number", str_cast<size_t>(start_turn_));
|
||||
first_turn_ = true;
|
||||
} else {
|
||||
first_turn_ = false;
|
||||
previous_turn_ = status_.turn();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,7 +411,7 @@ void play_controller::init_gui(){
|
|||
}
|
||||
}
|
||||
|
||||
void play_controller::init_side(const unsigned int team_index, bool /*is_replay*/){
|
||||
void play_controller::init_side(const unsigned int team_index, bool is_replay){
|
||||
log_scope("player turn");
|
||||
team& current_team = teams_[team_index];
|
||||
|
||||
|
@ -430,21 +429,37 @@ void play_controller::init_side(const unsigned int team_index, bool /*is_replay*
|
|||
gamestate_.set_variable("side_number",player_number_str.str());
|
||||
gamestate_.last_selected = map_location::null_location;
|
||||
|
||||
/*
|
||||
Normally, events must not be actively fired through replays, because
|
||||
they have been recorded previously and therefore will get executed anyway.
|
||||
Firing them in the normal code would lead to double execution.
|
||||
However, the following events are different in that they need to be executed _now_
|
||||
(before calculation of income and healing) or we will risk OOS errors if we manipulate
|
||||
these informations inside the events and in the replay have a different order of execution.
|
||||
*/
|
||||
/**
|
||||
* We do this only for local side when we are not replaying.
|
||||
* For all other sides it is recorded in replay and replay handler has to handle calling do_init_side()
|
||||
* functions.
|
||||
**/
|
||||
if (!current_team.is_local()
|
||||
|| is_replay)
|
||||
return;
|
||||
recorder.init_side();
|
||||
do_init_side(team_index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by replay handler or init_side() to do actual work for turn change.
|
||||
*/
|
||||
void play_controller::do_init_side(const unsigned int team_index){
|
||||
log_scope("player turn");
|
||||
team& current_team = teams_[team_index];
|
||||
|
||||
bool real_side_change = true;
|
||||
if(first_turn_) {
|
||||
first_turn_ = false;
|
||||
game_events::fire("turn " + str_cast<size_t>(start_turn_));
|
||||
game_events::fire("new turn");
|
||||
game_events::fire("side turn");
|
||||
} else if (int(team_index) + 1 != first_player_ || status_.turn() > start_turn_) {
|
||||
if (!loading_game_ || int(team_index) + 1 != first_player_ || status_.turn() > start_turn_) {
|
||||
if (status_.turn() != previous_turn_)
|
||||
{
|
||||
std::stringstream event_stream;
|
||||
event_stream << status_.turn();
|
||||
const std::string turn_num = event_stream.str();
|
||||
|
||||
game_events::fire("turn " + turn_num);
|
||||
game_events::fire("new turn");
|
||||
previous_turn_ = status_.turn();
|
||||
}
|
||||
// Fire side turn event only if real side change occurs,
|
||||
// not counting changes from void to a side
|
||||
game_events::fire("side turn");
|
||||
|
@ -529,8 +544,6 @@ void play_controller::finish_turn(){
|
|||
update_locker lock_display(gui_->video(),recorder.is_skipping());
|
||||
const std::string turn_num = event_stream.str();
|
||||
gamestate_.set_variable("turn_number",turn_num);
|
||||
game_events::fire("turn " + turn_num);
|
||||
game_events::fire("new turn");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ public:
|
|||
virtual void toggle_grid();
|
||||
virtual void search();
|
||||
|
||||
virtual void do_init_side(const unsigned int team_index);
|
||||
virtual void play_side(const unsigned int team_num, bool save) = 0;
|
||||
|
||||
protected:
|
||||
|
@ -155,7 +156,7 @@ protected:
|
|||
bool is_host_;
|
||||
bool skip_replay_;
|
||||
bool linger_;
|
||||
bool first_turn_;
|
||||
unsigned int previous_turn_;
|
||||
|
||||
const std::string& select_victory_music() const;
|
||||
const std::string& select_defeat_music() const;
|
||||
|
|
|
@ -149,7 +149,7 @@ void playmp_controller::before_human_turn(bool save){
|
|||
playsingle_controller::before_human_turn(save);
|
||||
|
||||
turn_data_ = new turn_info(gamestate_,status_,
|
||||
*gui_,map_,teams_,player_number_,units_,replay_sender_, undo_stack_);
|
||||
*gui_,map_,teams_,player_number_,units_,replay_sender_, undo_stack_, *this);
|
||||
turn_data_->replay_error().attach_handler(this);
|
||||
turn_data_->host_transfer().attach_handler(this);
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ void playmp_controller::linger(upload_log& log)
|
|||
player_number_ = first_player_;
|
||||
turn_data_ = new turn_info(gamestate_, status_,
|
||||
*gui_,map_, teams_, player_number_,
|
||||
units_, replay_sender_, undo_stack_);
|
||||
units_, replay_sender_, undo_stack_,*this);
|
||||
turn_data_->replay_error().attach_handler(this);
|
||||
turn_data_->host_transfer().attach_handler(this);
|
||||
|
||||
|
@ -389,7 +389,7 @@ void playmp_controller::wait_for_upload()
|
|||
const bool set_turn_data = (turn_data_ == 0);
|
||||
if(set_turn_data) {
|
||||
turn_data_ = new turn_info(gamestate_,status_,
|
||||
*gui_,map_,teams_,player_number_,units_,replay_sender_, undo_stack_);
|
||||
*gui_,map_,teams_,player_number_,units_,replay_sender_, undo_stack_, *this);
|
||||
turn_data_->replay_error().attach_handler(this);
|
||||
turn_data_->host_transfer().attach_handler(this);
|
||||
}
|
||||
|
@ -468,7 +468,7 @@ void playmp_controller::play_network_turn(){
|
|||
|
||||
gui_->enable_menu("endturn", false);
|
||||
turn_info turn_data(gamestate_,status_,*gui_,
|
||||
map_,teams_,player_number_,units_, replay_sender_, undo_stack_);
|
||||
map_,teams_,player_number_,units_, replay_sender_, undo_stack_,*this);
|
||||
turn_data.replay_error().attach_handler(this);
|
||||
turn_data.host_transfer().attach_handler(this);
|
||||
|
||||
|
@ -544,7 +544,7 @@ void playmp_controller::process_oos(const std::string& err_msg){
|
|||
|
||||
void playmp_controller::handle_generic_event(const std::string& name){
|
||||
turn_info turn_data(gamestate_,status_,*gui_,
|
||||
map_,teams_,player_number_,units_, replay_sender_, undo_stack_);
|
||||
map_,teams_,player_number_,units_, replay_sender_, undo_stack_, *this);
|
||||
|
||||
if (name == "ai_user_interact"){
|
||||
playsingle_controller::handle_generic_event(name);
|
||||
|
|
|
@ -549,7 +549,7 @@ void playsingle_controller::play_turn(bool save)
|
|||
} catch (end_turn_exception) {
|
||||
if (current_team().is_network() == false) {
|
||||
turn_info turn_data(gamestate_, status_, *gui_, map_,
|
||||
teams_, player_number_, units_, replay_sender_, undo_stack_);
|
||||
teams_, player_number_, units_, replay_sender_, undo_stack_,*this);
|
||||
recorder.end_turn();
|
||||
turn_data.sync_network();
|
||||
}
|
||||
|
@ -560,7 +560,7 @@ void playsingle_controller::play_turn(bool save)
|
|||
LOG_NG << "doing replay " << player_number_ << "\n";
|
||||
try {
|
||||
replaying_ = ::do_replay(*gui_, map_, units_, teams_,
|
||||
player_number_, status_, gamestate_);
|
||||
player_number_, status_, gamestate_, *this);
|
||||
} catch(replay::error&) {
|
||||
gui2::show_transient_message(gui_->video(),"",_("The file you have tried to load is corrupt"));
|
||||
|
||||
|
@ -572,7 +572,7 @@ void playsingle_controller::play_turn(bool save)
|
|||
if (current_team().is_human() && side_units(units_, player_number_) == 0)
|
||||
{
|
||||
turn_info turn_data(gamestate_, status_, *gui_, map_,
|
||||
teams_, player_number_, units_, replay_sender_, undo_stack_);
|
||||
teams_, player_number_, units_, replay_sender_, undo_stack_, *this);
|
||||
recorder.end_turn();
|
||||
turn_data.sync_network();
|
||||
continue;
|
||||
|
@ -831,7 +831,7 @@ void playsingle_controller::play_ai_turn(){
|
|||
const cursor::setter cursor_setter(cursor::WAIT);
|
||||
|
||||
turn_info turn_data(gamestate_,status_,*gui_,
|
||||
map_, teams_, player_number_, units_, replay_sender_, undo_stack_);
|
||||
map_, teams_, player_number_, units_, replay_sender_, undo_stack_, *this);
|
||||
|
||||
try {
|
||||
ai_manager::play_turn(player_number_, this);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "log.hpp"
|
||||
#include "replay.hpp"
|
||||
#include "formula_string_utils.hpp"
|
||||
#include "play_controller.hpp"
|
||||
|
||||
static lg::log_domain log_network("network");
|
||||
#define ERR_NW LOG_STREAM(err, log_network)
|
||||
|
@ -30,13 +31,20 @@ static lg::log_domain log_network("network");
|
|||
turn_info::turn_info(game_state& state_of_game,
|
||||
const gamestatus& status, game_display& gui, gamemap& map,
|
||||
std::vector<team>& teams, unsigned int team_num, unit_map& units,
|
||||
replay_network_sender& replay_sender, undo_list& undo_stack)
|
||||
replay_network_sender& replay_sender, undo_list& undo_stack, play_controller& controller)
|
||||
: state_of_game_(state_of_game), status_(status),
|
||||
gui_(gui), map_(map), teams_(teams), team_num_(team_num),
|
||||
units_(units), undo_stack_(undo_stack),
|
||||
replay_sender_(replay_sender), replay_error_("network_replay_error"),
|
||||
host_transfer_("host_transfer")
|
||||
{}
|
||||
host_transfer_("host_transfer"),
|
||||
controller_(controller)
|
||||
{
|
||||
/**
|
||||
* We do network sync so [init_side] is transfered to network hosts
|
||||
*/
|
||||
if(network::nconnections() > 0)
|
||||
send_data();
|
||||
}
|
||||
|
||||
turn_info::~turn_info(){
|
||||
undo_stack_.clear();
|
||||
|
@ -118,7 +126,7 @@ turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg
|
|||
|
||||
try{
|
||||
turn_end = do_replay(gui_, map_, units_, teams_,
|
||||
team_num_, status_, state_of_game_, &replay_obj);
|
||||
team_num_, status_, state_of_game_, controller_, &replay_obj);
|
||||
}
|
||||
catch (replay::error& e){
|
||||
//notify remote hosts of out of sync error
|
||||
|
|
|
@ -21,6 +21,7 @@ class game_state;
|
|||
class replay_network_sender;
|
||||
class team;
|
||||
class unit;
|
||||
class play_controller;
|
||||
|
||||
#include "global.hpp"
|
||||
|
||||
|
@ -37,7 +38,7 @@ public:
|
|||
turn_info(game_state& state_of_game,
|
||||
const gamestatus& status, game_display& gui, gamemap& map,
|
||||
std::vector<team>& teams, unsigned int team_num, unit_map& units,
|
||||
replay_network_sender& network_sender, undo_list& undo_stack);
|
||||
replay_network_sender& network_sender, undo_list& undo_stack, play_controller& controller);
|
||||
|
||||
~turn_info();
|
||||
|
||||
|
@ -82,6 +83,7 @@ private:
|
|||
|
||||
events::generic_event replay_error_;
|
||||
events::generic_event host_transfer_;
|
||||
play_controller &controller_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "log.hpp"
|
||||
#include "map.hpp"
|
||||
#include "map_label.hpp"
|
||||
#include "play_controller.hpp"
|
||||
#include "replay.hpp"
|
||||
#include "statistics.hpp"
|
||||
#include "unit_display.hpp"
|
||||
|
@ -359,6 +360,12 @@ void replay::add_rename(const std::string& name, const map_location& loc)
|
|||
cmd->add_child("rename", val);
|
||||
}
|
||||
|
||||
void replay::init_side()
|
||||
{
|
||||
config* const cmd = add_command();
|
||||
cmd->add_child("init_side");
|
||||
}
|
||||
|
||||
void replay::end_turn()
|
||||
{
|
||||
config* const cmd = add_command();
|
||||
|
@ -731,7 +738,7 @@ static void check_checksums(game_display& disp,const unit_map& units,const confi
|
|||
|
||||
bool do_replay(game_display& disp, const gamemap& map,
|
||||
unit_map& units, std::vector<team>& teams, int team_num,
|
||||
const gamestatus& state, game_state& state_of_game, replay* obj)
|
||||
const gamestatus& state, game_state& state_of_game, play_controller& controller, replay* obj)
|
||||
{
|
||||
log_scope("do replay");
|
||||
|
||||
|
@ -746,13 +753,13 @@ bool do_replay(game_display& disp, const gamemap& map,
|
|||
const rand_rng::set_random_generator generator_setter(&get_replay_source());
|
||||
|
||||
update_locker lock_update(disp.video(),get_replay_source().is_skipping());
|
||||
return do_replay_handle(disp, map, units, teams, team_num, state, state_of_game,
|
||||
return do_replay_handle(disp, map, units, teams, team_num, state, state_of_game, controller,
|
||||
std::string(""));
|
||||
}
|
||||
|
||||
bool do_replay_handle(game_display& disp, const gamemap& map,
|
||||
unit_map& units, std::vector<team>& teams, int team_num,
|
||||
const gamestatus& state, game_state& state_of_game,
|
||||
const gamestatus& state, game_state& state_of_game, play_controller& controller,
|
||||
const std::string& do_untill)
|
||||
{
|
||||
//a list of units that have promoted from the last attack
|
||||
|
@ -880,6 +887,11 @@ bool do_replay_handle(game_display& disp, const gamemap& map,
|
|||
}
|
||||
}
|
||||
|
||||
else if (cfg->child("init_side"))
|
||||
{
|
||||
controller.do_init_side(team_num - 1);
|
||||
}
|
||||
|
||||
//if there is an end turn directive
|
||||
else if (cfg->child("end_turn"))
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@ class config_writer;
|
|||
class game_display;
|
||||
class terrain_label;
|
||||
class unit_map;
|
||||
class play_controller;
|
||||
|
||||
struct verification_manager
|
||||
{
|
||||
|
@ -59,6 +60,7 @@ public:
|
|||
void add_label(const terrain_label*);
|
||||
void clear_labels(const std::string&);
|
||||
void add_rename(const std::string& name, const map_location& loc);
|
||||
void init_side();
|
||||
void end_turn();
|
||||
void add_event(const std::string& name,
|
||||
const map_location& loc=map_location::null_location);
|
||||
|
@ -153,11 +155,11 @@ extern replay recorder;
|
|||
//returns true if it got to the end of the turn without data running out
|
||||
bool do_replay(game_display& disp, const gamemap& map,
|
||||
unit_map& units, std::vector<team>& teams, int team_num,
|
||||
const gamestatus& state, game_state& state_of_game, replay* obj=NULL);
|
||||
const gamestatus& state, game_state& state_of_game, play_controller& controller, replay* obj=NULL);
|
||||
|
||||
bool do_replay_handle(game_display& disp, const gamemap& map,
|
||||
unit_map& units, std::vector<team>& teams, int team_num,
|
||||
const gamestatus& state, game_state& state_of_game,
|
||||
const gamestatus& state, game_state& state_of_game, play_controller& controller,
|
||||
const std::string& do_untill);
|
||||
|
||||
//an object which can be made to undo a recorded move
|
||||
|
|
|
@ -177,7 +177,7 @@ void replay_controller::reset_replay(){
|
|||
// failure)
|
||||
events_manager_.reset();
|
||||
events_manager_.reset(new game_events::manager(level_,map_,
|
||||
units_,teams_, gamestate_,status_));
|
||||
units_,teams_, gamestate_,status_, *this));
|
||||
events_manager_->set_gui(*gui_);
|
||||
events_manager_->set_soundsource(*soundsources_manager_);
|
||||
}
|
||||
|
@ -338,7 +338,7 @@ void replay_controller::play_side(const unsigned int /*team_index*/, bool){
|
|||
DBG_REPLAY << "doing replay " << player_number_ << "\n";
|
||||
try {
|
||||
::do_replay(*gui_, map_, units_, teams_,
|
||||
player_number_, status_, gamestate_);
|
||||
player_number_, status_, gamestate_, *this);
|
||||
} catch(replay::error&) {
|
||||
if(!continue_replay()) {
|
||||
throw;
|
||||
|
|
Loading…
Add table
Reference in a new issue