|
@@ -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)
|