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:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
// ============================================================================
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user