From fb5a6007874dc058d6c5d750eaed1d34a1afad50 Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 17 May 2017 09:19:19 +1000 Subject: [PATCH] Remove 'duplicated' input events (e.g. auto-repeat might send 'accelerate' events over and over). This reduces traffic to the server and other clients (and fixed a bug caused by rewinding those events in the wrong order). --- .../controller/local_player_controller.cpp | 14 +- src/karts/controller/player_controller.cpp | 121 +++++++++++++++++- src/karts/controller/player_controller.hpp | 1 + 3 files changed, 127 insertions(+), 9 deletions(-) diff --git a/src/karts/controller/local_player_controller.cpp b/src/karts/controller/local_player_controller.cpp index 1cc3316b8..89463dd4f 100644 --- a/src/karts/controller/local_player_controller.cpp +++ b/src/karts/controller/local_player_controller.cpp @@ -142,15 +142,21 @@ void LocalPlayerController::resetInputState() */ void LocalPlayerController::action(PlayerAction action, int value) { + // 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 (!actionChangesState(action, value)) + return; + // If this is a client, send the action to networking layer if (World::getWorld()->isNetworkWorld() && NetworkConfig::get()->isClient() && !RewindManager::get()->isRewinding() ) { - GameProtocol::getInstance()->controllerAction(m_kart->getWorldKartId(), - action, value, - m_steer_val_l, - m_steer_val_r); + GameProtocol::getInstance() + ->controllerAction(m_kart->getWorldKartId(), + action, value, + m_steer_val_l, m_steer_val_r); } PlayerController::action(action, value); } // action diff --git a/src/karts/controller/player_controller.cpp b/src/karts/controller/player_controller.cpp index 75ce0babe..f0c02defc 100644 --- a/src/karts/controller/player_controller.cpp +++ b/src/karts/controller/player_controller.cpp @@ -78,6 +78,115 @@ void PlayerController::resetInputState() m_controls->reset(); } // resetInputState +// ---------------------------------------------------------------------------- +/** Returns true if the specified action and value will trigger a state + * change. If a new action from the player does not cause a state change, + * there is no need to forward that action to the server (or other clients). + * NOTE: this function must close mirror action(), make sure both functions + * are changed in synch. + * \param action The action to be executed. + * \param value If 32768, it indicates a digital value of 'fully set' + * if between 1 and 32767, it indicates an analog value, + * and if it's 0 it indicates that the corresponding button + * was released. + * \return + */ + bool PlayerController::actionChangesState(PlayerAction action, int value) +{ + switch (action) + { + case PA_STEER_LEFT: + if (m_steer_val_l != value) return true; + if (value) + { + if (m_steer_val != value) return true; + return (m_controls->getSkidControl() == KartControl::SC_NO_DIRECTION); + } + else + return m_steer_val != m_steer_val_r; + + break; + case PA_STEER_RIGHT: + if (m_steer_val_r != -value) return true; + if (value) + { + if(m_steer_val != -value) return true; + return m_controls->getSkidControl() == KartControl::SC_NO_DIRECTION; + } + else + return m_steer_val != m_steer_val_l; + + break; + case PA_ACCEL: + if (m_prev_accel != value) return true; + if (value && !(m_penalty_time > 0.0f)) + { + if (m_controls->getAccel() != value / 32768.f) return true; + if (m_controls->getBrake()) return true; + return m_controls->getNitro() != m_prev_nitro; + } + else + { + if (m_controls->getAccel() != 0 ) return true; + if (m_controls->getBrake() != m_prev_brake) return true; + return m_controls->getNitro(); + } + break; + case PA_BRAKE: + if (m_prev_brake != (value != 0) ) return true; + // let's consider below that to be a deadzone + if (value > 32768 / 2) + { + if (!m_controls->getBrake() ) return true; + if (m_controls->getAccel() != 0) return true; + return m_controls->getNitro(); + } + else + { + if (m_controls->getBrake() ) return true; + if (m_controls->getAccel() != m_prev_accel/32768.0f) return true; + // Nitro still depends on whether we're accelerating + return m_controls->getNitro() != m_prev_nitro && m_prev_accel; + } + break; + case PA_NITRO: + // This basically keeps track whether the button still is being pressed + if (m_prev_nitro != (value != 0)) return true; + // Enable nitro only when also accelerating + return m_controls->getNitro() != ( (value != 0) && + m_controls->getAccel() ); + break; + case PA_RESCUE: + return m_controls->getRescue() != (value != 0); + break; + case PA_FIRE: + return m_controls->getFire() != (value != 0); + break; + case PA_LOOK_BACK: + return m_controls->getLookBack() != (value != 0); + break; + case PA_DRIFT: + if (value == 0) + return m_controls->getSkidControl() != KartControl::SC_NONE; + else + { + if (m_steer_val == 0) + return m_controls->getSkidControl() != KartControl::SC_NO_DIRECTION; + else + return m_controls->getSkidControl() != (m_steer_val<0 + ? KartControl::SC_RIGHT + : KartControl::SC_LEFT ); + } + break; + case PA_PAUSE_RACE: + if (value != 0) StateManager::get()->escapePressed(); + break; + default: + break; + } + return true; +} // actionChangesState + // ---------------------------------------------------------------------------- /** This function interprets a kart action and value, and set the corresponding * entries in the kart control data structure. This function handles esp. @@ -85,11 +194,13 @@ void PlayerController::resetInputState() * releasing right, the steering must switch to left again. Similarly it * handles 'press left, press right, release left' (in which case still * right must be selected). Similarly for braking and acceleration. - * \param action The action to be executed. - * \param value If 32768, it indicates a digital value of 'fully set' - * if between 1 and 32767, it indicates an analog value, - * and if it's 0 it indicates that the corresponding button - * was released. + * NOTE: this function must close mirror action(), make sure both functions + * are changed in synch. + * \param action The action to be executed. + * \param value If 32768, it indicates a digital value of 'fully set' + * if between 1 and 32767, it indicates an analog value, + * and if it's 0 it indicates that the corresponding button + * was released. */ void PlayerController::action(PlayerAction action, int value) { diff --git a/src/karts/controller/player_controller.hpp b/src/karts/controller/player_controller.hpp index 024738854..7bc6950f0 100644 --- a/src/karts/controller/player_controller.hpp +++ b/src/karts/controller/player_controller.hpp @@ -45,6 +45,7 @@ public: virtual ~PlayerController (); virtual void update (float) OVERRIDE; virtual void action (PlayerAction action, int value) OVERRIDE; + virtual bool actionChangesState(PlayerAction action, int value); virtual void actionFromNetwork(PlayerAction action, int value, int value_l, int value_r); virtual void skidBonusTriggered() OVERRIDE;