From 0761e775a2704fa267288b395d5b00c4c37b1061 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Wed, 30 Aug 2023 01:55:15 -0300 Subject: [PATCH] fix: store item indexes --- src/creatures/players/player.cpp | 2 +- src/game/game.cpp | 13 ++++- src/items/containers/container.cpp | 31 +++++++++++- src/items/containers/container.hpp | 15 ++++++ .../creatures/player/player_functions.cpp | 2 +- src/server/network/protocol/protocolgame.cpp | 49 ++++++++++--------- 6 files changed, 83 insertions(+), 29 deletions(-) diff --git a/src/creatures/players/player.cpp b/src/creatures/players/player.cpp index ba62b71e00f..11347c85ad1 100644 --- a/src/creatures/players/player.cpp +++ b/src/creatures/players/player.cpp @@ -1935,7 +1935,7 @@ void Player::onCloseContainer(const Container* container) { } void Player::onSendContainer(const Container* container) { - if (!client) { + if (!client || !container) { return; } diff --git a/src/game/game.cpp b/src/game/game.cpp index da9aec2d660..13512fe43bd 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -612,7 +612,12 @@ Thing* Game::internalGetThing(Player* player, const Position &pos, int32_t index } uint8_t slot = pos.z; - return parentContainer->getItemByIndex(player->getContainerIndex(fromCid) + slot); + auto containerIndex = player->getContainerIndex(fromCid) + slot; + if (parentContainer->isStoreInboxFiltered()) { + return parentContainer->getFilteredItemByIndex(containerIndex); + } + + return parentContainer->getItemByIndex(containerIndex); } else if (pos.y == 0x20 || pos.y == 0x21) { // '0x20' -> From depot. // '0x21' -> From inbox. @@ -1853,7 +1858,7 @@ ReturnValue Game::internalMoveItem(Cylinder* fromCylinder, Cylinder* toCylinder, return retMaxCount; } - // looting analyser from this point forward + // Actor related actions if (fromCylinder && actor && toCylinder) { if (!fromCylinder->getContainer() || !actor->getPlayer() || !toCylinder->getContainer()) { return ret; @@ -1870,9 +1875,13 @@ ReturnValue Game::internalMoveItem(Cylinder* fromCylinder, Cylinder* toCylinder, return ret; } + // Looting analyser if (it.isCorpse && toCylinder->getContainer()->getTopParent() == player && item->getIsLootTrackeable()) { player->sendLootStats(item, static_cast(item->getItemCount())); } + + player->onSendContainer(toCylinder->getContainer()); + player->onSendContainer(fromCylinder->getContainer()); } } diff --git a/src/items/containers/container.cpp b/src/items/containers/container.cpp index 723760ac781..7e925ca93ef 100644 --- a/src/items/containers/container.cpp +++ b/src/items/containers/container.cpp @@ -17,7 +17,7 @@ Container::Container(uint16_t type) : Container(type, items[type].maxItems) { m_maxItems = static_cast(g_configManager().getNumber(MAX_CONTAINER_ITEM)); - if (getID() == ITEM_GOLD_POUCH || getID() == ITEM_STORE_INBOX) { + if (getID() == ITEM_GOLD_POUCH || isStoreInbox()) { pagination = true; m_maxItems = 2000; maxSize = 32; @@ -232,10 +232,39 @@ std::ostringstream &Container::getContentDescription(std::ostringstream &os, boo return os; } +std::deque Container::getStoreInboxFilteredItems() const { + const auto enumName = getAttribute(ItemAttribute_t::STORE_INBOX_CATEGORY); + ItemDeque storeInboxFilteredList; + if (isStoreInboxFiltered()) { + for (Item* item : getItemList()) { + auto attribute = item->getCustomAttribute("unWrapId"); + uint16_t unWrapId = attribute ? static_cast(attribute->getInteger()) : 0; + if (unWrapId != 0) { + const auto &itemType = Item::items.getItemType(unWrapId); + if (itemType.m_primaryType == asLowerCaseString(enumName)) { + storeInboxFilteredList.push_back(item); + } + } + } + } + + return storeInboxFilteredList; +} + +Item* Container::getFilteredItemByIndex(size_t index) const { + const auto &filteredItems = getStoreInboxFilteredItems(); + if (index >= filteredItems.size()) { + return nullptr; + } + + return filteredItems[index]; +} + Item* Container::getItemByIndex(size_t index) const { if (index >= size()) { return nullptr; } + return itemlist[index]; } diff --git a/src/items/containers/container.hpp b/src/items/containers/container.hpp index 3ea2a2ac1a2..634dbc6268e 100644 --- a/src/items/containers/container.hpp +++ b/src/items/containers/container.hpp @@ -115,6 +115,8 @@ class Container : public Item, public Cylinder { bool hasParent() const; void addItem(Item* item); StashContainerList getStowableItems() const; + std::deque getStoreInboxFilteredItems() const; + Item* getFilteredItemByIndex(size_t index) const; Item* getItemByIndex(size_t index) const; bool isHoldingItem(const Item* item) const; bool isHoldingItemWithId(const uint16_t id) const; @@ -131,6 +133,19 @@ class Container : public Item, public Cylinder { return pagination; } + bool isStoreInbox() const { + return getID() == ITEM_STORE_INBOX; + } + + bool isStoreInboxFiltered() const { + auto attribute = getAttribute(ItemAttribute_t::STORE_INBOX_CATEGORY); + if (isStoreInbox() && !attribute.empty() && attribute != "All") { + return true; + } + + return false; + } + // cylinder implementations virtual ReturnValue queryAdd(int32_t index, const Thing &thing, uint32_t count, uint32_t flags, Creature* actor = nullptr) const override; ReturnValue queryMaxCount(int32_t index, const Thing &thing, uint32_t count, uint32_t &maxQueryCount, uint32_t flags) const override final; diff --git a/src/lua/functions/creatures/player/player_functions.cpp b/src/lua/functions/creatures/player/player_functions.cpp index ec76c89e735..102fb0a93c3 100644 --- a/src/lua/functions/creatures/player/player_functions.cpp +++ b/src/lua/functions/creatures/player/player_functions.cpp @@ -1902,7 +1902,7 @@ int PlayerFunctions::luaPlayerSendUpdateContainer(lua_State* L) { return 1; } - Container* container = getUserdata(L, 2); + const auto container = getUserdata(L, 2); if (!container) { reportErrorFunc("Container is nullptr"); return 1; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index dd386e13a0b..5693868ea00 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -218,17 +218,16 @@ namespace { * @param msg The network message to send the category to. */ template - void sendContainerCategory(NetworkMessage &msg, uint8_t categoryType = 0) { + void sendContainerCategory(NetworkMessage &msg, std::deque categories = {}, uint8_t categoryType = 0) { msg.addByte(categoryType); - - const uint8_t enumCount = magic_enum::enum_count(); - msg.addByte(enumCount - 1); - - for (auto value : magic_enum::enum_values()) { + g_logger().debug("Sendding category type '{}', categories total size '{}'", categoryType, categories.size()); + msg.addByte(categories.size()); + for (auto value : categories) { if (value == T::All) { continue; } + g_logger().debug("Sendding category number '{}', category name '{}'", static_cast(value), magic_enum::enum_name(value).data()); msg.addByte(static_cast(value)); msg.addString(magic_enum::enum_name(value).data()); } @@ -4254,21 +4253,7 @@ void ProtocolGame::sendContainer(uint8_t cid, const Container* container, bool h msg.addString(container->getName()); } - const auto &enumName = container->getAttribute(ItemAttribute_t::STORE_INBOX_CATEGORY); - uint32_t totalCountToSend = 0; - std::vector itemsStoreInboxToSend; - if (container->getID() == ITEM_STORE_INBOX && enumName != "All") { - for (Item* item : container->getItemList()) { - uint16_t unWrapId = item->getCustomAttribute("unWrapId") ? static_cast(item->getCustomAttribute("unWrapId")->getInteger()) : 0; - if (unWrapId != 0) { - const auto &itemType = Item::items.getItemType(unWrapId); - if (itemType.m_primaryType == asLowerCaseString(enumName)) { - itemsStoreInboxToSend.push_back(item); - totalCountToSend++; - } - } - } - } + const auto itemsStoreInboxToSend = container->getStoreInboxFilteredItems(); msg.addByte(container->capacity()); @@ -4283,8 +4268,8 @@ void ProtocolGame::sendContainer(uint8_t cid, const Container* container, bool h msg.addByte(container->hasPagination() ? 0x01 : 0x00); // Pagination uint32_t containerSize = container->size(); - if (totalCountToSend != 0) { - containerSize = totalCountToSend; + if (!itemsStoreInboxToSend.empty()) { + containerSize = itemsStoreInboxToSend.size(); } msg.add(containerSize); msg.add(firstIndex); @@ -4316,9 +4301,25 @@ void ProtocolGame::sendContainer(uint8_t cid, const Container* container, bool h if (!oldProtocol) { if (container->getID() == ITEM_STORE_INBOX) { + std::deque validCategories; + for (const auto item : container->getItemList()) { + auto attribute = item->getCustomAttribute("unWrapId"); + uint16_t unWrapId = attribute ? static_cast(attribute->getInteger()) : 0; + if (unWrapId != 0) { + const auto &itemType = Item::items.getItemType(unWrapId); + auto category = magic_enum::enum_cast(toPascalCase(itemType.m_primaryType)); + g_logger().debug("Store unwrap item '{}', primary type {}", unWrapId, toPascalCase(itemType.m_primaryType)); + if (category.has_value()) { + g_logger().debug("Adding valid category {}", static_cast(category.value())); + validCategories.push_back(category.value()); + } + } + } + + const auto enumName = container->getAttribute(ItemAttribute_t::STORE_INBOX_CATEGORY); auto category = magic_enum::enum_cast(enumName); if (category.has_value()) { - sendContainerCategory(msg, static_cast(category.value())); + sendContainerCategory(msg, validCategories, static_cast(category.value())); } else { sendContainerCategory(msg); }