Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
MailHandler.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "AccountMgr.h"
7#include "DatabaseEnv.h"
8#include "DBCStores.h"
9#include "GuildMgr.h"
10#include "Item.h"
11#include "Language.h"
12#include "Log.h"
13#include "Mail.h"
14#include "ObjectMgr.h"
15#include "Opcodes.h"
16#include "Player.h"
17#include "World.h"
18#include "WorldPacket.h"
19#include "WorldSession.h"
20
21namespace
22{
23struct SendMailRequest
24{
25 ObjectGuid mailbox;
26 ObjectGuid itemGuids[MAX_MAIL_ITEMS];
27 uint64 money;
28 uint64 COD;
29 std::string receiverName;
30 std::string subject;
31 std::string body;
32 uint32 unk1;
33 uint32 unk2;
34 uint8 itemCount;
35};
36
37struct MailDeleteRequest
38{
39 uint32 mailId;
40};
41
42struct MailboxMailRequest
43{
44 ObjectGuid mailbox;
45 uint32 mailId;
46};
47
48struct MailTakeItemRequest
49{
50 ObjectGuid mailbox;
51 uint32 mailId;
52 uint32 itemId;
53};
54
55struct MailTakeMoneyRequest
56{
57 ObjectGuid mailbox;
58 uint64 money;
59 uint32 mailId;
60};
61
62struct MailboxRequest
63{
64 ObjectGuid mailbox;
65};
66
67bool ReadSendMailRequest(WorldPacket& recvData, SendMailRequest& request)
68{
69 uint32 bodyLength;
70 uint32 subjectLength;
71 uint32 receiverLength;
72
73 recvData >> request.unk1 >> request.unk2; // both unknown
74 recvData >> request.COD >> request.money; // money and cod
75
76 request.mailbox[0] = recvData.ReadBit();
77 request.mailbox[6] = recvData.ReadBit();
78 request.mailbox[4] = recvData.ReadBit();
79 request.mailbox[1] = recvData.ReadBit();
80 bodyLength = recvData.ReadBits(11);
81 request.mailbox[3] = recvData.ReadBit();
82 receiverLength = recvData.ReadBits(9);
83 request.mailbox[7] = recvData.ReadBit();
84 request.mailbox[5] = recvData.ReadBit();
85
86 uint32 itemCount = recvData.ReadBits(5); // attached items count
87 if (itemCount > MAX_MAIL_ITEMS) // client limit
88 return false;
89
90 request.itemCount = uint8(itemCount);
91
92 for (uint8 i = 0; i < request.itemCount; ++i)
93 {
94 request.itemGuids[i][1] = recvData.ReadBit();
95 request.itemGuids[i][7] = recvData.ReadBit();
96 request.itemGuids[i][2] = recvData.ReadBit();
97 request.itemGuids[i][5] = recvData.ReadBit();
98 request.itemGuids[i][0] = recvData.ReadBit();
99 request.itemGuids[i][6] = recvData.ReadBit();
100 request.itemGuids[i][3] = recvData.ReadBit();
101 request.itemGuids[i][4] = recvData.ReadBit();
102 }
103
104 subjectLength = recvData.ReadBits(9);
105 request.mailbox[2] = recvData.ReadBit();
106
107 for (uint8 i = 0; i < request.itemCount; ++i)
108 {
109 recvData.read_skip<uint8>(); // item slot in mail, not used
110 recvData.ReadByteSeq(request.itemGuids[i][3]);
111 recvData.ReadByteSeq(request.itemGuids[i][0]);
112 recvData.ReadByteSeq(request.itemGuids[i][2]);
113 recvData.ReadByteSeq(request.itemGuids[i][1]);
114 recvData.ReadByteSeq(request.itemGuids[i][6]);
115 recvData.ReadByteSeq(request.itemGuids[i][5]);
116 recvData.ReadByteSeq(request.itemGuids[i][7]);
117 recvData.ReadByteSeq(request.itemGuids[i][4]);
118 }
119
120 recvData.ReadByteSeq(request.mailbox[1]);
121 request.body = recvData.ReadString(bodyLength);
122 recvData.ReadByteSeq(request.mailbox[0]);
123 request.subject = recvData.ReadString(subjectLength);
124 recvData.ReadByteSeq(request.mailbox[2]);
125 recvData.ReadByteSeq(request.mailbox[6]);
126 recvData.ReadByteSeq(request.mailbox[5]);
127 recvData.ReadByteSeq(request.mailbox[7]);
128 recvData.ReadByteSeq(request.mailbox[3]);
129 recvData.ReadByteSeq(request.mailbox[4]);
130 request.receiverName = recvData.ReadString(receiverLength);
131
132 return true;
133}
134
135MailboxMailRequest ReadMailMarkAsReadRequest(WorldPacket& recvData)
136{
137 MailboxMailRequest request;
138 recvData >> request.mailId;
139
140 request.mailbox[0] = recvData.ReadBit();
141 request.mailbox[2] = recvData.ReadBit();
142 request.mailbox[3] = recvData.ReadBit();
143 recvData.ReadBit();
144 request.mailbox[4] = recvData.ReadBit();
145 request.mailbox[6] = recvData.ReadBit();
146 request.mailbox[7] = recvData.ReadBit();
147 request.mailbox[1] = recvData.ReadBit();
148 request.mailbox[5] = recvData.ReadBit();
149 recvData.FlushBits();
150
151 recvData.ReadByteSeq(request.mailbox[1]);
152 recvData.ReadByteSeq(request.mailbox[7]);
153 recvData.ReadByteSeq(request.mailbox[2]);
154 recvData.ReadByteSeq(request.mailbox[5]);
155 recvData.ReadByteSeq(request.mailbox[6]);
156 recvData.ReadByteSeq(request.mailbox[3]);
157 recvData.ReadByteSeq(request.mailbox[4]);
158 recvData.ReadByteSeq(request.mailbox[0]);
159
160 return request;
161}
162
163MailDeleteRequest ReadMailDeleteRequest(WorldPacket& recvData)
164{
165 MailDeleteRequest request;
166 recvData >> request.mailId;
167 recvData.read_skip<uint32>(); // mailTemplateId
168 return request;
169}
170
171MailboxMailRequest ReadMailReturnToSenderRequest(WorldPacket& recvData)
172{
173 MailboxMailRequest request;
174 recvData >> request.mailId;
175
176 request.mailbox[2] = recvData.ReadBit();
177 request.mailbox[0] = recvData.ReadBit();
178 request.mailbox[4] = recvData.ReadBit();
179 request.mailbox[6] = recvData.ReadBit();
180 request.mailbox[3] = recvData.ReadBit();
181 request.mailbox[1] = recvData.ReadBit();
182 request.mailbox[7] = recvData.ReadBit();
183 request.mailbox[5] = recvData.ReadBit();
184
185 recvData.ReadByteSeq(request.mailbox[5]);
186 recvData.ReadByteSeq(request.mailbox[6]);
187 recvData.ReadByteSeq(request.mailbox[2]);
188 recvData.ReadByteSeq(request.mailbox[0]);
189 recvData.ReadByteSeq(request.mailbox[3]);
190 recvData.ReadByteSeq(request.mailbox[1]);
191 recvData.ReadByteSeq(request.mailbox[4]);
192 recvData.ReadByteSeq(request.mailbox[7]);
193
194 return request;
195}
196
197MailTakeItemRequest ReadMailTakeItemRequest(WorldPacket& recvData)
198{
199 MailTakeItemRequest request;
200 recvData >> request.mailId;
201 recvData >> request.itemId;
202
203 request.mailbox[6] = recvData.ReadBit();
204 request.mailbox[5] = recvData.ReadBit();
205 request.mailbox[2] = recvData.ReadBit();
206 request.mailbox[3] = recvData.ReadBit();
207 request.mailbox[0] = recvData.ReadBit();
208 request.mailbox[1] = recvData.ReadBit();
209 request.mailbox[4] = recvData.ReadBit();
210 request.mailbox[7] = recvData.ReadBit();
211
212 recvData.ReadByteSeq(request.mailbox[0]);
213 recvData.ReadByteSeq(request.mailbox[1]);
214 recvData.ReadByteSeq(request.mailbox[4]);
215 recvData.ReadByteSeq(request.mailbox[2]);
216 recvData.ReadByteSeq(request.mailbox[5]);
217 recvData.ReadByteSeq(request.mailbox[6]);
218 recvData.ReadByteSeq(request.mailbox[3]);
219 recvData.ReadByteSeq(request.mailbox[7]);
220
221 return request;
222}
223
224MailTakeMoneyRequest ReadMailTakeMoneyRequest(WorldPacket& recvData)
225{
226 MailTakeMoneyRequest request;
227 recvData >> request.mailId;
228 recvData >> request.money;
229
230 request.mailbox[7] = recvData.ReadBit();
231 request.mailbox[6] = recvData.ReadBit();
232 request.mailbox[3] = recvData.ReadBit();
233 request.mailbox[2] = recvData.ReadBit();
234 request.mailbox[4] = recvData.ReadBit();
235 request.mailbox[5] = recvData.ReadBit();
236 request.mailbox[0] = recvData.ReadBit();
237 request.mailbox[1] = recvData.ReadBit();
238
239 recvData.ReadByteSeq(request.mailbox[7]);
240 recvData.ReadByteSeq(request.mailbox[1]);
241 recvData.ReadByteSeq(request.mailbox[4]);
242 recvData.ReadByteSeq(request.mailbox[0]);
243 recvData.ReadByteSeq(request.mailbox[3]);
244 recvData.ReadByteSeq(request.mailbox[2]);
245 recvData.ReadByteSeq(request.mailbox[6]);
246 recvData.ReadByteSeq(request.mailbox[5]);
247
248 return request;
249}
250
251MailboxRequest ReadGetMailListRequest(WorldPacket& recvData)
252{
253 MailboxRequest request;
254
255 request.mailbox[6] = recvData.ReadBit();
256 request.mailbox[3] = recvData.ReadBit();
257 request.mailbox[7] = recvData.ReadBit();
258 request.mailbox[5] = recvData.ReadBit();
259 request.mailbox[4] = recvData.ReadBit();
260 request.mailbox[1] = recvData.ReadBit();
261 request.mailbox[2] = recvData.ReadBit();
262 request.mailbox[0] = recvData.ReadBit();
263
264 recvData.ReadByteSeq(request.mailbox[7]);
265 recvData.ReadByteSeq(request.mailbox[1]);
266 recvData.ReadByteSeq(request.mailbox[6]);
267 recvData.ReadByteSeq(request.mailbox[5]);
268 recvData.ReadByteSeq(request.mailbox[4]);
269 recvData.ReadByteSeq(request.mailbox[2]);
270 recvData.ReadByteSeq(request.mailbox[3]);
271 recvData.ReadByteSeq(request.mailbox[0]);
272
273 return request;
274}
275
276MailboxMailRequest ReadMailCreateTextItemRequest(WorldPacket& recvData)
277{
278 MailboxMailRequest request;
279 recvData >> request.mailId;
280
281 request.mailbox[4] = recvData.ReadBit();
282 request.mailbox[1] = recvData.ReadBit();
283 request.mailbox[6] = recvData.ReadBit();
284 request.mailbox[2] = recvData.ReadBit();
285 request.mailbox[5] = recvData.ReadBit();
286 request.mailbox[3] = recvData.ReadBit();
287 request.mailbox[0] = recvData.ReadBit();
288 request.mailbox[7] = recvData.ReadBit();
289
290 recvData.ReadByteSeq(request.mailbox[6]);
291 recvData.ReadByteSeq(request.mailbox[5]);
292 recvData.ReadByteSeq(request.mailbox[4]);
293 recvData.ReadByteSeq(request.mailbox[3]);
294 recvData.ReadByteSeq(request.mailbox[0]);
295 recvData.ReadByteSeq(request.mailbox[7]);
296 recvData.ReadByteSeq(request.mailbox[2]);
297 recvData.ReadByteSeq(request.mailbox[1]);
298
299 return request;
300}
301
302bool HasMailboxAccess(Player* player, ObjectGuid mailbox)
303{
304 return player->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX) != NULL;
305}
306
307bool IsDeliveredMail(Mail const* mail)
308{
309 return mail && mail->state != MailState::MAIL_STATE_DELETED && mail->deliver_time <= time(NULL);
310}
311
312Mail* GetDeliveredMailOrSendResult(Player* player, uint32 mailId, MailResponseType action)
313{
314 Mail* mail = player->GetMail(mailId);
315 if (!IsDeliveredMail(mail))
316 {
317 player->SendMailResult(mailId, action, MAIL_ERR_INTERNAL_ERROR);
318 return NULL;
319 }
320
321 return mail;
322}
323
324Mail* GetMoneyMailOrSendResult(Player* player, uint32 mailId, uint64 money)
325{
326 Mail* mail = player->GetMail(mailId);
327 if (!IsDeliveredMail(mail) || (money > 0 && mail->money != money))
328 {
330 return NULL;
331 }
332
333 return mail;
334}
335
336Mail* GetTextMailOrSendResult(Player* player, uint32 mailId)
337{
338 Mail* mail = player->GetMail(mailId);
339 if (!IsDeliveredMail(mail) || (mail->body.empty() && !mail->mailTemplateId))
340 {
342 return NULL;
343 }
344
345 return mail;
346}
347
348bool ValidateMailDelete(Player* player, uint32 mailId, Mail const* mail)
349{
350 if (mail && mail->COD)
351 {
353 return false;
354 }
355
356 return true;
357}
358
359bool ValidateSendMailCost(Player* player, uint64 requiredMoney)
360{
361 if (player->HasEnoughMoney(requiredMoney) || player->IsGameMaster())
362 return true;
363
365 return false;
366}
367
368bool ValidateReceiverMailboxCapacity(Player* player, uint8 mailsCount)
369{
370 // Mail count is sent as uint8 in the opcode; keep the historical cap below that limit.
371 if (mailsCount <= 100)
372 return true;
373
375 return false;
376}
377
378bool AreAttachedItemsAccountBound(Player* player, ObjectGuid* itemGuids, uint8 itemCount)
379{
380 if (!itemCount)
381 return false;
382
383 for (uint8 i = 0; i < itemCount; ++i)
384 {
385 if (Item* item = player->GetItemByGuid(itemGuids[i]))
386 {
387 ItemTemplate const* itemProto = item->GetTemplate();
388 if (!itemProto || !(itemProto->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT))
389 return false;
390 }
391 }
392
393 return true;
394}
395
396bool ValidateReceiverFaction(Player* player, uint32 receiverTeam, bool accountBound, bool allowTwoSideMail)
397{
398 if (accountBound || player->GetTeam() == receiverTeam || allowTwoSideMail)
399 return true;
400
402 return false;
403}
404
405bool ValidateSendMailAttachments(Player* player, ObjectGuid* itemGuids, uint8 itemCount, uint64 COD, uint32 receiverAccountId, Item** items)
406{
407 for (uint8 i = 0; i < itemCount; ++i)
408 {
409 if (!itemGuids[i])
410 {
412 return false;
413 }
414
415 Item* item = player->GetItemByGuid(itemGuids[i]);
416
417 // prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to mail)
418 if (!item)
419 {
421 return false;
422 }
423
424 if (!item->CanBeTraded(true))
425 {
427 return false;
428 }
429
430 if (item->IsBoundAccountWide() && item->IsSoulBound() && player->GetSession()->GetAccountId() != receiverAccountId)
431 {
433 return false;
434 }
435
437 {
439 return false;
440 }
441
443 {
445 return false;
446 }
447
448 if (item->IsNotEmptyBag())
449 {
451 return false;
452 }
453
454 items[i] = item;
455 }
456
457 return true;
458}
459
460bool ValidateMailCODPayment(Player* player, uint32 mailId, Mail const* mail)
461{
462 if (player->HasEnoughMoney(uint64(mail->COD)))
463 return true;
464
466 return false;
467}
468}
469
471{
472 SendMailRequest request;
473 if (!ReadSendMailRequest(recvData, request))
474 {
476 recvData.rfinish(); // set to end to avoid warnings spam
477 return;
478 }
479
480 ObjectGuid mailbox = request.mailbox;
481 ObjectGuid* itemGuids = request.itemGuids;
482 uint64 money = request.money;
483 uint64 COD = request.COD;
484 std::string& receiverName = request.receiverName;
485 std::string const& subject = request.subject;
486 std::string const& body = request.body;
487 uint32 unk1 = request.unk1;
488 uint32 unk2 = request.unk2;
489 uint8 itemCount = request.itemCount;
490
491 // packet read complete, now do check
492
493 Player* player = _player;
494
495 if (!HasMailboxAccess(player, mailbox))
496 return;
497
498 if (receiverName.empty())
499 return;
500
501 if (player->getLevel() < sWorld->getIntConfig(WorldIntConfigs::CONFIG_MAIL_LEVEL_REQ))
502 {
504 return;
505 }
506
507 uint64 receiverGuid = 0;
508 if (normalizePlayerName(receiverName))
509 receiverGuid = sObjectMgr->GetPlayerGUIDByName(receiverName);
510
511 if (!receiverGuid)
512 {
513 SF_LOG_INFO("network", "Player %u is sending mail to %s (GUID: not existed!) with subject %s "
514 "and body %s includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u",
515 player->GetGUIDLow(), receiverName.c_str(), subject.c_str(), body.c_str(),
516 itemCount, money, COD, unk1, unk2);
518 return;
519 }
520
521 SF_LOG_INFO("network", "Player %u is sending mail to %s (GUID: %u) with subject %s and body %s "
522 "includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u",
523 player->GetGUIDLow(), receiverName.c_str(), GUID_LOPART(receiverGuid), subject.c_str(),
524 body.c_str(), itemCount, money, COD, unk1, unk2);
525
526 if (player->GetGUID() == receiverGuid)
527 {
529 return;
530 }
531
532 uint32 cost = itemCount ? 30 * itemCount : 30; // price hardcoded in client
533
534 uint64 reqmoney = cost + money;
535
536 if (!ValidateSendMailCost(player, reqmoney))
537 return;
538
539 Player* receiver = ObjectAccessor::FindPlayer(receiverGuid);
540
541 uint32 receiverTeam = 0;
542 uint8 mailsCount = 0; //do not allow to send to one player more than 100 mails
543 uint8 receiverLevel = 0;
544 uint32 receiverAccountId = 0;
545
546 if (receiver)
547 {
548 receiverTeam = receiver->GetTeam();
549 mailsCount = receiver->GetMailSize();
550 receiverLevel = receiver->getLevel();
551 receiverAccountId = receiver->GetSession()->GetAccountId();
552 }
553 else
554 {
555 receiverTeam = sObjectMgr->GetPlayerTeamByGUID(receiverGuid);
556
557 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_COUNT);
558 stmt->setUInt32(0, GUID_LOPART(receiverGuid));
559
560 PreparedQueryResult result = CharacterDatabase.Query(stmt);
561 if (result)
562 {
563 Field* fields = result->Fetch();
564 mailsCount = fields[0].GetUInt64();
565 }
566
567 stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_LEVEL);
568 stmt->setUInt32(0, GUID_LOPART(receiverGuid));
569
570 result = CharacterDatabase.Query(stmt);
571 if (result)
572 {
573 Field* fields = result->Fetch();
574 receiverLevel = fields[0].GetUInt8();
575 }
576
577 receiverAccountId = sObjectMgr->GetPlayerAccountIdByGUID(receiverGuid);
578 }
579
580 // do not allow to have more than 100 mails in mailbox.. mails count is in opcode uint8!!! - so max can be 255..
581 if (!ValidateReceiverMailboxCapacity(player, mailsCount))
582 return;
583
584 // test the receiver's Faction... or all items are account bound
585 bool accountBound = AreAttachedItemsAccountBound(player, itemGuids, itemCount);
586 if (!ValidateReceiverFaction(player, receiverTeam, accountBound, HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_MAIL)))
587 return;
588
589 if (receiverLevel < sWorld->getIntConfig(WorldIntConfigs::CONFIG_MAIL_LEVEL_REQ))
590 {
592 return;
593 }
594
595 Item* items[MAX_MAIL_ITEMS];
596
597 if (!ValidateSendMailAttachments(player, itemGuids, itemCount, COD, receiverAccountId, items))
598 return;
599
600 player->SendMailResult(0, MAIL_SEND, MAIL_OK);
601
602 player->ModifyMoney(-int64(reqmoney));
604
605 bool needItemDelay = false;
606
607 MailDraft draft(subject, body);
608
609 SQLTransaction trans = CharacterDatabase.BeginTransaction();
610
611 if (itemCount > 0 || money > 0)
612 {
614 if (itemCount > 0)
615 {
616 for (uint8 i = 0; i < itemCount; ++i)
617 {
618 Item* item = items[i];
619 if (log)
620 {
621 sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail item: %s (Entry: %u Count: %u) "
622 "to player: %s (GUID: %u) (Account: %u)", GetPlayerName().c_str(), GetGuidLow(), GetAccountId(),
623 item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount(),
624 receiverName.c_str(), GUID_LOPART(receiverGuid), receiverAccountId);
625 }
626
627 item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable
628 player->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true);
629
630 item->DeleteFromInventoryDB(trans); // deletes item from character's inventory
631 item->SetOwnerGUID(receiverGuid);
632 item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone
633
634 draft.AddItem(item);
635 }
636
637 // if item send to character at another account, then apply item delivery delay
638 needItemDelay = player->GetSession()->GetAccountId() != receiverAccountId;
639 }
640
641 if (log && money > 0)
642 {
643 sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail money: " UI64FMTD " to player: %s (GUID: %u) (Account: %u)",
644 GetPlayerName().c_str(), GetGuidLow(), GetAccountId(), money, receiverName.c_str(), GUID_LOPART(receiverGuid), receiverAccountId);
645 }
646 }
647
648 // If theres is an item, there is a one hour delivery delay if sent to another account's character.
649 uint32 deliver_delay = needItemDelay ? sWorld->getIntConfig(WorldIntConfigs::CONFIG_MAIL_DELIVERY_DELAY) : 0;
650
651 // Mail sent between guild members arrives instantly if they have the guild perk "Guild Mail"
652 if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId()))
653 if (guild->GetLevel() >= 17 && guild->IsMember(receiverGuid))
654 deliver_delay = 0;
655
656 // will delete item or place to receiver mail list
657 draft
658 .AddMoney(money)
659 .AddCOD(COD)
660 .SendMailTo(trans, MailReceiver(receiver, GUID_LOPART(receiverGuid)), MailSender(player), body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay);
661
662 player->SaveInventoryAndGoldToDB(trans);
663 CharacterDatabase.CommitTransaction(trans);
664}
665
666//called when mail is read
668{
669 MailboxMailRequest request = ReadMailMarkAsReadRequest(recvData);
670 ObjectGuid mailbox = request.mailbox;
671 uint32 mailId = request.mailId;
672
673 if (!HasMailboxAccess(_player, mailbox))
674 return;
675
676 if (Mail* mail = _player->GetMail(mailId))
677 {
678 if (_player->unReadMails)
679 --_player->unReadMails;
680
683
684 _player->m_mailsUpdated = true;
685 }
686}
687
688//called when client deletes mail
690{
691 MailDeleteRequest request = ReadMailDeleteRequest(recvData);
692 uint32 mailId = request.mailId;
693
694 if (Mail* mail = _player->GetMail(mailId))
695 {
696 // delete shouldn't show up for COD mails
697 if (!ValidateMailDelete(_player, mailId, mail))
698 return;
699
701 }
702
703 _player->m_mailsUpdated = true;
704 _player->SendMailResult(mailId, MAIL_DELETED, MAIL_OK);
705}
706
708{
709 MailboxMailRequest request = ReadMailReturnToSenderRequest(recvData);
710 ObjectGuid mailbox = request.mailbox;
711 uint32 mailId = request.mailId;
712
713 if (!HasMailboxAccess(_player, mailbox))
714 return;
715
716 Player* player = _player;
717 Mail* m = GetDeliveredMailOrSendResult(player, mailId, MAIL_RETURNED_TO_SENDER);
718 if (!m)
719 return;
720 //we can return mail now, so firstly delete the old one
721 SQLTransaction trans = CharacterDatabase.BeginTransaction();
722
723 PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_BY_ID);
724 stmt->setUInt32(0, mailId);
725 trans->Append(stmt);
726
727 stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_ITEM_BY_ID);
728 stmt->setUInt32(0, mailId);
729 trans->Append(stmt);
730
731 player->RemoveMail(mailId);
732
733 // only return mail if the player exists (and delete if not existing)
734 if (m->messageType == MAIL_NORMAL && m->sender)
735 {
736 MailDraft draft(m->subject, m->body);
737 if (m->mailTemplateId)
738 draft = MailDraft(m->mailTemplateId, false); // items already included
739
740 if (m->HasItems())
741 {
742 for (MailItemInfoVec::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2)
743 {
744 if (Item* const item = player->GetMItem(itr2->item_guid))
745 draft.AddItem(item);
746 player->RemoveMItem(itr2->item_guid);
747 }
748 }
749 draft.AddMoney(m->money).SendReturnToSender(GetAccountId(), m->receiver, m->sender, trans);
750 }
751
752 CharacterDatabase.CommitTransaction(trans);
753
754 delete m; //we can deallocate old mail
756}
757
758//called when player takes item attached in mail
760{
761 MailTakeItemRequest request = ReadMailTakeItemRequest(recvData);
762 ObjectGuid mailbox = request.mailbox;
763 uint32 mailId = request.mailId;
764 uint32 itemId = request.itemId;
765
766 if (!HasMailboxAccess(_player, mailbox))
767 return;
768
769 Player* player = _player;
770
771 Mail* m = GetDeliveredMailOrSendResult(player, mailId, MAIL_ITEM_TAKEN);
772 if (!m)
773 return;
774
775 // prevent cheating with skip client money check
776 if (!ValidateMailCODPayment(player, mailId, m))
777 return;
778
779 Item* it = player->GetMItem(itemId);
780
781 ItemPosCountVec dest;
782 uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, it, false);
783 if (msg == EQUIP_ERR_OK)
784 {
785 SQLTransaction trans = CharacterDatabase.BeginTransaction();
786 m->RemoveItem(itemId);
787 m->removedItems.push_back(itemId);
788
789 if (m->COD > 0) //if there is COD, take COD money from player and send them to sender by mail
790 {
791 uint64 sender_guid = MAKE_NEW_GUID(m->sender, 0, HIGHGUID_PLAYER);
792 Player* receiver = ObjectAccessor::FindPlayer(sender_guid);
793
794 uint32 sender_accId = 0;
795
797 {
798 std::string sender_name;
799 if (receiver)
800 {
801 sender_accId = receiver->GetSession()->GetAccountId();
802 sender_name = receiver->GetName();
803 }
804 else
805 {
806 // can be calculated early
807 sender_accId = sObjectMgr->GetPlayerAccountIdByGUID(sender_guid);
808
809 if (!sObjectMgr->GetPlayerNameByGUID(sender_guid, sender_name))
810 sender_name = sObjectMgr->GetSkyFireStringForDBCLocale(LANG_UNKNOWN);
811 }
812 sLog->outCommand(GetAccountId(), "GM %s (Account: %u) receiver mail item: %s (Entry: %u Count: %u) and send COD money: " UI64FMTD " to player: %s (Account: %u)",
813 GetPlayerName().c_str(), GetAccountId(), it->GetTemplate()->Name1.c_str(), it->GetEntry(), it->GetCount(), m->COD, sender_name.c_str(), sender_accId);
814 }
815 else if (!receiver)
816 sender_accId = sObjectMgr->GetPlayerAccountIdByGUID(sender_guid);
817
818 // check player existence
819 if (receiver || sender_accId)
820 {
821 MailDraft(m->subject, "")
822 .AddMoney(m->COD)
824 }
825
826 player->ModifyMoney(-int32(m->COD));
827 }
828 m->COD = 0;
830 player->m_mailsUpdated = true;
831 player->RemoveMItem(it->GetGUIDLow());
832
833 uint32 count = it->GetCount(); // save counts before store and possible merge with deleting
834 it->SetState(ITEM_UNCHANGED); // need to set this state, otherwise item cannot be removed later, if neccessary
835 player->MoveItemToInventory(dest, it, true);
836
837 player->SaveInventoryAndGoldToDB(trans);
838 player->_SaveMail(trans);
839 CharacterDatabase.CommitTransaction(trans);
840
841 player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_OK, 0, itemId, count);
842 }
843 else
845}
846
848{
849 MailTakeMoneyRequest request = ReadMailTakeMoneyRequest(recvData);
850 ObjectGuid mailbox = request.mailbox;
851 uint64 money = request.money;
852 uint32 mailId = request.mailId;
853
854 if (!HasMailboxAccess(_player, mailbox))
855 return;
856
857 Player* player = _player;
858
859 Mail* m = GetMoneyMailOrSendResult(player, mailId, money);
860 if (!m)
861 return;
862
863 if (!player->ModifyMoney(m->money, false))
864 {
866 return;
867 }
868
869 m->money = 0;
871 player->m_mailsUpdated = true;
872
873 player->SendMailResult(mailId, MAIL_MONEY_TAKEN, MAIL_OK);
874
875 // save money and mail to prevent cheating
876 SQLTransaction trans = CharacterDatabase.BeginTransaction();
877 player->SaveGoldToDB(trans);
878 player->_SaveMail(trans);
879 CharacterDatabase.CommitTransaction(trans);
880}
881
882//called when player lists his received mails
884{
885 MailboxRequest request = ReadGetMailListRequest(recvData);
886 ObjectGuid mailbox = request.mailbox;
887
888 if (!HasMailboxAccess(_player, mailbox))
889 return;
890
891 Player* player = _player;
892
893 //load players mails, and mailed items
894 if (!player->m_mailsLoaded)
895 player->_LoadMail();
896
897 // client can't work with packets > max int16 value
898 const uint32 maxPacketSize = 32767;
899
900 uint32 mailCount = 0;
901 uint32 realCount = 0; // true mail count (includes any skipped mail)
902 time_t cur_time = time(NULL);
903 ByteBuffer mailData;
904
905 WorldPacket data(SMSG_MAIL_LIST_RESULT, 200); // guess size
906 data << uint32(0); // placeholder
907
908 size_t mailCountPos = data.bitwpos();
909 data.WriteBits(0, 18); // placeholder
910
911 for (PlayerMails::iterator itr = player->GetMailBegin(); itr != player->GetMailEnd(); ++itr)
912 {
913 Mail* mail = *itr;
914
915 // Only first 50 mails are displayed
916 if (mailCount >= 50)
917 {
918 realCount += 1;
919 continue;
920 }
921
922 // skip deleted or not delivered (deliver delay not expired) mails
923 if (mail->state == MailState::MAIL_STATE_DELETED || cur_time < mail->deliver_time)
924 continue;
925
926 // skip mail with more than MAX_MAIL_ITEMS items (should not occur)
927 uint8 itemCount = mail->items.size();
928 if (itemCount > MAX_MAIL_ITEMS)
929 {
930 realCount += 1;
931 continue;
932 }
933
934 // skip mail if the packet has become too large (should not occur)
935 size_t nextMailSize = 6 + 1 + 8 + itemCount * (4 + 4 + 4 + 4 + 4 + MAX_INSPECTED_ENCHANTMENT_SLOT * (4 + 4 + 4) +
936 4 + 4 + 4 + 4 + 1 + 4) + mail->body.size() + mail->subject.size() + 4 + 4 + 8 + 4 + 8 + 4 + 4 + 1 + 4;
937
938 if (data.wpos() + nextMailSize > maxPacketSize)
939 {
940 realCount += 1;
941 continue;
942 }
943
944 data.WriteBit(mail->messageType != MAIL_NORMAL ? 1 : 0);
945 data.WriteBits(mail->subject.size(), 8);
946 data.WriteBits(mail->body.size(), 13);
947 data.WriteBit(0);
948 data.WriteBit(0);
949
950 size_t itemCountPos = data.bitwpos();
951 data.WriteBits(0, 17); // placeholder
952
953 data.WriteBit(1); // has guid
954
955 ObjectGuid guid = mail->messageType == MAIL_NORMAL ? MAKE_NEW_GUID(mail->sender, 0, HIGHGUID_PLAYER) : 0;
956 data.WriteBit(guid[2]);
957 data.WriteBit(guid[6]);
958 data.WriteBit(guid[7]);
959 data.WriteBit(guid[0]);
960 data.WriteBit(guid[5]);
961 data.WriteBit(guid[3]);
962 data.WriteBit(guid[1]);
963 data.WriteBit(guid[4]);
964
965 uint8 trueItemCount = 0;
966 for (uint8 i = 0; i < itemCount; i++)
967 {
968 Item* item = player->GetMItem(mail->items[i].item_guid);
969 if (!item)
970 continue;
971
972 data.WriteBit(0);
973
974 mailData << uint32(item->GetGUIDLow());
975 mailData << uint32(4); // unknown
976 mailData << uint32(item->GetSpellCharges());
977 mailData << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY));
978 mailData << uint32(0); // unknown
979
980 for (uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; j++)
981 {
982 mailData << uint32(item->GetEnchantmentCharges((EnchantmentSlot)j));
983 mailData << uint32(item->GetEnchantmentDuration((EnchantmentSlot)j));
984 mailData << uint32(item->GetEnchantmentId((EnchantmentSlot)j));
985 }
986
987 mailData << uint32(item->GetItemSuffixFactor());
988 mailData << int32(item->GetItemRandomPropertyId());
990 mailData << uint32(item->GetCount());
991 mailData << uint8(i);
992 mailData << uint32(item->GetEntry());
993
994 trueItemCount++;
995 }
996
997 data.PutBits(itemCountPos, trueItemCount, 17);
998
999 mailData.WriteString(mail->body);
1000 mailData << uint32(mail->messageID);
1001 mailData.WriteByteSeq(guid[4]);
1002 mailData.WriteByteSeq(guid[0]);
1003 mailData.WriteByteSeq(guid[5]);
1004 mailData.WriteByteSeq(guid[3]);
1005 mailData.WriteByteSeq(guid[1]);
1006 mailData.WriteByteSeq(guid[7]);
1007 mailData.WriteByteSeq(guid[2]);
1008 mailData.WriteByteSeq(guid[6]);
1009 mailData << uint32(mail->mailTemplateId);
1010 mailData << uint64(mail->COD);
1011 mailData.WriteString(mail->subject);
1012 mailData << uint32(mail->stationery);
1013 mailData << float(float(mail->expire_time - time(NULL)) / float(DAY));
1014 mailData << uint64(mail->money);
1015 mailData << uint32(mail->checked);
1016
1017 if (mail->messageType != MAIL_NORMAL)
1018 mailData << uint32(mail->sender);
1019
1020 mailData << uint8(mail->messageType);
1021 mailData << uint32(0); // unknown
1022
1023 realCount++;
1024 mailCount++;
1025 }
1026
1027 data.FlushBits();
1028 data.append(mailData);
1029
1030 data.put<uint32>(0, realCount);
1031 data.PutBits(mailCountPos, mailCount, 18);
1032
1033 SendPacket(&data);
1034
1035 // recalculate m_nextMailDelivereTime and unReadMails
1036 _player->UpdateNextMailTimeAndUnreads();
1037}
1038
1039//used when player copies mail body to his inventory
1041{
1042 MailboxMailRequest request = ReadMailCreateTextItemRequest(recvData);
1043 ObjectGuid mailbox = request.mailbox;
1044 uint32 mailId = request.mailId;
1045
1046 if (!HasMailboxAccess(_player, mailbox))
1047 return;
1048
1049 Player* player = _player;
1050
1051 Mail* m = GetTextMailOrSendResult(player, mailId);
1052 if (!m)
1053 return;
1054
1055 Item* bodyItem = new Item; // This is not bag and then can be used new Item.
1056 if (!bodyItem->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_ITEM), MAIL_BODY_ITEM_TEMPLATE, player))
1057 {
1058 delete bodyItem;
1059 return;
1060 }
1061
1062 // in mail template case we need create new item text
1063 if (m->mailTemplateId)
1064 {
1065 MailTemplateEntry const* mailTemplateEntry = sMailTemplateStore.LookupEntry(m->mailTemplateId);
1066 if (!mailTemplateEntry)
1067 {
1069 return;
1070 }
1071
1072 bodyItem->SetText(mailTemplateEntry->content);
1073 }
1074 else
1075 bodyItem->SetText(m->body);
1076
1079
1080 SF_LOG_INFO("network", "HandleMailCreateTextItem mailid=%u", mailId);
1081
1082 ItemPosCountVec dest;
1083 uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, bodyItem, false);
1084 if (msg == EQUIP_ERR_OK)
1085 {
1088 player->m_mailsUpdated = true;
1089
1090 player->StoreItem(dest, bodyItem, true);
1091 player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_OK);
1092 }
1093 else
1094 {
1096 delete bodyItem;
1097 }
1098}
1099
1102{
1104
1105 if (!_player->m_mailsLoaded)
1106 _player->_LoadMail();
1107
1108 if (_player->unReadMails > 0)
1109 {
1110 ByteBuffer dataBuffer;
1111 uint8 count = 0;
1112 time_t now = time(NULL);
1113 bool hasVirtualRealmAddress = false, hasNativeRealmAddress = false;
1114
1115 size_t pos = data.bitwpos();
1116 data.WriteBits(count, 20);
1117
1118 for (PlayerMails::iterator itr = _player->GetMailBegin(); itr != _player->GetMailEnd(); ++itr)
1119 {
1120 Mail* m = (*itr);
1121 // must be not checked yet
1123 continue;
1124
1125 // and already delivered
1126 if (now < m->deliver_time)
1127 continue;
1128
1129 ObjectGuid senderGuid = (m->messageType == MAIL_NORMAL) ? MAKE_NEW_GUID(m->sender, 0, HIGHGUID_PLAYER) : 0;
1130
1131 data.WriteBit(senderGuid[3]);
1132 data.WriteBit(hasVirtualRealmAddress);
1133 data.WriteBit(senderGuid[2]);
1134 data.WriteBit(hasNativeRealmAddress);
1135 data.WriteBit(senderGuid[6]);
1136 data.WriteBit(senderGuid[1]);
1137 data.WriteBit(senderGuid[4]);
1138 data.WriteBit(senderGuid[0]);
1139 data.WriteBit(senderGuid[5]);
1140 data.WriteBit(senderGuid[7]);
1141
1142 dataBuffer << uint32(m->messageType != MAIL_NORMAL ? m->sender : 0); // non-player entries
1143 dataBuffer.WriteByteSeq(senderGuid[5]);
1144 dataBuffer.WriteByteSeq(senderGuid[4]);
1145 dataBuffer.WriteByteSeq(senderGuid[6]);
1146 dataBuffer.WriteByteSeq(senderGuid[1]);
1147 dataBuffer << uint8(m->messageType);
1148 dataBuffer.WriteByteSeq(senderGuid[0]);
1149 dataBuffer << float(m->deliver_time - now);
1150 if (hasNativeRealmAddress)
1151 dataBuffer << uint32(realmID);
1152 dataBuffer << uint32(m->stationery);
1153 dataBuffer.WriteByteSeq(senderGuid[3]);
1154 dataBuffer.WriteByteSeq(senderGuid[2]);
1155 if (hasVirtualRealmAddress)
1156 dataBuffer << uint32(realmID);
1157 dataBuffer.WriteByteSeq(senderGuid[7]);
1158
1159 count++;
1160 if (count == 3) // do not display more than 3 mails
1161 break;
1162 }
1163
1164 data.FlushBits();
1165 data.PutBits(pos, count, 20);
1166 data.append(dataBuffer);
1167
1168 data << float(0);
1169 }
1170 else
1171 {
1172 data.WriteBits(0, 20);
1173 data.FlushBits();
1174 data << float(-1);
1175 }
1176
1177 SendPacket(&data);
1178}
@ CHAR_SEL_CHAR_LEVEL
@ CHAR_DEL_MAIL_BY_ID
@ CHAR_DEL_MAIL_ITEM_BY_ID
@ CHAR_SEL_MAIL_COUNT
@ DAY
Definition Common.h:121
@ ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL
Definition DBCEnums.h:229
DBCStorage< MailTemplateEntry > sMailTemplateStore(MailTemplateEntryfmt)
std::int32_t int32
Definition Define.h:73
#define UI64FMTD
Definition Define.h:64
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
std::int64_t int64
Definition Define.h:72
#define sGuildMgr
Definition GuildMgr.h:53
EnchantmentSlot
Definition Item.h:149
@ MAX_INSPECTED_ENCHANTMENT_SLOT
Definition Item.h:158
@ EQUIP_ERR_TOO_MUCH_GOLD
Definition Item.h:105
@ EQUIP_ERR_MAIL_BOUND_ITEM
Definition Item.h:100
@ EQUIP_ERR_DESTROY_NONEMPTY_BAG
Definition Item.h:59
@ EQUIP_ERR_OK
Definition Item.h:28
@ EQUIP_ERR_NOT_SAME_ACCOUNT
Definition Item.h:110
@ ITEM_UNCHANGED
Definition Item.h:191
@ ITEM_PROTO_FLAG_CONJURED
@ ITEM_PROTO_FLAG_BIND_TO_ACCOUNT
@ ITEM_FLAG_MAIL_TEXT_MASK
@ ITEM_FLAG_WRAPPED
@ LANG_UNKNOWN
Definition Language.h:58
@ LANG_MAIL_RECEIVER_REQ
Definition Language.h:1118
@ LANG_MAIL_SENDER_REQ
Definition Language.h:1117
#define SF_LOG_INFO(filterType__,...)
Definition Log.h:137
#define sLog
Definition Log.h:106
@ MAIL_CHECK_MASK_HAS_BODY
Definition Mail.h:39
@ MAIL_CHECK_MASK_READ
Definition Mail.h:35
@ MAIL_CHECK_MASK_COD_PAYMENT
This mail was copied. Do not allow making a copy of items in mail.
Definition Mail.h:38
@ MAIL_CHECK_MASK_COPIED
This mail was returned. Do not allow returning mail back again.
Definition Mail.h:37
@ MAIL_STATE_DELETED
Definition Mail.h:59
@ MAIL_STATE_CHANGED
Definition Mail.h:58
#define MAIL_BODY_ITEM_TEMPLATE
Definition Mail.h:19
#define MAX_MAIL_ITEMS
Definition Mail.h:20
@ MAIL_NORMAL
Definition Mail.h:24
uint32 GUID_LOPART(uint64 x)
@ HIGHGUID_PLAYER
@ HIGHGUID_ITEM
uint64 MAKE_NEW_GUID(uint32 l, uint32 e, uint32 h)
bool normalizePlayerName(std::string &name)
#define sObjectMgr
Definition ObjectMgr.h:1617
std::vector< ItemPosCount > ItemPosCountVec
Definition Player.h:777
Skyfire::AutoPtr< PreparedResultSet, Skyfire::Mutex > PreparedQueryResult
Definition QueryResult.h:94
@ GAMEOBJECT_TYPE_MAILBOX
MailResponseType
@ MAIL_MONEY_TAKEN
@ MAIL_DELETED
@ MAIL_RETURNED_TO_SENDER
@ MAIL_MADE_PERMANENT
@ MAIL_ITEM_TAKEN
@ MAIL_SEND
@ MAIL_ERR_NOT_ENOUGH_MONEY
@ MAIL_ERR_NOT_YOUR_TEAM
@ MAIL_ERR_CANT_SEND_WRAPPED_COD
@ MAIL_ERR_RECIPIENT_CAP_REACHED
@ MAIL_ERR_EQUIP_ERROR
@ MAIL_ERR_RECIPIENT_NOT_FOUND
@ MAIL_OK
@ MAIL_ERR_TOO_MANY_ATTACHMENTS
@ MAIL_ERR_MAIL_ATTACHMENT_INVALID
@ MAIL_ERR_INTERNAL_ERROR
@ MAIL_ERR_CANNOT_SEND_TO_SELF
Skyfire::AutoPtr< Transaction, Skyfire::Mutex > SQLTransaction
Definition Transaction.h:42
@ NULL_BAG
Definition Unit.h:336
@ NULL_SLOT
Definition Unit.h:337
@ ITEM_FIELD_DURABILITY
@ ITEM_FIELD_MAX_DURABILITY
@ ITEM_FIELD_CREATOR
@ ITEM_FIELD_EXPIRATION
@ ITEM_FIELD_DYNAMIC_FLAGS
bool WriteBit(uint32 bit)
Definition ByteBuffer.h:164
void read_skip()
Definition ByteBuffer.h:502
void put(size_t pos, T value)
Definition ByteBuffer.h:233
size_t bitwpos() const
Returns position of last written bit.
Definition ByteBuffer.h:492
void WriteString(std::string const &str)
Definition ByteBuffer.h:578
uint32 ReadBits(size_t bits)
Definition ByteBuffer.h:198
void ReadByteSeq(uint8 &b)
Definition ByteBuffer.h:215
void append(T value)
Definition ByteBuffer.h:147
void rfinish()
Definition ByteBuffer.h:478
std::string ReadString(size_t length)
Definition ByteBuffer.h:565
void PutBits(size_t pos, T value, uint32 bitCount)
Definition ByteBuffer.h:283
size_t wpos() const
Definition ByteBuffer.h:483
void WriteBits(T value, size_t bits)
Definition ByteBuffer.h:192
void WriteByteSeq(uint8 b)
Definition ByteBuffer.h:227
void FlushBits()
Definition ByteBuffer.h:154
bool ReadBit()
Definition ByteBuffer.h:180
Definition Field.h:16
uint8 GetUInt8() const
Definition Field.h:26
uint64 GetUInt64() const
Definition Field.h:141
Definition Guild.h:324
Definition Item.h:202
uint8 GetSlot() const
Definition Item.h:265
void SetNotRefundable(Player *owner, bool changestate=true, SQLTransaction *trans=NULL)
Definition Item.cpp:1111
void SetText(std::string const &text)
Definition Item.h:292
void SetState(ItemUpdateState state, Player *forplayer=NULL)
Definition Item.cpp:667
uint32 GetEnchantmentId(EnchantmentSlot slot) const
Definition Item.h:287
int32 GetSpellCharges(uint8 index=0) const
Definition Item.h:298
void SetOwnerGUID(uint64 guid)
Definition Item.h:214
bool IsBoundAccountWide() const
Definition Item.h:219
bool CanBeTraded(bool mail=false, bool trade=false) const
Definition Item.cpp:744
uint32 GetEnchantmentDuration(EnchantmentSlot slot) const
Definition Item.h:288
virtual void SaveToDB(SQLTransaction &trans)
Definition Item.cpp:305
int32 GetItemRandomPropertyId() const
Definition Item.h:278
ItemTemplate const * GetTemplate() const
Definition Item.cpp:528
bool IsSoulBound() const
Definition Item.h:218
uint32 GetItemSuffixFactor() const
Definition Item.h:279
static void DeleteFromInventoryDB(SQLTransaction &trans, uint32 itemGuid)
Definition Item.cpp:516
uint32 GetEnchantmentCharges(EnchantmentSlot slot) const
Definition Item.h:289
bool IsNotEmptyBag() const
Definition Item.cpp:280
uint32 GetCount() const
Definition Item.h:258
virtual bool Create(uint32 guidlow, uint32 itemid, Player const *owner)
Definition Item.cpp:252
MailDraft & AddCOD(uint32 COD)
Definition Mail.h:127
void SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, SQLTransaction &trans)
Definition Mail.cpp:120
void SendMailTo(SQLTransaction &trans, MailReceiver const &receiver, MailSender const &sender, MailCheckMask checked=MAIL_CHECK_MASK_NONE, uint32 deliver_delay=0)
Definition Mail.cpp:162
MailDraft & AddItem(Item *item)
Definition Mail.cpp:70
MailDraft & AddMoney(uint64 money)
Definition Mail.h:126
static Player * FindPlayer(uint64)
uint64 GetGUID() const
Definition Object.h:119
uint32 GetUInt32Value(uint16 index) const
Definition Object.cpp:325
uint32 GetGUIDLow() const
Definition Object.h:120
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:1261
uint32 GetEntry() const
Definition Object.h:125
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:1309
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:1038
uint32 GetTeam() const
Definition Player.h:2527
void SaveInventoryAndGoldToDB(SQLTransaction &trans)
Definition Player.cpp:14609
void _SaveMail(SQLTransaction &trans)
Definition Player.cpp:14923
bool ModifyMoney(int64 amount, bool sendError=true)
Definition Player.cpp:18342
uint32 GetGuildId() const
Definition Player.h:2291
void _LoadMail()
Definition Player.cpp:13447
bool RemoveMItem(uint32 id)
void RemoveMail(uint32 id)
bool m_mailsUpdated
Definition Player.h:1928
void SendMailResult(uint32 mailId, MailResponseType mailAction, MailResponseResult mailError, uint32 equipError=0, uint32 item_guid=0, uint32 item_count=0)
PlayerMails::iterator GetMailBegin()
Definition Player.h:2011
Item * StoreItem(ItemPosCountVec const &pos, Item *pItem, bool update)
WorldSession * GetSession() const
Definition Player.h:2417
Item * GetItemByGuid(uint64 guid) const
uint32 GetMailSize()
Definition Player.h:2005
void MoveItemFromInventory(uint8 bag, uint8 slot, bool update)
GameObject * GetGameObjectIfCanInteractWith(uint64 guid, GameobjectTypes type) const
Definition Player.cpp:2887
bool m_mailsLoaded
Definition Player.h:1927
void MoveItemToInventory(ItemPosCountVec const &dest, Item *pItem, bool update, bool in_characterInventoryDB=false)
bool IsGameMaster() const
Definition Player.h:1369
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, Unit *unit=NULL)
Definition Player.cpp:21033
PlayerMails::iterator GetMailEnd()
Definition Player.h:2015
Item * GetMItem(uint32 id)
void SaveGoldToDB(SQLTransaction &trans)
Definition Player.cpp:14616
Mail * GetMail(uint32 id)
bool HasEnoughMoney(uint64 amount) const
Definition Player.h:1950
void setUInt32(const uint8 index, const uint32 value)
uint8 getLevel() const
Definition Unit.h:1528
std::string const & GetName() const
Definition Object.h:664
void HandleMailCreateTextItem(WorldPacket &recvData)
void HandleMailReturnToSender(WorldPacket &recvData)
const char * GetSkyFireString(int32 entry) const
void HandleSendMail(WorldPacket &recvData)
void SendNotification(const char *format,...) ATTR_PRINTF(2
uint32 GetGuidLow() const
Get player guid if available. Use for logging purposes only.
Player * GetPlayer() const
void HandleMailTakeItem(WorldPacket &recvData)
void HandleMailTakeMoney(WorldPacket &recvData)
void HandleGetMailList(WorldPacket &recvData)
void HandleMailMarkAsRead(WorldPacket &recvData)
bool HasPermission(uint32 permissionId)
void HandleQueryNextMailTime(WorldPacket &recvData)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
uint32 GetAccountId() const
Player * _player
std::string const & GetPlayerName() const
void HandleMailDelete(WorldPacket &recvData)
CharacterDatabaseWorkerPool CharacterDatabase
Accessor to the character database.
Definition Main.cpp:41
@ SMSG_MAIL_LIST_RESULT
Definition Opcodes.h:777
@ SMSG_MAIL_QUERY_NEXT_TIME_RESULT
Definition Opcodes.h:778
#define sWorld
Definition World.h:910
uint32 realmID
Id of the realm.
Definition Main.cpp:73
@ CONFIG_MAIL_DELIVERY_DELAY
Definition World.h:255
@ CONFIG_MAIL_LEVEL_REQ
Definition World.h:283
@ RBAC_PERM_TWO_SIDE_INTERACTION_MAIL
Definition RBAC.h:67
@ RBAC_PERM_LOG_GM_TRADE
Definition RBAC.h:51
std::string Name1
Definition Mail.h:156
bool HasItems() const
Definition Mail.h:198
uint8 messageType
Definition Mail.h:161
uint32 messageID
Definition Mail.h:160
std::vector< uint32 > removedItems
Definition Mail.h:169
uint64 money
Definition Mail.h:172
uint64 COD
Definition Mail.h:173
time_t expire_time
Definition Mail.h:170
uint32 sender
Definition Mail.h:164
uint32 receiver
Definition Mail.h:165
uint8 stationery
Definition Mail.h:162
std::string subject
Definition Mail.h:166
std::string body
Definition Mail.h:167
std::vector< MailItemInfo > items
Definition Mail.h:168
time_t deliver_time
Definition Mail.h:171
bool RemoveItem(uint32 item_guid)
Definition Mail.h:185
uint32 checked
Definition Mail.h:174
MailState state
Definition Mail.h:175
uint16 mailTemplateId
Definition Mail.h:163
char * content