Refactored state saving into a separate function to later allow

saving of an initial local state.
This commit is contained in:
hiker 2018-04-16 17:25:50 +10:00
parent 896b631f97
commit 3167180d7f
4 changed files with 46 additions and 29 deletions

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -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.