Don't split a game state upon receiving into separate chunks (one

for each rewinder), instead save only one state with all rewind
buffers.
This commit is contained in:
hiker
2018-04-17 09:17:02 +10:00
parent 3167180d7f
commit 70e7625282
8 changed files with 69 additions and 82 deletions

View File

@@ -127,8 +127,6 @@ BareNetworkString* KartRewinder::saveState() const
/** Actually rewind to the specified state. */
void KartRewinder::rewindToState(BareNetworkString *buffer)
{
buffer->reset(); // make sure the buffer is read from the beginning
// 1) Physics values: transform and velocities
// -------------------------------------------
btTransform t;

View File

@@ -293,20 +293,19 @@ void GameProtocol::handleState(Event *event)
return;
assert(NetworkConfig::get()->isClient());
NetworkString &data = event->data();
int ticks = data.getUInt32();
const NetworkString &data = event->data();
int ticks = data.getUInt32();
// Now copy the state data (without ticks etc) to a new
// string, so it can be reset to the beginning easily
// when restoring the state:
BareNetworkString *bns = new BareNetworkString(data.getCurrentData(),
data.size());
// The memory for bns will be handled in the RewindInfoState object
RewindManager::get()->addNetworkState(bns, ticks);
Log::info("GameProtocol", "Received at %d state from %d",
World::getWorld()->getTimeTicks(), ticks);
int index = 0;
while (data.size() > 0)
{
uint16_t count = data.getUInt16();
BareNetworkString *state = new BareNetworkString(data.getCurrentData(),
count);
data.skip(count);
RewindManager::get()->addNetworkState(index, state, ticks);
index++;
} // while data.size()>0
} // handleState
// ----------------------------------------------------------------------------

View File

@@ -19,6 +19,7 @@
#include "network/rewind_info.hpp"
#include "network/network_config.hpp"
#include "network/rewind_manager.hpp"
#include "physics/physics.hpp"
/** Constructor for a state: it only takes the size, and allocates a buffer
@@ -44,12 +45,23 @@ void RewindInfo::setTicks(int ticks)
} // setTicks
// ============================================================================
RewindInfoState::RewindInfoState(int ticks, Rewinder *rewinder,
BareNetworkString *buffer, bool is_confirmed)
: RewindInfoRewinder(ticks, rewinder, buffer, is_confirmed)
RewindInfoState::RewindInfoState(int ticks, BareNetworkString *buffer,
bool is_confirmed)
: RewindInfo(ticks, is_confirmed)
{
m_buffer = buffer;
} // RewindInfoState
// ------------------------------------------------------------------------
/** Rewinds to this state. This is called while going forwards in time
* again to reach current time. It will call rewindToState().
* if the state is a confirmed state.
*/
void RewindInfoState::rewind()
{
RewindManager::get()->restoreState(m_buffer);
} // rewind
// ============================================================================
RewindInfoEvent::RewindInfoEvent(int ticks, EventRewinder *event_rewinder,
BareNetworkString *buffer, bool is_confirmed)

View File

@@ -84,45 +84,22 @@ public:
}; // RewindInfo
// ============================================================================
/** A rewind info abstract class that keeps track of a rewinder object, and
* has a BareNetworkString buffer which is used to store a state or event.
/** A class that stores a game state and can rewind it.
*/
class RewindInfoRewinder : public RewindInfo
class RewindInfoState: public RewindInfo
{
private:
/** Pointer to the buffer which stores all states. */
BareNetworkString *m_buffer;
protected:
/** The Rewinder instance for which this data is. */
Rewinder *m_rewinder;
public:
RewindInfoRewinder(int ticks, Rewinder *rewinder,
BareNetworkString *buffer, bool is_confirmed)
: RewindInfo(ticks, is_confirmed)
{
m_rewinder = rewinder;
m_buffer = buffer;
} // RewindInfoRewinder
// ------------------------------------------------------------------------
virtual ~RewindInfoRewinder()
{
delete m_buffer;
} // ~RewindInfoRewinder
RewindInfoState(int ticks, BareNetworkString *buffer,
bool is_confirmed);
virtual ~RewindInfoState() {};
virtual void rewind();
// ------------------------------------------------------------------------
/** Returns a pointer to the state buffer. */
BareNetworkString *getBuffer() const { return m_buffer; }
}; // RewindInfoRewinder
// ============================================================================
class RewindInfoState: public RewindInfoRewinder
{
public:
RewindInfoState(int ticks, Rewinder *rewinder,
BareNetworkString *buffer, bool is_confirmed);
virtual ~RewindInfoState() {};
// ------------------------------------------------------------------------
virtual bool isState() const { return true; }
// ------------------------------------------------------------------------
@@ -130,23 +107,8 @@ public:
* It calls undoState in the rewinder. */
virtual void undo()
{
if(m_rewinder) // Unit testing uses NULL as rewinder
m_rewinder->undoState(getBuffer());
// Nothing being done in case of an undo that goes further back
} // undo
// ------------------------------------------------------------------------
/** Rewinds to this state. This is called while going forwards in time
* again to reach current time. It will call rewindToState().
* if the state is a confirmed state. */
virtual void rewind()
{
if (isConfirmed())
m_rewinder->rewindToState(getBuffer());
else
{
// TODO
// Handle replacing of stored states.
}
} // rewind
}; // class RewindInfoState
// ============================================================================

View File

@@ -158,12 +158,10 @@ 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(BareNetworkString *buffer, int ticks)
{
assert(NetworkConfig::get()->isClient());
m_rewind_queue.addNetworkState(m_all_rewinder[rewinder_index], buffer,
ticks);
m_rewind_queue.addNetworkState(buffer, ticks);
} // addNetworkState
// ----------------------------------------------------------------------------
@@ -195,6 +193,28 @@ void RewindManager::saveState(bool allow_local_save)
} // saveState
// ----------------------------------------------------------------------------
/** Restores a given state by calling rewindToState for each available rewinder
* with its correct data.
* \param data The data string used to store the whole game state.
*
*/
void RewindManager::restoreState(BareNetworkString *data)
{
data->reset();
int index = 0;
//AllRewinder::const_iterator rewinder;
for (auto rewinder = m_all_rewinder.begin(); rewinder != m_all_rewinder.end();
++rewinder)
{
uint16_t count = data->getUInt16();
if (count > 0)
{
(*rewinder)->rewindToState(data);
}
} // for all rewinder
} // restoreState
// ----------------------------------------------------------------------------
/** Determines if a new state snapshot should be taken, and if so calls all
* rewinder to do so.

View File

@@ -144,10 +144,10 @@ public:
bool confirmed, int ticks = -1);
void addNetworkEvent(EventRewinder *event_rewinder,
BareNetworkString *buffer, int ticks);
void addNetworkState(int rewinder_index, BareNetworkString *buffer,
int ticks);
void addNetworkState(BareNetworkString *buffer, int ticks);
void addNextTimeStep(int ticks, float dt);
void saveState(bool allow_local_save);
void restoreState(BareNetworkString *buffer);
// ------------------------------------------------------------------------
/** Adds a Rewinder to the list of all rewinders.
* \return true If rewinding is enabled, false otherwise.

View File

@@ -135,10 +135,10 @@ void RewindQueue::addLocalEvent(EventRewinder *event_rewinder,
* faster rewinds.
* \param ticks Time at which the event happened.
*/
void RewindQueue::addLocalState(Rewinder *rewinder, BareNetworkString *buffer,
void RewindQueue::addLocalState(BareNetworkString *buffer,
bool confirmed, int ticks)
{
RewindInfo *ri = new RewindInfoState(ticks, rewinder, buffer, confirmed);
RewindInfo *ri = new RewindInfoState(ticks, buffer, confirmed);
assert(ri);
insertRewindInfo(ri);
} // addLocalState
@@ -170,11 +170,9 @@ void RewindQueue::addNetworkEvent(EventRewinder *event_rewinder,
* \param buffer Pointer to the event data.
* \param ticks Time at which the event happened.
*/
void RewindQueue::addNetworkState(Rewinder *rewinder, BareNetworkString *buffer,
int ticks)
void RewindQueue::addNetworkState(BareNetworkString *buffer, int ticks)
{
RewindInfo *ri = new RewindInfoState(ticks, rewinder,
buffer, /*confirmed*/true);
RewindInfo *ri = new RewindInfoState(ticks, buffer, /*confirmed*/true);
m_network_events.lock();
m_network_events.getData().push_back(ri);
@@ -356,7 +354,7 @@ void RewindQueue::unitTesting()
assert(q0.isEmpty());
assert(!q0.hasMoreRewindInfo());
q0.addLocalState(NULL, NULL, /*confirmed*/true, 0);
q0.addLocalState(NULL, /*confirmed*/true, 0);
assert(q0.m_all_rewind_info.front()->isState());
assert(!q0.m_all_rewind_info.front()->isEvent());
assert(q0.hasMoreRewindInfo());
@@ -378,7 +376,7 @@ void RewindQueue::unitTesting()
assert((*rii)->isEvent());
// Another state must be sorted before the event:
q0.addNetworkState(dummy_rewinder, NULL, 0);
q0.addNetworkState(NULL, 0);
assert(q0.hasMoreRewindInfo());
q0.mergeNetworkData(world_ticks, &needs_rewind, &rewind_ticks);
assert(q0.m_all_rewind_info.size() == 3);
@@ -403,7 +401,7 @@ void RewindQueue::unitTesting()
// Now test inserting an event first, then the state
RewindQueue q1;
q1.addLocalEvent(NULL, NULL, true, 5);
q1.addLocalState(NULL, NULL, true, 5);
q1.addLocalState(NULL, true, 5);
rii = q1.m_all_rewind_info.begin();
assert((*rii)->isState());
rii++;

View File

@@ -63,12 +63,10 @@ public:
void reset();
void addLocalEvent(EventRewinder *event_rewinder, BareNetworkString *buffer,
bool confirmed, int ticks);
void addLocalState(Rewinder *rewinder, BareNetworkString *buffer,
bool confirmed, int ticks);
void addLocalState(BareNetworkString *buffer, bool confirmed, int ticks);
void addNetworkEvent(EventRewinder *event_rewinder,
BareNetworkString *buffer, int ticks);
void addNetworkState(Rewinder *rewinder, BareNetworkString *buffer,
int ticks);
void addNetworkState(BareNetworkString *buffer, int ticks);
void mergeNetworkData(int world_ticks, bool *needs_rewind,
int *rewind_ticks);
void replayAllEvents(int ticks);