Chests work now!
authorPerttu Ahola <celeron55@gmail.com>
Mon, 4 Apr 2011 12:13:19 +0000 (15:13 +0300)
committerPerttu Ahola <celeron55@gmail.com>
Mon, 4 Apr 2011 12:13:19 +0000 (15:13 +0300)
17 files changed:
data/chest_front.png [new file with mode: 0644]
data/chest_side.png [new file with mode: 0644]
data/chest_top.png [new file with mode: 0644]
data/furnace_front.png [new file with mode: 0644]
data/furnace_side.png [new file with mode: 0644]
data/sign_wall.png [new file with mode: 0644]
src/client.cpp
src/client.h
src/guiInventoryMenu.cpp
src/guiInventoryMenu.h
src/inventory.cpp
src/inventory.h
src/main.cpp
src/nodemetadata.cpp
src/nodemetadata.h
src/server.cpp
src/server.h

diff --git a/data/chest_front.png b/data/chest_front.png
new file mode 100644 (file)
index 0000000..c5628af
Binary files /dev/null and b/data/chest_front.png differ
diff --git a/data/chest_side.png b/data/chest_side.png
new file mode 100644 (file)
index 0000000..916dd78
Binary files /dev/null and b/data/chest_side.png differ
diff --git a/data/chest_top.png b/data/chest_top.png
new file mode 100644 (file)
index 0000000..58c7967
Binary files /dev/null and b/data/chest_top.png differ
diff --git a/data/furnace_front.png b/data/furnace_front.png
new file mode 100644 (file)
index 0000000..1620a27
Binary files /dev/null and b/data/furnace_front.png differ
diff --git a/data/furnace_side.png b/data/furnace_side.png
new file mode 100644 (file)
index 0000000..63cb162
Binary files /dev/null and b/data/furnace_side.png differ
diff --git a/data/sign_wall.png b/data/sign_wall.png
new file mode 100644 (file)
index 0000000..06eac1e
Binary files /dev/null and b/data/sign_wall.png differ
index 2fb14cb6810cb50b909e3a6a4aefbfc1c87a27c1..ae0e027c2dea52acd81b26bc02de76f86a752fee 100644 (file)
@@ -106,6 +106,9 @@ Client::Client(
                player->updateName(playername);
 
                m_env.addPlayer(player);
+               
+               // Initialize player in the inventory context
+               m_inventory_context.current_player = player;
        }
 }
 
@@ -1862,6 +1865,44 @@ void Client::getLocalInventory(Inventory &dst)
        dst = player->inventory;
 }
 
+InventoryContext *Client::getInventoryContext()
+{
+       return &m_inventory_context;
+}
+
+Inventory* Client::getInventory(InventoryContext *c, std::string id)
+{
+       if(id == "current_player")
+       {
+               assert(c->current_player);
+               return &(c->current_player->inventory);
+       }
+       
+       Strfnd fn(id);
+       std::string id0 = fn.next(":");
+
+       if(id0 == "nodemeta")
+       {
+               v3s16 p;
+               p.X = stoi(fn.next(","));
+               p.Y = stoi(fn.next(","));
+               p.Z = stoi(fn.next(","));
+               NodeMetadata* meta = getNodeMetadata(p);
+               if(meta)
+                       return meta->getInventory();
+               dstream<<"nodemeta at ("<<p.X<<","<<p.Y<<","<<p.Z<<"): "
+                               <<"no metadata found"<<std::endl;
+               return NULL;
+       }
+
+       dstream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
+       return NULL;
+}
+void Client::inventoryAction(InventoryAction *a)
+{
+       sendInventoryAction(a);
+}
+
 MapBlockObject * Client::getSelectedObject(
                f32 max_d,
                v3f from_pos_f_on_map,
index fdb98d28d5b485dbe218369c9e71c560361ad693..611116d45b8b4cb6b10db0c770bc720a204b5e2c 100644 (file)
@@ -224,7 +224,7 @@ struct IncomingPacket
 };
 #endif
 
-class Client : public con::PeerHandler
+class Client : public con::PeerHandler, public InventoryManager
 {
 public:
        /*
@@ -303,6 +303,11 @@ public:
        // Copies the inventory of the local player to parameter
        void getLocalInventory(Inventory &dst);
        
+       InventoryContext *getInventoryContext();
+
+       Inventory* getInventory(InventoryContext *c, std::string id);
+       void inventoryAction(InventoryAction *a);
+
        // Gets closest object pointed by the shootline
        // Returns NULL if not found
        MapBlockObject * getSelectedObject(
@@ -438,6 +443,8 @@ private:
        
        // The seed returned by the server in TOCLIENT_INIT is stored here
        u64 m_map_seed;
+       
+       InventoryContext m_inventory_context;
 };
 
 #endif // !SERVER
index ef795a5f43be32dd100a7766ca59dd0b3cf56aea..2d20b24aac384e358396a815076007f137d8d74f 100644 (file)
@@ -78,18 +78,19 @@ void drawInventoryItem(video::IVideoDriver *driver,
 
 GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env,
                gui::IGUIElement* parent, s32 id,
-               Inventory *inventory,
-               Queue<InventoryAction*> *actions,
-               IMenuManager *menumgr):
-       GUIModalMenu(env, parent, id, menumgr)
+               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_inventory = inventory;
        m_selected_item = NULL;
-       m_actions = actions;
-
-       /*m_selected_item = new ItemSpec;
-       m_selected_item->listname = "main";
-       m_selected_item->i = 3;*/
 }
 
 GUIInventoryMenu::~GUIInventoryMenu()
@@ -102,6 +103,19 @@ GUIInventoryMenu::~GUIInventoryMenu()
 
 void GUIInventoryMenu::removeChildren()
 {
+       /*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++)
+       {
+               children_copy.push_back(*i);
+       }
+       for(core::list<gui::IGUIElement*>::Iterator
+                       i = children_copy.begin();
+                       i != children_copy.end(); i++)
+       {
+               (*i)->remove();
+       }*/
        {
                gui::IGUIElement *e = getElementFromId(256);
                if(e != NULL)
@@ -114,15 +128,19 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize)
        // Remove children
        removeChildren();
        
-       padding = v2s32(24,24);
+       /*padding = v2s32(24,24);
        spacing = v2s32(60,56);
-       imgsize = v2s32(48,48);
+       imgsize = v2s32(48,48);*/
+
+       padding = v2s32(screensize.X/48, screensize.X/48);
+       spacing = v2s32(screensize.X/16, screensize.X/17);
+       imgsize = v2s32(screensize.X/20, screensize.X/20);
 
        s32 helptext_h = 15;
 
        v2s32 size(
-               padding.X*2+spacing.X*(8-1)+imgsize.X,
-               padding.Y*2+spacing.Y*(7-1)+imgsize.Y + helptext_h
+               padding.X*2+spacing.X*(m_menu_size.X-1)+imgsize.X,
+               padding.Y*2+spacing.Y*(m_menu_size.Y-1)+imgsize.Y + helptext_h
        );
 
        core::rect<s32> rect(
@@ -137,13 +155,27 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize)
 
        v2s32 basepos = getBasePos();
        
-       m_draw_positions.clear();
-       m_draw_positions.push_back(ListDrawSpec("main",
+       m_draw_spec.clear();
+       for(u16 i=0; i<m_init_draw_spec.size(); i++)
+       {
+               DrawSpec &s = m_init_draw_spec[i];
+               if(s.type == "list")
+               {
+                       m_draw_spec.push_back(ListDrawSpec(s.name, s.subname,
+                                       basepos + v2s32(spacing.X*s.pos.X, spacing.Y*s.pos.Y),
+                                       s.geom));
+               }
+       }
+
+       /*
+       m_draw_spec.clear();
+       m_draw_spec.push_back(ListDrawSpec("main",
                        basepos + v2s32(spacing.X*0, spacing.Y*3), v2s32(8, 4)));
-       m_draw_positions.push_back(ListDrawSpec("craft",
+       m_draw_spec.push_back(ListDrawSpec("craft",
                        basepos + v2s32(spacing.X*3, spacing.Y*0), v2s32(3, 3)));
-       m_draw_positions.push_back(ListDrawSpec("craftresult",
+       m_draw_spec.push_back(ListDrawSpec("craftresult",
                        basepos + v2s32(spacing.X*7, spacing.Y*1), v2s32(1, 1)));
+       */
        
        // Add children
        {
@@ -160,9 +192,9 @@ GUIInventoryMenu::ItemSpec GUIInventoryMenu::getItemAtPos(v2s32 p) const
 {
        core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y);
        
-       for(u32 i=0; i<m_draw_positions.size(); i++)
+       for(u32 i=0; i<m_draw_spec.size(); i++)
        {
-               const ListDrawSpec &s = m_draw_positions[i];
+               const ListDrawSpec &s = m_draw_spec[i];
 
                for(s32 i=0; i<s.geom.X*s.geom.Y; i++)
                {
@@ -172,15 +204,14 @@ GUIInventoryMenu::ItemSpec GUIInventoryMenu::getItemAtPos(v2s32 p) const
                        core::rect<s32> rect = imgrect + s.pos + p0;
                        if(rect.isPointInside(p))
                        {
-                               return ItemSpec(s.listname, i);
+                               return ItemSpec(s.inventoryname, s.listname, i);
                        }
                }
        }
 
-       return ItemSpec("", -1);
+       return ItemSpec("", "", -1);
 }
 
-//void GUIInventoryMenu::drawList(const std::string &name, v2s32 pos, v2s32 geom)
 void GUIInventoryMenu::drawList(const ListDrawSpec &s)
 {
        video::IVideoDriver* driver = Environment->getVideoDriver();
@@ -191,7 +222,9 @@ void GUIInventoryMenu::drawList(const ListDrawSpec &s)
        if (skin)
                font = skin->getFont();
        
-       InventoryList *ilist = m_inventory->getList(s.listname);
+       Inventory *inv = m_invmgr->getInventory(m_c, s.inventoryname);
+       assert(inv);
+       InventoryList *ilist = inv->getList(s.listname);
        
        core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y);
        
@@ -241,9 +274,9 @@ void GUIInventoryMenu::drawMenu()
                Draw items
        */
        
-       for(u32 i=0; i<m_draw_positions.size(); i++)
+       for(u32 i=0; i<m_draw_spec.size(); i++)
        {
-               ListDrawSpec &s = m_draw_positions[i];
+               ListDrawSpec &s = m_draw_spec[i];
                drawList(s);
        }
 
@@ -279,26 +312,36 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
                        ItemSpec s = getItemAtPos(p);
                        if(s.isValid())
                        {
-                               //dstream<<"Mouse down on "<<s.listname<<" "<<s.i<<std::endl;
+                               dstream<<"Mouse down on "<<s.inventoryname
+                                               <<"/"<<s.listname<<" "<<s.i<<std::endl;
                                if(m_selected_item)
                                {
+                                       Inventory *inv_from = m_invmgr->getInventory(m_c,
+                                                       m_selected_item->inventoryname);
+                                       Inventory *inv_to = m_invmgr->getInventory(m_c,
+                                                       s.inventoryname);
+                                       assert(inv_from);
+                                       assert(inv_to);
                                        InventoryList *list_from =
-                                                       m_inventory->getList(m_selected_item->listname);
+                                                       inv_from->getList(m_selected_item->listname);
                                        InventoryList *list_to =
-                                                       m_inventory->getList(s.listname);
+                                                       inv_to->getList(s.listname);
                                        // Indicates whether source slot completely empties
                                        bool source_empties = false;
                                        if(list_from && list_to
                                                        && list_from->getItem(m_selected_item->i) != NULL)
                                        {
-                                               dstream<<"Queueing IACTION_MOVE"<<std::endl;
+                                               dstream<<"Handing IACTION_MOVE to manager"<<std::endl;
                                                IMoveAction *a = new IMoveAction();
                                                a->count = right ? 1 : 0;
-                                               a->from_name = m_selected_item->listname;
+                                               a->from_inv = m_selected_item->inventoryname;
+                                               a->from_list = m_selected_item->listname;
                                                a->from_i = m_selected_item->i;
-                                               a->to_name = s.listname;
+                                               a->to_inv = s.inventoryname;
+                                               a->to_list = s.listname;
                                                a->to_i = s.i;
-                                               m_actions->push_back(a);
+                                               //ispec.actions->push_back(a);
+                                               m_invmgr->inventoryAction(a);
                                                
                                                if(list_from->getItem(m_selected_item->i)->getCount()==1)
                                                        source_empties = true;
@@ -316,7 +359,10 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
                                        /*
                                                Select if non-NULL
                                        */
-                                       InventoryList *list = m_inventory->getList(s.listname);
+                                       Inventory *inv = m_invmgr->getInventory(m_c,
+                                                       s.inventoryname);
+                                       assert(inv);
+                                       InventoryList *list = inv->getList(s.listname);
                                        if(list->getItem(s.i) != NULL)
                                        {
                                                m_selected_item = new ItemSpec(s);
index 45a5e236a42ebbcb987e7c9f7ed76cfab2469b8c..acddb5c24866b5f1c69d0277947042bc5486c3ff 100644 (file)
@@ -39,9 +39,12 @@ class GUIInventoryMenu : public GUIModalMenu
                {
                        i = -1;
                }
-               ItemSpec(const std::string &a_name, s32 a_i)
+               ItemSpec(const std::string &a_inventoryname,
+                               const std::string &a_listname,
+                               s32 a_i)
                {
-                       listname = a_name;
+                       inventoryname = a_inventoryname;
+                       listname = a_listname;
                        i = a_i;
                }
                bool isValid() const
@@ -49,6 +52,7 @@ class GUIInventoryMenu : public GUIModalMenu
                        return i != -1;
                }
 
+               std::string inventoryname;
                std::string listname;
                s32 i;
        };
@@ -58,24 +62,55 @@ class GUIInventoryMenu : public GUIModalMenu
                ListDrawSpec()
                {
                }
-               ListDrawSpec(const std::string &a_name, v2s32 a_pos, v2s32 a_geom)
+               ListDrawSpec(const std::string &a_inventoryname,
+                               const std::string &a_listname,
+                               v2s32 a_pos, v2s32 a_geom)
                {
-                       listname = a_name;
+                       inventoryname = a_inventoryname;
+                       listname = a_listname;
                        pos = a_pos;
                        geom = a_geom;
                }
 
+               std::string inventoryname;
                std::string listname;
                v2s32 pos;
                v2s32 geom;
        };
-
 public:
+       struct DrawSpec
+       {
+               DrawSpec()
+               {
+               }
+               DrawSpec(const std::string &a_type,
+                               const std::string &a_name,
+                               const std::string &a_subname,
+                               v2s32 a_pos,
+                               v2s32 a_geom)
+               {
+                       type = a_type;
+                       name = a_name;
+                       subname = a_subname;
+                       pos = a_pos;
+                       geom = a_geom;
+               }
+
+               std::string type;
+               std::string name;
+               std::string subname;
+               v2s32 pos;
+               v2s32 geom;
+       };
+
        GUIInventoryMenu(gui::IGUIEnvironment* env,
                        gui::IGUIElement* parent, s32 id,
-                       Inventory *inventory,
-                       Queue<InventoryAction*> *actions,
-                       IMenuManager *menumgr);
+                       IMenuManager *menumgr,
+                       v2s16 menu_size,
+                       core::array<DrawSpec> &init_draw_spec,
+                       InventoryContext *c,
+                       InventoryManager *invmgr
+                       );
        ~GUIInventoryMenu();
 
        void removeChildren();
@@ -96,16 +131,19 @@ private:
                return padding + AbsoluteRect.UpperLeftCorner;
        }
 
+       v2s16 m_menu_size;
+
        v2s32 padding;
        v2s32 spacing;
        v2s32 imgsize;
+       
+       InventoryContext *m_c;
+       InventoryManager *m_invmgr;
 
-       core::array<ListDrawSpec> m_draw_positions;
-
-       Inventory *m_inventory;
+       core::array<DrawSpec> m_init_draw_spec;
+       core::array<ListDrawSpec> m_draw_spec;
 
        ItemSpec *m_selected_item;
-       Queue<InventoryAction*> *m_actions;
 };
 
 #endif
index c29bb947082dddc354fc4f2e51d7cc14d622b396..a610a4617556d4e816c8e5d8608579b59c06238e 100644 (file)
@@ -96,17 +96,11 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
 #ifndef SERVER
 video::ITexture * MapBlockObjectItem::getImage()
 {
-       //TODO
-       
        if(m_inventorystring.substr(0,3) == "Rat")
-               //return g_device->getVideoDriver()->getTexture(porting::getDataPath("rat.png").c_str());
-               //return g_irrlicht->getTexture("rat.png");
-               return NULL;
+               return g_texturesource->getTextureRaw("rat.png");
        
        if(m_inventorystring.substr(0,4) == "Sign")
-               //return g_device->getVideoDriver()->getTexture(porting::getDataPath("sign.png").c_str());
-               //return g_irrlicht->getTexture("sign.png");
-               return NULL;
+               return g_texturesource->getTextureRaw("sign.png");
 
        return NULL;
 }
@@ -608,12 +602,27 @@ InventoryAction * InventoryAction::deSerialize(std::istream &is)
        return a;
 }
 
-void IMoveAction::apply(Inventory *inventory)
+void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr)
 {
-       /*dstream<<"from_name="<<from_name<<" to_name="<<to_name<<std::endl;
+#if 1
+
+       /*dstream<<"from_inv="<<from_inv<<" to_inv="<<to_inv<<std::endl;
+       dstream<<"from_list="<<from_list<<" to_list="<<to_list<<std::endl;
        dstream<<"from_i="<<from_i<<" to_i="<<to_i<<std::endl;*/
-       InventoryList *list_from = inventory->getList(from_name);
-       InventoryList *list_to = inventory->getList(to_name);
+
+       Inventory *inv_from = mgr->getInventory(c, from_inv);
+       Inventory *inv_to = mgr->getInventory(c, to_inv);
+
+       if(!inv_from || !inv_to)
+       {
+               dstream<<__FUNCTION_NAME<<": Operation not allowed "
+                               <<"(inventories not found)"<<std::endl;
+               return;
+       }
+
+       InventoryList *list_from = inv_from->getList(from_list);
+       InventoryList *list_to = inv_to->getList(to_list);
+
        /*dstream<<"list_from="<<list_from<<" list_to="<<list_to
                        <<std::endl;*/
        /*if(list_from)
@@ -625,12 +634,28 @@ void IMoveAction::apply(Inventory *inventory)
        
        /*
                If a list doesn't exist or the source item doesn't exist
-               or the source and the destination slots are the same
        */
-       if(!list_from || !list_to || list_from->getItem(from_i) == NULL
-                       || (list_from == list_to && from_i == to_i))
+       if(!list_from || !list_to)
+       {
+               dstream<<__FUNCTION_NAME<<": Operation not allowed "
+                               <<"(a list doesn't exist)"
+                               <<std::endl;
+               return;
+       }
+       if(list_from->getItem(from_i) == NULL)
+       {
+               dstream<<__FUNCTION_NAME<<": Operation not allowed "
+                               <<"(the source item doesn't exist)"
+                               <<std::endl;
+               return;
+       }
+       /*
+               If the source and the destination slots are the same
+       */
+       if(inv_from == inv_to && list_from == list_to && from_i == to_i)
        {
-               dstream<<__FUNCTION_NAME<<": Operation not allowed"<<std::endl;
+               dstream<<__FUNCTION_NAME<<": Operation not allowed "
+                               <<"(source and the destination slots are the same)"<<std::endl;
                return;
        }
        
@@ -645,29 +670,33 @@ void IMoveAction::apply(Inventory *inventory)
        InventoryItem *olditem = item1;
        item1 = list_to->addItem(to_i, item1);
 
-       // If nothing is returned, the item was fully added
-       if(item1 == NULL)
-               return;
-       
-       // If olditem is returned, nothing was added.
-       bool nothing_added = (item1 == olditem);
-       
-       // If something else is returned, part of the item was left unadded.
-       // Add the other part back to the source item
-       list_from->addItem(from_i, item1);
-
-       // If olditem is returned, nothing was added.
-       // Swap the items
-       if(nothing_added)
+       // If something is returned, the item was not fully added
+       if(item1 != NULL)
        {
-               // Take item from source list
-               item1 = list_from->changeItem(from_i, NULL);
-               // Adding was not possible, swap the items.
-               InventoryItem *item2 = list_to->changeItem(to_i, item1);
-               // Put item from destination list to the source list
-               list_from->changeItem(from_i, item2);
-               return;
+               // If olditem is returned, nothing was added.
+               bool nothing_added = (item1 == olditem);
+               
+               // If something else is returned, part of the item was left unadded.
+               // Add the other part back to the source item
+               list_from->addItem(from_i, item1);
+
+               // If olditem is returned, nothing was added.
+               // Swap the items
+               if(nothing_added)
+               {
+                       // Take item from source list
+                       item1 = list_from->changeItem(from_i, NULL);
+                       // Adding was not possible, swap the items.
+                       InventoryItem *item2 = list_to->changeItem(to_i, item1);
+                       // Put item from destination list to the source list
+                       list_from->changeItem(from_i, item2);
+               }
        }
+
+       mgr->inventoryModified(c, from_inv);
+       if(from_inv != to_inv)
+               mgr->inventoryModified(c, to_inv);
+#endif
 }
        
 //END
index 9155eb025f5868d34acecfaf4e7fc43cfa33925a..45bc488c54d16aa2aea21c816efaa6d1fbde5bc4 100644 (file)
@@ -495,6 +495,41 @@ private:
        core::array<InventoryList*> m_lists;
 };
 
+class Player;
+
+struct InventoryContext
+{
+       Player *current_player;
+       
+       InventoryContext():
+               current_player(NULL)
+       {}
+};
+
+class InventoryAction;
+
+class InventoryManager
+{
+public:
+       InventoryManager(){}
+       virtual ~InventoryManager(){}
+       
+       /*
+               Get a pointer to an inventory specified by id.
+               id can be:
+               - "current_player"
+               - "nodemeta:X,Y,Z"
+       */
+       virtual Inventory* getInventory(InventoryContext *c, std::string id)
+               {return NULL;}
+       // Used on the server by InventoryAction::apply
+       virtual void inventoryModified(InventoryContext *c, std::string id)
+               {}
+       // Used on the client
+       virtual void inventoryAction(InventoryAction *a)
+               {}
+};
+
 #define IACTION_MOVE 0
 
 struct InventoryAction
@@ -503,16 +538,18 @@ struct InventoryAction
        
        virtual u16 getType() const = 0;
        virtual void serialize(std::ostream &os) = 0;
-       virtual void apply(Inventory *inventory) = 0;
+       virtual void apply(InventoryContext *c, InventoryManager *mgr) = 0;
 };
 
 struct IMoveAction : public InventoryAction
 {
        // count=0 means "everything"
        u16 count;
-       std::string from_name;
+       std::string from_inv;
+       std::string from_list;
        s16 from_i;
-       std::string to_name;
+       std::string to_inv;
+       std::string to_list;
        s16 to_i;
        
        IMoveAction()
@@ -528,12 +565,16 @@ struct IMoveAction : public InventoryAction
                std::getline(is, ts, ' ');
                count = stoi(ts);
 
-               std::getline(is, from_name, ' ');
+               std::getline(is, from_inv, ' ');
+
+               std::getline(is, from_list, ' ');
 
                std::getline(is, ts, ' ');
                from_i = stoi(ts);
 
-               std::getline(is, to_name, ' ');
+               std::getline(is, to_inv, ' ');
+
+               std::getline(is, to_list, ' ');
 
                std::getline(is, ts, ' ');
                to_i = stoi(ts);
@@ -548,13 +589,15 @@ struct IMoveAction : public InventoryAction
        {
                os<<"Move ";
                os<<count<<" ";
-               os<<from_name<<" ";
+               os<<from_inv<<" ";
+               os<<from_list<<" ";
                os<<from_i<<" ";
-               os<<to_name<<" ";
+               os<<to_inv<<" ";
+               os<<to_list<<" ";
                os<<to_i;
        }
 
-       void apply(Inventory *inventory);
+       void apply(InventoryContext *c, InventoryManager *mgr);
 };
 
 #endif
index 6bcd7f5ac004f1607e6554db0f2d305bb7cf416d..49246ec8939f18e4c4a6589b4ad92351c08cb20d 100644 (file)
@@ -448,6 +448,7 @@ public:
 MainGameCallback g_gamecallback;\r
 \r
 // Inventory actions from the menu are buffered here before sending\r
+// TODO: Get rid of this\r
 Queue<InventoryAction*> inventory_action_queue;\r
 // This is a copy of the inventory that the client's environment has\r
 Inventory local_inventory;\r
@@ -621,9 +622,26 @@ public:
                                        {\r
                                                dstream<<DTIME<<"MyEventReceiver: "\r
                                                                <<"Launching inventory"<<std::endl;\r
-                                               (new GUIInventoryMenu(guienv, guiroot, -1,\r
-                                                               &local_inventory, &inventory_action_queue,\r
-                                                               &g_menumgr))->drop();\r
+                                               \r
+                                               core::array<GUIInventoryMenu::DrawSpec> draw_spec;\r
+                                               draw_spec.push_back(GUIInventoryMenu::DrawSpec(\r
+                                                               "list", "current_player", "main",\r
+                                                               v2s32(0, 3), v2s32(8, 4)));\r
+                                               draw_spec.push_back(GUIInventoryMenu::DrawSpec(\r
+                                                               "list", "current_player", "craft",\r
+                                                               v2s32(3, 0), v2s32(3, 3)));\r
+                                               draw_spec.push_back(GUIInventoryMenu::DrawSpec(\r
+                                                               "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
+\r
+                                               menu->drop();\r
+\r
                                                return true;\r
                                        }\r
                                        if(event.KeyInput.Key == irr::KEY_KEY_T)\r
@@ -2950,25 +2968,54 @@ int main(int argc, char *argv[])
                        {\r
                                std::cout<<DTIME<<"Ground right-clicked"<<std::endl;\r
                                \r
-                               if(meta && meta->typeId() == CONTENT_SIGN_WALL)\r
+                               if(meta && meta->typeId() == CONTENT_SIGN_WALL && !random_input)\r
                                {\r
                                        dstream<<"Sign node right-clicked"<<std::endl;\r
                                        \r
-                                       if(random_input == false)\r
-                                       {\r
-                                               // Get a new text for it\r
+                                       SignNodeMetadata *signmeta = (SignNodeMetadata*)meta;\r
+                                       \r
+                                       // Get a new text for it\r
 \r
-                                               TextDest *dest = new TextDestSignNode(nodepos, &client);\r
+                                       TextDest *dest = new TextDestSignNode(nodepos, &client);\r
 \r
-                                               SignNodeMetadata *signmeta = (SignNodeMetadata*)meta;\r
-                                               \r
-                                               std::wstring wtext =\r
-                                                               narrow_to_wide(signmeta->getText());\r
+                                       std::wstring wtext =\r
+                                                       narrow_to_wide(signmeta->getText());\r
+\r
+                                       (new GUITextInputMenu(guienv, guiroot, -1,\r
+                                                       &g_menumgr, dest,\r
+                                                       wtext))->drop();\r
+                               }\r
+                               else if(meta && meta->typeId() == CONTENT_CHEST && !random_input)\r
+                               {\r
+                                       dstream<<"Chest node right-clicked"<<std::endl;\r
+                                       \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
+                                       chest_inv_id += ",";\r
+                                       chest_inv_id += itos(nodepos.Y);\r
+                                       chest_inv_id += ",";\r
+                                       chest_inv_id += itos(nodepos.Z);\r
+                                       \r
+                                       draw_spec.push_back(GUIInventoryMenu::DrawSpec(\r
+                                                       "list", chest_inv_id, "0",\r
+                                                       v2s32(0, 0), v2s32(8, 4)));\r
+                                       draw_spec.push_back(GUIInventoryMenu::DrawSpec(\r
+                                                       "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
+\r
+                                       menu->drop();\r
 \r
-                                               (new GUITextInputMenu(guienv, guiroot, -1,\r
-                                                               &g_menumgr, dest,\r
-                                                               wtext))->drop();\r
-                                       }\r
                                }\r
                                else\r
                                {\r
@@ -3196,8 +3243,6 @@ int main(int argc, char *argv[])
                        old_selected_item = g_selected_item;\r
                        //std::cout<<"Updating local inventory"<<std::endl;\r
                        client.getLocalInventory(local_inventory);\r
-                       /*quick_inventory->setSelection(g_selected_item);\r
-                       quick_inventory->update();*/\r
                }\r
                \r
                /*\r
index fca4e5b845b14881d52d907022952f327755d87d..294db178f240f7e0d19f018764bed7dcb8e0c480 100644 (file)
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "utility.h"
 #include "mapnode.h"
 #include "exceptions.h"
+#include "inventory.h"
 
 /*
        NodeMetadata
@@ -111,6 +112,13 @@ std::string SignNodeMetadata::infoText()
 ChestNodeMetadata::ChestNodeMetadata()
 {
        NodeMetadata::registerType(typeId(), create);
+       
+       m_inventory = new Inventory();
+       m_inventory->addList("0", 8*4);
+}
+ChestNodeMetadata::~ChestNodeMetadata()
+{
+       delete m_inventory;
 }
 u16 ChestNodeMetadata::typeId() const
 {
@@ -118,19 +126,28 @@ u16 ChestNodeMetadata::typeId() const
 }
 NodeMetadata* ChestNodeMetadata::create(std::istream &is)
 {
-       return new ChestNodeMetadata();
+       ChestNodeMetadata *d = new ChestNodeMetadata();
+       d->m_inventory->deSerialize(is);
+       return d;
 }
 NodeMetadata* ChestNodeMetadata::clone()
 {
-       return new ChestNodeMetadata();
+       ChestNodeMetadata *d = new ChestNodeMetadata();
+       *d->m_inventory = *m_inventory;
+       return d;
 }
 void ChestNodeMetadata::serializeBody(std::ostream &os)
 {
+       m_inventory->serialize(os);
 }
 std::string ChestNodeMetadata::infoText()
 {
        return "Chest";
 }
+/*Inventory* ChestNodeMetadata::getInventory()
+{
+       return m_inventory;
+}*/
 
 /*
        NodeMetadatalist
index 21916677ee370e01d61bfc6ee50b3ec6ac8e45f7..8877c266760fb96cbf7d34dd743c2fd9b041bec2 100644 (file)
@@ -37,6 +37,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
                - Text
 */
 
+class Inventory;
+
 class NodeMetadata
 {
 public:
@@ -52,7 +54,8 @@ public:
        virtual u16 typeId() const = 0;
        virtual NodeMetadata* clone() = 0;
        virtual void serializeBody(std::ostream &os) = 0;
-       virtual std::string infoText() { return "<todo: remove this text>"; }
+       virtual std::string infoText() {return "<todo: remove this text>";}
+       virtual Inventory* getInventory() {return NULL;}
 
 protected:
        static void registerType(u16 id, Factory f);
@@ -83,14 +86,17 @@ class ChestNodeMetadata : public NodeMetadata
 {
 public:
        ChestNodeMetadata();
+       ~ChestNodeMetadata();
        
        virtual u16 typeId() const;
        static NodeMetadata* create(std::istream &is);
        virtual NodeMetadata* clone();
        virtual void serializeBody(std::ostream &os);
        virtual std::string infoText();
+       virtual Inventory* getInventory() {return m_inventory;}
 
 private:
+       Inventory *m_inventory;
 };
 
 class NodeMetadataList
index 4f3846cf8802f1194b45280fd4452a2ea16b1df7..a70c42a358eafd306829062437609bae2665c182 100644 (file)
@@ -2460,6 +2460,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                InventoryAction *a = InventoryAction::deSerialize(is);
                if(a != NULL)
                {
+                       // Create context
+                       InventoryContext c;
+                       c.current_player = player;
+
                        /*
                                Handle craftresult specially if not in creative mode
                        */
@@ -2468,50 +2472,60 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                        && g_settings.getBool("creative_mode") == false)
                        {
                                IMoveAction *ma = (IMoveAction*)a;
-                               // Don't allow moving anything to craftresult
-                               if(ma->to_name == "craftresult")
-                               {
-                                       // Do nothing
-                                       disable_action = true;
-                               }
-                               // When something is removed from craftresult
-                               if(ma->from_name == "craftresult")
+                               if(ma->to_inv == "current_player" &&
+                                               ma->from_inv == "current_player")
                                {
-                                       disable_action = true;
-                                       // Remove stuff from craft
-                                       InventoryList *clist = player->inventory.getList("craft");
-                                       if(clist)
+                                       // Don't allow moving anything to craftresult
+                                       if(ma->to_list == "craftresult")
                                        {
-                                               u16 count = ma->count;
-                                               if(count == 0)
-                                                       count = 1;
-                                               clist->decrementMaterials(count);
+                                               // Do nothing
+                                               disable_action = true;
                                        }
-                                       // Do action
-                                       // Feed action to player inventory
-                                       a->apply(&player->inventory);
-                                       // Eat it
-                                       delete a;
-                                       // If something appeared in craftresult, throw it
-                                       // in the main list
-                                       InventoryList *rlist = player->inventory.getList("craftresult");
-                                       InventoryList *mlist = player->inventory.getList("main");
-                                       if(rlist && mlist && rlist->getUsedSlots() == 1)
+                                       // When something is removed from craftresult
+                                       if(ma->from_list == "craftresult")
                                        {
-                                               InventoryItem *item1 = rlist->changeItem(0, NULL);
-                                               mlist->addItem(item1);
+                                               disable_action = true;
+                                               // Remove stuff from craft
+                                               InventoryList *clist = player->inventory.getList("craft");
+                                               if(clist)
+                                               {
+                                                       u16 count = ma->count;
+                                                       if(count == 0)
+                                                               count = 1;
+                                                       clist->decrementMaterials(count);
+                                               }
+                                               // Do action
+                                               // Feed action to player inventory
+                                               //a->apply(&player->inventory);
+                                               a->apply(&c, this);
+                                               // Eat it
+                                               delete a;
+                                               // If something appeared in craftresult, throw it
+                                               // in the main list
+                                               InventoryList *rlist = player->inventory.getList("craftresult");
+                                               InventoryList *mlist = player->inventory.getList("main");
+                                               if(rlist && mlist && rlist->getUsedSlots() == 1)
+                                               {
+                                                       InventoryItem *item1 = rlist->changeItem(0, NULL);
+                                                       mlist->addItem(item1);
+                                               }
                                        }
                                }
                        }
+                       
                        if(disable_action == false)
                        {
                                // Feed action to player inventory
-                               a->apply(&player->inventory);
-                               // Eat it
+                               //a->apply(&player->inventory);
+                               a->apply(&c, this);
+                               // Eat the action
                                delete a;
                        }
-                       // Send inventory
-                       SendInventory(player->peer_id);
+                       else
+                       {
+                               // Send inventory
+                               SendInventory(player->peer_id);
+                       }
                }
                else
                {
@@ -2679,6 +2693,63 @@ void Server::onMapEditEvent(MapEditEvent *event)
        m_unsent_map_edit_queue.push_back(e);
 }
 
+Inventory* Server::getInventory(InventoryContext *c, std::string id)
+{
+       if(id == "current_player")
+       {
+               assert(c->current_player);
+               return &(c->current_player->inventory);
+       }
+       
+       Strfnd fn(id);
+       std::string id0 = fn.next(":");
+
+       if(id0 == "nodemeta")
+       {
+               v3s16 p;
+               p.X = stoi(fn.next(","));
+               p.Y = stoi(fn.next(","));
+               p.Z = stoi(fn.next(","));
+               NodeMetadata *meta = m_env.getMap().getNodeMetadata(p);
+               if(meta)
+                       return meta->getInventory();
+               dstream<<"nodemeta at ("<<p.X<<","<<p.Y<<","<<p.Z<<"): "
+                               <<"no metadata found"<<std::endl;
+               return NULL;
+       }
+
+       dstream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
+       return NULL;
+}
+void Server::inventoryModified(InventoryContext *c, std::string id)
+{
+       if(id == "current_player")
+       {
+               assert(c->current_player);
+               // Send inventory
+               SendInventory(c->current_player->peer_id);
+               return;
+       }
+       
+       Strfnd fn(id);
+       std::string id0 = fn.next(":");
+
+       if(id0 == "nodemeta")
+       {
+               v3s16 p;
+               p.X = stoi(fn.next(","));
+               p.Y = stoi(fn.next(","));
+               p.Z = stoi(fn.next(","));
+               assert(c->current_player);
+               RemoteClient *client = getClient(c->current_player->peer_id);
+               v3s16 blockpos = getNodeBlockPos(p);
+               client->SetBlockNotSent(blockpos);
+               return;
+       }
+
+       dstream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
+}
+
 core::list<PlayerInfo> Server::getPlayerInfo()
 {
        DSTACK(__FUNCTION_NAME);
@@ -3027,7 +3098,8 @@ void Server::SendInventory(u16 peer_id)
                                specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
                                if(checkItemCombination(items, specs))
                                {
-                                       rlist->addItem(new MapBlockObjectItem("Sign"));
+                                       //rlist->addItem(new MapBlockObjectItem("Sign"));
+                                       rlist->addItem(new MaterialItem(CONTENT_SIGN_WALL, 1));
                                        found = true;
                                }
                        }
@@ -3092,6 +3164,26 @@ void Server::SendInventory(u16 peer_id)
                                        found = true;
                                }
                        }
+
+                       // Chest1
+                       if(!found)
+                       {
+                               ItemSpec specs[9];
+                               specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+                               specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+                               specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+                               specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+                               specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+                               specs[6] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+                               specs[7] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+                               specs[8] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+                               if(checkItemCombination(items, specs))
+                               {
+                                       rlist->addItem(new MaterialItem(CONTENT_CHEST, 1));
+                                       found = true;
+                               }
+                       }
+
                }
        } // if creative_mode == false
 
index f997828b2a20276cfce58f95366090a218a8694c..f1c7b6e01cdc1b333b23713ef85dece373caab6f 100644 (file)
@@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "utility.h"
 #include "porting.h"
 #include "map.h"
+#include "inventory.h"
 
 struct QueuedBlockEmerge
 {
@@ -342,7 +343,8 @@ private:
        u32 m_excess_gotblocks;
 };
 
-class Server : public con::PeerHandler, public MapEventReceiver
+class Server : public con::PeerHandler, public MapEventReceiver,
+               public InventoryManager
 {
 public:
        /*
@@ -382,6 +384,12 @@ public:
        */
        void onMapEditEvent(MapEditEvent *event);
 
+       /*
+               Shall be called with the environment and the connection locked.
+       */
+       Inventory* getInventory(InventoryContext *c, std::string id);
+       void inventoryModified(InventoryContext *c, std::string id);
+
 private:
 
        // Virtual methods from con::PeerHandler.