@@ -171,7 +171,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
171
171
{
172
172
Inventory *inv_from = mgr->getInventory (from_inv);
173
173
Inventory *inv_to = mgr->getInventory (to_inv);
174
-
174
+
175
175
if (!inv_from) {
176
176
infostream << " IMoveAction::apply(): FAIL: source inventory not found: "
177
177
<< " from_inv=\" " <<from_inv.dump () << " \" "
@@ -271,7 +271,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
271
271
272
272
int src_can_take_count = 0xffff ;
273
273
int dst_can_put_count = 0xffff ;
274
-
274
+
275
275
/* Query detached inventories */
276
276
277
277
// Move occurs in the same detached inventory
@@ -338,7 +338,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
338
338
}
339
339
340
340
int old_count = count;
341
-
341
+
342
342
/* Modify count according to collected data */
343
343
count = try_take_count;
344
344
if (src_can_take_count != -1 && count > src_can_take_count)
@@ -348,7 +348,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
348
348
/* Limit according to source item count */
349
349
if (count > list_from->getItem (from_i).count )
350
350
count = list_from->getItem (from_i).count ;
351
-
351
+
352
352
/* If no items will be moved, don't go further */
353
353
if (count == 0 )
354
354
{
@@ -379,21 +379,28 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
379
379
list_to, to_i, count, !caused_by_move_somewhere);
380
380
381
381
// If source is infinite, reset it's stack
382
- if (src_can_take_count == -1 ){
383
- // If destination stack is of different type and there are leftover
384
- // items, attempt to put the leftover items to a different place in the
385
- // destination inventory.
386
- // The client-side GUI will try to guess if this happens.
387
- if (from_stack_was.name != to_stack_was.name ){
388
- for (u32 i=0 ; i<list_to->getSize (); i++){
389
- if (list_to->getItem (i).empty ()){
390
- list_to->changeItem (i, to_stack_was);
391
- break ;
382
+ if (src_can_take_count == -1 ) {
383
+ // For the caused_by_move_somewhere == true case we didn't force-put the item,
384
+ // which guarantees there is no leftover, and code below would duplicate the
385
+ // (not replaced) to_stack_was item.
386
+ if (!caused_by_move_somewhere) {
387
+ // If destination stack is of different type and there are leftover
388
+ // items, attempt to put the leftover items to a different place in the
389
+ // destination inventory.
390
+ // The client-side GUI will try to guess if this happens.
391
+ if (from_stack_was.name != to_stack_was.name ) {
Has conversations. Original line has conversations.
392
+ for (u32 i = 0 ; i < list_to->getSize (); i++) {
Has a conversation. Original line has a conversation.
393
+ if (list_to->getItem (i).empty ()) {
394
+ list_to->changeItem (i, to_stack_was);
395
+ break ;
396
+ }
392
397
}
393
398
}
394
399
}
395
- list_from->deleteItem (from_i);
396
- list_from->addItem (from_i, from_stack_was);
400
+ if (move_count > 0 ) {
401
+ list_from->deleteItem (from_i);
402
+ list_from->addItem (from_i, from_stack_was);
403
+ }
397
404
}
398
405
// If destination is infinite, reset it's stack and take count from source
399
406
if (dst_can_put_count == -1 ){
@@ -416,6 +423,13 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
416
423
<< " i=" << to_i
417
424
<< std::endl;
418
425
426
+ // If we are inside the move somewhere loop, we don't need to report
427
+ // anything if nothing happened (perhaps we don't need to report
428
+ // anything for caused_by_move_somewhere == true, but this way its safer)
429
+ if (caused_by_move_somewhere && move_count == 0 ) {
430
+ return ;
431
+ }
432
+
419
433
/*
420
434
Record rollback information
421
435
*/
@@ -454,7 +468,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
454
468
/*
455
469
Report move to endpoints
456
470
*/
457
-
471
+
458
472
/* Detached inventories */
459
473
460
474
// Both endpoints are same detached
@@ -507,7 +521,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
507
521
from_inv.p , from_list, from_i, src_item, player);
508
522
}
509
523
}
510
-
524
+
511
525
mgr->setInventoryModified (from_inv, false );
512
526
if (inv_from != inv_to)
513
527
mgr->setInventoryModified (to_inv, false );
@@ -567,7 +581,7 @@ IDropAction::IDropAction(std::istream &is)
567
581
void IDropAction::apply (InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef)
568
582
{
569
583
Inventory *inv_from = mgr->getInventory (from_inv);
570
-
584
+
571
585
if (!inv_from){
572
586
infostream<<" IDropAction::apply(): FAIL: source inventory not found: "
573
587
<<" from_inv=\" " <<from_inv.dump ()<<" \" " <<std::endl;
@@ -627,7 +641,7 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
627
641
628
642
if (src_can_take_count != -1 && src_can_take_count < take_count)
629
643
take_count = src_can_take_count;
630
-
644
+
631
645
int actually_dropped_count = 0 ;
632
646
633
647
ItemStack src_item = list_from->getItem (from_i);
@@ -644,7 +658,7 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
644
658
infostream<<" Actually dropped no items" <<std::endl;
645
659
return ;
646
660
}
647
-
661
+
648
662
// If source isn't infinite
649
663
if (src_can_take_count != -1 ){
650
664
// Take item from source list
@@ -662,13 +676,13 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
662
676
<<" list=\" " <<from_list<<" \" "
663
677
<<" i=" <<from_i
664
678
<<std::endl;
665
-
679
+
666
680
src_item.count = actually_dropped_count;
667
681
668
682
/*
669
683
Report drop to endpoints
670
684
*/
671
-
685
+
672
686
// Source is detached
673
687
if (from_inv.type == InventoryLocation::DETACHED)
674
688
{
@@ -752,7 +766,7 @@ void ICraftAction::apply(InventoryManager *mgr,
752
766
ServerActiveObject *player, IGameDef *gamedef)
753
767
{
754
768
Inventory *inv_craft = mgr->getInventory (craft_inv);
755
-
769
+
756
770
if (!inv_craft) {
757
771
infostream << " ICraftAction::apply(): FAIL: inventory not found: "
758
772
<< " craft_inv=\" " << craft_inv.dump () << " \" " << std::endl;
@@ -872,7 +886,7 @@ bool getCraftingResult(Inventory *inv, ItemStack& result,
872
886
bool decrementInput, IGameDef *gamedef)
873
887
{
874
888
DSTACK (__FUNCTION_NAME);
875
-
889
+
876
890
result.clear ();
877
891
878
892
// Get the InventoryList in which we will operate