Use BareNetworkString for storing states and events.
This commit is contained in:
parent
1025e25846
commit
05db7c1481
@ -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
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user