diff --git a/src/karts/controller/ai_base_controller.cpp b/src/karts/controller/ai_base_controller.cpp index c4a42e2c7..9439bd161 100644 --- a/src/karts/controller/ai_base_controller.cpp +++ b/src/karts/controller/ai_base_controller.cpp @@ -335,7 +335,7 @@ void AIBaseController::saveState(BareNetworkString *buffer) const { // Endcontroller needs this for proper offset in kart rewinder // Must match the number of bytes in Playercontroller. - buffer->addUInt32(0).addUInt32(0).addUInt32(0).addUInt8(0).addUInt32(0); + buffer->addUInt32(0).addUInt32(0).addUInt8(0); } // copyToBuffer //----------------------------------------------------------------------------- @@ -343,5 +343,5 @@ void AIBaseController::rewindTo(BareNetworkString *buffer) { // Endcontroller needs this for proper offset in kart rewinder. // Skip the same number of bytes as PlayerController. - buffer->skip(4 * 4 + 1); + buffer->skip(4 * 2 + 1); } // rewindTo diff --git a/src/karts/controller/ai_base_controller.hpp b/src/karts/controller/ai_base_controller.hpp index c2431da71..0c0f2e8a2 100644 --- a/src/karts/controller/ai_base_controller.hpp +++ b/src/karts/controller/ai_base_controller.hpp @@ -65,7 +65,7 @@ protected: * for AI testing only. */ static int m_test_ai; - void setControllerName(const std::string &name); + void setControllerName(const std::string &name) OVERRIDE; float steerToPoint(const Vec3 &point); float normalizeAngle(float angle); // ------------------------------------------------------------------------ @@ -75,7 +75,7 @@ protected: // ------------------------------------------------------------------------ void determineTurnRadius(const Vec3 &end, Vec3 *center, float *radius) const; - virtual void update(int ticks); + virtual void update(int ticks) OVERRIDE; virtual void setSteering (float angle, float dt); // ------------------------------------------------------------------------ /** Return true if AI can skid now. */ @@ -84,7 +84,7 @@ protected: public: AIBaseController(AbstractKart *kart); virtual ~AIBaseController() {}; - virtual void reset(); + virtual void reset() OVERRIDE; virtual bool disableSlipstreamBonus() const OVERRIDE; virtual void crashed(const Material *m) OVERRIDE; static void enableDebug() {m_ai_debug = true; } @@ -98,11 +98,11 @@ public: virtual void setPosition(int p) OVERRIDE {}; virtual bool isPlayerController() const OVERRIDE { return false; } virtual bool isLocalPlayerController() const OVERRIDE { return false; } - virtual bool action(PlayerAction action, int value, bool dry_run=false) OVERRIDE + virtual bool action(PlayerAction action, int value, bool dry_run=false) OVERRIDE { return true; }; - virtual void skidBonusTriggered() {}; + virtual void skidBonusTriggered() OVERRIDE {} // ------------------------------------------------------------------------ virtual void saveState(BareNetworkString *buffer) const OVERRIDE; virtual void rewindTo(BareNetworkString *buffer) OVERRIDE; diff --git a/src/karts/controller/end_controller.cpp b/src/karts/controller/end_controller.cpp index e7cc77539..6d8a0b2fc 100644 --- a/src/karts/controller/end_controller.cpp +++ b/src/karts/controller/end_controller.cpp @@ -163,12 +163,14 @@ void EndController::newLap(int lap) //----------------------------------------------------------------------------- /** The end controller must forward 'fire' presses to the race gui. */ -void EndController::action(PlayerAction action, int value) +bool EndController::action(PlayerAction action, int value, bool dry_run) { - if(action!=PA_FIRE) return; - RaceResultGUI *race_result_gui = dynamic_cast(World::getWorld()->getRaceGUI()); - if(!race_result_gui) return; + if(action!=PA_FIRE) return true; + RaceResultGUI *race_result_gui = + dynamic_cast(World::getWorld()->getRaceGUI()); + if(!race_result_gui) return true; race_result_gui->nextPhase(); + return true; } // action //----------------------------------------------------------------------------- diff --git a/src/karts/controller/end_controller.hpp b/src/karts/controller/end_controller.hpp index 7790175ff..66a65b9ee 100644 --- a/src/karts/controller/end_controller.hpp +++ b/src/karts/controller/end_controller.hpp @@ -86,7 +86,8 @@ public: ~EndController(); virtual void update (int ticks) ; virtual void reset (); - virtual void action (PlayerAction action, int value); + virtual bool action (PlayerAction action, int value, + bool dry_run = false); virtual void newLap (int lap); // ------------------------------------------------------------------------ virtual bool canGetAchievements() const diff --git a/src/karts/controller/ghost_controller.hpp b/src/karts/controller/ghost_controller.hpp index 1ca16d032..bad39f0d9 100644 --- a/src/karts/controller/ghost_controller.hpp +++ b/src/karts/controller/ghost_controller.hpp @@ -62,8 +62,8 @@ public: bool dry_run=false) OVERRIDE; virtual void skidBonusTriggered() OVERRIDE {} virtual void newLap(int lap) OVERRIDE {} - virtual void saveState(BareNetworkString *buffer) const {}; - virtual void rewindTo(BareNetworkString *buffer) {}; + virtual void saveState(BareNetworkString *buffer) const OVERRIDE {} + virtual void rewindTo(BareNetworkString *buffer) OVERRIDE {} void addReplayTime(float time); // ------------------------------------------------------------------------ diff --git a/src/karts/controller/local_player_controller.cpp b/src/karts/controller/local_player_controller.cpp index 9dfcbdea9..8e38816aa 100644 --- a/src/karts/controller/local_player_controller.cpp +++ b/src/karts/controller/local_player_controller.cpp @@ -39,6 +39,7 @@ #include "modes/world.hpp" #include "network/network_config.hpp" #include "network/protocols/game_protocol.hpp" +#include "network/rewind_manager.hpp" #include "race/history.hpp" #include "states_screens/race_gui_base.hpp" #include "tracks/track.hpp" @@ -114,7 +115,6 @@ LocalPlayerController::~LocalPlayerController() */ void LocalPlayerController::reset() { - m_actions.fill(0); PlayerController::reset(); m_sound_schedule = false; } // reset @@ -150,58 +150,35 @@ void LocalPlayerController::resetInputState() bool LocalPlayerController::action(PlayerAction action, int value, bool dry_run) { + // Pause race doesn't need to be sent to server if (action == PA_PAUSE_RACE) { PlayerController::action(action, value); return true; } - m_actions[action] = value; - return true; -} // action -// ---------------------------------------------------------------------------- -void LocalPlayerController::handleBufferedActions(double time_spent) -{ - if (!isLocalPlayerController()) - return; + // If this event does not change the control state (e.g. + // it's a (auto) repeat event), do nothing. This especially + // optimises traffic to the server and other clients. + if (!PlayerController::action(action, value, /*dry_run*/true)) return false; - // There is 0.1 delay in server, if time_spent is more than ~0.1, than - // the timer will be incorrect, in this case ignore all actions - if (time_spent > 0.09 && NetworkConfig::get()->isNetworking()) + // Register event with history + if(!history->replayHistory()) + history->addEvent(m_kart->getWorldKartId(), action, value); + + // If this is a client, send the action to networking layer + if (World::getWorld()->isNetworkWorld() && + NetworkConfig::get()->isClient() && + !RewindManager::get()->isRewinding()) { - Log::warn("LocalPlayerController", "Update race is too slow to catch" - " up: %lf", time_spent); - return; - } - - for (int i = 0; i < PA_PAUSE_RACE; i++) - { - PlayerAction action = (PlayerAction)i; - int value = m_actions[i]; - - // If this event does not change the control state (e.g. - // it's a (auto) repeat event), do nothing. This especially - // optimises traffic to the server and other clients. - if (!PlayerController::action(action, value, /*dry_run*/true)) - continue; - - // Register event with history - if(!history->replayHistory()) - history->addEvent(m_kart->getWorldKartId(), action, value); - - // If this is a client, send the action to networking layer - if (World::getWorld()->isNetworkWorld() && - NetworkConfig::get()->isClient()) + if (auto gp = GameProtocol::lock()) { - if (auto gp = GameProtocol::lock()) - { - gp->controllerAction(m_kart->getWorldKartId(), action, value, - m_steer_val_l, m_steer_val_r); - } + gp->controllerAction(m_kart->getWorldKartId(), action, value, + m_steer_val_l, m_steer_val_r); } - PlayerController::action(action, value, /*dry_run*/false); } -} // handleBufferedActions + return PlayerController::action(action, value, /*dry_run*/false); +} // action //----------------------------------------------------------------------------- /** Handles steering for a player kart. diff --git a/src/karts/controller/local_player_controller.hpp b/src/karts/controller/local_player_controller.hpp index b675b011e..90f992bea 100644 --- a/src/karts/controller/local_player_controller.hpp +++ b/src/karts/controller/local_player_controller.hpp @@ -23,8 +23,6 @@ #include "karts/controller/player_controller.hpp" -#include - class AbstractKart; class ParticleEmitter; class SFXBase; @@ -65,8 +63,6 @@ private: virtual void displayPenaltyWarning() OVERRIDE; void nitroNotFullSound(); - std::array m_actions; - public: LocalPlayerController(AbstractKart *kart, const int local_player_id, @@ -91,8 +87,6 @@ public: // ------------------------------------------------------------------------ /** Returns the name of the player profile. */ core::stringw getName() const OVERRIDE; - // ------------------------------------------------------------------------ - void handleBufferedActions(double time_spent); }; // LocalPlayerController diff --git a/src/karts/controller/player_controller.cpp b/src/karts/controller/player_controller.cpp index de790d331..6de9e3d07 100644 --- a/src/karts/controller/player_controller.cpp +++ b/src/karts/controller/player_controller.cpp @@ -388,9 +388,8 @@ void PlayerController::saveState(BareNetworkString *buffer) const { // NOTE: when the size changes, the AIBaseController::saveState and // restore state MUST be adjusted!! - buffer->addUInt32(m_steer_val).addUInt32(m_steer_val_l) - .addUInt32(m_steer_val_r).addUInt8(m_prev_brake) - .addUInt32(m_prev_accel); + buffer->addUInt32(m_steer_val).addUInt32(m_prev_accel) + .addUInt8(m_prev_brake); } // copyToBuffer //----------------------------------------------------------------------------- @@ -398,11 +397,9 @@ void PlayerController::rewindTo(BareNetworkString *buffer) { // NOTE: when the size changes, the AIBaseController::saveState and // restore state MUST be adjusted!! - m_steer_val = buffer->getUInt32(); - m_steer_val_l = buffer->getUInt32(); - m_steer_val_r = buffer->getUInt32(); - m_prev_brake = buffer->getUInt8(); - m_prev_accel = buffer->getUInt32(); + m_steer_val = buffer->getUInt32(); + m_prev_accel = buffer->getUInt32(); + m_prev_brake = buffer->getUInt8(); } // rewindTo // ---------------------------------------------------------------------------- diff --git a/src/karts/controller/player_controller.hpp b/src/karts/controller/player_controller.hpp index 1f082f702..0a50233f4 100644 --- a/src/karts/controller/player_controller.hpp +++ b/src/karts/controller/player_controller.hpp @@ -26,6 +26,7 @@ class Player; class PlayerController : public Controller { +friend class KartRewinder; protected: int m_steer_val, m_steer_val_l, m_steer_val_r; int m_prev_accel; diff --git a/src/karts/kart_rewinder.cpp b/src/karts/kart_rewinder.cpp index cfe038f50..83e8edf0c 100644 --- a/src/karts/kart_rewinder.cpp +++ b/src/karts/kart_rewinder.cpp @@ -21,7 +21,7 @@ #include "items/attachment.hpp" #include "items/powerup.hpp" #include "karts/abstract_kart.hpp" -#include "karts/controller/controller.hpp" +#include "karts/controller/player_controller.hpp" #include "karts/kart_properties.hpp" #include "karts/max_speed.hpp" #include "karts/skidding.hpp" @@ -121,7 +121,6 @@ BareNetworkString* KartRewinder::saveState(std::vector* ru) buffer->add(q); buffer->add(body->getLinearVelocity()); buffer->add(body->getAngularVelocity()); - buffer->addUInt8(m_has_started); // necessary for startup speed boost buffer->addFloat(m_vehicle->getMinSpeed()); buffer->addFloat(m_vehicle->getTimedRotationTime()); buffer->add(m_vehicle->getTimedRotation()); @@ -130,13 +129,12 @@ BareNetworkString* KartRewinder::saveState(std::vector* ru) // ------------------------------------- getControls().saveState(buffer); getController()->saveState(buffer); - buffer->addTime(m_brake_ticks); // 3) Attachment, powerup, nitro // ----------------------------- getAttachment()->saveState(buffer); getPowerup()->saveState(buffer); - buffer->addUInt8(m_min_nitro_ticks).addFloat(getEnergy()); + buffer->addFloat(getEnergy()); // 4) Max speed info // ------------------ @@ -179,7 +177,6 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count) setTrans(t); } - m_has_started = buffer->getUInt8()!=0; // necessary for startup speed boost m_vehicle->setMinSpeed(buffer->getFloat()); float time_rot = buffer->getFloat(); // Set timed rotation divides by time_rot @@ -195,7 +192,6 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count) // ------------------------------ getControls().rewindTo(buffer); getController()->rewindTo(buffer); - m_brake_ticks = buffer->getTime(); // 3) Attachment, powerup, nitro // ------------------------------ @@ -204,7 +200,6 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count) updateWeight(); getPowerup()->rewindTo(buffer); - m_min_nitro_ticks = buffer->getUInt8(); float nitro = buffer->getFloat(); setEnergy(nitro); @@ -240,27 +235,51 @@ std::function KartRewinder::getLocalStateRestoreFunction() return nullptr; // In theory all ticks / boolean related stuff can be saved locally + bool has_started = m_has_started; int bubblegum_ticks = m_bubblegum_ticks; int bounce_back_ticks = m_bounce_back_ticks; int invulnerable_ticks = m_invulnerable_ticks; int squash_ticks = m_squash_ticks; bool fire_clicked = m_fire_clicked; int view_blocked_by_plunger = m_view_blocked_by_plunger; + int brake_ticks = m_brake_ticks; + int8_t min_nitro_ticks = m_min_nitro_ticks; // Attachment local state float initial_speed = getAttachment()->getInitialSpeed(); float node_scale = getAttachment()->getNodeScale(); - return [bubblegum_ticks, bounce_back_ticks, invulnerable_ticks, squash_ticks, - fire_clicked, view_blocked_by_plunger, initial_speed, - node_scale, this]() + + // Controller local state + int steer_val_l = 0; + int steer_val_r = 0; + PlayerController* pc = dynamic_cast(m_controller); + if (pc) { + steer_val_l = pc->m_steer_val_l; + steer_val_r = pc->m_steer_val_r; + } + + return [has_started, bubblegum_ticks, bounce_back_ticks, + invulnerable_ticks, squash_ticks, fire_clicked, + view_blocked_by_plunger, brake_ticks, min_nitro_ticks, initial_speed, + node_scale, steer_val_l, steer_val_r, this]() + { + m_has_started = has_started; m_bubblegum_ticks = bubblegum_ticks; m_bounce_back_ticks = bounce_back_ticks; m_invulnerable_ticks = invulnerable_ticks; m_squash_ticks = squash_ticks; m_fire_clicked = fire_clicked; m_view_blocked_by_plunger = view_blocked_by_plunger; + m_brake_ticks = brake_ticks; + m_min_nitro_ticks = min_nitro_ticks; getAttachment()->setInitialSpeed(initial_speed); getAttachment()->setNodeScale(node_scale); + PlayerController* pc = dynamic_cast(m_controller); + if (pc) + { + pc->m_steer_val_l = steer_val_l; + pc->m_steer_val_r = steer_val_r; + } }; } // getLocalStateRestoreFunction diff --git a/src/main_loop.cpp b/src/main_loop.cpp index 2963f6766..fa32e09c0 100644 --- a/src/main_loop.cpp +++ b/src/main_loop.cpp @@ -26,8 +26,6 @@ #include "guiengine/engine.hpp" #include "guiengine/message_queue.hpp" #include "guiengine/modaldialog.hpp" -#include "karts/controller/local_player_controller.hpp" -#include "karts/abstract_kart.hpp" #include "input/input_manager.hpp" #include "modes/profile_world.hpp" #include "modes/world.hpp" @@ -410,8 +408,7 @@ void MainLoop::run() } m_ticks_adjustment.unlock(); - double time_spent = StkTime::getRealTime(); - for(int i = 0; i < num_steps; i++) + for (int i = 0; i < num_steps; i++) { PROFILER_PUSH_CPU_MARKER("Protocol manager update", 0x7F, 0x00, 0x7F); @@ -432,7 +429,6 @@ void MainLoop::run() if (m_frame_before_loading_world) { - time_spent = StkTime::getRealTime(); m_frame_before_loading_world = false; break; } @@ -447,22 +443,6 @@ void MainLoop::run() World::getWorld()->updateTime(1); } } // for i < num_steps - - time_spent = StkTime::getRealTime() - time_spent; - // Handle buffered player actions - if (World::getWorld()) - { - for (unsigned i = 0; i < World::getWorld()->getNumKarts(); i++) - { - LocalPlayerController* lpc = - dynamic_cast - (World::getWorld()->getKart(i)->getController()); - if (lpc) - lpc->handleBufferedActions(time_spent); - } - if (auto gp = GameProtocol::lock()) - gp->sendAllActions(); - } PROFILER_POP_CPU_MARKER(); // MainLoop pop PROFILER_SYNC_FRAME(); } // while !m_abort diff --git a/src/network/protocols/game_protocol.cpp b/src/network/protocols/game_protocol.cpp index fcd1377e7..4d153b341 100644 --- a/src/network/protocols/game_protocol.cpp +++ b/src/network/protocols/game_protocol.cpp @@ -66,10 +66,10 @@ GameProtocol::~GameProtocol() } // ~GameProtocol //----------------------------------------------------------------------------- -/** Will send all commands collected during the last +/** Synchronous update - will send all commands collected during the last * frame (and could optional only send messages every N frames). */ -void GameProtocol::sendAllActions() +void GameProtocol::update(int ticks) { if (m_all_actions.size() == 0) return; // nothing to do @@ -91,7 +91,7 @@ void GameProtocol::sendAllActions() // FIXME: for now send reliable sendToServer(m_data_to_send, /*reliable*/ true); m_all_actions.clear(); -} // sendAllActions +} // update //----------------------------------------------------------------------------- /** Called when a message from a remote GameProtocol is received. diff --git a/src/network/protocols/game_protocol.hpp b/src/network/protocols/game_protocol.hpp index 86bb93397..1d2ca11e1 100644 --- a/src/network/protocols/game_protocol.hpp +++ b/src/network/protocols/game_protocol.hpp @@ -81,8 +81,7 @@ public: virtual ~GameProtocol(); virtual bool notifyEventAsynchronous(Event* event) OVERRIDE; - virtual void update(int ticks) OVERRIDE {} - void sendAllActions(); + virtual void update(int ticks) OVERRIDE; void controllerAction(int kart_id, PlayerAction action, int value, int val_l, int val_r);