diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/inventorymanager.cpp | 64 | ||||
-rw-r--r-- | src/inventorymanager.h | 16 |
2 files changed, 47 insertions, 33 deletions
diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp index d23d1529d..bf5a7dd9d 100644 --- a/src/inventorymanager.cpp +++ b/src/inventorymanager.cpp @@ -171,7 +171,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame { Inventory *inv_from = mgr->getInventory(from_inv); Inventory *inv_to = mgr->getInventory(to_inv); - + if (!inv_from) { infostream << "IMoveAction::apply(): FAIL: source inventory not found: " << "from_inv=\""<<from_inv.dump() << "\"" @@ -271,7 +271,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame int src_can_take_count = 0xffff; int dst_can_put_count = 0xffff; - + /* Query detached inventories */ // Move occurs in the same detached inventory @@ -338,7 +338,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame } int old_count = count; - + /* Modify count according to collected data */ count = try_take_count; if(src_can_take_count != -1 && count > src_can_take_count) @@ -348,7 +348,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame /* 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) { @@ -379,21 +379,28 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame list_to, to_i, count, !caused_by_move_somewhere); // If source is infinite, reset it's stack - if(src_can_take_count == -1){ - // If destination stack is of different type and there are leftover - // items, attempt to put the leftover items to a different place in the - // destination inventory. - // The client-side GUI will try to guess if this happens. - if(from_stack_was.name != to_stack_was.name){ - for(u32 i=0; i<list_to->getSize(); i++){ - if(list_to->getItem(i).empty()){ - list_to->changeItem(i, to_stack_was); - break; + if (src_can_take_count == -1) { + // For the caused_by_move_somewhere == true case we didn't force-put the item, + // which guarantees there is no leftover, and code below would duplicate the + // (not replaced) to_stack_was item. + if (!caused_by_move_somewhere) { + // If destination stack is of different type and there are leftover + // items, attempt to put the leftover items to a different place in the + // destination inventory. + // The client-side GUI will try to guess if this happens. + if (from_stack_was.name != to_stack_was.name) { + for (u32 i = 0; i < list_to->getSize(); i++) { + if (list_to->getItem(i).empty()) { + list_to->changeItem(i, to_stack_was); + break; + } } } } - list_from->deleteItem(from_i); - list_from->addItem(from_i, from_stack_was); + if (move_count > 0) { + list_from->deleteItem(from_i); + list_from->addItem(from_i, from_stack_was); + } } // If destination is infinite, reset it's stack and take count from source if(dst_can_put_count == -1){ @@ -416,6 +423,13 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame << " i=" << to_i << 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) + if (caused_by_move_somewhere && move_count == 0) { + return; + } + /* Record rollback information */ @@ -454,7 +468,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame /* Report move to endpoints */ - + /* Detached inventories */ // Both endpoints are same detached @@ -507,7 +521,7 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame from_inv.p, from_list, from_i, src_item, player); } } - + mgr->setInventoryModified(from_inv, false); if(inv_from != inv_to) mgr->setInventoryModified(to_inv, false); @@ -567,7 +581,7 @@ IDropAction::IDropAction(std::istream &is) void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef) { Inventory *inv_from = mgr->getInventory(from_inv); - + if(!inv_from){ infostream<<"IDropAction::apply(): FAIL: source inventory not found: " <<"from_inv=\""<<from_inv.dump()<<"\""<<std::endl; @@ -627,7 +641,7 @@ 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; - + int actually_dropped_count = 0; ItemStack src_item = list_from->getItem(from_i); @@ -644,7 +658,7 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame infostream<<"Actually dropped no items"<<std::endl; return; } - + // If source isn't infinite if(src_can_take_count != -1){ // Take item from source list @@ -662,13 +676,13 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame <<" list=\""<<from_list<<"\"" <<" i="<<from_i <<std::endl; - + src_item.count = actually_dropped_count; /* Report drop to endpoints */ - + // Source is detached if(from_inv.type == InventoryLocation::DETACHED) { @@ -752,7 +766,7 @@ void ICraftAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef) { Inventory *inv_craft = mgr->getInventory(craft_inv); - + if (!inv_craft) { infostream << "ICraftAction::apply(): FAIL: inventory not found: " << "craft_inv=\"" << craft_inv.dump() << "\"" << std::endl; @@ -872,7 +886,7 @@ bool getCraftingResult(Inventory *inv, ItemStack& result, bool decrementInput, IGameDef *gamedef) { DSTACK(__FUNCTION_NAME); - + result.clear(); // Get the InventoryList in which we will operate diff --git a/src/inventorymanager.h b/src/inventorymanager.h index bbeb5117c..35fcf4b99 100644 --- a/src/inventorymanager.h +++ b/src/inventorymanager.h @@ -108,7 +108,7 @@ class InventoryManager public: InventoryManager(){} virtual ~InventoryManager(){} - + // Get an inventory (server and client) virtual Inventory* getInventory(const InventoryLocation &loc){return NULL;} // Set modified (will be saved and sent over network; only on server) @@ -124,7 +124,7 @@ public: struct InventoryAction { static InventoryAction * deSerialize(std::istream &is); - + virtual u16 getType() const = 0; virtual void serialize(std::ostream &os) const = 0; virtual void apply(InventoryManager *mgr, ServerActiveObject *player, @@ -149,7 +149,7 @@ struct IMoveAction : public InventoryAction // related to movement to somewhere bool caused_by_move_somewhere; u32 move_count; - + IMoveAction() { count = 0; @@ -159,7 +159,7 @@ struct IMoveAction : public InventoryAction caused_by_move_somewhere = false; move_count = 0; } - + IMoveAction(std::istream &is, bool somewhere); u16 getType() const @@ -195,13 +195,13 @@ struct IDropAction : public InventoryAction InventoryLocation from_inv; std::string from_list; s16 from_i; - + IDropAction() { count = 0; from_i = -1; } - + IDropAction(std::istream &is); u16 getType() const @@ -228,12 +228,12 @@ struct ICraftAction : public InventoryAction // count=0 means "everything" u16 count; InventoryLocation craft_inv; - + ICraftAction() { count = 0; } - + ICraftAction(std::istream &is); u16 getType() const |