diff --git a/src/creatures/monsters/spawns/spawn_monster.cpp b/src/creatures/monsters/spawns/spawn_monster.cpp index 153db66dee4..7d7bbc84e34 100644 --- a/src/creatures/monsters/spawns/spawn_monster.cpp +++ b/src/creatures/monsters/spawns/spawn_monster.cpp @@ -327,7 +327,7 @@ void SpawnMonster::scheduleSpawn(uint32_t spawnMonsterId, spawnBlock_t &sb, cons } void SpawnMonster::cleanup() { - for (auto it = spawnedMonsterMap.begin(); it != spawnedMonsterMap.end(); ) { + for (auto it = spawnedMonsterMap.begin(); it != spawnedMonsterMap.end();) { const auto &monster = it->second; if (!monster || monster->isRemoved()) { auto spawnIt = spawnMonsterMap.find(it->first); diff --git a/src/game/game.cpp b/src/game/game.cpp index 4018c1b2f90..c2ae19087ef 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -4123,7 +4123,7 @@ void Game::playerMoveUpContainer(uint32_t playerId, uint8_t cid) { auto it = browseFields.find(tile); if (it == browseFields.end() || it->second.expired()) { - parentContainer = Container::create(tile); + parentContainer = Container::createBrowseField(tile); browseFields[tile] = parentContainer; } else { parentContainer = it->second.lock(); @@ -4688,7 +4688,7 @@ void Game::playerBrowseField(uint32_t playerId, const Position &pos) { auto it = browseFields.find(tile); if (it == browseFields.end() || it->second.expired()) { - container = Container::create(tile); + container = Container::createBrowseField(tile); browseFields[tile] = container; } else { container = it->second.lock(); diff --git a/src/items/containers/container.cpp b/src/items/containers/container.cpp index e19de0da183..70ad1cbabbf 100644 --- a/src/items/containers/container.cpp +++ b/src/items/containers/container.cpp @@ -44,20 +44,36 @@ std::shared_ptr Container::create(uint16_t type, uint16_t size, bool return std::make_shared(type, size, unlocked, pagination); } -std::shared_ptr Container::create(const std::shared_ptr &tile) { - auto container = std::make_shared(ITEM_BROWSEFIELD, 30, false, true); +std::shared_ptr Container::createBrowseField(const std::shared_ptr &tile) { + const auto &newContainer = create(ITEM_BROWSEFIELD, 30, false, true); + if (!newContainer || !tile) { + return nullptr; + } + const TileItemVector* itemVector = tile->getItemList(); if (itemVector) { for (const auto &item : *itemVector) { - if (((item->getContainer() || item->hasProperty(CONST_PROP_MOVABLE)) || (item->isWrapable() && !item->hasProperty(CONST_PROP_MOVABLE) && !item->hasProperty(CONST_PROP_BLOCKPATH))) && !item->hasAttribute(ItemAttribute_t::UNIQUEID)) { - container->itemlist.push_front(item); - item->setParent(container); + if (!item) { + continue; } + + // Checks if the item has an internal container, is movable, or is packable without blocking the path. + bool isItemValid = item->getContainer() || item->hasProperty(CONST_PROP_MOVABLE) || (item->isWrapable() && !item->hasProperty(CONST_PROP_MOVABLE) && !item->hasProperty(CONST_PROP_BLOCKPATH)); + + // If the item has a unique ID or is not valid, skip to the next item. + if (item->hasAttribute(ItemAttribute_t::UNIQUEID) || !isItemValid) { + continue; + } + + // Add the item to the new container and set its parent. + newContainer->itemlist.push_front(item); + item->setParent(newContainer); } } - container->setParent(tile); - return container; + // Set the parent of the new container to be the tile. + newContainer->setParent(tile); + return newContainer; } Container::~Container() { diff --git a/src/items/containers/container.hpp b/src/items/containers/container.hpp index b9840a0b0b5..f7e1b5c42a3 100644 --- a/src/items/containers/container.hpp +++ b/src/items/containers/container.hpp @@ -138,7 +138,21 @@ class Container : public Item, public Cylinder { static std::shared_ptr create(uint16_t type); static std::shared_ptr create(uint16_t type, uint16_t size, bool unlocked = true, bool pagination = false); - static std::shared_ptr create(const std::shared_ptr &type); + + /** + * @brief Creates a container for browse field functionality with items from a specified tile. + * + * This function generates a new container specifically for browse field use, + * populating it with items that meet certain criteria from the provided tile. Items + * that can be included must either have an internal container, be movable, or be + * wrapable without blocking path and without a unique ID. + * + * @param tile A shared pointer to the Tile from which items will be sourced. + * @return std::shared_ptr Returns a shared pointer to the newly created Container if successful; otherwise, returns nullptr. + * + * @note This function will return nullptr if the newContainer could not be created or if the tile pointer is null. + */ + static std::shared_ptr createBrowseField(const std::shared_ptr &type); // non-copyable Container(const Container &) = delete; diff --git a/src/server/network/protocol/protocolgame.cpp b/src/server/network/protocol/protocolgame.cpp index c59f0d89c25..3383a5fc3ca 100644 --- a/src/server/network/protocol/protocolgame.cpp +++ b/src/server/network/protocol/protocolgame.cpp @@ -4615,7 +4615,7 @@ void ProtocolGame::sendUnjustifiedPoints(const uint8_t &dayProgress, const uint8 } void ProtocolGame::sendContainer(uint8_t cid, const std::shared_ptr &container, bool hasParent, uint16_t firstIndex) { - if (!player) { + if (!player || !container) { return; }