Skip to content

Commit

Permalink
move mp countdown code to new class
Browse files Browse the repository at this point in the history
  • Loading branch information
gfgtdf committed Feb 26, 2015
1 parent f16a0f6 commit 781df37
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 98 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Expand Up @@ -773,6 +773,7 @@ set(wesnoth-main_SRC
game_initialization/configure_engine.cpp
game_initialization/connect_engine.cpp
controller_base.cpp
countdown_clock.cpp
game_initialization/create_engine.cpp
game_initialization/depcheck.cpp
desktop/notifications.cpp
Expand Down
1 change: 1 addition & 0 deletions src/SConscript
Expand Up @@ -245,6 +245,7 @@ wesnoth_sources = Split("""
game_initialization/configure_engine.cpp
game_initialization/connect_engine.cpp
controller_base.cpp
countdown_clock.cpp
game_initialization/create_engine.cpp
desktop/notifications.cpp
desktop/open.cpp
Expand Down
73 changes: 73 additions & 0 deletions src/countdown_clock.cpp
@@ -0,0 +1,73 @@

#include "countdown_clock.hpp"

#include "team.hpp"
#include "saved_game.hpp"
#include "preferences.hpp"
#include "sound.hpp"

namespace {
const int WARNTIME = 20000; //start beeping when 20 seconds are left (20,000ms)
unsigned timer_refresh = 0;
const unsigned timer_refresh_rate = 50; // prevents calling SDL_GetTicks() too frequently
}


countdown_clock::countdown_clock(team& team, const mp_game_settings& settings)
: team_(team)
, settings_(settings)
, last_timestamp_(SDL_GetTicks())
, playing_sound_(false)
{
}


countdown_clock::~countdown_clock()
{
if(playing_sound_)
{
sound::stop_bell();
}
}

int countdown_clock::update_timestamp(int new_timestamp)
{
int res = std::max<int>(0, new_timestamp - last_timestamp_);
last_timestamp_ = new_timestamp;
return res;
}

void countdown_clock::update_team(int new_timestamp)
{
int time_passed = update_timestamp(new_timestamp);
team_.set_countdown_time(std::max<int>(0, team_.countdown_time() - time_passed));
}

//make sure we think about countdown even while dialogs are open
void countdown_clock::process(events::pump_info &info)
{
if(info.ticks(&timer_refresh, timer_refresh_rate)) {
update(info.ticks());
}
}

bool countdown_clock::update(int new_timestamp)
{
update_team(new_timestamp);
maybe_play_sound();
return team_.countdown_time() > 0;
}

void countdown_clock::maybe_play_sound()
{
if(!playing_sound_ && team_.countdown_time() < WARNTIME )
{
if(preferences::turn_bell() || preferences::sound_on() || preferences::UI_sound_on())
{
const int loop_ticks = team_.countdown_time();
const int fadein_ticks = (loop_ticks > WARNTIME / 2) ? loop_ticks - WARNTIME / 2 : 0;
sound::play_timer(game_config::sounds::timer_bell, loop_ticks, fadein_ticks);
playing_sound_ = true;
}
}
}
28 changes: 28 additions & 0 deletions src/countdown_clock.hpp
@@ -0,0 +1,28 @@
#pragma once
#include "events.hpp"
#include <SDL_timer.h>

class team;
struct mp_game_settings;
class countdown_clock : public events::pump_monitor
{
public:
countdown_clock(team& team, const mp_game_settings& settings);
~countdown_clock();
/// @returns ticks passed since last update
/// @param new_timestamp latest result of SDL_GetTicks()
int update_timestamp(int new_timestamp);
/// @param new_timestamp latest result of SDL_GetTicks()
void update_team(int new_timestamp);
void process(events::pump_info &info);
/// @return whether there is time left
/// @param new_timestamp latest result of SDL_GetTicks()
bool update(int new_timestamp = SDL_GetTicks());
void maybe_play_sound();
private:
team& team_;
const mp_game_settings& settings_;
int last_timestamp_;
bool playing_sound_;
};

115 changes: 23 additions & 92 deletions src/playmp_controller.cpp
Expand Up @@ -31,7 +31,7 @@
#include "formula_string_utils.hpp"
#include "unit_animation.hpp"
#include "whiteboard/manager.hpp"

#include "countdown_clock.hpp"
#include <boost/foreach.hpp>

static lg::log_domain log_engine("engine");
Expand All @@ -45,7 +45,6 @@ playmp_controller::playmp_controller(const config& level,
bool skip_replay, bool blindfold_replay_, bool is_host)
: playsingle_controller(level, state_of_game, ticks,
game_config, tdata, video, skip_replay || blindfold_replay_) //this || means that if blindfold is enabled, quick replays will be on.
, beep_warning_time_(0)
, network_processing_stopped_(false)
, blindfold_(*gui_,blindfold_replay_)
{
Expand All @@ -66,11 +65,6 @@ playmp_controller::playmp_controller(const config& level,
playmp_controller::~playmp_controller() {
//halt and cancel the countdown timer
try {

if(beep_warning_time_ < 0) {
sound::stop_bell();
}

turn_data_.host_transfer().detach_handler(this);
} catch (...) {}
}
Expand Down Expand Up @@ -114,51 +108,15 @@ void playmp_controller::remove_blindfold() {
}
}

bool playmp_controller::counting_down() {
return beep_warning_time_ > 0;
}

namespace {
const int WARNTIME = 20000; //start beeping when 20 seconds are left (20,000ms)
unsigned timer_refresh = 0;
const unsigned timer_refresh_rate = 50; // prevents calling SDL_GetTicks() too frequently
}

//make sure we think about countdown even while dialogs are open
void playmp_controller::process(events::pump_info &info) {
if(playmp_controller::counting_down()) {
if(info.ticks(&timer_refresh, timer_refresh_rate)) {
playmp_controller::think_about_countdown(info.ticks());
}
}
}

void playmp_controller::reset_countdown()
{
if (beep_warning_time_ < 0)
sound::stop_bell();
beep_warning_time_ = 0;
}

//check if it is time to start playing the timer warning
void playmp_controller::think_about_countdown(int ticks) {
if(ticks >= beep_warning_time_) {
const bool bell_on = preferences::turn_bell();
if(bell_on || preferences::sound_on() || preferences::UI_sound_on()) {
const int loop_ticks = WARNTIME - (ticks - beep_warning_time_);
const int fadein_ticks = (loop_ticks > WARNTIME / 2) ? loop_ticks - WARNTIME / 2 : 0;
sound::play_timer(game_config::sounds::timer_bell, loop_ticks, fadein_ticks);
beep_warning_time_ = -1;
}
}
}

possible_end_play_signal playmp_controller::play_human_turn()
{
LOG_NG << "playmp::play_human_turn...\n";

remove_blindfold();
int cur_ticks = SDL_GetTicks();
boost::scoped_ptr<countdown_clock> timer;
if(!linger_ && saved_game_.mp_settings().mp_countdown) {
timer.reset(new countdown_clock(current_team(), saved_game_.mp_settings()));
}
show_turn_dialog();

if (!preferences::disable_auto_moves()) {
Expand Down Expand Up @@ -210,36 +168,17 @@ possible_end_play_signal playmp_controller::play_human_turn()
}

HANDLE_END_PLAY_SIGNAL( play_slice() );

if (!linger_ && (current_team().countdown_time() > 0) && saved_game_.mp_settings().mp_countdown) {
SDL_Delay(1);
const int ticks = SDL_GetTicks();
int new_time = current_team().countdown_time()-std::max<int>(1,(ticks - cur_ticks));
if (new_time > 0 ){
current_team().set_countdown_time(new_time);
cur_ticks = ticks;
if(current_team().is_local_human() && !beep_warning_time_) {
beep_warning_time_ = new_time - WARNTIME + ticks;
}
if(counting_down()) {
think_about_countdown(ticks);
}
} else {
// Clock time ended
// If no turn bonus or action bonus -> defeat
const int action_increment = saved_game_.mp_settings().mp_countdown_action_bonus;
if ( (saved_game_.mp_settings().mp_countdown_turn_bonus == 0 )
&& (action_increment == 0 || current_team().action_bonus_count() == 0)) {
// Not possible to end level in MP with throw end_level_exception(DEFEAT);
// because remote players only notice network disconnection
// Current solution end remaining turns automatically
current_team().set_countdown_time(10);
if(timer)
{
SDL_Delay(1);
bool time_left = timer->update();
if(!time_left)
{
//End the turn of there is no time left.
return boost::none;
}

return boost::none;
}
}
}
catch(...)
{
turn_data_.send_data();
Expand Down Expand Up @@ -325,9 +264,6 @@ void playmp_controller::linger()
set_completion setter(saved_game_,"running");
// End all unit moves
gamestate_.board_.set_all_units_user_end_turn();
//current_team().set_countdown_time(0);
//halt and cancel the countdown timer
reset_countdown();

set_end_scenario_button();

Expand Down Expand Up @@ -407,20 +343,20 @@ void playmp_controller::wait_for_upload()
}

void playmp_controller::after_human_turn(){
if ( saved_game_.mp_settings().mp_countdown ){
const int action_increment = saved_game_.mp_settings().mp_countdown_action_bonus;
const int maxtime = saved_game_.mp_settings().mp_countdown_reservoir_time;
int secs = (current_team().countdown_time() / 1000) + saved_game_.mp_settings().mp_countdown_turn_bonus;
secs += action_increment * current_team().action_bonus_count();
if(saved_game_.mp_settings().mp_countdown)
{
//time_left + turn_bonus + (action_bouns * number of actions done)
const int new_time_in_secs = (current_team().countdown_time() / 1000)
+ saved_game_.mp_settings().mp_countdown_turn_bonus
+ saved_game_.mp_settings().mp_countdown_action_bonus * current_team().action_bonus_count();
const int new_time = 1000 * std::min<int>(new_time_in_secs, saved_game_.mp_settings().mp_countdown_reservoir_time);

current_team().set_action_bonus_count(0);
secs = (secs > maxtime) ? maxtime : secs;
current_team().set_countdown_time(1000 * secs);
recorder.add_countdown_update(current_team().countdown_time(),player_number_);
current_team().set_countdown_time(new_time);
recorder.add_countdown_update(new_time, player_number_);
}
LOG_NG << "playmp::after_human_turn...\n";



// Normal post-processing for human turns (clear undos, end the turn, etc.)
playsingle_controller::after_human_turn();
//send one more time to make sure network is up-to-date.
Expand All @@ -430,11 +366,6 @@ void playmp_controller::after_human_turn(){

void playmp_controller::finish_side_turn(){
play_controller::finish_side_turn();


//halt and cancel the countdown timer
reset_countdown();

}

possible_end_play_signal playmp_controller::play_network_turn(){
Expand Down
7 changes: 1 addition & 6 deletions src/playmp_controller.hpp
Expand Up @@ -21,7 +21,7 @@

class turn_info;

class playmp_controller : public playsingle_controller, public events::pump_monitor, public syncmp_handler
class playmp_controller : public playsingle_controller, public syncmp_handler
{
public:
playmp_controller(const config& level, saved_game& state_of_game,
Expand All @@ -33,10 +33,6 @@ class playmp_controller : public playsingle_controller, public events::pump_moni
static unsigned int replay_last_turn() { return replay_last_turn_; }
static void set_replay_last_turn(unsigned int turn);

bool counting_down();
void reset_countdown();
void think_about_countdown(int ticks);
void process(events::pump_info &info);
void maybe_linger();
void process_oos(const std::string& err_msg) const;

Expand All @@ -63,7 +59,6 @@ class playmp_controller : public playsingle_controller, public events::pump_moni
/** Wait for the host to upload the next scenario. */
void wait_for_upload();

int beep_warning_time_;
mutable bool network_processing_stopped_;

virtual void on_not_observer();
Expand Down

0 comments on commit 781df37

Please sign in to comment.