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"
23 #include "inventory.h"
29 #define NODEMETA_GENERIC 1
30 #define NODEMETA_SIGN 14
31 #define NODEMETA_CHEST 15
32 #define NODEMETA_FURNACE 16
33 #define NODEMETA_LOCKABLE_CHEST 17
35 class SignNodeMetadata : public NodeMetadata
38 SignNodeMetadata(IGameDef *gamedef, std::string text);
39 //~SignNodeMetadata();
41 virtual u16 typeId() const;
42 virtual const char* typeName() const
44 static NodeMetadata* create(std::istream &is, IGameDef *gamedef);
45 static NodeMetadata* create(IGameDef *gamedef);
46 virtual NodeMetadata* clone(IGameDef *gamedef);
47 virtual void serializeBody(std::ostream &os);
48 virtual std::string infoText();
50 virtual bool allowsTextInput(){ return true; }
51 virtual std::string getText(){ return m_text; }
52 virtual void setText(const std::string &t){ m_text = t; }
58 class ChestNodeMetadata : public NodeMetadata
61 ChestNodeMetadata(IGameDef *gamedef);
64 virtual u16 typeId() const;
65 virtual const char* typeName() const
67 static NodeMetadata* create(std::istream &is, IGameDef *gamedef);
68 static NodeMetadata* create(IGameDef *gamedef);
69 virtual NodeMetadata* clone(IGameDef *gamedef);
70 virtual void serializeBody(std::ostream &os);
71 virtual std::string infoText();
72 virtual Inventory* getInventory() {return m_inventory;}
73 virtual bool nodeRemovalDisabled();
74 virtual std::string getInventoryDrawSpecString();
77 Inventory *m_inventory;
80 class LockingChestNodeMetadata : public NodeMetadata
83 LockingChestNodeMetadata(IGameDef *gamedef);
84 ~LockingChestNodeMetadata();
86 virtual u16 typeId() const;
87 virtual const char* typeName() const
88 { return "locked_chest"; }
89 static NodeMetadata* create(std::istream &is, IGameDef *gamedef);
90 static NodeMetadata* create(IGameDef *gamedef);
91 virtual NodeMetadata* clone(IGameDef *gamedef);
92 virtual void serializeBody(std::ostream &os);
93 virtual std::string infoText();
94 virtual Inventory* getInventory() {return m_inventory;}
95 virtual bool nodeRemovalDisabled();
96 virtual std::string getInventoryDrawSpecString();
98 virtual std::string getOwner(){ return m_text; }
99 virtual void setOwner(std::string t){ m_text = t; }
102 Inventory *m_inventory;
106 class FurnaceNodeMetadata : public NodeMetadata
109 FurnaceNodeMetadata(IGameDef *gamedef);
110 ~FurnaceNodeMetadata();
112 virtual u16 typeId() const;
113 virtual const char* typeName() const
114 { return "furnace"; }
115 virtual NodeMetadata* clone(IGameDef *gamedef);
116 static NodeMetadata* create(std::istream &is, IGameDef *gamedef);
117 static NodeMetadata* create(IGameDef *gamedef);
118 virtual void serializeBody(std::ostream &os);
119 virtual std::string infoText();
120 virtual Inventory* getInventory() {return m_inventory;}
121 virtual void inventoryModified();
122 virtual bool step(float dtime);
123 virtual bool nodeRemovalDisabled();
124 virtual std::string getInventoryDrawSpecString();
127 Inventory *m_inventory;
128 float m_step_accumulator;
129 float m_fuel_totaltime;
131 float m_src_totaltime;
140 SignNodeMetadata proto_SignNodeMetadata(NULL, "");
142 SignNodeMetadata::SignNodeMetadata(IGameDef *gamedef, std::string text):
143 NodeMetadata(gamedef),
146 NodeMetadata::registerType(typeId(), typeName(), create, create);
148 u16 SignNodeMetadata::typeId() const
150 return NODEMETA_SIGN;
152 NodeMetadata* SignNodeMetadata::create(std::istream &is, IGameDef *gamedef)
154 std::string text = deSerializeString(is);
155 return new SignNodeMetadata(gamedef, text);
157 NodeMetadata* SignNodeMetadata::create(IGameDef *gamedef)
159 return new SignNodeMetadata(gamedef, "");
161 NodeMetadata* SignNodeMetadata::clone(IGameDef *gamedef)
163 return new SignNodeMetadata(gamedef, m_text);
165 void SignNodeMetadata::serializeBody(std::ostream &os)
167 os<<serializeString(m_text);
169 std::string SignNodeMetadata::infoText()
171 return std::string("\"")+m_text+"\"";
179 ChestNodeMetadata proto_ChestNodeMetadata(NULL);
181 ChestNodeMetadata::ChestNodeMetadata(IGameDef *gamedef):
182 NodeMetadata(gamedef)
184 NodeMetadata::registerType(typeId(), typeName(), create, create);
186 m_inventory = new Inventory();
187 m_inventory->addList("0", 8*4);
189 ChestNodeMetadata::~ChestNodeMetadata()
193 u16 ChestNodeMetadata::typeId() const
195 return NODEMETA_CHEST;
197 NodeMetadata* ChestNodeMetadata::create(std::istream &is, IGameDef *gamedef)
199 ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
200 d->m_inventory->deSerialize(is, gamedef);
203 NodeMetadata* ChestNodeMetadata::create(IGameDef *gamedef)
205 ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
208 NodeMetadata* ChestNodeMetadata::clone(IGameDef *gamedef)
210 ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
211 *d->m_inventory = *m_inventory;
214 void ChestNodeMetadata::serializeBody(std::ostream &os)
216 m_inventory->serialize(os);
218 std::string ChestNodeMetadata::infoText()
222 bool ChestNodeMetadata::nodeRemovalDisabled()
225 Disable removal if chest contains something
227 InventoryList *list = m_inventory->getList("0");
230 if(list->getUsedSlots() == 0)
234 std::string ChestNodeMetadata::getInventoryDrawSpecString()
238 "list[current_name;0;0,0;8,4;]"
239 "list[current_player;main;0,5;8,4;]";
243 LockingChestNodeMetadata
247 LockingChestNodeMetadata proto_LockingChestNodeMetadata(NULL);
249 LockingChestNodeMetadata::LockingChestNodeMetadata(IGameDef *gamedef):
250 NodeMetadata(gamedef)
252 NodeMetadata::registerType(typeId(), typeName(), create, create);
254 m_inventory = new Inventory();
255 m_inventory->addList("0", 8*4);
257 LockingChestNodeMetadata::~LockingChestNodeMetadata()
261 u16 LockingChestNodeMetadata::typeId() const
263 return NODEMETA_LOCKABLE_CHEST;
265 NodeMetadata* LockingChestNodeMetadata::create(std::istream &is, IGameDef *gamedef)
267 LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
268 d->setOwner(deSerializeString(is));
269 d->m_inventory->deSerialize(is, gamedef);
272 NodeMetadata* LockingChestNodeMetadata::create(IGameDef *gamedef)
274 LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
277 NodeMetadata* LockingChestNodeMetadata::clone(IGameDef *gamedef)
279 LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
280 *d->m_inventory = *m_inventory;
283 void LockingChestNodeMetadata::serializeBody(std::ostream &os)
285 os<<serializeString(m_text);
286 m_inventory->serialize(os);
288 std::string LockingChestNodeMetadata::infoText()
290 return "Locking Chest";
292 bool LockingChestNodeMetadata::nodeRemovalDisabled()
295 Disable removal if chest contains something
297 InventoryList *list = m_inventory->getList("0");
300 if(list->getUsedSlots() == 0)
304 std::string LockingChestNodeMetadata::getInventoryDrawSpecString()
308 "list[current_name;0;0,0;8,4;]"
309 "list[current_player;main;0,5;8,4;]";
317 FurnaceNodeMetadata proto_FurnaceNodeMetadata(NULL);
319 FurnaceNodeMetadata::FurnaceNodeMetadata(IGameDef *gamedef):
320 NodeMetadata(gamedef)
322 NodeMetadata::registerType(typeId(), typeName(), create, create);
324 m_inventory = new Inventory();
325 m_inventory->addList("fuel", 1);
326 m_inventory->addList("src", 1);
327 m_inventory->addList("dst", 4);
329 m_step_accumulator = 0;
330 m_fuel_totaltime = 0;
335 FurnaceNodeMetadata::~FurnaceNodeMetadata()
339 u16 FurnaceNodeMetadata::typeId() const
341 return NODEMETA_FURNACE;
343 NodeMetadata* FurnaceNodeMetadata::clone(IGameDef *gamedef)
345 FurnaceNodeMetadata *d = new FurnaceNodeMetadata(m_gamedef);
346 *d->m_inventory = *m_inventory;
349 NodeMetadata* FurnaceNodeMetadata::create(std::istream &is, IGameDef *gamedef)
351 FurnaceNodeMetadata *d = new FurnaceNodeMetadata(gamedef);
353 d->m_inventory->deSerialize(is, gamedef);
357 d->m_fuel_totaltime = (float)temp/10;
359 d->m_fuel_time = (float)temp/10;
363 NodeMetadata* FurnaceNodeMetadata::create(IGameDef *gamedef)
365 FurnaceNodeMetadata *d = new FurnaceNodeMetadata(gamedef);
368 void FurnaceNodeMetadata::serializeBody(std::ostream &os)
370 m_inventory->serialize(os);
371 os<<itos(m_fuel_totaltime*10)<<" ";
372 os<<itos(m_fuel_time*10)<<" ";
374 std::string FurnaceNodeMetadata::infoText()
377 if(m_fuel_time >= m_fuel_totaltime)
379 const InventoryList *src_list = m_inventory->getList("src");
381 const InventoryItem *src_item = src_list->getItem(0);
383 if(src_item && src_item->isCookable()) {
384 InventoryList *dst_list = m_inventory->getList("dst");
385 if(!dst_list->roomForCookedItem(src_item))
386 return "Furnace is overloaded";
387 return "Furnace is out of fuel";
390 return "Furnace is inactive";
394 std::string s = "Furnace is active";
395 // Do this so it doesn't always show (0%) for weak fuel
396 if(m_fuel_totaltime > 3) {
398 s += itos(m_fuel_time/m_fuel_totaltime*100);
404 bool FurnaceNodeMetadata::nodeRemovalDisabled()
407 Disable removal if furnace is not empty
409 InventoryList *list[3] = {m_inventory->getList("src"),
410 m_inventory->getList("dst"), m_inventory->getList("fuel")};
412 for(int i = 0; i < 3; i++) {
415 if(list[i]->getUsedSlots() == 0)
422 void FurnaceNodeMetadata::inventoryModified()
424 infostream<<"Furnace inventory modification callback"<<std::endl;
426 bool FurnaceNodeMetadata::step(float dtime)
429 infostream<<"Furnace stepping a long time ("<<dtime<<")"<<std::endl;
430 // Update at a fixed frequency
431 const float interval = 2.0;
432 m_step_accumulator += dtime;
433 bool changed = false;
434 while(m_step_accumulator > interval)
436 m_step_accumulator -= interval;
439 //infostream<<"Furnace step dtime="<<dtime<<std::endl;
441 InventoryList *dst_list = m_inventory->getList("dst");
444 InventoryList *src_list = m_inventory->getList("src");
446 InventoryItem *src_item = src_list->getItem(0);
448 bool room_available = false;
450 if(src_item && src_item->isCookable())
451 room_available = dst_list->roomForCookedItem(src_item);
453 // Start only if there are free slots in dst, so that it can
454 // accomodate any result item
457 m_src_totaltime = src_item->getCookTime();
466 If fuel is burning, increment the burn counters.
467 If item finishes cooking, move it to result.
469 if(m_fuel_time < m_fuel_totaltime)
471 //infostream<<"Furnace is active"<<std::endl;
472 m_fuel_time += dtime;
474 if(m_src_time >= m_src_totaltime && m_src_totaltime > 0.001
477 InventoryItem *cookresult = src_item->createCookResult();
478 dst_list->addItem(cookresult);
479 src_list->decrementMaterials(1);
485 // If the fuel was not used up this step, just keep burning it
486 if(m_fuel_time < m_fuel_totaltime)
491 Get the source again in case it has all burned
493 src_item = src_list->getItem(0);
496 If there is no source item, or the source item is not cookable,
497 or the furnace is still cooking, or the furnace became overloaded, stop loop.
499 if(src_item == NULL || !room_available || m_fuel_time < m_fuel_totaltime ||
500 dst_list->roomForCookedItem(src_item) == false)
502 m_step_accumulator = 0;
506 //infostream<<"Furnace is out of fuel"<<std::endl;
508 InventoryList *fuel_list = m_inventory->getList("fuel");
510 const InventoryItem *fuel_item = fuel_list->getItem(0);
512 if(fuel_item && fuel_item->getBurnTime() >= 0){
513 m_fuel_totaltime = fuel_item->getBurnTime();
515 fuel_list->decrementMaterials(1);
518 //infostream<<"No fuel found"<<std::endl;
519 // No fuel, stop loop.
520 m_step_accumulator = 0;
526 std::string FurnaceNodeMetadata::getInventoryDrawSpecString()
530 "list[current_name;fuel;2,3;1,1;]"
531 "list[current_name;src;2,1;1,1;]"
532 "list[current_name;dst;5,1;2,2;]"
533 "list[current_player;main;0,5;8,4;]";
540 class GenericNodeMetadata : public NodeMetadata
543 Inventory *m_inventory;
547 std::string m_infotext;
548 std::string m_inventorydrawspec;
549 bool m_allow_text_input;
550 bool m_removal_disabled;
551 bool m_enforce_owner;
553 bool m_inventory_modified;
554 bool m_text_modified;
556 std::map<std::string, std::string> m_stringvars;
561 return NODEMETA_GENERIC;
563 const char* typeName() const
568 GenericNodeMetadata(IGameDef *gamedef):
569 NodeMetadata(gamedef),
571 m_inventory(new Inventory()),
575 m_infotext("GenericNodeMetadata"),
576 m_inventorydrawspec(""),
577 m_allow_text_input(false),
578 m_removal_disabled(false),
579 m_enforce_owner(false),
581 m_inventory_modified(false),
582 m_text_modified(false)
584 NodeMetadata::registerType(typeId(), typeName(), create, create);
586 virtual ~GenericNodeMetadata()
590 NodeMetadata* clone(IGameDef *gamedef)
592 GenericNodeMetadata *d = new GenericNodeMetadata(m_gamedef);
594 *d->m_inventory = *m_inventory;
596 d->m_owner = m_owner;
598 d->m_infotext = m_infotext;
599 d->m_inventorydrawspec = m_inventorydrawspec;
600 d->m_allow_text_input = m_allow_text_input;
601 d->m_removal_disabled = m_removal_disabled;
602 d->m_enforce_owner = m_enforce_owner;
603 d->m_inventory_modified = m_inventory_modified;
604 d->m_text_modified = m_text_modified;
607 static NodeMetadata* create(IGameDef *gamedef)
609 GenericNodeMetadata *d = new GenericNodeMetadata(gamedef);
612 static NodeMetadata* create(std::istream &is, IGameDef *gamedef)
614 GenericNodeMetadata *d = new GenericNodeMetadata(gamedef);
616 d->m_inventory->deSerialize(is, gamedef);
617 d->m_text = deSerializeLongString(is);
618 d->m_owner = deSerializeString(is);
620 d->m_infotext = deSerializeString(is);
621 d->m_inventorydrawspec = deSerializeString(is);
622 d->m_allow_text_input = readU8(is);
623 d->m_removal_disabled = readU8(is);
624 d->m_enforce_owner = readU8(is);
626 int num_vars = readU32(is);
627 for(int i=0; i<num_vars; i++){
628 std::string name = deSerializeString(is);
629 std::string var = deSerializeLongString(is);
630 d->m_stringvars[name] = var;
635 void serializeBody(std::ostream &os)
637 m_inventory->serialize(os);
638 os<<serializeLongString(m_text);
639 os<<serializeString(m_owner);
641 os<<serializeString(m_infotext);
642 os<<serializeString(m_inventorydrawspec);
643 writeU8(os, m_allow_text_input);
644 writeU8(os, m_removal_disabled);
645 writeU8(os, m_enforce_owner);
647 int num_vars = m_stringvars.size();
648 writeU32(os, num_vars);
649 for(std::map<std::string, std::string>::iterator
650 i = m_stringvars.begin(); i != m_stringvars.end(); i++){
651 os<<serializeString(i->first);
652 os<<serializeLongString(i->second);
656 std::string infoText()
660 Inventory* getInventory()
664 void inventoryModified()
666 m_inventory_modified = true;
668 bool step(float dtime)
672 bool nodeRemovalDisabled()
674 return m_removal_disabled;
676 std::string getInventoryDrawSpecString()
678 return m_inventorydrawspec;
680 bool allowsTextInput()
682 return m_allow_text_input;
684 std::string getText()
688 void setText(const std::string &t)
691 m_text_modified = true;
693 std::string getOwner()
700 void setOwner(std::string t)
705 /* Interface for GenericNodeMetadata */
707 void setInfoText(const std::string &text)
709 infostream<<"GenericNodeMetadata::setInfoText(\""
710 <<text<<"\")"<<std::endl;
713 void setInventoryDrawSpec(const std::string &text)
715 m_inventorydrawspec = text;
717 void setAllowTextInput(bool b)
719 m_allow_text_input = b;
721 void setRemovalDisabled(bool b)
723 m_removal_disabled = b;
725 void setEnforceOwner(bool b)
729 bool isInventoryModified()
731 return m_inventory_modified;
733 void resetInventoryModified()
735 m_inventory_modified = false;
737 bool isTextModified()
739 return m_text_modified;
741 void resetTextModified()
743 m_text_modified = false;
745 void setString(const std::string &name, const std::string &var)
747 m_stringvars[name] = var;
749 std::string getString(const std::string &name)
751 std::map<std::string, std::string>::iterator i;
752 i = m_stringvars.find(name);
753 if(i == m_stringvars.end())
760 GenericNodeMetadata proto_GenericNodeMetadata(NULL);