aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.cpp2
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.cpp2
-rw-r--r--src/server/game/Accounts/BattlenetAccountMgr.cpp7
-rw-r--r--src/server/game/Accounts/BattlenetAccountMgr.h2
-rw-r--r--src/server/game/Handlers/MailHandler.cpp285
5 files changed, 148 insertions, 150 deletions
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp
index 3d0631b5216..675036a5500 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp
@@ -121,7 +121,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_REPUTATION, "SELECT faction, standing, flags FROM character_reputation WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_INVENTORY, "SELECT " SelectItemInstanceContent ", bag, slot FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid WHERE ci.guid = ? ORDER BY (ii.flags & 0x80000) ASC, bag ASC, slot ASC", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_ACTIONS, "SELECT a.button, a.action, a.type FROM character_action as a, characters as c WHERE a.guid = c.guid AND a.spec = c.activeTalentGroup AND a.guid = ? ORDER BY button", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_MAIL_COUNT, "SELECT COUNT(*) FROM mail WHERE receiver = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_MAIL_COUNT, "SELECT COUNT(*) FROM mail WHERE receiver = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_SOCIALLIST, "SELECT cs.friend, c.account, cs.flags, cs.note FROM character_social cs JOIN characters c ON c.guid = cs.friend WHERE cs.guid = ? AND c.deleteinfos_name IS NULL LIMIT 255", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_HOMEBIND, "SELECT mapId, zoneId, posX, posY, posZ, orientation FROM character_homebind WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_SPELLCOOLDOWNS, "SELECT spell, item, time, categoryId, categoryEnd FROM character_spell_cooldown WHERE guid = ? AND time > UNIX_TIMESTAMP()", CONNECTION_ASYNC);
diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp
index 09372319688..f02ad1a4e68 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/database/Database/Implementation/LoginDatabase.cpp
@@ -141,7 +141,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_BNET_CHECK_PASSWORD, "SELECT 1 FROM battlenet_accounts WHERE id = ? AND sha_pass_hash = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_UPD_BNET_ACCOUNT_LOCK, "UPDATE battlenet_accounts SET locked = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_ACCOUNT_LOCK_CONTRY, "UPDATE battlenet_accounts SET lock_country = ? WHERE id = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_GAME_ACCOUNT, "SELECT battlenet_account FROM account WHERE id = ?", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_GAME_ACCOUNT, "SELECT battlenet_account FROM account WHERE id = ?", CONNECTION_BOTH);
PrepareStatement(LOGIN_UPD_BNET_GAME_ACCOUNT_LINK, "UPDATE account SET battlenet_account = ?, battlenet_index = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_BNET_MAX_ACCOUNT_INDEX, "SELECT MAX(battlenet_index) FROM account WHERE battlenet_account = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_BNET_GAME_ACCOUNT_LIST_SMALL, "SELECT a.id, a.username FROM account a LEFT JOIN battlenet_accounts ba ON a.battlenet_account = ba.id WHERE ba.email = ?", CONNECTION_SYNCH);
diff --git a/src/server/game/Accounts/BattlenetAccountMgr.cpp b/src/server/game/Accounts/BattlenetAccountMgr.cpp
index a204e99f337..08a807b8db6 100644
--- a/src/server/game/Accounts/BattlenetAccountMgr.cpp
+++ b/src/server/game/Accounts/BattlenetAccountMgr.cpp
@@ -161,6 +161,13 @@ uint32 Battlenet::AccountMgr::GetIdByGameAccount(uint32 gameAccountId)
return 0;
}
+QueryCallback Battlenet::AccountMgr::GetIdByGameAccountAsync(uint32 gameAccountId)
+{
+ LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_GAME_ACCOUNT);
+ stmt->setUInt32(0, gameAccountId);
+ return LoginDatabase.AsyncQuery(stmt);
+}
+
uint8 Battlenet::AccountMgr::GetMaxIndex(uint32 accountId)
{
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_MAX_ACCOUNT_INDEX);
diff --git a/src/server/game/Accounts/BattlenetAccountMgr.h b/src/server/game/Accounts/BattlenetAccountMgr.h
index 43c60c5b006..bfeb02302f7 100644
--- a/src/server/game/Accounts/BattlenetAccountMgr.h
+++ b/src/server/game/Accounts/BattlenetAccountMgr.h
@@ -21,6 +21,7 @@
#include "Define.h"
#include <string>
+class QueryCallback;
enum class AccountOpResult : uint8;
#define MAX_BNET_EMAIL_STR 320
@@ -38,6 +39,7 @@ namespace Battlenet
TC_GAME_API uint32 GetId(std::string_view username);
TC_GAME_API bool GetName(uint32 accountId, std::string& name);
TC_GAME_API uint32 GetIdByGameAccount(uint32 gameAccountId);
+ [[nodiscard]] TC_GAME_API QueryCallback GetIdByGameAccountAsync(uint32 gameAccountId);
TC_GAME_API uint8 GetMaxIndex(uint32 accountId);
TC_GAME_API std::string CalculateShaPassHash(std::string_view name, std::string_view password);
diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp
index 6959405c23b..410726ec394 100644
--- a/src/server/game/Handlers/MailHandler.cpp
+++ b/src/server/game/Handlers/MailHandler.cpp
@@ -144,201 +144,190 @@ void WorldSession::HandleSendMail(WorldPackets::Mail::SendMail& sendMail)
return;
}
- Player* receiver = ObjectAccessor::FindConnectedPlayer(receiverGuid);
-
- uint32 receiverTeam = 0;
- uint8 mailsCount = 0; //do not allow to send to one player more than 100 mails
- uint8 receiverLevel = 0;
- uint32 receiverAccountId = 0;
- uint32 receiverBnetAccountId = 0;
-
- if (receiver)
+ auto mailCountCheckContinuation = [this, player = _player, receiverGuid, mailInfo = std::move(sendMail.Info), reqmoney, cost](uint32 receiverTeam, uint64 mailsCount, uint8 receiverLevel, uint32 receiverAccountId, uint32 receiverBnetAccountId) mutable
{
- receiverTeam = receiver->GetTeam();
- mailsCount = receiver->GetMailSize();
- receiverLevel = receiver->GetLevel();
- receiverAccountId = receiver->GetSession()->GetAccountId();
- receiverBnetAccountId = receiver->GetSession()->GetBattlenetAccountId();
- }
- else
- {
- if (CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(receiverGuid))
- {
- receiverTeam = Player::TeamForRace(characterInfo->Race);
- receiverLevel = characterInfo->Level;
- receiverAccountId = characterInfo->AccountId;
- }
-
- CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_COUNT);
- stmt->setUInt64(0, receiverGuid.GetCounter());
+ if (_player != player)
+ return;
- PreparedQueryResult result = CharacterDatabase.Query(stmt);
- if (result)
+ // do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255..
+ if (mailsCount > 100)
{
- Field* fields = result->Fetch();
- mailsCount = fields[0].GetUInt64();
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_CAP_REACHED);
+ return;
}
- receiverBnetAccountId = Battlenet::AccountMgr::GetIdByGameAccount(receiverAccountId);
- }
-
- // do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255..
- if (mailsCount > 100)
- {
- player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_CAP_REACHED);
- return;
- }
-
- // test the receiver's Faction... or all items are account bound
- bool accountBound = !sendMail.Info.Attachments.empty();
- for (auto const& att : sendMail.Info.Attachments)
- {
- if (Item* item = player->GetItemByGuid(att.ItemGUID))
+ // test the receiver's Faction... or all items are account bound
+ bool accountBound = !mailInfo.Attachments.empty();
+ for (auto const& att : mailInfo.Attachments)
{
- ItemTemplate const* itemProto = item->GetTemplate();
- if (!itemProto || !itemProto->HasFlag(ITEM_FLAG_IS_BOUND_TO_ACCOUNT))
+ if (Item* item = player->GetItemByGuid(att.ItemGUID))
{
- accountBound = false;
- break;
+ ItemTemplate const* itemProto = item->GetTemplate();
+ if (!itemProto || !itemProto->HasFlag(ITEM_FLAG_IS_BOUND_TO_ACCOUNT))
+ {
+ accountBound = false;
+ break;
+ }
}
}
- }
- if (!accountBound && player->GetTeam() != receiverTeam && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_MAIL))
- {
- player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM);
- return;
- }
-
- if (receiverLevel < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ))
- {
- SendNotification(GetTrinityString(LANG_MAIL_RECEIVER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ));
- return;
- }
-
- std::vector<Item*> items;
-
- for (auto const& att : sendMail.Info.Attachments)
- {
- if (att.ItemGUID.IsEmpty())
+ if (!accountBound && player->GetTeam() != receiverTeam && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_MAIL))
{
- player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID);
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_YOUR_TEAM);
return;
}
- Item* item = player->GetItemByGuid(att.ItemGUID);
-
- // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail)
- if (!item)
+ if (receiverLevel < sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ))
{
- player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID);
+ SendNotification(GetTrinityString(LANG_MAIL_RECEIVER_REQ), sWorld->getIntConfig(CONFIG_MAIL_LEVEL_REQ));
return;
}
- if (!item->CanBeTraded(true))
- {
- player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM);
- return;
- }
+ std::vector<Item*> items;
- if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != receiverAccountId)
+ for (auto const& att : mailInfo.Attachments)
{
- if (!item->IsBattlenetAccountBound() || !player->GetSession()->GetBattlenetAccountId() || player->GetSession()->GetBattlenetAccountId() != receiverBnetAccountId)
+ if (att.ItemGUID.IsEmpty())
{
- player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_NOT_SAME_ACCOUNT);
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID);
return;
}
- }
- if (item->GetTemplate()->HasFlag(ITEM_FLAG_CONJURED) || *item->m_itemData->Expiration)
- {
- player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM);
- return;
- }
+ Item* item = player->GetItemByGuid(att.ItemGUID);
- if (sendMail.Info.Cod && item->IsWrapped())
- {
- player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD);
- return;
- }
+ // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail)
+ if (!item)
+ {
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID);
+ return;
+ }
- if (item->IsNotEmptyBag())
- {
- player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_DESTROY_NONEMPTY_BAG);
- return;
- }
+ if (!item->CanBeTraded(true))
+ {
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM);
+ return;
+ }
- items.push_back(item);
- }
+ if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != receiverAccountId)
+ {
+ if (!item->IsBattlenetAccountBound() || !player->GetSession()->GetBattlenetAccountId() || player->GetSession()->GetBattlenetAccountId() != receiverBnetAccountId)
+ {
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_NOT_SAME_ACCOUNT);
+ return;
+ }
+ }
+
+ if (item->GetTemplate()->HasFlag(ITEM_FLAG_CONJURED) || *item->m_itemData->Expiration)
+ {
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_MAIL_BOUND_ITEM);
+ return;
+ }
+
+ if (mailInfo.Cod && item->IsWrapped())
+ {
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD);
+ return;
+ }
+
+ if (item->IsNotEmptyBag())
+ {
+ player->SendMailResult(0, MAIL_SEND, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_DESTROY_NONEMPTY_BAG);
+ return;
+ }
- player->SendMailResult(0, MAIL_SEND, MAIL_OK);
+ items.push_back(item);
+ }
- player->ModifyMoney(-reqmoney);
- player->UpdateCriteria(CriteriaType::MoneySpentOnPostage, cost);
+ player->SendMailResult(0, MAIL_SEND, MAIL_OK);
- bool needItemDelay = false;
+ player->ModifyMoney(-reqmoney);
+ player->UpdateCriteria(CriteriaType::MoneySpentOnPostage, cost);
- MailDraft draft(sendMail.Info.Subject, sendMail.Info.Body);
+ bool needItemDelay = false;
- CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
+ MailDraft draft(mailInfo.Subject, mailInfo.Body);
- if (!sendMail.Info.Attachments.empty() || sendMail.Info.SendMoney > 0)
- {
- bool log = HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE);
- if (!sendMail.Info.Attachments.empty())
+ CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
+
+ if (!mailInfo.Attachments.empty() || mailInfo.SendMoney > 0)
{
- for (auto const& item : items)
+ bool log = HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE);
+ if (!mailInfo.Attachments.empty())
{
- if (log)
+ for (auto const& item : items)
{
- sLog->outCommand(GetAccountId(), "GM %s (%s) (Account: %u) mail item: %s (Entry: %u Count: %u) "
- "to: %s (%s) (Account: %u)", GetPlayerName().c_str(), _player->GetGUID().ToString().c_str(), GetAccountId(),
- item->GetTemplate()->GetDefaultLocaleName(), item->GetEntry(), item->GetCount(),
- sendMail.Info.Target.c_str(), receiverGuid.ToString().c_str(), receiverAccountId);
- }
+ if (log)
+ {
+ sLog->outCommand(GetAccountId(), "GM %s (%s) (Account: %u) mail item: %s (Entry: %u Count: %u) "
+ "to: %s (%s) (Account: %u)", GetPlayerName().c_str(), _player->GetGUID().ToString().c_str(), GetAccountId(),
+ item->GetTemplate()->GetDefaultLocaleName(), item->GetEntry(), item->GetCount(),
+ mailInfo.Target.c_str(), receiverGuid.ToString().c_str(), receiverAccountId);
+ }
+
+ item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable
+ player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true);
+
+ item->DeleteFromInventoryDB(trans); // deletes item from character's inventory
+ item->SetOwnerGUID(receiverGuid);
+ item->SetState(ITEM_CHANGED);
+ item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone
- item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable
- player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true);
-
- item->DeleteFromInventoryDB(trans); // deletes item from character's inventory
- item->SetOwnerGUID(receiverGuid);
- item->SetState(ITEM_CHANGED);
- item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone
+ draft.AddItem(item);
+ }
- draft.AddItem(item);
+ // if item send to character at another account, then apply item delivery delay
+ needItemDelay = player->GetSession()->GetAccountId() != receiverAccountId;
}
- // if item send to character at another account, then apply item delivery delay
- needItemDelay = player->GetSession()->GetAccountId() != receiverAccountId;
+ if (log && mailInfo.SendMoney > 0)
+ {
+ sLog->outCommand(GetAccountId(), "GM %s (%s) (Account: %u) mail money: " SI64FMTD " to: %s (%s) (Account: %u)",
+ GetPlayerName().c_str(), _player->GetGUID().ToString().c_str(), GetAccountId(), mailInfo.SendMoney, mailInfo.Target.c_str(), receiverGuid.ToString().c_str(), receiverAccountId);
+ }
}
- if (log && sendMail.Info.SendMoney > 0)
- {
- sLog->outCommand(GetAccountId(), "GM %s (%s) (Account: %u) mail money: " SI64FMTD " to: %s (%s) (Account: %u)",
- GetPlayerName().c_str(), _player->GetGUID().ToString().c_str(), GetAccountId(), sendMail.Info.SendMoney, sendMail.Info.Target.c_str(), receiverGuid.ToString().c_str(), receiverAccountId);
- }
- }
+ // If theres is an item, there is a one hour delivery delay if sent to another account's character.
+ uint32 deliver_delay = needItemDelay ? sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0;
+
+ // Mail sent between guild members arrives instantly
+ if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId()))
+ if (guild->IsMember(receiverGuid))
+ deliver_delay = 0;
- // If theres is an item, there is a one hour delivery delay if sent to another account's character.
- uint32 deliver_delay = needItemDelay ? sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0;
+ // don't ask for COD if there are no items
+ if (mailInfo.Attachments.empty())
+ mailInfo.Cod = 0;
- // Mail sent between guild members arrives instantly
- if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId()))
- if (guild->IsMember(receiverGuid))
- deliver_delay = 0;
+ // will delete item or place to receiver mail list
+ draft
+ .AddMoney(mailInfo.SendMoney)
+ .AddCOD(mailInfo.Cod)
+ .SendMailTo(trans, MailReceiver(ObjectAccessor::FindConnectedPlayer(receiverGuid), receiverGuid.GetCounter()), MailSender(player), mailInfo.Body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay);
- // don't ask for COD if there are no items
- if (sendMail.Info.Attachments.empty())
- sendMail.Info.Cod = 0;
+ player->SaveInventoryAndGoldToDB(trans);
+ CharacterDatabase.CommitTransaction(trans);
+ };
- // will delete item or place to receiver mail list
- draft
- .AddMoney(sendMail.Info.SendMoney)
- .AddCOD(sendMail.Info.Cod)
- .SendMailTo(trans, MailReceiver(receiver, receiverGuid.GetCounter()), MailSender(player), sendMail.Info.Body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay);
+ if (Player* receiver = ObjectAccessor::FindConnectedPlayer(receiverGuid))
+ {
+ mailCountCheckContinuation(receiver->GetTeam(), receiver->GetMailSize(), receiver->GetLevel(), receiver->GetSession()->GetAccountId(), receiver->GetSession()->GetBattlenetAccountId());
+ }
+ else
+ {
+ CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_COUNT);
+ stmt->setUInt64(0, receiverGuid.GetCounter());
- player->SaveInventoryAndGoldToDB(trans);
- CharacterDatabase.CommitTransaction(trans);
+ GetQueryProcessor().AddCallback(CharacterDatabase.AsyncQuery(stmt)
+ .WithChainingPreparedCallback([continuation = std::move(mailCountCheckContinuation), receiverGuid](QueryCallback& queryCallback, PreparedQueryResult mailCountResult) mutable
+ {
+ if (CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(receiverGuid))
+ queryCallback.WithPreparedCallback([continuation = std::move(continuation), characterInfo, mailCountResult](PreparedQueryResult bnetAccountResult) mutable
+ {
+ continuation(Player::TeamForRace(characterInfo->Race), mailCountResult ? (*mailCountResult)[0].GetUInt64() : UI64LIT(0),
+ characterInfo->Level, characterInfo->AccountId, bnetAccountResult ? (*bnetAccountResult)[0].GetUInt32() : 0);
+ }).SetNextQuery(Battlenet::AccountMgr::GetIdByGameAccountAsync(characterInfo->AccountId));
+ }));
+ }
}
//called when mail is read