//called when player takes item attached in mail void WorldSession::HandleMailTakeItem(WorldPacket & recv_data ) { uint64 mailbox; uint32 mailId; uint32 itemId; recv_data >> mailbox; if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; recv_data >> mailId; recv_data >> itemId; // item guid low? Player* pl = _player; Mail* m = pl->GetMail(mailId); if(!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) { pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_INTERNAL_ERROR); return; } // prevent cheating with skip client money check if(pl->GetMoney() < m->COD) { pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_NOT_ENOUGH_MONEY); return; } Item *it = pl->GetMItem(itemId); ItemPosCountVec dest; uint8 msg = _player->CanStoreItem( NULL_BAG, NULL_SLOT, dest, it, false ); if( msg == EQUIP_ERR_OK ) { m->RemoveItem(itemId); m->removedItems.push_back(itemId); if (m->COD > 0) //if there is COD, take COD money from player and send them to sender by mail { uint64 sender_guid = MAKE_NEW_GUID(m->sender, 0, HIGHGUID_PLAYER); Player *receive = objmgr.GetPlayer(sender_guid); uint32 sender_accId = 0; if( GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) { std::string sender_name; if(receive) { sender_accId = receive->GetSession()->GetAccountId(); sender_name = receive->GetName(); } else { // can be calculated early sender_accId = objmgr.GetPlayerAccountIdByGUID(sender_guid); if(!objmgr.GetPlayerNameByGUID(sender_guid,sender_name)) sender_name = objmgr.GetMangosStringForDBCLocale(LANG_UNKNOWN); } sLog.outCommand(GetAccountId(),"GM %s (Account: %u) receive mail item: %s (Entry: %u Count: %u) and send COD money: %u to player: %s (Account: %u)", GetPlayerName(),GetAccountId(),it->GetProto()->Name1,it->GetEntry(),it->GetCount(),m->COD,sender_name.c_str(),sender_accId); } else if(!receive) sender_accId = objmgr.GetPlayerAccountIdByGUID(sender_guid); // check player existence if(receive || sender_accId) { WorldSession::SendMailTo(receive, MAIL_NORMAL, MAIL_STATIONERY_NORMAL, m->receiver, m->sender, m->subject, 0, NULL, m->COD, 0, MAIL_CHECK_MASK_COD_PAYMENT); } pl->ModifyMoney( -int32(m->COD) ); } m->COD = 0; m->state = MAIL_STATE_CHANGED; pl->m_mailsUpdated = true; pl->RemoveMItem(it->GetGUIDLow()); uint32 count = it->GetCount(); // save counts before store and possible merge with deleting pl->MoveItemToInventory(dest,it,true); CharacterDatabase.BeginTransaction(); pl->SaveInventoryAndGoldToDB(); pl->_SaveMail(); CharacterDatabase.CommitTransaction(); pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_OK, 0, itemId, count); } else pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_EQUIP_ERROR, msg); }
//called when player takes item attached in mail void WorldSession::HandleMailTakeItem(WorldPacket& recvData) { ObjectGuid mailbox; uint32 mailId; uint32 itemId; recvData >> mailId; recvData >> itemId; recvData.ReadGuidMask(mailbox, 6, 5, 2, 3, 0, 1, 4, 7); recvData.ReadGuidBytes(mailbox, 0, 1, 4, 2, 5, 6, 3, 7); if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; Player* player = _player; Mail* m = player->GetMail(mailId); if (!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) { player->SendMailResult(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); return; } Item* it = player->GetMItem(itemId); 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); if (m->COD > 0) //if there is COD, take COD money from player and send them to sender by mail { uint64 sender_guid = MAKE_NEW_GUID(m->sender, 0, HIGHGUID_PLAYER); Player* receiver = ObjectAccessor::FindPlayer(sender_guid); uint32 sender_accId = 0; if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) { std::string sender_name; if (receiver) { sender_accId = receiver->GetSession()->GetAccountId(); sender_name = receiver->GetName(); } else { // can be calculated early sender_accId = sObjectMgr->GetPlayerAccountIdByGUID(sender_guid); if (!sObjectMgr->GetPlayerNameByGUID(sender_guid, sender_name)) sender_name = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN); } 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)", GetPlayerName().c_str(), GetAccountId(), it->GetTemplate()->Name1.c_str(), it->GetEntry(), it->GetCount(), m->COD, sender_name.c_str(), sender_accId); } else if (!receiver) sender_accId = sObjectMgr->GetPlayerAccountIdByGUID(sender_guid); // check player existence if (receiver || sender_accId) { MailDraft(m->subject, "") .AddMoney(m->COD) .SendMailTo(trans, MailReceiver(receiver, m->sender), MailSender(MAIL_NORMAL, m->receiver), MAIL_CHECK_MASK_COD_PAYMENT); } player->ModifyMoney(-int32(m->COD)); } m->COD = 0; m->state = MAIL_STATE_CHANGED; player->m_mailsUpdated = true; player->RemoveMItem(it->GetGUIDLow()); uint32 count = it->GetCount(); // save counts before store and possible merge with deleting it->SetState(ITEM_UNCHANGED); // need to set this state, otherwise item cannot be removed later, if neccessary player->MoveItemToInventory(dest, it, true); player->SaveInventoryAndGoldToDB(trans); player->_SaveMail(trans); CharacterDatabase.CommitTransaction(trans); player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_OK, 0, itemId, count); } else player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_EQUIP_ERROR, msg); }
//called when player takes item attached in mail void WorldSession::HandleMailTakeItem(WorldPackets::Mail::MailTakeItem& packet) { uint32 AttachID = packet.AttachID; if (!CanOpenMailBox(packet.Mailbox)) return; Player* player = _player; Mail* m = player->GetMail(packet.MailID); if (!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(nullptr)) { 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(), [AttachID](MailItemInfo info){ return info.item_guid == AttachID; }) == m->items.end()) { 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(packet.MailID, MAIL_ITEM_TAKEN, MAIL_ERR_NOT_ENOUGH_MONEY); return; } 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(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 { ObjectGuid sender_guid = ObjectGuid::Create<HighGuid::Player>(m->sender); Player* receiver = ObjectAccessor::FindConnectedPlayer(sender_guid); uint32 sender_accId = 0; if (HasPermission(rbac::RBAC_PERM_LOG_GM_TRADE)) { std::string sender_name; if (receiver) { sender_accId = receiver->GetSession()->GetAccountId(); sender_name = receiver->GetName(); } else { // can be calculated early sender_accId = ObjectMgr::GetPlayerAccountIdByGUID(sender_guid); if (!ObjectMgr::GetPlayerNameByGUID(sender_guid, sender_name)) sender_name = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN); } 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)", GetPlayerName().c_str(), GetAccountId(), it->GetTemplate()->GetDefaultLocaleName(), it->GetEntry(), it->GetCount(), m->COD, sender_name.c_str(), sender_accId); } else if (!receiver) sender_accId = ObjectMgr::GetPlayerAccountIdByGUID(sender_guid); // check player existence if (receiver || sender_accId) { MailDraft(m->subject, "") .AddMoney(m->COD) .SendMailTo(trans, MailReceiver(receiver, m->sender), MailSender(MAIL_NORMAL, m->receiver), MAIL_CHECK_MASK_COD_PAYMENT); } player->ModifyMoney(-int32(m->COD)); } m->COD = 0; m->state = MAIL_STATE_CHANGED; player->m_mailsUpdated = true; player->RemoveMItem(it->GetGUID().GetCounter()); uint32 count = it->GetCount(); // save counts before store and possible merge with deleting it->SetState(ITEM_UNCHANGED); // need to set this state, otherwise item cannot be removed later, if neccessary player->MoveItemToInventory(dest, it, true); player->SaveInventoryAndGoldToDB(trans); player->_SaveMail(trans); CharacterDatabase.CommitTransaction(trans); player->SendMailResult(packet.MailID, MAIL_ITEM_TAKEN, MAIL_OK, 0, packet.AttachID, count); } else player->SendMailResult(packet.MailID, MAIL_ITEM_TAKEN, MAIL_ERR_EQUIP_ERROR, msg); }
/** * Handles the packet sent by the client when taking an item from the mail. */ void WorldSession::HandleMailTakeItem(WorldPacket& recv_data) { ObjectGuid mailboxGuid; uint32 mailId; recv_data >> mailboxGuid; recv_data >> mailId; if (!CheckMailBox(mailboxGuid)) return; Player* pl = _player; Mail* m = pl->GetMail(mailId); if (!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) { pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_INTERNAL_ERROR); return; } // prevent cheating with skip client money check if (pl->GetMoney() < m->COD) { pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_NOT_ENOUGH_MONEY); return; } uint32 itemId = m->items[0].item_template; uint32 itemGuid = m->items[0].item_guid; Item* it = pl->GetMItem(itemGuid); ItemPosCountVec dest; InventoryResult msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, it, false); if (msg == EQUIP_ERR_OK) { m->RemoveItem(itemGuid); m->removedItems.push_back(itemGuid); if (m->COD > 0) // if there is COD, take COD money from player and send them to sender by mail { ObjectGuid sender_guid = ObjectGuid(HIGHGUID_PLAYER, m->sender); Player* sender = sObjectMgr.GetPlayer(sender_guid); uint32 sender_accId = 0; if (GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_GM_LOG_TRADE)) { std::string sender_name; if (sender) { sender_accId = sender->GetSession()->GetAccountId(); sender_name = sender->GetName(); } else if (sender_guid) { // can be calculated early sender_accId = sObjectMgr.GetPlayerAccountIdByGUID(sender_guid); if (!sObjectMgr.GetPlayerNameByGUID(sender_guid, sender_name)) sender_name = sObjectMgr.GetMangosStringForDBCLocale(LANG_UNKNOWN); } sLog.outCommand(GetAccountId(), "GM %s (Account: %u) receive mail item: %s (Entry: %u Count: %u) and send COD money: %u to player: %s (Account: %u)", GetPlayerName(), GetAccountId(), it->GetProto()->Name1, it->GetEntry(), it->GetCount(), m->COD, sender_name.c_str(), sender_accId); } else if (!sender) sender_accId = sObjectMgr.GetPlayerAccountIdByGUID(sender_guid); // check player existence if (sender || sender_accId) { MailDraft(m->subject) .SetMoney(m->COD) .SendMailTo(MailReceiver(sender, sender_guid), _player, MAIL_CHECK_MASK_COD_PAYMENT); } pl->ModifyMoney(-int32(m->COD)); } m->COD = 0; m->state = MAIL_STATE_CHANGED; pl->m_mailsUpdated = true; pl->RemoveMItem(it->GetGUIDLow()); uint32 count = it->GetCount(); // save counts before store and possible merge with deleting pl->MoveItemToInventory(dest, it, true); CharacterDatabase.BeginTransaction(); pl->SaveInventoryAndGoldToDB(); pl->_SaveMail(); CharacterDatabase.CommitTransaction(); pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_OK, 0, itemId, count); } else pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_EQUIP_ERROR, msg); }
//called when player takes item attached in mail void WorldSession::HandleMailTakeItem(WorldPacket & recvData) { uint64 mailbox; uint32 mailId; uint32 itemId; recvData >> mailbox; recvData >> mailId; recvData >> itemId; // item guid low if (!CanOpenMailBox(mailbox)) return; Player* player = _player; Mail* m = player->GetMail(mailId); if (!m || m->state == MAIL_STATE_DELETED || m->deliver_time > time(NULL)) { player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_INTERNAL_ERROR); return; } // verify that the mail has the item to avoid cheaters taking COD items without paying bool foundItem = false; for (std::vector<MailItemInfo>::const_iterator itr = m->items.begin(); itr != m->items.end(); ++itr) if (itr->item_guid == itemId) { foundItem = true; break; } if (!foundItem) { player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_INTERNAL_ERROR); return; } // prevent cheating with skip client money check if (!player->HasEnoughMoney(m->COD)) { player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_NOT_ENOUGH_MONEY); return; } Item* it = player->GetMItem(itemId); 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); if (m->COD > 0) // if there is COD, take COD money from player and send them to sender by mail { uint64 sender_guid = MAKE_NEW_GUID(m->sender, 0, HIGHGUID_PLAYER); uint32 sender_accId = 0; Player* sender = ObjectAccessor::FindPlayerInOrOutOfWorld(sender_guid); if (sender) sender_accId = sender->GetSession()->GetAccountId(); else sender_accId = sObjectMgr->GetPlayerAccountIdByGUID(sender_guid); // check player existence if (sender || sender_accId) { MailDraft(m->subject, "") .AddMoney(m->COD) .SendMailTo(trans, MailReceiver(sender, m->sender), MailSender(MAIL_NORMAL, m->receiver), MAIL_CHECK_MASK_COD_PAYMENT); if( m->COD >= 10*GOLD ) { std::string senderName; if (!sObjectMgr->GetPlayerNameByGUID(sender_guid, senderName)) senderName = sObjectMgr->GetTrinityStringForDBCLocale(LANG_UNKNOWN); std::string subj = m->subject; CleanStringForMysqlQuery(subj); CharacterDatabase.PExecute("INSERT INTO log_money VALUES(%u, %u, \"%s\", \"%s\", %u, \"%s\", %u, \"<COD> %s\", NOW())", GetAccountId(), player->GetGUIDLow(), player->GetName().c_str(), player->GetSession()->GetRemoteAddress().c_str(), sender_accId, senderName.c_str(), m->COD, subj.c_str()); } } player->ModifyMoney(-int32(m->COD)); } m->COD = 0; m->state = MAIL_STATE_CHANGED; player->m_mailsUpdated = true; player->RemoveMItem(it->GetGUIDLow()); uint32 count = it->GetCount(); // save counts before store and possible merge with deleting it->SetState(ITEM_UNCHANGED); // need to set this state, otherwise item cannot be removed later, if neccessary player->MoveItemToInventory(dest, it, true); player->SaveInventoryAndGoldToDB(trans); player->_SaveMail(trans); CharacterDatabase.CommitTransaction(trans); player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_OK, 0, itemId, count); } else player->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_ERR_EQUIP_ERROR, msg); }