]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/nodemetadata.cpp
disable tiling of textures only if smooth lighting is used
[dragonfireclient.git] / src / nodemetadata.cpp
index 294db178f240f7e0d19f018764bed7dcb8e0c480..308a3385432a5126ee6e4010158e24dbd4f6bdda 100644 (file)
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapnode.h"
 #include "exceptions.h"
 #include "inventory.h"
+#include <sstream>
 
 /*
        NodeMetadata
@@ -39,21 +40,39 @@ NodeMetadata::~NodeMetadata()
 
 NodeMetadata* NodeMetadata::deSerialize(std::istream &is)
 {
+       // Read id
        u8 buf[2];
        is.read((char*)buf, 2);
        s16 id = readS16(buf);
-
+       
+       // Read data
+       std::string data = deSerializeString(is);
+       
+       // Find factory function
        core::map<u16, Factory>::Node *n;
        n = m_types.find(id);
        if(n == NULL)
        {
-               dstream<<"NodeMetadata(): No factory for typeId="<<id<<std::endl;
-               throw SerializationError("Unknown metadata id");
+               // If factory is not found, just return.
+               dstream<<"WARNING: NodeMetadata: No factory for typeId="
+                               <<id<<std::endl;
+               return NULL;
        }
        
-       Factory f = n->getValue();
-       NodeMetadata *meta = (*f)(is);
-       return meta;
+       // Try to load the metadata. If it fails, just return.
+       try
+       {
+               std::istringstream iss(data, std::ios_base::binary);
+               
+               Factory f = n->getValue();
+               NodeMetadata *meta = (*f)(iss);
+               return meta;
+       }
+       catch(SerializationError &e)
+       {
+               dstream<<"WARNING: NodeMetadata: ignoring SerializationError"<<std::endl;
+               return NULL;
+       }
 }
 
 void NodeMetadata::serialize(std::ostream &os)
@@ -61,8 +80,10 @@ void NodeMetadata::serialize(std::ostream &os)
        u8 buf[2];
        writeU16(buf, typeId());
        os.write((char*)buf, 2);
-
-       serializeBody(os);
+       
+       std::ostringstream oss(std::ios_base::binary);
+       serializeBody(oss);
+       os<<serializeString(oss.str());
 }
 
 void NodeMetadata::registerType(u16 id, Factory f)
@@ -78,6 +99,9 @@ void NodeMetadata::registerType(u16 id, Factory f)
        SignNodeMetadata
 */
 
+// Prototype
+SignNodeMetadata proto_SignNodeMetadata("");
+
 SignNodeMetadata::SignNodeMetadata(std::string text):
        m_text(text)
 {
@@ -109,6 +133,9 @@ std::string SignNodeMetadata::infoText()
        ChestNodeMetadata
 */
 
+// Prototype
+ChestNodeMetadata proto_ChestNodeMetadata;
+
 ChestNodeMetadata::ChestNodeMetadata()
 {
        NodeMetadata::registerType(typeId(), create);
@@ -144,10 +171,190 @@ std::string ChestNodeMetadata::infoText()
 {
        return "Chest";
 }
-/*Inventory* ChestNodeMetadata::getInventory()
+bool ChestNodeMetadata::nodeRemovalDisabled()
 {
-       return m_inventory;
-}*/
+       /*
+               Disable removal if chest contains something
+       */
+       InventoryList *list = m_inventory->getList("0");
+       if(list == NULL)
+               return false;
+       if(list->getUsedSlots() == 0)
+               return false;
+       return true;
+}
+
+/*
+       FurnaceNodeMetadata
+*/
+
+// Prototype
+FurnaceNodeMetadata proto_FurnaceNodeMetadata;
+
+FurnaceNodeMetadata::FurnaceNodeMetadata()
+{
+       NodeMetadata::registerType(typeId(), create);
+       
+       m_inventory = new Inventory();
+       m_inventory->addList("fuel", 1);
+       m_inventory->addList("src", 1);
+       m_inventory->addList("dst", 4);
+
+       m_step_accumulator = 0;
+       m_fuel_totaltime = 0;
+       m_fuel_time = 0;
+       m_src_totaltime = 0;
+       m_src_time = 0;
+}
+FurnaceNodeMetadata::~FurnaceNodeMetadata()
+{
+       delete m_inventory;
+}
+u16 FurnaceNodeMetadata::typeId() const
+{
+       return CONTENT_FURNACE;
+}
+NodeMetadata* FurnaceNodeMetadata::clone()
+{
+       FurnaceNodeMetadata *d = new FurnaceNodeMetadata();
+       *d->m_inventory = *m_inventory;
+       return d;
+}
+NodeMetadata* FurnaceNodeMetadata::create(std::istream &is)
+{
+       FurnaceNodeMetadata *d = new FurnaceNodeMetadata();
+
+       d->m_inventory->deSerialize(is);
+
+       int temp;
+       is>>temp;
+       d->m_fuel_totaltime = (float)temp/10;
+       is>>temp;
+       d->m_fuel_time = (float)temp/10;
+
+       return d;
+}
+void FurnaceNodeMetadata::serializeBody(std::ostream &os)
+{
+       m_inventory->serialize(os);
+       os<<itos(m_fuel_totaltime*10)<<" ";
+       os<<itos(m_fuel_time*10)<<" ";
+}
+std::string FurnaceNodeMetadata::infoText()
+{
+       //return "Furnace";
+       if(m_fuel_time >= m_fuel_totaltime)
+       {
+               InventoryList *src_list = m_inventory->getList("src");
+               assert(src_list);
+               InventoryItem *src_item = src_list->getItem(0);
+
+               if(src_item)
+                       return "Furnace is out of fuel";
+               else
+                       return "Furnace is inactive";
+       }
+       else
+       {
+               std::string s = "Furnace is active (";
+               s += itos(m_fuel_time/m_fuel_totaltime*100);
+               s += "%)";
+               return s;
+       }
+}
+void FurnaceNodeMetadata::inventoryModified()
+{
+       dstream<<"Furnace inventory modification callback"<<std::endl;
+}
+bool FurnaceNodeMetadata::step(float dtime)
+{
+       // Update at a fixed frequency
+       const float interval = 0.5;
+       m_step_accumulator += dtime;
+       if(m_step_accumulator < interval)
+               return false;
+       m_step_accumulator -= interval;
+       dtime = interval;
+
+       //dstream<<"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);
+       
+       // Start only if there are free slots in dst, so that it can
+       // accomodate any result item
+       if(dst_list->getFreeSlots() > 0 && src_item && src_item->isCookable())
+       {
+               m_src_totaltime = 3;
+       }
+       else
+       {
+               m_src_time = 0;
+               m_src_totaltime = 0;
+       }
+
+       if(m_fuel_time < m_fuel_totaltime)
+       {
+               //dstream<<"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)
+               {
+                       InventoryItem *cookresult = src_item->createCookResult();
+                       dst_list->addItem(cookresult);
+                       src_list->decrementMaterials(1);
+                       m_src_time = 0;
+                       m_src_totaltime = 0;
+               }
+               return true;
+       }
+       
+       if(src_item == NULL || m_src_totaltime < 0.001)
+       {
+               return false;
+       }
+       
+       bool changed = false;
+
+       //dstream<<"Furnace is out of fuel"<<std::endl;
+
+       InventoryList *fuel_list = m_inventory->getList("fuel");
+       assert(fuel_list);
+       InventoryItem *fuel_item = fuel_list->getItem(0);
+
+       if(ItemSpec(ITEM_MATERIAL, CONTENT_TREE).checkItem(fuel_item))
+       {
+               m_fuel_totaltime = 10;
+               m_fuel_time = 0;
+               fuel_list->decrementMaterials(1);
+               changed = true;
+       }
+       else if(ItemSpec(ITEM_MATERIAL, CONTENT_WOOD).checkItem(fuel_item))
+       {
+               m_fuel_totaltime = 5;
+               m_fuel_time = 0;
+               fuel_list->decrementMaterials(1);
+               changed = true;
+       }
+       else if(ItemSpec(ITEM_CRAFT, "lump_of_coal").checkItem(fuel_item))
+       {
+               m_fuel_totaltime = 10;
+               m_fuel_time = 0;
+               fuel_list->decrementMaterials(1);
+               changed = true;
+       }
+       else
+       {
+               //dstream<<"No fuel found"<<std::endl;
+       }
+
+       return changed;
+}
 
 /*
        NodeMetadatalist
@@ -157,6 +364,10 @@ void NodeMetadataList::serialize(std::ostream &os)
 {
        u8 buf[6];
        
+       u16 version = 1;
+       writeU16(buf, version);
+       os.write((char*)buf, 2);
+
        u16 count = m_data.size();
        writeU16(buf, count);
        os.write((char*)buf, 2);
@@ -182,6 +393,16 @@ void NodeMetadataList::deSerialize(std::istream &is)
 
        u8 buf[6];
        
+       is.read((char*)buf, 2);
+       u16 version = readU16(buf);
+
+       if(version > 1)
+       {
+               dstream<<__FUNCTION_NAME<<": version "<<version<<" not supported"
+                               <<std::endl;
+               throw SerializationError("NodeMetadataList::deSerialize");
+       }
+       
        is.read((char*)buf, 2);
        u16 count = readU16(buf);
        
@@ -197,17 +418,21 @@ void NodeMetadataList::deSerialize(std::istream &is)
                p16 -= p.Y * MAP_BLOCKSIZE;
                p.X += p16;
                
+               NodeMetadata *data = NodeMetadata::deSerialize(is);
+
+               if(data == NULL)
+                       continue;
+               
                if(m_data.find(p))
                {
-                       dstream<<"ERROR: NodeMetadataList::deSerialize(): "
+                       dstream<<"WARNING: NodeMetadataList::deSerialize(): "
                                        <<"already set data at position"
-                                       <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
+                                       <<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
                                        <<std::endl;
-                       throw SerializationError("NodeMetadataList::deSerialize()");
+                       delete data;
+                       continue;
                }
 
-               NodeMetadata *data = NodeMetadata::deSerialize(is);
-               
                m_data.insert(p, data);
        }
 }
@@ -247,3 +472,32 @@ void NodeMetadataList::set(v3s16 p, NodeMetadata *d)
        m_data.insert(p, d);
 }
 
+bool NodeMetadataList::step(float dtime)
+{
+       bool something_changed = false;
+       for(core::map<v3s16, NodeMetadata*>::Iterator
+                       i = m_data.getIterator();
+                       i.atEnd()==false; i++)
+       {
+               v3s16 p = i.getNode()->getKey();
+               NodeMetadata *meta = i.getNode()->getValue();
+               bool changed = meta->step(dtime);
+               if(changed)
+                       something_changed = true;
+               /*if(res.inventory_changed)
+               {
+                       std::string inv_id;
+                       inv_id += "nodemeta:";
+                       inv_id += itos(p.X);
+                       inv_id += ",";
+                       inv_id += itos(p.Y);
+                       inv_id += ",";
+                       inv_id += itos(p.Z);
+                       InventoryContext c;
+                       c.current_player = NULL;
+                       inv_mgr->inventoryModified(&c, inv_id);
+               }*/
+       }
+       return something_changed;
+}
+