3 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "inventorymanager.h"
22 #include "environment.h"
23 #include "scriptapi.h"
24 #include "serverobject.h"
25 #include "main.h" // for g_settings
33 std::string InventoryLocation::dump() const
35 std::ostringstream os(std::ios::binary);
40 void InventoryLocation::serialize(std::ostream &os) const
43 case InventoryLocation::UNDEFINED:
48 case InventoryLocation::CURRENT_PLAYER:
53 case InventoryLocation::PLAYER:
58 case InventoryLocation::NODEMETA:
60 os<<"nodemeta:"<<p.X<<","<<p.Y<<","<<p.Z;
68 void InventoryLocation::deSerialize(std::istream &is)
71 std::getline(is, tname, ':');
72 if(tname == "undefined")
74 type = InventoryLocation::UNDEFINED;
76 else if(tname == "current_player")
78 type = InventoryLocation::CURRENT_PLAYER;
80 else if(tname == "player")
82 type = InventoryLocation::PLAYER;
83 std::getline(is, name, '\n');
85 else if(tname == "nodemeta")
87 type = InventoryLocation::NODEMETA;
89 std::getline(is, pos, '\n');
91 p.X = stoi(fn.next(","));
92 p.Y = stoi(fn.next(","));
93 p.Z = stoi(fn.next(","));
97 infostream<<"Unknown InventoryLocation type=\""<<tname<<"\""<<std::endl;
98 throw SerializationError("Unknown InventoryLocation type");
102 void InventoryLocation::deSerialize(std::string s)
104 std::istringstream is(s, std::ios::binary);
112 InventoryAction * InventoryAction::deSerialize(std::istream &is)
115 std::getline(is, type, ' ');
117 InventoryAction *a = NULL;
121 a = new IMoveAction(is);
123 else if(type == "Drop")
125 a = new IDropAction(is);
131 IMoveAction::IMoveAction(std::istream &is)
135 std::getline(is, ts, ' ');
138 std::getline(is, ts, ' ');
139 from_inv.deSerialize(ts);
141 std::getline(is, from_list, ' ');
143 std::getline(is, ts, ' ');
146 std::getline(is, ts, ' ');
147 to_inv.deSerialize(ts);
149 std::getline(is, to_list, ' ');
151 std::getline(is, ts, ' ');
155 void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player)
157 Inventory *inv_from = mgr->getInventory(from_inv);
158 Inventory *inv_to = mgr->getInventory(to_inv);
161 infostream<<"IMoveAction::apply(): FAIL: source inventory not found: "
162 <<"from_inv=\""<<from_inv.dump()<<"\""
163 <<", to_inv=\""<<to_inv.dump()<<"\""<<std::endl;
167 infostream<<"IMoveAction::apply(): FAIL: destination inventory not found: "
168 <<"from_inv=\""<<from_inv.dump()<<"\""
169 <<", to_inv=\""<<to_inv.dump()<<"\""<<std::endl;
173 InventoryList *list_from = inv_from->getList(from_list);
174 InventoryList *list_to = inv_to->getList(to_list);
177 If a list doesn't exist or the source item doesn't exist
180 infostream<<"IMoveAction::apply(): FAIL: source list not found: "
181 <<"from_inv=\""<<from_inv.dump()<<"\""
182 <<", from_list=\""<<from_list<<"\""<<std::endl;
186 infostream<<"IMoveAction::apply(): FAIL: destination list not found: "
187 <<"to_inv=\""<<to_inv.dump()<<"\""
188 <<", to_list=\""<<to_list<<"\""<<std::endl;
191 if(list_from->getItem(from_i).empty())
193 infostream<<"IMoveAction::apply(): FAIL: source item not found: "
194 <<"from_inv=\""<<from_inv.dump()<<"\""
195 <<", from_list=\""<<from_list<<"\""
196 <<" from_i="<<from_i<<std::endl;
200 If the source and the destination slots are the same
202 if(inv_from == inv_to && list_from == list_to && from_i == to_i)
204 infostream<<"IMoveAction::apply(): FAIL: source and destination slots "
205 <<"are the same: inv=\""<<from_inv.dump()
206 <<"\" list=\""<<from_list
207 <<"\" i="<<from_i<<std::endl;
211 // Take item from source list
214 item1 = list_from->changeItem(from_i, ItemStack());
216 item1 = list_from->takeItem(from_i, count);
218 // Try to add the item to destination list
219 int oldcount = item1.count;
220 item1 = list_to->addItem(to_i, item1);
222 // If something is returned, the item was not fully added
225 // If olditem is returned, nothing was added.
226 bool nothing_added = (item1.count == oldcount);
228 // If something else is returned, part of the item was left unadded.
229 // Add the other part back to the source item
230 list_from->addItem(from_i, item1);
232 // If olditem is returned, nothing was added.
236 // Take item from source list
237 item1 = list_from->changeItem(from_i, ItemStack());
238 // Adding was not possible, swap the items.
239 ItemStack item2 = list_to->changeItem(to_i, item1);
240 // Put item from destination list to the source list
241 list_from->changeItem(from_i, item2);
245 mgr->setInventoryModified(from_inv);
246 if(inv_from != inv_to)
247 mgr->setInventoryModified(to_inv);
249 infostream<<"IMoveAction::apply(): moved at "
250 <<" count="<<count<<"\""
251 <<" from inv=\""<<from_inv.dump()<<"\""
252 <<" list=\""<<from_list<<"\""
254 <<" to inv=\""<<to_inv.dump()<<"\""
255 <<" list=\""<<to_list<<"\""
260 IDropAction::IDropAction(std::istream &is)
264 std::getline(is, ts, ' ');
267 std::getline(is, ts, ' ');
268 from_inv.deSerialize(ts);
270 std::getline(is, from_list, ' ');
272 std::getline(is, ts, ' ');
276 void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player)
278 Inventory *inv_from = mgr->getInventory(from_inv);
281 infostream<<"IDropAction::apply(): FAIL: source inventory not found: "
282 <<"from_inv=\""<<from_inv.dump()<<"\""<<std::endl;
286 InventoryList *list_from = inv_from->getList(from_list);
289 If a list doesn't exist or the source item doesn't exist
292 infostream<<"IDropAction::apply(): FAIL: source list not found: "
293 <<"from_inv=\""<<from_inv.dump()<<"\""<<std::endl;
296 if(list_from->getItem(from_i).empty())
298 infostream<<"IDropAction::apply(): FAIL: source item not found: "
299 <<"from_inv=\""<<from_inv.dump()<<"\""
300 <<", from_list=\""<<from_list<<"\""
301 <<" from_i="<<from_i<<std::endl;
308 ItemStack item = list_from->getItem(from_i);
309 if(scriptapi_item_on_drop(player->getEnv()->getLua(), item, player,
310 player->getBasePosition() + v3f(0,1,0)))
312 // Apply returned ItemStack
313 if(g_settings->getBool("creative_mode") == false
314 || from_inv.type != InventoryLocation::PLAYER)
315 list_from->changeItem(from_i, item);
316 mgr->setInventoryModified(from_inv);
319 infostream<<"IDropAction::apply(): dropped "
320 <<" from inv=\""<<from_inv.dump()<<"\""
321 <<" list=\""<<from_list<<"\""