void LootRoll::Finalize() { sEventMgr.RemoveEvents(this); // this we will have to finalize with groups types.. for now // we'll just assume need before greed. person with highest roll // in need gets the item. uint32 highest = 0; int8 hightype = -1; uint64 player = 0; WorldPacket data(34); /* Player * gplr = NULL; for(std::map<uint64, uint32>::iterator itr = NeedRolls.begin(); itr != NeedRolls.end(); ++itr) { gplr = _mgr->GetPlayer((uint32)itr->first); if(gplr) break; } if(!gplr) { for(std::map<uint64, uint32>::iterator itr = GreedRolls.begin(); itr != GreedRolls.end(); ++itr) { gplr = _mgr->GetPlayer((uint32)itr->first); if(gplr) break; } } */ for(std::map<uint32, uint32>::iterator itr = m_NeedRolls.begin(); itr != m_NeedRolls.end(); ++itr) { if(itr->second > highest) { highest = itr->second; player = itr->first; hightype = NEED; } /* data.Initialize(SMSG_LOOT_ROLL); data << _guid << _slotid << itr->first; data << _itemid << _randomsuffixid << _randompropertyid; data << uint8(itr->second) << uint8(NEED); if(gplr && gplr->GetGroup()) gplr->GetGroup()->SendPacketToAll(&data); */ } if(!highest) { for(std::map<uint32, uint32>::iterator itr = m_GreedRolls.begin(); itr != m_GreedRolls.end(); ++itr) { if(itr->second > highest) { highest = itr->second; player = itr->first; hightype = GREED; } /* data.Initialize(SMSG_LOOT_ROLL); data << _guid << _slotid << itr->first; data << _itemid << _randomsuffixid << _randompropertyid; data << uint8(itr->second) << uint8(GREED); if(gplr && gplr->GetGroup()) gplr->GetGroup()->SendPacketToAll(&data); */ } } Loot* pLoot = 0; uint32 guidtype = GET_TYPE_FROM_GUID(_guid); if(guidtype == HIGHGUID_TYPE_UNIT) { Creature* pc = _mgr->GetCreature(GET_LOWGUID_PART(_guid)); if(pc) pLoot = &pc->loot; } else if(guidtype == HIGHGUID_TYPE_GAMEOBJECT) { GameObject* go = _mgr->GetGameObject(GET_LOWGUID_PART(_guid)); if(go) pLoot = &go->loot; } if(!pLoot) { delete this; return; } if(_slotid >= pLoot->items.size()) { delete this; return; } pLoot->items.at(_slotid).roll = NULL; uint32 itemid = pLoot->items.at(_slotid).item.itemproto->ItemId; uint32 amt = pLoot->items.at(_slotid).iItemsCount; if(!amt) { delete this; return; } Player* _player = (player) ? _mgr->GetPlayer((uint32)player) : 0; if(!player || !_player) { /* all passed */ data.Initialize(SMSG_LOOT_ALL_PASSED); data << _guid << _groupcount << _itemid << _randomsuffixid << _randompropertyid; set<uint32>::iterator pitr = m_passRolls.begin(); while(_player == NULL && pitr != m_passRolls.end()) _player = _mgr->GetPlayer((*(pitr++))); if(_player != NULL) { if(_player->InGroup()) _player->GetGroup()->SendPacketToAll(&data); else _player->GetSession()->SendPacket(&data); } /* item can now be looted by anyone :) */ pLoot->items.at(_slotid).passed = true; delete this; return; } pLoot->items.at(_slotid).roll = 0; data.Initialize(SMSG_LOOT_ROLL_WON); data << _guid << _slotid << _itemid << _randomsuffixid << _randompropertyid; data << _player->GetGUID() << uint8(highest) << uint8(hightype); if(_player->InGroup()) _player->GetGroup()->SendPacketToAll(&data); else _player->GetSession()->SendPacket(&data); ItemPrototype* it = ItemPrototypeStorage.LookupEntry(itemid); int8 error; if((error = _player->GetItemInterface()->CanReceiveItem(it, 1)) != 0) { _player->GetItemInterface()->BuildInventoryChangeError(NULL, NULL, error); return; } Item* add = _player->GetItemInterface()->FindItemLessMax(itemid, amt, false); if(!add) { SlotResult slotresult = _player->GetItemInterface()->FindFreeInventorySlot(it); if(!slotresult.Result) { _player->GetItemInterface()->BuildInventoryChangeError(NULL, NULL, INV_ERR_INVENTORY_FULL); return; } LOG_DEBUG("AutoLootItem MISC"); Item* item = objmgr.CreateItem(itemid, _player); if(item == NULL) return; item->SetStackCount(amt); if(pLoot->items.at(_slotid).iRandomProperty != NULL) { item->SetItemRandomPropertyId(pLoot->items.at(_slotid).iRandomProperty->ID); item->ApplyRandomProperties(false); } else if(pLoot->items.at(_slotid).iRandomSuffix != NULL) { item->SetRandomSuffix(pLoot->items.at(_slotid).iRandomSuffix->id); item->ApplyRandomProperties(false); } if(_player->GetItemInterface()->SafeAddItem(item, slotresult.ContainerSlot, slotresult.Slot)) { _player->SendItemPushResult(false, true, true, true, slotresult.ContainerSlot, slotresult.Slot, 1, item->GetEntry(), item->GetItemRandomSuffixFactor(), item->GetItemRandomPropertyId(), item->GetStackCount()); sQuestMgr.OnPlayerItemPickup(_player, item); #ifdef ENABLE_ACHIEVEMENTS _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item->GetEntry(), 1, 0); #endif } else item->DeleteMe(); } else { add->SetStackCount(add->GetStackCount() + amt); add->m_isDirty = true; sQuestMgr.OnPlayerItemPickup(_player, add); _player->SendItemPushResult(false, true, true, false, (uint8)_player->GetItemInterface()->GetBagSlotByGuid(add->GetGUID()), 0xFFFFFFFF, 1, add->GetEntry(), add->GetItemRandomSuffixFactor(), add->GetItemRandomPropertyId(), add->GetStackCount()); #ifdef ENABLE_ACHIEVEMENTS _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, add->GetEntry(), 1, 0); #endif } pLoot->items.at(_slotid).iItemsCount = 0; // this gets sent to all looters data.Initialize(SMSG_LOOT_REMOVED); data << uint8(_slotid); Player* plr; for(LooterSet::iterator itr = pLoot->looters.begin(); itr != pLoot->looters.end(); ++itr) { if((plr = _player->GetMapMgr()->GetPlayer(*itr)) != 0) plr->GetSession()->SendPacket(&data); } delete this; }
void WorldSession::HandleVoidStorageTransfer(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_VOID_STORAGE_TRANSFER"); Player* player = GetPlayer(); ObjectGuid npcGuid; npcGuid[7] = recvData.ReadBit(); npcGuid[4] = recvData.ReadBit(); uint32 countWithdraw = recvData.ReadBits(26); if (countWithdraw > 9) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to withdraw more than 9 items (%u).", player->GetGUIDLow(), player->GetName().c_str(), countWithdraw); return; } std::vector<ObjectGuid> itemIds(countWithdraw); for (uint32 i = 0; i < countWithdraw; ++i) { itemIds[i][4] = recvData.ReadBit(); itemIds[i][0] = recvData.ReadBit(); itemIds[i][5] = recvData.ReadBit(); itemIds[i][7] = recvData.ReadBit(); itemIds[i][6] = recvData.ReadBit(); itemIds[i][1] = recvData.ReadBit(); itemIds[i][2] = recvData.ReadBit(); itemIds[i][3] = recvData.ReadBit(); } uint32 countDeposit = recvData.ReadBits(26); //40 if (countDeposit > 9) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to deposit more than 9 items (%u).", player->GetGUIDLow(), player->GetName().c_str(), countDeposit); return; } std::vector<ObjectGuid> itemGuids(countDeposit); for (uint32 i = 0; i < countDeposit; ++i) { itemGuids[i][0] = recvData.ReadBit(); itemGuids[i][3] = recvData.ReadBit(); itemGuids[i][6] = recvData.ReadBit(); itemGuids[i][5] = recvData.ReadBit(); itemGuids[i][4] = recvData.ReadBit(); itemGuids[i][2] = recvData.ReadBit(); itemGuids[i][1] = recvData.ReadBit(); itemGuids[i][7] = recvData.ReadBit(); } npcGuid[6] = recvData.ReadBit(); npcGuid[0] = recvData.ReadBit(); npcGuid[3] = recvData.ReadBit(); npcGuid[1] = recvData.ReadBit(); npcGuid[2] = recvData.ReadBit(); npcGuid[5] = recvData.ReadBit(); for (uint32 i = 0; i < countWithdraw; ++i) { recvData.ReadByteSeq(itemIds[i][0]); recvData.ReadByteSeq(itemIds[i][4]); recvData.ReadByteSeq(itemIds[i][1]); recvData.ReadByteSeq(itemIds[i][2]); recvData.ReadByteSeq(itemIds[i][6]); recvData.ReadByteSeq(itemIds[i][3]); recvData.ReadByteSeq(itemIds[i][7]); recvData.ReadByteSeq(itemIds[i][5]); } recvData.ReadByteSeq(npcGuid[5]); for (uint32 i = 0; i < countDeposit; ++i) { recvData.ReadByteSeq(itemGuids[i][5]); recvData.ReadByteSeq(itemGuids[i][6]); recvData.ReadByteSeq(itemGuids[i][3]); recvData.ReadByteSeq(itemGuids[i][4]); recvData.ReadByteSeq(itemGuids[i][1]); recvData.ReadByteSeq(itemGuids[i][7]); recvData.ReadByteSeq(itemGuids[i][2]); recvData.ReadByteSeq(itemGuids[i][0]); } recvData.ReadByteSeq(npcGuid[1]); recvData.ReadByteSeq(npcGuid[7]); recvData.ReadByteSeq(npcGuid[4]); recvData.ReadByteSeq(npcGuid[3]); recvData.ReadByteSeq(npcGuid[2]); recvData.ReadByteSeq(npcGuid[0]); recvData.ReadByteSeq(npcGuid[6]); Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER); if (!unit) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid)); return; } if (!player->IsVoidStorageUnlocked()) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName().c_str()); return; } if (itemGuids.size() > player->GetNumOfVoidStorageFreeSlots()) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL); return; } uint32 freeBagSlots = 0; if (itemIds.size() != 0) { // make this a Player function for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) if (Bag* bag = player->GetBagByPos(i)) freeBagSlots += bag->GetFreeSlots(); for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) if (!player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) ++freeBagSlots; } if (itemIds.size() > freeBagSlots) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL); return; } if (!player->HasEnoughMoney(uint64(itemGuids.size() * VOID_STORAGE_STORE_ITEM))) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NOT_ENOUGH_MONEY); return; } std::pair<VoidStorageItem, uint8> depositItems[VOID_STORAGE_MAX_DEPOSIT]; uint8 depositCount = 0; for (std::vector<ObjectGuid>::iterator itr = itemGuids.begin(); itr != itemGuids.end(); ++itr) { Item* item = player->GetItemByGuid(*itr); if (!item) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to deposit an invalid item (item guid: " UI64FMTD ").", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr)); continue; } VoidStorageItem itemVS(sObjectMgr->GenerateVoidStorageItemId(), item->GetEntry(), item->GetUInt64Value(ITEM_FIELD_CREATOR), item->GetItemRandomPropertyId(), item->GetItemSuffixFactor()); uint8 slot = player->AddVoidStorageItem(itemVS); depositItems[depositCount++] = std::make_pair(itemVS, slot); player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); } int64 cost = depositCount * VOID_STORAGE_STORE_ITEM; player->ModifyMoney(-cost); VoidStorageItem withdrawItems[VOID_STORAGE_MAX_WITHDRAW]; uint8 withdrawCount = 0; for (std::vector<ObjectGuid>::iterator itr = itemIds.begin(); itr != itemIds.end(); ++itr) { uint8 slot; VoidStorageItem* itemVS = player->GetVoidStorageItem(*itr, slot); if (!itemVS) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) tried to withdraw an invalid item (id: " UI64FMTD ")", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr)); continue; } ItemPosCountVec dest; InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemVS->ItemEntry, 1); if (msg != EQUIP_ERR_OK) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL); TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) couldn't withdraw item id " UI64FMTD " because inventory was full.", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr)); return; } Item* item = player->StoreNewItem(dest, itemVS->ItemEntry, true, itemVS->ItemRandomPropertyId); item->SetUInt64Value(ITEM_FIELD_CREATOR, uint64(itemVS->CreatorGuid)); item->SetBinding(true); player->SendNewItem(item, 1, false, false, false); withdrawItems[withdrawCount++] = *itemVS; player->DeleteVoidStorageItem(slot); } WorldPacket data(SMSG_VOID_STORAGE_TRANSFER_CHANGES, ((5 + 5 + (7 + 7) * depositCount + 7 * withdrawCount) / 8) + 7 * withdrawCount + (7 + 7 + 4 * 4) * depositCount); data.WriteBits(depositCount, 5); data.WriteBits(withdrawCount, 5); for (uint8 i = 0; i < depositCount; ++i) { ObjectGuid itemId = depositItems[i].first.ItemId; ObjectGuid creatorGuid = depositItems[i].first.CreatorGuid; data.WriteBit(creatorGuid[7]); data.WriteBit(itemId[7]); data.WriteBit(itemId[4]); data.WriteBit(creatorGuid[6]); data.WriteBit(creatorGuid[5]); data.WriteBit(itemId[3]); data.WriteBit(itemId[5]); data.WriteBit(creatorGuid[4]); data.WriteBit(creatorGuid[2]); data.WriteBit(creatorGuid[0]); data.WriteBit(creatorGuid[3]); data.WriteBit(creatorGuid[1]); data.WriteBit(itemId[2]); data.WriteBit(itemId[0]); data.WriteBit(itemId[1]); data.WriteBit(itemId[6]); } for (uint8 i = 0; i < withdrawCount; ++i) { ObjectGuid itemId = withdrawItems[i].ItemId; data.WriteBit(itemId[1]); data.WriteBit(itemId[7]); data.WriteBit(itemId[3]); data.WriteBit(itemId[5]); data.WriteBit(itemId[6]); data.WriteBit(itemId[2]); data.WriteBit(itemId[4]); data.WriteBit(itemId[0]); } data.FlushBits(); for (uint8 i = 0; i < withdrawCount; ++i) { ObjectGuid itemId = withdrawItems[i].ItemId; data.WriteByteSeq(itemId[3]); data.WriteByteSeq(itemId[1]); data.WriteByteSeq(itemId[0]); data.WriteByteSeq(itemId[2]); data.WriteByteSeq(itemId[7]); data.WriteByteSeq(itemId[5]); data.WriteByteSeq(itemId[6]); data.WriteByteSeq(itemId[4]); } for (uint8 i = 0; i < depositCount; ++i) { ObjectGuid itemId = depositItems[i].first.ItemId; ObjectGuid creatorGuid = depositItems[i].first.CreatorGuid; data << uint32(depositItems[i].first.ItemSuffixFactor); data.WriteByteSeq(itemId[6]); data.WriteByteSeq(itemId[4]); data.WriteByteSeq(creatorGuid[4]); data.WriteByteSeq(itemId[2]); data.WriteByteSeq(creatorGuid[1]); data.WriteByteSeq(creatorGuid[3]); data.WriteByteSeq(itemId[3]); data.WriteByteSeq(creatorGuid[0]); data.WriteByteSeq(itemId[0]); data.WriteByteSeq(creatorGuid[6]); data.WriteByteSeq(itemId[5]); data.WriteByteSeq(creatorGuid[5]); data.WriteByteSeq(creatorGuid[7]); data << uint32(depositItems[i].first.ItemEntry); data.WriteByteSeq(itemId[1]); data << uint32(depositItems[i].second); // slot data.WriteByteSeq(creatorGuid[2]); data.WriteByteSeq(itemId[7]); data << uint32(depositItems[i].first.ItemRandomPropertyId); } SendPacket(&data); SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NO_ERROR); }
/** * Handles the packet sent by the client when requesting the current mail list. * It will send a list of all available mails in the players mailbox to the client. */ void WorldSession::HandleGetMailList(WorldPacket & recv_data ) { ObjectGuid mailboxGuid; recv_data >> mailboxGuid; if (!CheckMailBox(mailboxGuid)) return; // client can't work with packets > max int16 value const uint32 maxPacketSize = 32767; uint32 mailsCount = 0; // real send to client mails amount WorldPacket data(SMSG_MAIL_LIST_RESULT, (200)); // guess size data << uint8(0); // mail's count time_t cur_time = time(NULL); for(PlayerMails::iterator itr = _player->GetMailBegin(); itr != _player->GetMailEnd(); ++itr) { // packet send mail count as uint8, prevent overflow if(mailsCount >= 254) break; // skip deleted or not delivered (deliver delay not expired) mails if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time) continue; /*[-ZERO] TODO recheck this size_t next_mail_size = 4+1+8+((*itr)->subject.size()+1)+4*7+1+item_count*(1+4+4+6*3*4+4+4+1+4+4+4); if(data.wpos()+next_mail_size > maxPacketSize) break; */ data << uint32((*itr)->messageID); // Message ID data << uint8((*itr)->messageType); // Message Type switch((*itr)->messageType) { case MAIL_NORMAL: // sender guid data << ObjectGuid(HIGHGUID_PLAYER, (*itr)->sender); break; case MAIL_CREATURE: case MAIL_GAMEOBJECT: case MAIL_AUCTION: data << (uint32) (*itr)->sender; // creature/gameobject entry, auction id break; case MAIL_ITEM: // item entry (?) sender = "Unknown", NYI break; } data << (*itr)->subject; // Subject string - once 00, when mail type = 3 data << uint32((*itr)->itemTextId); // sure about this data << uint32(0); // unknown data << uint32((*itr)->stationery); // stationery (Stationery.dbc) // 1.12.1 can have only single item Item *item = (*itr)->items.size() > 0 ? _player->GetMItem((*itr)->items[0].item_guid) : NULL; data << uint32(item ? item->GetEntry() : 0); // entry // permanent enchantment data << uint32(item ? item->GetEnchantmentId((EnchantmentSlot)PERM_ENCHANTMENT_SLOT) : 0); // can be negative data << uint32(item ? item->GetItemRandomPropertyId() : 0); // unk data << uint32(item ? item->GetItemSuffixFactor() : 0); data << uint8(item ? item->GetCount() : 0); // stack count data << uint32(item ? item->GetSpellCharges() : 0); // charges // durability data << uint32(item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0); // durability data << uint32(item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0); data << uint32((*itr)->money); // copper data << uint32((*itr)->COD); // Cash on delivery data << uint32((*itr)->checked); // flags data << float(float((*itr)->expire_time - time(NULL)) / float(DAY));// Time data << uint32((*itr)->mailTemplateId); // mail template (MailTemplate.dbc) mailsCount += 1; } data.put<uint8>(0, mailsCount); // set real send mails to client SendPacket(&data); // recalculate m_nextMailDelivereTime and unReadMails _player->UpdateNextMailTimeAndUnreads(); }
//called when player lists his received mails void WorldSession::HandleGetMailList(WorldPacket& recvData) { ObjectGuid mailbox; recvData >> mailbox; if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; Player* player = _player; //load players mails, and mailed items if (!player->m_mailsLoaded) player->_LoadMail(); // client can't work with packets > max int16 value const uint32 maxPacketSize = 32767; uint32 mailCount = 0; uint32 realCount = 0; // true mail count (includes any skipped mail) time_t cur_time = time(NULL); ByteBuffer mailData; WorldPacket data(SMSG_MAIL_LIST_RESULT, 200); // guess size data << uint32(0); // placeholder size_t mailCountPos = data.bitwpos(); data.WriteBits(0, 18); // placeholder for (PlayerMails::iterator itr = player->GetMailBegin(); itr != player->GetMailEnd(); ++itr) { Mail* mail = *itr; // Only first 50 mails are displayed if (mailCount >= 50) { realCount += 1; continue; } // skip deleted or not delivered (deliver delay not expired) mails if (mail->state == MAIL_STATE_DELETED || cur_time < mail->deliver_time) continue; // skip mail with more than MAX_MAIL_ITEMS items (should not occur) uint8 itemCount = mail->items.size(); if (itemCount > MAX_MAIL_ITEMS) { realCount += 1; continue; } // skip mail if the packet has become too large (should not occur) size_t nextMailSize = 6 + 1 + 8 + itemCount * (4 + 4 + 4 + 4 + 4 + MAX_INSPECTED_ENCHANTMENT_SLOT * (4 + 4 + 4) + 4 + 4 + 4 + 4 + 1 + 4) + mail->body.size() + mail->subject.size() + 4 + 4 + 8 + 4 + 8 + 4 + 4 + 1 + 4; if (data.wpos() + nextMailSize > maxPacketSize) { realCount += 1; continue; } data.WriteBit(mail->messageType != MAIL_NORMAL ? 1 : 0); data.WriteBits(mail->subject.size(), 8); data.WriteBits(mail->body.size(), 13); data.WriteBit(0); data.WriteBit(0); size_t itemCountPos = data.bitwpos(); data.WriteBits(0, 17); // placeholder data.WriteBit(1); // has guid ObjectGuid guid = mail->messageType == MAIL_NORMAL ? MAKE_NEW_GUID(mail->sender, 0, HIGHGUID_PLAYER) : 0; data << guid; uint8 trueItemCount = 0; for (uint8 i = 0; i < itemCount; i++) { Item* item = player->GetMItem(mail->items[i].item_guid); if (!item) continue; data.WriteBit(0); mailData << uint32(item->GetGUIDLow()); mailData << uint32(4); // unknown mailData << uint32(item->GetSpellCharges()); mailData << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY)); mailData << uint32(0); // unknown for (uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; j++) { mailData << uint32(item->GetEnchantmentCharges((EnchantmentSlot)j)); mailData << uint32(item->GetEnchantmentDuration((EnchantmentSlot)j)); mailData << uint32(item->GetEnchantmentId((EnchantmentSlot)j)); } mailData << uint32(item->GetItemSuffixFactor()); mailData << int32(item->GetItemRandomPropertyId()); mailData << uint32(item->GetUInt32Value(ITEM_FIELD_MAX_DURABILITY)); mailData << uint32(item->GetCount()); mailData << uint8(i); mailData << uint32(item->GetEntry()); trueItemCount++; } data.PutBits(itemCountPos, trueItemCount, 17); mailData.WriteString(mail->body); mailData << uint32(mail->messageID); mailData << guid; mailData << uint32(mail->mailTemplateId); mailData << uint64(mail->COD); mailData.WriteString(mail->subject); mailData << uint32(mail->stationery); mailData << float(float(mail->expire_time - time(NULL)) / DAY); mailData << uint64(mail->money); mailData << uint32(mail->checked); if (mail->messageType != MAIL_NORMAL) mailData << uint32(mail->sender); mailData << uint8(mail->messageType); mailData << uint32(0); // unknown realCount++; mailCount++; } data.FlushBits(); data.append(mailData); data.put<uint32>(0, realCount); data.PutBits(mailCountPos, mailCount, 18); SendPacket(&data); // recalculate m_nextMailDelivereTime and unReadMails _player->UpdateNextMailTimeAndUnreads(); }
void AuctionHouseObject::BuildListAuctionItems(WorldPackets::AuctionHouse::AuctionListItemsResult& packet, Player* player, std::wstring const& wsearchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable, uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality, uint32& totalcount) { time_t curTime = sWorld->GetGameTime(); for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr) { AuctionEntry* Aentry = itr->second; // Skip expired auctions if (Aentry->expire_time < curTime) continue; Item* item = sAuctionMgr->GetAItem(Aentry->itemGUIDLow); if (!item) continue; ItemTemplate const* proto = item->GetTemplate(); if (itemClass != 0xffffffff && proto->GetClass() != itemClass) continue; if (itemSubClass != 0xffffffff && proto->GetSubClass() != itemSubClass) continue; if (inventoryType != 0xffffffff && proto->GetInventoryType() != InventoryType(inventoryType)) continue; if (quality != 0xffffffff && proto->GetQuality() != quality) continue; if (levelmin != 0 && (proto->GetBaseRequiredLevel() < levelmin || (levelmax != 0 && proto->GetBaseRequiredLevel() > levelmax))) continue; if (usable != 0 && player->CanUseItem(item) != EQUIP_ERR_OK) continue; // Allow search by suffix (ie: of the Monkey) or partial name (ie: Monkey) // No need to do any of this if no search term was entered if (!wsearchedname.empty()) { std::string name = proto->GetName(player->GetSession()->GetSessionDbcLocale()); if (name.empty()) continue; // DO NOT use GetItemEnchantMod(proto->RandomProperty) as it may return a result // that matches the search but it may not equal item->GetItemRandomPropertyId() // used in BuildAuctionInfo() which then causes wrong items to be listed int32 propRefID = item->GetItemRandomPropertyId(); if (propRefID) { // Append the suffix to the name (ie: of the Monkey) if one exists // These are found in ItemRandomSuffix.dbc and ItemRandomProperties.dbc // even though the DBC names seem misleading const char* suffix = nullptr; if (propRefID < 0) { const ItemRandomSuffixEntry* itemRandSuffix = sItemRandomSuffixStore.LookupEntry(-propRefID); if (itemRandSuffix) suffix = itemRandSuffix->Name_lang; } else { const ItemRandomPropertiesEntry* itemRandProp = sItemRandomPropertiesStore.LookupEntry(propRefID); if (itemRandProp) suffix = itemRandProp->Name_lang; } // dbc local name if (suffix) { // Append the suffix (ie: of the Monkey) to the name using localization // or default enUS if localization is invalid name += ' '; name += suffix; } } // Perform the search (with or without suffix) if (!Utf8FitTo(name, wsearchedname)) continue; } // Add the item if no search term or if entered search term was found if (packet.Items.size() < 50 && totalcount >= listfrom) Aentry->BuildAuctionInfo(packet.Items, true); ++totalcount; } }
//called when player lists his received mails void WorldSession::HandleGetMail(WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8); uint64 mailbox; recv_data >> mailbox; //GameObject* obj = ObjectAccessor::GetGameObject(_player, mailbox); //if(!obj || !obj->IsMailBox()) // return; Player* pl = _player; //load players mails, and mailed items if(!pl->m_mailsLoaded) pl ->_LoadMail(); // client can't work with packets > max int16 value const uint32 maxPacketSize = 32767; uint32 mails_count = 0; // real send to client mails amount WorldPacket data(SMSG_MAIL_LIST_RESULT, (200)); // guess size data << uint8(0); // mail's count time_t cur_time = time(NULL); for(PlayerMails::iterator itr = pl->GetmailBegin(); itr != pl->GetmailEnd(); ++itr) { // skip deleted or not delivered (deliver delay not expired) mails if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time) continue; uint8 item_count = (*itr)->items.size(); // max count is MAX_MAIL_ITEMS (12) size_t next_mail_size = 2+4+1+8+4*8+((*itr)->subject.size()+1)+1+item_count*(1+4+4+6*3*4+4+4+1+4+4+4); if(data.wpos()+next_mail_size > maxPacketSize) break; data << (uint16) 0x0040; // unknown 2.3.0, different values data << (uint32) (*itr)->messageID; // Message ID data << (uint8) (*itr)->messageType; // Message Type switch((*itr)->messageType) { case MAIL_NORMAL: // sender guid data << uint64(MAKE_NEW_GUID((*itr)->sender, 0, HIGHGUID_PLAYER)); break; case MAIL_CREATURE: case MAIL_GAMEOBJECT: case MAIL_AUCTION: data << (uint32) (*itr)->sender; // creature/gameobject entry, auction id break; case MAIL_ITEM: // item entry (?) sender = "Unknown", NYI break; } data << (uint32) (*itr)->COD; // COD data << (uint32) (*itr)->itemTextId; // sure about this data << (uint32) 0; // unknown data << (uint32) (*itr)->stationery; // stationery (Stationery.dbc) data << (uint32) (*itr)->money; // Gold data << (uint32) 0x04; // unknown, 0x4 - auction, 0x10 - normal // Time data << (float) ((*itr)->expire_time-time(NULL))/DAY; data << (uint32) (*itr)->mailTemplateId; // mail template (MailTemplate.dbc) data << (*itr)->subject; // Subject string - once 00, when mail type = 3 data << (uint8) item_count; // client limit is 0x10 for(uint8 i = 0; i < item_count; ++i) { Item *item = pl->GetMItem((*itr)->items[i].item_guid); // item index (0-6?) data << (uint8) i; // item guid low? data << (uint32) (item ? item->GetGUIDLow() : 0); // entry data << (uint32) (item ? item->GetEntry() : 0); for(uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j) { // unsure data << (uint32) (item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0); // unsure data << (uint32) (item ? item->GetEnchantmentDuration((EnchantmentSlot)j) : 0); // unsure data << (uint32) (item ? item->GetEnchantmentId((EnchantmentSlot)j) : 0); } // can be negative data << (uint32) (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; } mails_count += 1; } data.put<uint8>(0, mails_count); // set real send mails to client SendPacket(&data); // recalculate m_nextMailDelivereTime and unReadMails _player->UpdateNextMailTimeAndUnreads(); }
void WorldSession::HandleVoidStorageTransfer(WorldPackets::VoidStorage::VoidStorageTransfer& voidStorageTransfer) { Creature* unit = _player->GetNPCIfCanInteractWith(voidStorageTransfer.Npc, UNIT_NPC_FLAG_VAULTKEEPER); if (!unit) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - %s not found or player can't interact with it.", voidStorageTransfer.Npc.ToString().c_str()); return; } if (!_player->IsVoidStorageUnlocked()) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (%s, name: %s) queried void storage without unlocking it.", _player->GetGUID().ToString().c_str(), _player->GetName().c_str()); return; } if (voidStorageTransfer.Deposits.size() > _player->GetNumOfVoidStorageFreeSlots()) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL); return; } uint32 freeBagSlots = 0; if (!voidStorageTransfer.Withdrawals.empty()) { // make this a Player function for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) if (Bag* bag = _player->GetBagByPos(i)) freeBagSlots += bag->GetFreeSlots(); for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) if (!_player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) ++freeBagSlots; } if (voidStorageTransfer.Withdrawals.size() > freeBagSlots) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL); return; } if (!_player->HasEnoughMoney(uint64(voidStorageTransfer.Deposits.size() * VOID_STORAGE_STORE_ITEM_COST))) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NOT_ENOUGH_MONEY); return; } WorldPackets::VoidStorage::VoidStorageTransferChanges voidStorageTransferChanges; voidStorageTransferChanges.AddedItems.reserve(VOID_STORAGE_MAX_DEPOSIT); voidStorageTransferChanges.RemovedItems.reserve(VOID_STORAGE_MAX_DEPOSIT); uint8 depositCount = 0; for (uint32 i = 0; i < voidStorageTransfer.Deposits.size(); ++i) { Item* item = _player->GetItemByGuid(voidStorageTransfer.Deposits[i]); if (!item) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - %s %s wants to deposit an invalid item (%s).", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), voidStorageTransfer.Deposits[i].ToString().c_str()); continue; } VoidStorageItem itemVS(sObjectMgr->GenerateVoidStorageItemId(), item->GetEntry(), item->GetGuidValue(ITEM_FIELD_CREATOR), item->GetItemRandomPropertyId(), item->GetItemSuffixFactor(), item->GetModifier(ITEM_MODIFIER_UPGRADE_ID), item->GetDynamicValues(ITEM_DYNAMIC_FIELD_BONUSLIST_IDS)); WorldPackets::VoidStorage::VoidItem voidItem; voidItem.Guid = ObjectGuid::Create<HighGuid::Item>(itemVS.ItemId); voidItem.Creator = item->GetGuidValue(ITEM_FIELD_CREATOR); voidItem.Item.Initialize(&itemVS); voidItem.Slot = _player->AddVoidStorageItem(std::move(itemVS)); voidStorageTransferChanges.AddedItems.push_back(voidItem); _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); ++depositCount; } int64 cost = depositCount * VOID_STORAGE_STORE_ITEM_COST; _player->ModifyMoney(-cost); for (uint32 i = 0; i < voidStorageTransfer.Withdrawals.size(); ++i) { uint8 slot = 0; VoidStorageItem* itemVS = _player->GetVoidStorageItem(voidStorageTransfer.Withdrawals[i].GetCounter(), slot); if (!itemVS) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - %s %s tried to withdraw an invalid item (id: %s)", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), voidStorageTransfer.Withdrawals[i].ToString().c_str()); continue; } ItemPosCountVec dest; InventoryResult msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemVS->ItemEntry, 1); if (msg != EQUIP_ERR_OK) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL); TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - %s %s couldn't withdraw item id %s because inventory was full.", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), voidStorageTransfer.Withdrawals[i].ToString().c_str()); return; } Item* item = _player->StoreNewItem(dest, itemVS->ItemEntry, true, itemVS->ItemRandomPropertyId, GuidSet(), itemVS->BonusListIDs); item->SetUInt32Value(ITEM_FIELD_PROPERTY_SEED, itemVS->ItemSuffixFactor); item->SetGuidValue(ITEM_FIELD_CREATOR, itemVS->CreatorGuid); item->SetModifier(ITEM_MODIFIER_UPGRADE_ID, itemVS->ItemUpgradeId); item->SetBinding(true); voidStorageTransferChanges.RemovedItems.push_back(ObjectGuid::Create<HighGuid::Item>(itemVS->ItemId)); _player->DeleteVoidStorageItem(slot); } SendPacket(voidStorageTransferChanges.Write()); SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NO_ERROR); }
void WorldSession::SendUpdateTrade(bool trader_data /*= true*/) { TradeData* view_trade = trader_data ? _player->GetTradeData()->GetTraderData() : _player->GetTradeData(); ByteBuffer itemData(7*2 + 7*4 + 3*4 + 3*4 + 1); uint8 count = 0; for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i) if (view_trade->GetItem(TradeSlots(i))) ++count; WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, 4*6 + 8 + 1 + 3 + count * 70); data << uint32(0); // this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?) data << uint32(0); // unk 2 data << uint64(view_trade->GetMoney()); // trader gold data << uint32(view_trade->GetSpell()); // spell casted on lowest slot item data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = next field in most cases data << uint32(0); // unk 5 data << uint8(trader_data); // 1 means traders data, 0 means own data << uint32(TRADE_SLOT_COUNT); // trade slots count/number?, = prev field in most cases data.WriteBits(count, 22); for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i) { Item* item = view_trade->GetItem(TradeSlots(i)); if (!item) continue; ObjectGuid giftCreatorGuid = item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR); ObjectGuid creatorGuid = item->GetUInt64Value(ITEM_FIELD_CREATOR); data.WriteBit(giftCreatorGuid[7]); data.WriteBit(giftCreatorGuid[1]); bool notWrapped = data.WriteBit(!item->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)); data.WriteBit(giftCreatorGuid[3]); if (notWrapped) { data.WriteBit(creatorGuid[7]); data.WriteBit(creatorGuid[1]); data.WriteBit(creatorGuid[4]); data.WriteBit(creatorGuid[6]); data.WriteBit(creatorGuid[2]); data.WriteBit(creatorGuid[3]); data.WriteBit(creatorGuid[5]); data.WriteBit(item->GetTemplate()->LockID != 0); data.WriteBit(creatorGuid[0]); itemData.WriteByteSeq(creatorGuid[1]); itemData << uint32(item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT)); for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS /*3*/; ++enchant_slot) itemData << uint32(item->GetEnchantmentId(EnchantmentSlot(enchant_slot))); itemData << uint32(item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)); itemData.WriteByteSeq(creatorGuid[6]); itemData.WriteByteSeq(creatorGuid[2]); itemData.WriteByteSeq(creatorGuid[7]); itemData.WriteByteSeq(creatorGuid[4]); itemData << uint32(item->GetEnchantmentId(REFORGE_ENCHANTMENT_SLOT)); itemData << uint32(item->GetUInt32Value(ITEM_FIELD_DURABILITY)); itemData << uint32(item->GetItemRandomPropertyId()); itemData.WriteByteSeq(creatorGuid[3]); itemData << uint32(0); // unk7 itemData.WriteByteSeq(creatorGuid[0]); itemData << uint32(item->GetSpellCharges()); itemData << uint32(item->GetItemSuffixFactor()); itemData.WriteByteSeq(creatorGuid[5]); } data.WriteBit(giftCreatorGuid[6]); data.WriteBit(giftCreatorGuid[4]); data.WriteBit(giftCreatorGuid[2]); data.WriteBit(giftCreatorGuid[0]); data.WriteBit(giftCreatorGuid[5]); itemData.WriteByteSeq(giftCreatorGuid[6]); itemData.WriteByteSeq(giftCreatorGuid[1]); itemData.WriteByteSeq(giftCreatorGuid[7]); itemData.WriteByteSeq(giftCreatorGuid[4]); itemData << uint32(item->GetTemplate()->ItemId); itemData.WriteByteSeq(giftCreatorGuid[0]); itemData << uint32(item->GetCount()); itemData.WriteByteSeq(giftCreatorGuid[5]); itemData << uint8(i); itemData.WriteByteSeq(giftCreatorGuid[2]); itemData.WriteByteSeq(giftCreatorGuid[3]); } data.FlushBits(); data.append(itemData); SendPacket(&data); }
bool ChatHandler::HandleAddItemSetCommand(const char* args, WorldSession* m_session) { uint32 setid = (args ? atoi(args) : 0); if(!setid) { RedSystemMessage(m_session, "You must specify a setid."); return false; } Player* chr = getSelectedChar(m_session); if(!chr) { RedSystemMessage(m_session, "Unable to select character."); return false; } ItemSetEntry* entry = dbcItemSet.LookupEntryForced(setid); std::list<ItemPrototype*>* l = objmgr.GetListForItemSet(setid); if(!entry || !l) { RedSystemMessage(m_session, "Invalid item set."); return false; } //const char* setname = sItemSetStore.LookupString(entry->name); BlueSystemMessage(m_session, "Searching item set %u...", setid); uint32 start = getMSTime(); sGMLog.writefromsession(m_session, "used add item set command, set %u, target %s", setid, chr->GetName()); for(std::list<ItemPrototype*>::iterator itr = l->begin(); itr != l->end(); ++itr) { Item* itm = objmgr.CreateItem((*itr)->ItemId, m_session->GetPlayer()); if(!itm) continue; if(itm->GetProto()->Bonding == ITEM_BIND_ON_PICKUP) { if(itm->GetProto()->Flags & ITEM_FLAG_ACCOUNTBOUND) // don't "Soulbind" account-bound items itm->AccountBind(); else itm->SoulBind(); } if(!chr->GetItemInterface()->AddItemToFreeSlot(itm)) { m_session->SendNotification("No free slots left!"); itm->DeleteMe(); return false; } else { //SystemMessage(m_session, "Added item: %s [%u]", (*itr)->Name1, (*itr)->ItemId); SlotResult* le = chr->GetItemInterface()->LastSearchResult(); chr->SendItemPushResult(false, true, false, true, le->ContainerSlot, le->Slot, 1 , itm->GetEntry(), itm->GetItemRandomSuffixFactor(), itm->GetItemRandomPropertyId(), itm->GetStackCount()); } } GreenSystemMessage(m_session, "Added set to inventory complete. Time: %u ms", getMSTime() - start); return true; }
/// \todo refactoring bool MailMessage::AddMessageDataToPacket(WorldPacket& data) { uint8 i = 0; uint32 j; std::vector<uint32>::iterator itr; Item* pItem; // add stuff if (deleted_flag) return false; uint8 guidsize; if (message_type == 0) guidsize = 8; else guidsize = 4; size_t msize = 2 + 4 + 1 + guidsize + 7 * 4 + (subject.size() + 1) + (body.size() + 1) + 1 + (items.size() * (1 + 2 * 4 + 7 * (3 * 4) + 6 * 4 + 1)); data << uint16(msize); // message size data << uint32(message_id); data << uint8(message_type); switch (message_type) { case NORMAL: data << uint64(sender_guid); break; case COD: case AUCTION: case GAMEOBJECT: case ITEM: data << uint32(Arcemu::Util::GUID_LOPART(sender_guid)); break; case CREATURE: data << uint32(Arcemu::Util::GET_CREATURE_ENTRY_FROM_GUID(sender_guid)); break; } data << uint32(cod); // cod data << uint32(0); data << uint32(stationery); data << uint32(money); // money data << uint32(checked_flag); // "checked" flag data << float((expire_time - uint32(UNIXTIME)) / 86400.0f); data << uint32(0); // mail template data << subject; data << body; data << uint8(items.size()); // item count if (!items.empty()) { for (itr = items.begin(); itr != items.end(); ++itr) { pItem = objmgr.LoadItem(*itr); if (pItem == NULL) continue; data << uint8(i++); data << uint32(pItem->GetLowGUID()); data << uint32(pItem->GetEntry()); for (j = 0; j < 7; ++j) { data << uint32(pItem->GetEnchantmentId(j)); data << uint32(pItem->GetEnchantmentDuration(j)); data << uint32(0); } data << uint32(pItem->GetItemRandomPropertyId()); data << uint32(pItem->GetItemRandomSuffixFactor()); data << uint32(pItem->GetStackCount()); data << uint32(pItem->GetChargesLeft()); data << uint32(pItem->GetDurabilityMax()); data << uint32(pItem->GetDurability()); data << uint8(0); // unknown delete pItem; } } return true; }
void WorldSession::HandleVoidStorageTransfer(WorldPacket& recvData) { Player* player = GetPlayer(); // Read everything ObjectGuid npcGuid; recvData.ReadByteMask(npcGuid[1]); uint32 countDeposit = recvData.ReadBits(26); if (countDeposit > 9) return; std::vector<ObjectGuid> itemGuids(countDeposit); for (uint32 i = 0; i < countDeposit; ++i) { recvData .ReadByteMask(itemGuids[i][4]) .ReadByteMask(itemGuids[i][6]) .ReadByteMask(itemGuids[i][7]) .ReadByteMask(itemGuids[i][0]) .ReadByteMask(itemGuids[i][1]) .ReadByteMask(itemGuids[i][5]) .ReadByteMask(itemGuids[i][3]) .ReadByteMask(itemGuids[i][2]); } recvData .ReadByteMask(npcGuid[2]) .ReadByteMask(npcGuid[0]) .ReadByteMask(npcGuid[3]) .ReadByteMask(npcGuid[5]) .ReadByteMask(npcGuid[6]) .ReadByteMask(npcGuid[4]); uint32 countWithdraw = recvData.ReadBits(26); if (countWithdraw > 9) return; std::vector<ObjectGuid> itemIds(countWithdraw); for (uint32 i = 0; i < countWithdraw; ++i) { recvData .ReadByteMask(itemIds[i][4]) .ReadByteMask(itemIds[i][7]) .ReadByteMask(itemIds[i][1]) .ReadByteMask(itemIds[i][0]) .ReadByteMask(itemIds[i][2]) .ReadByteMask(itemIds[i][3]) .ReadByteMask(itemIds[i][5]) .ReadByteMask(itemIds[i][6]); } recvData.ReadByteMask(npcGuid[7]); for (uint32 i = 0; i < countDeposit; ++i) { recvData .ReadByteSeq(itemGuids[i][6]) .ReadByteSeq(itemGuids[i][1]) .ReadByteSeq(itemGuids[i][0]) .ReadByteSeq(itemGuids[i][2]) .ReadByteSeq(itemGuids[i][4]) .ReadByteSeq(itemGuids[i][5]) .ReadByteSeq(itemGuids[i][3]) .ReadByteSeq(itemGuids[i][7]); } recvData.ReadByteSeq(npcGuid[5]); recvData.ReadByteSeq(npcGuid[6]); for (uint32 i = 0; i < countWithdraw; ++i) { recvData .ReadByteSeq(itemIds[i][3]) .ReadByteSeq(itemIds[i][0]) .ReadByteSeq(itemIds[i][1]) .ReadByteSeq(itemIds[i][6]) .ReadByteSeq(itemIds[i][2]) .ReadByteSeq(itemIds[i][7]) .ReadByteSeq(itemIds[i][5]) .ReadByteSeq(itemIds[i][4]); } recvData .ReadByteSeq(npcGuid[1]) .ReadByteSeq(npcGuid[4]) .ReadByteSeq(npcGuid[7]) .ReadByteSeq(npcGuid[3]) .ReadByteSeq(npcGuid[2]) .ReadByteSeq(npcGuid[0]); Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER); if (!unit) return; if (!player->IsVoidStorageUnlocked()) return; if (itemGuids.size() > player->GetNumOfVoidStorageFreeSlots()) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL); return; } uint32 freeBagSlots = 0; if (itemIds.size() != 0) { // make this a Player function for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) if (Bag* bag = player->GetBagByPos(i)) freeBagSlots += bag->GetFreeSlots(); for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) if (!player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) ++freeBagSlots; } if (itemIds.size() > freeBagSlots) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL); return; } if (!player->HasEnoughMoney(uint64(itemGuids.size() * VOID_STORAGE_STORE_ITEM))) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NOT_ENOUGH_MONEY); return; } std::pair<VoidStorageItem, uint8> depositItems[VOID_STORAGE_MAX_DEPOSIT]; uint8 depositCount = 0; for (std::vector<ObjectGuid>::iterator itr = itemGuids.begin(); itr != itemGuids.end(); ++itr) { Item* item = player->GetItemByGuid(*itr); if (!item) continue; VoidStorageItem itemVS(sObjectMgr->GenerateVoidStorageItemId(), item->GetEntry(), item->GetUInt64Value(ITEM_FIELD_CREATOR), item->GetItemRandomPropertyId(), item->GetItemSuffixFactor()); uint8 slot = player->AddVoidStorageItem(itemVS); depositItems[depositCount++] = std::make_pair(itemVS, slot); player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); } int64 cost = depositCount * VOID_STORAGE_STORE_ITEM; player->ModifyMoney(-cost); VoidStorageItem withdrawItems[VOID_STORAGE_MAX_WITHDRAW]; uint8 withdrawCount = 0; for (std::vector<ObjectGuid>::iterator itr = itemIds.begin(); itr != itemIds.end(); ++itr) { uint8 slot; VoidStorageItem* itemVS = player->GetVoidStorageItem(*itr, slot); if (!itemVS) continue; ItemPosCountVec dest; InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemVS->ItemEntry, 1); if (msg != EQUIP_ERR_OK) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL); return; } Item* item = player->StoreNewItem(dest, itemVS->ItemEntry, true, itemVS->ItemRandomPropertyId); item->SetUInt64Value(ITEM_FIELD_CREATOR, uint64(itemVS->CreatorGuid)); item->SetBinding(true); player->SendNewItem(item, 1, false, false, false); withdrawItems[withdrawCount++] = *itemVS; player->DeleteVoidStorageItem(slot); } WorldPacket data(SMSG_VOID_STORAGE_TRANSFER_CHANGES, ((5 + 5 + (7 + 7) * depositCount + 7 * withdrawCount) / 8) + 7 * withdrawCount + (7 + 7 + 4 * 4) * depositCount); data.WriteBits(depositCount, 5); data.WriteBits(withdrawCount, 5); for (uint8 i = 0; i < depositCount; ++i) { ObjectGuid itemId = depositItems[i].first.ItemId; ObjectGuid creatorGuid = depositItems[i].first.CreatorGuid; data.WriteByteMask(creatorGuid[7]); data.WriteByteMask(itemId[7]); data.WriteByteMask(itemId[4]); data.WriteByteMask(creatorGuid[6]); data.WriteByteMask(creatorGuid[5]); data.WriteByteMask(itemId[3]); data.WriteByteMask(itemId[5]); data.WriteByteMask(creatorGuid[4]); data.WriteByteMask(creatorGuid[2]); data.WriteByteMask(creatorGuid[0]); data.WriteByteMask(creatorGuid[3]); data.WriteByteMask(creatorGuid[1]); data.WriteByteMask(itemId[2]); data.WriteByteMask(itemId[0]); data.WriteByteMask(itemId[1]); data.WriteByteMask(itemId[6]); } for (uint8 i = 0; i < withdrawCount; ++i) { ObjectGuid itemId = withdrawItems[i].ItemId; data.WriteByteMask(itemId[1]); data.WriteByteMask(itemId[7]); data.WriteByteMask(itemId[3]); data.WriteByteMask(itemId[5]); data.WriteByteMask(itemId[6]); data.WriteByteMask(itemId[2]); data.WriteByteMask(itemId[4]); data.WriteByteMask(itemId[0]); } for (uint8 i = 0; i < withdrawCount; ++i) { ObjectGuid itemId = withdrawItems[i].ItemId; data.WriteByteSeq(itemId[3]); data.WriteByteSeq(itemId[1]); data.WriteByteSeq(itemId[0]); data.WriteByteSeq(itemId[2]); data.WriteByteSeq(itemId[7]); data.WriteByteSeq(itemId[5]); data.WriteByteSeq(itemId[6]); data.WriteByteSeq(itemId[4]); } for (uint8 i = 0; i < depositCount; ++i) { ObjectGuid itemId = depositItems[i].first.ItemId; ObjectGuid creatorGuid = depositItems[i].first.CreatorGuid; data << uint32(depositItems[i].first.ItemSuffixFactor); data.WriteByteSeq(itemId[6]); data.WriteByteSeq(itemId[4]); data.WriteByteSeq(creatorGuid[4]); data.WriteByteSeq(itemId[2]); data.WriteByteSeq(creatorGuid[1]); data.WriteByteSeq(creatorGuid[3]); data.WriteByteSeq(itemId[3]); data.WriteByteSeq(creatorGuid[0]); data.WriteByteSeq(itemId[0]); data.WriteByteSeq(creatorGuid[6]); data.WriteByteSeq(itemId[5]); data.WriteByteSeq(creatorGuid[5]); data.WriteByteSeq(creatorGuid[7]); data << uint32(depositItems[i].first.ItemEntry); data.WriteByteSeq(itemId[1]); data << uint32(depositItems[i].second); // slot data.WriteByteSeq(creatorGuid[2]); data.WriteByteSeq(itemId[7]); data << uint32(depositItems[i].first.ItemRandomPropertyId); } SendPacket(&data); SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NO_ERROR); }
void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player, std::wstring const& wsearchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable, uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality, uint32& count, uint32& totalcount, bool getall) { int loc_idx = player->GetSession()->GetSessionDbLocaleIndex(); int locdbc_idx = player->GetSession()->GetSessionDbcLocale(); time_t curTime = GameTime::GetGameTime(); PlayerGetAllThrottleMap::const_iterator itr = GetAllThrottleMap.find(player->GetGUID()); time_t throttleTime = itr != GetAllThrottleMap.end() ? itr->second : curTime; if (getall && throttleTime <= curTime) { for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr) { AuctionEntry* Aentry = itr->second; // Skip expired auctions if (Aentry->expire_time < curTime) continue; Item* item = sAuctionMgr->GetAItem(Aentry->itemGUIDLow); if (!item) continue; ++count; ++totalcount; Aentry->BuildAuctionInfo(data, item); if (count >= MAX_GETALL_RETURN) break; } GetAllThrottleMap[player->GetGUID()] = curTime + sWorld->getIntConfig(CONFIG_AUCTION_GETALL_DELAY); return; } for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr) { AuctionEntry* Aentry = itr->second; // Skip expired auctions if (Aentry->expire_time < curTime) continue; Item* item = sAuctionMgr->GetAItem(Aentry->itemGUIDLow); if (!item) continue; ItemTemplate const* proto = item->GetTemplate(); if (itemClass != 0xffffffff && proto->Class != itemClass) continue; if (itemSubClass != 0xffffffff && proto->SubClass != itemSubClass) continue; if (inventoryType != 0xffffffff && proto->InventoryType != inventoryType) continue; if (quality != 0xffffffff && proto->Quality != quality) continue; if (levelmin != 0x00 && (proto->RequiredLevel < levelmin || (levelmax != 0x00 && proto->RequiredLevel > levelmax))) continue; if (usable != 0x00 && player->CanUseItem(item) != EQUIP_ERR_OK) continue; // Allow search by suffix (ie: of the Monkey) or partial name (ie: Monkey) // No need to do any of this if no search term was entered if (!wsearchedname.empty()) { std::string name = proto->Name1; if (name.empty()) continue; // local name if (loc_idx >= 0) if (ItemLocale const* il = sObjectMgr->GetItemLocale(proto->ItemId)) ObjectMgr::GetLocaleString(il->Name, loc_idx, name); // DO NOT use GetItemEnchantMod(proto->RandomProperty) as it may return a result // that matches the search but it may not equal item->GetItemRandomPropertyId() // used in BuildAuctionInfo() which then causes wrong items to be listed int32 propRefID = item->GetItemRandomPropertyId(); if (propRefID) { // Append the suffix to the name (ie: of the Monkey) if one exists // These are found in ItemRandomSuffix.dbc and ItemRandomProperties.dbc // even though the DBC names seem misleading char* const* suffix = nullptr; if (propRefID < 0) { const ItemRandomSuffixEntry* itemRandSuffix = sItemRandomSuffixStore.LookupEntry(-propRefID); if (itemRandSuffix) suffix = itemRandSuffix->nameSuffix; } else { const ItemRandomPropertiesEntry* itemRandProp = sItemRandomPropertiesStore.LookupEntry(propRefID); if (itemRandProp) suffix = itemRandProp->nameSuffix; } // dbc local name if (suffix) { // Append the suffix (ie: of the Monkey) to the name using localization // or default enUS if localization is invalid name += ' '; name += suffix[locdbc_idx >= 0 ? locdbc_idx : LOCALE_enUS]; } } // Perform the search (with or without suffix) if (!Utf8FitTo(name, wsearchedname)) continue; } // Add the item if no search term or if entered search term was found if (count < 50 && totalcount >= listfrom) { ++count; Aentry->BuildAuctionInfo(data, item); } ++totalcount; } }
WorldPacket* Mailbox::BuildMailboxListingPacket() { WorldPacket* data = new WorldPacket(SMSG_MAIL_LIST_RESULT, 200); MessageMap::iterator itr; uint8 i = 0; uint32 realCount = 0; uint32 mailsCount = 0; uint32 t = (uint32)UNIXTIME; *data << uint32(0); // real mail's count *data << uint8(0); // mail's count for (itr = Messages.begin(); itr != Messages.end(); ++itr) { if (itr->second.expire_time && t > itr->second.expire_time) continue; // expired mail -> skip it if ((uint32)UNIXTIME < itr->second.delivery_time) continue; // undelivered if (mailsCount >= 50) //VLack: We could calculate message sizes instead of this, but the original code did a break at 50, so I won't fix this up if no one felt the need to do so before ;-) { realCount += 1; continue; } uint8 item_count = itr->second.items.size(); // max count is MAX_MAIL_ITEMS (12) size_t next_mail_size = 2 + 4 + 1 + (itr->second.message_type == NORMAL ? 8 : 4) + 4 * 8 + (itr->second.subject.size() + 1) + (itr->second.body.size() + 1) + 1 + item_count*(1 + 4 + 4 + MAX_INSPECTED_ENCHANTMENT_SLOT * 3 * 4 + 4 + 4 + 4 + 4 + 4 + 4 + 1); *data << uint16(next_mail_size); // Message size *data << uint32(itr->second.message_id); // Message ID *data << uint8(itr->second.message_type); // Message Type switch (itr->second.message_type) { case NORMAL: *data << uint64((itr->second.sender_guid)); break; case COD: case AUCTION: case ITEM: *data << uint32(Arcemu::Util::GUID_LOPART((itr->second.sender_guid))); break; case GAMEOBJECT: case CREATURE: *data << uint32(static_cast<uint32>((itr->second.sender_guid))); break; } *data << uint64(itr->second.cod); // COD *data << uint32(0); // Package.dbc ID ? *data << uint32(itr->second.stationery); // stationery (Stationery.dbc) *data << uint64(itr->second.money); // Gold *data << uint32(itr->second.checked_flag); // flags *data << float(float((itr->second.expire_time - uint32(UNIXTIME)) / DAY)); // Time *data << uint32(itr->second.message_id); // mail template (MailTemplate.dbc) *data << itr->second.subject; // Subject string - once 00, when mail type = 3, max 256 *data << itr->second.body; // message? max 8000 *data << uint8(item_count); // client limit is 0x10 Item* pItem; std::vector<uint32>::iterator itr2; for (uint8 i = 0; i < item_count; ++i) { pItem = objmgr.LoadItem(itr->second.items[i]); // item index (0-6?) *data << uint8(i); // item guid low? *data << uint32((pItem ? pItem->GetLowGUID() : 0)); // entry *data << uint32((pItem ? pItem->GetEntry() : 0)); for (uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j) { *data << uint32((pItem ? pItem->GetEnchantmentId((EnchantmentSlot)j) : 0)); *data << uint32((pItem ? pItem->GetEnchantmentDuration((EnchantmentSlot)j) : 0)); *data << uint32((pItem ? pItem->GetEnchantmentCharges((EnchantmentSlot)j) : 0)); } // can be negative *data << int32((pItem ? pItem->GetItemRandomPropertyId() : 0)); // unk *data << uint32((pItem ? pItem->GetItemRandomSuffixFactor() : 0)); // stack count *data << uint32((pItem ? pItem->GetStackCount() : 0)); // charges *data << uint32((pItem ? pItem->GetChargesLeft() : 0)); // durability *data << uint32((pItem ? pItem->GetDurabilityMax() : 0)); // durability *data << uint32((pItem ? pItem->GetDurability() : 0)); // unknown wotlk *data << uint8(0); } ++realCount; ++mailsCount; } 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 // do cleanup on request mail CleanupExpiredMessages(); return data; }
void AuctionHouseMgr::LoadAuctions() { QueryResult* result = CharacterDatabase.Query("SELECT COUNT(*) FROM auction"); if (!result) { BarGoLink bar(1); bar.step(); sLog.outString(">> Loaded 0 auctions. DB table `auction` is empty."); return; } Field* fields = result->Fetch(); uint32 AuctionCount = fields[0].GetUInt32(); delete result; if (!AuctionCount) { BarGoLink bar(1); bar.step(); sLog.outString(">> Loaded 0 auctions. DB table `auction` is empty."); return; } result = CharacterDatabase.Query("SELECT id,houseid,itemguid,item_template,item_count,item_randompropertyid,itemowner,buyoutprice,time,buyguid,lastbid,startbid,deposit FROM auction"); if (!result) { BarGoLink bar(1); bar.step(); sLog.outString(">> Loaded 0 auctions. DB table `auction` is empty."); return; } BarGoLink bar(AuctionCount); typedef std::map<uint32, std::wstring> PlayerNames; PlayerNames playerNames; // caching for load time do { fields = result->Fetch(); bar.step(); AuctionEntry* auction = new AuctionEntry; auction->Id = fields[0].GetUInt32(); uint32 houseid = fields[1].GetUInt32(); auction->itemGuidLow = fields[2].GetUInt32(); auction->itemTemplate = fields[3].GetUInt32(); auction->itemCount = fields[4].GetUInt32(); auction->itemRandomPropertyId = fields[5].GetUInt32(); auction->owner = fields[6].GetUInt32(); if (auction->owner) { std::wstring& plWName = playerNames[auction->owner]; if (plWName.empty()) { std::string plName; if (!sObjectMgr.GetPlayerNameByGUID(ObjectGuid(HIGHGUID_PLAYER, auction->owner), plName)) plName = sObjectMgr.GetMangosStringForDBCLocale(LANG_UNKNOWN); Utf8toWStr(plName, plWName); } auction->ownerName = plWName; } auction->buyout = fields[7].GetUInt32(); auction->expireTime = time_t(fields[8].GetUInt64()); auction->bidder = fields[9].GetUInt32(); auction->bid = fields[10].GetUInt32(); auction->startbid = fields[11].GetUInt32(); auction->deposit = fields[12].GetUInt32(); auction->auctionHouseEntry = NULL; // init later // check if sold item exists for guid // and item_template in fact (GetAItem will fail if problematic in result check in AuctionHouseMgr::LoadAuctionItems) Item* pItem = GetAItem(auction->itemGuidLow); if (!pItem) { auction->DeleteFromDB(); sLog.outError("Auction %u has not a existing item : %u, deleted", auction->Id, auction->itemGuidLow); delete auction; continue; } // overwrite by real item data if ((auction->itemTemplate != pItem->GetEntry()) || (auction->itemCount != pItem->GetCount()) || (auction->itemRandomPropertyId != pItem->GetItemRandomPropertyId())) { auction->itemTemplate = pItem->GetEntry(); auction->itemCount = pItem->GetCount(); auction->itemRandomPropertyId = pItem->GetItemRandomPropertyId(); // No SQL injection (no strings) CharacterDatabase.PExecute("UPDATE auction SET item_template = %u, item_count = %u, item_randompropertyid = %i WHERE itemguid = %u", auction->itemTemplate, auction->itemCount, auction->itemRandomPropertyId, auction->itemGuidLow); } auction->auctionHouseEntry = sAuctionHouseStore.LookupEntry(houseid); if (!auction->auctionHouseEntry) { // need for send mail, use goblin auctionhouse auction->auctionHouseEntry = sAuctionHouseStore.LookupEntry(7); // Attempt send item back to owner std::ostringstream msgAuctionCanceledOwner; msgAuctionCanceledOwner << auction->itemTemplate << ":" << auction->itemRandomPropertyId << ":" << AUCTION_CANCELED; if (auction->itemGuidLow) { RemoveAItem(auction->itemGuidLow); auction->itemGuidLow = 0; // item will deleted or added to received mail list MailDraft(msgAuctionCanceledOwner.str(), "")// TODO: fix body .AddItem(pItem) .SendMailTo(MailReceiver(ObjectGuid(HIGHGUID_PLAYER, auction->owner)), auction, MAIL_CHECK_MASK_COPIED); } auction->DeleteFromDB(); delete auction; continue; } GetAuctionsMap(auction->auctionHouseEntry)->AddAuction(auction); } while (result->NextRow()); delete result; sLog.outString(">> Loaded %u auctions", AuctionCount); sLog.outString(); }
/** * Handles the packet sent by the client when requesting the current mail list. * It will send a list of all available mails in the players mailbox to the client. */ void WorldSession::HandleGetMailList(WorldPacket& recv_data) { ObjectGuid mailboxGuid; recv_data >> mailboxGuid; if (!CheckMailBox(mailboxGuid)) return; // client can't work with packets > max int16 value const uint32 maxPacketSize = 32767; uint32 mailsCount = 0; // send to client mails amount WorldPacket data(SMSG_MAIL_LIST_RESULT, (200)); // guess size data << uint8(0); // mail's count time_t cur_time = time(nullptr); for (PlayerMails::iterator itr = _player->GetMailBegin(); itr != _player->GetMailEnd(); ++itr) { // packet send mail count as uint8, prevent overflow if (mailsCount >= 254) break; // skip deleted or not delivered (deliver delay not expired) mails if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time) continue; uint8 item_count = (*itr)->items.size(); // max count is MAX_MAIL_ITEMS (12) size_t next_mail_size = 2 + 4 + 1 + 8 + 4 * 8 + ((*itr)->subject.size() + 1) + 1 + item_count * (1 + 4 + 4 + 6 * 3 * 4 + 4 + 4 + 1 + 4 + 4 + 4); if (data.wpos() + next_mail_size > maxPacketSize) break; 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(HIGHGUID_PLAYER, (*itr)->sender); break; case MAIL_CREATURE: case MAIL_GAMEOBJECT: case MAIL_AUCTION: data << uint32((*itr)->sender); // creature/gameobject entry, auction id break; case MAIL_ITEM: // item entry (?) sender = "Unknown", NYI data << uint32(0); // item entry break; } data << uint32((*itr)->COD); // COD data << uint32((*itr)->itemTextId); // item text data << uint32(0); // unknown data << uint32((*itr)->stationery); // stationery (Stationery.dbc) data << uint32((*itr)->money); // copper data << uint32((*itr)->checked); // flags data << float(float((*itr)->expire_time - time(nullptr)) / float(DAY));// Time data << uint32((*itr)->mailTemplateId); // mail template (MailTemplate.dbc) data << (*itr)->subject; // Subject string - once 00, when mail type = 3, max 256 data << (uint8)item_count; 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 << uint32(item ? item->GetGUIDLow() : 0); // entry data << uint32(item ? item->GetEntry() : 0); for (uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j) { // unsure data << uint32(item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0); // unsure data << uint32(item ? item->GetEnchantmentDuration((EnchantmentSlot)j) : 0); // unsure data << uint32(item ? item->GetEnchantmentId((EnchantmentSlot)j) : 0); } // can be negative data << uint32(item ? item->GetItemRandomPropertyId() : 0); // unk data << uint32(item ? item->GetItemSuffixFactor() : 0); // stack count data << (uint8)(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); } mailsCount += 1; } data.put<uint8>(0, mailsCount); // set real send mails to client SendPacket(data); // recalculate m_nextMailDelivereTime and unReadMails _player->UpdateNextMailTimeAndUnreads(); }
void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player, std::wstring const& wsearchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable, uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality, uint32& count, uint32& totalcount) { int loc_idx = player->GetSession()->GetSessionDbLocaleIndex(); int locdbc_idx = player->GetSession()->GetSessionDbcLocale(); for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr) { AuctionEntry* Aentry = itr->second; Item* item = sAuctionMgr->GetAItem(Aentry->item_guidlow); if (!item) continue; ItemTemplate const* proto = item->GetTemplate(); if (itemClass != 0xffffffff && proto->Class != itemClass) continue; if (itemSubClass != 0xffffffff && proto->SubClass != itemSubClass) continue; if (inventoryType != 0xffffffff && proto->InventoryType != inventoryType) continue; if (quality != 0xffffffff && proto->Quality != quality) continue; if (levelmin != 0x00 && (proto->RequiredLevel < levelmin || (levelmax != 0x00 && proto->RequiredLevel > levelmax))) continue; if (usable != 0x00 && player->CanUseItem(item) != EQUIP_ERR_OK) continue; // Allow search by suffix (ie: of the Monkey) or partial name (ie: Monkey) // No need to do any of this if no search term was entered if (!wsearchedname.empty()) { std::string name = proto->Name1; if (name.empty()) continue; // local name if (loc_idx >= 0) if (ItemLocale const* il = sObjectMgr->GetItemLocale(proto->ItemId)) ObjectMgr::GetLocaleString(il->Name, loc_idx, name); // DO NOT use GetItemEnchantMod(proto->RandomProperty) as it may return a result // that matches the search but it may not equal item->GetItemRandomPropertyId() // used in BuildAuctionInfo() which then causes wrong items to be listed int32 propRefID = item->GetItemRandomPropertyId(); if (propRefID) { // Append the suffix to the name (ie: of the Monkey) if one exists // These are found in ItemRandomProperties.dbc, not ItemRandomSuffix.dbc // even though the DBC names seem misleading const ItemRandomPropertiesEntry* itemRandProp = sItemRandomPropertiesStore.LookupEntry(propRefID); if (itemRandProp) { char* temp = itemRandProp->nameSuffix; // dbc local name if (temp) { // Append the suffix (ie: of the Monkey) to the name using localization // or default enUS if localization is invalid name += ' '; name += temp[locdbc_idx >= 0 ? locdbc_idx : LOCALE_enUS]; } } } // Perform the search (with or without suffix) if (!Utf8FitTo(name, wsearchedname)) continue; } // Add the item if no search term or if entered search term was found if (count < 50 && totalcount >= listfrom) { ++count; Aentry->BuildAuctionInfo(data); } ++totalcount; } }
void WorldSession::SendUpdateTrade() { Item *item = NULL; if( !_player || !_player->pTrader ) return; // reset trade status if (_player->acceptTrade) { _player->acceptTrade = false; SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); } if (_player->pTrader->acceptTrade) { _player->pTrader->acceptTrade = false; _player->pTrader->GetSession()->SendTradeStatus(TRADE_STATUS_BACK_TO_TRADE); } WorldPacket data(SMSG_TRADE_STATUS_EXTENDED, (100)); // guess size data << (uint8 ) 1; // can be different (only seen 0 and 1) data << (uint32) 0; // added in 2.4.0, this value must be equal to value from TRADE_STATUS_OPEN_WINDOW status packet (different value for different players to block multiple trades?) data << (uint32) TRADE_SLOT_COUNT; // trade slots count/number?, = next field in most cases data << (uint32) TRADE_SLOT_COUNT; // trade slots count/number?, = prev field in most cases data << (uint32) _player->pTrader->tradeGold; // trader gold data << (uint32) 0; // spell casted on lowest slot item for (uint8 i = 0; i < TRADE_SLOT_COUNT; ++i) { item = (_player->pTrader->tradeItems[i] != NULL_SLOT ? _player->pTrader->GetItemByPos( _player->pTrader->tradeItems[i] ) : NULL); data << (uint8) i; // trade slot number, if not specified, then end of packet if(item) { data << (uint32) item->GetProto()->ItemId; // entry // display id data << (uint32) item->GetProto()->DisplayInfoID; // stack count data << (uint32) item->GetUInt32Value(ITEM_FIELD_STACK_COUNT); data << (uint32) 0; // probably gift=1, created_by=0? // gift creator data << (uint64) item->GetUInt64Value(ITEM_FIELD_GIFTCREATOR); data << (uint32) item->GetEnchantmentId(PERM_ENCHANTMENT_SLOT); for (uint8 j = 0; j < 3; ++j) data << (uint32) 0; // enchantment id (permanent/gems?) // creator data << (uint64) item->GetUInt64Value(ITEM_FIELD_CREATOR); data << (uint32) item->GetSpellCharges(); // charges data << (uint32) item->GetItemSuffixFactor(); // SuffixFactor // random properties id data << (uint32) item->GetItemRandomPropertyId(); data << (uint32) item->GetProto()->LockID; // lock id // max durability data << (uint32) item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY); // durability data << (uint32) item->GetUInt32Value(ITEM_FIELD_DURABILITY); } else { for (uint8 j = 0; j < 18; j++) data << uint32(0); } } SendPacket(&data); }
//called when player lists his received mails void WorldSession::HandleGetMailList(WorldPacket & recv_data) { uint64 mailbox; recv_data >> mailbox; if (!GetPlayer()->GetGameObjectIfCanInteractWith(mailbox, GAMEOBJECT_TYPE_MAILBOX)) return; Player* pl = _player; //load players mails, and mailed items if (!pl->m_mailsLoaded) pl ->_LoadMail(); // client can't work with packets > max int16 value const uint32 maxPacketSize = 32767; 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 = pl->GetMailBegin(); itr != pl->GetMailEnd(); ++itr) { // packet send mail count as uint8, prevent overflow if (mailsCount >= 254) { realCount += 1; continue; } // skip deleted or not delivered (deliver delay not expired) mails if ((*itr)->state == MAIL_STATE_DELETED || cur_time < (*itr)->deliver_time) continue; uint8 item_count = (*itr)->items.size(); // max count is MAX_MAIL_ITEMS (12) 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+4+4+7*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 << uint64(MAKE_NEW_GUID((*itr)->sender, 0, HIGHGUID_PLAYER)); break; case MAIL_CREATURE: case MAIL_GAMEOBJECT: case MAIL_AUCTION: data << uint32((*itr)->sender); // creature/gameobject entry, auction id break; case MAIL_ITEM: // item entry (?) sender = "Unknown", NYI data << uint32(0); // item entry break; } data << uint32((*itr)->COD); // COD data << uint32(0); // probably changed in 3.3.3 data << uint32((*itr)->stationery); // stationery (Stationery.dbc) data << uint32((*itr)->money); // Gold data << uint32((*itr)->checked); // flags data << 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 = pl->GetMItem((*itr)->items[i].item_guid); // item index (0-6?) data << uint8(i); // item guid low? data << uint32((item ? item->GetGUIDLow() : 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 += 1; mailsCount += 1; } 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); // recalculate m_nextMailDelivereTime and unReadMails _player->UpdateNextMailTimeAndUnreads(); }
void WorldSession::HandleVoidStorageTransfer(WorldPackets::VoidStorage::VoidStorageTransfer& voidStorageTransfer) { if (voidStorageTransfer.DepositsCount > VOID_STORAGE_MAX_DEPOSIT) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (%s, name: %s) wants to deposit more than 9 items (%u).", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), voidStorageTransfer.DepositsCount); return; } if (voidStorageTransfer.WithdrawalsCount > VOID_STORAGE_MAX_WITHDRAW) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (%s, name: %s) wants to withdraw more than 9 items (%u).", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), voidStorageTransfer.WithdrawalsCount); return; } Creature* unit = _player->GetNPCIfCanInteractWith(voidStorageTransfer.Npc, UNIT_NPC_FLAG_VAULTKEEPER); if (!unit) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - %s not found or player can't interact with it.", voidStorageTransfer.Npc.ToString().c_str()); return; } if (!_player->IsVoidStorageUnlocked()) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - Player (%s, name: %s) queried void storage without unlocking it.", _player->GetGUID().ToString().c_str(), _player->GetName().c_str()); return; } if (voidStorageTransfer.DepositsCount > _player->GetNumOfVoidStorageFreeSlots()) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL); return; } uint32 freeBagSlots = 0; if (voidStorageTransfer.WithdrawalsCount) { // make this a Player function for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) if (Bag* bag = _player->GetBagByPos(i)) freeBagSlots += bag->GetFreeSlots(); for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) if (!_player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) ++freeBagSlots; } if (voidStorageTransfer.WithdrawalsCount > freeBagSlots) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL); return; } if (!_player->HasEnoughMoney(uint64(voidStorageTransfer.DepositsCount * VOID_STORAGE_STORE_ITEM_COST))) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NOT_ENOUGH_MONEY); return; } std::pair<VoidStorageItem, uint8> depositItems[VOID_STORAGE_MAX_DEPOSIT]; uint8 depositCount = 0; for (uint32 i = 0; i < voidStorageTransfer.DepositsCount; ++i) { Item* item = _player->GetItemByGuid(voidStorageTransfer.Deposits[i]); if (!item) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - %s %s wants to deposit an invalid item (%s).", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), voidStorageTransfer.Deposits[i].ToString().c_str()); continue; } // TODO: Save these fields to database - for now disallow storing these items to prevent data loss if (item->GetUInt32Value(ITEM_FIELD_MODIFIERS_MASK) || !item->GetDynamicValues(ITEM_DYNAMIC_FIELD_BONUSLIST_IDS).empty()) continue; VoidStorageItem itemVS(sObjectMgr->GenerateVoidStorageItemId(), item->GetEntry(), item->GetGuidValue(ITEM_FIELD_CREATOR), item->GetItemRandomPropertyId(), item->GetItemSuffixFactor()); uint8 slot = _player->AddVoidStorageItem(itemVS); depositItems[depositCount++] = std::make_pair(itemVS, slot); _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); } int64 cost = depositCount * VOID_STORAGE_STORE_ITEM_COST; _player->ModifyMoney(-cost); VoidStorageItem withdrawItems[VOID_STORAGE_MAX_WITHDRAW]; uint8 withdrawCount = 0; for (uint32 i = 0; i < voidStorageTransfer.WithdrawalsCount; ++i) { uint8 slot = 0; VoidStorageItem* itemVS = _player->GetVoidStorageItem(voidStorageTransfer.Withdrawals[i].GetCounter(), slot); if (!itemVS) { TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - %s %s tried to withdraw an invalid item (id: %s)", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), voidStorageTransfer.Withdrawals[i].ToString().c_str()); continue; } ItemPosCountVec dest; InventoryResult msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemVS->ItemEntry, 1); if (msg != EQUIP_ERR_OK) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL); TC_LOG_DEBUG("network", "WORLD: HandleVoidStorageTransfer - %s %s couldn't withdraw item id %s because inventory was full.", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), voidStorageTransfer.Withdrawals[i].ToString().c_str()); return; } Item* item = _player->StoreNewItem(dest, itemVS->ItemEntry, true, itemVS->ItemRandomPropertyId); item->SetUInt32Value(ITEM_FIELD_PROPERTY_SEED, itemVS->ItemSuffixFactor); item->SetGuidValue(ITEM_FIELD_CREATOR, itemVS->CreatorGuid); item->SetBinding(true); _player->SendNewItem(item, 1, false, false, false); withdrawItems[withdrawCount++] = *itemVS; _player->DeleteVoidStorageItem(slot); } WorldPackets::VoidStorage::VoidStorageTransferChanges voidStorageTransferChanges; voidStorageTransferChanges.AddedItems.resize(depositCount); voidStorageTransferChanges.RemovedItems.resize(withdrawCount); for (uint8 i = 0; i < depositCount; ++i) { voidStorageTransferChanges.AddedItems[i].Guid = ObjectGuid::Create<HighGuid::Item>(depositItems[i].first.ItemId); voidStorageTransferChanges.AddedItems[i].Creator = depositItems[i].first.CreatorGuid; voidStorageTransferChanges.AddedItems[i].Slot = depositItems[i].second; voidStorageTransferChanges.AddedItems[i].Item.Initialize(&depositItems[i].first); } for (uint8 i = 0; i < withdrawCount; ++i) voidStorageTransferChanges.RemovedItems[i] = ObjectGuid::Create<HighGuid::Item>(withdrawItems[i].ItemId); SendPacket(voidStorageTransferChanges.Write()); SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NO_ERROR); }