rendered paste bodyIndex: 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; }; #endifIndex: 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<Item*> m_itemUpdateQueue; uint8 m_afk; uint8 m_dnd;