void ProtocolGame::sendSaleItemList(const std::list<ShopInfo>& shop)
{
NetworkMessage msg;
msg.addByte(0x7B);
msg.add<uint32_t>(player->getMoney());
std::map<uint16_t, uint32_t> saleMap;
if (shop.size() <= 5) {
// For very small shops it's not worth it to create the complete map
for (const ShopInfo& shopInfo : shop) {
if (shopInfo.sellPrice == 0) {
continue;
}
int8_t subtype = -1;
const ItemType& itemType = Item::items[shopInfo.itemId];
if (itemType.hasSubType() && !itemType.stackable) {
subtype = (shopInfo.subType == 0 ? -1 : shopInfo.subType);
}
uint32_t count = player->getItemTypeCount(shopInfo.itemId, subtype);
if (count > 0) {
saleMap[shopInfo.itemId] = count;
}
}
}
else {
// Large shop, it's better to get a cached map of all item counts and use it
// We need a temporary map since the finished map should only contain items
// available in the shop
std::map<uint32_t, uint32_t> tempSaleMap;
player->getAllItemTypeCount(tempSaleMap);
// We must still check manually for the special items that require subtype matches
// (That is, fluids such as potions etc., actually these items are very few since
// health potions now use their own ID)
for (const ShopInfo& shopInfo : shop) {
if (shopInfo.sellPrice == 0) {
continue;
}
int8_t subtype = -1;
const ItemType& itemType = Item::items[shopInfo.itemId];
if (itemType.hasSubType() && !itemType.stackable) {
subtype = (shopInfo.subType == 0 ? -1 : shopInfo.subType);
}
if (subtype != -1) {
uint32_t count;
if (itemType.isFluidContainer() || itemType.isSplash()) {
count = player->getItemTypeCount(shopInfo.itemId, subtype); // This shop item requires extra checks
}
else {
auto itShopItem = tempSaleMap.find(shopInfo.itemId);
if (itShopItem != tempSaleMap.end())
{
count = itShopItem->second;
}
else
{
count = 0;
}
}
if (count > 0) {
saleMap[shopInfo.itemId] = count;
}
}
else {
std::map<uint32_t, uint32_t>::const_iterator findIt = tempSaleMap.find(shopInfo.itemId);
if (findIt != tempSaleMap.end() && findIt->second > 0) {
saleMap[shopInfo.itemId] = findIt->second;
}
}
}
}
uint8_t itemsToSend = std::min<size_t>(saleMap.size(), std::numeric_limits<uint8_t>::max());
msg.addByte(itemsToSend);
uint8_t i = 0;
for (std::map<uint16_t, uint32_t>::const_iterator it = saleMap.begin(); i < itemsToSend; ++it, ++i) {
msg.addItemId(it->first);
msg.addByte(std::min<uint32_t>(it->second, std::numeric_limits<uint8_t>::max()));
}
writeToOutputBuffer(msg);
}