aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp18
-rw-r--r--src/server/game/Entities/Item/AzeriteItem/AzeriteItem.h1
-rw-r--r--src/server/game/Entities/Item/Item.cpp28
-rw-r--r--src/server/game/Entities/Player/Player.cpp136
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp7
-rw-r--r--src/server/game/Mails/Mail.cpp6
7 files changed, 121 insertions, 77 deletions
diff --git a/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp b/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp
index 3d8fd01134c..dc539b82b85 100644
--- a/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp
+++ b/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.cpp
@@ -177,20 +177,24 @@ void AzeriteItem::LoadAzeriteItemData(Player const* owner, AzeriteItemData& azer
}
}
-void AzeriteItem::DeleteFromDB(CharacterDatabaseTransaction& trans)
+void AzeriteItem::DeleteFromDB(CharacterDatabaseTransaction& trans, ObjectGuid::LowType itemGuid)
{
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_AZERITE);
- stmt->setUInt64(0, GetGUID().GetCounter());
- trans->Append(stmt);
+ stmt->setUInt64(0, itemGuid);
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_AZERITE_MILESTONE_POWER);
- stmt->setUInt64(0, GetGUID().GetCounter());
- trans->Append(stmt);
+ stmt->setUInt64(0, itemGuid);
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_AZERITE_UNLOCKED_ESSENCE);
- stmt->setUInt64(0, GetGUID().GetCounter());
- trans->Append(stmt);
+ stmt->setUInt64(0, itemGuid);
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
+}
+void AzeriteItem::DeleteFromDB(CharacterDatabaseTransaction& trans)
+{
+ AzeriteItem::DeleteFromDB(trans, GetGUID().GetCounter());
Item::DeleteFromDB(trans);
}
diff --git a/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.h b/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.h
index 9e69debf38d..4c1c882b0e1 100644
--- a/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.h
+++ b/src/server/game/Entities/Item/AzeriteItem/AzeriteItem.h
@@ -35,6 +35,7 @@ public:
void SaveToDB(CharacterDatabaseTransaction& trans) override;
void LoadAzeriteItemData(Player const* owner, AzeriteItemData& azeriteItem);
+ static void DeleteFromDB(CharacterDatabaseTransaction& trans, ObjectGuid::LowType itemGuid);
void DeleteFromDB(CharacterDatabaseTransaction& trans) override;
uint32 GetLevel() const { return m_azeriteItemData->Level; }
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 1dd190053d8..e71c5fb1060 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -379,7 +379,7 @@ void ItemAdditionalLoadInfo::Init(std::unordered_map<ObjectGuid::LowType, ItemAd
}
// 0 1 2
- // SELECT iaue.itemGuid, iaue.azeriteEssenceId, iaue.`rank` FROM item_instance_azerite_unlocked_essence iaue INNER JOIN ...
+ // SELECT iaue.itemGuid, iaue.azeriteEssenceId, iaue.`rank` FROM item_instance_azerite_unlocked_essence iaue INNER JOIN ...
if (azeriteItemUnlockedEssencesResult)
{
do
@@ -989,7 +989,31 @@ void Item::DeleteFromDB(CharacterDatabaseTransaction& trans, ObjectGuid::LowType
{
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
stmt->setUInt64(0, itemGuid);
- trans->Append(stmt);
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_GEMS);
+ stmt->setUInt64(0, itemGuid);
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_TRANSMOG);
+ stmt->setUInt64(0, itemGuid);
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT);
+ stmt->setUInt64(0, itemGuid);
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT_POWERS);
+ stmt->setUInt64(0, itemGuid);
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_MODIFIERS);
+ stmt->setUInt64(0, itemGuid);
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GIFT);
+ stmt->setUInt64(0, itemGuid);
+ CharacterDatabase.ExecuteOrAppend(trans, stmt);
}
void Item::DeleteFromDB(CharacterDatabaseTransaction& trans)
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index e6aff9ca6eb..acd895cb925 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -3829,6 +3829,44 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
if (resultMail)
{
+ std::unordered_map<uint32, std::vector<Item*>> itemsByMail;
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAILITEMS);
+ stmt->setUInt64(0, guid);
+ PreparedQueryResult resultItems = CharacterDatabase.Query(stmt);
+
+ if (resultItems)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAILITEMS_ARTIFACT);
+ stmt->setUInt64(0, guid);
+ PreparedQueryResult artifactResult = CharacterDatabase.Query(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAILITEMS_AZERITE);
+ stmt->setUInt64(0, guid);
+ PreparedQueryResult azeriteResult = CharacterDatabase.Query(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAILITEMS_AZERITE_MILESTONE_POWER);
+ stmt->setUInt64(0, guid);
+ PreparedQueryResult azeriteItemMilestonePowersResult = CharacterDatabase.Query(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAILITEMS_AZERITE_UNLOCKED_ESSENCE);
+ stmt->setUInt64(0, guid);
+ PreparedQueryResult azeriteItemUnlockedEssencesResult = CharacterDatabase.Query(stmt);
+
+ std::unordered_map<ObjectGuid::LowType, ItemAdditionalLoadInfo> additionalData;
+ ItemAdditionalLoadInfo::Init(&additionalData, artifactResult, azeriteResult, azeriteItemMilestonePowersResult,
+ azeriteItemUnlockedEssencesResult, azeriteEmpoweredItemResult);
+
+ do
+ {
+ Field* fields = resultItems->Fetch();
+ uint32 mailId = fields[44].GetUInt32();
+ if (Item* mailItem = _LoadMailedItem(playerguid, nullptr, mailId, nullptr, fields, Trinity::Containers::MapGetValuePtr(additionalData, fields[0].GetUInt64())))
+ itemsByMail[mailId].push_back(mailItem);
+
+ } while (resultItems->NextRow());
+ }
+
do
{
Field* mailFields = resultMail->Fetch();
@@ -3864,41 +3902,14 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
if (mailTemplateId)
draft = MailDraft(mailTemplateId, false); // items are already included
- if (has_items)
+ auto itemsItr = itemsByMail.find(mail_id);
+ if (itemsItr != itemsByMail.end())
{
- // Data needs to be at first place for Item::LoadFromDB
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAILITEMS);
- stmt->setUInt32(0, mail_id);
- PreparedQueryResult resultItems = CharacterDatabase.Query(stmt);
- if (resultItems)
- {
- do
- {
- Field* itemFields = resultItems->Fetch();
- ObjectGuid::LowType itemGuidLow = itemFields[0].GetUInt64();
- uint32 itemEntry = itemFields[1].GetUInt32();
-
- ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(itemEntry);
- if (!itemProto)
- {
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
- stmt->setUInt64(0, itemGuidLow);
- trans->Append(stmt);
- continue;
- }
-
- Item* item = NewItemOrBag(itemProto);
- if (!item->LoadFromDB(itemGuidLow, playerguid, itemFields, itemEntry))
- {
- item->FSetState(ITEM_REMOVED);
- item->SaveToDB(trans); // it also deletes item object!
- continue;
- }
-
- draft.AddItem(item);
- }
- while (resultItems->NextRow());
- }
+ for (Item* item : itemsItr->second)
+ draft.AddItem(item);
+
+ // MailDraft will take care of freeing memory
+ itemsByMail.erase(itemsItr);
}
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_ITEM_BY_ID);
@@ -3910,6 +3921,11 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
draft.AddMoney(money).SendReturnToSender(pl_account, guid, sender, trans);
}
while (resultMail->NextRow());
+
+ // Free remaining items
+ for (auto&& kvp : itemsByMail)
+ for (Item* item : kvp.second)
+ delete item;
}
// Unsummon and delete for pets in world is not required: player deleted from CLI or character list with not loaded pet.
@@ -19059,32 +19075,34 @@ Item* Player::_LoadItem(CharacterDatabaseTransaction& trans, uint32 zoneId, uint
GetGUID().ToString().c_str(), GetName().c_str(), itemEntry);
Item::DeleteFromInventoryDB(trans, itemGuid);
Item::DeleteFromDB(trans, itemGuid);
+ AzeriteItem::DeleteFromDB(trans, itemGuid);
}
return item;
}
// load mailed item which should receive current player
-void Player::_LoadMailedItem(Mail* mail, Field* fields, ItemAdditionalLoadInfo* addionalData)
+Item* Player::_LoadMailedItem(ObjectGuid const& playerGuid, Player* player, uint32 mailId, Mail* mail, Field* fields, ItemAdditionalLoadInfo* addionalData)
{
ObjectGuid::LowType itemGuid = fields[0].GetUInt64();
uint32 itemEntry = fields[1].GetUInt32();
- mail->AddItem(itemGuid, itemEntry);
-
ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemEntry);
if (!proto)
{
TC_LOG_ERROR("entities.player", "Player '%s' (%s) has unknown item_template in mailed items (GUID: " UI64FMTD ", Entry: %u) in mail (%u), deleted.",
- GetName().c_str(), GetGUID().ToString().c_str(), itemGuid, itemEntry, mail->messageID);
+ player ? player->GetName().c_str() : "<unknown>", playerGuid.ToString().c_str(), itemGuid, itemEntry, mailId);
+
+ CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_MAIL_ITEM);
stmt->setUInt64(0, itemGuid);
- CharacterDatabase.Execute(stmt);
+ trans->Append(stmt);
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
- stmt->setUInt64(0, itemGuid);
- CharacterDatabase.Execute(stmt);
- return;
+ Item::DeleteFromDB(trans, itemGuid);
+ AzeriteItem::DeleteFromDB(trans, itemGuid);
+
+ CharacterDatabase.CommitTransaction(trans);
+ return nullptr;
}
Item* item = NewItemOrBag(proto);
@@ -19092,7 +19110,7 @@ void Player::_LoadMailedItem(Mail* mail, Field* fields, ItemAdditionalLoadInfo*
ObjectGuid ownerGuid = fields[43].GetUInt64() ? ObjectGuid::Create<HighGuid::Player>(fields[43].GetUInt64()) : ObjectGuid::Empty;
if (!item->LoadFromDB(itemGuid, ownerGuid, fields, itemEntry))
{
- TC_LOG_ERROR("entities.player", "Player::_LoadMailedItems: Item (GUID: " UI64FMTD ") in mail (%u) doesn't exist, deleted from mail.", itemGuid, mail->messageID);
+ TC_LOG_ERROR("entities.player", "Player::_LoadMailedItems: Item (GUID: " UI64FMTD ") in mail (%u) doesn't exist, deleted from mail.", itemGuid, mailId);
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_ITEM);
stmt->setUInt64(0, itemGuid);
@@ -19102,21 +19120,27 @@ void Player::_LoadMailedItem(Mail* mail, Field* fields, ItemAdditionalLoadInfo*
CharacterDatabaseTransaction temp = CharacterDatabaseTransaction(nullptr);
item->SaveToDB(temp); // it also deletes item object !
- return;
+ return nullptr;
}
if (addionalData)
{
if (item->GetTemplate()->GetArtifactID() && addionalData->Artifact)
- item->LoadArtifactData(this, addionalData->Artifact->Xp, addionalData->Artifact->ArtifactAppearanceId,
+ item->LoadArtifactData(player, addionalData->Artifact->Xp, addionalData->Artifact->ArtifactAppearanceId,
addionalData->Artifact->ArtifactTierId, addionalData->Artifact->ArtifactPowers);
if (addionalData->AzeriteItem)
if (AzeriteItem* azeriteItem = item->ToAzeriteItem())
- azeriteItem->LoadAzeriteItemData(this, *addionalData->AzeriteItem);
+ azeriteItem->LoadAzeriteItemData(player, *addionalData->AzeriteItem);
}
- AddMItem(item);
+ if (mail)
+ mail->AddItem(itemGuid, itemEntry);
+
+ if (player)
+ player->AddMItem(item);
+
+ return item;
}
void Player::_LoadMailInit(PreparedQueryResult resultUnread, PreparedQueryResult resultDelivery)
@@ -19206,7 +19230,7 @@ void Player::_LoadMail()
{
Field* fields = result->Fetch();
uint32 mailId = fields[44].GetUInt32();
- _LoadMailedItem(mailById[mailId], fields, Trinity::Containers::MapGetValuePtr(additionalData, fields[0].GetUInt64()));
+ _LoadMailedItem(GetGUID(), this, mailId, mailById[mailId], fields, Trinity::Containers::MapGetValuePtr(additionalData, fields[0].GetUInt64()));
}
while (result->NextRow());
}
@@ -20590,13 +20614,8 @@ void Player::_SaveInventory(CharacterDatabaseTransaction& trans)
if (!item || item->GetState() == ITEM_NEW)
continue;
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM);
- stmt->setUInt64(0, item->GetGUID().GetCounter());
- trans->Append(stmt);
-
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
- stmt->setUInt64(0, item->GetGUID().GetCounter());
- trans->Append(stmt);
+ item->DeleteFromInventoryDB(trans);
+ item->DeleteFromDB(trans);
m_items[i]->FSetState(ITEM_NEW);
}
@@ -20817,9 +20836,8 @@ void Player::_SaveMail(CharacterDatabaseTransaction& trans)
{
for (MailItemInfoVec::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2)
{
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
- stmt->setUInt64(0, itr2->item_guid);
- trans->Append(stmt);
+ Item::DeleteFromDB(trans, itr2->item_guid);
+ AzeriteItem::DeleteFromDB(trans, itr2->item_guid);
}
}
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_BY_ID);
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 68802a620d3..6a2592a0fe0 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2513,7 +2513,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void _LoadVoidStorage(PreparedQueryResult result);
void _LoadMailInit(PreparedQueryResult resultUnread, PreparedQueryResult resultDelivery);
void _LoadMail();
- void _LoadMailedItem(Mail* mail, Field* fields, ItemAdditionalLoadInfo* addionalData);
+ static Item* _LoadMailedItem(ObjectGuid const& playerGuid, Player* player, uint32 mailId, Mail* mail, Field* fields, ItemAdditionalLoadInfo* addionalData);
void _LoadQuestStatus(PreparedQueryResult result);
void _LoadQuestStatusObjectives(PreparedQueryResult result);
void _LoadQuestStatusRewarded(PreparedQueryResult result);
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index b37d3fadb49..61c7b168a40 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -18,6 +18,7 @@
#include "ObjectMgr.h"
#include "ArenaTeamMgr.h"
+#include "AzeriteItem.h"
#include "Chat.h"
#include "Containers.h"
#include "DatabaseEnv.h"
@@ -5867,12 +5868,12 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp)
// if it is mail from non-player, or if it's already return mail, it shouldn't be returned, but deleted
if (m->messageType != MAIL_NORMAL || (m->checked & (MAIL_CHECK_MASK_COD_PAYMENT | MAIL_CHECK_MASK_RETURNED)))
{
+ CharacterDatabaseTransaction nonTransactional(nullptr);
// mail open and then not returned
for (MailItemInfoVec::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2)
{
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
- stmt->setUInt64(0, itr2->item_guid);
- CharacterDatabase.Execute(stmt);
+ Item::DeleteFromDB(nonTransactional, itr2->item_guid);
+ AzeriteItem::DeleteFromDB(nonTransactional, itr2->item_guid);
}
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_ITEM_BY_ID);
diff --git a/src/server/game/Mails/Mail.cpp b/src/server/game/Mails/Mail.cpp
index aaad1e4fcdf..53d232d20cc 100644
--- a/src/server/game/Mails/Mail.cpp
+++ b/src/server/game/Mails/Mail.cpp
@@ -129,11 +129,7 @@ void MailDraft::deleteIncludedItems(CharacterDatabaseTransaction& trans, bool in
Item* item = mailItemIter->second;
if (inDB)
- {
- CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE);
- stmt->setUInt64(0, item->GetGUID().GetCounter());
- trans->Append(stmt);
- }
+ item->DeleteFromDB(trans);
delete item;
}