From 9f658d952912c4abefe199d1f073cea825b49201 Mon Sep 17 00:00:00 2001 From: Eduardo Dantas Date: Mon, 30 Sep 2024 16:01:02 -0300 Subject: [PATCH] fix: overload when setting item decay when player logs in --- src/io/functions/iologindata_load_player.cpp | 24 ++++++++++++-------- src/items/containers/container.cpp | 7 ------ src/items/containers/container.hpp | 1 - src/items/decay/decay.cpp | 15 +++++++++--- src/items/decay/decay.hpp | 6 ++--- src/map/mapcache.cpp | 4 +++- 6 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/io/functions/iologindata_load_player.cpp b/src/io/functions/iologindata_load_player.cpp index 3042f4ce03b..4cf83adaed3 100644 --- a/src/io/functions/iologindata_load_player.cpp +++ b/src/io/functions/iologindata_load_player.cpp @@ -479,25 +479,24 @@ void IOLoginDataLoad::loadPlayerInventoryItems(std::shared_ptr player, D bool oldProtocol = g_configManager().getBoolean(OLD_PROTOCOL, __FUNCTION__) && player->getProtocolVersion() < 1200; Database &db = Database::getInstance(); - std::ostringstream query; - query << "SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_items` WHERE `player_id` = " << player->getGUID() << " ORDER BY `sid` DESC"; + auto query = fmt::format("SELECT pid, sid, itemtype, count, attributes FROM player_items WHERE player_id = {} ORDER BY sid DESC", player->getGUID()); ItemsMap inventoryItems; std::vector>> openContainersList; + std::vector> itemsToStartDecaying; try { - if ((result = db.storeQuery(query.str()))) { + if ((result = db.storeQuery(query))) { loadItems(inventoryItems, result, player); for (ItemsMap::const_reverse_iterator it = inventoryItems.rbegin(), end = inventoryItems.rend(); it != end; ++it) { const std::pair, int32_t> &pair = it->second; - std::shared_ptr item = pair.first; + const std::shared_ptr &item = pair.first; if (!item) { continue; } int32_t pid = pair.second; - if (pid >= CONST_SLOT_FIRST && pid <= CONST_SLOT_LAST) { player->internalAddThing(pid, item); item->startDecaying(); @@ -507,14 +506,15 @@ void IOLoginDataLoad::loadPlayerInventoryItems(std::shared_ptr player, D continue; } - std::shared_ptr container = it2->second.first->getContainer(); + const std::shared_ptr &container = it2->second.first->getContainer(); if (container) { container->internalAddThing(item); - item->startDecaying(); + // Here, the sub-containers do not yet have a parent, since the main backpack has not yet been added to the player, so we need to postpone + itemsToStartDecaying.emplace_back(item); } } - std::shared_ptr itemContainer = item->getContainer(); + const std::shared_ptr &itemContainer = item->getContainer(); if (itemContainer) { if (!oldProtocol) { auto cid = item->getAttribute(ItemAttribute_t::OPENCONTAINER); @@ -538,6 +538,11 @@ void IOLoginDataLoad::loadPlayerInventoryItems(std::shared_ptr player, D } } + // Now that all items and containers have been added and parent chain is established, start decay + for (const auto& item : itemsToStartDecaying) { + item->startDecaying(); + } + if (!oldProtocol) { std::ranges::sort(openContainersList.begin(), openContainersList.end(), [](const std::pair> &left, const std::pair> &right) { return left.first < right.first; @@ -548,8 +553,9 @@ void IOLoginDataLoad::loadPlayerInventoryItems(std::shared_ptr player, D player->onSendContainer(it.second); } } + } catch (const std::exception &e) { - g_logger().error("[IOLoginDataLoad::loadPlayerInventoryItems] - Exceção durante o carregamento do inventário: {}", e.what()); + g_logger().error("[IOLoginDataLoad::loadPlayerInventoryItems] - Exception during inventory loading: {}", e.what()); } } diff --git a/src/items/containers/container.cpp b/src/items/containers/container.cpp index be2e63ae95b..cde207a7348 100644 --- a/src/items/containers/container.cpp +++ b/src/items/containers/container.cpp @@ -895,13 +895,6 @@ void Container::internalAddThing(uint32_t, std::shared_ptr thing) { updateItemWeight(item->getWeight()); } -void Container::startDecaying() { - g_decay().startDecay(getContainer()); - for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) { - g_decay().startDecay(*it); - } -} - void Container::stopDecaying() { g_decay().stopDecay(getContainer()); for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) { diff --git a/src/items/containers/container.hpp b/src/items/containers/container.hpp index 6bfb509b8d3..9fb1f069226 100644 --- a/src/items/containers/container.hpp +++ b/src/items/containers/container.hpp @@ -166,7 +166,6 @@ class Container : public Item, public Cylinder { void internalAddThing(std::shared_ptr thing) override final; void internalAddThing(uint32_t index, std::shared_ptr thing) override final; - void startDecaying() override; void stopDecaying() override; virtual void removeItem(std::shared_ptr thing, bool sendUpdateToClient = false); diff --git a/src/items/decay/decay.cpp b/src/items/decay/decay.cpp index bdf9ed36040..58bd6095340 100644 --- a/src/items/decay/decay.cpp +++ b/src/items/decay/decay.cpp @@ -17,7 +17,7 @@ Decay &Decay::getInstance() { return inject(); } -void Decay::startDecay(std::shared_ptr item) { +void Decay::startDecay(const std::shared_ptr &item) { if (!item) { return; } @@ -32,6 +32,8 @@ void Decay::startDecay(std::shared_ptr item) { return; } + g_logger().trace("Try decay item {}", item->getName()); + const auto duration = item->getAttribute(ItemAttribute_t::DURATION); if (duration <= 0 && item->hasAttribute(ItemAttribute_t::DURATION)) { internalDecayItem(item); @@ -63,7 +65,10 @@ void Decay::startDecay(std::shared_ptr item) { } } -void Decay::stopDecay(std::shared_ptr item) { +void Decay::stopDecay(const std::shared_ptr &item) { + if (!item) { + return; + } if (item->hasAttribute(ItemAttribute_t::DECAYSTATE)) { auto timestamp = item->getAttribute(ItemAttribute_t::DURATION_TIMESTAMP); if (item->hasAttribute(ItemAttribute_t::DURATION_TIMESTAMP)) { @@ -146,7 +151,11 @@ void Decay::checkDecay() { } } -void Decay::internalDecayItem(std::shared_ptr item) { +void Decay::internalDecayItem(const std::shared_ptr &item) { + if (!item) { + return; + } + const ItemType &it = Item::items[item->getID()]; // Remove the item and halt the decay process if a player triggers a bug where the item's decay ID matches its equip or de-equip transformation ID if (it.id == it.transformEquipTo || it.id == it.transformDeEquipTo) { diff --git a/src/items/decay/decay.hpp b/src/items/decay/decay.hpp index e2916f6134f..cce3b8b78d5 100644 --- a/src/items/decay/decay.hpp +++ b/src/items/decay/decay.hpp @@ -20,12 +20,12 @@ class Decay { static Decay &getInstance(); - void startDecay(std::shared_ptr item); - void stopDecay(std::shared_ptr item); + void startDecay(const std::shared_ptr &item); + void stopDecay(const std::shared_ptr &item); private: void checkDecay(); - void internalDecayItem(std::shared_ptr item); + void internalDecayItem(const std::shared_ptr &item); uint32_t eventId { 0 }; // order is important, so we use an std::map diff --git a/src/map/mapcache.cpp b/src/map/mapcache.cpp index 33a069f5ae9..bad1315113c 100644 --- a/src/map/mapcache.cpp +++ b/src/map/mapcache.cpp @@ -93,7 +93,9 @@ std::shared_ptr MapCache::createItem(const std::shared_ptr &Bas item->setItemCount(1); } - item->startDecaying(); + if (item->canDecay()) { + item->startDecaying(); + } item->loadedFromMap = true; item->decayDisabled = Item::items[item->getID()].decayTo != -1;