diff options
Diffstat (limited to 'src/inventorymanager.cpp')
-rw-r--r-- | src/inventorymanager.cpp | 80 |
1 files changed, 78 insertions, 2 deletions
diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp index ecdb56a97..b3dd84b74 100644 --- a/src/inventorymanager.cpp +++ b/src/inventorymanager.cpp @@ -378,6 +378,15 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame // Move action within the same inventory src_can_take_count = allowMove(src_item.count, player); + inv_from = mgr->getInventory(from_inv); + inv_to = mgr->getInventory(to_inv); + if (!inv_from || !inv_to) + return; + list_from = inv_from->getList(from_list); + list_to = inv_to->getList(to_list); + if (!list_from || !list_to) + return; + bool swap_expected = allow_swap; allow_swap = allow_swap && (src_can_take_count == -1 || src_can_take_count >= src_item.count); @@ -385,6 +394,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame int try_put_count = list_to->getItem(to_i).count; swapDirections(); dst_can_put_count = allowMove(try_put_count, player); + allow_swap = allow_swap && (dst_can_put_count == -1 || dst_can_put_count >= try_put_count); swapDirections(); @@ -402,6 +412,16 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame src_item.count = move_count; dst_can_put_count = allowPut(src_item, player); src_can_take_count = allowTake(src_item, player); + + inv_from = mgr->getInventory(from_inv); + inv_to = mgr->getInventory(to_inv); + if (!inv_from || !inv_to) + return; + list_from = inv_from->getList(from_list); + list_to = inv_to->getList(to_list); + if (!list_from || !list_to) + return; + if (caused_by_move_somewhere) // Reset source item count src_item.count = src_item_count; @@ -416,7 +436,27 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame swapDirections(); int src_can_take = allowPut(dst_item, player); + + inv_from = mgr->getInventory(from_inv); + inv_to = mgr->getInventory(to_inv); + if (!inv_from || !inv_to) + return; + list_from = inv_from->getList(from_list); + list_to = inv_to->getList(to_list); + if (!list_from || !list_to) + return; + int dst_can_put = allowTake(dst_item, player); + + inv_from = mgr->getInventory(from_inv); + inv_to = mgr->getInventory(to_inv); + if (!inv_from || !inv_to) + return; + list_from = inv_from->getList(from_list); + list_to = inv_to->getList(to_list); + if (!list_from || !list_to) + return; + allow_swap = allow_swap && (src_can_take == -1 || src_can_take >= dst_item.count) && (dst_can_put == -1 || dst_can_put >= dst_item.count); @@ -465,6 +505,15 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame return; } + inv_from = mgr->getInventory(from_inv); + inv_to = mgr->getInventory(to_inv); + if (!inv_from || !inv_to) + return; + list_from = inv_from->getList(from_list); + list_to = inv_to->getList(to_list); + if (!list_from || !list_to) + return; + src_item = list_from->getItem(from_i); src_item.count = count; ItemStack from_stack_was = list_from->getItem(from_i); @@ -576,11 +625,20 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame onMove(count, player); if (did_swap) { // Item is now placed in source list + + inv_from = mgr->getInventory(from_inv); + if (!inv_from) + return; + list_from = inv_from->getList(from_list); + if (!list_from) + return; + src_item = list_from->getItem(from_i); swapDirections(); onMove(src_item.count, player); swapDirections(); } + mgr->setInventoryModified(from_inv); } else { int src_item_count = src_item.count; @@ -594,6 +652,14 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame src_item.count = src_item_count; if (did_swap) { // Item is now placed in source list + + inv_from = mgr->getInventory(from_inv); + if (!inv_from) + return; + list_from = inv_from->getList(from_list); + if (!list_from) + return; + src_item = list_from->getItem(from_i); swapDirections(); onPutAndOnTake(src_item, player); @@ -721,6 +787,15 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame if (src_can_take_count != -1 && src_can_take_count < take_count) take_count = src_can_take_count; + // Inventory references may be stale + inv_from = mgr->getInventory(from_inv); + if (!inv_from) + return; + + list_from = inv_from->getList(from_list); + if (!list_from) + return; + // Update item due executed callbacks src_item = list_from->getItem(from_i); @@ -935,11 +1010,12 @@ void ICraftAction::apply(InventoryManager *mgr, output_replacement = list_main->addItem(output_replacement); if (output_replacement.empty()) continue; - u16 count = output_replacement.count; + u16 count; do { + count = output_replacement.count; PLAYER_TO_SA(player)->item_OnDrop(output_replacement, player, player->getBasePosition()); - if (count >= output_replacement.count) { + if (count <= output_replacement.count) { errorstream << "Couldn't drop replacement stack " << output_replacement.getItemString() << " because drop loop didn't " "decrease count." << std::endl; |