mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-21 15:27:47 -04:00
Merge pull request #14025 from Carbenium/mail-1
Core/Packets: Implement all mail system relevant packets
This commit is contained in:
@@ -56,6 +56,7 @@
|
||||
#include "LFGMgr.h"
|
||||
#include "Language.h"
|
||||
#include "Log.h"
|
||||
#include "MailPackets.h"
|
||||
#include "MapInstanced.h"
|
||||
#include "MapManager.h"
|
||||
#include "MovementStructures.h"
|
||||
@@ -3236,26 +3237,36 @@ void Player::RemoveMail(uint32 id)
|
||||
|
||||
void Player::SendMailResult(uint32 mailId, MailResponseType mailAction, MailResponseResult mailError, uint32 equipError, ObjectGuid::LowType item_guid, uint32 item_count)
|
||||
{
|
||||
WorldPacket data(SMSG_SEND_MAIL_RESULT, (4+4+4+(mailError == MAIL_ERR_EQUIP_ERROR?4:(mailAction == MAIL_ITEM_TAKEN?4+4:0))));
|
||||
data << uint32(mailId);
|
||||
data << uint32(mailAction);
|
||||
data << uint32(mailError);
|
||||
if (mailError == MAIL_ERR_EQUIP_ERROR)
|
||||
data << uint32(equipError);
|
||||
else if (mailAction == MAIL_ITEM_TAKEN)
|
||||
|
||||
WorldPackets::Mail::MailCommandResult result;
|
||||
|
||||
result.MailID = mailId;
|
||||
result.Command = mailAction;
|
||||
result.ErrorCode = mailError;
|
||||
|
||||
switch (mailError)
|
||||
{
|
||||
data << uint64(item_guid); // item guid low?
|
||||
data << uint32(item_count); // item count?
|
||||
case MAIL_ERR_EQUIP_ERROR:
|
||||
result.BagResult = equipError;
|
||||
break;
|
||||
case MAIL_ITEM_TAKEN:
|
||||
result.AttachID = item_guid;
|
||||
result.QtyInInventory = item_count;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
GetSession()->SendPacket(&data);
|
||||
|
||||
GetSession()->SendPacket(result.Write());
|
||||
}
|
||||
|
||||
void Player::SendNewMail()
|
||||
{
|
||||
// deliver undelivered mail
|
||||
WorldPacket data(SMSG_RECEIVED_MAIL, 4);
|
||||
data << (uint32) 0;
|
||||
GetSession()->SendPacket(&data);
|
||||
WorldPackets::Mail::NotifyRecievedMail notify;
|
||||
notify.Delay = 0.0f;
|
||||
|
||||
GetSession()->SendPacket(notify.Write());
|
||||
}
|
||||
|
||||
void Player::UpdateNextMailTimeAndUnreads()
|
||||
|
||||
@@ -1835,8 +1835,7 @@ class Player : public Unit, public GridObject<Player>
|
||||
uint32 GetMailSize() { return m_mail.size();}
|
||||
Mail* GetMail(uint32 id);
|
||||
|
||||
PlayerMails::iterator GetMailBegin() { return m_mail.begin();}
|
||||
PlayerMails::iterator GetMailEnd() { return m_mail.end();}
|
||||
PlayerMails const& GetMails() const { return m_mail; }
|
||||
|
||||
void SendItemRetrievalMail(uint32 itemEntry, uint32 count); // Item retrieval mails sent by The Postmaster (34337), used in multiple places.
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "World.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
#include "MailPackets.h"
|
||||
#include "Language.h"
|
||||
#include "DBCStores.h"
|
||||
#include "Item.h"
|
||||
@@ -57,91 +58,18 @@ bool WorldSession::CanOpenMailBox(ObjectGuid guid)
|
||||
return true;
|
||||
}
|
||||
|
||||
void WorldSession::HandleSendMail(WorldPacket& recvData)
|
||||
void WorldSession::HandleSendMail(WorldPackets::Mail::SendMail& packet)
|
||||
{
|
||||
ObjectGuid mailbox;
|
||||
uint64 money, COD;
|
||||
std::string receiverName, subject, body;
|
||||
uint32 bodyLength, subjectLength, receiverLength;
|
||||
uint32 package, stationery;
|
||||
|
||||
recvData >> package;
|
||||
recvData >> stationery;
|
||||
|
||||
recvData >> COD >> money; // money and cod
|
||||
bodyLength = recvData.ReadBits(12);
|
||||
subjectLength = recvData.ReadBits(9);
|
||||
|
||||
uint8 items_count = recvData.ReadBits(5); // attached items count
|
||||
|
||||
if (items_count > MAX_MAIL_ITEMS) // client limit
|
||||
if (packet.Info.Attachments.size() > MAX_MAIL_ITEMS) // client limit
|
||||
{
|
||||
GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_TOO_MANY_ATTACHMENTS);
|
||||
recvData.rfinish(); // set to end to avoid warnings spam
|
||||
return;
|
||||
}
|
||||
|
||||
mailbox[0] = recvData.ReadBit();
|
||||
|
||||
ObjectGuid itemGUIDs[MAX_MAIL_ITEMS];
|
||||
|
||||
for (uint8 i = 0; i < items_count; ++i)
|
||||
{
|
||||
itemGUIDs[i][2] = recvData.ReadBit();
|
||||
itemGUIDs[i][6] = recvData.ReadBit();
|
||||
itemGUIDs[i][3] = recvData.ReadBit();
|
||||
itemGUIDs[i][7] = recvData.ReadBit();
|
||||
itemGUIDs[i][1] = recvData.ReadBit();
|
||||
itemGUIDs[i][0] = recvData.ReadBit();
|
||||
itemGUIDs[i][4] = recvData.ReadBit();
|
||||
itemGUIDs[i][5] = recvData.ReadBit();
|
||||
}
|
||||
|
||||
mailbox[3] = recvData.ReadBit();
|
||||
mailbox[4] = recvData.ReadBit();
|
||||
receiverLength = recvData.ReadBits(7);
|
||||
mailbox[2] = recvData.ReadBit();
|
||||
mailbox[6] = recvData.ReadBit();
|
||||
mailbox[1] = recvData.ReadBit();
|
||||
mailbox[7] = recvData.ReadBit();
|
||||
mailbox[5] = recvData.ReadBit();
|
||||
|
||||
recvData.ReadByteSeq(mailbox[4]);
|
||||
|
||||
for (uint8 i = 0; i < items_count; ++i)
|
||||
{
|
||||
recvData.ReadByteSeq(itemGUIDs[i][6]);
|
||||
recvData.ReadByteSeq(itemGUIDs[i][1]);
|
||||
recvData.ReadByteSeq(itemGUIDs[i][7]);
|
||||
recvData.ReadByteSeq(itemGUIDs[i][2]);
|
||||
recvData.read_skip<uint8>(); // item slot in mail, not used
|
||||
recvData.ReadByteSeq(itemGUIDs[i][3]);
|
||||
recvData.ReadByteSeq(itemGUIDs[i][0]);
|
||||
recvData.ReadByteSeq(itemGUIDs[i][4]);
|
||||
recvData.ReadByteSeq(itemGUIDs[i][5]);
|
||||
}
|
||||
|
||||
recvData.ReadByteSeq(mailbox[7]);
|
||||
recvData.ReadByteSeq(mailbox[3]);
|
||||
recvData.ReadByteSeq(mailbox[6]);
|
||||
recvData.ReadByteSeq(mailbox[5]);
|
||||
|
||||
subject = recvData.ReadString(subjectLength);
|
||||
receiverName = recvData.ReadString(receiverLength);
|
||||
|
||||
recvData.ReadByteSeq(mailbox[2]);
|
||||
recvData.ReadByteSeq(mailbox[0]);
|
||||
|
||||
body = recvData.ReadString(bodyLength);
|
||||
|
||||
recvData.ReadByteSeq(mailbox[1]);
|
||||
|
||||
// packet read complete, now do check
|
||||
|
||||
if (!CanOpenMailBox(mailbox))
|
||||
if (!CanOpenMailBox(packet.Info.Mailbox))
|
||||
return;
|
||||
|
||||
if (receiverName.empty())
|
||||
if (packet.Info.Target.empty())
|
||||
return;
|
||||
|
||||
Player* player = _player;
|
||||
@@ -153,23 +81,39 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
|
||||
}
|
||||
|
||||
ObjectGuid receiverGuid;
|
||||
if (normalizePlayerName(receiverName))
|
||||
receiverGuid = ObjectMgr::GetPlayerGUIDByName(receiverName);
|
||||
if (normalizePlayerName(packet.Info.Target))
|
||||
receiverGuid = ObjectMgr::GetPlayerGUIDByName(packet.Info.Target);
|
||||
|
||||
if (!receiverGuid)
|
||||
{
|
||||
TC_LOG_INFO("network", "Player %s is sending mail to %s (GUID: not existed!) with subject %s "
|
||||
"and body %s includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u",
|
||||
player->GetGUID().ToString().c_str(), receiverName.c_str(), subject.c_str(), body.c_str(),
|
||||
items_count, money, COD, stationery, package);
|
||||
"and body %s includes " SZFMTD " items, " SI64FMTD " copper and " SI64FMTD " COD copper with StationeryID = %d, PackageID = %d",
|
||||
GetPlayerInfo().c_str(), packet.Info.Target.c_str(), packet.Info.Subject.c_str(), packet.Info.Body.c_str(),
|
||||
packet.Info.Attachments.size(), packet.Info.SendMoney, packet.Info.Cod, packet.Info.StationeryID, packet.Info.PackageID);
|
||||
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_RECIPIENT_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet.Info.SendMoney < 0)
|
||||
{
|
||||
GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_INTERNAL_ERROR);
|
||||
TC_LOG_WARN("cheat", "Player %s attempted to send mail to %s (%s) with negative money value (SendMoney: " SI64FMTD ")",
|
||||
GetPlayerInfo().c_str(), packet.Info.Target.c_str(), receiverGuid.ToString().c_str(), packet.Info.SendMoney);
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet.Info.Cod < 0)
|
||||
{
|
||||
GetPlayer()->SendMailResult(0, MAIL_SEND, MAIL_ERR_INTERNAL_ERROR);
|
||||
TC_LOG_WARN("cheat", "Player %s attempted to send mail to %s (%s) with negative COD value (Cod: " SI64FMTD ")",
|
||||
GetPlayerInfo().c_str(), packet.Info.Target.c_str(), receiverGuid.ToString().c_str(), packet.Info.Cod);
|
||||
return;
|
||||
}
|
||||
|
||||
TC_LOG_INFO("network", "Player %s is sending mail to %s (%s) with subject %s and body %s "
|
||||
"includes %u items, " UI64FMTD " copper and " UI64FMTD " COD copper with unk1 = %u, unk2 = %u",
|
||||
player->GetGUID().ToString().c_str(), receiverName.c_str(), receiverGuid.ToString().c_str(), subject.c_str(),
|
||||
body.c_str(), items_count, money, COD, stationery, package);
|
||||
"includes " SZFMTD " items, " SI64FMTD " copper and " SI64FMTD " COD copper with StationeryID = %d, PackageID = %d",
|
||||
GetPlayerInfo().c_str(), packet.Info.Target.c_str(), receiverGuid.ToString().c_str(), packet.Info.Subject.c_str(),
|
||||
packet.Info.Body.c_str(), packet.Info.Attachments.size(), packet.Info.SendMoney, packet.Info.Cod, packet.Info.StationeryID, packet.Info.PackageID);
|
||||
|
||||
if (player->GetGUID() == receiverGuid)
|
||||
{
|
||||
@@ -177,12 +121,12 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 cost = items_count ? 30 * items_count : 30; // price hardcoded in client
|
||||
uint32 cost = !packet.Info.Attachments.empty() ? 30 * packet.Info.Attachments.size() : 30; // price hardcoded in client
|
||||
|
||||
uint64 reqmoney = cost + money;
|
||||
int64 reqmoney = cost + packet.Info.SendMoney;
|
||||
|
||||
// Check for overflow
|
||||
if (reqmoney < money)
|
||||
if (reqmoney < packet.Info.SendMoney)
|
||||
{
|
||||
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_NOT_ENOUGH_MONEY);
|
||||
return;
|
||||
@@ -246,10 +190,10 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
|
||||
}
|
||||
|
||||
// test the receiver's Faction... or all items are account bound
|
||||
bool accountBound = items_count ? true : false;
|
||||
for (uint8 i = 0; i < items_count; ++i)
|
||||
bool accountBound = !packet.Info.Attachments.empty();
|
||||
for (auto const& att : packet.Info.Attachments)
|
||||
{
|
||||
if (Item* item = player->GetItemByGuid(itemGUIDs[i]))
|
||||
if (Item* item = player->GetItemByGuid(att.ItemGUID))
|
||||
{
|
||||
ItemTemplate const* itemProto = item->GetTemplate();
|
||||
if (!itemProto || !(itemProto->GetFlags() & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT))
|
||||
@@ -272,17 +216,17 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
Item* items[MAX_MAIL_ITEMS];
|
||||
std::vector<Item*> items;
|
||||
|
||||
for (uint8 i = 0; i < items_count; ++i)
|
||||
for (auto const& att : packet.Info.Attachments)
|
||||
{
|
||||
if (!itemGUIDs[i])
|
||||
if (att.ItemGUID.IsEmpty())
|
||||
{
|
||||
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_MAIL_ATTACHMENT_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
Item* item = player->GetItemByGuid(itemGUIDs[i]);
|
||||
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)
|
||||
@@ -312,7 +256,7 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
if (COD && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED))
|
||||
if (packet.Info.Cod && item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED))
|
||||
{
|
||||
player->SendMailResult(0, MAIL_SEND, MAIL_ERR_CANT_SEND_WRAPPED_COD);
|
||||
return;
|
||||
@@ -324,38 +268,37 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
items[i] = item;
|
||||
items.push_back(item);
|
||||
}
|
||||
|
||||
player->SendMailResult(0, MAIL_SEND, MAIL_OK);
|
||||
|
||||
player->ModifyMoney(-int64(reqmoney));
|
||||
player->ModifyMoney(-reqmoney);
|
||||
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost);
|
||||
|
||||
bool needItemDelay = false;
|
||||
|
||||
MailDraft draft(subject, body);
|
||||
MailDraft draft(packet.Info.Subject, packet.Info.Body);
|
||||
|
||||
SQLTransaction trans = CharacterDatabase.BeginTransaction();
|
||||
|
||||
if (items_count > 0 || money > 0)
|
||||
if (!packet.Info.Attachments.empty() || packet.Info.SendMoney > 0)
|
||||
{
|
||||
bool log = HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE);
|
||||
if (items_count > 0)
|
||||
if (!packet.Info.Attachments.empty())
|
||||
{
|
||||
for (uint8 i = 0; i < items_count; ++i)
|
||||
for (auto const& item : items)
|
||||
{
|
||||
Item* item = items[i];
|
||||
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(),
|
||||
receiverName.c_str(), receiverGuid.ToString().c_str(), receiverAccountId);
|
||||
packet.Info.Target.c_str(), receiverGuid.ToString().c_str(), receiverAccountId);
|
||||
}
|
||||
|
||||
item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable
|
||||
player->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true);
|
||||
player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true);
|
||||
|
||||
item->DeleteFromInventoryDB(trans); // deletes item from character's inventory
|
||||
item->SetOwnerGUID(receiverGuid);
|
||||
@@ -368,10 +311,10 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
|
||||
needItemDelay = player->GetSession()->GetAccountId() != receiverAccountId;
|
||||
}
|
||||
|
||||
if (log && money > 0)
|
||||
if (log && packet.Info.SendMoney > 0)
|
||||
{
|
||||
sLog->outCommand(GetAccountId(), "GM %s (%s) (Account: %u) mail money: " UI64FMTD " to: %s (%s) (Account: %u)",
|
||||
GetPlayerName().c_str(), _player->GetGUID().ToString().c_str(), GetAccountId(), money, receiverName.c_str(), receiverGuid.ToString().c_str(), receiverAccountId);
|
||||
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(), packet.Info.SendMoney, packet.Info.Target.c_str(), receiverGuid.ToString().c_str(), receiverAccountId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,32 +327,27 @@ void WorldSession::HandleSendMail(WorldPacket& recvData)
|
||||
deliver_delay = 0;
|
||||
|
||||
// don't ask for COD if there are no items
|
||||
if (items_count == 0)
|
||||
COD = 0;
|
||||
if (packet.Info.Attachments.empty())
|
||||
packet.Info.Cod = 0;
|
||||
|
||||
// will delete item or place to receiver mail list
|
||||
draft
|
||||
.AddMoney(money)
|
||||
.AddCOD(COD)
|
||||
.SendMailTo(trans, MailReceiver(receiver, receiverGuid.GetCounter()), MailSender(player), body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay);
|
||||
.AddMoney(packet.Info.SendMoney)
|
||||
.AddCOD(packet.Info.Cod)
|
||||
.SendMailTo(trans, MailReceiver(receiver, receiverGuid.GetCounter()), MailSender(player), packet.Info.Body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay);
|
||||
|
||||
player->SaveInventoryAndGoldToDB(trans);
|
||||
CharacterDatabase.CommitTransaction(trans);
|
||||
}
|
||||
|
||||
//called when mail is read
|
||||
void WorldSession::HandleMailMarkAsRead(WorldPacket& recvData)
|
||||
void WorldSession::HandleMailMarkAsRead(WorldPackets::Mail::MailMarkAsRead& packet)
|
||||
{
|
||||
ObjectGuid mailbox;
|
||||
uint32 mailId;
|
||||
recvData >> mailbox;
|
||||
recvData >> mailId;
|
||||
|
||||
if (!CanOpenMailBox(mailbox))
|
||||
if (!CanOpenMailBox(packet.Mailbox))
|
||||
return;
|
||||
|
||||
Player* player = _player;
|
||||
Mail* m = player->GetMail(mailId);
|
||||
Mail* m = player->GetMail(packet.MailID);
|
||||
if (m && m->state != MAIL_STATE_DELETED)
|
||||
{
|
||||
if (player->unReadMails)
|
||||
@@ -421,18 +359,9 @@ void WorldSession::HandleMailMarkAsRead(WorldPacket& recvData)
|
||||
}
|
||||
|
||||
//called when client deletes mail
|
||||
void WorldSession::HandleMailDelete(WorldPacket& recvData)
|
||||
void WorldSession::HandleMailDelete(WorldPackets::Mail::MailDelete& packet)
|
||||
{
|
||||
ObjectGuid mailbox;
|
||||
uint32 mailId;
|
||||
recvData >> mailbox;
|
||||
recvData >> mailId;
|
||||
recvData.read_skip<uint32>(); // mailTemplateId
|
||||
|
||||
if (!CanOpenMailBox(mailbox))
|
||||
return;
|
||||
|
||||
Mail* m = _player->GetMail(mailId);
|
||||
Mail* m = _player->GetMail(packet.MailID);
|
||||
Player* player = _player;
|
||||
player->m_mailsUpdated = true;
|
||||
if (m)
|
||||
@@ -440,45 +369,40 @@ void WorldSession::HandleMailDelete(WorldPacket& recvData)
|
||||
// delete shouldn't show up for COD mails
|
||||
if (m->COD)
|
||||
{
|
||||
player->SendMailResult(mailId, MAIL_DELETED, MAIL_ERR_INTERNAL_ERROR);
|
||||
player->SendMailResult(packet.MailID, MAIL_DELETED, MAIL_ERR_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
m->state = MAIL_STATE_DELETED;
|
||||
}
|
||||
player->SendMailResult(mailId, MAIL_DELETED, MAIL_OK);
|
||||
player->SendMailResult(packet.MailID, MAIL_DELETED, MAIL_OK);
|
||||
}
|
||||
|
||||
void WorldSession::HandleMailReturnToSender(WorldPacket& recvData)
|
||||
void WorldSession::HandleMailReturnToSender(WorldPackets::Mail::MailReturnToSender& packet)
|
||||
{
|
||||
ObjectGuid mailbox;
|
||||
uint32 mailId;
|
||||
recvData >> mailbox;
|
||||
recvData >> mailId;
|
||||
recvData.read_skip<uint64>(); // original sender GUID for return to, not used
|
||||
|
||||
if (!CanOpenMailBox(mailbox))
|
||||
return;
|
||||
//TODO: find a proper way to replace this check. Idea: Save Guid form MailGetList until CMSG_CLOSE_INTERACTION is sent
|
||||
/*if (!CanOpenMailBox(mailbox))
|
||||
return;*/
|
||||
|
||||
Player* player = _player;
|
||||
Mail* m = player->GetMail(mailId);
|
||||
if (!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL))
|
||||
Mail* m = player->GetMail(packet.MailID);
|
||||
if (!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(nullptr) || m->sender != packet.SenderGUID.GetCounter())
|
||||
{
|
||||
player->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, MAIL_ERR_INTERNAL_ERROR);
|
||||
player->SendMailResult(packet.MailID, MAIL_RETURNED_TO_SENDER, MAIL_ERR_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
//we can return mail now, so firstly delete the old one
|
||||
SQLTransaction trans = CharacterDatabase.BeginTransaction();
|
||||
|
||||
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_BY_ID);
|
||||
stmt->setUInt32(0, mailId);
|
||||
stmt->setUInt32(0, packet.MailID);
|
||||
trans->Append(stmt);
|
||||
|
||||
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_MAIL_ITEM_BY_ID);
|
||||
stmt->setUInt32(0, mailId);
|
||||
stmt->setUInt32(0, packet.MailID);
|
||||
trans->Append(stmt);
|
||||
|
||||
player->RemoveMail(mailId);
|
||||
player->RemoveMail(packet.MailID);
|
||||
|
||||
// only return mail if the player exists (and delete if not existing)
|
||||
if (m->messageType == MAIL_NORMAL && m->sender)
|
||||
@@ -502,54 +426,49 @@ void WorldSession::HandleMailReturnToSender(WorldPacket& recvData)
|
||||
CharacterDatabase.CommitTransaction(trans);
|
||||
|
||||
delete m; //we can deallocate old mail
|
||||
player->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, MAIL_OK);
|
||||
player->SendMailResult(packet.MailID, MAIL_RETURNED_TO_SENDER, MAIL_OK);
|
||||
}
|
||||
|
||||
//called when player takes item attached in mail
|
||||
void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
|
||||
void WorldSession::HandleMailTakeItem(WorldPackets::Mail::MailTakeItem& packet)
|
||||
{
|
||||
ObjectGuid mailbox;
|
||||
uint32 mailId;
|
||||
ObjectGuid::LowType itemId;
|
||||
recvData >> mailbox;
|
||||
recvData >> mailId;
|
||||
recvData >> itemId; // item guid low
|
||||
uint32 AttachID = packet.AttachID;
|
||||
|
||||
if (!CanOpenMailBox(mailbox))
|
||||
if (!CanOpenMailBox(packet.Mailbox))
|
||||
return;
|
||||
|
||||
Player* player = _player;
|
||||
|
||||
Mail* m = player->GetMail(mailId);
|
||||
if (!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL))
|
||||
Mail* m = player->GetMail(packet.MailID);
|
||||
if (!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(nullptr))
|
||||
{
|
||||
player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_INTERNAL_ERROR);
|
||||
player->SendMailResult(packet.MailID, MAIL_ITEM_TAKEN, MAIL_ERR_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// verify that the mail has the item to avoid cheaters taking COD items without paying
|
||||
if (std::find_if(m->items.begin(), m->items.end(), [itemId](MailItemInfo info){ return info.item_guid == itemId; }) == m->items.end())
|
||||
if (std::find_if(m->items.begin(), m->items.end(), [AttachID](MailItemInfo info){ return info.item_guid == AttachID; }) == m->items.end())
|
||||
{
|
||||
player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_INTERNAL_ERROR);
|
||||
player->SendMailResult(packet.MailID, MAIL_ITEM_TAKEN, MAIL_ERR_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// prevent cheating with skip client money check
|
||||
if (!player->HasEnoughMoney(uint64(m->COD)))
|
||||
{
|
||||
player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_NOT_ENOUGH_MONEY);
|
||||
player->SendMailResult(packet.MailID, MAIL_ITEM_TAKEN, MAIL_ERR_NOT_ENOUGH_MONEY);
|
||||
return;
|
||||
}
|
||||
|
||||
Item* it = player->GetMItem(itemId);
|
||||
Item* it = player->GetMItem(packet.AttachID);
|
||||
|
||||
ItemPosCountVec dest;
|
||||
uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, it, false);
|
||||
if (msg == EQUIP_ERR_OK)
|
||||
{
|
||||
SQLTransaction trans = CharacterDatabase.BeginTransaction();
|
||||
m->RemoveItem(itemId);
|
||||
m->removedItems.push_back(itemId);
|
||||
m->RemoveItem(packet.AttachID);
|
||||
m->removedItems.push_back(packet.AttachID);
|
||||
|
||||
if (m->COD > 0) //if there is COD, take COD money from player and send them to sender by mail
|
||||
{
|
||||
@@ -603,38 +522,30 @@ void WorldSession::HandleMailTakeItem(WorldPacket& recvData)
|
||||
player->_SaveMail(trans);
|
||||
CharacterDatabase.CommitTransaction(trans);
|
||||
|
||||
player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_OK, 0, itemId, count);
|
||||
player->SendMailResult(packet.MailID, MAIL_ITEM_TAKEN, MAIL_OK, 0, packet.AttachID, count);
|
||||
}
|
||||
else
|
||||
player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_EQUIP_ERROR, msg);
|
||||
player->SendMailResult(packet.MailID, MAIL_ITEM_TAKEN, MAIL_ERR_EQUIP_ERROR, msg);
|
||||
}
|
||||
|
||||
void WorldSession::HandleMailTakeMoney(WorldPacket& recvData)
|
||||
void WorldSession::HandleMailTakeMoney(WorldPackets::Mail::MailTakeMoney& packet)
|
||||
{
|
||||
ObjectGuid mailbox;
|
||||
uint64 money;
|
||||
uint32 mailId;
|
||||
|
||||
recvData >> mailbox;
|
||||
recvData >> mailId;
|
||||
recvData >> money;
|
||||
|
||||
if (!CanOpenMailBox(mailbox))
|
||||
if (!CanOpenMailBox(packet.Mailbox))
|
||||
return;
|
||||
|
||||
Player* player = _player;
|
||||
|
||||
Mail* m = player->GetMail(mailId);
|
||||
Mail* m = player->GetMail(packet.MailID);
|
||||
if ((!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) ||
|
||||
(money > 0 && m->money != money))
|
||||
(packet.Money > 0 && m->money != uint64(packet.Money)))
|
||||
{
|
||||
player->SendMailResult(mailId, MAIL_MONEY_TAKEN, MAIL_ERR_INTERNAL_ERROR);
|
||||
player->SendMailResult(packet.MailID, MAIL_MONEY_TAKEN, MAIL_ERR_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player->ModifyMoney(m->money, false))
|
||||
{
|
||||
player->SendMailResult(mailId, MAIL_MONEY_TAKEN, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_TOO_MUCH_GOLD);
|
||||
player->SendMailResult(packet.MailID, MAIL_MONEY_TAKEN, MAIL_ERR_EQUIP_ERROR, EQUIP_ERR_TOO_MUCH_GOLD);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -642,7 +553,7 @@ void WorldSession::HandleMailTakeMoney(WorldPacket& recvData)
|
||||
m->state = MAIL_STATE_CHANGED;
|
||||
player->m_mailsUpdated = true;
|
||||
|
||||
player->SendMailResult(mailId, MAIL_MONEY_TAKEN, MAIL_OK);
|
||||
player->SendMailResult(packet.MailID, MAIL_MONEY_TAKEN, MAIL_OK);
|
||||
|
||||
// save money and mail to prevent cheating
|
||||
SQLTransaction trans = CharacterDatabase.BeginTransaction();
|
||||
@@ -652,12 +563,9 @@ void WorldSession::HandleMailTakeMoney(WorldPacket& recvData)
|
||||
}
|
||||
|
||||
//called when player lists his received mails
|
||||
void WorldSession::HandleGetMailList(WorldPacket& recvData)
|
||||
void WorldSession::HandleGetMailList(WorldPackets::Mail::MailGetList& packet)
|
||||
{
|
||||
ObjectGuid mailbox;
|
||||
recvData >> mailbox;
|
||||
|
||||
if (!CanOpenMailBox(mailbox))
|
||||
if (!CanOpenMailBox(packet.Mailbox))
|
||||
return;
|
||||
|
||||
Player* player = _player;
|
||||
@@ -666,130 +574,42 @@ void WorldSession::HandleGetMailList(WorldPacket& recvData)
|
||||
if (!player->m_mailsLoaded)
|
||||
player->_LoadMail();
|
||||
|
||||
// client can't work with packets > max int16 value
|
||||
const uint32 maxPacketSize = 32767;
|
||||
WorldPackets::Mail::MailListResult response;
|
||||
response.TotalNumRecords = player->GetMailSize();
|
||||
|
||||
uint32 mailsCount = 0; // real send to client mails amount
|
||||
uint32 realCount = 0; // real mails amount
|
||||
|
||||
WorldPacket data(SMSG_MAIL_LIST_RESULT, 200); // guess size
|
||||
data << uint32(0); // real mail's count
|
||||
data << uint8(0); // mail's count
|
||||
time_t cur_time = time(NULL);
|
||||
|
||||
for (PlayerMails::iterator itr = player->GetMailBegin(); itr != player->GetMailEnd(); ++itr)
|
||||
time_t cur_time = time(nullptr);
|
||||
|
||||
for (Mail* m : player->GetMails())
|
||||
{
|
||||
// Only first 50 mails are displayed
|
||||
if (mailsCount >= 50)
|
||||
{
|
||||
realCount += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip deleted or not delivered (deliver delay not expired) mails
|
||||
if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time)
|
||||
if (m->state == MAIL_STATE_DELETED || cur_time < m->deliver_time)
|
||||
continue;
|
||||
|
||||
uint8 item_count = (*itr)->items.size(); // max count is MAX_MAIL_ITEMS (12)
|
||||
response.Mails.emplace_back(m, player);
|
||||
|
||||
size_t next_mail_size = 2+4+1+((*itr)->messageType == MAIL_NORMAL ? 8 : 4)+4*8+((*itr)->subject.size()+1)+((*itr)->body.size()+1)+1+item_count*(1+8+4+MAX_INSPECTED_ENCHANTMENT_SLOT*3*4+4+4+4+4+4+4+1);
|
||||
|
||||
if (data.wpos()+next_mail_size > maxPacketSize)
|
||||
{
|
||||
realCount += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
data << uint16(next_mail_size); // Message size
|
||||
data << uint32((*itr)->messageID); // Message ID
|
||||
data << uint8((*itr)->messageType); // Message Type
|
||||
|
||||
switch ((*itr)->messageType)
|
||||
{
|
||||
case MAIL_NORMAL: // sender guid
|
||||
data << ObjectGuid::Create<HighGuid::Player>((*itr)->sender);
|
||||
break;
|
||||
case MAIL_CREATURE:
|
||||
case MAIL_GAMEOBJECT:
|
||||
case MAIL_AUCTION:
|
||||
case MAIL_CALENDAR:
|
||||
data << uint32((*itr)->sender); // creature/gameobject entry, auction id, calendar event id?
|
||||
break;
|
||||
}
|
||||
|
||||
data << uint64((*itr)->COD); // COD
|
||||
data << uint32(0); // Package.dbc ID ?
|
||||
data << uint32((*itr)->stationery); // stationery (Stationery.dbc)
|
||||
data << uint64((*itr)->money); // Gold
|
||||
data << uint32((*itr)->checked); // flags
|
||||
data << float(float((*itr)->expire_time-time(NULL))/DAY); // Time
|
||||
data << uint32((*itr)->mailTemplateId); // mail template (MailTemplate.dbc)
|
||||
data << (*itr)->subject; // Subject string - once 00, when mail type = 3, max 256
|
||||
data << (*itr)->body; // message? max 8000
|
||||
data << uint8(item_count); // client limit is 0x10
|
||||
|
||||
for (uint8 i = 0; i < item_count; ++i)
|
||||
{
|
||||
Item* item = player->GetMItem((*itr)->items[i].item_guid);
|
||||
// item index (0-6?)
|
||||
data << uint8(i);
|
||||
// item guid low?
|
||||
data << uint64((item ? item->GetGUID().GetCounter() : UI64LIT(0)));
|
||||
// entry
|
||||
data << uint32((item ? item->GetEntry() : 0));
|
||||
for (uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j)
|
||||
{
|
||||
data << uint32((item ? item->GetEnchantmentId((EnchantmentSlot)j) : 0));
|
||||
data << uint32((item ? item->GetEnchantmentDuration((EnchantmentSlot)j) : 0));
|
||||
data << uint32((item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0));
|
||||
}
|
||||
|
||||
// can be negative
|
||||
data << int32((item ? item->GetItemRandomPropertyId() : 0));
|
||||
// unk
|
||||
data << uint32((item ? item->GetItemSuffixFactor() : 0));
|
||||
// stack count
|
||||
data << uint32((item ? item->GetCount() : 0));
|
||||
// charges
|
||||
data << uint32((item ? item->GetSpellCharges() : 0));
|
||||
// durability
|
||||
data << uint32((item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0));
|
||||
// durability
|
||||
data << uint32((item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0));
|
||||
// unknown wotlk
|
||||
data << uint8(0);
|
||||
}
|
||||
|
||||
++realCount;
|
||||
++mailsCount;
|
||||
// max. 50 mails can be sent
|
||||
if (response.Mails.size() >= 50)
|
||||
break;
|
||||
}
|
||||
|
||||
data.put<uint32>(0, realCount); // this will display warning about undelivered mail to player if realCount > mailsCount
|
||||
data.put<uint8>(4, mailsCount); // set real send mails to client
|
||||
SendPacket(&data);
|
||||
SendPacket(response.Write());
|
||||
|
||||
// recalculate m_nextMailDelivereTime and unReadMails
|
||||
_player->UpdateNextMailTimeAndUnreads();
|
||||
}
|
||||
|
||||
//used when player copies mail body to his inventory
|
||||
void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData)
|
||||
void WorldSession::HandleMailCreateTextItem(WorldPackets::Mail::MailCreateTextItem& packet)
|
||||
{
|
||||
ObjectGuid mailbox;
|
||||
uint32 mailId;
|
||||
|
||||
recvData >> mailbox;
|
||||
recvData >> mailId;
|
||||
|
||||
if (!CanOpenMailBox(mailbox))
|
||||
if (!CanOpenMailBox(packet.Mailbox))
|
||||
return;
|
||||
|
||||
Player* player = _player;
|
||||
|
||||
Mail* m = player->GetMail(mailId);
|
||||
if (!m || (m->body.empty() && !m->mailTemplateId) || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL) || (m->checked & MAIL_CHECK_MASK_COPIED))
|
||||
Mail* m = player->GetMail(packet.MailID);
|
||||
if (!m || (m->body.empty() && !m->mailTemplateId) || m->state == MAIL_STATE_DELETED || m->deliver_time > time(nullptr) || (m->checked & MAIL_CHECK_MASK_COPIED))
|
||||
{
|
||||
player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_INTERNAL_ERROR);
|
||||
player->SendMailResult(packet.MailID, MAIL_MADE_PERMANENT, MAIL_ERR_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -806,7 +626,7 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData)
|
||||
MailTemplateEntry const* mailTemplateEntry = sMailTemplateStore.LookupEntry(m->mailTemplateId);
|
||||
if (!mailTemplateEntry)
|
||||
{
|
||||
player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_INTERNAL_ERROR);
|
||||
player->SendMailResult(packet.MailID, MAIL_MADE_PERMANENT, MAIL_ERR_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -820,8 +640,6 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData)
|
||||
|
||||
bodyItem->SetFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_MAIL_TEXT_MASK);
|
||||
|
||||
TC_LOG_INFO("network", "HandleMailCreateTextItem mailid=%u", mailId);
|
||||
|
||||
ItemPosCountVec dest;
|
||||
uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, bodyItem, false);
|
||||
if (msg == EQUIP_ERR_OK)
|
||||
@@ -831,65 +649,54 @@ void WorldSession::HandleMailCreateTextItem(WorldPacket& recvData)
|
||||
player->m_mailsUpdated = true;
|
||||
|
||||
player->StoreItem(dest, bodyItem, true);
|
||||
player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_OK);
|
||||
player->SendMailResult(packet.MailID, MAIL_MADE_PERMANENT, MAIL_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
player->SendMailResult(mailId, MAIL_MADE_PERMANENT, MAIL_ERR_EQUIP_ERROR, msg);
|
||||
player->SendMailResult(packet.MailID, MAIL_MADE_PERMANENT, MAIL_ERR_EQUIP_ERROR, msg);
|
||||
delete bodyItem;
|
||||
}
|
||||
}
|
||||
|
||||
/// @todo Fix me! ... this void has probably bad condition, but good data are sent
|
||||
void WorldSession::HandleQueryNextMailTime(WorldPacket& /*recvData*/)
|
||||
void WorldSession::HandleQueryNextMailTime(WorldPackets::Mail::MailQueryNextMailTime& /*packet*/)
|
||||
{
|
||||
WorldPacket data(SMSG_MAIL_QUERY_NEXT_TIME_RESULT, 8);
|
||||
WorldPackets::Mail::MailQueryNextTimeResult result;
|
||||
|
||||
if (!_player->m_mailsLoaded)
|
||||
_player->_LoadMail();
|
||||
|
||||
if (_player->unReadMails > 0)
|
||||
{
|
||||
data << float(0); // float
|
||||
data << uint32(0); // count
|
||||
result.NextMailTime = 0.0f;
|
||||
|
||||
uint32 count = 0;
|
||||
time_t now = time(NULL);
|
||||
time_t now = time(nullptr);
|
||||
std::set<ObjectGuid::LowType> sentSenders;
|
||||
for (PlayerMails::iterator itr = _player->GetMailBegin(); itr != _player->GetMailEnd(); ++itr)
|
||||
|
||||
for (Mail* mail : _player->GetMails())
|
||||
{
|
||||
Mail* m = (*itr);
|
||||
// must be not checked yet
|
||||
if (m->checked & MAIL_CHECK_MASK_READ)
|
||||
if (mail->checked & MAIL_CHECK_MASK_READ)
|
||||
continue;
|
||||
|
||||
// and already delivered
|
||||
if (now < m->deliver_time)
|
||||
// already delivered
|
||||
if (now < mail->deliver_time)
|
||||
continue;
|
||||
|
||||
// only send each mail sender once
|
||||
if (sentSenders.count(m->sender))
|
||||
if (sentSenders.count(mail->sender))
|
||||
continue;
|
||||
|
||||
data << (m->messageType == MAIL_NORMAL ? ObjectGuid::Create<HighGuid::Player>(m->sender) : ObjectGuid::Empty); // player guid
|
||||
data << uint32(m->messageType != MAIL_NORMAL ? m->sender : 0); // non-player entries
|
||||
data << uint32(m->messageType);
|
||||
data << uint32(m->stationery);
|
||||
data << float(m->deliver_time - now);
|
||||
result.Next.emplace_back(mail);
|
||||
|
||||
sentSenders.insert(m->sender);
|
||||
++count;
|
||||
if (count == 2) // do not display more than 2 mails
|
||||
sentSenders.insert(mail->sender);
|
||||
|
||||
// do not send more than 2 mails
|
||||
if (sentSenders.size() > 2)
|
||||
break;
|
||||
}
|
||||
|
||||
data.put<uint32>(4, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
data << float(-DAY);
|
||||
data << uint32(0);
|
||||
}
|
||||
result.NextMailTime = -DAY;
|
||||
|
||||
SendPacket(&data);
|
||||
SendPacket(result.Write());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Mail.h"
|
||||
#include "MailPackets.h"
|
||||
#include "Player.h"
|
||||
#include "World.h"
|
||||
|
||||
WorldPackets::Mail::MailAttachedItem::MailAttachedItem(::Item const* item, uint8 pos)
|
||||
{
|
||||
Position = pos;
|
||||
AttachID = item->GetGUID().GetCounter();
|
||||
Count = item->GetCount();
|
||||
Charges = item->GetSpellCharges();
|
||||
MaxDurability = item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY);
|
||||
Durability = item->GetUInt32Value(ITEM_FIELD_DURABILITY);
|
||||
Unlocked = !item->IsLocked(); //TODO: Check
|
||||
|
||||
for (uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; j++)
|
||||
{
|
||||
Enchants[j].Enchant = item->GetEnchantmentId((EnchantmentSlot)j);
|
||||
Enchants[j].Duration = item->GetEnchantmentDuration((EnchantmentSlot)j);
|
||||
Enchants[j].Charges = item->GetEnchantmentCharges((EnchantmentSlot)j);
|
||||
}
|
||||
}
|
||||
|
||||
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Mail::MailAttachedItem const& att)
|
||||
{
|
||||
data << uint8(att.Position);
|
||||
data << uint32(att.AttachID);
|
||||
data << WorldPackets::Item::ItemInstance(att.Item);
|
||||
|
||||
for (auto const& en : att.Enchants)
|
||||
{
|
||||
data << int32(en.Enchant);
|
||||
data << int32(en.Duration);
|
||||
data << int32(en.Charges);
|
||||
}
|
||||
|
||||
data << int32(att.Count);
|
||||
data << int32(att.Charges);
|
||||
data << int32(att.MaxDurability);
|
||||
data << int32(att.Durability);
|
||||
data.WriteBit(att.Unlocked);
|
||||
data.FlushBits();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
WorldPackets::Mail::MailListEntry::MailListEntry(::Mail const* mail, ::Player* player)
|
||||
{
|
||||
MailID = mail->messageID;
|
||||
SenderType = mail->messageType;
|
||||
|
||||
switch (mail->messageType)
|
||||
{
|
||||
case MAIL_NORMAL:
|
||||
SenderCharacter.Set(ObjectGuid::Create<HighGuid::Player>(mail->sender));
|
||||
SenderHint.NativeRealmAddress.Set(GetVirtualRealmAddress());
|
||||
SenderHint.VirtualRealmAddress.Set(GetVirtualRealmAddress());
|
||||
break;
|
||||
case MAIL_CREATURE:
|
||||
case MAIL_GAMEOBJECT:
|
||||
case MAIL_AUCTION:
|
||||
case MAIL_CALENDAR:
|
||||
AltSenderID.Set(mail->sender);
|
||||
break;
|
||||
}
|
||||
|
||||
Cod = mail->COD;
|
||||
PackageID = 0;
|
||||
StationeryID = mail->stationery;
|
||||
SentMoney = mail->money;
|
||||
Flags = mail->checked;
|
||||
DaysLeft = float(mail->expire_time - time(nullptr)) / DAY;
|
||||
MailTemplateID = mail->mailTemplateId;
|
||||
Subject = mail->subject;
|
||||
Body = mail->body;
|
||||
|
||||
for (uint8 i = 0; i < mail->items.size(); i++)
|
||||
{
|
||||
if (::Item* item = player->GetMItem(mail->items[i].item_guid))
|
||||
Attachments.emplace_back(item, i);
|
||||
}
|
||||
}
|
||||
|
||||
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Mail::MailListEntry const& entry)
|
||||
{
|
||||
data << int32(entry.MailID);
|
||||
data << int8(entry.SenderType);
|
||||
|
||||
data << entry.SenderHint;
|
||||
|
||||
data << int64(entry.Cod);
|
||||
data << int32(entry.PackageID);
|
||||
data << int32(entry.StationeryID);
|
||||
data << int64(entry.SentMoney);
|
||||
data << int32(entry.Flags);
|
||||
data << float(entry.DaysLeft);
|
||||
data << int32(entry.MailTemplateID);
|
||||
|
||||
data << int32(entry.Attachments.size());
|
||||
|
||||
for (auto const& att : entry.Attachments)
|
||||
data << att;
|
||||
|
||||
data.WriteBit(entry.SenderCharacter.HasValue);
|
||||
data.WriteBit(entry.AltSenderID.HasValue);
|
||||
data.WriteBits(entry.Subject.size(), 8);
|
||||
data.WriteBits(entry.Body.size(), 13);
|
||||
data.FlushBits();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void WorldPackets::Mail::MailGetList::Read()
|
||||
{
|
||||
_worldPacket >> Mailbox;
|
||||
LowGuids.resize(_worldPacket.read<int32>());
|
||||
|
||||
for (auto& l : LowGuids)
|
||||
_worldPacket >> l;
|
||||
}
|
||||
|
||||
WorldPacket const* WorldPackets::Mail::MailListResult::Write()
|
||||
{
|
||||
_worldPacket << int32(Mails.size());
|
||||
_worldPacket << int32(TotalNumRecords);
|
||||
|
||||
for (auto const& mail : Mails)
|
||||
_worldPacket << mail;
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
void WorldPackets::Mail::MailCreateTextItem::Read()
|
||||
{
|
||||
_worldPacket >> Mailbox;
|
||||
_worldPacket >> MailID;
|
||||
}
|
||||
|
||||
void WorldPackets::Mail::SendMail::Read()
|
||||
{
|
||||
_worldPacket >> Info.Mailbox;
|
||||
_worldPacket >> Info.StationeryID;
|
||||
_worldPacket >> Info.PackageID;
|
||||
_worldPacket >> Info.SendMoney;
|
||||
_worldPacket >> Info.Cod;
|
||||
|
||||
uint32 targetLength = _worldPacket.ReadBits(9);
|
||||
uint32 subjectLength = _worldPacket.ReadBits(9);
|
||||
uint32 bodyLength = _worldPacket.ReadBits(11);
|
||||
|
||||
Info.Attachments.resize(_worldPacket.ReadBits(5));
|
||||
|
||||
Info.Target = _worldPacket.ReadString(targetLength);
|
||||
Info.Subject = _worldPacket.ReadString(subjectLength);
|
||||
Info.Body = _worldPacket.ReadString(bodyLength);
|
||||
|
||||
for (auto& att : Info.Attachments)
|
||||
{
|
||||
_worldPacket >> att.AttachPosition;
|
||||
_worldPacket >> att.ItemGUID;
|
||||
}
|
||||
}
|
||||
|
||||
void WorldPackets::Mail::MailReturnToSender::Read()
|
||||
{
|
||||
_worldPacket >> MailID;
|
||||
_worldPacket >> SenderGUID;
|
||||
}
|
||||
|
||||
WorldPacket const* WorldPackets::Mail::MailCommandResult::Write()
|
||||
{
|
||||
_worldPacket << uint32(MailID);
|
||||
_worldPacket << uint32(Command);
|
||||
_worldPacket << uint32(ErrorCode);
|
||||
_worldPacket << uint32(BagResult);
|
||||
_worldPacket << uint32(AttachID);
|
||||
_worldPacket << uint32(QtyInInventory);
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
void WorldPackets::Mail::MailMarkAsRead::Read()
|
||||
{
|
||||
_worldPacket >> Mailbox;
|
||||
_worldPacket >> MailID;
|
||||
BiReceipt = _worldPacket.ReadBit();
|
||||
}
|
||||
|
||||
void WorldPackets::Mail::MailDelete::Read()
|
||||
{
|
||||
_worldPacket >> MailID;
|
||||
_worldPacket >> DeleteReason;
|
||||
}
|
||||
|
||||
void WorldPackets::Mail::MailTakeItem::Read()
|
||||
{
|
||||
_worldPacket >> Mailbox;
|
||||
_worldPacket >> MailID;
|
||||
_worldPacket >> AttachID;
|
||||
}
|
||||
|
||||
void WorldPackets::Mail::MailTakeMoney::Read()
|
||||
{
|
||||
_worldPacket >> Mailbox;
|
||||
_worldPacket >> MailID;
|
||||
_worldPacket >> Money;
|
||||
}
|
||||
|
||||
WorldPackets::Mail::MailQueryNextTimeResult::MailNextTimeEntry::MailNextTimeEntry(::Mail const* mail)
|
||||
{
|
||||
switch (mail->messageType)
|
||||
{
|
||||
case MAIL_NORMAL:
|
||||
SenderGuid = ObjectGuid::Create<HighGuid::Player>(mail->sender);
|
||||
SenderHint.NativeRealmAddress.Set(GetVirtualRealmAddress());
|
||||
SenderHint.VirtualRealmAddress.Set(GetVirtualRealmAddress());
|
||||
break;
|
||||
case MAIL_AUCTION:
|
||||
case MAIL_CREATURE:
|
||||
case MAIL_GAMEOBJECT:
|
||||
case MAIL_CALENDAR:
|
||||
AltSenderID = mail->sender;
|
||||
break;
|
||||
}
|
||||
|
||||
TimeLeft = mail->deliver_time - time(nullptr);
|
||||
AltSenderType = mail->messageType;
|
||||
StationeryID = mail->stationery;
|
||||
}
|
||||
|
||||
WorldPacket const* WorldPackets::Mail::MailQueryNextTimeResult::Write()
|
||||
{
|
||||
_worldPacket << float(NextMailTime);
|
||||
_worldPacket << int32(Next.size());
|
||||
|
||||
for (auto const& entry : Next)
|
||||
{
|
||||
_worldPacket << entry.SenderGuid;
|
||||
_worldPacket << entry.SenderHint;
|
||||
|
||||
_worldPacket << float(entry.TimeLeft);
|
||||
_worldPacket << int32(entry.AltSenderID);
|
||||
_worldPacket << int8(entry.AltSenderType);
|
||||
_worldPacket << int32(entry.StationeryID);
|
||||
}
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
WorldPacket const* WorldPackets::Mail::NotifyRecievedMail::Write()
|
||||
{
|
||||
_worldPacket << float(Delay);
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MailPackets_h__
|
||||
#define MailPackets_h__
|
||||
|
||||
#include "ItemPackets.h"
|
||||
#include "Packet.h"
|
||||
#include "QueryPackets.h"
|
||||
#include "ObjectGuid.h"
|
||||
|
||||
struct Mail;
|
||||
|
||||
namespace WorldPackets
|
||||
{
|
||||
namespace Mail
|
||||
{
|
||||
struct MailAttachedItemEnchant
|
||||
{
|
||||
int32 Enchant = 0;
|
||||
int32 Duration = 0;
|
||||
int32 Charges = 0;
|
||||
};
|
||||
|
||||
struct MailAttachedItem
|
||||
{
|
||||
MailAttachedItem(::Item const* item, uint8 pos);
|
||||
|
||||
uint8 Position = 0;
|
||||
int32 AttachID = 0;
|
||||
Item::ItemInstance Item;
|
||||
int32 Count = 0;
|
||||
int32 Charges = 0;
|
||||
int32 MaxDurability = 0;
|
||||
int32 Durability = 0;
|
||||
bool Unlocked = false;
|
||||
MailAttachedItemEnchant Enchants[8];
|
||||
};
|
||||
|
||||
struct MailListEntry
|
||||
{
|
||||
MailListEntry(::Mail const* mail, ::Player* player);
|
||||
|
||||
int32 MailID = 0;
|
||||
uint8 SenderType = 0;
|
||||
Optional<ObjectGuid> SenderCharacter;
|
||||
Query::PlayerGuidLookupHint SenderHint;
|
||||
Optional<uint32> AltSenderID;
|
||||
int64 Cod = 0;
|
||||
int32 PackageID = 0;
|
||||
int32 StationeryID = 0;
|
||||
int64 SentMoney = 0;
|
||||
int32 Flags = 0;
|
||||
float DaysLeft = 0.0f;
|
||||
int32 MailTemplateID = 0;
|
||||
std::string Subject;
|
||||
std::string Body;
|
||||
std::vector<MailAttachedItem> Attachments;
|
||||
};
|
||||
|
||||
class MailGetList final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
MailGetList(WorldPacket&& packet) : ClientPacket(CMSG_GET_MAIL_LIST, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
ObjectGuid Mailbox;
|
||||
std::vector<ObjectGuid::LowType> LowGuids;
|
||||
};
|
||||
|
||||
class MailListResult final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
MailListResult() : ServerPacket(SMSG_MAIL_LIST_RESULT, 8) { }
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
int32 TotalNumRecords = 0;
|
||||
std::vector<MailListEntry> Mails;
|
||||
};
|
||||
|
||||
class MailCreateTextItem final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
MailCreateTextItem(WorldPacket&& packet) : ClientPacket(CMSG_MAIL_CREATE_TEXT_ITEM, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
ObjectGuid Mailbox;
|
||||
uint32 MailID = 0;
|
||||
};
|
||||
|
||||
class SendMail final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
struct StructSendMail
|
||||
{
|
||||
struct MailAttachment
|
||||
{
|
||||
uint8 AttachPosition = 0;
|
||||
ObjectGuid ItemGUID;
|
||||
};
|
||||
|
||||
ObjectGuid Mailbox;
|
||||
int32 StationeryID = 0;
|
||||
int32 PackageID = 0;
|
||||
int64 SendMoney = 0;
|
||||
int64 Cod = 0;
|
||||
std::string Target;
|
||||
std::string Subject;
|
||||
std::string Body;
|
||||
std::vector<MailAttachment> Attachments;
|
||||
};
|
||||
|
||||
SendMail(WorldPacket&& packet) : ClientPacket(CMSG_SEND_MAIL, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
StructSendMail Info;
|
||||
};
|
||||
|
||||
class MailCommandResult final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
MailCommandResult() : ServerPacket(SMSG_SEND_MAIL_RESULT) { }
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
uint32 MailID = 0;
|
||||
uint32 Command = 0;
|
||||
uint32 ErrorCode = 0;
|
||||
uint32 BagResult = 0;
|
||||
uint32 AttachID = 0;
|
||||
uint32 QtyInInventory = 0;
|
||||
};
|
||||
|
||||
class MailReturnToSender final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
MailReturnToSender(WorldPacket&& packet) : ClientPacket(CMSG_MAIL_RETURN_TO_SENDER, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
int32 MailID = 0;
|
||||
ObjectGuid SenderGUID;
|
||||
};
|
||||
|
||||
class MailMarkAsRead final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
MailMarkAsRead(WorldPacket&& packet) : ClientPacket(CMSG_MAIL_MARK_AS_READ, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
ObjectGuid Mailbox;
|
||||
int32 MailID = 0;
|
||||
bool BiReceipt = false;
|
||||
};
|
||||
|
||||
class MailDelete final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
MailDelete(WorldPacket&& packet) : ClientPacket(CMSG_MAIL_DELETE, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
int32 MailID = 0;
|
||||
int32 DeleteReason = 0;
|
||||
};
|
||||
|
||||
class MailTakeItem final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
MailTakeItem(WorldPacket&& packet) : ClientPacket(CMSG_MAIL_TAKE_ITEM, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
ObjectGuid Mailbox;
|
||||
int32 MailID = 0;
|
||||
int32 AttachID = 0;
|
||||
};
|
||||
|
||||
class MailTakeMoney final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
MailTakeMoney(WorldPacket&& packet) : ClientPacket(CMSG_MAIL_TAKE_MONEY, std::move(packet)) { }
|
||||
|
||||
void Read() override;
|
||||
|
||||
ObjectGuid Mailbox;
|
||||
int32 MailID = 0;
|
||||
int64 Money = 0;
|
||||
};
|
||||
|
||||
class MailQueryNextMailTime final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
MailQueryNextMailTime(WorldPacket&& packet) : ClientPacket(CMSG_QUERY_NEXT_MAIL_TIME, std::move(packet)) { }
|
||||
|
||||
void Read() override { }
|
||||
};
|
||||
|
||||
class MailQueryNextTimeResult final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
struct MailNextTimeEntry
|
||||
{
|
||||
MailNextTimeEntry(::Mail const* mail);
|
||||
|
||||
ObjectGuid SenderGuid;
|
||||
Query::PlayerGuidLookupHint SenderHint;
|
||||
float TimeLeft = 0.0f;
|
||||
int32 AltSenderID = 0;
|
||||
int8 AltSenderType = 0;
|
||||
int32 StationeryID = 0;
|
||||
};
|
||||
|
||||
MailQueryNextTimeResult() : ServerPacket(SMSG_MAIL_QUERY_NEXT_TIME_RESULT, 8) { }
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
float NextMailTime = 0.0f;
|
||||
std::vector<MailNextTimeEntry> Next;
|
||||
};
|
||||
|
||||
class NotifyRecievedMail : ServerPacket
|
||||
{
|
||||
public:
|
||||
NotifyRecievedMail() : ServerPacket(SMSG_NOTIFY_RECEIVED_MAIL, 4) { }
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
float Delay = 0.0f;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Mail::MailAttachedItem const& att);
|
||||
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Mail::MailListEntry const& entry);
|
||||
|
||||
#endif // MailPackets_h__
|
||||
@@ -107,6 +107,21 @@ void WorldPackets::Query::QueryPlayerName::Read()
|
||||
_worldPacket >> Hint.NativeRealmAddress.Value;
|
||||
}
|
||||
|
||||
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Query::PlayerGuidLookupHint const& lookupHint)
|
||||
{
|
||||
data.WriteBit(lookupHint.VirtualRealmAddress.HasValue);
|
||||
data.WriteBit(lookupHint.NativeRealmAddress.HasValue);
|
||||
data.FlushBits();
|
||||
|
||||
if (lookupHint.VirtualRealmAddress.HasValue)
|
||||
data << uint32(lookupHint.VirtualRealmAddress.Value);
|
||||
|
||||
if (lookupHint.NativeRealmAddress.HasValue)
|
||||
data << uint32(lookupHint.NativeRealmAddress.Value);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
bool WorldPackets::Query::PlayerGuidLookupData::Initialize(ObjectGuid const& guid, Player const* player /*= nullptr*/)
|
||||
{
|
||||
CharacterInfo const* characterInfo = sWorld->GetCharacterInfo(guid);
|
||||
|
||||
@@ -323,6 +323,7 @@ namespace WorldPackets
|
||||
}
|
||||
}
|
||||
|
||||
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Query::PlayerGuidLookupHint const& lookupHint);
|
||||
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Query::PlayerGuidLookupData const& lookupData);
|
||||
|
||||
#endif // QueryPackets_h__
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "Packets/InspectPackets.h"
|
||||
#include "Packets/ItemPackets.h"
|
||||
#include "Packets/LootPackets.h"
|
||||
#include "Packets/MailPackets.h"
|
||||
#include "Packets/MiscPackets.h"
|
||||
#include "Packets/MovementPackets.h"
|
||||
#include "Packets/NPCPackets.h"
|
||||
@@ -377,7 +378,7 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_GET_CHALLENGE_MODE_REWARDS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_GET_GARRISON_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_HANDLER(CMSG_GET_ITEM_PURCHASE_DATA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::GetItemPurchaseData, &WorldSession::HandleGetItemPurchaseData);
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_GET_MAIL_LIST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGetMailList );
|
||||
DEFINE_HANDLER(CMSG_GET_MAIL_LIST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::MailGetList, &WorldSession::HandleGetMailList);
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_GET_MIRROR_IMAGE_DATA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMirrorImageDataRequest );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_GET_SHIPMENT_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_GET_TROPHY_LIST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
@@ -529,12 +530,12 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_LOOT_ROLL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLootRoll );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_LOW_LEVEL_RAID1, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_LOW_LEVEL_RAID2, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_MAIL_CREATE_TEXT_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMailCreateTextItem );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_MAIL_DELETE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMailDelete );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_MAIL_MARK_AS_READ, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMailMarkAsRead );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_MAIL_RETURN_TO_SENDER, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMailReturnToSender );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_MAIL_TAKE_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMailTakeItem );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_MAIL_TAKE_MONEY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMailTakeMoney );
|
||||
DEFINE_HANDLER(CMSG_MAIL_CREATE_TEXT_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::MailCreateTextItem, &WorldSession::HandleMailCreateTextItem);
|
||||
DEFINE_HANDLER(CMSG_MAIL_DELETE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::MailDelete, &WorldSession::HandleMailDelete);
|
||||
DEFINE_HANDLER(CMSG_MAIL_MARK_AS_READ, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::MailMarkAsRead, &WorldSession::HandleMailMarkAsRead);
|
||||
DEFINE_HANDLER(CMSG_MAIL_RETURN_TO_SENDER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::MailReturnToSender, &WorldSession::HandleMailReturnToSender);
|
||||
DEFINE_HANDLER(CMSG_MAIL_TAKE_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::MailTakeItem, &WorldSession::HandleMailTakeItem);
|
||||
DEFINE_HANDLER(CMSG_MAIL_TAKE_MONEY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::MailTakeMoney, &WorldSession::HandleMailTakeMoney);
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_MASTER_LOOT_ITEM, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_MEETINGSTONE_INFO, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_MESSAGECHAT_ADDON_CHANNEL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
@@ -690,7 +691,7 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_QUERY_COUNTDOWN_TIMER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_QUERY_GUILD_XP, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryXPOpcode );
|
||||
DEFINE_HANDLER(CMSG_QUERY_INSPECT_ACHIEVEMENTS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Inspect::QueryInspectAchievements, &WorldSession::HandleQueryInspectAchievements);
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_QUERY_NEXT_MAIL_TIME, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryNextMailTime );
|
||||
DEFINE_HANDLER(CMSG_QUERY_NEXT_MAIL_TIME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::MailQueryNextMailTime, &WorldSession::HandleQueryNextMailTime);
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_QUERY_PETITION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_QUERY_SCENARIO_POI, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_HANDLER(CMSG_QUERY_TIME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Query::QueryTime, &WorldSession::HandleQueryTimeOpcode);
|
||||
@@ -768,7 +769,7 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_SELF_RES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSelfResOpcode );
|
||||
DEFINE_HANDLER(CMSG_SELL_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Item::SellItem, &WorldSession::HandleSellItemOpcode);
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_SEND_CONTACT_LIST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleContactListOpcode );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_SEND_MAIL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSendMail );
|
||||
DEFINE_HANDLER(CMSG_SEND_MAIL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Mail::SendMail, &WorldSession::HandleSendMail);
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_SEND_SOR_REQUEST_VIA_ADDRESS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_SEND_SOR_REQUEST_VIA_BNET_ACCOUNT_ID, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
DEFINE_OPCODE_HANDLER_OLD(CMSG_SERVERTIME, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
@@ -1477,8 +1478,8 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOOT_ROLL_WON, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOOT_SLOT_CHANGED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOSS_OF_CONTROL_AURA_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAIL_LIST_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAIL_QUERY_NEXT_TIME_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAIL_LIST_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAIL_QUERY_NEXT_TIME_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAP_OBJECTIVES_INIT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MAP_OBJ_EVENTS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MASTER_LOOT_CANDIDATE_LIST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
@@ -1594,7 +1595,7 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_DEST_LOC_SPELL_CAST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_MISSILE_TRAJECTORY_COLLISION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_MONEY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_RECEIVED_MAIL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_RECEIVED_MAIL, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NPC_TEXT_UPDATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NPC_WONT_TALK, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_OFFER_PETITION_ERROR, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
@@ -1782,7 +1783,7 @@ void OpcodeTable::Initialize()
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SELL_ITEM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SELL_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_ITEM_PASSIVES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_MAIL_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_MAIL_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_RAID_TARGET_UPDATE_ALL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_RAID_TARGET_UPDATE_SINGLE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_SPELL_CHARGES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
|
||||
@@ -198,6 +198,19 @@ namespace WorldPackets
|
||||
class LootMoney;
|
||||
}
|
||||
|
||||
namespace Mail
|
||||
{
|
||||
class MailCreateTextItem;
|
||||
class MailDelete;
|
||||
class MailGetList;
|
||||
class MailMarkAsRead;
|
||||
class MailQueryNextMailTime;
|
||||
class MailReturnToSender;
|
||||
class MailTakeItem;
|
||||
class MailTakeMoney;
|
||||
class SendMail;
|
||||
}
|
||||
|
||||
namespace Misc
|
||||
{
|
||||
class AreaTrigger;
|
||||
@@ -937,16 +950,16 @@ class WorldSession
|
||||
// Black Market
|
||||
void HandleBlackMarketOpen(WorldPackets::BlackMarket::BlackMarketOpen& packet);
|
||||
|
||||
void HandleGetMailList(WorldPacket& recvData);
|
||||
void HandleSendMail(WorldPacket& recvData);
|
||||
void HandleMailTakeMoney(WorldPacket& recvData);
|
||||
void HandleMailTakeItem(WorldPacket& recvData);
|
||||
void HandleMailMarkAsRead(WorldPacket& recvData);
|
||||
void HandleMailReturnToSender(WorldPacket& recvData);
|
||||
void HandleMailDelete(WorldPacket& recvData);
|
||||
void HandleGetMailList(WorldPackets::Mail::MailGetList& packet);
|
||||
void HandleSendMail(WorldPackets::Mail::SendMail& packet);
|
||||
void HandleMailTakeMoney(WorldPackets::Mail::MailTakeMoney& packet);
|
||||
void HandleMailTakeItem(WorldPackets::Mail::MailTakeItem& packet);
|
||||
void HandleMailMarkAsRead(WorldPackets::Mail::MailMarkAsRead& packet);
|
||||
void HandleMailReturnToSender(WorldPackets::Mail::MailReturnToSender& packet);
|
||||
void HandleMailDelete(WorldPackets::Mail::MailDelete& packet);
|
||||
void HandleItemTextQuery(WorldPacket& recvData);
|
||||
void HandleMailCreateTextItem(WorldPacket& recvData);
|
||||
void HandleQueryNextMailTime(WorldPacket& recvData);
|
||||
void HandleMailCreateTextItem(WorldPackets::Mail::MailCreateTextItem& packet);
|
||||
void HandleQueryNextMailTime(WorldPackets::Mail::MailQueryNextMailTime& packet);
|
||||
void HandleCancelChanneling(WorldPacket& recvData);
|
||||
|
||||
void SendItemPageInfo(ItemTemplate* itemProto);
|
||||
|
||||
@@ -131,7 +131,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_INSTANCELOCKTIMES, "SELECT instanceId, releaseTime FROM account_instance_times WHERE accountId = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC, "SELECT button, action, type FROM character_action WHERE guid = ? AND spec = ? ORDER BY button", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_MAILITEMS, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, transmogrification, upgradeId, enchantIllusion, item_guid, itemEntry, owner_guid FROM mail_items mi JOIN item_instance ii ON mi.item_guid = ii.guid WHERE mail_id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_MAILITEMS, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, transmogrification, upgradeId, enchantIllusion, bonusListIDs, item_guid, itemEntry, owner_guid FROM mail_items mi JOIN item_instance ii ON mi.item_guid = ii.guid WHERE mail_id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_AUCTION_ITEMS, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, transmogrification, upgradeId, enchantIllusion, itemguid, itemEntry FROM auctionhouse ah JOIN item_instance ii ON ah.itemguid = ii.guid", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_AUCTIONS, "SELECT id, auctioneerguid, itemguid, itemEntry, count, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_INS_AUCTION, "INSERT INTO auctionhouse (id, auctioneerguid, itemguid, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
Reference in New Issue
Block a user