Skip to content

Commit 051e4c2

Browse files
authoredFeb 21, 2021
Fix wrong reported item counts for inventory actions using Shift-Move (#10930)
1 parent c12e9cd commit 051e4c2

File tree

2 files changed

+43
-6
lines changed

2 files changed

+43
-6
lines changed
 

Diff for: ‎games/devtest/mods/chest/init.lua

+14-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ minetest.register_node("chest:chest", {
2323
local inv = meta:get_inventory()
2424
return inv:is_empty("main")
2525
end,
26+
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
27+
minetest.chat_send_player(player:get_player_name(), "Allow put: " .. stack:to_string())
28+
return stack:get_count()
29+
end,
30+
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
31+
minetest.chat_send_player(player:get_player_name(), "Allow take: " .. stack:to_string())
32+
return stack:get_count()
33+
end,
34+
on_metadata_inventory_put = function(pos, listname, index, stack, player)
35+
minetest.chat_send_player(player:get_player_name(), "On put: " .. stack:to_string())
36+
end,
37+
on_metadata_inventory_take = function(pos, listname, index, stack, player)
38+
minetest.chat_send_player(player:get_player_name(), "On take: " .. stack:to_string())
39+
end,
2640
})
27-
28-

Diff for: ‎src/inventorymanager.cpp

+29-4
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
301301
if (!list_to->getItem(dest_i).empty()) {
302302
to_i = dest_i;
303303
apply(mgr, player, gamedef);
304+
assert(move_count <= count);
304305
count -= move_count;
305306
}
306307
}
@@ -352,10 +353,12 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
352353
bool allow_swap = !list_to->itemFits(to_i, src_item, &restitem)
353354
&& restitem.count == src_item.count
354355
&& !caused_by_move_somewhere;
356+
move_count = src_item.count - restitem.count;
355357

356358
// Shift-click: Cannot fill this stack, proceed with next slot
357-
if (caused_by_move_somewhere && restitem.count == src_item.count)
359+
if (caused_by_move_somewhere && move_count == 0) {
358360
return;
361+
}
359362

360363
if (allow_swap) {
361364
// Swap will affect the entire stack if it can performed.
@@ -384,9 +387,16 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
384387
src_can_take_count = dst_can_put_count = 0;
385388
} else {
386389
// Take from one inventory, put into another
390+
int src_item_count = src_item.count;
391+
if (caused_by_move_somewhere)
392+
// When moving somewhere: temporarily use the actual movable stack
393+
// size to ensure correct callback execution.
394+
src_item.count = move_count;
387395
dst_can_put_count = allowPut(src_item, player);
388396
src_can_take_count = allowTake(src_item, player);
389-
397+
if (caused_by_move_somewhere)
398+
// Reset source item count
399+
src_item.count = src_item_count;
390400
bool swap_expected = allow_swap;
391401
allow_swap = allow_swap
392402
&& (src_can_take_count == -1 || src_can_take_count >= src_item.count)
@@ -416,12 +426,17 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
416426
count = src_can_take_count;
417427
if (dst_can_put_count != -1 && count > dst_can_put_count)
418428
count = dst_can_put_count;
429+
419430
/* Limit according to source item count */
420431
if (count > list_from->getItem(from_i).count)
421432
count = list_from->getItem(from_i).count;
422433

423434
/* If no items will be moved, don't go further */
424435
if (count == 0) {
436+
if (caused_by_move_somewhere)
437+
// Set move count to zero, as no items have been moved
438+
move_count = 0;
439+
425440
// Undo client prediction. See 'clientApply'
426441
if (from_inv.type == InventoryLocation::PLAYER)
427442
list_from->setModified();
@@ -438,6 +453,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
438453
<<" list=\""<<to_list<<"\""
439454
<<" i="<<to_i
440455
<<std::endl;
456+
441457
return;
442458
}
443459

@@ -455,6 +471,8 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
455471
bool did_swap = false;
456472
move_count = list_from->moveItem(from_i,
457473
list_to, to_i, count, allow_swap, &did_swap);
474+
if (caused_by_move_somewhere)
475+
count = old_count;
458476
assert(allow_swap == did_swap);
459477

460478
// If source is infinite, reset it's stack
@@ -503,8 +521,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
503521
<< std::endl;
504522

505523
// If we are inside the move somewhere loop, we don't need to report
506-
// anything if nothing happened (perhaps we don't need to report
507-
// anything for caused_by_move_somewhere == true, but this way its safer)
524+
// anything if nothing happened
508525
if (caused_by_move_somewhere && move_count == 0)
509526
return;
510527

@@ -558,7 +575,15 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
558575
}
559576
mgr->setInventoryModified(from_inv);
560577
} else {
578+
int src_item_count = src_item.count;
579+
if (caused_by_move_somewhere)
580+
// When moving somewhere: temporarily use the actual movable stack
581+
// size to ensure correct callback execution.
582+
src_item.count = move_count;
561583
onPutAndOnTake(src_item, player);
584+
if (caused_by_move_somewhere)
585+
// Reset source item count
586+
src_item.count = src_item_count;
562587
if (did_swap) {
563588
// Item is now placed in source list
564589
src_item = list_from->getItem(from_i);

0 commit comments

Comments
 (0)
Please sign in to comment.