fix chat during [delay] and animations

fixes #1856
This commit is contained in:
gfgtdf 2018-03-24 23:16:57 +01:00
parent 125c33039a
commit 219f977b27
7 changed files with 60 additions and 16 deletions

View file

@ -66,7 +66,7 @@ public:
controller_base(const config& game_config);
virtual ~controller_base();
void play_slice(bool is_delay_enabled = true);
virtual void play_slice(bool is_delay_enabled = true);
static const config& get_theme(const config& game_config, std::string theme_name);

View file

@ -454,7 +454,15 @@ void playmp_controller::send_user_choice()
turn_data_.send_data();
}
void playmp_controller::process_network_data()
void playmp_controller::play_slice(bool is_delay_enabled)
{
process_network_data(true);
//cannot use turn_data_.send_data() here.
replay_sender_.sync_non_undoable();
playsingle_controller::play_slice(is_delay_enabled);
}
void playmp_controller::process_network_data(bool chat_only)
{
if(end_turn_ == END_TURN_SYNCED || is_regular_game_end() || player_type_changed_) {
return;
@ -465,10 +473,13 @@ void playmp_controller::process_network_data()
res = turn_info::replay_to_process_data_result(do_replay());
}
else if(network_reader_.read(cfg)) {
res = turn_data_.process_network_data(cfg);
res = turn_data_.process_network_data(cfg, chat_only);
}
if (res == turn_info::PROCESS_RESTART_TURN) {
if (res == turn_info::PROCESS_CANNOT_HANDLE) {
network_reader_.push_front(std::move(cfg));
}
else if (res == turn_info::PROCESS_RESTART_TURN) {
player_type_changed_ = true;
}
else if (res == turn_info::PROCESS_END_TURN) {

View file

@ -40,6 +40,9 @@ public:
bool is_networked_mp() const override;
void send_to_wesnothd(const config& cfg, const std::string& packet_type = "unknown") const override;
bool receive_from_wesnothd(config& cfg) const override;
void play_slice(bool is_delay_enabled = true) override;
protected:
virtual void handle_generic_event(const std::string& name) override;
@ -67,6 +70,6 @@ protected:
private:
void set_end_scenario_button();
void reset_end_scenario_button();
void process_network_data();
void process_network_data(bool chat_only = false);
mp_campaign_info* mp_info_;
};

View file

@ -85,10 +85,14 @@ void turn_info::send_data()
}
}
turn_info::PROCESS_DATA_RESULT turn_info::handle_turn(const config& t)
turn_info::PROCESS_DATA_RESULT turn_info::handle_turn(const config& t, bool chat_only)
{
//t can contain a [command] or a [upload_log]
assert(t.all_children_count() == 1);
if(!t.child_or_empty("command").has_child("speak") && chat_only) {
return PROCESS_CANNOT_HANDLE;
}
/** @todo FIXME: Check what commands we execute when it's our turn! */
//note, that this function might call itself recursively: do_replay -> ... -> get_user_choice -> ... -> playmp_controller::pull_remote_choice -> sync_network -> handle_turn
@ -119,7 +123,7 @@ turn_info::PROCESS_DATA_RESULT turn_info::process_network_data_from_reader()
return PROCESS_CONTINUE;
}
turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg)
turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg, bool chat_only)
{
// the simple wesnothserver implementation in wesnoth was removed years ago.
assert(cfg.all_children_count() == 1);
@ -154,7 +158,7 @@ turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg
}
else if (const config &turn = cfg.child("turn"))
{
return handle_turn(turn);
return handle_turn(turn, chat_only);
}
else if (cfg.has_child("whiteboard"))
{
@ -346,6 +350,9 @@ turn_info::PROCESS_DATA_RESULT turn_info::process_network_data(const config& cfg
// The host has ended linger mode in a campaign -> enable the "End scenario" button
// and tell we did get the notification.
else if (cfg.child("notify_next_scenario")) {
if(chat_only) {
return PROCESS_CANNOT_HANDLE;
}
std::shared_ptr<gui::button> btn_end = display::get_singleton()->find_action_button("button-endturn");
if(btn_end) {
btn_end->enable(true);

View file

@ -42,6 +42,8 @@ public:
PROCESS_END_LINGER,
/** When we couldn't process the network data because we found a dependent command, this should only happen if we were called playmp_controller::from handle_generic_event -> sync_network*/
PROCESS_FOUND_DEPENDENT,
/** when we couldn't handle the given action currently. */
PROCESS_CANNOT_HANDLE,
/** We found a player action in the replay that caused the game to end*/
PROCESS_END_LEVEL
};
@ -51,7 +53,7 @@ public:
void send_data();
//function which will process incoming network data received with playturn_network_adapter, and act on it.
PROCESS_DATA_RESULT process_network_data(const config& cfg);
PROCESS_DATA_RESULT process_network_data(const config& cfg, bool chat_only = false);
//reads as much data from network_reader_ as possible and processed it.
PROCESS_DATA_RESULT process_network_data_from_reader();
@ -61,7 +63,7 @@ public:
static PROCESS_DATA_RESULT replay_to_process_data_result(REPLAY_RETURN replayreturn);
private:
static void change_side_controller(int side, const std::string& player);
PROCESS_DATA_RESULT handle_turn(const config& t);
PROCESS_DATA_RESULT handle_turn(const config& t, bool chat_only = false);
void do_save();

View file

@ -66,9 +66,20 @@ bool playturn_network_adapter::is_at_end()
return this->next_ == data_.back().ordered_end();
}
void playturn_network_adapter::push_front(config&& cfg)
{
data_front_.emplace_front(std::move(cfg));
}
bool playturn_network_adapter::read(config& dst)
{
assert(dst.empty());
if(!data_front_.empty())
{
dst = std::move(data_front_.back());
data_front_.pop_back();
return true;
}
if(is_at_end())
{
read_from_network();
@ -114,10 +125,12 @@ bool playturn_network_adapter::read(config& dst)
}
playturn_network_adapter::playturn_network_adapter(source_type source)
: data_({config()}),
next_(data_.front().ordered_end()),
next_command_num_(0),
network_reader_(source)
: network_reader_(source)
, data_({config()})
, data_front_()
, next_(data_.front().ordered_end())
, next_command_num_(0)
{
}

View file

@ -37,16 +37,24 @@ public:
void set_source(source_type source);
//returns a function to be passed to set_source.
static source_type get_source_from_config(config& src);
void push_front(config&& cfg);
private:
//reads data from the network stream.
void read_from_network();
//a function to receive data from the network.
source_type network_reader_;
// note: all of the following could be replaced by a simple std::list<config> if we would
// split incoming tags right after we rechived them from network_reader_ the reason
// why we currently don'T do that is for performance.
//this always contains one empty config because we want a valid value for next_.
std::list<config> data_;
//packages that the client could not process at that point.
std::list<config> data_front_;
//the position of the next to be received element in data_->front().
config::all_children_iterator next_;
//if we are processing a [turn] with multiple [command] we want to split them.
//In this case next_command_num_ is the next to be processed turn into a command otherwise it's 0;
unsigned int next_command_num_;
//a function to receive data from the network.
source_type network_reader_;
};