From 3167180d7fca4e2ae2c7937c4f7ecc1b8a8d05da Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 16 Apr 2018 17:25:50 +1000 Subject: [PATCH] Refactored state saving into a separate function to later allow saving of an initial local state. --- src/network/protocols/game_protocol.cpp | 16 +++++--- src/network/protocols/game_protocol.hpp | 4 +- src/network/rewind_manager.cpp | 54 +++++++++++++++---------- src/network/rewind_manager.hpp | 1 + 4 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/network/protocols/game_protocol.cpp b/src/network/protocols/game_protocol.cpp index 953cc4bde..6f709ac3e 100644 --- a/src/network/protocols/game_protocol.cpp +++ b/src/network/protocols/game_protocol.cpp @@ -245,13 +245,17 @@ void GameProtocol::handleAdjustTime(Event *event) // ---------------------------------------------------------------------------- /** Called by the server before assembling a new message containing the full * state of the race to be sent to a client. + * \param allow_local_save If set it allows a state to be saved on a client. + * This only happens at the very first time step to ensure each client + * has a state in case it receives an event before a server state. */ -void GameProtocol::startNewState() +void GameProtocol::startNewState(bool allow_local_save) { - assert(NetworkConfig::get()->isServer()); + assert(allow_local_save || NetworkConfig::get()->isServer()); + m_data_to_send->clear(); m_data_to_send->addUInt8(GP_STATE).addUInt32(World::getWorld()->getTimeTicks()); - Log::info("GameProtocol", "Sending new state at %d.", + Log::info("GameProtocol", "Starting new state at %d.", World::getWorld()->getTimeTicks()); } // startNewState @@ -260,9 +264,9 @@ void GameProtocol::startNewState() * is copied, so the data can be freed after this call/. * \param buffer Adds the data in the buffer to the current state. */ -void GameProtocol::addState(BareNetworkString *buffer) +void GameProtocol::addState(bool allow_local_save, BareNetworkString *buffer) { - assert(NetworkConfig::get()->isServer()); + assert(allow_local_save || NetworkConfig::get()->isServer()); m_data_to_send->addUInt16(buffer->size()); (*m_data_to_send) += *buffer; } // addState @@ -273,6 +277,8 @@ void GameProtocol::addState(BareNetworkString *buffer) */ void GameProtocol::sendState() { + Log::info("GameProtocol", "Sending new state at %d.", + World::getWorld()->getTimeTicks()); assert(NetworkConfig::get()->isServer()); sendMessageToPeersChangingToken(m_data_to_send, /*reliable*/true); } // sendState diff --git a/src/network/protocols/game_protocol.hpp b/src/network/protocols/game_protocol.hpp index ad40535e6..a821597c7 100644 --- a/src/network/protocols/game_protocol.hpp +++ b/src/network/protocols/game_protocol.hpp @@ -78,8 +78,8 @@ public: void controllerAction(int kart_id, PlayerAction action, int value, int val_l, int val_r); - void startNewState(); - void addState(BareNetworkString *buffer); + void startNewState(bool allow_local_save); + void addState(bool allow_local_save, BareNetworkString *buffer); void sendState(); void adjustTimeForClient(STKPeer *peer, int ticks); diff --git a/src/network/rewind_manager.cpp b/src/network/rewind_manager.cpp index ac354fb95..5ba8a0c8e 100755 --- a/src/network/rewind_manager.cpp +++ b/src/network/rewind_manager.cpp @@ -158,16 +158,43 @@ void RewindManager::addNetworkEvent(EventRewinder *event_rewinder, * \param time Time at which the event was recorded. * \param buffer Pointer to the event data. */ -void RewindManager::addNetworkState(int rewinder_index, BareNetworkString *buffer, - int ticks) +void RewindManager::addNetworkState(int rewinder_index, + BareNetworkString *buffer, int ticks) { assert(NetworkConfig::get()->isClient()); - // On a client dt from a state is never used, it maintains - // its own dt information (using TimeEvents). m_rewind_queue.addNetworkState(m_all_rewinder[rewinder_index], buffer, ticks); } // addNetworkState +// ---------------------------------------------------------------------------- +/** Saves a local state using the GameProtocol function to combine several + * independent rewinders to write one state. Typically only the server needs + * to save a state (which is then send to the clients), except that each + * client needs one initial state (in case that it receives an event from + * a client before a state from the serer). + * \param allow_local_save Do a local save. + */ +void RewindManager::saveState(bool allow_local_save) +{ + PROFILER_PUSH_CPU_MARKER("RewindManager - save state", 0x20, 0x7F, 0x20); + GameProtocol::lock()->startNewState(allow_local_save); + AllRewinder::const_iterator rewinder; + for (rewinder = m_all_rewinder.begin(); rewinder != m_all_rewinder.end(); ++rewinder) + { + // TODO: check if it's worth passing in a sufficiently large buffer from + // GameProtocol - this would save the copy operation. + BareNetworkString *buffer = (*rewinder)->saveState(); + if (buffer && buffer->size() >= 0) + { + m_overall_state_size += buffer->size(); + GameProtocol::lock()->addState(allow_local_save, buffer); + } // size >= 0 + delete buffer; // buffer can be freed + } + PROFILER_POP_CPU_MARKER(); + +} // saveState + // ---------------------------------------------------------------------------- /** Determines if a new state snapshot should be taken, and if so calls all * rewinder to do so. @@ -192,31 +219,14 @@ void RewindManager::update(int ticks_not_used) return; } - // Save state - PROFILER_PUSH_CPU_MARKER("RewindManager - save state", 0x20, 0x7F, 0x20); - GameProtocol::lock()->startNewState(); - AllRewinder::const_iterator rewinder; - for (rewinder = m_all_rewinder.begin(); rewinder != m_all_rewinder.end(); ++rewinder) - { - // TODO: check if it's worth passing in a sufficiently large buffer from - // GameProtocol - this would save the copy operation. - BareNetworkString *buffer = (*rewinder)->saveState(); - if (buffer && buffer->size() >= 0) - { - m_overall_state_size += buffer->size(); - GameProtocol::lock()->addState(buffer); - } // size >= 0 - delete buffer; // buffer can be freed - } - PROFILER_POP_CPU_MARKER(); + saveState(/**allow_local_save*/false); PROFILER_PUSH_CPU_MARKER("RewindManager - send state", 0x20, 0x7F, 0x40); GameProtocol::lock()->sendState(); PROFILER_POP_CPU_MARKER(); m_last_saved_state = ticks; } // update -#include "karts/abstract_kart.hpp" // ---------------------------------------------------------------------------- /** Replays all events from the last event played till the specified time. * \param world_ticks Up to (and inclusive) which time events will be replayed. diff --git a/src/network/rewind_manager.hpp b/src/network/rewind_manager.hpp index d5fdce6be..a8fecaf6d 100644 --- a/src/network/rewind_manager.hpp +++ b/src/network/rewind_manager.hpp @@ -147,6 +147,7 @@ public: void addNetworkState(int rewinder_index, BareNetworkString *buffer, int ticks); void addNextTimeStep(int ticks, float dt); + void saveState(bool allow_local_save); // ------------------------------------------------------------------------ /** Adds a Rewinder to the list of all rewinders. * \return true If rewinding is enabled, false otherwise.