95 TC_LOG_INFO(
"network",
"Player {} is sending mail to {} (GUID: non-existing!) with subject {} "
96 "and body {} includes {} items, {} copper and {} COD copper with StationeryID = {}",
106 TC_LOG_WARN(
"cheat",
"Player {} attempted to send mail to {} ({}) with negative money value (SendMoney: {})",
114 TC_LOG_WARN(
"cheat",
"Player {} attempted to send mail to {} ({}) with negative COD value (Cod: {})",
119 TC_LOG_INFO(
"network",
"Player {} is sending mail to {} ({}) with subject {} and body {} "
120 "includes {} items, {} copper and " SI64FMTD " COD copper with StationeryID = {}",
124 if (player->
GetGUID() == receiverGuid)
141 auto mailCountCheckContinuation = [
this, player =
_player, receiverGuid, mailInfo = std::move(sendMail.
Info), reqmoney, cost](
Team receiverTeam,
uint64 mailsCount,
uint8 receiverLevel,
uint32 receiverAccountId,
uint32 receiverBnetAccountId)
mutable
153 if (mailsCount > 100)
160 bool accountBound = !mailInfo.Attachments.empty();
168 accountBound =
false;
186 std::vector<Item*> items;
239 items.push_back(item);
247 bool needItemDelay =
false;
249 MailDraft draft(mailInfo.Subject, mailInfo.Body);
253 if (!mailInfo.Attachments.empty() || mailInfo.SendMoney > 0)
256 if (!mailInfo.Attachments.empty())
258 for (
auto const& item : items)
262 sLog->OutCommand(
GetAccountId(),
"GM {} ({}) (Account: {}) mail item: {} (Entry: {} Count: {}) "
264 item->GetTemplate()->GetDefaultLocaleName(), item->GetEntry(), item->GetCount(),
265 mailInfo.Target, receiverGuid.
ToString(), receiverAccountId);
271 item->DeleteFromInventoryDB(trans);
272 item->SetOwnerGUID(receiverGuid);
274 item->SaveToDB(trans);
283 if (log && mailInfo.SendMoney > 0)
285 sLog->OutCommand(
GetAccountId(),
"GM {} ({}) (Account: {}) mail money: {} to: {} ({}) (Account: {})",
295 if (guild->IsMember(receiverGuid))
299 if (mailInfo.Attachments.empty())
314 mailCountCheckContinuation(receiver->GetTeam(), receiver->GetMailSize(), receiver->GetLevel(), receiver->GetSession()->GetAccountId(), receiver->GetSession()->GetBattlenetAccountId());
322 .WithChainingPreparedCallback([continuation = std::move(mailCountCheckContinuation), receiverGuid](
QueryCallback& queryCallback,
PreparedQueryResult mailCountResult)
mutable
324 if (CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(receiverGuid))
325 queryCallback.WithPreparedCallback([continuation = std::move(continuation), characterInfo, mailCountResult](PreparedQueryResult bnetAccountResult) mutable
327 continuation(Player::TeamForRace(characterInfo->Race), mailCountResult ? (*mailCountResult)[0].GetUInt64() : UI64LIT(0),
328 characterInfo->Level, characterInfo->AccountId, bnetAccountResult ? (*bnetAccountResult)[0].GetUInt32() : 0);
406 for (MailItemInfoVec::iterator itr2 = m->
items.begin(); itr2 != m->
items.end(); ++itr2)
408 if (
Item*
const item = player->
GetMItem(itr2->item_guid))
440 if (std::find_if(m->
items.begin(), m->
items.end(), [AttachID](
MailItemInfo info){ return info.item_guid == AttachID; }) == m->
items.end())
472 std::string sender_name;
476 sender_name = receiver->
GetName();
481 sender_accId =
sCharacterCache->GetCharacterAccountIdByGuid(sender_guid);
483 if (!
sCharacterCache->GetCharacterNameByGuid(sender_guid, sender_name))
486 sLog->OutCommand(
GetAccountId(),
"GM {} (Account: {}) receiver mail item: {} (Entry: {} Count: {}) and send COD money: {} to player: {} (Account: {})",
490 sender_accId =
sCharacterCache->GetCharacterAccountIdByGuid(sender_guid);
493 if (receiver || sender_accId)
573 if (response.
Mails.size() < 100)
574 response.
Mails.emplace_back(m, player);
610 ASSERT(mailTemplateEntry);
648 std::set<ObjectGuid::LowType> sentSenders;
656 if (now < mail->deliver_time)
660 if (sentSenders.count(mail->sender))
663 result.
Next.emplace_back(mail);
665 sentSenders.insert(mail->sender);
668 if (sentSenders.size() > 2)
@ CHAR_DEL_MAIL_ITEM_BY_ID
DB2Storage< MailTemplateEntry > sMailTemplateStore("MailTemplate.db2", &MailTemplateLoadInfo::Instance)
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
@ EQUIP_ERR_TOO_MUCH_GOLD
@ EQUIP_ERR_MAIL_BOUND_ITEM
@ EQUIP_ERR_DESTROY_NONEMPTY_BAG
@ EQUIP_ERR_NOT_SAME_ACCOUNT
@ ITEM_FIELD_FLAG_READABLE
@ ITEM_FLAG_IS_BOUND_TO_ACCOUNT
#define TC_LOG_WARN(filterType__,...)
#define TC_LOG_INFO(filterType__,...)
@ MAIL_CHECK_MASK_HAS_BODY
@ MAIL_CHECK_MASK_COD_PAYMENT
This mail was copied. Do not allow making a copy of items in mail.
@ MAIL_CHECK_MASK_COPIED
This mail was returned. Do not allow returning mail back again.
#define MAIL_BODY_ITEM_TEMPLATE
#define MAX_CLIENT_MAIL_ITEMS
bool normalizePlayerName(std::string &name)
std::vector< ItemPosCount > ItemPosCountVec
@ GAMEOBJECT_TYPE_MAILBOX
@ MAIL_RETURNED_TO_SENDER
@ MAIL_ERR_NOT_ENOUGH_MONEY
@ MAIL_ERR_CANT_SEND_WRAPPED_COD
@ MAIL_ERR_RECIPIENT_CAP_REACHED
@ MAIL_ERR_RECIPIENT_NOT_FOUND
@ MAIL_ERR_TOO_MANY_ATTACHMENTS
@ MAIL_ERR_MAIL_ATTACHMENT_INVALID
@ MAIL_ERR_INTERNAL_ERROR
@ MAIL_ERR_CANNOT_SEND_TO_SELF
T & AddCallback(T &&query)
void SetState(ItemUpdateState state, Player *forplayer=nullptr)
void SetItemFlag(ItemFieldFlags flags)
void SetText(std::string const &text)
bool IsBoundAccountWide() const
bool CanBeTraded(bool mail=false, bool trade=false) const
ItemTemplate const * GetTemplate() const
bool IsBattlenetAccountBound() const
void SetCreator(ObjectGuid guid)
bool IsNotEmptyBag() const
UF::UpdateField< UF::ItemData, 0, TYPEID_ITEM > m_itemData
static Item * CreateItem(uint32 itemEntry, uint32 count, ItemContext context, Player const *player=nullptr, bool addDefaultBonuses=true)
void SendMailTo(CharacterDatabaseTransaction trans, MailReceiver const &receiver, MailSender const &sender, MailCheckMask checked=MAIL_CHECK_MASK_NONE, uint32 deliver_delay=0)
MailDraft & AddCOD(uint64 COD)
void SendReturnToSender(uint32 sender_acc, ObjectGuid::LowType sender_guid, ObjectGuid::LowType receiver_guid, CharacterDatabaseTransaction trans)
MailDraft & AddItem(Item *item)
MailDraft & AddMoney(uint64 money)
LowType GetCounter() const
std::string ToString() const
bool IsGameObject() const
bool IsAnyTypeCreature() const
static ObjectGuid GetGUID(Object const *o)
void UpdateNextMailTimeAndUnreads()
bool ModifyMoney(int64 amount, bool sendError=true)
Creature * GetNPCIfCanInteractWith(ObjectGuid const &guid, NPCFlags npcFlags, NPCFlags2 npcFlags2) const
Item * GetMItem(ObjectGuid::LowType id)
void SendMailResult(uint64 mailId, MailResponseType mailAction, MailResponseResult mailError, uint32 equipError=0, ObjectGuid::LowType itemGuid=UI64LIT(0), uint32 itemCount=0) const
InventoryResult CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *pItem, bool swap=false) const
void SaveInventoryAndGoldToDB(CharacterDatabaseTransaction trans)
GameObject * GetGameObjectIfCanInteractWith(ObjectGuid const &guid) const
Item * StoreItem(ItemPosCountVec const &pos, Item *pItem, bool update)
WorldSession * GetSession() const
PlayerMails const & GetMails() const
void MoveItemFromInventory(uint8 bag, uint8 slot, bool update)
void UpdateCriteria(CriteriaType type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, WorldObject *ref=nullptr)
void MoveItemToInventory(ItemPosCountVec const &dest, Item *pItem, bool update, bool in_characterInventoryDB=false)
void _SaveMail(CharacterDatabaseTransaction trans)
ObjectGuid::LowType GetGuildId() const
bool RemoveMItem(ObjectGuid::LowType id)
bool IsGameMaster() const
Mail * GetMail(uint64 id)
Item * GetItemByGuid(ObjectGuid guid) const
void RemoveMail(uint64 id)
std::unique_ptr< PlayerMenu > PlayerTalkClass
bool HasEnoughMoney(uint64 amount) const
void setUInt64(const uint8 index, const uint64 value)
std::string const & GetName() const
WorldPacket const * Write() override
std::vector< MailListEntry > Mails
WorldPacket const * Write() override
std::vector< MailNextTimeEntry > Next
char const * GetTrinityString(uint32 entry) const
void SendNotification(char const *format,...) ATTR_PRINTF(2
LocaleConstant GetSessionDbcLocale() const
std::string GetPlayerInfo() const
void HandleSendMail(WorldPackets::Mail::SendMail &sendMail)
Player * GetPlayer() const
bool CanOpenMailBox(ObjectGuid guid)
void HandleMailDelete(WorldPackets::Mail::MailDelete &mailDelete)
QueryCallbackProcessor & GetQueryProcessor()
void HandleMailTakeItem(WorldPackets::Mail::MailTakeItem &takeItem)
void HandleQueryNextMailTime(WorldPackets::Mail::MailQueryNextMailTime &queryNextMailTime)
void HandleMailMarkAsRead(WorldPackets::Mail::MailMarkAsRead &markAsRead)
bool HasPermission(uint32 permissionId)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
uint32 GetBattlenetAccountId() const
void HandleMailReturnToSender(WorldPackets::Mail::MailReturnToSender &returnToSender)
uint32 GetAccountId() const
void HandleMailCreateTextItem(WorldPackets::Mail::MailCreateTextItem &createTextItem)
void HandleMailTakeMoney(WorldPackets::Mail::MailTakeMoney &takeMoney)
void HandleGetMailList(WorldPackets::Mail::MailGetList &getList)
std::string const & GetPlayerName() const
bool ValidateHyperlinksAndMaybeKick(std::string const &str)
@ CONFIG_MAIL_DELIVERY_DELAY
TC_GAME_API QueryCallback GetIdByGameAccountAsync(uint32 gameAccountId)
TC_GAME_API Player * FindConnectedPlayer(ObjectGuid const &)
@ RBAC_PERM_TWO_SIDE_INTERACTION_MAIL
@ RBAC_PERM_COMMAND_MAILBOX
bool HasFlag(ItemFlags flag) const
char const * GetDefaultLocaleName() const
ObjectGuid::LowType receiver
ObjectGuid::LowType sender
std::vector< ObjectGuid::LowType > removedItems
std::vector< MailItemInfo > items
bool RemoveItem(ObjectGuid::LowType item_guid)
std::vector< MailAttachment > Attachments