changed node metadata format to better accomodate future needs and problems
authorPerttu Ahola <celeron55@gmail.com>
Mon, 4 Apr 2011 21:24:47 +0000 (00:24 +0300)
committerPerttu Ahola <celeron55@gmail.com>
Mon, 4 Apr 2011 21:24:47 +0000 (00:24 +0300)
12 files changed:
src/CMakeLists.txt
src/guiInventoryMenu.cpp
src/guiInventoryMenu.h
src/main.cpp
src/map.cpp
src/mapblock.cpp
src/mapnode.cpp
src/mapnode.h
src/modalMenu.h
src/nodemetadata.cpp
src/nodemetadata.h
src/server.cpp

index e414df33ae23f6c6b8ff26b499bd8478b03fd091..17eabcb91538cdef91bcdacc4005ebd849ad599a 100644 (file)
@@ -81,6 +81,7 @@ set(common_SRCS
 set(minetest_SRCS
        ${common_SRCS}
        clientobject.cpp
+       guiFurnaceMenu.cpp
        guiMainMenu.cpp
        guiMessageMenu.cpp
        guiTextInputMenu.cpp
index 2d20b24aac384e358396a815076007f137d8d74f..b83a84449043cd4e646863bede945805bb3b7a51 100644 (file)
@@ -80,15 +80,13 @@ GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env,
                gui::IGUIElement* parent, s32 id,
                IMenuManager *menumgr,
                v2s16 menu_size,
-               core::array<DrawSpec> &init_draw_spec,
                InventoryContext *c,
                InventoryManager *invmgr
                ):
        GUIModalMenu(env, parent, id, menumgr),
        m_menu_size(menu_size),
        m_c(c),
-       m_invmgr(invmgr),
-       m_init_draw_spec(init_draw_spec)
+       m_invmgr(invmgr)
 {
        m_selected_item = NULL;
 }
@@ -103,7 +101,7 @@ GUIInventoryMenu::~GUIInventoryMenu()
 
 void GUIInventoryMenu::removeChildren()
 {
-       /*const core::list<gui::IGUIElement*> &children = getChildren();
+       const core::list<gui::IGUIElement*> &children = getChildren();
        core::list<gui::IGUIElement*> children_copy;
        for(core::list<gui::IGUIElement*>::ConstIterator
                        i = children.begin(); i != children.end(); i++)
@@ -115,12 +113,12 @@ void GUIInventoryMenu::removeChildren()
                        i != children_copy.end(); i++)
        {
                (*i)->remove();
-       }*/
-       {
+       }
+       /*{
                gui::IGUIElement *e = getElementFromId(256);
                if(e != NULL)
                        e->remove();
-       }
+       }*/
 }
 
 void GUIInventoryMenu::regenerateGui(v2u32 screensize)
@@ -326,6 +324,10 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
                                                        inv_from->getList(m_selected_item->listname);
                                        InventoryList *list_to =
                                                        inv_to->getList(s.listname);
+                                       if(list_from == NULL)
+                                               dstream<<"from list doesn't exist"<<std::endl;
+                                       if(list_to == NULL)
+                                               dstream<<"to list doesn't exist"<<std::endl;
                                        // Indicates whether source slot completely empties
                                        bool source_empties = false;
                                        if(list_from && list_to
index acddb5c24866b5f1c69d0277947042bc5486c3ff..10fb7a4250dd11ff0403cd0b0eaff27547a882df 100644 (file)
@@ -107,12 +107,16 @@ public:
                        gui::IGUIElement* parent, s32 id,
                        IMenuManager *menumgr,
                        v2s16 menu_size,
-                       core::array<DrawSpec> &init_draw_spec,
                        InventoryContext *c,
                        InventoryManager *invmgr
                        );
        ~GUIInventoryMenu();
 
+       void setDrawSpec(core::array<DrawSpec> &init_draw_spec)
+       {
+               m_init_draw_spec = init_draw_spec;
+       }
+
        void removeChildren();
        /*
                Remove and re-add (or reposition) stuff
@@ -125,7 +129,7 @@ public:
 
        bool OnEvent(const SEvent& event);
        
-private:
+protected:
        v2s32 getBasePos() const
        {
                return padding + AbsoluteRect.UpperLeftCorner;
index df5bca21ee24ba944d65f4b431b2216ba6bf916e..7ec542533782efdfd09c9e1977ab0641e793cbf9 100644 (file)
@@ -180,6 +180,10 @@ SUGG: Don't update all meshes always on single node changes, but
 \r
 TODO: Remove IrrlichtWrapper\r
 \r
+SUGG: Add a "description" field to InventoryList and show it in\r
+      GUIInventoryMenu\r
+         - If separate menus are made for everything, this is not needed\r
+\r
 Server:\r
 -------\r
 \r
@@ -332,6 +336,7 @@ Making it more portable:
 #include "mineral.h"\r
 #include "noise.h"\r
 #include "tile.h"\r
+#include "guiFurnaceMenu.h"\r
 \r
 // TODO: Remove this\r
 IrrlichtWrapper *g_irrlicht = NULL;\r
@@ -626,6 +631,12 @@ public:
                                                dstream<<DTIME<<"MyEventReceiver: "\r
                                                                <<"Launching inventory"<<std::endl;\r
                                                \r
+                                               GUIInventoryMenu *menu =\r
+                                                       new GUIInventoryMenu(guienv, guiroot, -1,\r
+                                                               &g_menumgr, v2s16(8,7),\r
+                                                               g_client->getInventoryContext(),\r
+                                                               g_client);\r
+\r
                                                core::array<GUIInventoryMenu::DrawSpec> draw_spec;\r
                                                draw_spec.push_back(GUIInventoryMenu::DrawSpec(\r
                                                                "list", "current_player", "main",\r
@@ -637,11 +648,7 @@ public:
                                                                "list", "current_player", "craftresult",\r
                                                                v2s32(7, 1), v2s32(1, 1)));\r
 \r
-                                               GUIInventoryMenu *menu =\r
-                                                       new GUIInventoryMenu(guienv, guiroot, -1,\r
-                                                               &g_menumgr, v2s16(8,7), draw_spec,\r
-                                                               g_client->getInventoryContext(),\r
-                                                               g_client);\r
+                                               menu->setDrawSpec(draw_spec);\r
 \r
                                                menu->drop();\r
 \r
@@ -2994,8 +3001,6 @@ int main(int argc, char *argv[])
                                        \r
                                        //ChestNodeMetadata *chestmeta = (ChestNodeMetadata*)meta;\r
 \r
-                                       core::array<GUIInventoryMenu::DrawSpec> draw_spec;\r
-                                       \r
                                        std::string chest_inv_id;\r
                                        chest_inv_id += "nodemeta:";\r
                                        chest_inv_id += itos(nodepos.X);\r
@@ -3004,6 +3009,14 @@ int main(int argc, char *argv[])
                                        chest_inv_id += ",";\r
                                        chest_inv_id += itos(nodepos.Z);\r
                                        \r
+                                       GUIInventoryMenu *menu =\r
+                                               new GUIInventoryMenu(guienv, guiroot, -1,\r
+                                                       &g_menumgr, v2s16(8,9),\r
+                                                       g_client->getInventoryContext(),\r
+                                                       g_client);\r
+\r
+                                       core::array<GUIInventoryMenu::DrawSpec> draw_spec;\r
+                                       \r
                                        draw_spec.push_back(GUIInventoryMenu::DrawSpec(\r
                                                        "list", chest_inv_id, "0",\r
                                                        v2s32(0, 0), v2s32(8, 4)));\r
@@ -3011,11 +3024,18 @@ int main(int argc, char *argv[])
                                                        "list", "current_player", "main",\r
                                                        v2s32(0, 5), v2s32(8, 4)));\r
 \r
-                                       GUIInventoryMenu *menu =\r
-                                               new GUIInventoryMenu(guienv, guiroot, -1,\r
-                                                       &g_menumgr, v2s16(8,9), draw_spec,\r
-                                                       g_client->getInventoryContext(),\r
-                                                       g_client);\r
+                                       menu->setDrawSpec(draw_spec);\r
+\r
+                                       menu->drop();\r
+\r
+                               }\r
+                               else if(meta && meta->typeId() == CONTENT_FURNACE && !random_input)\r
+                               {\r
+                                       dstream<<"Furnace node right-clicked"<<std::endl;\r
+                                       \r
+                                       GUIFurnaceMenu *menu =\r
+                                               new GUIFurnaceMenu(guienv, guiroot, -1,\r
+                                                       &g_menumgr, nodepos, g_client);\r
 \r
                                        menu->drop();\r
 \r
index d644215be78911de0d56af9825eb684e98d94d3d..f6115a62a9fd84ea9be827576bb641843c12f9de 100644 (file)
@@ -5192,14 +5192,14 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
 {
        DSTACK(__FUNCTION_NAME);
 
+       // Block file is map/sectors/xxxxxxxx/xxxx
+       std::string fullpath = m_savedir+"/sectors/"+sectordir+"/"+blockfile;
        try{
 
-               // Block file is map/sectors/xxxxxxxx/xxxx
-               std::string fullpath = m_savedir+"/sectors/"+sectordir+"/"+blockfile;
                std::ifstream is(fullpath.c_str(), std::ios_base::binary);
                if(is.good() == false)
                        throw FileNotGoodException("Cannot open block file");
-
+               
                v3s16 p3d = getBlockPos(sectordir, blockfile);
                v2s16 p2d(p3d.X, p3d.Z);
                
@@ -5264,6 +5264,8 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
                                "(SerializationError). Ignoring. "
                                "A new one will be generated."
                                <<std::endl;
+
+               // TODO: Backup file; name is in fullpath.
        }
 }
 
index efa760f0e6fbdea57894322f5187cb80a983b328..a4e13320e261400ec878f3d339a7eaf0e33ac600 100644 (file)
@@ -1922,7 +1922,9 @@ void MapBlock::serialize(std::ostream &os, u8 version)
                */
                if(version >= 14)
                {
-                       m_node_metadata.serialize(os);
+                       std::ostringstream oss(std::ios_base::binary);
+                       m_node_metadata.serialize(oss);
+                       os<<serializeString(oss.str());
                }
        }
 }
@@ -2043,7 +2045,17 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
                */
                if(version >= 14)
                {
-                       m_node_metadata.deSerialize(is);
+                       // Ignore errors
+                       try{
+                               std::string data = deSerializeString(is);
+                               std::istringstream iss(data, std::ios_base::binary);
+                               m_node_metadata.deSerialize(iss);
+                       }
+                       catch(SerializationError &e)
+                       {
+                               dstream<<"WARNING: MapBlock::deSerialize(): Ignoring an error"
+                                               <<" while deserializing node metadata"<<std::endl;
+                       }
                }
        }
        
index f498d9e75548a7b5a59b36db843948db9c160e31..8e968c81120b5b29559c838c2a7708f47a0c6922 100644 (file)
@@ -321,6 +321,8 @@ void init_mapnode()
        f->setTexture(5, "furnace_front.png"); // Z-
        f->setInventoryTexture("furnace_front.png");
        f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
+       if(f->initial_metadata == NULL)
+               f->initial_metadata = new FurnaceNodeMetadata();
        
 }
 
index 2843208a9050cf763d9e25ff1a341b00fdbfc42a..ce233e8e39e4c87a5321a1e95d6b8a6312d46661 100644 (file)
@@ -98,6 +98,7 @@ void init_content_inventory_texture_paths();
 #define CONTENT_SIGN_WALL 14
 #define CONTENT_CHEST 15
 #define CONTENT_FURNACE 16
+//#define CONTENT_WORKBENCH 17
 
 /*
        Content feature list
index ebbb06cfe0f8cde56acaa6a55067f532418ced40..1f6d4d897dfe6126d0a69a8c375c50a4188edaab 100644 (file)
@@ -46,6 +46,8 @@ public:
                IGUIElement(gui::EGUIET_ELEMENT, env, parent, id,
                                core::rect<s32>(0,0,100,100))
        {
+               //m_force_regenerate_gui = false;
+               
                m_menumgr = menumgr;
                m_allow_focus_removal = false;
                m_screensize_old = v2u32(0,0);
@@ -76,10 +78,11 @@ public:
                        
                video::IVideoDriver* driver = Environment->getVideoDriver();
                v2u32 screensize = driver->getScreenSize();
-               if(screensize != m_screensize_old)
+               if(screensize != m_screensize_old /*|| m_force_regenerate_gui*/)
                {
                        m_screensize_old = screensize;
                        regenerateGui(screensize);
+                       //m_force_regenerate_gui = false;
                }
 
                drawMenu();
@@ -119,7 +122,9 @@ public:
        virtual void regenerateGui(v2u32 screensize) = 0;
        virtual void drawMenu() = 0;
        virtual bool OnEvent(const SEvent& event) { return false; };
-       
+
+protected:
+       //bool m_force_regenerate_gui;
 private:
        IMenuManager *m_menumgr;
        // This might be necessary to expose to the implementation if it
index 294db178f240f7e0d19f018764bed7dcb8e0c480..2405e7601ea7d42c5b0c67840164323ec8ba5d40 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)
@@ -144,10 +165,56 @@ std::string ChestNodeMetadata::infoText()
 {
        return "Chest";
 }
-/*Inventory* ChestNodeMetadata::getInventory()
+
+/*
+       FurnaceNodeMetadata
+*/
+
+FurnaceNodeMetadata::FurnaceNodeMetadata()
 {
-       return m_inventory;
-}*/
+       NodeMetadata::registerType(typeId(), create);
+       
+       m_inventory = new Inventory();
+       m_inventory->addList("fuel", 1);
+       m_inventory->addList("src", 1);
+       m_inventory->addList("dst", 1);
+}
+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);
+       /*std::string params;
+       std::getline(is, params, '\n');*/
+       return d;
+}
+void FurnaceNodeMetadata::serializeBody(std::ostream &os)
+{
+       m_inventory->serialize(os);
+       // This line will contain the other parameters
+       //os<<"\n";
+}
+std::string FurnaceNodeMetadata::infoText()
+{
+       return "Furnace";
+}
+void FurnaceNodeMetadata::inventoryModified()
+{
+       dstream<<"Furnace inventory modification callback"<<std::endl;
+}
 
 /*
        NodeMetadatalist
@@ -197,17 +264,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);
        }
 }
index 8877c266760fb96cbf7d34dd743c2fd9b041bec2..e8aa57622d51a1706e9e278331134796e8abcafc 100644 (file)
@@ -56,6 +56,9 @@ public:
        virtual void serializeBody(std::ostream &os) = 0;
        virtual std::string infoText() {return "<todo: remove this text>";}
        virtual Inventory* getInventory() {return NULL;}
+       // This is called always after the inventory is modified, before
+       // the changes are copied elsewhere
+       virtual void inventoryModified(){}
 
 protected:
        static void registerType(u16 id, Factory f);
@@ -99,6 +102,28 @@ private:
        Inventory *m_inventory;
 };
 
+class FurnaceNodeMetadata : public NodeMetadata
+{
+public:
+       FurnaceNodeMetadata();
+       ~FurnaceNodeMetadata();
+       
+       virtual u16 typeId() const;
+       virtual NodeMetadata* clone();
+       static NodeMetadata* create(std::istream &is);
+       virtual void serializeBody(std::ostream &os);
+       virtual std::string infoText();
+       virtual Inventory* getInventory() {return m_inventory;}
+       virtual void inventoryModified();
+
+private:
+       Inventory *m_inventory;
+};
+
+/*
+       List of metadata of all the nodes of a block
+*/
+
 class NodeMetadataList
 {
 public:
index 7266a6ddfe6c268d4143462bffbe1cd8bb2633a8..df712e07f9164d6dc3a5f893253bd74987585830 100644 (file)
@@ -2743,8 +2743,9 @@ void Server::inventoryModified(InventoryContext *c, std::string id)
                assert(c->current_player);
                v3s16 blockpos = getNodeBlockPos(p);
 
-               /*RemoteClient *client = getClient(c->current_player->peer_id);
-               client->SetBlockNotSent(blockpos);*/
+               NodeMetadata *meta = m_env.getMap().getNodeMetadata(p);
+               if(meta)
+                       meta->inventoryModified();
 
                for(core::map<u16, RemoteClient*>::Iterator
                        i = m_clients.getIterator();