void WorldSession::HandleSendMail(WorldPacket& recvData) { MailMessage msg; ObjectGuid mailbox; uint32_t unk1, unk2; uint64_t money, COD; std::vector< Item* > items; Item* pItem; recvData >> unk1; recvData >> unk2; recvData >> COD; recvData >> money; uint32_t bodyLength = recvData.readBits(12); uint32_t subjectLength = recvData.readBits(9); uint8_t items_count = static_cast<uint8_t>(recvData.readBits(5)); // attached items count if (items_count > MAIL_MAX_ITEM_SLOT) { SendMailError(MAIL_ERR_TOO_MANY_ATTACHMENTS); return; } mailbox[0] = recvData.readBit(); ObjectGuid itemGUIDs[MAIL_MAX_ITEM_SLOT]; for (uint8_t 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(); uint32_t 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_t 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_t>(); // 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]); std::string subject = recvData.ReadString(subjectLength); std::string receiver = recvData.ReadString(receiverLength); recvData.ReadByteSeq(mailbox[2]); recvData.ReadByteSeq(mailbox[0]); std::string body = recvData.ReadString(bodyLength); recvData.ReadByteSeq(mailbox[1]); // Search for the recipient PlayerInfo* player_info = ObjectMgr::getSingleton().GetPlayerInfoByName(receiver.c_str()); if (!player_info) { SendMailError(MAIL_ERR_RECIPIENT_NOT_FOUND); return; } for (uint8_t i = 0; i < items_count; ++i) { pItem = _player->GetItemInterface()->GetItemByGUID(itemGUIDs[i]); if (pItem == nullptr || pItem->isSoulbound() || pItem->hasFlags(ITEM_FLAG_CONJURED)) { SendMailError(MAIL_ERR_INTERNAL_ERROR); return; } if (pItem->isAccountbound() && GetAccountId() != player_info->acct) // don't mail account-bound items to another account { WorldPacket data(SMSG_SEND_MAIL_RESULT, 16); data << uint32_t(0); data << uint32_t(0); data << uint32_t(MAIL_ERR_BAG_FULL); data << uint32_t(INV_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS); SendPacket(&data); return; } items.push_back(pItem); } if (receiver.empty()) return; bool interfaction = false; if (sMailSystem.MailOption(MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION) || (HasGMPermissions() && sMailSystem.MailOption(MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION_GM))) { interfaction = true; } // Check we're sending to the same faction (disable this for testing) if (player_info->team != _player->GetTeam() && !interfaction) { SendMailError(MAIL_ERR_NOT_YOUR_ALLIANCE); return; } // Check if we're sending mail to ourselves if (strcmp(player_info->name, _player->GetName()) == 0 && !GetPermissionCount()) { SendMailError(MAIL_ERR_CANNOT_SEND_TO_SELF); return; } if (msg.stationery == MAIL_STATIONERY_GM && !HasGMPermissions()) { SendMailError(MAIL_ERR_INTERNAL_ERROR); return; } // Instant delivery time by default. msg.delivery_time = (uint32_t)UNIXTIME; // Set up the cost uint32_t cost = items_count ? 30 * items_count : 30; // price hardcoded in client if (!sMailSystem.MailOption(MAIL_FLAG_DISABLE_POSTAGE_COSTS) && !(GetPermissionCount() && sMailSystem.MailOption(MAIL_FLAG_NO_COST_FOR_GM))) { cost += 30; } // check that we have enough in our backpack if (!_player->HasGold(cost)) { SendMailError(MAIL_ERR_NOT_ENOUGH_MONEY); return; } // Check for the item, and required item. if (!items.empty()) { for (std::vector< Item* >::iterator itr = items.begin(); itr != items.end(); ++itr) { pItem = *itr; if (_player->GetItemInterface()->SafeRemoveAndRetreiveItemByGuid(pItem->getGuid(), false) != pItem) continue; // should never be hit. pItem->RemoveFromWorld(); pItem->setOwner(NULL); pItem->SaveToDB(INVENTORY_SLOT_NOT_SET, 0, true, NULL); msg.items.push_back(pItem->getGuidLow()); if (GetPermissionCount() > 0) { /* log the message */ sGMLog.writefromsession(this, "sent mail with item entry %u to %s, with gold %u.", pItem->getEntry(), player_info->name, money); } pItem->DeleteMe(); } } if (money != 0 || COD != 0 || (!items.size() && player_info->acct != _player->GetSession()->GetAccountId())) { if (!sMailSystem.MailOption(MAIL_FLAG_DISABLE_HOUR_DELAY_FOR_ITEMS)) msg.delivery_time += 3600; // 1hr } // take the money _player->ModGold(-static_cast<int32_t>(cost)); // Fill in the rest of the info msg.player_guid = player_info->guid; msg.sender_guid = _player->getGuid(); msg.money = static_cast<uint32_t>(money); msg.cod = static_cast<uint32_t>(COD); msg.subject = subject; msg.body = body; // 30 day expiry time for unread mail if (!sMailSystem.MailOption(MAIL_FLAG_NO_EXPIRY)) msg.expire_time = (uint32_t)UNIXTIME + (TIME_DAY * MAIL_DEFAULT_EXPIRATION_TIME); else msg.expire_time = 0; msg.deleted_flag = false; msg.message_type = 0; msg.checked_flag = msg.body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY; // Great, all our info is filled in. Now we can add it to the other players mailbox. sMailSystem.DeliverMessage(player_info->guid, &msg); // Save/Update character's gold if they've received gold that is. This prevents a rollback. CharacterDatabase.Execute("UPDATE characters SET gold = %u WHERE guid = %u", _player->GetGold(), _player->m_playerInfo->guid); // Success packet :) SendMailError(MAIL_OK); }
void WorldSession::HandleSendMail(WorldPacket & recv_data ) { MailMessage msg; uint64 gameobject; uint32 unk2; uint8 itemcount; uint8 itemslot; uint8 i; uint64 itemguid; vector< Item* > items; vector< Item* >::iterator itr; string recepient; Item * pItem; //uint32 err = MAIL_OK; recv_data >> gameobject >> recepient; recv_data >> msg.subject >> msg.body >> msg.stationary; recv_data >> unk2 >> itemcount; //he simply ads ' ' after each '%' to string so that vsnprintf function would not find tokens in string char *t=(char*)msg.subject.c_str(); if( t[0] != 0 ) //if not an empty string { int ind=1; //make sure we do not have any recognizable tokens here while(t[ind]!=0 && ind<5000) { if(t[ind-1]=='%') t[ind]=' ';//just remove chars that could be interpreted ind++; } } msg.subject = t; t=(char*)msg.body.c_str(); if( t[0] != 0 ) //if not an empty string { int ind=1; while(t[ind]!=0 && ind<5000) { if(t[ind-1]=='%') t[ind]=' ';//just remove chars that could be interpreted ind++; } } msg.body = t; if( itemcount > 12 ) { //SystemMessage("Sorry, Ascent does not support sending multiple items at this time. (don't want to lose your item do you) Remove some items, and try again."); SendMailError(MAIL_ERR_INTERNAL_ERROR); return; } for( i = 0; i < itemcount; ++i ) { recv_data >> itemslot; recv_data >> itemguid; pItem = _player->GetItemInterface()->GetItemByGUID( itemguid ); if( pItem == NULL || pItem->IsSoulbound() || pItem->HasFlag( ITEM_FIELD_FLAGS, ITEM_FLAG_CONJURED ) ) { SendMailError( MAIL_ERR_INTERNAL_ERROR ); return; } items.push_back( pItem ); } recv_data >> msg.money; recv_data >> msg.cod; // left over: (TODO- FIX ME BURLEX!) // uint32 // uint32 // uint8 // Search for the recipient PlayerInfo* player = ObjectMgr::getSingleton().GetPlayerInfoByName(recepient.c_str()); if( player == NULL ) { SendMailError( MAIL_ERR_RECIPIENT_NOT_FOUND ); return; } bool interfaction = false; if( sMailSystem.MailOption( MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION ) || (HasGMPermissions() && sMailSystem.MailOption( MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION_GM ) ) ) { interfaction = true; } // Check we're sending to the same faction (disable this for testing) if( player->team != _player->GetTeam() && !interfaction ) { SendMailError( MAIL_ERR_NOT_YOUR_ALLIANCE ); return; } // Check if we're sending mail to ourselves if( strcmp(player->name, _player->GetName()) == 0 && !GetPermissionCount()) { SendMailError(MAIL_ERR_CANNOT_SEND_TO_SELF); return; } if( msg.stationary == 0x3d || msg.stationary == 0x3d && !HasGMPermissions()) { SendMailError(MAIL_ERR_INTERNAL_ERROR); return; } // Instant delivery time by default. msg.delivery_time = (uint32)UNIXTIME; // Set up the cost int32 cost = 0; if( !sMailSystem.MailOption( MAIL_FLAG_DISABLE_POSTAGE_COSTS ) && !( GetPermissionCount() && sMailSystem.MailOption( MAIL_FLAG_NO_COST_FOR_GM ) ) ) { cost = 30; } // Check for attached money if( msg.money > 0 ) cost += msg.money; if( cost < 0 ) { SendMailError(MAIL_ERR_INTERNAL_ERROR); return; } // check that we have enough in our backpack if( (int32)_player->GetUInt32Value( PLAYER_FIELD_COINAGE ) < cost ) { SendMailError( MAIL_ERR_NOT_ENOUGH_MONEY ); return; } // Check for the item, and required item. if( !items.empty( ) ) { for( itr = items.begin(); itr != items.end(); ++itr ) { pItem = *itr; if( _player->GetItemInterface()->SafeRemoveAndRetreiveItemByGuid(pItem->GetGUID(), false) != pItem ) continue; // should never be hit. pItem->RemoveFromWorld(); pItem->SetOwner( NULL ); pItem->SaveToDB( INVENTORY_SLOT_NOT_SET, 0, true, NULL ); msg.items.push_back( pItem->GetUInt32Value(OBJECT_FIELD_GUID) ); if( GetPermissionCount() > 0 ) { /* log the message */ sGMLog.writefromsession(this, "sent mail with item entry %u to %s, with gold %u.", pItem->GetEntry(), player->name, msg.money); } pItem->DeleteMe(); } } if(msg.money != 0 || msg.cod != 0 || !msg.items.size() && player->acct != _player->GetSession()->GetAccountId()) { if(!sMailSystem.MailOption(MAIL_FLAG_DISABLE_HOUR_DELAY_FOR_ITEMS)) msg.delivery_time += 3600; // 1hr } // take the money _player->ModUnsigned32Value(PLAYER_FIELD_COINAGE, -cost); // Fill in the rest of the info msg.player_guid = player->guid; msg.sender_guid = _player->GetGUID(); // 30 day expiry time for unread mail mail if(!sMailSystem.MailOption(MAIL_FLAG_NO_EXPIRY)) msg.expire_time = (uint32)UNIXTIME + (TIME_DAY * MAIL_DEFAULT_EXPIRATION_TIME); else msg.expire_time = 0; msg.copy_made = false; msg.read_flag = false; msg.deleted_flag = false; msg.message_type = 0; // Great, all our info is filled in. Now we can add it to the other players mailbox. sMailSystem.DeliverMessage(player->guid, &msg); // Success packet :) SendMailError(MAIL_OK); }
void WorldSession::HandleSendMail(WorldPacket& recv_data) { CHECK_INWORLD_RETURN MailMessage msg; uint64 gameobject; uint32 unk2; uint8 itemcount; uint8 itemslot; uint8 i; uint64 itemguid; std::vector< Item* > items; std::vector< Item* >::iterator itr; std::string recepient; Item* pItem; //uint32 err = MAIL_OK; recv_data >> gameobject >> recepient; recv_data >> msg.subject >> msg.body >> msg.stationery; recv_data >> unk2 >> itemcount; if (itemcount > MAIL_MAX_ITEM_SLOT || msg.body.find("%") != std::string::npos || msg.subject.find("%") != std::string::npos) { SendMailError(MAIL_ERR_INTERNAL_ERROR); return; } // Search for the recipient PlayerInfo* player = ObjectMgr::getSingleton().GetPlayerInfoByName(recepient.c_str()); if (player == NULL) { SendMailError(MAIL_ERR_RECIPIENT_NOT_FOUND); return; } for (i = 0; i < itemcount; ++i) { recv_data >> itemslot; recv_data >> itemguid; pItem = _player->GetItemInterface()->GetItemByGUID(itemguid); if (pItem == NULL || pItem->IsSoulbound() || pItem->IsConjured()) { SendMailError(MAIL_ERR_INTERNAL_ERROR); return; } if (pItem->IsAccountbound() && GetAccountId() != player->acct) // don't mail account-bound items to another account { WorldPacket data(SMSG_SEND_MAIL_RESULT, 16); data << uint32(0); data << uint32(0); data << uint32(MAIL_ERR_BAG_FULL); data << uint32(INV_ERR_ARTEFACTS_ONLY_FOR_OWN_CHARACTERS); SendPacket(&data); return; } items.push_back(pItem); } recv_data >> msg.money; recv_data >> msg.cod; ///\todo left over: (TODO- FIX ME BURLEX!) // uint32 // uint32 // uint8 bool interfaction = false; if (sMailSystem.MailOption(MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION) || (HasGMPermissions() && sMailSystem.MailOption(MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION_GM))) { interfaction = true; } // Check we're sending to the same faction (disable this for testing) if (player->team != _player->GetTeam() && !interfaction) { SendMailError(MAIL_ERR_NOT_YOUR_ALLIANCE); return; } // Check if we're sending mail to ourselves if (strcmp(player->name, _player->GetName()) == 0 && !GetPermissionCount()) { SendMailError(MAIL_ERR_CANNOT_SEND_TO_SELF); return; } if (msg.stationery == MAIL_STATIONERY_GM && !HasGMPermissions()) { SendMailError(MAIL_ERR_INTERNAL_ERROR); return; } // Instant delivery time by default. msg.delivery_time = (uint32)UNIXTIME; // Set up the cost int32 cost = 0; // Check for attached money if (msg.money > 0) cost += msg.money; if (!sMailSystem.MailOption(MAIL_FLAG_DISABLE_POSTAGE_COSTS) && !(GetPermissionCount() && sMailSystem.MailOption(MAIL_FLAG_NO_COST_FOR_GM))) { cost += 30; } // check that we have enough in our backpack if (!_player->HasGold(cost)) { SendMailError(MAIL_ERR_NOT_ENOUGH_MONEY); return; } // Check for the item, and required item. if (!items.empty()) { for (itr = items.begin(); itr != items.end(); ++itr) { pItem = *itr; if (_player->GetItemInterface()->SafeRemoveAndRetreiveItemByGuid(pItem->GetGUID(), false) != pItem) continue; // should never be hit. pItem->RemoveFromWorld(); pItem->SetOwner(NULL); pItem->SaveToDB(INVENTORY_SLOT_NOT_SET, 0, true, NULL); msg.items.push_back(pItem->GetLowGUID()); if (GetPermissionCount() > 0) { /* log the message */ sGMLog.writefromsession(this, "sent mail with item entry %u to %s, with gold %u.", pItem->GetEntry(), player->name, msg.money); } pItem->DeleteMe(); } } if (msg.money != 0 || msg.cod != 0 || (!msg.items.size() && player->acct != _player->GetSession()->GetAccountId())) { if (!sMailSystem.MailOption(MAIL_FLAG_DISABLE_HOUR_DELAY_FOR_ITEMS)) msg.delivery_time += 3600; // 1hr } // take the money _player->ModGold(-cost); // Fill in the rest of the info msg.player_guid = player->guid; msg.sender_guid = _player->GetGUID(); // 30 day expiry time for unread mail if (!sMailSystem.MailOption(MAIL_FLAG_NO_EXPIRY)) msg.expire_time = (uint32)UNIXTIME + (TIME_DAY * MAIL_DEFAULT_EXPIRATION_TIME); else msg.expire_time = 0; msg.deleted_flag = false; msg.message_type = 0; msg.checked_flag = msg.body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY; // Great, all our info is filled in. Now we can add it to the other players mailbox. sMailSystem.DeliverMessage(player->guid, &msg); // Save/Update character's gold if they've received gold that is. This prevents a rollback. CharacterDatabase.Execute("UPDATE characters SET gold = %u WHERE guid = %u", _player->GetGold(), _player->m_playerInfo->guid); // Success packet :) SendMailError(MAIL_OK); }
void WorldSession::HandleSendMail(WorldPacket & recv_data ) { MailMessage msg; uint64 gameobject; uint32 unk2; uint8 itemcount; uint8 itemslot; uint8 i; uint64 itemguid; vector< ItemPointer > items; vector< ItemPointer >::iterator itr; string recepient; ItemPointer pItem; int8 real_item_slot; recv_data >> gameobject >> recepient; // Search for the recipient PlayerInfo* player = ObjectMgr::getSingleton().GetPlayerInfoByName(recepient.c_str()); if( player == NULL ) { SendMailError(MAIL_ERR_RECIPIENT_NOT_FOUND); return; } msg.player_guid = player->guid; msg.sender_guid = _player->GetGUID(); recv_data >> msg.subject >> msg.body >> msg.stationary; // Check attached items recv_data >> unk2 >> itemcount; for( i = 0; i < itemcount; ++i ) { recv_data >> itemslot; recv_data >> itemguid; pItem = _player->GetItemInterface()->GetItemByGUID( itemguid ); real_item_slot = _player->GetItemInterface()->GetInventorySlotByGuid( itemguid ); if( pItem == NULL || pItem->IsSoulbound() || pItem->HasFlag( ITEM_FIELD_FLAGS, ITEM_FLAG_CONJURED ) || ( pItem->IsContainer() && (TO_CONTAINER( pItem ))->HasItems() ) || real_item_slot >= 0 && real_item_slot < INVENTORY_SLOT_ITEM_START ) { SendMailError(MAIL_ERR_INTERNAL_ERROR); return; } items.push_back( pItem ); } if( items.size() > 12 || msg.body.find("%") != string::npos || msg.subject.find("%") != string::npos) { SendMailError(MAIL_ERR_INTERNAL_ERROR); return; } recv_data >> msg.money; recv_data >> msg.cod; // left over: (TODO- FIX ME BURLEX!) // uint32 // uint32 // uint8 // Check if we're sending mail to ourselves if(msg.player_guid == msg.sender_guid && !GetPermissionCount()) { SendMailError(MAIL_ERR_CANNOT_SEND_TO_SELF); return; } // Check stationary if( msg.stationary == 0x3d && !HasGMPermissions()) { SendMailError(MAIL_ERR_INTERNAL_ERROR); return; } // Set up the cost int32 cost = 0; if( !sMailSystem.MailOption( MAIL_FLAG_DISABLE_POSTAGE_COSTS ) && !( GetPermissionCount() && sMailSystem.MailOption( MAIL_FLAG_NO_COST_FOR_GM ) ) ) { cost = 30; } // Check for attached money if( msg.money > 0 ) cost += msg.money; if( cost < 0 ) { SendMailError(MAIL_ERR_INTERNAL_ERROR); return; } // check that we have enough in our backpack if( (int32)_player->GetUInt32Value( PLAYER_FIELD_COINAGE ) < cost ) { SendMailError( MAIL_ERR_NOT_ENOUGH_MONEY ); return; } // Check we're sending to the same faction (disable this for testing) bool interfaction = (sMailSystem.MailOption( MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION ) || (HasGMPermissions() && sMailSystem.MailOption( MAIL_FLAG_CAN_SEND_TO_OPPOSITE_FACTION_GM ) )); if(!interfaction) { if(player->team != _player->GetTeam()) { SendMailError( MAIL_ERR_NOT_YOUR_ALLIANCE ); return; } } msg.message_id = 0; msg.message_type = 0; msg.copy_made = false; msg.read_flag = false; msg.deleted_flag = false; msg.returned_flag = false; msg.delivery_time = (uint32)UNIXTIME; if(msg.money != 0 || msg.cod != 0 || !items.size() && player->acct != _player->GetSession()->GetAccountId()) { if(!sMailSystem.MailOption(MAIL_FLAG_DISABLE_HOUR_DELAY_FOR_ITEMS)) msg.delivery_time += 3600; // +1hr } msg.expire_time = 0; if(!sMailSystem.MailOption(MAIL_FLAG_NO_EXPIRY)) { msg.expire_time = (uint32)UNIXTIME + (TIME_DAY * 30); if (msg.cod != 0) { msg.expire_time = (uint32)UNIXTIME + (TIME_DAY * 3); } } // Sending Message // take the money _player->ModUnsigned32Value(PLAYER_FIELD_COINAGE, -cost); // Check for the item, and required item. if( !items.empty( ) ) { for( itr = items.begin(); itr != items.end(); ++itr ) { pItem = *itr; if( _player->GetItemInterface()->SafeRemoveAndRetreiveItemByGuid(pItem->GetGUID(), false) != pItem ) continue; // should never be hit. pItem->RemoveFromWorld(); pItem->SetOwner( NULLPLR ); pItem->SaveToDB( INVENTORY_SLOT_NOT_SET, 0, true, NULL ); msg.items.push_back( pItem->GetUInt32Value(OBJECT_FIELD_GUID) ); if( GetPermissionCount() > 0 ) { /* log the message */ sGMLog.writefromsession(this, "sent mail with item entry %u to %s, with gold %u.", pItem->GetEntry(), player->name, msg.money); } pItem->Destructor(); } } // Great, all our info is filled in. Now we can add it to the other players mailbox. sMailSystem.DeliverMessage(&msg); // Success packet :) SendMailError(MAIL_OK); }