Buffer all inputs until last frame ticks

This commit is contained in:
Benau 2018-06-25 11:57:18 +08:00
parent d68111af51
commit bd5381dad7
6 changed files with 66 additions and 27 deletions

View File

@ -150,29 +150,43 @@ void LocalPlayerController::resetInputState()
bool LocalPlayerController::action(PlayerAction action, int value,
bool dry_run)
{
// 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;
// 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() )
{
if (auto gp = GameProtocol::lock())
{
gp->controllerAction(m_kart->getWorldKartId(), action, value,
m_steer_val_l, m_steer_val_r);
}
}
return PlayerController::action(action, value, /*dry_run*/false);
m_actions.emplace_back(action, value);
return true;
} // action
// ----------------------------------------------------------------------------
void LocalPlayerController::handleBufferedActions()
{
for (auto& p : m_actions)
{
PlayerAction action = p.first;
int value = p.second;
// 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())
{
gp->controllerAction(m_kart->getWorldKartId(), action, value,
m_steer_val_l, m_steer_val_r);
}
}
PlayerController::action(action, value, /*dry_run*/false);
}
m_actions.clear();
} // handleBufferedActions
//-----------------------------------------------------------------------------
/** Handles steering for a player kart.
*/

View File

@ -23,6 +23,9 @@
#include "karts/controller/player_controller.hpp"
#include <utility>
#include <vector>
class AbstractKart;
class ParticleEmitter;
class SFXBase;
@ -62,6 +65,9 @@ private:
virtual void steer(int, int) OVERRIDE;
virtual void displayPenaltyWarning() OVERRIDE;
void nitroNotFullSound();
std::vector<std::pair<PlayerAction, int> > m_actions;
public:
LocalPlayerController(AbstractKart *kart,
const int local_player_id,
@ -86,7 +92,8 @@ public:
// ------------------------------------------------------------------------
/** Returns the name of the player profile. */
core::stringw getName() const OVERRIDE;
// ------------------------------------------------------------------------
void handleBufferedActions();
}; // LocalPlayerController

View File

@ -247,7 +247,7 @@ void PlayerController::actionFromNetwork(PlayerAction p_action, int value,
{
m_steer_val_l = value_l;
m_steer_val_r = value_r;
action(p_action, value);
PlayerController::action(p_action, value, /*dry_run*/false);
} // actionFromNetwork
//-----------------------------------------------------------------------------

View File

@ -26,10 +26,13 @@
#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"
#include "network/network_config.hpp"
#include "network/protocols/game_protocol.hpp"
#include "network/protocol_manager.hpp"
#include "network/race_event_manager.hpp"
#include "network/rewind_manager.hpp"
@ -427,6 +430,20 @@ void MainLoop::run()
}
} // for i < num_steps
// Handle buffered player actions
if (World::getWorld())
{
for (unsigned i = 0; i < World::getWorld()->getNumKarts(); i++)
{
LocalPlayerController* lpc =
dynamic_cast<LocalPlayerController*>
(World::getWorld()->getKart(i)->getController());
if (lpc)
lpc->handleBufferedActions();
}
if (auto gp = GameProtocol::lock())
gp->sendAllActions();
}
m_is_last_substep = false;
PROFILER_POP_CPU_MARKER(); // MainLoop pop
PROFILER_SYNC_FRAME();

View File

@ -65,10 +65,10 @@ GameProtocol::~GameProtocol()
} // ~GameProtocol
//-----------------------------------------------------------------------------
/** Synchronous update - will send all commands collected during the last
/** Will send all commands collected during the last
* frame (and could optional only send messages every N frames).
*/
void GameProtocol::update(int ticks)
void GameProtocol::sendAllActions()
{
if (m_all_actions.size() == 0) return; // nothing to do
@ -90,7 +90,7 @@ void GameProtocol::update(int ticks)
// FIXME: for now send reliable
sendToServer(m_data_to_send, /*reliable*/ true);
m_all_actions.clear();
} // update
} // sendAllActions
//-----------------------------------------------------------------------------
/** Called when a message from a remote GameProtocol is received.

View File

@ -80,7 +80,8 @@ public:
virtual ~GameProtocol();
virtual bool notifyEventAsynchronous(Event* event) OVERRIDE;
virtual void update(int ticks) OVERRIDE;
virtual void update(int ticks) OVERRIDE {}
void sendAllActions();
void controllerAction(int kart_id, PlayerAction action,
int value, int val_l, int val_r);