aboutsummaryrefslogtreecommitdiff
path: root/src/content_nodemeta.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/content_nodemeta.cpp')
-rw-r--r--src/content_nodemeta.cpp287
1 files changed, 179 insertions, 108 deletions
diff --git a/src/content_nodemeta.cpp b/src/content_nodemeta.cpp
index 8666051a4..9fb5450cf 100644
--- a/src/content_nodemeta.cpp
+++ b/src/content_nodemeta.cpp
@@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "inventory.h"
#include "log.h"
#include "utility.h"
+#include "craftdef.h"
+#include "gamedef.h"
class Inventory;
@@ -125,9 +127,14 @@ public:
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;
@@ -185,9 +192,7 @@ ChestNodeMetadata::ChestNodeMetadata(IGameDef *gamedef):
NodeMetadata(gamedef)
{
NodeMetadata::registerType(typeId(), typeName(), create, create);
-
- m_inventory = new Inventory();
- m_inventory->addList("0", 8*4);
+ m_inventory = NULL;
}
ChestNodeMetadata::~ChestNodeMetadata()
{
@@ -200,18 +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)
@@ -253,9 +261,7 @@ LockingChestNodeMetadata::LockingChestNodeMetadata(IGameDef *gamedef):
NodeMetadata(gamedef)
{
NodeMetadata::registerType(typeId(), typeName(), create, create);
-
- m_inventory = new Inventory();
- m_inventory->addList("0", 8*4);
+ m_inventory = NULL;
}
LockingChestNodeMetadata::~LockingChestNodeMetadata()
{
@@ -269,18 +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)
@@ -324,10 +333,9 @@ FurnaceNodeMetadata::FurnaceNodeMetadata(IGameDef *gamedef):
{
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;
@@ -346,26 +354,52 @@ 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)
@@ -373,36 +407,13 @@ void FurnaceNodeMetadata::serializeBody(std::ostream &os)
m_inventory->serialize(os);
os<<itos(m_fuel_totaltime*10)<<" ";
os<<itos(m_fuel_time*10)<<" ";
+ os<<itos(m_src_totaltime*10)<<" ";
+ os<<itos(m_src_time*10)<<" ";
+ os<<serializeJsonString(m_infotext);
}
std::string FurnaceNodeMetadata::infoText()
{
- //return "Furnace";
- if(m_fuel_time >= 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()
{
@@ -440,86 +451,107 @@ bool FurnaceNodeMetadata::step(float dtime)
dtime = interval;
//infostream<<"Furnace step dtime="<<dtime<<std::endl;
-
+
InventoryList *dst_list = m_inventory->getList("dst");
assert(dst_list);
- InventoryList *src_list = m_inventory->getList("src");
- assert(src_list);
- InventoryItem *src_item = src_list->getItem(0);
-
+ // 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 = 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"<<std::endl;
- m_fuel_time += dtime;
- m_src_time += dtime;
- if(m_src_time >= m_src_totaltime && m_src_totaltime > 0.001
- && src_item)
+ float burntime;
+ if(burning)
+ {
+ changed = true;
+ m_src_time += dtime;
+ m_src_totaltime = cooktime;
+ infotext = "Furnace is cooking";
+ }
+ else if(getBurnResult(true, burntime))
+ {
+ // Fuel inserted
+ changed = 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 = 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;
+ }
+ }
+
+ // 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 += "%)";
}
-
- //infostream<<"Furnace is out of fuel"<<std::endl;
- InventoryList *fuel_list = m_inventory->getList("fuel");
- assert(fuel_list);
- const InventoryItem *fuel_item = fuel_list->getItem(0);
+ if(infotext != m_infotext)
+ {
+ m_infotext = infotext;
+ changed = 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);
- changed = true;
- } else {
- //infostream<<"No fuel found"<<std::endl;
- // No fuel, stop loop.
+ m_fuel_totaltime = 0;
+ }
+
+ if(!changed)
+ {
m_step_accumulator = 0;
break;
}
@@ -535,6 +567,43 @@ std::string FurnaceNodeMetadata::getInventoryDrawSpecString()
"list[current_name;dst;5,1;2,2;]"
"list[current_player;main;0,5;8,4;]";
}
+bool FurnaceNodeMetadata::getCookResult(bool remove,
+ std::string &cookresult, float &cooktime)
+{
+ std::vector<ItemStack> 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<ItemStack> 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
@@ -571,7 +640,7 @@ public:
GenericNodeMetadata(IGameDef *gamedef):
NodeMetadata(gamedef),
- m_inventory(new Inventory()),
+ m_inventory(NULL),
m_text(""),
m_owner(""),
@@ -594,7 +663,7 @@ public:
{
GenericNodeMetadata *d = new GenericNodeMetadata(m_gamedef);
- *d->m_inventory = *m_inventory;
+ d->m_inventory = new Inventory(*m_inventory);
d->m_text = m_text;
d->m_owner = m_owner;
@@ -610,13 +679,15 @@ public:
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->deSerialize(is, gamedef);
+ d->m_inventory = new Inventory(gamedef->idef());
+ d->m_inventory->deSerialize(is);
d->m_text = deSerializeLongString(is);
d->m_owner = deSerializeString(is);