diff options
Diffstat (limited to 'src/inventorymanager.cpp')
-rw-r--r-- | src/inventorymanager.cpp | 96 |
1 files changed, 73 insertions, 23 deletions
diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp index 640e3395b..96ce48086 100644 --- a/src/inventorymanager.cpp +++ b/src/inventorymanager.cpp @@ -121,16 +121,13 @@ InventoryAction * InventoryAction::deSerialize(std::istream &is) InventoryAction *a = NULL; - if(type == "Move") - { - a = new IMoveAction(is); - } - else if(type == "Drop") - { + if (type == "Move") { + a = new IMoveAction(is, false); + } else if (type == "MoveSomewhere") { + a = new IMoveAction(is, true); + } else if (type == "Drop") { a = new IDropAction(is); - } - else if(type == "Craft") - { + } else if(type == "Craft") { a = new ICraftAction(is); } @@ -141,9 +138,12 @@ InventoryAction * InventoryAction::deSerialize(std::istream &is) IMoveAction */ -IMoveAction::IMoveAction(std::istream &is) +IMoveAction::IMoveAction(std::istream &is, bool somewhere) { std::string ts; + move_somewhere = somewhere; + caused_by_move_somewhere = false; + move_count = 0; std::getline(is, ts, ' '); count = stoi(ts); @@ -161,8 +161,10 @@ IMoveAction::IMoveAction(std::istream &is) std::getline(is, to_list, ' '); - std::getline(is, ts, ' '); - to_i = stoi(ts); + if (!somewhere) { + std::getline(is, ts, ' '); + to_i = stoi(ts); + } } void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef) @@ -202,6 +204,48 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame return; } + if (move_somewhere) { + s16 old_to_i = to_i; + u16 old_count = count; + caused_by_move_somewhere = true; + move_somewhere = false; + + infostream << "IMoveAction::apply(): moving item somewhere" + << " msom=" << move_somewhere + << " count=" << count + << " from inv=\"" << from_inv.dump() << "\"" + << " list=\"" << from_list << "\"" + << " i=" << from_i + << " to inv=\"" << to_inv.dump() << "\"" + << " list=\"" << to_list << "\"" + << std::endl; + + // Try to add the item to destination list + s16 dest_size = list_to->getSize(); + // First try all the non-empty slots + for (s16 dest_i = 0; dest_i < dest_size && count > 0; dest_i++) { + if (!list_to->getItem(dest_i).empty()) { + to_i = dest_i; + apply(mgr, player, gamedef); + count -= move_count; + } + } + + // Then try all the empty ones + for (s16 dest_i = 0; dest_i < dest_size && count > 0; dest_i++) { + if (list_to->getItem(dest_i).empty()) { + to_i = dest_i; + apply(mgr, player, gamedef); + count -= move_count; + } + } + + to_i = old_to_i; + count = old_count; + caused_by_move_somewhere = false; + move_somewhere = true; + return; + } /* Do not handle rollback if both inventories are that of the same player */ @@ -324,7 +368,8 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame If something is wrong (source item is empty, destination is the same as source), nothing happens */ - list_from->moveItem(from_i, list_to, to_i, count); + move_count = list_from->moveItem(from_i, + list_to, to_i, count, !caused_by_move_somewhere); // If source is infinite, reset it's stack if(src_can_take_count == -1){ @@ -352,15 +397,17 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame list_from->takeItem(from_i, count); } - infostream<<"IMoveAction::apply(): moved" - <<" count="<<count - <<" from inv=\""<<from_inv.dump()<<"\"" - <<" list=\""<<from_list<<"\"" - <<" i="<<from_i - <<" to inv=\""<<to_inv.dump()<<"\"" - <<" list=\""<<to_list<<"\"" - <<" i="<<to_i - <<std::endl; + infostream << "IMoveAction::apply(): moved" + << " msom=" << move_somewhere + << " caused=" << caused_by_move_somewhere + << " count=" << count + << " from inv=\"" << from_inv.dump() << "\"" + << " list=\"" << from_list << "\"" + << " i=" << from_i + << " to inv=\"" << to_inv.dump() << "\"" + << " list=\"" << to_list << "\"" + << " i=" << to_i + << std::endl; /* Record rollback information @@ -480,7 +527,10 @@ void IMoveAction::clientApply(InventoryManager *mgr, IGameDef *gamedef) if(!list_from || !list_to) return; - list_from->moveItem(from_i, list_to, to_i, count); + if (!move_somewhere) + list_from->moveItem(from_i, list_to, to_i, count); + else + list_from->moveItemSomewhere(from_i, list_to, count); mgr->setInventoryModified(from_inv); if(inv_from != inv_to) |