Only send state for moving track object
This commit is contained in:
parent
ab528e2840
commit
565dfcef96
@ -197,8 +197,9 @@ void NetworkItemManager::setItemConfirmationTime(std::weak_ptr<STKPeer> peer,
|
||||
* to save the initial state, which is the first confirmed state by all
|
||||
* clients.
|
||||
*/
|
||||
BareNetworkString* NetworkItemManager::saveState()
|
||||
BareNetworkString* NetworkItemManager::saveState(std::vector<std::string>* ru)
|
||||
{
|
||||
ru->push_back(getUniqueIdentity());
|
||||
// On the server:
|
||||
// ==============
|
||||
m_item_events.lock();
|
||||
|
@ -76,7 +76,8 @@ public:
|
||||
virtual void collectedItem(Item *item, AbstractKart *kart) OVERRIDE;
|
||||
virtual Item* dropNewItem(ItemState::ItemType type, const AbstractKart *kart,
|
||||
const Vec3 *xyz=NULL) OVERRIDE;
|
||||
virtual BareNetworkString* saveState() OVERRIDE;
|
||||
virtual BareNetworkString* saveState(std::vector<std::string>* ru)
|
||||
OVERRIDE;
|
||||
virtual void restoreState(BareNetworkString *buffer, int count) OVERRIDE;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void rewindToEvent(BareNetworkString *bns) OVERRIDE {};
|
||||
|
@ -95,13 +95,16 @@ void KartRewinder::computeError()
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Saves all state information for a kart in a memory buffer. The memory
|
||||
* is allocated here and the address returned. It will then be managed
|
||||
* by the RewindManager. The size is used to keep track of memory usage
|
||||
* for rewinding.
|
||||
* \param[out] buffer Address of the memory buffer.
|
||||
* \returns Size of allocated memory, or -1 in case of an error.
|
||||
* by the RewindManager.
|
||||
* \param[out] ru The unique identity of rewinder writing to.
|
||||
* \return The address of the memory buffer with the state.
|
||||
*/
|
||||
BareNetworkString* KartRewinder::saveState()
|
||||
BareNetworkString* KartRewinder::saveState(std::vector<std::string>* ru)
|
||||
{
|
||||
if (m_eliminated)
|
||||
return nullptr;
|
||||
|
||||
ru->push_back(getUniqueIdentity());
|
||||
const int MEMSIZE = 17*sizeof(float) + 9+3;
|
||||
|
||||
BareNetworkString *buffer = new BareNetworkString(MEMSIZE);
|
||||
@ -230,6 +233,9 @@ void KartRewinder::rewindToEvent(BareNetworkString *buffer)
|
||||
// ----------------------------------------------------------------------------
|
||||
std::function<void()> KartRewinder::getLocalStateRestoreFunction()
|
||||
{
|
||||
if (m_eliminated)
|
||||
return nullptr;
|
||||
|
||||
// In theory all ticks / boolean related stuff can be saved locally
|
||||
int bubblegum_ticks = m_bubblegum_ticks;
|
||||
int bounce_back_ticks = m_bounce_back_ticks;
|
||||
|
@ -44,7 +44,8 @@ public:
|
||||
~KartRewinder() {}
|
||||
virtual void saveTransform() OVERRIDE;
|
||||
virtual void computeError() OVERRIDE;
|
||||
virtual BareNetworkString* saveState() OVERRIDE;
|
||||
virtual BareNetworkString* saveState(std::vector<std::string>* ru)
|
||||
OVERRIDE;
|
||||
void reset() OVERRIDE;
|
||||
virtual void restoreState(BareNetworkString *p, int count) OVERRIDE;
|
||||
virtual void rewindToEvent(BareNetworkString *p) OVERRIDE;
|
||||
|
@ -69,6 +69,7 @@
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_manager.hpp"
|
||||
#include "tracks/track_object_manager.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/profiler.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
@ -1031,6 +1032,10 @@ void World::update(int ticks)
|
||||
RewindManager::get()->update(ticks);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("World::update (Track object manager)", 0x20, 0x7F, 0x40);
|
||||
Track::getCurrentTrack()->getTrackObjectManager()->update(stk_config->ticks2Time(ticks));
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
|
||||
PROFILER_PUSH_CPU_MARKER("World::update (Kart::upate)", 0x40, 0x7F, 0x00);
|
||||
|
||||
// Update all the karts. This in turn will also update the controller,
|
||||
|
@ -82,9 +82,9 @@ void GameSetup::loadWorld()
|
||||
if (PlayerManager::getCurrentPlayer())
|
||||
PlayerManager::getCurrentPlayer()->setCurrentChallenge("");
|
||||
race_manager->setTimeTarget(0.0f);
|
||||
race_manager->setReverseTrack(m_reverse);
|
||||
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
|
||||
{
|
||||
race_manager->setReverseTrack(false);
|
||||
if (isSoccerGoalTarget())
|
||||
race_manager->setMaxGoal(m_laps);
|
||||
else
|
||||
@ -92,6 +92,7 @@ void GameSetup::loadWorld()
|
||||
}
|
||||
else
|
||||
{
|
||||
race_manager->setReverseTrack(m_reverse);
|
||||
race_manager->startSingleRace(m_tracks.back(), m_laps,
|
||||
false/*from_overworld*/);
|
||||
}
|
||||
|
@ -304,22 +304,13 @@ void GameProtocol::handleItemEventConfirmation(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 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(bool local_save)
|
||||
void GameProtocol::startNewState()
|
||||
{
|
||||
assert(local_save || NetworkConfig::get()->isServer());
|
||||
|
||||
assert(NetworkConfig::get()->isServer());
|
||||
m_data_to_send->clear();
|
||||
// Local saves don't neet this info, they pass time directly to the
|
||||
// RewindInfo in RewindManager::saveLocalState.
|
||||
if (!local_save)
|
||||
{
|
||||
m_data_to_send->addUInt8(GP_STATE)
|
||||
.addUInt32(World::getWorld()->getTimeTicks());
|
||||
}
|
||||
m_data_to_send->addUInt8(GP_STATE)
|
||||
.addUInt32(World::getWorld()->getTimeTicks());
|
||||
} // startNewState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -329,10 +320,43 @@ void GameProtocol::startNewState(bool local_save)
|
||||
*/
|
||||
void GameProtocol::addState(BareNetworkString *buffer)
|
||||
{
|
||||
assert(NetworkConfig::get()->isServer());
|
||||
m_data_to_send->addUInt16(buffer->size());
|
||||
(*m_data_to_send) += *buffer;
|
||||
} // addState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called by a server to finalize the current state, which add updated
|
||||
* names of rewinder using to the beginning of state buffer
|
||||
* \param prev_rewinder List of previous rewinder using.
|
||||
* \param cur_rewinder List of current rewinder using.
|
||||
*/
|
||||
void GameProtocol::finalizeState(std::vector<std::string>& prev_rewinder,
|
||||
std::vector<std::string>& cur_rewinder)
|
||||
{
|
||||
assert(NetworkConfig::get()->isServer());
|
||||
auto& buffer = m_data_to_send->getBuffer();
|
||||
auto pos = buffer.begin() + 1/*protocol type*/ + 1 /*gp event type*/+
|
||||
4/*time*/;
|
||||
|
||||
if (prev_rewinder != cur_rewinder)
|
||||
{
|
||||
m_data_to_send->reset();
|
||||
std::vector<uint8_t> names;
|
||||
names.push_back((uint8_t)cur_rewinder.size());
|
||||
for (std::string& name : cur_rewinder)
|
||||
{
|
||||
names.push_back((uint8_t)name.size());
|
||||
std::vector<uint8_t> rewinder(name.begin(), name.end());
|
||||
names.insert(names.end(), rewinder.begin(), rewinder.end());
|
||||
}
|
||||
buffer.insert(pos, names.begin(), names.end());
|
||||
std::swap(prev_rewinder, cur_rewinder);
|
||||
}
|
||||
else
|
||||
buffer.insert(pos, 0);
|
||||
} // finalizeState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called when the last state information has been added and the message
|
||||
* can be sent to the clients.
|
||||
@ -355,6 +379,19 @@ void GameProtocol::handleState(Event *event)
|
||||
assert(NetworkConfig::get()->isClient());
|
||||
const NetworkString &data = event->data();
|
||||
int ticks = data.getUInt32();
|
||||
|
||||
// Check for updated rewinder using
|
||||
unsigned new_rewinder_size = data.getUInt8();
|
||||
std::vector<std::string> new_rewinder_using;
|
||||
for (unsigned i = 0; i < new_rewinder_size; i++)
|
||||
{
|
||||
std::string name;
|
||||
data.decodeString(&name);
|
||||
new_rewinder_using.push_back(name);
|
||||
}
|
||||
if (!new_rewinder_using.empty())
|
||||
RewindManager::get()->setRewinderUsing(new_rewinder_using);
|
||||
|
||||
// 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:
|
||||
|
@ -86,9 +86,11 @@ public:
|
||||
|
||||
void controllerAction(int kart_id, PlayerAction action,
|
||||
int value, int val_l, int val_r);
|
||||
void startNewState(bool local_save);
|
||||
void startNewState();
|
||||
void addState(BareNetworkString *buffer);
|
||||
void sendState();
|
||||
void finalizeState(std::vector<std::string>& prev_rewinder,
|
||||
std::vector<std::string>& cur_rewinder);
|
||||
void adjustTimeForClient(STKPeer *peer, int ticks);
|
||||
void sendItemEventConfirmation(int ticks);
|
||||
|
||||
|
@ -49,6 +49,7 @@ RewindInfoState::RewindInfoState(int ticks, BareNetworkString *buffer,
|
||||
bool is_confirmed)
|
||||
: RewindInfo(ticks, is_confirmed)
|
||||
{
|
||||
m_rewinder_using = RewindManager::get()->getRewinderUsing();
|
||||
m_buffer = buffer;
|
||||
} // RewindInfoState
|
||||
|
||||
@ -59,8 +60,21 @@ RewindInfoState::RewindInfoState(int ticks, BareNetworkString *buffer,
|
||||
*/
|
||||
void RewindInfoState::restore()
|
||||
{
|
||||
RewindManager::get()->restoreState(m_buffer);
|
||||
} // rewind
|
||||
m_buffer->reset();
|
||||
for (const std::string& name : m_rewinder_using)
|
||||
{
|
||||
uint16_t count = m_buffer->getUInt16();
|
||||
Rewinder* r = RewindManager::get()->getRewinder(name);
|
||||
if (r == NULL)
|
||||
{
|
||||
Log::error("RewindInfoState", "Missing rewinder %s",
|
||||
name.c_str());
|
||||
m_buffer->skip(count);
|
||||
continue;
|
||||
}
|
||||
r->restoreState(m_buffer, count);
|
||||
} // for all rewinder
|
||||
} // restore
|
||||
|
||||
// ============================================================================
|
||||
RewindInfoEvent::RewindInfoEvent(int ticks, EventRewinder *event_rewinder,
|
||||
|
@ -91,6 +91,8 @@ public:
|
||||
class RewindInfoState: public RewindInfo
|
||||
{
|
||||
private:
|
||||
std::vector<std::string> m_rewinder_using;
|
||||
|
||||
/** Pointer to the buffer which stores all states. */
|
||||
BareNetworkString *m_buffer;
|
||||
public:
|
||||
|
@ -82,16 +82,15 @@ void RewindManager::reset()
|
||||
|
||||
if (!m_enable_rewind_manager) return;
|
||||
|
||||
AllRewinder::iterator r = m_all_rewinder.begin();
|
||||
while (r != m_all_rewinder.end())
|
||||
for (auto it = m_all_rewinder.begin(); it != m_all_rewinder.end();)
|
||||
{
|
||||
if (!(*r)->canBeDestroyed())
|
||||
if (!it->second->canBeDestroyed())
|
||||
{
|
||||
r++;
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
Rewinder *rewinder = *r;
|
||||
r = m_all_rewinder.erase(r);
|
||||
Rewinder* rewinder = it->second;
|
||||
it = m_all_rewinder.erase(it);
|
||||
delete rewinder;
|
||||
}
|
||||
|
||||
@ -150,54 +149,35 @@ void RewindManager::addNetworkState(BareNetworkString *buffer, int 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.
|
||||
/** Saves a state using the GameProtocol function to combine several
|
||||
* independent rewinders to write one state.
|
||||
*/
|
||||
void RewindManager::saveState(bool local_save)
|
||||
void RewindManager::saveState()
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("RewindManager - save state", 0x20, 0x7F, 0x20);
|
||||
auto gp = GameProtocol::lock();
|
||||
if (!gp)
|
||||
return;
|
||||
gp->startNewState(local_save);
|
||||
AllRewinder::const_iterator rewinder;
|
||||
for (rewinder = m_all_rewinder.begin(); rewinder != m_all_rewinder.end(); ++rewinder)
|
||||
gp->startNewState();
|
||||
|
||||
m_overall_state_size = 0;
|
||||
std::vector<std::string> rewinder_using;
|
||||
for (auto& p : m_all_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)
|
||||
BareNetworkString* buffer = p.second->saveState(&rewinder_using);
|
||||
if (buffer != NULL)
|
||||
{
|
||||
m_overall_state_size += buffer->size();
|
||||
gp->addState(buffer);
|
||||
} // size >= 0
|
||||
}
|
||||
delete buffer; // buffer can be freed
|
||||
}
|
||||
gp->finalizeState(m_current_rewinder_using, rewinder_using);
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
} // 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();
|
||||
|
||||
for (auto rewinder = m_all_rewinder.begin();
|
||||
rewinder != m_all_rewinder.end(); ++rewinder)
|
||||
{
|
||||
uint16_t count = data->getUInt16();
|
||||
(*rewinder)->restoreState(data, count);
|
||||
} // for all rewinder
|
||||
} // restoreState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Determines if a new state snapshot should be taken, and if so calls all
|
||||
* rewinder to do so.
|
||||
@ -221,12 +201,12 @@ void RewindManager::update(int ticks_not_used)
|
||||
if (NetworkConfig::get()->isClient())
|
||||
{
|
||||
auto& ret = m_local_state[ticks];
|
||||
for (Rewinder* r : m_all_rewinder)
|
||||
ret[r] = r->getLocalStateRestoreFunction();
|
||||
for (auto& p : m_all_rewinder)
|
||||
ret.push_back(p.second->getLocalStateRestoreFunction());
|
||||
}
|
||||
else
|
||||
{
|
||||
saveState(/**allow_local_save*/false);
|
||||
saveState();
|
||||
PROFILER_PUSH_CPU_MARKER("RewindManager - send state", 0x20, 0x7F, 0x40);
|
||||
if (auto gp = GameProtocol::lock())
|
||||
gp->sendState();
|
||||
@ -293,12 +273,8 @@ void RewindManager::rewindTo(int rewind_ticks, int now_ticks)
|
||||
// First save all current transforms so that the error
|
||||
// can be computed between the transforms before and after
|
||||
// the rewind.
|
||||
AllRewinder::iterator rewinder;
|
||||
for (rewinder = m_all_rewinder.begin();
|
||||
rewinder != m_all_rewinder.end(); ++rewinder)
|
||||
{
|
||||
(*rewinder)->saveTransform();
|
||||
}
|
||||
for (auto& p : m_all_rewinder)
|
||||
p.second->saveTransform();
|
||||
|
||||
// Then undo the rewind infos going backwards in time
|
||||
// --------------------------------------------------
|
||||
@ -327,10 +303,10 @@ void RewindManager::rewindTo(int rewind_ticks, int now_ticks)
|
||||
auto it = m_local_state.find(exact_rewind_ticks);
|
||||
if (it != m_local_state.end())
|
||||
{
|
||||
for (auto& local_state : it->second)
|
||||
for (auto& restore_local_state : it->second)
|
||||
{
|
||||
if (local_state.second)
|
||||
local_state.second();
|
||||
if (restore_local_state)
|
||||
restore_local_state();
|
||||
}
|
||||
for (auto it = m_local_state.begin(); it != m_local_state.end();)
|
||||
{
|
||||
@ -356,7 +332,7 @@ void RewindManager::rewindTo(int rewind_ticks, int now_ticks)
|
||||
}
|
||||
|
||||
// Now go forward through the list of rewind infos till we reach 'now':
|
||||
while(world->getTimeTicks() < now_ticks )
|
||||
while (world->getTimeTicks() < now_ticks)
|
||||
{
|
||||
m_rewind_queue.replayAllEvents(world->getTimeTicks());
|
||||
|
||||
@ -371,11 +347,8 @@ void RewindManager::rewindTo(int rewind_ticks, int now_ticks)
|
||||
} // while (world->getTicks() < current_ticks)
|
||||
|
||||
// Now compute the errors which need to be visually smoothed
|
||||
for (rewinder = m_all_rewinder.begin();
|
||||
rewinder != m_all_rewinder.end(); ++rewinder)
|
||||
{
|
||||
(*rewinder)->computeError();
|
||||
}
|
||||
for (auto& p : m_all_rewinder)
|
||||
p.second->computeError();
|
||||
|
||||
history->setReplayHistory(is_history);
|
||||
m_is_rewinding = false;
|
||||
|
@ -88,12 +88,12 @@ private:
|
||||
* rewind data in case of local races only. */
|
||||
static bool m_enable_rewind_manager;
|
||||
|
||||
typedef std::vector<Rewinder *> AllRewinder;
|
||||
std::vector<std::string> m_current_rewinder_using;
|
||||
|
||||
std::map<int, std::map<Rewinder*, std::function<void()> > > m_local_state;
|
||||
std::map<int, std::vector<std::function<void()> > > m_local_state;
|
||||
|
||||
/** A list of all objects that can be rewound. */
|
||||
AllRewinder m_all_rewinder;
|
||||
std::map<std::string, Rewinder*> m_all_rewinder;
|
||||
|
||||
/** The queue that stores all rewind infos. */
|
||||
RewindQueue m_rewind_queue;
|
||||
@ -149,16 +149,26 @@ public:
|
||||
void addNetworkEvent(EventRewinder *event_rewinder,
|
||||
BareNetworkString *buffer, int ticks);
|
||||
void addNetworkState(BareNetworkString *buffer, int ticks);
|
||||
void saveState(bool local_save);
|
||||
void restoreState(BareNetworkString *buffer);
|
||||
void saveState();
|
||||
// ------------------------------------------------------------------------
|
||||
Rewinder* getRewinder(const std::string& name)
|
||||
{
|
||||
auto it = m_all_rewinder.find(name);
|
||||
if (it == m_all_rewinder.end())
|
||||
return NULL;
|
||||
return it->second;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Adds a Rewinder to the list of all rewinders.
|
||||
* \return true If rewinding is enabled, false otherwise.
|
||||
*/
|
||||
bool addRewinder(Rewinder *rewinder)
|
||||
{
|
||||
if(!m_enable_rewind_manager) return false;
|
||||
m_all_rewinder.push_back(rewinder);
|
||||
if (!m_enable_rewind_manager) return false;
|
||||
// Maximum 1 bit to store no of rewinder used
|
||||
if (m_all_rewinder.size() == 255)
|
||||
return false;
|
||||
m_all_rewinder[rewinder->getUniqueIdentity()] = rewinder;
|
||||
return true;
|
||||
} // addRewinder
|
||||
|
||||
@ -179,6 +189,15 @@ public:
|
||||
{
|
||||
return m_rewind_queue.getLatestConfirmedState();
|
||||
} // getLatestConfirmedState
|
||||
// ------------------------------------------------------------------------
|
||||
/* Used by client to update rewinder using. */
|
||||
void setRewinderUsing(std::vector<std::string>& ru)
|
||||
{ m_current_rewinder_using = std::move(ru); }
|
||||
// ------------------------------------------------------------------------
|
||||
/* Used by client to get a copied list of rewinder using to be used
|
||||
in different thread safely. */
|
||||
const std::vector<std::string>& getRewinderUsing() const
|
||||
{ return m_current_rewinder_using; }
|
||||
|
||||
}; // RewindManager
|
||||
|
||||
|
@ -408,7 +408,8 @@ void RewindQueue::unitTesting()
|
||||
class DummyRewinder : public Rewinder, public EventRewinder
|
||||
{
|
||||
public:
|
||||
BareNetworkString* saveState() { return NULL; }
|
||||
BareNetworkString* saveState(std::vector<std::string>* ru)
|
||||
{ return NULL; }
|
||||
virtual void undoEvent(BareNetworkString *s) {}
|
||||
virtual void rewindToEvent(BareNetworkString *s) {}
|
||||
virtual void restoreState(BareNetworkString *s, int count) {}
|
||||
@ -417,7 +418,7 @@ void RewindQueue::unitTesting()
|
||||
virtual void rewind(BareNetworkString *s) {}
|
||||
virtual void saveTransform() {}
|
||||
virtual void computeError() {}
|
||||
DummyRewinder() : Rewinder("", true) {}
|
||||
DummyRewinder() : Rewinder("dummy_rewinder", true) {}
|
||||
};
|
||||
DummyRewinder *dummy_rewinder = new DummyRewinder();
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
Rewinder::Rewinder(const std::string& ui, bool can_be_destroyed, bool auto_add)
|
||||
: m_unique_identity(ui)
|
||||
{
|
||||
assert(!m_unique_identity.empty() && m_unique_identity.size() < 255);
|
||||
m_can_be_destroyed = can_be_destroyed;
|
||||
if (auto_add)
|
||||
add();
|
||||
|
@ -19,8 +19,9 @@
|
||||
#ifndef HEADER_REWINDER_HPP
|
||||
#define HEADER_REWINDER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class BareNetworkString;
|
||||
|
||||
@ -54,10 +55,10 @@ public:
|
||||
|
||||
/** Provides a copy of the state of the object in one memory buffer.
|
||||
* The memory is managed by the RewindManager.
|
||||
* \param[out] buffer The address of the memory buffer with the state.
|
||||
* \return Size of the buffer, or -1 in case of an error.
|
||||
* \param[out] ru The unique identity of rewinder writing to.
|
||||
* \return The address of the memory buffer with the state.
|
||||
*/
|
||||
virtual BareNetworkString* saveState() = 0;
|
||||
virtual BareNetworkString* saveState(std::vector<std::string>* ru) = 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.
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "physics/physics.hpp"
|
||||
#include "physics/triangle_mesh.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "tracks/track_object.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
@ -171,7 +172,9 @@ PhysicalObject::PhysicalObject(bool is_dynamic,
|
||||
m_current_transform.setOrigin(Vec3());
|
||||
m_current_transform.setRotation(
|
||||
btQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
m_previous_transform = m_current_transform;
|
||||
|
||||
m_last_transform = m_current_transform;
|
||||
m_no_server_state = false;
|
||||
|
||||
m_body_added = false;
|
||||
|
||||
@ -638,7 +641,7 @@ void PhysicalObject::update(float dt)
|
||||
{
|
||||
if (!m_is_dynamic) return;
|
||||
|
||||
m_motion_state->getWorldTransform(m_current_transform);
|
||||
m_current_transform = m_body->getWorldTransform();
|
||||
|
||||
const Vec3 &xyz = m_current_transform.getOrigin();
|
||||
if(m_reset_when_too_low && xyz.getY()<m_reset_height)
|
||||
@ -687,6 +690,9 @@ void PhysicalObject::reset()
|
||||
m_body->setAngularVelocity(btVector3(0,0,0));
|
||||
m_body->setLinearVelocity(btVector3(0,0,0));
|
||||
m_body->activate();
|
||||
|
||||
m_last_transform = m_init_pos;
|
||||
m_last_lv = m_last_av = Vec3(0.0f);
|
||||
} // reset
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -787,6 +793,7 @@ void PhysicalObject::addForRewind()
|
||||
// ----------------------------------------------------------------------------
|
||||
void PhysicalObject::saveTransform()
|
||||
{
|
||||
m_no_server_state = true;
|
||||
} // saveTransform
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -795,37 +802,72 @@ void PhysicalObject::computeError()
|
||||
} // computeError
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
BareNetworkString* PhysicalObject::saveState()
|
||||
BareNetworkString* PhysicalObject::saveState(std::vector<std::string>* ru)
|
||||
{
|
||||
btTransform cur_transform = m_body->getWorldTransform();
|
||||
if ((cur_transform.getOrigin() - m_last_transform.getOrigin())
|
||||
.length() == 0.0f &&
|
||||
m_body->getLinearVelocity() == m_last_lv &&
|
||||
m_body->getLinearVelocity() == m_last_av)
|
||||
return nullptr;
|
||||
|
||||
ru->push_back(getUniqueIdentity());
|
||||
BareNetworkString *buffer = new BareNetworkString();
|
||||
buffer->add(m_current_transform.getOrigin());
|
||||
buffer->add(m_current_transform.getRotation());
|
||||
buffer->add(m_body->getLinearVelocity());
|
||||
buffer->add(m_body->getAngularVelocity());
|
||||
m_last_transform = cur_transform;
|
||||
m_last_lv = m_body->getLinearVelocity();
|
||||
m_last_av = m_body->getAngularVelocity();
|
||||
buffer->add(m_last_transform.getOrigin());
|
||||
buffer->add(m_last_transform.getRotation());
|
||||
buffer->add(m_last_lv);
|
||||
buffer->add(m_last_av);
|
||||
return buffer;
|
||||
} // saveState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void PhysicalObject::restoreState(BareNetworkString *buffer, int count)
|
||||
{
|
||||
btTransform t;
|
||||
t.setOrigin(buffer->getVec3());
|
||||
t.setRotation(buffer->getQuat());
|
||||
m_body->setLinearVelocity(buffer->getVec3());
|
||||
m_body->setAngularVelocity(buffer->getVec3());
|
||||
m_body->proceedToTransform(t);
|
||||
m_no_server_state = false;
|
||||
m_last_transform.setOrigin(buffer->getVec3());
|
||||
m_last_transform.setRotation(buffer->getQuat());
|
||||
m_last_lv = buffer->getVec3();
|
||||
m_last_av = buffer->getVec3();
|
||||
|
||||
m_body->setWorldTransform(m_last_transform);
|
||||
m_motion_state->setWorldTransform(m_last_transform);
|
||||
m_body->setInterpolationWorldTransform(m_last_transform);
|
||||
m_body->setLinearVelocity(m_last_lv);
|
||||
m_body->setAngularVelocity(m_last_av);
|
||||
m_body->setInterpolationLinearVelocity(m_last_lv);
|
||||
m_body->setInterpolationAngularVelocity(m_last_av);
|
||||
} // restoreState
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::function<void()> PhysicalObject::getLocalStateRestoreFunction()
|
||||
{
|
||||
btTransform t = m_current_transform;
|
||||
btTransform t = m_body->getWorldTransform();
|
||||
Vec3 lv = m_body->getLinearVelocity();
|
||||
Vec3 av = m_body->getAngularVelocity();
|
||||
return [t, lv, av, this]()
|
||||
{
|
||||
m_body->setLinearVelocity(lv);
|
||||
m_body->setAngularVelocity(av);
|
||||
m_body->proceedToTransform(t);
|
||||
if (m_no_server_state)
|
||||
{
|
||||
m_body->setWorldTransform(m_last_transform);
|
||||
m_motion_state->setWorldTransform(m_last_transform);
|
||||
m_body->setInterpolationWorldTransform(m_last_transform);
|
||||
m_body->setLinearVelocity(m_last_lv);
|
||||
m_body->setAngularVelocity(m_last_av);
|
||||
m_body->setInterpolationLinearVelocity(m_last_lv);
|
||||
m_body->setInterpolationAngularVelocity(m_last_av);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_body->setWorldTransform(t);
|
||||
m_motion_state->setWorldTransform(t);
|
||||
m_body->setInterpolationWorldTransform(t);
|
||||
m_body->setLinearVelocity(lv);
|
||||
m_body->setAngularVelocity(av);
|
||||
m_body->setInterpolationLinearVelocity(lv);
|
||||
m_body->setInterpolationAngularVelocity(av);
|
||||
}
|
||||
};
|
||||
} // getLocalStateRestoreFunction
|
||||
|
@ -142,8 +142,6 @@ private:
|
||||
* world transform. */
|
||||
btTransform m_current_transform;
|
||||
|
||||
btTransform m_previous_transform;
|
||||
|
||||
/** The mesh might not have the same center as bullet does. This
|
||||
* offset is used to offset the location of the graphical mesh
|
||||
* so that the graphics are aligned with the bullet collision shape. */
|
||||
@ -188,6 +186,11 @@ private:
|
||||
/** Non-null only if the shape is exact */
|
||||
TriangleMesh *m_triangle_mesh;
|
||||
|
||||
btTransform m_last_transform;
|
||||
Vec3 m_last_lv;
|
||||
Vec3 m_last_av;
|
||||
bool m_no_server_state;
|
||||
|
||||
public:
|
||||
PhysicalObject(bool is_dynamic, const Settings& settings,
|
||||
TrackObject* object);
|
||||
@ -275,7 +278,7 @@ public:
|
||||
void addForRewind();
|
||||
virtual void saveTransform();
|
||||
virtual void computeError();
|
||||
virtual BareNetworkString* saveState();
|
||||
virtual BareNetworkString* saveState(std::vector<std::string>* ru);
|
||||
virtual void undoEvent(BareNetworkString *buffer) {}
|
||||
virtual void rewindToEvent(BareNetworkString *buffer) {}
|
||||
virtual void restoreState(BareNetworkString *buffer, int count);
|
||||
|
@ -1550,7 +1550,6 @@ void Track::update(int ticks)
|
||||
m_startup_run = true;
|
||||
}
|
||||
float dt = stk_config->ticks2Time(ticks);
|
||||
m_track_object_manager->update(dt);
|
||||
CheckManager::get()->update(dt);
|
||||
ItemManager::get()->update(ticks);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user