Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/game
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2025-04-27 14:04:27 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2025-04-27 14:04:27 +1000
commit1af9343e61ccf24fe55127d458df614d94f8ba7d (patch)
tree8f7de15ca1692389efc517483c943552661e45fd /source/game
parent962913abde4fce6f0b81c1fcb7d2296b97aeed43 (diff)
add a test callback to bestSlotAvailable to never visit the same slot again when used by itemsFitWhere
fixes a freeze when picking up a large quantity of items under specific conditions
Diffstat (limited to 'source/game')
-rw-r--r--source/game/StarItemBag.cpp17
-rw-r--r--source/game/StarItemBag.hpp1
2 files changed, 15 insertions, 3 deletions
diff --git a/source/game/StarItemBag.cpp b/source/game/StarItemBag.cpp
index 8abdd6f..1f8f74f 100644
--- a/source/game/StarItemBag.cpp
+++ b/source/game/StarItemBag.cpp
@@ -234,17 +234,22 @@ auto ItemBag::itemsFitWhere(ItemConstPtr const& items, uint64_t max) const -> It
return ItemsFitWhereResult();
List<size_t> slots;
+ StableHashSet<size_t> taken;
uint64_t count = std::min(items->count(), max);
while (true) {
if (count == 0)
break;
- size_t slot = bestSlotAvailable(items, false);
+ size_t slot = bestSlotAvailable(items, false, [&](size_t i) {
+ return !taken.contains(i);
+ });
if (slot == NPos)
break;
- else
+ else {
slots.append(slot);
+ taken.insert(slot);
+ }
uint64_t available = stackTransfer(at(slot), items);
if (available != 0)
@@ -350,9 +355,11 @@ uint64_t ItemBag::stackTransfer(ItemConstPtr const& to, ItemConstPtr const& from
return std::min(to->maxStack() - to->count(), from->count());
}
-size_t ItemBag::bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly) const {
+size_t ItemBag::bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly, std::function<bool(size_t)> test) const {
// First look for any slots that can stack, before empty slots.
for (size_t i = 0; i < m_items.size(); ++i) {
+ if (!test(i))
+ continue;
auto const& storedItem = at(i);
if (storedItem && stackTransfer(storedItem, item) != 0)
return i;
@@ -369,4 +376,8 @@ size_t ItemBag::bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly) con
return NPos;
}
+size_t ItemBag::bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly) const {
+ return bestSlotAvailable(item, stacksOnly, [](size_t) { return true; });
+}
+
}
diff --git a/source/game/StarItemBag.hpp b/source/game/StarItemBag.hpp
index 7b0246d..7480d7c 100644
--- a/source/game/StarItemBag.hpp
+++ b/source/game/StarItemBag.hpp
@@ -109,6 +109,7 @@ private:
// Returns the slot that contains the item already and has the *highest*
// stack count but not full, or an empty slot, or NPos for no room.
+ size_t bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly, std::function<bool(size_t)> test) const;
size_t bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly) const;
List<ItemPtr> m_items;