From 2d1aa9eeb4602850d0ad6828df99afc2400855c8 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Fri, 15 Sep 2023 14:17:37 -0300 Subject: [PATCH] fix: reward collect crash (#1602) The crash occurred in very difficult scenarios, when the object's parent had been removed (for example, due to the decay of the boss's original body), which caused the reward container to lose the parent, but still remain in memory. From now on, we will set a new parent (the reward chest and the tile). Fixes #994 Fixes #1147 --- src/game/game.cpp | 18 +++++++++++++++--- src/lua/creature/actions.cpp | 10 +++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/game/game.cpp b/src/game/game.cpp index db498e7d8ef..425693e4a77 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -2695,9 +2695,9 @@ ReturnValue Game::internalCollectLootItems(Player* player, Item* item, ObjectCat ReturnValue Game::collectRewardChestItems(Player* player, uint32_t maxMoveItems /* = 0*/) { // Check if have item on player reward chest RewardChest* rewardChest = player->getRewardChest(); - if (!rewardChest || rewardChest->empty()) { - g_logger().debug("Reward chest is wrong or empty"); - return RETURNVALUE_NOTPOSSIBLE; + if (rewardChest->empty()) { + g_logger().debug("Reward chest is empty"); + return RETURNVALUE_REWARDCHESTISEMPTY; } auto rewardItemsVector = player->getRewardsFromContainer(rewardChest->getContainer()); @@ -9821,6 +9821,18 @@ void Game::playerRewardChestCollect(uint32_t playerId, const Position &pos, uint return; } + // Updates the parent of the reward chest and reward containers to avoid memory usage after cleaning + RewardChest* playerRewardChest = player->getRewardChest(); + if (playerRewardChest->empty()) { + player->sendCancelMessage(RETURNVALUE_REWARDCHESTISEMPTY); + return; + } + + playerRewardChest->setParent(item->getContainer()->getParent()->getTile()); + for (const auto &[mapRewardId, reward] : player->rewardMap) { + reward->setParent(playerRewardChest); + } + std::lock_guard lock(player->quickLootMutex); ReturnValue returnValue = collectRewardChestItems(player, maxMoveItems); diff --git a/src/lua/creature/actions.cpp b/src/lua/creature/actions.cpp index e760d3c66ff..34fa1cba896 100644 --- a/src/lua/creature/actions.cpp +++ b/src/lua/creature/actions.cpp @@ -310,17 +310,17 @@ ReturnValue Actions::internalUseItem(Player* player, const Position &pos, uint8_ // reward chest if (container->getRewardChest() != nullptr && container->getParent()) { - RewardChest* myRewardChest = player->getRewardChest(); - if (myRewardChest->size() == 0) { + RewardChest* playerRewardChest = player->getRewardChest(); + if (playerRewardChest->empty()) { return RETURNVALUE_REWARDCHESTISEMPTY; } - myRewardChest->setParent(container->getParent()->getTile()); + playerRewardChest->setParent(container->getParent()->getTile()); for (const auto &[mapRewardId, reward] : player->rewardMap) { - reward->setParent(myRewardChest); + reward->setParent(playerRewardChest); } - openContainer = myRewardChest; + openContainer = playerRewardChest; } auto rewardId = container->getAttribute(ItemAttribute_t::DATE);