From 6f45409f50a02a59a534255b40a29c85c86f41bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Paulo?= Date: Wed, 18 Dec 2024 13:56:04 -0300 Subject: [PATCH] * Optimized the `onPlayerSellAllLoot` code to prevent prolonged freezes. --- markdowns/CHANGELOG.md | 1 + src/creatures/npcs/npc.cpp | 50 +++++++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/markdowns/CHANGELOG.md b/markdowns/CHANGELOG.md index 22c7148b..1e9616ff 100644 --- a/markdowns/CHANGELOG.md +++ b/markdowns/CHANGELOG.md @@ -8,6 +8,7 @@ - Protocol 14.05 support. ([Tryller](https://github.com/jprzimba)) - New protocol 14.05 assets. ([Tryller](https://github.com/jprzimba)) - Fix gotoHouse talkaction. ([Tryller](https://github.com/jprzimba)) +- Optimized the `onPlayerSellAllLoot` code to prevent prolonged freezes. ([Tryller](https://github.com/jprzimba)) ## Added files diff --git a/src/creatures/npcs/npc.cpp b/src/creatures/npcs/npc.cpp index 710f0d57..2d848ada 100644 --- a/src/creatures/npcs/npc.cpp +++ b/src/creatures/npcs/npc.cpp @@ -443,48 +443,60 @@ void Npc::onPlayerSellAllLoot(uint32_t playerId, uint16_t itemId, bool ignore, u if (!player) { return; } + if (itemId == ITEM_GOLD_POUCH) { const auto &container = player->getLootPouch(); if (!container) { return; } - bool hasMore = false; + uint64_t toSellCount = 0; phmap::flat_hash_map toSell; - for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { - if (toSellCount >= 500) { - hasMore = true; - break; - } - const auto &item = *it; + ContainerIterator it = container->iterator(); + + while (it.hasNext()) { + auto item = *it; if (!item) { continue; } + toSell[item->getID()] += item->getItemAmount(); if (item->isStackable()) { toSellCount++; } else { toSellCount += item->getItemAmount(); } + + if (toSellCount >= 100) { + break; + } + + it.advance(); } - for (const auto &[m_itemId, amount] : toSell) { - onPlayerSellItem(player, m_itemId, 0, amount, ignore, totalPrice, container); - } - auto ss = std::stringstream(); - if (totalPrice == 0) { + + if (toSell.empty()) { + std::stringstream ss; ss << "You have no items in your loot pouch."; - player->sendTextMessage(MESSAGE_TRANSACTION, ss.str()); + player->sendTextMessage(MESSAGE_FAILURE, ss.str()); return; } - if (hasMore) { - g_dispatcher().scheduleEvent( - SCHEDULER_MINTICKS, [this, playerId = player->getID(), itemId, ignore, totalPrice] { onPlayerSellAllLoot(playerId, itemId, ignore, totalPrice); }, __FUNCTION__ - ); - return; + + for (auto &[itemId, amount] : toSell) { + onPlayerSellItem(player, itemId, 0, amount, ignore, totalPrice, container); } + + const auto &task = player->createPlayerTask( + 100, [this, playerId, itemId, ignore, totalPrice]() { + onPlayerSellAllLoot(playerId, itemId, ignore, totalPrice); + }, + __FUNCTION__ + ); + player->setNextActionPushTask(task); + + auto ss = std::stringstream(); ss << "You sold all of the items from your loot pouch for "; ss << totalPrice << " gold."; - player->sendTextMessage(MESSAGE_TRANSACTION, ss.str()); + player->sendTextMessage(MESSAGE_LOOK, ss.str()); player->openPlayerContainers(); } }