diff --git a/src/items/item_manager.cpp b/src/items/item_manager.cpp index 3ecccca20..0e25687a6 100644 --- a/src/items/item_manager.cpp +++ b/src/items/item_manager.cpp @@ -226,13 +226,15 @@ unsigned int ItemManager::insertItem(Item *item) // previously deleted entry, otherwise at the end. int index = -1; for(index=(int)m_all_items.size()-1; index>=0 && m_all_items[index]; index--) {} - - if(index==-1) index = (int)m_all_items.size(); - - if(index<(int)m_all_items.size()) - m_all_items[index] = item; - else + if (index == -1) + { + index = (int)m_all_items.size(); m_all_items.push_back(item); + } + else + { + m_all_items[index] = item; + } item->setItemId(index); // Now insert into the appropriate quad list, if there is a quad list @@ -352,7 +354,7 @@ Item* ItemManager::placeTrigger(const Vec3& xyz, float distance, * \param item The item that was collected. * \param kart The kart that collected the item. */ -void ItemManager::collectedItem(Item *item, AbstractKart *kart) +void ItemManager::collectedItem(ItemState *item, AbstractKart *kart) { assert(item); // Spare tire karts don't collect items diff --git a/src/items/item_manager.hpp b/src/items/item_manager.hpp index 83f5f9a9e..26614eebf 100644 --- a/src/items/item_manager.hpp +++ b/src/items/item_manager.hpp @@ -133,7 +133,7 @@ public: void updateGraphics (float dt); void checkItemHit (AbstractKart* kart); void reset (); - virtual void collectedItem (Item *item, AbstractKart *kart); + virtual void collectedItem (ItemState *item, AbstractKart *kart); void switchItems (); bool randomItemsForArena(const AlignedArray& pos); // ------------------------------------------------------------------------ diff --git a/src/items/network_item_manager.cpp b/src/items/network_item_manager.cpp index cc643818d..abb4cd480 100644 --- a/src/items/network_item_manager.cpp +++ b/src/items/network_item_manager.cpp @@ -95,7 +95,7 @@ void NetworkItemManager::initClientConfirmState() * \param item The item that was collected. * \param kart The kart that collected the item. */ -void NetworkItemManager::collectedItem(Item *item, AbstractKart *kart) +void NetworkItemManager::collectedItem(ItemState *item, AbstractKart *kart) { if(NetworkConfig::get()->isServer()) { @@ -142,7 +142,7 @@ Item* NetworkItemManager::dropNewItem(ItemState::ItemType type, kart->getXYZ() ); m_item_events.unlock(); return item; -} // newItem +} // dropNewItem // ---------------------------------------------------------------------------- /** Called by the GameProtocol when a confirmation for an item event is @@ -237,9 +237,9 @@ void NetworkItemManager::forwardTime(int ticks) //----------------------------------------------------------------------------- /** Restores the state of the items to the current world time. It takes the - * last saved - - * using exactly 'count' bytes of the message. + * last saved confirmed state, applies any updates from the server, and + * then syncs up the confirmed state to the in-race items. + * It uses exactly 'count' bytes of the message. * \param buffer the state content. * \param count Number of bytes used for this state. */ @@ -299,13 +299,14 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count) // Forward the saved state: if (dt>0) forwardTime(dt); - // TODO: apply the various events types, atm only collection is supported: + // TODO: apply the various events types, atm only collection + // and new items are supported. if(iei.isItemCollection()) { int index = iei.getIndex(); // An item on the track was collected: AbstractKart *kart = World::getWorld()->getKart(iei.getKartId()); - m_confirmed_state[index]->collected(kart); + collectedItem(m_confirmed_state[index], kart); if (m_confirmed_state[index]->isUsedUp()) { delete m_confirmed_state[index]; @@ -327,7 +328,10 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count) if (m_confirmed_state[is->getItemId()] == NULL) m_confirmed_state[is->getItemId()] = is; else + { *m_confirmed_state[is->getItemId()] = *is; + delete is; + } } } current_time = iei.getTicks(); @@ -351,7 +355,7 @@ void NetworkItemManager::restoreState(BareNetworkString *buffer, int count) for(unsigned int i=0; igetXYZ(); Item *item_new = dropNewItem(is->getType(), is->getPreviousOwner(), &xyz); + if (i != item_new->getItemId()) + { + // The server has this item at a different index in the list + // of all items, which means the client has an incorrect + // item at the index given by the server - delete that item + Log::info("nim", "about to delete item with not matching index i %d item %d", + i, item_new->getItemId()); + if(m_all_items[i]) + deleteItem(m_all_items[i]); + m_all_items[item_new->getItemId()] = NULL; + m_all_items[i] = item_new; + item_new->setItemId(i); + } item_new->setPredicted(false); - item_new->setItemId(i); item_new->setDeactivatedTicks(is->getDeactivatedTicks()); - m_all_items[i] = item_new; *((ItemState*)m_all_items[i]) = *is; } else if (!is && item) diff --git a/src/items/network_item_manager.hpp b/src/items/network_item_manager.hpp index 1e1d93ff9..4b2befbc0 100644 --- a/src/items/network_item_manager.hpp +++ b/src/items/network_item_manager.hpp @@ -73,7 +73,7 @@ public: virtual void reset() OVERRIDE; virtual void setItemConfirmationTime(std::weak_ptr peer, int ticks) OVERRIDE; - virtual void collectedItem(Item *item, AbstractKart *kart) OVERRIDE; + virtual void collectedItem(ItemState *item, AbstractKart *kart) OVERRIDE; virtual Item* dropNewItem(ItemState::ItemType type, const AbstractKart *kart, const Vec3 *xyz=NULL) OVERRIDE; virtual BareNetworkString* saveState(std::vector* ru) diff --git a/src/modes/easter_egg_hunt.cpp b/src/modes/easter_egg_hunt.cpp index ec74d98ca..d578164c3 100644 --- a/src/modes/easter_egg_hunt.cpp +++ b/src/modes/easter_egg_hunt.cpp @@ -159,7 +159,8 @@ const std::string& EasterEggHunt::getIdent() const /** Called when a kart has collected an egg. * \param kart The kart that collected an egg. */ -void EasterEggHunt::collectedItem(const AbstractKart *kart, const Item *item) +void EasterEggHunt::collectedItem(const AbstractKart *kart, + const ItemState *item ) { if(item->getType() != ItemState::ITEM_EASTER_EGG) return; diff --git a/src/modes/easter_egg_hunt.hpp b/src/modes/easter_egg_hunt.hpp index ba5e5eaf9..9a16275ee 100644 --- a/src/modes/easter_egg_hunt.hpp +++ b/src/modes/easter_egg_hunt.hpp @@ -66,7 +66,7 @@ public: virtual void getKartsDisplayInfo( std::vector *info) OVERRIDE; virtual void collectedItem(const AbstractKart *kart, - const Item *item ) OVERRIDE; + const ItemState *item ) OVERRIDE; void collectedEasterEggGhost(int world_id); const int numberOfEggsFound() { return m_eggs_found; } diff --git a/src/modes/world.hpp b/src/modes/world.hpp index 2737d541b..1a25567eb 100644 --- a/src/modes/world.hpp +++ b/src/modes/world.hpp @@ -42,7 +42,7 @@ class AbstractKart; class btRigidBody; class Controller; -class Item; +class ItemState; class PhysicalObject; namespace Scripting @@ -263,7 +263,8 @@ public: int *amount ); // ------------------------------------------------------------------------ /** Receives notification if an item is collected. Used for easter eggs. */ - virtual void collectedItem(const AbstractKart *kart, const Item *item) {} + virtual void collectedItem(const AbstractKart *kart, + const ItemState *item ) {} // ------------------------------------------------------------------------ virtual void endRaceEarly() { return; } // ------------------------------------------------------------------------