From 565dfcef9682411d542a42007b64b7714dfcf5a7 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 13 Jul 2018 10:47:30 +0800 Subject: [PATCH] Only send state for moving track object --- src/items/network_item_manager.cpp | 3 +- src/items/network_item_manager.hpp | 3 +- src/karts/kart_rewinder.cpp | 16 +++-- src/karts/kart_rewinder.hpp | 3 +- src/modes/world.cpp | 5 ++ src/network/game_setup.cpp | 3 +- src/network/protocols/game_protocol.cpp | 63 +++++++++++++++---- src/network/protocols/game_protocol.hpp | 4 +- src/network/rewind_info.cpp | 18 +++++- src/network/rewind_info.hpp | 2 + src/network/rewind_manager.cpp | 83 +++++++++---------------- src/network/rewind_manager.hpp | 33 +++++++--- src/network/rewind_queue.cpp | 5 +- src/network/rewinder.cpp | 1 + src/network/rewinder.hpp | 9 +-- src/physics/physical_object.cpp | 76 +++++++++++++++++----- src/physics/physical_object.hpp | 9 ++- src/tracks/track.cpp | 1 - 18 files changed, 223 insertions(+), 114 deletions(-) diff --git a/src/items/network_item_manager.cpp b/src/items/network_item_manager.cpp index f6688f86f..d5ccf3a5a 100644 --- a/src/items/network_item_manager.cpp +++ b/src/items/network_item_manager.cpp @@ -197,8 +197,9 @@ void NetworkItemManager::setItemConfirmationTime(std::weak_ptr peer, * to save the initial state, which is the first confirmed state by all * clients. */ -BareNetworkString* NetworkItemManager::saveState() +BareNetworkString* NetworkItemManager::saveState(std::vector* ru) { + ru->push_back(getUniqueIdentity()); // On the server: // ============== m_item_events.lock(); diff --git a/src/items/network_item_manager.hpp b/src/items/network_item_manager.hpp index 0abe60dbd..cfeec8e3d 100644 --- a/src/items/network_item_manager.hpp +++ b/src/items/network_item_manager.hpp @@ -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* ru) + OVERRIDE; virtual void restoreState(BareNetworkString *buffer, int count) OVERRIDE; // ------------------------------------------------------------------------ virtual void rewindToEvent(BareNetworkString *bns) OVERRIDE {}; diff --git a/src/karts/kart_rewinder.cpp b/src/karts/kart_rewinder.cpp index 7fe3df980..320ee13bb 100644 --- a/src/karts/kart_rewinder.cpp +++ b/src/karts/kart_rewinder.cpp @@ -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* 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 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; diff --git a/src/karts/kart_rewinder.hpp b/src/karts/kart_rewinder.hpp index 3f323d695..f8c191d09 100644 --- a/src/karts/kart_rewinder.hpp +++ b/src/karts/kart_rewinder.hpp @@ -44,7 +44,8 @@ public: ~KartRewinder() {} virtual void saveTransform() OVERRIDE; virtual void computeError() OVERRIDE; - virtual BareNetworkString* saveState() OVERRIDE; + virtual BareNetworkString* saveState(std::vector* ru) + OVERRIDE; void reset() OVERRIDE; virtual void restoreState(BareNetworkString *p, int count) OVERRIDE; virtual void rewindToEvent(BareNetworkString *p) OVERRIDE; diff --git a/src/modes/world.cpp b/src/modes/world.cpp index 82c711990..eb7b844be 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -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, diff --git a/src/network/game_setup.cpp b/src/network/game_setup.cpp index 59dcfdc95..d6532046f 100644 --- a/src/network/game_setup.cpp +++ b/src/network/game_setup.cpp @@ -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*/); } diff --git a/src/network/protocols/game_protocol.cpp b/src/network/protocols/game_protocol.cpp index 89709c7e4..3b373dfcd 100644 --- a/src/network/protocols/game_protocol.cpp +++ b/src/network/protocols/game_protocol.cpp @@ -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& prev_rewinder, + std::vector& 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 names; + names.push_back((uint8_t)cur_rewinder.size()); + for (std::string& name : cur_rewinder) + { + names.push_back((uint8_t)name.size()); + std::vector 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 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: diff --git a/src/network/protocols/game_protocol.hpp b/src/network/protocols/game_protocol.hpp index 4e1f387fe..86bb93397 100644 --- a/src/network/protocols/game_protocol.hpp +++ b/src/network/protocols/game_protocol.hpp @@ -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& prev_rewinder, + std::vector& cur_rewinder); void adjustTimeForClient(STKPeer *peer, int ticks); void sendItemEventConfirmation(int ticks); diff --git a/src/network/rewind_info.cpp b/src/network/rewind_info.cpp index 32a75f6ff..e0c19cd10 100644 --- a/src/network/rewind_info.cpp +++ b/src/network/rewind_info.cpp @@ -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, diff --git a/src/network/rewind_info.hpp b/src/network/rewind_info.hpp index 201d1bf77..9633e4690 100644 --- a/src/network/rewind_info.hpp +++ b/src/network/rewind_info.hpp @@ -91,6 +91,8 @@ public: class RewindInfoState: public RewindInfo { private: + std::vector m_rewinder_using; + /** Pointer to the buffer which stores all states. */ BareNetworkString *m_buffer; public: diff --git a/src/network/rewind_manager.cpp b/src/network/rewind_manager.cpp index 9ed449f4d..dab801a33 100644 --- a/src/network/rewind_manager.cpp +++ b/src/network/rewind_manager.cpp @@ -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 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; diff --git a/src/network/rewind_manager.hpp b/src/network/rewind_manager.hpp index 14baabdd5..c6df43571 100644 --- a/src/network/rewind_manager.hpp +++ b/src/network/rewind_manager.hpp @@ -88,12 +88,12 @@ private: * rewind data in case of local races only. */ static bool m_enable_rewind_manager; - typedef std::vector AllRewinder; + std::vector m_current_rewinder_using; - std::map > > m_local_state; + std::map > > m_local_state; /** A list of all objects that can be rewound. */ - AllRewinder m_all_rewinder; + std::map 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& 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& getRewinderUsing() const + { return m_current_rewinder_using; } }; // RewindManager diff --git a/src/network/rewind_queue.cpp b/src/network/rewind_queue.cpp index 1e61b2930..411860855 100644 --- a/src/network/rewind_queue.cpp +++ b/src/network/rewind_queue.cpp @@ -408,7 +408,8 @@ void RewindQueue::unitTesting() class DummyRewinder : public Rewinder, public EventRewinder { public: - BareNetworkString* saveState() { return NULL; } + BareNetworkString* saveState(std::vector* 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(); diff --git a/src/network/rewinder.cpp b/src/network/rewinder.cpp index 6c55c759b..48b8c9b41 100644 --- a/src/network/rewinder.cpp +++ b/src/network/rewinder.cpp @@ -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(); diff --git a/src/network/rewinder.hpp b/src/network/rewinder.hpp index 89c620265..f772221a7 100644 --- a/src/network/rewinder.hpp +++ b/src/network/rewinder.hpp @@ -19,8 +19,9 @@ #ifndef HEADER_REWINDER_HPP #define HEADER_REWINDER_HPP -#include #include +#include +#include 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* 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. diff --git a/src/physics/physical_object.cpp b/src/physics/physical_object.cpp index 3cd207c75..829f6c975 100644 --- a/src/physics/physical_object.cpp +++ b/src/physics/physical_object.cpp @@ -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()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* 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 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 diff --git a/src/physics/physical_object.hpp b/src/physics/physical_object.hpp index b061ce51e..923c2979b 100644 --- a/src/physics/physical_object.hpp +++ b/src/physics/physical_object.hpp @@ -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* ru); virtual void undoEvent(BareNetworkString *buffer) {} virtual void rewindToEvent(BareNetworkString *buffer) {} virtual void restoreState(BareNetworkString *buffer, int count); diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index af6b78eda..99c71ce57 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -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);