Index: src/game/Item.cpp =================================================================== --- src/game/Item.cpp (revision 2584) +++ src/game/Item.cpp (working copy) @@ -165,6 +165,8 @@ m_valuesCount = ITEM_END; m_slot = 0; + uState = ITEM_NEW; + uQueuePos = -1; } uint32 GetRandPropertiesSeedfromDisplayInfoDBC(uint32 DisplayID) @@ -448,17 +450,36 @@ void Item::SaveToDB() { uint32 guid = GetGUIDLow(); - sDatabase.PExecute("DELETE FROM `item_instance` WHERE `guid` = '%u'", guid); + switch (uState) + { + case ITEM_NEW: + { + std::ostringstream ss; + ss << "INSERT INTO `item_instance` (`guid`,`data`) VALUES (" << guid << ",'"; + for(uint16 i = 0; i < m_valuesCount; i++ ) + ss << GetUInt32Value(i) << " "; + ss << "' )"; - std::ostringstream ss; - ss << "INSERT INTO `item_instance` (`guid`,`data`) VALUES (" << guid << ",'"; + sDatabase.Execute( ss.str().c_str() ); + } break; + case ITEM_CHANGED: + { + std::ostringstream ss; + ss << "UPDATE `item_instance` SET `data` = '"; + for(uint16 i = 0; i < m_valuesCount; i++ ) + ss << GetUInt32Value(i) << " "; + ss << "' WHERE `guid` = '" << guid << "'"; - for(uint16 i = 0; i < m_valuesCount; i++ ) - ss << GetUInt32Value(i) << " "; - - ss << "' )"; - - sDatabase.Execute( ss.str().c_str() ); + sDatabase.Execute( ss.str().c_str() ); + } break; + case ITEM_REMOVED: + { + sDatabase.PExecute("DELETE FROM `item_instance` WHERE `guid` = '%u'", guid); + delete this; + return; + } + } + SetState(ITEM_UNCHANGED); } bool Item::LoadFromDB(uint32 guid, uint64 owner_guid) @@ -490,6 +511,7 @@ _LoadQuests(); + SetState(ITEM_UNCHANGED); return true; } @@ -760,3 +782,29 @@ SetUInt32Value(ITEM_FIELD_ENCHANTMENT+15,item_rand->enchant_id_3); } } + +void Item::SetState(ItemUpdateState state, Player *forplayer) +{ + if (state == ITEM_UNCHANGED) + { + uState = state; + if (forplayer) + forplayer->m_itemUpdateQueue.erase(forplayer->m_itemUpdateQueue.begin() + uQueuePos); + // unset in queue + uQueuePos = -1; + } + else if (uState == ITEM_UNCHANGED || uState == ITEM_CHANGED) + { + uState = state; + AddToUpdateQueueOf(forplayer); + } + else if (uState == ITEM_NEW && state == ITEM_REMOVED) + delete this; +} + +void Item::AddToUpdateQueueOf(Player *player) +{ + if (!player || uState == ITEM_UNCHANGED || IsInUpdateQueue()) return; + player->m_itemUpdateQueue.push_back(this); + uQueuePos = player->m_itemUpdateQueue.size()-1; +} Index: src/game/Item.h =================================================================== --- src/game/Item.h (revision 2584) +++ src/game/Item.h (working copy) @@ -122,6 +122,14 @@ SELL_ERR_CANT_FIND_VENDOR = 3 }; +enum ItemUpdateState +{ + ITEM_UNCHANGED = 0, + ITEM_CHANGED = 1, + ITEM_NEW = 2, + ITEM_REMOVED = 3, +}; + class MANGOS_DLL_SPEC Item : public Object { public: @@ -160,9 +168,17 @@ void SetItemRandomProperties(); Loot loot; + // Update States + ItemUpdateState GetState() const { return uState; } + void SetState(ItemUpdateState state, Player *forplayer = NULL); + void AddToUpdateQueueOf(Player *player); + bool IsInUpdateQueue() const { return uQueuePos != -1; } + protected: void _LoadQuests(); private: uint32 m_slot; + ItemUpdateState uState; + int16 uQueuePos; }; #endif Index: src/game/Player.cpp =================================================================== --- src/game/Player.cpp (revision 2584) +++ src/game/Player.cpp (working copy) @@ -7280,6 +7280,8 @@ pItem->AddToWorld(); pItem->SendUpdateToPlayer( this ); } + + pItem->SetState(ITEM_CHANGED, this); } else { @@ -7292,6 +7294,8 @@ pItem->AddToWorld(); pItem->SendUpdateToPlayer( this ); } + pBag->SetState(ITEM_CHANGED, this); + pItem->SetState(ITEM_CHANGED, this); } } } @@ -7302,13 +7306,13 @@ pItem2->SendUpdateToPlayer( this ); // delete item (it not in any slot currently) - pItem->DeleteFromDB(); + //pItem->DeleteFromDB(); if( IsInWorld() && update ) { pItem->RemoveFromWorld(); pItem->DestroyForPlayer( this ); } - delete pItem; + pItem->SetState(ITEM_REMOVED, this); return pItem2; } @@ -7382,6 +7386,7 @@ SetUInt32Value(VisibleBase + 8, pItem->GetUInt32Value(ITEM_FIELD_RANDOM_PROPERTIES_ID)); } + pItem->SetState(ITEM_CHANGED, this); } // Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case. @@ -7424,6 +7429,7 @@ pItem->SetSlot( NULL_SLOT ); if( IsInWorld() && update ) pItem->SendUpdateToPlayer( this ); + pItem->SetState(ITEM_CHANGED, this); } } @@ -7500,7 +7506,7 @@ pItem->SetOwnerGUID(0); pItem->SetSlot( NULL_SLOT ); pItem->SetUInt64Value( ITEM_FIELD_CONTAINED, 0 ); - pItem->DeleteFromDB(); + //pItem->DeleteFromDB(); ItemPrototype const *pProto = pItem->GetProto(); if( bag == INVENTORY_SLOT_BAG_0 ) @@ -7568,8 +7574,8 @@ } } } + pItem->SetState(ITEM_REMOVED, this); } - delete pItem; } void Player::DestroyItemCount( uint32 item, uint32 count, bool update ) @@ -8155,6 +8161,7 @@ if((*itr)->leftduration > 0) { (*itr)->item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+(*itr)->slot*3+1,(*itr)->leftduration); + (*itr)->item->SetState(ITEM_CHANGED, this); } } } @@ -9843,28 +9850,33 @@ continue; } + bool success = true; dest = ((INVENTORY_SLOT_BAG_0 << 8) | slot); if( IsInventoryPos( dest ) ) { if( CanStoreItem( INVENTORY_SLOT_BAG_0, slot, dest, item, false ) == EQUIP_ERR_OK ) StoreItem(dest, item, true); else - delete item; + success = false; } else if( IsEquipmentPos( dest ) ) { if( CanEquipItem( slot, dest, item, false, false ) == EQUIP_ERR_OK ) QuickEquipItem(dest, item); else - delete item; + success = false; } else if( IsBankPos( dest ) ) { if( CanBankItem( INVENTORY_SLOT_BAG_0, slot, dest, item, false ) == EQUIP_ERR_OK ) BankItem(dest, item, true); else - delete item; + success = false; } + + // item's state changed after stored + if (success) item->SetState(ITEM_UNCHANGED, this); + else delete item; } while (result->NextRow()); delete result; @@ -10269,8 +10281,12 @@ void Player::_SaveInventory() { - sDatabase.PExecute("DELETE FROM `character_inventory` WHERE `guid` = '%u' AND `bag` = '%u'",GetGUIDLow(), INVENTORY_SLOT_BAG_0); + for(int i = 0; i < m_itemUpdateQueue.size(); i++) + if(m_itemUpdateQueue[i]) m_itemUpdateQueue[i]->SaveToDB(); + m_itemUpdateQueue.clear(); + /*sDatabase.PExecute("DELETE FROM `character_inventory` WHERE `guid` = '%u' AND `bag` = '%u'",GetGUIDLow(), INVENTORY_SLOT_BAG_0); + for(int i = EQUIPMENT_SLOT_START; i < BANK_SLOT_BAG_END; i++) { if ( m_items[i] != 0 ) @@ -10278,7 +10294,7 @@ sDatabase.PExecute("INSERT INTO `character_inventory` (`guid`,`bag`,`slot`,`item`,`item_template`) VALUES ('%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), INVENTORY_SLOT_BAG_0, i, m_items[i]->GetGUIDLow(), m_items[i]->GetEntry()); m_items[i]->SaveToDB(); } - } + }*/ } void Player::_SaveMail() Index: src/game/Player.h =================================================================== --- src/game/Player.h (revision 2584) +++ src/game/Player.h (working copy) @@ -390,6 +390,7 @@ class MANGOS_DLL_SPEC Player : public Unit { friend class WorldSession; + friend void Item::AddToUpdateQueueOf(Player *player); public: explicit Player (WorldSession *session); ~Player ( ); @@ -546,6 +547,7 @@ float GetPosStat(Stats stat) const { return GetFloatValue(PLAYER_FIELD_POSSTAT0+stat); } float GetNegStat(Stats stat) const { return GetFloatValue(PLAYER_FIELD_NEGSTAT0+stat); } float GetCreateStat(Stats stat) const { return m_createStats[stat]; } + float GetStatDiff(Stats stat) const {return GetStat(stat) - GetCreateStat(stat); } /*********************************************************/ /*** STORAGE SYSTEM ***/ @@ -591,6 +593,7 @@ void SendEquipError( uint8 msg, Item* pItem, Item *pItem2 ); void SendBuyError( uint8 msg, Creature* pCreature, uint32 item, uint32 param ); void SendSellError( uint8 msg, Creature* pCreature, uint64 guid, uint32 param ); + void AddWeaponProficiency(uint32 newflag) { m_WeaponProficiency |= newflag ;} void AddArmorProficiency(uint32 newflag) { m_ArmorProficiency |= newflag ;} uint32 GetWeaponProficiency() const { return m_WeaponProficiency;} @@ -1202,6 +1205,7 @@ Item* m_items[BUYBACK_SLOT_END]; Item* m_buybackitems[BUYBACK_SLOT_END - BUYBACK_SLOT_START]; + std::vector m_itemUpdateQueue; uint8 m_afk; uint8 m_dnd;