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 "content_nodemeta.h"
21 #include "inventory.h"
22 #include "content_mapnode.h"
30 SignNodeMetadata proto_SignNodeMetadata(NULL, "");
32 SignNodeMetadata::SignNodeMetadata(IGameDef *gamedef, std::string text):
33 NodeMetadata(gamedef),
36 NodeMetadata::registerType(typeId(), create);
38 u16 SignNodeMetadata::typeId() const
40 return CONTENT_SIGN_WALL;
42 NodeMetadata* SignNodeMetadata::create(std::istream &is, IGameDef *gamedef)
44 std::string text = deSerializeString(is);
45 return new SignNodeMetadata(gamedef, text);
47 NodeMetadata* SignNodeMetadata::clone(IGameDef *gamedef)
49 return new SignNodeMetadata(gamedef, m_text);
51 void SignNodeMetadata::serializeBody(std::ostream &os)
53 os<<serializeString(m_text);
55 std::string SignNodeMetadata::infoText()
57 return std::string("\"")+m_text+"\"";
65 ChestNodeMetadata proto_ChestNodeMetadata(NULL);
67 ChestNodeMetadata::ChestNodeMetadata(IGameDef *gamedef):
70 NodeMetadata::registerType(typeId(), create);
72 m_inventory = new Inventory();
73 m_inventory->addList("0", 8*4);
75 ChestNodeMetadata::~ChestNodeMetadata()
79 u16 ChestNodeMetadata::typeId() const
83 NodeMetadata* ChestNodeMetadata::create(std::istream &is, IGameDef *gamedef)
85 ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
86 d->m_inventory->deSerialize(is, gamedef);
89 NodeMetadata* ChestNodeMetadata::clone(IGameDef *gamedef)
91 ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
92 *d->m_inventory = *m_inventory;
95 void ChestNodeMetadata::serializeBody(std::ostream &os)
97 m_inventory->serialize(os);
99 std::string ChestNodeMetadata::infoText()
103 bool ChestNodeMetadata::nodeRemovalDisabled()
106 Disable removal if chest contains something
108 InventoryList *list = m_inventory->getList("0");
111 if(list->getUsedSlots() == 0)
115 std::string ChestNodeMetadata::getInventoryDrawSpecString()
119 "list[current_name;0;0,0;8,4;]"
120 "list[current_player;main;0,5;8,4;]";
124 LockingChestNodeMetadata
128 LockingChestNodeMetadata proto_LockingChestNodeMetadata(NULL);
130 LockingChestNodeMetadata::LockingChestNodeMetadata(IGameDef *gamedef):
131 NodeMetadata(gamedef)
133 NodeMetadata::registerType(typeId(), create);
135 m_inventory = new Inventory();
136 m_inventory->addList("0", 8*4);
138 LockingChestNodeMetadata::~LockingChestNodeMetadata()
142 u16 LockingChestNodeMetadata::typeId() const
144 return CONTENT_LOCKABLE_CHEST;
146 NodeMetadata* LockingChestNodeMetadata::create(std::istream &is, IGameDef *gamedef)
148 LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
149 d->setOwner(deSerializeString(is));
150 d->m_inventory->deSerialize(is, gamedef);
153 NodeMetadata* LockingChestNodeMetadata::clone(IGameDef *gamedef)
155 LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
156 *d->m_inventory = *m_inventory;
159 void LockingChestNodeMetadata::serializeBody(std::ostream &os)
161 os<<serializeString(m_text);
162 m_inventory->serialize(os);
164 std::string LockingChestNodeMetadata::infoText()
166 return "Locking Chest";
168 bool LockingChestNodeMetadata::nodeRemovalDisabled()
171 Disable removal if chest contains something
173 InventoryList *list = m_inventory->getList("0");
176 if(list->getUsedSlots() == 0)
180 std::string LockingChestNodeMetadata::getInventoryDrawSpecString()
184 "list[current_name;0;0,0;8,4;]"
185 "list[current_player;main;0,5;8,4;]";
193 FurnaceNodeMetadata proto_FurnaceNodeMetadata(NULL);
195 FurnaceNodeMetadata::FurnaceNodeMetadata(IGameDef *gamedef):
196 NodeMetadata(gamedef)
198 NodeMetadata::registerType(typeId(), create);
200 m_inventory = new Inventory();
201 m_inventory->addList("fuel", 1);
202 m_inventory->addList("src", 1);
203 m_inventory->addList("dst", 4);
205 m_step_accumulator = 0;
206 m_fuel_totaltime = 0;
211 FurnaceNodeMetadata::~FurnaceNodeMetadata()
215 u16 FurnaceNodeMetadata::typeId() const
217 return CONTENT_FURNACE;
219 NodeMetadata* FurnaceNodeMetadata::clone(IGameDef *gamedef)
221 FurnaceNodeMetadata *d = new FurnaceNodeMetadata(m_gamedef);
222 *d->m_inventory = *m_inventory;
225 NodeMetadata* FurnaceNodeMetadata::create(std::istream &is, IGameDef *gamedef)
227 FurnaceNodeMetadata *d = new FurnaceNodeMetadata(gamedef);
229 d->m_inventory->deSerialize(is, gamedef);
233 d->m_fuel_totaltime = (float)temp/10;
235 d->m_fuel_time = (float)temp/10;
239 void FurnaceNodeMetadata::serializeBody(std::ostream &os)
241 m_inventory->serialize(os);
242 os<<itos(m_fuel_totaltime*10)<<" ";
243 os<<itos(m_fuel_time*10)<<" ";
245 std::string FurnaceNodeMetadata::infoText()
248 if(m_fuel_time >= m_fuel_totaltime)
250 const InventoryList *src_list = m_inventory->getList("src");
252 const InventoryItem *src_item = src_list->getItem(0);
254 if(src_item && src_item->isCookable()) {
255 InventoryList *dst_list = m_inventory->getList("dst");
256 if(!dst_list->roomForCookedItem(src_item))
257 return "Furnace is overloaded";
258 return "Furnace is out of fuel";
261 return "Furnace is inactive";
265 std::string s = "Furnace is active";
266 // Do this so it doesn't always show (0%) for weak fuel
267 if(m_fuel_totaltime > 3) {
269 s += itos(m_fuel_time/m_fuel_totaltime*100);
275 bool FurnaceNodeMetadata::nodeRemovalDisabled()
278 Disable removal if furnace is not empty
280 InventoryList *list[3] = {m_inventory->getList("src"),
281 m_inventory->getList("dst"), m_inventory->getList("fuel")};
283 for(int i = 0; i < 3; i++) {
286 if(list[i]->getUsedSlots() == 0)
293 void FurnaceNodeMetadata::inventoryModified()
295 infostream<<"Furnace inventory modification callback"<<std::endl;
297 bool FurnaceNodeMetadata::step(float dtime)
300 infostream<<"Furnace stepping a long time ("<<dtime<<")"<<std::endl;
301 // Update at a fixed frequency
302 const float interval = 2.0;
303 m_step_accumulator += dtime;
304 bool changed = false;
305 while(m_step_accumulator > interval)
307 m_step_accumulator -= interval;
310 //infostream<<"Furnace step dtime="<<dtime<<std::endl;
312 InventoryList *dst_list = m_inventory->getList("dst");
315 InventoryList *src_list = m_inventory->getList("src");
317 InventoryItem *src_item = src_list->getItem(0);
319 bool room_available = false;
321 if(src_item && src_item->isCookable())
322 room_available = dst_list->roomForCookedItem(src_item);
324 // Start only if there are free slots in dst, so that it can
325 // accomodate any result item
337 If fuel is burning, increment the burn counters.
338 If item finishes cooking, move it to result.
340 if(m_fuel_time < m_fuel_totaltime)
342 //infostream<<"Furnace is active"<<std::endl;
343 m_fuel_time += dtime;
345 if(m_src_time >= m_src_totaltime && m_src_totaltime > 0.001
348 InventoryItem *cookresult = src_item->createCookResult();
349 dst_list->addItem(cookresult);
350 src_list->decrementMaterials(1);
356 // If the fuel was not used up this step, just keep burning it
357 if(m_fuel_time < m_fuel_totaltime)
362 Get the source again in case it has all burned
364 src_item = src_list->getItem(0);
367 If there is no source item, or the source item is not cookable,
368 or the furnace is still cooking, or the furnace became overloaded, stop loop.
370 if(src_item == NULL || !room_available || m_fuel_time < m_fuel_totaltime ||
371 dst_list->roomForCookedItem(src_item) == false)
373 m_step_accumulator = 0;
377 //infostream<<"Furnace is out of fuel"<<std::endl;
379 InventoryList *fuel_list = m_inventory->getList("fuel");
381 const InventoryItem *fuel_item = fuel_list->getItem(0);
383 if(ItemSpec(ITEM_MATERIAL, CONTENT_TREE).checkItem(fuel_item))
385 m_fuel_totaltime = 30;
387 fuel_list->decrementMaterials(1);
390 else if(ItemSpec(ITEM_MATERIAL, CONTENT_JUNGLETREE).checkItem(fuel_item))
392 m_fuel_totaltime = 30;
394 fuel_list->decrementMaterials(1);
397 else if(ItemSpec(ITEM_MATERIAL, CONTENT_FENCE).checkItem(fuel_item))
399 m_fuel_totaltime = 30/2;
401 fuel_list->decrementMaterials(1);
404 else if(ItemSpec(ITEM_MATERIAL, CONTENT_WOOD).checkItem(fuel_item))
406 m_fuel_totaltime = 30/4;
408 fuel_list->decrementMaterials(1);
411 else if(ItemSpec(ITEM_MATERIAL, CONTENT_BOOKSHELF).checkItem(fuel_item))
413 m_fuel_totaltime = 30/4;
415 fuel_list->decrementMaterials(1);
418 else if(ItemSpec(ITEM_MATERIAL, CONTENT_LEAVES).checkItem(fuel_item))
420 m_fuel_totaltime = 30/16;
422 fuel_list->decrementMaterials(1);
425 else if(ItemSpec(ITEM_MATERIAL, CONTENT_PAPYRUS).checkItem(fuel_item))
427 m_fuel_totaltime = 30/32;
429 fuel_list->decrementMaterials(1);
432 else if(ItemSpec(ITEM_MATERIAL, CONTENT_JUNGLEGRASS).checkItem(fuel_item))
434 m_fuel_totaltime = 30/32;
436 fuel_list->decrementMaterials(1);
439 else if(ItemSpec(ITEM_MATERIAL, CONTENT_CACTUS).checkItem(fuel_item))
441 m_fuel_totaltime = 30/4;
443 fuel_list->decrementMaterials(1);
446 else if(ItemSpec(ITEM_CRAFT, "Stick").checkItem(fuel_item))
448 m_fuel_totaltime = 30/4/4;
450 fuel_list->decrementMaterials(1);
453 else if(ItemSpec(ITEM_CRAFT, "lump_of_coal").checkItem(fuel_item))
455 m_fuel_totaltime = 40;
457 fuel_list->decrementMaterials(1);
462 //infostream<<"No fuel found"<<std::endl;
463 // No fuel, stop loop.
464 m_step_accumulator = 0;
470 std::string FurnaceNodeMetadata::getInventoryDrawSpecString()
474 "list[current_name;fuel;2,3;1,1;]"
475 "list[current_name;src;2,1;1,1;]"
476 "list[current_name;dst;5,1;2,2;]"
477 "list[current_player;main;0,5;8,4;]";