Use BareNetworkString for storing states and events.

This commit is contained in:
hiker 2016-08-04 23:15:12 +10:00
parent 1025e25846
commit 05db7c1481
9 changed files with 114 additions and 92 deletions

View File

@ -19,6 +19,7 @@
#ifndef HEADER_KART_CONTROL_HPP
#define HEADER_KART_CONTROL_HPP
#include "network/network_string.hpp"
#include <string.h>
@ -85,20 +86,20 @@ public:
static int getLength() { return 9; }
// ------------------------------------------------------------------------
/** Copies the important data from this objects into a memory buffer. */
void copyToMemory(char *buffer)
void copyToBuffer(BareNetworkString *buffer)
{
memcpy(buffer, &m_steer, sizeof(float));
memcpy(buffer+sizeof(float), &m_accel, sizeof(float));
buffer[2*sizeof(float)] = getButtonsCompressed();
} // copyToMemory
buffer->add(m_steer);
buffer->add(m_accel);
buffer->addChar(getButtonsCompressed());
} // copyToBuffer
// ------------------------------------------------------------------------
/** Restores this object from a previously saved memory buffer. */
void setFromMemory(char *buffer)
void setFromBuffer(BareNetworkString *buffer)
{
memcpy(&m_steer, buffer , sizeof(float));
memcpy(&m_accel, buffer+ sizeof(float), sizeof(float));
setButtonsCompressed(buffer[2*sizeof(float)] );
m_steer = buffer->getFloat();
m_accel = buffer->getFloat();
setButtonsCompressed(buffer->getUInt8());
} // setFromMemory
// ------------------------------------------------------------------------

View File

@ -18,8 +18,10 @@
#include "karts/kart_rewinder.hpp"
#include "karts/abstract_kart.hpp"
#include "items/attachment.hpp"
#include "modes/world.hpp"
#include "network/rewind_manager.hpp"
#include "network/network_string.hpp"
#include "utils/vec3.hpp"
#include <string.h>
@ -37,44 +39,49 @@ KartRewinder::KartRewinder(AbstractKart *kart) : Rewinder(/*can_be_destroyed*/ f
* \param[out] buffer Address of the memory buffer.
* \returns Size of allocated memory, or -1 in case of an error.
*/
int KartRewinder::getState(char **buffer) const
BareNetworkString* KartRewinder::getState() const
{
const int MEMSIZE = 13*sizeof(float) + 9;
*buffer = new char[MEMSIZE];
float* p = (float*)*buffer;
if(!buffer)
{
Log::error("KartRewinder", "Can not allocate %d bytes.", MEMSIZE);
return -1;
}
BareNetworkString *buffer = new BareNetworkString(MEMSIZE);
const btRigidBody *body = m_kart->getBody();
const btTransform &t = body->getWorldTransform();
buffer->add(t.getOrigin());
btQuaternion q = t.getRotation();
memcpy(p+ 0, t.getOrigin(), 3*sizeof(float));
memcpy(p+ 3, &q, 4*sizeof(float));
memcpy(p+ 7, body->getLinearVelocity(), 3*sizeof(float));
memcpy(p+10, body->getAngularVelocity(), 3*sizeof(float));
m_kart->getControls().copyToMemory((char*)(p+13));
return MEMSIZE;
buffer->add(q);
buffer->add(body->getLinearVelocity());
buffer->add(body->getAngularVelocity());
// Attachment
Attachment::AttachmentType atype = m_kart->getAttachment()->getType();
//buffer->addUInt8(uint8_t(atype));
if(atype!=Attachment::ATTACH_NOTHING)
{
//buffer->addFloat(m_kart->getAttachment()->getTimeLeft());
}
// Steering information
m_kart->getControls().copyToBuffer(buffer);
return buffer;
} // getState
// ----------------------------------------------------------------------------
/** Actually rewind to the specified state. */
void KartRewinder::rewindToState(char *buffer)
void KartRewinder::rewindToState(BareNetworkString *buffer)
{
buffer->reset(); // make sure the buffer is read from the beginning
btTransform t;
float *p = (float*)buffer;
t.setOrigin(*(btVector3*)p);
t.setRotation(*(btQuaternion*)(p+3));
t.setOrigin(buffer->getVec3());
t.setRotation(buffer->getQuat());
btRigidBody *body = m_kart->getBody();
body->proceedToTransform(t);
body->setLinearVelocity(*(btVector3*)(p+7));
body->setAngularVelocity(*(btVector3*)(p+10));
m_kart->getControls().setFromMemory((char*)(p+13));
body->setLinearVelocity(buffer->getVec3());
body->setAngularVelocity(buffer->getVec3());
m_kart->getControls().setFromBuffer(buffer);
return;
} // rewindToState
@ -85,21 +92,22 @@ void KartRewinder::rewindToState(char *buffer)
*/
void KartRewinder::update()
{
if(m_kart->getControls() == m_previous_control)
if(m_kart->getControls() == m_previous_control ||
RewindManager::get()->isRewinding())
return;
m_previous_control = m_kart->getControls();
char *buffer = new char[m_previous_control.getLength()];
m_previous_control.copyToMemory(buffer);
BareNetworkString *buffer = new BareNetworkString(m_previous_control.getLength());
m_previous_control.copyToBuffer(buffer);
// The rewind manager will free the memory once it's not needed anymore
RewindManager::get()->addEvent(this, buffer);
} // update
// ----------------------------------------------------------------------------
void KartRewinder::rewindToEvent(char *p)
void KartRewinder::rewindToEvent(BareNetworkString *buffer)
{
m_kart->getControls().setFromMemory(p);
m_kart->getControls().setFromBuffer(buffer);
}; // rewindToEvent

View File

@ -25,6 +25,7 @@
#include "utils/cpp2011.hpp"
class AbstractKart;
class BareNetworkString;
class KartRewinder : public Rewinder
{
@ -37,17 +38,17 @@ private:
public:
KartRewinder(AbstractKart *kart);
virtual ~KartRewinder() {};
virtual int getState(char **buffer) const;
virtual void rewindToState(char *p) OVERRIDE;
virtual void rewindToEvent(char *p) OVERRIDE;
virtual BareNetworkString* getState() const;
virtual void rewindToState(BareNetworkString *p) OVERRIDE;
virtual void rewindToEvent(BareNetworkString *p) OVERRIDE;
// -------------------------------------------------------------------------
virtual void undoState(char *p) OVERRIDE
virtual void undoState(BareNetworkString *p) OVERRIDE
{
}; // undoState
// -------------------------------------------------------------------------
virtual void undoEvent(char *p) OVERRIDE
virtual void undoEvent(BareNetworkString *p) OVERRIDE
{
}; // undoEvent

View File

@ -137,6 +137,9 @@ public:
memcpy(m_buffer.data(), data, len);
} // BareNetworkString
// ------------------------------------------------------------------------
/** Allows to read a buffer from the beginning again. */
void reset() { m_current_offset = 0; }
// ------------------------------------------------------------------------
BareNetworkString& encodeString(const std::string &value);
BareNetworkString& encodeString(const irr::core::stringw &value);

View File

@ -38,8 +38,8 @@ RewindInfoTime::RewindInfoTime(float time)
} // RewindInfoTime
// ============================================================================
RewindInfoState::RewindInfoState(float time, Rewinder *rewinder, char *buffer,
bool is_confirmed)
RewindInfoState::RewindInfoState(float time, Rewinder *rewinder,
BareNetworkString *buffer, bool is_confirmed)
: RewindInfoRewinder(time, rewinder, buffer, is_confirmed)
{
m_local_physics_time = World::getWorld()->getPhysics()->getPhysicsWorld()
@ -47,8 +47,8 @@ RewindInfoState::RewindInfoState(float time, Rewinder *rewinder, char *buffer,
} // RewindInfoState
// ============================================================================
RewindInfoEvent::RewindInfoEvent(float time, Rewinder *rewinder, char *buffer,
bool is_confirmed)
RewindInfoEvent::RewindInfoEvent(float time, Rewinder *rewinder,
BareNetworkString *buffer, bool is_confirmed)
: RewindInfoRewinder(time, rewinder, buffer, is_confirmed)
{
} // RewindInfoEvent

View File

@ -19,25 +19,30 @@
#ifndef HEADER_REWIND_INFO_HPP
#define HEADER_REWIND_INFO_HPP
#include "network/network_string.hpp"
#include "network/rewinder.hpp"
#include "utils/leak_check.hpp"
#include "utils/ptr_vector.hpp"
#include <assert.h>
#include <vector>
/** Used to store rewind information for a given time for all rewind
* instances.
* Rewind information can either be a state (for example a kart would
* have position, rotation, linear and angular velocity, ... as state),
* or an event (for a kart that would be pressing or releasing of a key).
* State changes and events can be delivered in different frequencies,
* and might be released (to save memory) differently: A state can be
* reproduced from a previous state by replaying the simulation taking
* all events into account.
*/
/** Used to store rewind information for a given time for all rewind
* instances.
* Rewind information can either be a state (for example a kart would
* have position, rotation, linear and angular velocity, ... as state),
* or an event (for a kart that would be pressing or releasing of a key).
* State changes and events can be delivered in different frequencies,
* and might be released (to save memory) differently: A state can be
* reproduced from a previous state by replaying the simulation taking
* all events into account.
*/
class RewindInfo
{
private:
LEAK_CHECK();
/** Time when this state was taken. */
float m_time;
@ -77,30 +82,35 @@ public:
}; // RewindInfo
// ============================================================================
/** A rewind info abstract class that keeps track of a rewinder object.
/** 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.
*/
class RewindInfoRewinder : 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;
/** Pointer to the buffer which stores all states. */
char *m_buffer;
public:
RewindInfoRewinder(float time, Rewinder *rewinder, char *buffer,
bool is_confirmed)
RewindInfoRewinder(float time, Rewinder *rewinder,
BareNetworkString *buffer, bool is_confirmed)
: RewindInfo(time, is_confirmed)
{
m_rewinder = rewinder;
m_buffer = buffer;
} // RewindInfoRewinder
// ------------------------------------------------------------------------
~RewindInfoRewinder()
virtual ~RewindInfoRewinder()
{
delete m_buffer;
} // ~RewindInfoRewinder
// ------------------------------------------------------------------------
/** Returns a pointer to the state buffer. */
BareNetworkString *getBuffer() const { return m_buffer; }
}; // RewindInfoRewinder
// ============================================================================
@ -131,33 +141,30 @@ private:
float m_local_physics_time;
public:
RewindInfoState(float time, Rewinder *rewinder, char *buffer,
bool is_confirmed);
RewindInfoState(float time, Rewinder *rewinder,
BareNetworkString *buffer, bool is_confirmed);
virtual ~RewindInfoState() {};
// ------------------------------------------------------------------------
/** Returns the left-over physics time. */
float getLocalPhysicsTime() const { return m_local_physics_time; }
// ------------------------------------------------------------------------
/** Returns a pointer to the state buffer. */
char *getBuffer() const { return m_buffer; }
// ------------------------------------------------------------------------
virtual bool isState() const { return true; }
// ------------------------------------------------------------------------
/** Called when going back in time to undo any rewind information.
* It calls undoState in the rewinder. */
virtual void undo()
{
m_rewinder->undoState(m_buffer);
m_rewinder->undoState(getBuffer());
} // undoEvent
// ------------------------------------------------------------------------
/** Rewinds to this state. This is called while going forwards in time
* again to reach current time. It will call rewindToState(char *)
* again to reach current time. It will call rewindToState().
* if the state is a confirmed state. */
virtual void rewind()
{
if (isConfirmed())
m_rewinder->rewindToState(m_buffer);
m_rewinder->rewindToState(getBuffer());
else
{
// TODO
@ -170,13 +177,10 @@ public:
class RewindInfoEvent : public RewindInfoRewinder
{
public:
RewindInfoEvent(float time, Rewinder *rewinder, char *buffer,
bool is_confirmed);
RewindInfoEvent(float time, Rewinder *rewinder,
BareNetworkString *buffer, bool is_confirmed);
virtual ~RewindInfoEvent() {}
// ------------------------------------------------------------------------
/** Returns a pointer to the state buffer. */
char *getBuffer() const { return m_buffer; }
// ------------------------------------------------------------------------
virtual bool isEvent() const { return true; }
// ------------------------------------------------------------------------
@ -184,15 +188,15 @@ public:
* It calls undoEvent in the rewinder. */
virtual void undo()
{
m_rewinder->undoEvent(m_buffer);
m_rewinder->undoEvent(getBuffer());
} // undo
// ------------------------------------------------------------------------
/** This is called while going forwards in time again to reach current
* time. Calls rewindEvent(char*).
* time. Calls rewindEvent().
*/
virtual void rewind()
{
m_rewinder->rewindToEvent(m_buffer);
m_rewinder->rewindToEvent(getBuffer());
} // rewind
}; // class RewindIndoEvent

View File

@ -20,6 +20,7 @@
#include "graphics/irr_driver.hpp"
#include "modes/world.hpp"
#include "network/network_string.hpp"
#include "network/rewinder.hpp"
#include "network/rewind_info.hpp"
#include "physics/physics.hpp"
@ -64,6 +65,7 @@ RewindManager::~RewindManager()
for(unsigned int i=0; i<m_rewind_info.size(); i++)
{
delete m_rewind_info[i];
m_rewind_info[i] = NULL;
}
m_rewind_info.clear();
} // ~RewindManager
@ -208,7 +210,7 @@ unsigned int RewindManager::findFirstIndex(float target_time) const
* \param time Time at which the event was recorded.
* \param buffer Pointer to the event data.
*/
void RewindManager::addEvent(Rewinder *rewinder, char *buffer)
void RewindManager::addEvent(Rewinder *rewinder, BareNetworkString *buffer)
{
if(m_is_rewinding) return;
RewindInfo *ri = new RewindInfoEvent(getCurrentTime(), rewinder,
@ -240,17 +242,18 @@ void RewindManager::saveStates()
// For now always create a snapshot.
for(unsigned int i=0; i<m_all_rewinder.size(); i++)
{
char *p;
int size = m_all_rewinder[i]->getState(&p);
if(size>=0)
BareNetworkString *buffer = m_all_rewinder[i]->getState();
if(buffer && buffer->size()>=0)
{
m_overall_state_size += size;
m_overall_state_size += buffer->size();
RewindInfo *ri = new RewindInfoState(getCurrentTime(),
m_all_rewinder[i], p,
m_all_rewinder[i], buffer,
/*is_confirmed*/true);
assert(ri);
insertRewindInfo(ri);
} // size >= 0
else
delete buffer; // NULL or 0 byte buffer
}
Log::verbose("RewindManager", "%f allocated %ld bytes search %d/%d=%f",
@ -367,7 +370,7 @@ float RewindManager::determineTimeStepSize(int next_state, float end_time)
{
// If there is a next state (which is known to have a different time)
// use the time difference to determine the time step size.
if(next_state < m_rewind_info.size())
if(next_state < (int)m_rewind_info.size())
return m_rewind_info[next_state]->getTime() - World::getWorld()->getTime();
// Otherwise, i.e. we are rewinding the last state/event, take the

View File

@ -172,7 +172,7 @@ public:
void reset();
void saveStates();
void rewindTo(float target_time);
void addEvent(Rewinder *rewinder, char *buffer);
void addEvent(Rewinder *rewinder, BareNetworkString *buffer);
// ------------------------------------------------------------------------
/** Adds a Rewinder to the list of all rewinders.
* \return true If rewinding is enabled, false otherwise.

View File

@ -19,6 +19,8 @@
#ifndef HEADER_REWINDER_HPP
#define HEADER_REWINDER_HPP
class BareNetworkString;
class Rewinder
{
private:
@ -32,31 +34,31 @@ public:
* \param[out] buffer The address of the memory buffer with the state.
* \return Size of the buffer, or -1 in case of an error.
*/
virtual int getState(char **buffer) const = 0;
virtual BareNetworkString* getState() const = 0;
/** Called when an event needs to be undone. This is called while going
* backwards for rewinding - all stored events will get an 'undo' call.
* A dummy implementation is provided which just ignores this.
*/
virtual void undoEvent(char *buffer) = 0;
virtual void undoEvent(BareNetworkString *buffer) = 0;
/** Called when an event needs to be replayed. This is called during
* rewind, i.e. when going forward in time again.
*/
virtual void rewindToEvent(char *buffer) = 0;
virtual void rewindToEvent(BareNetworkString *buffer) = 0;
/** Called when a state needs to be replayed. This is called during
* rewind, i.e. when going forward in time again, and only for confirmed
* states.
*/
virtual void rewindToState(char *buffer) = 0;
virtual void rewindToState(BareNetworkString *buffer) = 0;
/** Undo the effects of the given state, but do not rewind to that
* state (which is done by rewindTo). This is called while going
* backwards for rewinding - all stored events will get an 'undo' call.
* Provided here a dummy implementation that just ignores the state.
*/
virtual void undoState(char *p) = 0;
virtual void undoState(BareNetworkString *buffer) = 0;
// -------------------------------------------------------------------------
/** True if this rewinder can be destroyed. Karts can not be destroyed,