sa->player_inventory_OnPut(*this, src_item, player);
else
assert(false);
-
+
if (from_inv.type == InventoryLocation::DETACHED)
sa->detached_inventory_OnTake(*this, src_item, player);
else if (from_inv.type == InventoryLocation::NODEMETA)
}
if (!list_to) {
infostream << "IMoveAction::apply(): FAIL: destination list not found: "
- << "to_inv=\""<<to_inv.dump() << "\""
+ << "to_inv=\"" << to_inv.dump() << "\""
<< ", to_list=\"" << to_list << "\"" << std::endl;
return;
}
if (!list_to->getItem(dest_i).empty()) {
to_i = dest_i;
apply(mgr, player, gamedef);
+ assert(move_count <= count);
count -= move_count;
}
}
return;
}
- if ((u16)to_i > list_to->getSize()) {
+ if (from_i < 0 || list_from->getSize() <= (u32) from_i) {
+ infostream << "IMoveAction::apply(): FAIL: source index out of bounds: "
+ << "size of from_list=\"" << list_from->getSize() << "\""
+ << ", from_index=\"" << from_i << "\"" << std::endl;
+ return;
+ }
+
+ if (to_i < 0 || list_to->getSize() <= (u32) to_i) {
infostream << "IMoveAction::apply(): FAIL: destination index out of bounds: "
- << "to_i=" << to_i
- << ", size=" << list_to->getSize() << std::endl;
+ << "size of to_list=\"" << list_to->getSize() << "\""
+ << ", to_index=\"" << to_i << "\"" << std::endl;
return;
}
+
/*
Do not handle rollback if both inventories are that of the same player
*/
*/
ItemStack src_item = list_from->getItem(from_i);
- if (count > 0)
+ if (count > 0 && count < src_item.count)
src_item.count = count;
if (src_item.empty())
return;
bool allow_swap = !list_to->itemFits(to_i, src_item, &restitem)
&& restitem.count == src_item.count
&& !caused_by_move_somewhere;
+ move_count = src_item.count - restitem.count;
// Shift-click: Cannot fill this stack, proceed with next slot
- if (caused_by_move_somewhere && restitem.count == src_item.count)
+ if (caused_by_move_somewhere && move_count == 0) {
return;
+ }
if (allow_swap) {
// Swap will affect the entire stack if it can performed.
src_can_take_count = dst_can_put_count = 0;
} else {
// Take from one inventory, put into another
+ int src_item_count = src_item.count;
+ if (caused_by_move_somewhere)
+ // When moving somewhere: temporarily use the actual movable stack
+ // size to ensure correct callback execution.
+ src_item.count = move_count;
dst_can_put_count = allowPut(src_item, player);
src_can_take_count = allowTake(src_item, player);
-
+ if (caused_by_move_somewhere)
+ // Reset source item count
+ src_item.count = src_item_count;
bool swap_expected = allow_swap;
allow_swap = allow_swap
&& (src_can_take_count == -1 || src_can_take_count >= src_item.count)
count = src_can_take_count;
if (dst_can_put_count != -1 && count > dst_can_put_count)
count = dst_can_put_count;
+
/* Limit according to source item count */
if (count > list_from->getItem(from_i).count)
count = list_from->getItem(from_i).count;
/* If no items will be moved, don't go further */
if (count == 0) {
+ if (caused_by_move_somewhere)
+ // Set move count to zero, as no items have been moved
+ move_count = 0;
+
// Undo client prediction. See 'clientApply'
if (from_inv.type == InventoryLocation::PLAYER)
list_from->setModified();
<<" list=\""<<to_list<<"\""
<<" i="<<to_i
<<std::endl;
+
return;
}
bool did_swap = false;
move_count = list_from->moveItem(from_i,
list_to, to_i, count, allow_swap, &did_swap);
+ if (caused_by_move_somewhere)
+ count = old_count;
assert(allow_swap == did_swap);
// If source is infinite, reset it's stack
<< std::endl;
// If we are inside the move somewhere loop, we don't need to report
- // anything if nothing happened (perhaps we don't need to report
- // anything for caused_by_move_somewhere == true, but this way its safer)
+ // anything if nothing happened
if (caused_by_move_somewhere && move_count == 0)
return;
}
mgr->setInventoryModified(from_inv);
} else {
+ int src_item_count = src_item.count;
+ if (caused_by_move_somewhere)
+ // When moving somewhere: temporarily use the actual movable stack
+ // size to ensure correct callback execution.
+ src_item.count = move_count;
onPutAndOnTake(src_item, player);
+ if (caused_by_move_somewhere)
+ // Reset source item count
+ src_item.count = src_item_count;
if (did_swap) {
// Item is now placed in source list
src_item = list_from->getItem(from_i);
do {
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;
if (!clist)
return false;
- // Mangle crafting grid to an another format
+ // Mangle crafting grid to another format
CraftInput ci;
ci.method = CRAFT_METHOD_NORMAL;
ci.width = clist->getWidth() ? clist->getWidth() : 3;