X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fcontent_nodemeta.cpp;h=b36d57c89fc73654021ababc29ccf9232bc68c4d;hb=2de8f915f877e3b6779576c19e523c854966c7cd;hp=ab98496688bfbf6956d513e60a8096dabfb638d9;hpb=df8346ef4d70ba7c717c4c7b9c783df876378ca8;p=dragonfireclient.git diff --git a/src/content_nodemeta.cpp b/src/content_nodemeta.cpp index ab9849668..b36d57c89 100644 --- a/src/content_nodemeta.cpp +++ b/src/content_nodemeta.cpp @@ -18,14 +18,129 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "content_nodemeta.h" + +#include #include "inventory.h" #include "log.h" #include "utility.h" +#include "craftdef.h" +#include "gamedef.h" + +class Inventory; +#define NODEMETA_GENERIC 1 #define NODEMETA_SIGN 14 #define NODEMETA_CHEST 15 -#define NODEMETA_LOCKABLE_CHEST 17 #define NODEMETA_FURNACE 16 +#define NODEMETA_LOCKABLE_CHEST 17 + +core::map NodeMetadata::m_types; +core::map NodeMetadata::m_names; + +class SignNodeMetadata : public NodeMetadata +{ +public: + SignNodeMetadata(IGameDef *gamedef, std::string text); + //~SignNodeMetadata(); + + virtual u16 typeId() const; + virtual const char* typeName() const + { return "sign"; } + static NodeMetadata* create(std::istream &is, IGameDef *gamedef); + static NodeMetadata* create(IGameDef *gamedef); + virtual NodeMetadata* clone(IGameDef *gamedef); + virtual void serializeBody(std::ostream &os); + virtual std::string infoText(); + + virtual bool allowsTextInput(){ return true; } + virtual std::string getText(){ return m_text; } + virtual void setText(const std::string &t){ m_text = t; } + +private: + std::string m_text; +}; + +class ChestNodeMetadata : public NodeMetadata +{ +public: + ChestNodeMetadata(IGameDef *gamedef); + ~ChestNodeMetadata(); + + virtual u16 typeId() const; + virtual const char* typeName() const + { return "chest"; } + static NodeMetadata* create(std::istream &is, IGameDef *gamedef); + static NodeMetadata* create(IGameDef *gamedef); + virtual NodeMetadata* clone(IGameDef *gamedef); + virtual void serializeBody(std::ostream &os); + virtual std::string infoText(); + virtual Inventory* getInventory() {return m_inventory;} + virtual bool nodeRemovalDisabled(); + virtual std::string getInventoryDrawSpecString(); + +private: + Inventory *m_inventory; +}; + +class LockingChestNodeMetadata : public NodeMetadata +{ +public: + LockingChestNodeMetadata(IGameDef *gamedef); + ~LockingChestNodeMetadata(); + + virtual u16 typeId() const; + virtual const char* typeName() const + { return "locked_chest"; } + static NodeMetadata* create(std::istream &is, IGameDef *gamedef); + static NodeMetadata* create(IGameDef *gamedef); + virtual NodeMetadata* clone(IGameDef *gamedef); + virtual void serializeBody(std::ostream &os); + virtual std::string infoText(); + virtual Inventory* getInventory() {return m_inventory;} + virtual bool nodeRemovalDisabled(); + virtual std::string getInventoryDrawSpecString(); + + virtual std::string getOwner(){ return m_text; } + virtual void setOwner(std::string t){ m_text = t; } + +private: + Inventory *m_inventory; + std::string m_text; +}; + +class FurnaceNodeMetadata : public NodeMetadata +{ +public: + FurnaceNodeMetadata(IGameDef *gamedef); + ~FurnaceNodeMetadata(); + + virtual u16 typeId() const; + virtual const char* typeName() const + { return "furnace"; } + virtual NodeMetadata* clone(IGameDef *gamedef); + static NodeMetadata* create(std::istream &is, IGameDef *gamedef); + static NodeMetadata* create(IGameDef *gamedef); + virtual void serializeBody(std::ostream &os); + virtual std::string infoText(); + virtual Inventory* getInventory() {return m_inventory;} + virtual void inventoryModified(); + virtual bool step(float dtime); + virtual bool nodeRemovalDisabled(); + virtual std::string getInventoryDrawSpecString(); + +protected: + bool getCookResult(bool remove, std::string &cookresult, float &cooktime); + bool getBurnResult(bool remove, float &burntime); + +private: + Inventory *m_inventory; + std::string m_infotext; + float m_step_accumulator; + float m_fuel_totaltime; + float m_fuel_time; + float m_src_totaltime; + float m_src_time; +}; /* SignNodeMetadata @@ -38,7 +153,7 @@ SignNodeMetadata::SignNodeMetadata(IGameDef *gamedef, std::string text): NodeMetadata(gamedef), m_text(text) { - NodeMetadata::registerType(typeId(), create); + NodeMetadata::registerType(typeId(), typeName(), create, create); } u16 SignNodeMetadata::typeId() const { @@ -49,6 +164,10 @@ NodeMetadata* SignNodeMetadata::create(std::istream &is, IGameDef *gamedef) std::string text = deSerializeString(is); return new SignNodeMetadata(gamedef, text); } +NodeMetadata* SignNodeMetadata::create(IGameDef *gamedef) +{ + return new SignNodeMetadata(gamedef, ""); +} NodeMetadata* SignNodeMetadata::clone(IGameDef *gamedef) { return new SignNodeMetadata(gamedef, m_text); @@ -72,10 +191,8 @@ ChestNodeMetadata proto_ChestNodeMetadata(NULL); ChestNodeMetadata::ChestNodeMetadata(IGameDef *gamedef): NodeMetadata(gamedef) { - NodeMetadata::registerType(typeId(), create); - - m_inventory = new Inventory(); - m_inventory->addList("0", 8*4); + NodeMetadata::registerType(typeId(), typeName(), create, create); + m_inventory = NULL; } ChestNodeMetadata::~ChestNodeMetadata() { @@ -88,13 +205,21 @@ u16 ChestNodeMetadata::typeId() const NodeMetadata* ChestNodeMetadata::create(std::istream &is, IGameDef *gamedef) { ChestNodeMetadata *d = new ChestNodeMetadata(gamedef); - d->m_inventory->deSerialize(is, gamedef); + d->m_inventory = new Inventory(gamedef->idef()); + d->m_inventory->deSerialize(is); + return d; +} +NodeMetadata* ChestNodeMetadata::create(IGameDef *gamedef) +{ + ChestNodeMetadata *d = new ChestNodeMetadata(gamedef); + d->m_inventory = new Inventory(gamedef->idef()); + d->m_inventory->addList("0", 8*4); return d; } NodeMetadata* ChestNodeMetadata::clone(IGameDef *gamedef) { ChestNodeMetadata *d = new ChestNodeMetadata(gamedef); - *d->m_inventory = *m_inventory; + d->m_inventory = new Inventory(*m_inventory); return d; } void ChestNodeMetadata::serializeBody(std::ostream &os) @@ -135,10 +260,8 @@ LockingChestNodeMetadata proto_LockingChestNodeMetadata(NULL); LockingChestNodeMetadata::LockingChestNodeMetadata(IGameDef *gamedef): NodeMetadata(gamedef) { - NodeMetadata::registerType(typeId(), create); - - m_inventory = new Inventory(); - m_inventory->addList("0", 8*4); + NodeMetadata::registerType(typeId(), typeName(), create, create); + m_inventory = NULL; } LockingChestNodeMetadata::~LockingChestNodeMetadata() { @@ -152,13 +275,21 @@ NodeMetadata* LockingChestNodeMetadata::create(std::istream &is, IGameDef *gamed { LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef); d->setOwner(deSerializeString(is)); - d->m_inventory->deSerialize(is, gamedef); + d->m_inventory = new Inventory(gamedef->idef()); + d->m_inventory->deSerialize(is); + return d; +} +NodeMetadata* LockingChestNodeMetadata::create(IGameDef *gamedef) +{ + LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef); + d->m_inventory = new Inventory(gamedef->idef()); + d->m_inventory->addList("0", 8*4); return d; } NodeMetadata* LockingChestNodeMetadata::clone(IGameDef *gamedef) { LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef); - *d->m_inventory = *m_inventory; + d->m_inventory = new Inventory(*m_inventory); return d; } void LockingChestNodeMetadata::serializeBody(std::ostream &os) @@ -200,12 +331,11 @@ FurnaceNodeMetadata proto_FurnaceNodeMetadata(NULL); FurnaceNodeMetadata::FurnaceNodeMetadata(IGameDef *gamedef): NodeMetadata(gamedef) { - NodeMetadata::registerType(typeId(), create); + NodeMetadata::registerType(typeId(), typeName(), create, create); - m_inventory = new Inventory(); - m_inventory->addList("fuel", 1); - m_inventory->addList("src", 1); - m_inventory->addList("dst", 4); + m_inventory = NULL; + + m_infotext = "Furnace is inactive"; m_step_accumulator = 0; m_fuel_totaltime = 0; @@ -224,58 +354,66 @@ u16 FurnaceNodeMetadata::typeId() const NodeMetadata* FurnaceNodeMetadata::clone(IGameDef *gamedef) { FurnaceNodeMetadata *d = new FurnaceNodeMetadata(m_gamedef); - *d->m_inventory = *m_inventory; + d->m_inventory = new Inventory(*m_inventory); return d; } NodeMetadata* FurnaceNodeMetadata::create(std::istream &is, IGameDef *gamedef) { FurnaceNodeMetadata *d = new FurnaceNodeMetadata(gamedef); - d->m_inventory->deSerialize(is, gamedef); + d->m_inventory = new Inventory(gamedef->idef()); + d->m_inventory->deSerialize(is); - int temp; + int temp = 0; is>>temp; d->m_fuel_totaltime = (float)temp/10; + temp = 0; is>>temp; d->m_fuel_time = (float)temp/10; + temp = 0; + is>>temp; + d->m_src_totaltime = (float)temp/10; + temp = 0; + is>>temp; + d->m_src_time = (float)temp/10; + + if(is.eof()) + { + // Old furnaces didn't serialize src_totaltime and src_time + d->m_src_totaltime = 0; + d->m_src_time = 0; + d->m_infotext = ""; + } + else + { + // New furnaces also serialize the infotext (so that the + // client doesn't need to have the list of cooking recipes). + d->m_infotext = deSerializeJsonString(is); + } return d; } +NodeMetadata* FurnaceNodeMetadata::create(IGameDef *gamedef) +{ + FurnaceNodeMetadata *d = new FurnaceNodeMetadata(gamedef); + d->m_inventory = new Inventory(gamedef->idef()); + d->m_inventory->addList("fuel", 1); + d->m_inventory->addList("src", 1); + d->m_inventory->addList("dst", 4); + return d; +} void FurnaceNodeMetadata::serializeBody(std::ostream &os) { m_inventory->serialize(os); os<= m_fuel_totaltime) - { - const InventoryList *src_list = m_inventory->getList("src"); - assert(src_list); - const InventoryItem *src_item = src_list->getItem(0); - - if(src_item && src_item->isCookable()) { - InventoryList *dst_list = m_inventory->getList("dst"); - if(!dst_list->roomForCookedItem(src_item)) - return "Furnace is overloaded"; - return "Furnace is out of fuel"; - } - else - return "Furnace is inactive"; - } - else - { - std::string s = "Furnace is active"; - // Do this so it doesn't always show (0%) for weak fuel - if(m_fuel_totaltime > 3) { - s += " ("; - s += itos(m_fuel_time/m_fuel_totaltime*100); - s += "%)"; - } - return s; - } + return m_infotext; } bool FurnaceNodeMetadata::nodeRemovalDisabled() { @@ -303,6 +441,10 @@ bool FurnaceNodeMetadata::step(float dtime) { if(dtime > 60.0) infostream<<"Furnace stepping a long time ("<getList("dst"); + assert(dst_list); + // Update at a fixed frequency const float interval = 2.0; m_step_accumulator += dtime; @@ -313,86 +455,110 @@ bool FurnaceNodeMetadata::step(float dtime) dtime = interval; //infostream<<"Furnace step dtime="<getList("dst"); - assert(dst_list); - InventoryList *src_list = m_inventory->getList("src"); - assert(src_list); - InventoryItem *src_item = src_list->getItem(0); - + bool changed_this_loop = false; + + // Check + // 1. if the source item is cookable + // 2. if there is room for the cooked item + std::string cookresult; + float cooktime; + bool cookable = getCookResult(false, cookresult, cooktime); + ItemStack cookresult_item; bool room_available = false; - - if(src_item && src_item->isCookable()) - room_available = dst_list->roomForCookedItem(src_item); - - // Start only if there are free slots in dst, so that it can - // accomodate any result item - if(room_available) + if(cookable) { - m_src_totaltime = src_item->getCookTime(); + cookresult_item.deSerialize(cookresult, m_gamedef->idef()); + room_available = dst_list->roomForItem(cookresult_item); } - else + + // Step fuel time + bool burning = (m_fuel_time < m_fuel_totaltime); + if(burning) { - m_src_time = 0; - m_src_totaltime = 0; + changed_this_loop = true; + m_fuel_time += dtime; } - - /* - If fuel is burning, increment the burn counters. - If item finishes cooking, move it to result. - */ - if(m_fuel_time < m_fuel_totaltime) + + std::string infotext; + if(room_available) { - //infostream<<"Furnace is active"<= m_src_totaltime && m_src_totaltime > 0.001 - && src_item) + float burntime; + if(burning) + { + changed_this_loop = true; + m_src_time += dtime; + m_src_totaltime = cooktime; + infotext = "Furnace is cooking"; + } + else if(getBurnResult(true, burntime)) + { + // Fuel inserted + changed_this_loop = true; + m_fuel_time = 0; + m_fuel_totaltime = burntime; + //m_src_time += dtime; + //m_src_totaltime = cooktime; + infotext = "Furnace is cooking"; + } + else { - InventoryItem *cookresult = src_item->createCookResult(); - dst_list->addItem(cookresult); - src_list->decrementMaterials(1); m_src_time = 0; m_src_totaltime = 0; + infotext = "Furnace is out of fuel"; + } + if(m_src_totaltime > 0.001 && m_src_time >= m_src_totaltime) + { + // One item fully cooked + changed_this_loop = true; + dst_list->addItem(cookresult_item); + getCookResult(true, cookresult, cooktime); // decrement source + m_src_totaltime = 0; + m_src_time = 0; } - changed = true; - - // If the fuel was not used up this step, just keep burning it - if(m_fuel_time < m_fuel_totaltime) - continue; } - - /* - Get the source again in case it has all burned - */ - src_item = src_list->getItem(0); - - /* - If there is no source item, or the source item is not cookable, - or the furnace is still cooking, or the furnace became overloaded, stop loop. - */ - if(src_item == NULL || !room_available || m_fuel_time < m_fuel_totaltime || - dst_list->roomForCookedItem(src_item) == false) + else { - m_step_accumulator = 0; - break; + // Not cookable or no room available + m_src_totaltime = 0; + m_src_time = 0; + if(cookable) + infotext = "Furnace is overloaded"; + else if(burning) + infotext = "Furnace is active"; + else + { + infotext = "Furnace is inactive"; + m_fuel_totaltime = 0; + m_fuel_time = 0; + } } - - //infostream<<"Furnace is out of fuel"<getList("fuel"); - assert(fuel_list); - const InventoryItem *fuel_item = fuel_list->getItem(0); + // Do this so it doesn't always show (0%) for weak fuel + if(m_fuel_totaltime > 3) { + infotext += " ("; + infotext += itos(m_fuel_time/m_fuel_totaltime*100); + infotext += "%)"; + } + + if(infotext != m_infotext) + { + m_infotext = infotext; + changed_this_loop = true; + } - if(fuel_item && fuel_item->getBurnTime() >= 0){ - m_fuel_totaltime = fuel_item->getBurnTime(); + if(burning && m_fuel_time >= m_fuel_totaltime) + { m_fuel_time = 0; - fuel_list->decrementMaterials(1); + m_fuel_totaltime = 0; + } + + if(changed_this_loop) + { changed = true; - } else { - //infostream<<"No fuel found"< items; + InventoryList *src_list = m_inventory->getList("src"); + assert(src_list); + items.push_back(src_list->getItem(0)); + + CraftInput ci(CRAFT_METHOD_COOKING, 1, items); + CraftOutput co; + bool found = m_gamedef->getCraftDefManager()->getCraftResult( + ci, co, remove, m_gamedef); + if(remove) + src_list->changeItem(0, ci.items[0]); + + cookresult = co.item; + cooktime = co.time; + return found; +} +bool FurnaceNodeMetadata::getBurnResult(bool remove, float &burntime) +{ + std::vector items; + InventoryList *fuel_list = m_inventory->getList("fuel"); + assert(fuel_list); + items.push_back(fuel_list->getItem(0)); + + CraftInput ci(CRAFT_METHOD_FUEL, 1, items); + CraftOutput co; + bool found = m_gamedef->getCraftDefManager()->getCraftResult( + ci, co, remove, m_gamedef); + if(remove) + fuel_list->changeItem(0, ci.items[0]); + + burntime = co.time; + return found; +} + + +/* + GenericNodeMetadata +*/ + +class GenericNodeMetadata : public NodeMetadata +{ +private: + Inventory *m_inventory; + std::string m_text; + std::string m_owner; + + std::string m_infotext; + std::string m_inventorydrawspec; + bool m_allow_text_input; + bool m_removal_disabled; + bool m_enforce_owner; + + bool m_inventory_modified; + bool m_text_modified; + + std::map m_stringvars; + +public: + u16 typeId() const + { + return NODEMETA_GENERIC; + } + const char* typeName() const + { + return "generic"; + } + + GenericNodeMetadata(IGameDef *gamedef): + NodeMetadata(gamedef), + + m_inventory(NULL), + m_text(""), + m_owner(""), + + m_infotext("GenericNodeMetadata"), + m_inventorydrawspec(""), + m_allow_text_input(false), + m_removal_disabled(false), + m_enforce_owner(false), + + m_inventory_modified(false), + m_text_modified(false) + { + NodeMetadata::registerType(typeId(), typeName(), create, create); + } + virtual ~GenericNodeMetadata() + { + delete m_inventory; + } + NodeMetadata* clone(IGameDef *gamedef) + { + GenericNodeMetadata *d = new GenericNodeMetadata(m_gamedef); + + d->m_inventory = new Inventory(*m_inventory); + d->m_text = m_text; + d->m_owner = m_owner; + + d->m_infotext = m_infotext; + d->m_inventorydrawspec = m_inventorydrawspec; + d->m_allow_text_input = m_allow_text_input; + d->m_removal_disabled = m_removal_disabled; + d->m_enforce_owner = m_enforce_owner; + d->m_inventory_modified = m_inventory_modified; + d->m_text_modified = m_text_modified; + return d; + } + static NodeMetadata* create(IGameDef *gamedef) + { + GenericNodeMetadata *d = new GenericNodeMetadata(gamedef); + d->m_inventory = new Inventory(gamedef->idef()); + return d; + } + static NodeMetadata* create(std::istream &is, IGameDef *gamedef) + { + GenericNodeMetadata *d = new GenericNodeMetadata(gamedef); + + d->m_inventory = new Inventory(gamedef->idef()); + d->m_inventory->deSerialize(is); + d->m_text = deSerializeLongString(is); + d->m_owner = deSerializeString(is); + + d->m_infotext = deSerializeString(is); + d->m_inventorydrawspec = deSerializeString(is); + d->m_allow_text_input = readU8(is); + d->m_removal_disabled = readU8(is); + d->m_enforce_owner = readU8(is); + + int num_vars = readU32(is); + for(int i=0; im_stringvars[name] = var; + } + return d; + } + void serializeBody(std::ostream &os) + { + m_inventory->serialize(os); + os<::iterator + i = m_stringvars.begin(); i != m_stringvars.end(); i++){ + os<first); + os<second); + } + } + + std::string infoText() + { + return m_infotext; + } + Inventory* getInventory() + { + return m_inventory; + } + void inventoryModified() + { + m_inventory_modified = true; + } + bool step(float dtime) + { + return false; + } + bool nodeRemovalDisabled() + { + return m_removal_disabled; + } + std::string getInventoryDrawSpecString() + { + return m_inventorydrawspec; + } + bool allowsTextInput() + { + return m_allow_text_input; + } + std::string getText() + { + return m_text; + } + void setText(const std::string &t) + { + m_text = t; + m_text_modified = true; + } + std::string getOwner() + { + if(m_enforce_owner) + return m_owner; + else + return ""; + } + void setOwner(std::string t) + { + m_owner = t; + } + + /* Interface for GenericNodeMetadata */ + + void setInfoText(const std::string &text) + { + infostream<<"GenericNodeMetadata::setInfoText(\"" + <::iterator i; + i = m_stringvars.find(name); + if(i == m_stringvars.end()) + return ""; + return i->second; + } +}; + +// Prototype +GenericNodeMetadata proto_GenericNodeMetadata(NULL);