Add InvRef and InvStack (currently untested and unusable)
authorPerttu Ahola <celeron55@gmail.com>
Tue, 6 Dec 2011 13:21:56 +0000 (15:21 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Sun, 1 Jan 2012 23:49:38 +0000 (01:49 +0200)
13 files changed:
src/CMakeLists.txt
src/client.cpp
src/client.h
src/craftdef.cpp
src/guiInventoryMenu.cpp
src/guiInventoryMenu.h
src/inventory.cpp
src/inventory.h
src/inventorymanager.cpp [new file with mode: 0644]
src/inventorymanager.h [new file with mode: 0644]
src/scriptapi.cpp
src/server.cpp
src/server.h

index 2088c8b791c6bd43f8afbd8e04a5b06798f63311..3b3b326c454f9967ffef4a823507b737212616ea 100644 (file)
@@ -94,6 +94,7 @@ configure_file(
 )
 
 set(common_SRCS
+       inventorymanager.cpp
        mods.cpp
        serverremoteplayer.cpp
        content_abm.cpp
index d092c6a10ceb00b4277c8c3690fecb688e7fc113..cfdc713db5ff19f9820fe7b69756818f3ee2545b 100644 (file)
@@ -1782,6 +1782,34 @@ InventoryContext *Client::getInventoryContext()
        return &m_inventory_context;
 }
 
+Inventory* Client::getInventory(const InventoryLocation &loc)
+{
+       switch(loc.type){
+       case InventoryLocation::UNDEFINED:
+       {}
+       break;
+       case InventoryLocation::PLAYER:
+       {
+               Player *player = m_env.getPlayer(loc.name.c_str());
+               if(!player)
+                       return NULL;
+               return &player->inventory;
+       }
+       break;
+       case InventoryLocation::NODEMETA:
+       {
+               NodeMetadata *meta = m_env.getMap().getNodeMetadata(loc.p);
+               if(!meta)
+                       return NULL;
+               return meta->getInventory();
+       }
+       break;
+       default:
+               assert(0);
+       }
+       return NULL;
+}
+#if 0
 Inventory* Client::getInventory(InventoryContext *c, std::string id)
 {
        if(id == "current_player")
@@ -1810,6 +1838,7 @@ Inventory* Client::getInventory(InventoryContext *c, std::string id)
        infostream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
        return NULL;
 }
+#endif
 void Client::inventoryAction(InventoryAction *a)
 {
        sendInventoryAction(a);
index 2f212dad8d92ce9cf74bd7378df0462896956763..e74fec5a7cf61b7c5f4d99fae25faaf927aaada4 100644 (file)
@@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "clientobject.h"
 #include "utility.h" // For IntervalLimiter
 #include "gamedef.h"
+#include "inventorymanager.h"
 
 struct MeshMakeData;
 class IGameDef;
@@ -245,7 +246,9 @@ public:
        
        InventoryContext *getInventoryContext();
 
-       Inventory* getInventory(InventoryContext *c, std::string id);
+       /* InventoryManager interface */
+       Inventory* getInventory(const InventoryLocation &loc);
+       //Inventory* getInventory(InventoryContext *c, std::string id);
        void inventoryAction(InventoryAction *a);
 
        // Gets closest object pointed by the shootline
index e701a427959f18383aa6598b1de85148713b6bd9..0cbb74ea07cae5e9f5ae2c718e496004a7d047b9 100644 (file)
@@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "utility.h"
 #include "gamedef.h"
 #include "inventory.h"
+#include "inventorymanager.h" // checkItemCombination
 
 CraftPointerInput::~CraftPointerInput()
 {
index d9a98b5b0a1e939744d147c9d61ed30f96b9a497..552e10db2940acd66ee9397f27f36f5f2a0c7caf 100644 (file)
@@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <IGUIStaticText.h>
 #include <IGUIFont.h>
 #include "log.h"
+#include "inventorymanager.h"
 
 void drawInventoryItem(video::IVideoDriver *driver,
                gui::IGUIFont *font,
index c8fe0d0681323ba030fd23144481a2e9b6dc32d6..359268687ad7239f08b2549439afbe36210c9e57 100644 (file)
@@ -27,6 +27,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "modalMenu.h"
 
 class ITextureSource;
+class InventoryContext;
+class InventoryManager;
 
 void drawInventoryItem(video::IVideoDriver *driver,
                gui::IGUIFont *font,
index dd2713ca9f6b854f05667922a2e02ff48e452825..0d38bed78bae09d4664e87e6c089c2974010ac5f 100644 (file)
@@ -37,7 +37,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "scriptapi.h"
 #include "strfnd.h"
 #include "nameidmapping.h" // For loading legacy MaterialItems
-#include "serverremoteplayer.h"
 
 /*
        InventoryItem
@@ -567,6 +566,22 @@ void InventoryList::clearItems()
        //setDirty(true);
 }
 
+void InventoryList::setSize(u32 newsize)
+{
+       if(newsize < m_items.size()){
+               for(u32 i=newsize; i<m_items.size(); i++){
+                       if(m_items[i])
+                               delete m_items[i];
+               }
+               m_items.erase(newsize, m_items.size() - newsize);
+       } else {
+               for(u32 i=m_items.size(); i<newsize; i++){
+                       m_items.push_back(NULL);
+               }
+       }
+       m_size = newsize;
+}
+
 void InventoryList::serialize(std::ostream &os) const
 {
        //os.imbue(std::locale("C"));
@@ -1041,458 +1056,4 @@ const s32 Inventory::getListIndex(const std::string &name) const
        return -1;
 }
 
-/*
-       InventoryAction
-*/
-
-InventoryAction * InventoryAction::deSerialize(std::istream &is)
-{
-       std::string type;
-       std::getline(is, type, ' ');
-
-       InventoryAction *a = NULL;
-
-       if(type == "Move")
-       {
-               a = new IMoveAction(is);
-       }
-       else if(type == "Drop")
-       {
-               a = new IDropAction(is);
-       }
-
-       return a;
-}
-
-static std::string describeC(const struct InventoryContext *c)
-{
-       if(c->current_player == NULL)
-               return "current_player=NULL";
-       else
-               return std::string("current_player=") + c->current_player->getName();
-}
-
-IMoveAction::IMoveAction(std::istream &is)
-{
-       std::string ts;
-
-       std::getline(is, ts, ' ');
-       count = stoi(ts);
-
-       std::getline(is, from_inv, ' ');
-
-       std::getline(is, from_list, ' ');
-
-       std::getline(is, ts, ' ');
-       from_i = stoi(ts);
-
-       std::getline(is, to_inv, ' ');
-
-       std::getline(is, to_list, ' ');
-
-       std::getline(is, ts, ' ');
-       to_i = stoi(ts);
-}
-
-void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr,
-               ServerEnvironment *env)
-{
-       Inventory *inv_from = mgr->getInventory(c, from_inv);
-       Inventory *inv_to = mgr->getInventory(c, to_inv);
-       
-       if(!inv_from){
-               infostream<<"IMoveAction::apply(): FAIL: source inventory not found: "
-                               <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
-                               <<", to_inv=\""<<to_inv<<"\""<<std::endl;
-               return;
-       }
-       if(!inv_to){
-               infostream<<"IMoveAction::apply(): FAIL: destination inventory not found: "
-                               "context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
-                               <<", to_inv=\""<<to_inv<<"\""<<std::endl;
-               return;
-       }
-
-       InventoryList *list_from = inv_from->getList(from_list);
-       InventoryList *list_to = inv_to->getList(to_list);
-
-       /*
-               If a list doesn't exist or the source item doesn't exist
-       */
-       if(!list_from){
-               infostream<<"IMoveAction::apply(): FAIL: source list not found: "
-                               <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
-                               <<", from_list=\""<<from_list<<"\""<<std::endl;
-               return;
-       }
-       if(!list_to){
-               infostream<<"IMoveAction::apply(): FAIL: destination list not found: "
-                               <<"context=["<<describeC(c)<<"], to_inv=\""<<to_inv<<"\""
-                               <<", to_list=\""<<to_list<<"\""<<std::endl;
-               return;
-       }
-       if(list_from->getItem(from_i) == NULL)
-       {
-               infostream<<"IMoveAction::apply(): FAIL: source item not found: "
-                               <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
-                               <<", from_list=\""<<from_list<<"\""
-                               <<" from_i="<<from_i<<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)
-       {
-               infostream<<"IMoveAction::apply(): FAIL: source and destination slots "
-                               <<"are the same: inv=\""<<from_inv<<"\" list=\""<<from_list
-                               <<"\" i="<<from_i<<std::endl;
-               return;
-       }
-       
-       // Take item from source list
-       InventoryItem *item1 = NULL;
-       if(count == 0)
-               item1 = list_from->changeItem(from_i, NULL);
-       else
-               item1 = list_from->takeItem(from_i, count);
-
-       // Try to add the item to destination list
-       InventoryItem *olditem = item1;
-       item1 = list_to->addItem(to_i, item1);
-
-       // If something is returned, the item was not fully added
-       if(item1 != NULL)
-       {
-               // 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);
-       
-       infostream<<"IMoveAction::apply(): moved at "
-                       <<"["<<describeC(c)<<"]"
-                       <<" from inv=\""<<from_inv<<"\""
-                       <<" list=\""<<from_list<<"\""
-                       <<" i="<<from_i
-                       <<" to inv=\""<<to_inv<<"\""
-                       <<" list=\""<<to_list<<"\""
-                       <<" i="<<to_i
-                       <<std::endl;
-}
-
-IDropAction::IDropAction(std::istream &is)
-{
-       std::string ts;
-
-       std::getline(is, ts, ' ');
-       count = stoi(ts);
-
-       std::getline(is, from_inv, ' ');
-
-       std::getline(is, from_list, ' ');
-
-       std::getline(is, ts, ' ');
-       from_i = stoi(ts);
-}
-
-void IDropAction::apply(InventoryContext *c, InventoryManager *mgr,
-               ServerEnvironment *env)
-{
-       if(c->current_player == NULL){
-               infostream<<"IDropAction::apply(): FAIL: current_player is NULL"<<std::endl;
-               return;
-       }
-
-       // Do NOT cast directly to ServerActiveObject*, it breaks
-       // because of multiple inheritance.
-       ServerActiveObject *dropper =
-               static_cast<ServerActiveObject*>(
-               static_cast<ServerRemotePlayer*>(
-                       c->current_player
-               ));
-
-       Inventory *inv_from = mgr->getInventory(c, from_inv);
-       
-       if(!inv_from){
-               infostream<<"IDropAction::apply(): FAIL: source inventory not found: "
-                               <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""<<std::endl;
-               return;
-       }
-
-       InventoryList *list_from = inv_from->getList(from_list);
-
-       /*
-               If a list doesn't exist or the source item doesn't exist
-       */
-       if(!list_from){
-               infostream<<"IDropAction::apply(): FAIL: source list not found: "
-                               <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
-                               <<", from_list=\""<<from_list<<"\""<<std::endl;
-               return;
-       }
-       InventoryItem *item = list_from->getItem(from_i);
-       if(item == NULL)
-       {
-               infostream<<"IDropAction::apply(): FAIL: source item not found: "
-                               <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
-                               <<", from_list=\""<<from_list<<"\""
-                               <<" from_i="<<from_i<<std::endl;
-               return;
-       }
-
-       v3f pos = dropper->getBasePosition();
-       pos.Y += 0.5*BS;
-
-       s16 count2 = count;
-       if(count2 == 0)
-               count2 = -1;
-
-       /*
-               Drop the item
-       */
-       bool remove = item->dropOrPlace(env, dropper, pos, false, count2);
-       if(remove)
-               list_from->deleteItem(from_i);
-
-       mgr->inventoryModified(c, from_inv);
-
-       infostream<<"IDropAction::apply(): dropped "
-                       <<"["<<describeC(c)<<"]"
-                       <<" from inv=\""<<from_inv<<"\""
-                       <<" list=\""<<from_list<<"\""
-                       <<" i="<<from_i
-                       <<std::endl;
-}
-
-/*
-       Craft checking system
-*/
-
-bool ItemSpec::checkItem(const InventoryItem *item) const
-{
-       if(type == ITEM_NONE)
-       {
-               // Has to be no item
-               if(item != NULL)
-                       return false;
-               return true;
-       }
-       
-       // There should be an item
-       if(item == NULL)
-               return false;
-
-       std::string itemname = item->getName();
-
-       if(type == ITEM_MATERIAL)
-       {
-               if(itemname != "MaterialItem")
-                       return false;
-               MaterialItem *mitem = (MaterialItem*)item;
-               if(num != 65535){
-                       if(mitem->getMaterial() != num)
-                               return false;
-               } else {
-                       if(mitem->getNodeName() != name)
-                               return false;
-               }
-       }
-       else if(type == ITEM_CRAFT)
-       {
-               if(itemname != "CraftItem")
-                       return false;
-               CraftItem *mitem = (CraftItem*)item;
-               if(mitem->getSubName() != name)
-                       return false;
-       }
-       else if(type == ITEM_TOOL)
-       {
-               // Not supported yet
-               assert(0);
-       }
-       else if(type == ITEM_MBO)
-       {
-               // Not supported yet
-               assert(0);
-       }
-       else
-       {
-               // Not supported yet
-               assert(0);
-       }
-       return true;
-}
-
-bool checkItemCombination(InventoryItem const * const *items, const ItemSpec *specs)
-{
-       u16 items_min_x = 100;
-       u16 items_max_x = 100;
-       u16 items_min_y = 100;
-       u16 items_max_y = 100;
-       for(u16 y=0; y<3; y++)
-       for(u16 x=0; x<3; x++)
-       {
-               if(items[y*3 + x] == NULL)
-                       continue;
-               if(items_min_x == 100 || x < items_min_x)
-                       items_min_x = x;
-               if(items_min_y == 100 || y < items_min_y)
-                       items_min_y = y;
-               if(items_max_x == 100 || x > items_max_x)
-                       items_max_x = x;
-               if(items_max_y == 100 || y > items_max_y)
-                       items_max_y = y;
-       }
-       // No items at all, just return false
-       if(items_min_x == 100)
-               return false;
-       
-       u16 items_w = items_max_x - items_min_x + 1;
-       u16 items_h = items_max_y - items_min_y + 1;
-
-       u16 specs_min_x = 100;
-       u16 specs_max_x = 100;
-       u16 specs_min_y = 100;
-       u16 specs_max_y = 100;
-       for(u16 y=0; y<3; y++)
-       for(u16 x=0; x<3; x++)
-       {
-               if(specs[y*3 + x].type == ITEM_NONE)
-                       continue;
-               if(specs_min_x == 100 || x < specs_min_x)
-                       specs_min_x = x;
-               if(specs_min_y == 100 || y < specs_min_y)
-                       specs_min_y = y;
-               if(specs_max_x == 100 || x > specs_max_x)
-                       specs_max_x = x;
-               if(specs_max_y == 100 || y > specs_max_y)
-                       specs_max_y = y;
-       }
-       // No specs at all, just return false
-       if(specs_min_x == 100)
-               return false;
-
-       u16 specs_w = specs_max_x - specs_min_x + 1;
-       u16 specs_h = specs_max_y - specs_min_y + 1;
-
-       // Different sizes
-       if(items_w != specs_w || items_h != specs_h)
-               return false;
-
-       for(u16 y=0; y<specs_h; y++)
-       for(u16 x=0; x<specs_w; x++)
-       {
-               u16 items_x = items_min_x + x;
-               u16 items_y = items_min_y + y;
-               u16 specs_x = specs_min_x + x;
-               u16 specs_y = specs_min_y + y;
-               const InventoryItem *item = items[items_y * 3 + items_x];
-               const ItemSpec &spec = specs[specs_y * 3 + specs_x];
-
-               if(spec.checkItem(item) == false)
-                       return false;
-       }
-
-       return true;
-}
-
-bool checkItemCombination(const InventoryItem * const * items,
-               const InventoryItem * const * specs)
-{
-       u16 items_min_x = 100;
-       u16 items_max_x = 100;
-       u16 items_min_y = 100;
-       u16 items_max_y = 100;
-       for(u16 y=0; y<3; y++)
-       for(u16 x=0; x<3; x++)
-       {
-               if(items[y*3 + x] == NULL)
-                       continue;
-               if(items_min_x == 100 || x < items_min_x)
-                       items_min_x = x;
-               if(items_min_y == 100 || y < items_min_y)
-                       items_min_y = y;
-               if(items_max_x == 100 || x > items_max_x)
-                       items_max_x = x;
-               if(items_max_y == 100 || y > items_max_y)
-                       items_max_y = y;
-       }
-       // No items at all, just return false
-       if(items_min_x == 100)
-               return false;
-       
-       u16 items_w = items_max_x - items_min_x + 1;
-       u16 items_h = items_max_y - items_min_y + 1;
-
-       u16 specs_min_x = 100;
-       u16 specs_max_x = 100;
-       u16 specs_min_y = 100;
-       u16 specs_max_y = 100;
-       for(u16 y=0; y<3; y++)
-       for(u16 x=0; x<3; x++)
-       {
-               if(specs[y*3 + x] == NULL)
-                       continue;
-               if(specs_min_x == 100 || x < specs_min_x)
-                       specs_min_x = x;
-               if(specs_min_y == 100 || y < specs_min_y)
-                       specs_min_y = y;
-               if(specs_max_x == 100 || x > specs_max_x)
-                       specs_max_x = x;
-               if(specs_max_y == 100 || y > specs_max_y)
-                       specs_max_y = y;
-       }
-       // No specs at all, just return false
-       if(specs_min_x == 100)
-               return false;
-
-       u16 specs_w = specs_max_x - specs_min_x + 1;
-       u16 specs_h = specs_max_y - specs_min_y + 1;
-
-       // Different sizes
-       if(items_w != specs_w || items_h != specs_h)
-               return false;
-
-       for(u16 y=0; y<specs_h; y++)
-       for(u16 x=0; x<specs_w; x++)
-       {
-               u16 items_x = items_min_x + x;
-               u16 items_y = items_min_y + y;
-               u16 specs_x = specs_min_x + x;
-               u16 specs_y = specs_min_y + y;
-               const InventoryItem *item = items[items_y * 3 + items_x];
-               const InventoryItem *spec = specs[specs_y * 3 + specs_x];
-               
-               if(item == NULL && spec == NULL)
-                       continue;
-               if(item == NULL && spec != NULL)
-                       return false;
-               if(item != NULL && spec == NULL)
-                       return false;
-               if(!spec->isSubsetOf(item))
-                       return false;
-       }
-
-       return true;
-}
-
 //END
index 795d32d3e8034f37b31b4ff0500e61969da56173..15de3c8e7d8cdd1ffc2180964a57598d74456638 100644 (file)
@@ -419,6 +419,7 @@ public:
        InventoryList(std::string name, u32 size);
        ~InventoryList();
        void clearItems();
+       void setSize(u32 newsize);
        void serialize(std::ostream &os) const;
        void deSerialize(std::istream &is, IGameDef *gamedef);
 
@@ -513,182 +514,5 @@ private:
        core::array<InventoryList*> m_lists;
 };
 
-class Player;
-
-struct InventoryContext
-{
-       Player *current_player;
-       
-       InventoryContext():
-               current_player(NULL)
-       {}
-};
-
-struct 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 and other stuff
-       virtual void inventoryModified(InventoryContext *c, std::string id)
-               {}
-       // Used on the client
-       virtual void inventoryAction(InventoryAction *a)
-               {}
-};
-
-#define IACTION_MOVE 0
-#define IACTION_DROP 1
-
-struct InventoryAction
-{
-       static InventoryAction * deSerialize(std::istream &is);
-
-       virtual u16 getType() const = 0;
-       virtual void serialize(std::ostream &os) const = 0;
-       virtual void apply(InventoryContext *c, InventoryManager *mgr,
-                       ServerEnvironment *env) = 0;
-       virtual ~InventoryAction() {};
-};
-
-struct IMoveAction : public InventoryAction
-{
-       // count=0 means "everything"
-       u16 count;
-       std::string from_inv;
-       std::string from_list;
-       s16 from_i;
-       std::string to_inv;
-       std::string to_list;
-       s16 to_i;
-       
-       IMoveAction()
-       {
-               count = 0;
-               from_i = -1;
-               to_i = -1;
-       }
-       
-       IMoveAction(std::istream &is);
-
-       u16 getType() const
-       {
-               return IACTION_MOVE;
-       }
-
-       void serialize(std::ostream &os) const
-       {
-               os<<"Move ";
-               os<<count<<" ";
-               os<<from_inv<<" ";
-               os<<from_list<<" ";
-               os<<from_i<<" ";
-               os<<to_inv<<" ";
-               os<<to_list<<" ";
-               os<<to_i;
-       }
-
-       void apply(InventoryContext *c, InventoryManager *mgr,
-                       ServerEnvironment *env);
-};
-
-struct IDropAction : public InventoryAction
-{
-       // count=0 means "everything"
-       u16 count;
-       std::string from_inv;
-       std::string from_list;
-       s16 from_i;
-       
-       IDropAction()
-       {
-               count = 0;
-               from_i = -1;
-       }
-       
-       IDropAction(std::istream &is);
-
-       u16 getType() const
-       {
-               return IACTION_DROP;
-       }
-
-       void serialize(std::ostream &os) const
-       {
-               os<<"Drop ";
-               os<<count<<" ";
-               os<<from_inv<<" ";
-               os<<from_list<<" ";
-               os<<from_i;
-       }
-
-       void apply(InventoryContext *c, InventoryManager *mgr,
-                       ServerEnvironment *env);
-};
-
-/*
-       Craft checking system
-*/
-
-enum ItemSpecType
-{
-       ITEM_NONE,
-       ITEM_MATERIAL,
-       ITEM_CRAFT,
-       ITEM_TOOL,
-       ITEM_MBO
-};
-
-struct ItemSpec
-{
-       enum ItemSpecType type;
-       // Only other one of these is used
-       std::string name;
-       u16 num;
-
-       ItemSpec():
-               type(ITEM_NONE)
-       {
-       }
-       ItemSpec(enum ItemSpecType a_type, std::string a_name):
-               type(a_type),
-               name(a_name),
-               num(65535)
-       {
-       }
-       ItemSpec(enum ItemSpecType a_type, u16 a_num):
-               type(a_type),
-               name(""),
-               num(a_num)
-       {
-       }
-
-       bool checkItem(const InventoryItem *item) const;
-};
-
-/*
-       items: a pointer to an array of 9 pointers to items
-       specs: a pointer to an array of 9 ItemSpecs
-*/
-bool checkItemCombination(const InventoryItem * const*items, const ItemSpec *specs);
-
-/*
-       items: a pointer to an array of 9 pointers to items
-       specs: a pointer to an array of 9 pointers to items
-*/
-bool checkItemCombination(const InventoryItem * const * items,
-               const InventoryItem * const * specs);
-
 #endif
 
diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp
new file mode 100644 (file)
index 0000000..195438d
--- /dev/null
@@ -0,0 +1,544 @@
+/*
+Minetest-c55
+Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "inventorymanager.h"
+#include "serverremoteplayer.h"
+#include "log.h"
+#include "mapblock.h" // getNodeBlockPos
+
+/*
+       InventoryManager
+*/
+
+// Wrapper for old code
+Inventory* InventoryManager::getInventory(InventoryContext *c, std::string id)
+{
+       if(id == "current_player")
+       {
+               assert(c->current_player);
+               InventoryLocation loc;
+               loc.setPlayer(c->current_player->getName());
+               return getInventory(loc);
+       }
+       
+       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(","));
+
+               InventoryLocation loc;
+               loc.setNodeMeta(p);
+               return getInventory(loc);
+       }
+
+       errorstream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
+       return NULL;
+}
+// Wrapper for old code
+void InventoryManager::inventoryModified(InventoryContext *c, std::string id)
+{
+       if(id == "current_player")
+       {
+               assert(c->current_player);
+               InventoryLocation loc;
+               loc.setPlayer(c->current_player->getName());
+               setInventoryModified(loc);
+               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(","));
+               v3s16 blockpos = getNodeBlockPos(p);
+
+               InventoryLocation loc;
+               loc.setNodeMeta(p);
+               setInventoryModified(loc);
+               return;
+       }
+
+       errorstream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
+}
+
+/*
+       InventoryAction
+*/
+
+InventoryAction * InventoryAction::deSerialize(std::istream &is)
+{
+       std::string type;
+       std::getline(is, type, ' ');
+
+       InventoryAction *a = NULL;
+
+       if(type == "Move")
+       {
+               a = new IMoveAction(is);
+       }
+       else if(type == "Drop")
+       {
+               a = new IDropAction(is);
+       }
+
+       return a;
+}
+
+static std::string describeC(const struct InventoryContext *c)
+{
+       if(c->current_player == NULL)
+               return "current_player=NULL";
+       else
+               return std::string("current_player=") + c->current_player->getName();
+}
+
+IMoveAction::IMoveAction(std::istream &is)
+{
+       std::string ts;
+
+       std::getline(is, ts, ' ');
+       count = stoi(ts);
+
+       std::getline(is, from_inv, ' ');
+
+       std::getline(is, from_list, ' ');
+
+       std::getline(is, ts, ' ');
+       from_i = stoi(ts);
+
+       std::getline(is, to_inv, ' ');
+
+       std::getline(is, to_list, ' ');
+
+       std::getline(is, ts, ' ');
+       to_i = stoi(ts);
+}
+
+void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr,
+               ServerEnvironment *env)
+{
+       Inventory *inv_from = mgr->getInventory(c, from_inv);
+       Inventory *inv_to = mgr->getInventory(c, to_inv);
+       
+       if(!inv_from){
+               infostream<<"IMoveAction::apply(): FAIL: source inventory not found: "
+                               <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
+                               <<", to_inv=\""<<to_inv<<"\""<<std::endl;
+               return;
+       }
+       if(!inv_to){
+               infostream<<"IMoveAction::apply(): FAIL: destination inventory not found: "
+                               "context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
+                               <<", to_inv=\""<<to_inv<<"\""<<std::endl;
+               return;
+       }
+
+       InventoryList *list_from = inv_from->getList(from_list);
+       InventoryList *list_to = inv_to->getList(to_list);
+
+       /*
+               If a list doesn't exist or the source item doesn't exist
+       */
+       if(!list_from){
+               infostream<<"IMoveAction::apply(): FAIL: source list not found: "
+                               <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
+                               <<", from_list=\""<<from_list<<"\""<<std::endl;
+               return;
+       }
+       if(!list_to){
+               infostream<<"IMoveAction::apply(): FAIL: destination list not found: "
+                               <<"context=["<<describeC(c)<<"], to_inv=\""<<to_inv<<"\""
+                               <<", to_list=\""<<to_list<<"\""<<std::endl;
+               return;
+       }
+       if(list_from->getItem(from_i) == NULL)
+       {
+               infostream<<"IMoveAction::apply(): FAIL: source item not found: "
+                               <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
+                               <<", from_list=\""<<from_list<<"\""
+                               <<" from_i="<<from_i<<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)
+       {
+               infostream<<"IMoveAction::apply(): FAIL: source and destination slots "
+                               <<"are the same: inv=\""<<from_inv<<"\" list=\""<<from_list
+                               <<"\" i="<<from_i<<std::endl;
+               return;
+       }
+       
+       // Take item from source list
+       InventoryItem *item1 = NULL;
+       if(count == 0)
+               item1 = list_from->changeItem(from_i, NULL);
+       else
+               item1 = list_from->takeItem(from_i, count);
+
+       // Try to add the item to destination list
+       InventoryItem *olditem = item1;
+       item1 = list_to->addItem(to_i, item1);
+
+       // If something is returned, the item was not fully added
+       if(item1 != NULL)
+       {
+               // 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);
+       
+       infostream<<"IMoveAction::apply(): moved at "
+                       <<"["<<describeC(c)<<"]"
+                       <<" from inv=\""<<from_inv<<"\""
+                       <<" list=\""<<from_list<<"\""
+                       <<" i="<<from_i
+                       <<" to inv=\""<<to_inv<<"\""
+                       <<" list=\""<<to_list<<"\""
+                       <<" i="<<to_i
+                       <<std::endl;
+}
+
+IDropAction::IDropAction(std::istream &is)
+{
+       std::string ts;
+
+       std::getline(is, ts, ' ');
+       count = stoi(ts);
+
+       std::getline(is, from_inv, ' ');
+
+       std::getline(is, from_list, ' ');
+
+       std::getline(is, ts, ' ');
+       from_i = stoi(ts);
+}
+
+void IDropAction::apply(InventoryContext *c, InventoryManager *mgr,
+               ServerEnvironment *env)
+{
+       if(c->current_player == NULL){
+               infostream<<"IDropAction::apply(): FAIL: current_player is NULL"<<std::endl;
+               return;
+       }
+
+       // Do NOT cast directly to ServerActiveObject*, it breaks
+       // because of multiple inheritance.
+       ServerActiveObject *dropper =
+               static_cast<ServerActiveObject*>(
+               static_cast<ServerRemotePlayer*>(
+                       c->current_player
+               ));
+
+       Inventory *inv_from = mgr->getInventory(c, from_inv);
+       
+       if(!inv_from){
+               infostream<<"IDropAction::apply(): FAIL: source inventory not found: "
+                               <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""<<std::endl;
+               return;
+       }
+
+       InventoryList *list_from = inv_from->getList(from_list);
+
+       /*
+               If a list doesn't exist or the source item doesn't exist
+       */
+       if(!list_from){
+               infostream<<"IDropAction::apply(): FAIL: source list not found: "
+                               <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
+                               <<", from_list=\""<<from_list<<"\""<<std::endl;
+               return;
+       }
+       InventoryItem *item = list_from->getItem(from_i);
+       if(item == NULL)
+       {
+               infostream<<"IDropAction::apply(): FAIL: source item not found: "
+                               <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""
+                               <<", from_list=\""<<from_list<<"\""
+                               <<" from_i="<<from_i<<std::endl;
+               return;
+       }
+
+       v3f pos = dropper->getBasePosition();
+       pos.Y += 0.5*BS;
+
+       s16 count2 = count;
+       if(count2 == 0)
+               count2 = -1;
+
+       /*
+               Drop the item
+       */
+       bool remove = item->dropOrPlace(env, dropper, pos, false, count2);
+       if(remove)
+               list_from->deleteItem(from_i);
+
+       mgr->inventoryModified(c, from_inv);
+
+       infostream<<"IDropAction::apply(): dropped "
+                       <<"["<<describeC(c)<<"]"
+                       <<" from inv=\""<<from_inv<<"\""
+                       <<" list=\""<<from_list<<"\""
+                       <<" i="<<from_i
+                       <<std::endl;
+}
+
+/*
+       Craft checking system
+*/
+
+bool ItemSpec::checkItem(const InventoryItem *item) const
+{
+       if(type == ITEM_NONE)
+       {
+               // Has to be no item
+               if(item != NULL)
+                       return false;
+               return true;
+       }
+       
+       // There should be an item
+       if(item == NULL)
+               return false;
+
+       std::string itemname = item->getName();
+
+       if(type == ITEM_MATERIAL)
+       {
+               if(itemname != "MaterialItem")
+                       return false;
+               MaterialItem *mitem = (MaterialItem*)item;
+               if(num != 65535){
+                       if(mitem->getMaterial() != num)
+                               return false;
+               } else {
+                       if(mitem->getNodeName() != name)
+                               return false;
+               }
+       }
+       else if(type == ITEM_CRAFT)
+       {
+               if(itemname != "CraftItem")
+                       return false;
+               CraftItem *mitem = (CraftItem*)item;
+               if(mitem->getSubName() != name)
+                       return false;
+       }
+       else if(type == ITEM_TOOL)
+       {
+               // Not supported yet
+               assert(0);
+       }
+       else if(type == ITEM_MBO)
+       {
+               // Not supported yet
+               assert(0);
+       }
+       else
+       {
+               // Not supported yet
+               assert(0);
+       }
+       return true;
+}
+
+bool checkItemCombination(InventoryItem const * const *items, const ItemSpec *specs)
+{
+       u16 items_min_x = 100;
+       u16 items_max_x = 100;
+       u16 items_min_y = 100;
+       u16 items_max_y = 100;
+       for(u16 y=0; y<3; y++)
+       for(u16 x=0; x<3; x++)
+       {
+               if(items[y*3 + x] == NULL)
+                       continue;
+               if(items_min_x == 100 || x < items_min_x)
+                       items_min_x = x;
+               if(items_min_y == 100 || y < items_min_y)
+                       items_min_y = y;
+               if(items_max_x == 100 || x > items_max_x)
+                       items_max_x = x;
+               if(items_max_y == 100 || y > items_max_y)
+                       items_max_y = y;
+       }
+       // No items at all, just return false
+       if(items_min_x == 100)
+               return false;
+       
+       u16 items_w = items_max_x - items_min_x + 1;
+       u16 items_h = items_max_y - items_min_y + 1;
+
+       u16 specs_min_x = 100;
+       u16 specs_max_x = 100;
+       u16 specs_min_y = 100;
+       u16 specs_max_y = 100;
+       for(u16 y=0; y<3; y++)
+       for(u16 x=0; x<3; x++)
+       {
+               if(specs[y*3 + x].type == ITEM_NONE)
+                       continue;
+               if(specs_min_x == 100 || x < specs_min_x)
+                       specs_min_x = x;
+               if(specs_min_y == 100 || y < specs_min_y)
+                       specs_min_y = y;
+               if(specs_max_x == 100 || x > specs_max_x)
+                       specs_max_x = x;
+               if(specs_max_y == 100 || y > specs_max_y)
+                       specs_max_y = y;
+       }
+       // No specs at all, just return false
+       if(specs_min_x == 100)
+               return false;
+
+       u16 specs_w = specs_max_x - specs_min_x + 1;
+       u16 specs_h = specs_max_y - specs_min_y + 1;
+
+       // Different sizes
+       if(items_w != specs_w || items_h != specs_h)
+               return false;
+
+       for(u16 y=0; y<specs_h; y++)
+       for(u16 x=0; x<specs_w; x++)
+       {
+               u16 items_x = items_min_x + x;
+               u16 items_y = items_min_y + y;
+               u16 specs_x = specs_min_x + x;
+               u16 specs_y = specs_min_y + y;
+               const InventoryItem *item = items[items_y * 3 + items_x];
+               const ItemSpec &spec = specs[specs_y * 3 + specs_x];
+
+               if(spec.checkItem(item) == false)
+                       return false;
+       }
+
+       return true;
+}
+
+bool checkItemCombination(const InventoryItem * const * items,
+               const InventoryItem * const * specs)
+{
+       u16 items_min_x = 100;
+       u16 items_max_x = 100;
+       u16 items_min_y = 100;
+       u16 items_max_y = 100;
+       for(u16 y=0; y<3; y++)
+       for(u16 x=0; x<3; x++)
+       {
+               if(items[y*3 + x] == NULL)
+                       continue;
+               if(items_min_x == 100 || x < items_min_x)
+                       items_min_x = x;
+               if(items_min_y == 100 || y < items_min_y)
+                       items_min_y = y;
+               if(items_max_x == 100 || x > items_max_x)
+                       items_max_x = x;
+               if(items_max_y == 100 || y > items_max_y)
+                       items_max_y = y;
+       }
+       // No items at all, just return false
+       if(items_min_x == 100)
+               return false;
+       
+       u16 items_w = items_max_x - items_min_x + 1;
+       u16 items_h = items_max_y - items_min_y + 1;
+
+       u16 specs_min_x = 100;
+       u16 specs_max_x = 100;
+       u16 specs_min_y = 100;
+       u16 specs_max_y = 100;
+       for(u16 y=0; y<3; y++)
+       for(u16 x=0; x<3; x++)
+       {
+               if(specs[y*3 + x] == NULL)
+                       continue;
+               if(specs_min_x == 100 || x < specs_min_x)
+                       specs_min_x = x;
+               if(specs_min_y == 100 || y < specs_min_y)
+                       specs_min_y = y;
+               if(specs_max_x == 100 || x > specs_max_x)
+                       specs_max_x = x;
+               if(specs_max_y == 100 || y > specs_max_y)
+                       specs_max_y = y;
+       }
+       // No specs at all, just return false
+       if(specs_min_x == 100)
+               return false;
+
+       u16 specs_w = specs_max_x - specs_min_x + 1;
+       u16 specs_h = specs_max_y - specs_min_y + 1;
+
+       // Different sizes
+       if(items_w != specs_w || items_h != specs_h)
+               return false;
+
+       for(u16 y=0; y<specs_h; y++)
+       for(u16 x=0; x<specs_w; x++)
+       {
+               u16 items_x = items_min_x + x;
+               u16 items_y = items_min_y + y;
+               u16 specs_x = specs_min_x + x;
+               u16 specs_y = specs_min_y + y;
+               const InventoryItem *item = items[items_y * 3 + items_x];
+               const InventoryItem *spec = specs[specs_y * 3 + specs_x];
+               
+               if(item == NULL && spec == NULL)
+                       continue;
+               if(item == NULL && spec != NULL)
+                       return false;
+               if(item != NULL && spec == NULL)
+                       return false;
+               if(!spec->isSubsetOf(item))
+                       return false;
+       }
+
+       return true;
+}
+
+
diff --git a/src/inventorymanager.h b/src/inventorymanager.h
new file mode 100644 (file)
index 0000000..4abe5e7
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+Minetest-c55
+Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef INVENTORYMANAGER_HEADER
+#define INVENTORYMANAGER_HEADER
+
+#include "inventory.h"
+
+// Should probably somehow replace InventoryContext over time
+struct InventoryLocation
+{
+       enum Type{
+               UNDEFINED,
+               PLAYER,
+               NODEMETA
+       } type;
+
+       std::string name; // PLAYER
+       v3s16 p; // NODEMETA
+
+       void setPlayer(const std::string &name_)
+       {
+               type = PLAYER;
+               name = name_;
+       }
+       void setNodeMeta(v3s16 p_)
+       {
+               type = NODEMETA;
+               p = p_;
+       }
+};
+
+class Player;
+
+struct InventoryContext
+{
+       Player *current_player;
+       
+       InventoryContext():
+               current_player(NULL)
+       {}
+};
+
+struct InventoryAction;
+
+class InventoryManager
+{
+public:
+       InventoryManager(){}
+       virtual ~InventoryManager(){}
+       
+       // Get an inventory or set it modified (so it will be updated over
+       // network or so)
+       virtual Inventory* getInventory(const InventoryLocation &loc){return NULL;}
+       virtual void setInventoryModified(const InventoryLocation &loc){}
+
+       // Used on the client to send an action to the server
+       virtual void inventoryAction(InventoryAction *a){}
+
+       // (Deprecated; these wrap to the latter ones)
+       // Get a pointer to an inventory specified by id. id can be:
+       // - "current_player"
+       // - "nodemeta:X,Y,Z"
+       Inventory* getInventory(InventoryContext *c, std::string id);
+       // Used on the server by InventoryAction::apply and other stuff
+       void inventoryModified(InventoryContext *c, std::string id);
+};
+
+#define IACTION_MOVE 0
+#define IACTION_DROP 1
+
+struct InventoryAction
+{
+       static InventoryAction * deSerialize(std::istream &is);
+       
+       virtual u16 getType() const = 0;
+       virtual void serialize(std::ostream &os) const = 0;
+       virtual void apply(InventoryContext *c, InventoryManager *mgr,
+                       ServerEnvironment *env) = 0;
+};
+
+struct IMoveAction : public InventoryAction
+{
+       // count=0 means "everything"
+       u16 count;
+       std::string from_inv;
+       std::string from_list;
+       s16 from_i;
+       std::string to_inv;
+       std::string to_list;
+       s16 to_i;
+       
+       IMoveAction()
+       {
+               count = 0;
+               from_i = -1;
+               to_i = -1;
+       }
+       
+       IMoveAction(std::istream &is);
+
+       u16 getType() const
+       {
+               return IACTION_MOVE;
+       }
+
+       void serialize(std::ostream &os) const
+       {
+               os<<"Move ";
+               os<<count<<" ";
+               os<<from_inv<<" ";
+               os<<from_list<<" ";
+               os<<from_i<<" ";
+               os<<to_inv<<" ";
+               os<<to_list<<" ";
+               os<<to_i;
+       }
+
+       void apply(InventoryContext *c, InventoryManager *mgr,
+                       ServerEnvironment *env);
+};
+
+struct IDropAction : public InventoryAction
+{
+       // count=0 means "everything"
+       u16 count;
+       std::string from_inv;
+       std::string from_list;
+       s16 from_i;
+       
+       IDropAction()
+       {
+               count = 0;
+               from_i = -1;
+       }
+       
+       IDropAction(std::istream &is);
+
+       u16 getType() const
+       {
+               return IACTION_DROP;
+       }
+
+       void serialize(std::ostream &os) const
+       {
+               os<<"Drop ";
+               os<<count<<" ";
+               os<<from_inv<<" ";
+               os<<from_list<<" ";
+               os<<from_i;
+       }
+
+       void apply(InventoryContext *c, InventoryManager *mgr,
+                       ServerEnvironment *env);
+};
+
+/*
+       Craft checking system
+*/
+
+enum ItemSpecType
+{
+       ITEM_NONE,
+       ITEM_MATERIAL,
+       ITEM_CRAFT,
+       ITEM_TOOL,
+       ITEM_MBO
+};
+
+struct ItemSpec
+{
+       enum ItemSpecType type;
+       // Only other one of these is used
+       std::string name;
+       u16 num;
+
+       ItemSpec():
+               type(ITEM_NONE)
+       {
+       }
+       ItemSpec(enum ItemSpecType a_type, std::string a_name):
+               type(a_type),
+               name(a_name),
+               num(65535)
+       {
+       }
+       ItemSpec(enum ItemSpecType a_type, u16 a_num):
+               type(a_type),
+               name(""),
+               num(a_num)
+       {
+       }
+
+       bool checkItem(const InventoryItem *item) const;
+};
+
+/*
+       items: a pointer to an array of 9 pointers to items
+       specs: a pointer to an array of 9 ItemSpecs
+*/
+bool checkItemCombination(const InventoryItem * const*items, const ItemSpec *specs);
+
+/*
+       items: a pointer to an array of 9 pointers to items
+       specs: a pointer to an array of 9 pointers to items
+*/
+bool checkItemCombination(const InventoryItem * const * items,
+               const InventoryItem * const * specs);
+
+
+#endif
+
index 1a50e1e34e1571854c11323e229a2f5066d1a07b..f7a2ce9aae1c423f28afb96a079c226ea925b13d 100644 (file)
@@ -204,6 +204,20 @@ static v2f read_v2f(lua_State *L, int index)
        return p;
 }
 
+static Server* get_server(lua_State *L)
+{
+       // Get server from registry
+       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
+       return (Server*)lua_touserdata(L, -1);
+}
+
+static ServerEnvironment* get_env(lua_State *L)
+{
+       // Get environment from registry
+       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_env");
+       return (ServerEnvironment*)lua_touserdata(L, -1);
+}
+
 static v3f readFloatPos(lua_State *L, int index)
 {
        v3f pos;
@@ -551,6 +565,68 @@ static void inventory_get_list_to_lua(Inventory *inv, const char *name,
        }
 }
 
+static void push_stack_item(lua_State *L, InventoryItem *item0)
+{
+       if(item0 == NULL){
+               lua_pushnil(L);
+       }
+       if(std::string("MaterialItem") == item0->getName()){
+               MaterialItem *item = (MaterialItem*)item0;
+               lua_newtable(L);
+               lua_pushstring(L, "NodeItem");
+               lua_setfield(L, -2, "type");
+               lua_pushstring(L, item->getNodeName().c_str());
+               lua_setfield(L, -2, "name");
+       }
+       else if(std::string("CraftItem") == item0->getName()){
+               CraftItem *item = (CraftItem*)item0;
+               lua_newtable(L);
+               lua_pushstring(L, "CraftItem");
+               lua_setfield(L, -2, "type");
+               lua_pushstring(L, item->getSubName().c_str());
+               lua_setfield(L, -2, "name");
+       }
+       else if(std::string("ToolItem") == item0->getName()){
+               ToolItem *item = (ToolItem*)item0;
+               lua_newtable(L);
+               lua_pushstring(L, "ToolItem");
+               lua_setfield(L, -2, "type");
+               lua_pushstring(L, item->getToolName().c_str());
+               lua_setfield(L, -2, "name");
+               lua_pushstring(L, itos(item->getWear()).c_str());
+               lua_setfield(L, -2, "wear");
+       }
+       else{
+               errorstream<<"push_stack_item: Unknown item name: \""
+                               <<item0->getName()<<"\""<<std::endl;
+               lua_pushnil(L);
+       }
+}
+
+static InventoryItem* check_stack_item(lua_State *L, int index)
+{
+       if(index < 0)
+               index = lua_gettop(L) + 1 + index;
+       if(lua_isnil(L, index))
+               return NULL;
+       if(!lua_istable(L, index))
+               throw LuaError(L, "check_stack_item: Item not nil or table");
+       // A very crappy implementation for now
+       // Will be replaced when unified namespace for items is made
+       std::string type = getstringfield_default(L, index, "type", "");
+       std::string name = getstringfield_default(L, index, "name", "");
+       std::string num = getstringfield_default(L, index, "wear", "_");
+       if(num == "_")
+               num = 1;
+       std::string itemstring = type + " \"" + name + "\" " + num;
+       try{
+               return InventoryItem::deSerialize(itemstring, get_server(L));
+       }catch(SerializationError &e){
+               throw LuaError(L, std::string("check_stack_item: "
+                               "internal error (itemstring=\"")+itemstring+"\")");
+       }
+}
+
 /*
        ToolDiggingProperties
 */
@@ -835,12 +911,9 @@ static int l_register_tool(lua_State *L)
        luaL_checktype(L, 2, LUA_TTABLE);
        int table = 2;
 
-       // Get server from registry
-       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
-       Server *server = (Server*)lua_touserdata(L, -1);
-       // And get the writable tool definition manager from the server
+       // Get the writable tool definition manager from the server
        IWritableToolDefManager *tooldef =
-                       server->getWritableToolDefManager();
+                       get_server(L)->getWritableToolDefManager();
        
        ToolDefinition def = read_tool_definition(L, table);
 
@@ -857,12 +930,9 @@ static int l_register_craftitem(lua_State *L)
        luaL_checktype(L, 2, LUA_TTABLE);
        int table = 2;
 
-       // Get server from registry
-       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
-       Server *server = (Server*)lua_touserdata(L, -1);
-       // And get the writable CraftItem definition manager from the server
+       // Get the writable CraftItem definition manager from the server
        IWritableCraftItemDefManager *craftitemdef =
-                       server->getWritableCraftItemDefManager();
+                       get_server(L)->getWritableCraftItemDefManager();
        
        // Check if on_drop is defined
        lua_getfield(L, table, "on_drop");
@@ -907,12 +977,9 @@ static int l_register_node(lua_State *L)
        luaL_checktype(L, 2, LUA_TTABLE);
        int nodedef_table = 2;
 
-       // Get server from registry
-       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
-       Server *server = (Server*)lua_touserdata(L, -1);
-       // And get the writable node definition manager from the server
+       // Get the writable node definition manager from the server
        IWritableNodeDefManager *nodedef =
-                       server->getWritableNodeDefManager();
+                       get_server(L)->getWritableNodeDefManager();
        
        // Get default node definition from registry
        lua_getfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
@@ -1147,12 +1214,9 @@ static int l_alias_node(lua_State *L)
        std::string name = luaL_checkstring(L, 1);
        std::string convert_to = luaL_checkstring(L, 2);
 
-       // Get server from registry
-       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
-       Server *server = (Server*)lua_touserdata(L, -1);
-       // And get the writable node definition manager from the server
+       // Get the writable node definition manager from the server
        IWritableNodeDefManager *nodedef =
-                       server->getWritableNodeDefManager();
+                       get_server(L)->getWritableNodeDefManager();
        
        nodedef->setAlias(name, convert_to);
        
@@ -1165,12 +1229,9 @@ static int l_alias_tool(lua_State *L)
        std::string name = luaL_checkstring(L, 1);
        std::string convert_to = luaL_checkstring(L, 2);
 
-       // Get server from registry
-       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
-       Server *server = (Server*)lua_touserdata(L, -1);
-       // And get the writable tool definition manager from the server
+       // Get the writable tool definition manager from the server
        IWritableToolDefManager *tooldef =
-                       server->getWritableToolDefManager();
+                       get_server(L)->getWritableToolDefManager();
        
        tooldef->setAlias(name, convert_to);
 
@@ -1183,12 +1244,9 @@ static int l_alias_craftitem(lua_State *L)
        std::string name = luaL_checkstring(L, 1);
        std::string convert_to = luaL_checkstring(L, 2);
 
-       // Get server from registry
-       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
-       Server *server = (Server*)lua_touserdata(L, -1);
-       // And get the writable CraftItem definition manager from the server
+       // Get the writable CraftItem definition manager from the server
        IWritableCraftItemDefManager *craftitemdef =
-                       server->getWritableCraftItemDefManager();
+                       get_server(L)->getWritableCraftItemDefManager();
        
        craftitemdef->setAlias(name, convert_to);
 
@@ -1202,12 +1260,9 @@ static int l_register_craft(lua_State *L)
        luaL_checktype(L, 1, LUA_TTABLE);
        int table0 = 1;
 
-       // Get server from registry
-       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
-       Server *server = (Server*)lua_touserdata(L, -1);
-       // And get the writable craft definition manager from the server
+       // Get the writable craft definition manager from the server
        IWritableCraftDefManager *craftdef =
-                       server->getWritableCraftDefManager();
+                       get_server(L)->getWritableCraftDefManager();
        
        std::string output;
        int width = 0;
@@ -1295,8 +1350,7 @@ static int l_chat_send_all(lua_State *L)
 {
        const char *text = luaL_checkstring(L, 1);
        // Get server from registry
-       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
-       Server *server = (Server*)lua_touserdata(L, -1);
+       Server *server = get_server(L);
        // Send
        server->notifyPlayers(narrow_to_wide(text));
        return 0;
@@ -1308,8 +1362,7 @@ static int l_chat_send_player(lua_State *L)
        const char *name = luaL_checkstring(L, 1);
        const char *text = luaL_checkstring(L, 2);
        // Get server from registry
-       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
-       Server *server = (Server*)lua_touserdata(L, -1);
+       Server *server = get_server(L);
        // Send
        server->notifyPlayer(name, narrow_to_wide(text));
        return 0;
@@ -1320,8 +1373,7 @@ static int l_get_player_privs(lua_State *L)
 {
        const char *name = luaL_checkstring(L, 1);
        // Get server from registry
-       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
-       Server *server = (Server*)lua_touserdata(L, -1);
+       Server *server = get_server(L);
        // Do it
        lua_newtable(L);
        int table = lua_gettop(L);
@@ -1413,11 +1465,337 @@ static void luaentity_get(lua_State *L, u16 id)
 }
 
 /*
-       Reference wrappers
+       Object wrappers
 */
 
 #define method(class, name) {#name, class::l_##name}
 
+/*
+       InvStack
+*/
+
+class InvStack
+{
+private:
+       InventoryItem *m_stack;
+
+       static const char className[];
+       static const luaL_reg methods[];
+
+       // Exported functions
+       
+       // garbage collector
+       static int gc_object(lua_State *L) {
+               InvStack *o = *(InvStack **)(lua_touserdata(L, 1));
+               delete o;
+               return 0;
+       }
+
+       // take_item(self)
+       static int l_take_item(lua_State *L)
+       {
+               InvStack *o = checkobject(L, 1);
+               push_stack_item(L, o->m_stack);
+               if(o->m_stack->getCount() == 1){
+                       delete o->m_stack;
+                       o->m_stack = NULL;
+               } else {
+                       o->m_stack->remove(1);
+               }
+               return 1;
+       }
+
+       // put_item(self, item) -> true/false
+       static int l_put_item(lua_State *L)
+       {
+               InvStack *o = checkobject(L, 1);
+               InventoryItem *item = check_stack_item(L, 2);
+               if(!item){ // nil can always be inserted
+                       lua_pushboolean(L, true);
+                       return 1;
+               }
+               if(!item->addableTo(o->m_stack)){
+                       lua_pushboolean(L, false);
+                       return 1;
+               }
+               o->m_stack->add(1);
+               delete item;
+               lua_pushboolean(L, true);
+               return 1;
+       }
+
+public:
+       InvStack(InventoryItem *item=NULL):
+               m_stack(item)
+       {
+       }
+
+       ~InvStack()
+       {
+               delete m_stack;
+       }
+
+       static InvStack* checkobject(lua_State *L, int narg)
+       {
+               luaL_checktype(L, narg, LUA_TUSERDATA);
+               void *ud = luaL_checkudata(L, narg, className);
+               if(!ud) luaL_typerror(L, narg, className);
+               return *(InvStack**)ud;  // unbox pointer
+       }
+
+       InventoryItem* getItemCopy()
+       {
+               if(!m_stack)
+                       return NULL;
+               return m_stack->clone();
+       }
+       
+       // Creates an InvStack and leaves it on top of stack
+       static int create_object(lua_State *L)
+       {
+               InventoryItem *item = NULL;
+               if(lua_isstring(L, 1)){
+                       std::string itemstring = lua_tostring(L, 1);
+                       if(itemstring != ""){
+                               try{
+                                       IGameDef *gdef = get_server(L);
+                                       item = InventoryItem::deSerialize(itemstring, gdef);
+                               }catch(SerializationError &e){
+                               }
+                       }
+               }
+               InvStack *o = new InvStack(item);
+               *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+               luaL_getmetatable(L, className);
+               lua_setmetatable(L, -2);
+               return 1;
+       }
+       // Not callable from Lua
+       static int create(lua_State *L, InventoryItem *item)
+       {
+               InvStack *o = new InvStack(item);
+               *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+               luaL_getmetatable(L, className);
+               lua_setmetatable(L, -2);
+               return 1;
+       }
+
+       static void Register(lua_State *L)
+       {
+               lua_newtable(L);
+               int methodtable = lua_gettop(L);
+               luaL_newmetatable(L, className);
+               int metatable = lua_gettop(L);
+
+               lua_pushliteral(L, "__metatable");
+               lua_pushvalue(L, methodtable);
+               lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
+
+               lua_pushliteral(L, "__index");
+               lua_pushvalue(L, methodtable);
+               lua_settable(L, metatable);
+
+               lua_pushliteral(L, "__gc");
+               lua_pushcfunction(L, gc_object);
+               lua_settable(L, metatable);
+
+               lua_pop(L, 1);  // drop metatable
+
+               luaL_openlib(L, 0, methods, 0);  // fill methodtable
+               lua_pop(L, 1);  // drop methodtable
+
+               // Can be created from Lua (InvStack::create(itemstring))
+               lua_register(L, className, create_object);
+       }
+};
+const char InvStack::className[] = "InvStack";
+const luaL_reg InvStack::methods[] = {
+       method(InvStack, take_item),
+       method(InvStack, put_item),
+       {0,0}
+};
+
+/*
+       InvRef
+*/
+
+class InvRef
+{
+private:
+       InventoryLocation m_loc;
+
+       static const char className[];
+       static const luaL_reg methods[];
+
+       static InvRef *checkobject(lua_State *L, int narg)
+       {
+               luaL_checktype(L, narg, LUA_TUSERDATA);
+               void *ud = luaL_checkudata(L, narg, className);
+               if(!ud) luaL_typerror(L, narg, className);
+               return *(InvRef**)ud;  // unbox pointer
+       }
+       
+       static Inventory* getinv(lua_State *L, InvRef *ref)
+       {
+               return get_server(L)->getInventory(ref->m_loc);
+       }
+
+       static InventoryList* getlist(lua_State *L, InvRef *ref,
+                       const char *listname)
+       {
+               Inventory *inv = getinv(L, ref);
+               if(!inv)
+                       return NULL;
+               return inv->getList(listname);
+       }
+
+       static InventoryItem* getitem(lua_State *L, InvRef *ref,
+                       const char *listname, int i)
+       {
+               InventoryList *list = getlist(L, ref, listname);
+               if(!list)
+                       return NULL;
+               return list->getItem(i);
+       }
+
+       static void reportInventoryChange(lua_State *L, InvRef *ref)
+       {
+               // Inform other things that the inventory has changed
+               get_server(L)->setInventoryModified(ref->m_loc);
+       }
+       
+       // Exported functions
+       
+       // garbage collector
+       static int gc_object(lua_State *L) {
+               InvRef *o = *(InvRef **)(lua_touserdata(L, 1));
+               delete o;
+               return 0;
+       }
+
+       // set_size(self, listname, size)
+       static int l_set_size(lua_State *L)
+       {
+               InvRef *ref = checkobject(L, 1);
+               const char *listname = luaL_checkstring(L, 2);
+               int newsize = luaL_checknumber(L, 3);
+               Inventory *inv = getinv(L, ref);
+               if(newsize == 0){
+                       inv->deleteList(listname);
+                       return 0;
+               }
+               InventoryList *list = inv->getList(listname);
+               if(list){
+                       list->setSize(newsize);
+               } else {
+                       list = inv->addList(listname, newsize);
+               }
+               return 0;
+       }
+
+       // get_stack(self, listname, i)
+       static int l_get_stack(lua_State *L)
+       {
+               InvRef *ref = checkobject(L, 1);
+               const char *listname = luaL_checkstring(L, 2);
+               int i = luaL_checknumber(L, 3);
+               InventoryItem *item = getitem(L, ref, listname, i);
+               if(!item){
+                       InvStack::create(L, NULL);
+                       return 1;
+               }
+               InvStack::create(L, item->clone());
+               return 1;
+       }
+
+       // set_stack(self, listname, i, stack)
+       static int l_set_stack(lua_State *L)
+       {
+               InvRef *ref = checkobject(L, 1);
+               const char *listname = luaL_checkstring(L, 2);
+               int i = luaL_checknumber(L, 3);
+               InvStack *stack = InvStack::checkobject(L, 4);
+               InventoryList *list = getlist(L, ref, listname);
+               if(!list){
+                       lua_pushboolean(L, false);
+                       return 1;
+               }
+               InventoryItem *newitem = stack->getItemCopy();
+               InventoryItem *olditem = list->changeItem(i, newitem);
+               bool success = (olditem != newitem);
+               delete olditem;
+               lua_pushboolean(L, success);
+               return 1;
+       }
+
+public:
+       InvRef(const InventoryLocation &loc):
+               m_loc(loc)
+       {
+       }
+
+       ~InvRef()
+       {
+       }
+
+       // Creates an InvRef and leaves it on top of stack
+       // Not callable from Lua; all references are created on the C side.
+       static void create(lua_State *L, const InventoryLocation &loc)
+       {
+               InvRef *o = new InvRef(loc);
+               *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+               luaL_getmetatable(L, className);
+               lua_setmetatable(L, -2);
+       }
+       static void createPlayer(lua_State *L, Player *player)
+       {
+               InventoryLocation loc;
+               loc.setPlayer(player->getName());
+               create(L, loc);
+       }
+       static void createNodeMeta(lua_State *L, v3s16 p)
+       {
+               InventoryLocation loc;
+               loc.setNodeMeta(p);
+               create(L, loc);
+       }
+
+       static void Register(lua_State *L)
+       {
+               lua_newtable(L);
+               int methodtable = lua_gettop(L);
+               luaL_newmetatable(L, className);
+               int metatable = lua_gettop(L);
+
+               lua_pushliteral(L, "__metatable");
+               lua_pushvalue(L, methodtable);
+               lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
+
+               lua_pushliteral(L, "__index");
+               lua_pushvalue(L, methodtable);
+               lua_settable(L, metatable);
+
+               lua_pushliteral(L, "__gc");
+               lua_pushcfunction(L, gc_object);
+               lua_settable(L, metatable);
+
+               lua_pop(L, 1);  // drop metatable
+
+               luaL_openlib(L, 0, methods, 0);  // fill methodtable
+               lua_pop(L, 1);  // drop methodtable
+
+               // Cannot be created from Lua
+               //lua_register(L, className, create_object);
+       }
+};
+const char InvRef::className[] = "InvRef";
+const luaL_reg InvRef::methods[] = {
+       method(InvRef, set_size),
+       method(InvRef, get_stack),
+       method(InvRef, set_stack),
+       {0,0}
+};
+
 /*
        NodeMetaRef
 */
@@ -2189,41 +2567,7 @@ private:
                if(player == NULL) return 0;
                // Do it
                InventoryItem *item0 = player->getWieldedItem();
-               if(item0 == NULL){
-                       lua_pushnil(L);
-                       return 1;
-               }
-               if(std::string("MaterialItem") == item0->getName()){
-                       MaterialItem *item = (MaterialItem*)item0;
-                       lua_newtable(L);
-                       lua_pushstring(L, "NodeItem");
-                       lua_setfield(L, -2, "type");
-                       lua_pushstring(L, item->getNodeName().c_str());
-                       lua_setfield(L, -2, "name");
-               }
-               else if(std::string("CraftItem") == item0->getName()){
-                       CraftItem *item = (CraftItem*)item0;
-                       lua_newtable(L);
-                       lua_pushstring(L, "CraftItem");
-                       lua_setfield(L, -2, "type");
-                       lua_pushstring(L, item->getSubName().c_str());
-                       lua_setfield(L, -2, "name");
-               }
-               else if(std::string("ToolItem") == item0->getName()){
-                       ToolItem *item = (ToolItem*)item0;
-                       lua_newtable(L);
-                       lua_pushstring(L, "ToolItem");
-                       lua_setfield(L, -2, "type");
-                       lua_pushstring(L, item->getToolName().c_str());
-                       lua_setfield(L, -2, "name");
-                       lua_pushstring(L, itos(item->getWear()).c_str());
-                       lua_setfield(L, -2, "wear");
-               }
-               else{
-                       errorstream<<"l_get_wielded_item: Unknown item name: \""
-                                       <<item0->getName()<<"\""<<std::endl;
-                       lua_pushnil(L);
-               }
+               push_stack_item(L, item0);
                return 1;
        }
 
@@ -3236,12 +3580,9 @@ void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode,
        //infostream<<"scriptapi_environment_on_placenode"<<std::endl;
        StackUnroller stack_unroller(L);
 
-       // Get server from registry
-       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
-       Server *server = (Server*)lua_touserdata(L, -1);
-       // And get the writable node definition manager from the server
+       // Get the writable node definition manager from the server
        IWritableNodeDefManager *ndef =
-                       server->getWritableNodeDefManager();
+                       get_server(L)->getWritableNodeDefManager();
        
        // Get minetest.registered_on_placenodes
        lua_getglobal(L, "minetest");
@@ -3271,12 +3612,9 @@ void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
        //infostream<<"scriptapi_environment_on_dignode"<<std::endl;
        StackUnroller stack_unroller(L);
 
-       // Get server from registry
-       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
-       Server *server = (Server*)lua_touserdata(L, -1);
-       // And get the writable node definition manager from the server
+       // Get the writable node definition manager from the server
        IWritableNodeDefManager *ndef =
-                       server->getWritableNodeDefManager();
+                       get_server(L)->getWritableNodeDefManager();
        
        // Get minetest.registered_on_dignodes
        lua_getglobal(L, "minetest");
@@ -3306,12 +3644,9 @@ void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
        //infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
        StackUnroller stack_unroller(L);
 
-       // Get server from registry
-       lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
-       Server *server = (Server*)lua_touserdata(L, -1);
-       // And get the writable node definition manager from the server
+       // Get the writable node definition manager from the server
        IWritableNodeDefManager *ndef =
-                       server->getWritableNodeDefManager();
+                       get_server(L)->getWritableNodeDefManager();
        
        // Get minetest.registered_on_punchnodes
        lua_getglobal(L, "minetest");
index 4a0e952a8715e9eb9e5bc3993afa780b52cf7e45..3679195f366264e4db4546a98a87e6f43cd60f7b 100644 (file)
@@ -2458,7 +2458,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                        craftresult and immediately moved to the free slot.
                                */
                                do{
-                                       Inventory *inv_to = getInventory(&c, ma->to_inv);
+                                       Inventory *inv_to = InventoryManager::getInventory(&c, ma->to_inv);
                                        if(!inv_to) break;
                                        InventoryList *list_to = inv_to->getList(ma->to_list);
                                        if(!list_to) break;
@@ -3517,6 +3517,68 @@ void Server::onMapEditEvent(MapEditEvent *event)
        m_unsent_map_edit_queue.push_back(e);
 }
 
+Inventory* Server::getInventory(const InventoryLocation &loc)
+{
+       switch(loc.type){
+       case InventoryLocation::UNDEFINED:
+       {}
+       break;
+       case InventoryLocation::PLAYER:
+       {
+               Player *player = m_env->getPlayer(loc.name.c_str());
+               if(!player)
+                       return NULL;
+               return &player->inventory;
+       }
+       break;
+       case InventoryLocation::NODEMETA:
+       {
+               NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
+               if(!meta)
+                       return NULL;
+               return meta->getInventory();
+       }
+       break;
+       default:
+               assert(0);
+       }
+       return NULL;
+}
+void Server::setInventoryModified(const InventoryLocation &loc)
+{
+       switch(loc.type){
+       case InventoryLocation::UNDEFINED:
+       {}
+       break;
+       case InventoryLocation::PLAYER:
+       {
+               ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>
+                               (m_env->getPlayer(loc.name.c_str()));
+               if(!srp)
+                       return;
+               srp->m_inventory_not_sent = true;
+       }
+       break;
+       case InventoryLocation::NODEMETA:
+       {
+               v3s16 blockpos = getNodeBlockPos(loc.p);
+
+               NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
+               if(meta)
+                       meta->inventoryModified();
+               
+               MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
+               if(block)
+                       block->raiseModified(MOD_STATE_WRITE_NEEDED);
+               
+               setBlockNotSent(blockpos);
+       }
+       break;
+       default:
+               assert(0);
+       }
+}
+#if 0
 Inventory* Server::getInventory(InventoryContext *c, std::string id)
 {
        if(id == "current_player")
@@ -3534,12 +3596,10 @@ Inventory* Server::getInventory(InventoryContext *c, std::string id)
                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();
-               infostream<<"nodemeta at ("<<p.X<<","<<p.Y<<","<<p.Z<<"): "
-                               <<"no metadata found"<<std::endl;
-               return NULL;
+
+               InventoryLocation loc;
+               loc.setNodeMeta(p);
+               return getInventory(loc);
        }
 
        infostream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
@@ -3567,21 +3627,15 @@ void Server::inventoryModified(InventoryContext *c, std::string id)
                p.Z = stoi(fn.next(","));
                v3s16 blockpos = getNodeBlockPos(p);
 
-               NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
-               if(meta)
-                       meta->inventoryModified();
-               
-               MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
-               if(block)
-                       block->raiseModified(MOD_STATE_WRITE_NEEDED);
-               
-               setBlockNotSent(blockpos);
-
+               InventoryLocation loc;
+               loc.setNodeMeta(p);
+               setInventoryModified(loc);
                return;
        }
 
        infostream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
 }
+#endif
 
 core::list<PlayerInfo> Server::getPlayerInfo()
 {
index ac893817540124836eda84de2f7ccce76ee581c0..129b4ac81fe2238e56b33f4a99f084dac388b543 100644 (file)
@@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "serialization.h" // For SER_FMT_VER_INVALID
 #include "serverremoteplayer.h"
 #include "mods.h"
+#include "inventorymanager.h"
 struct LuaState;
 typedef struct lua_State lua_State;
 class IWritableToolDefManager;
@@ -413,8 +414,8 @@ public:
        /*
                Shall be called with the environment and the connection locked.
        */
-       Inventory* getInventory(InventoryContext *c, std::string id);
-       void inventoryModified(InventoryContext *c, std::string id);
+       Inventory* getInventory(const InventoryLocation &loc);
+       void setInventoryModified(const InventoryLocation &loc);
 
        // Connection must be locked when called
        std::wstring getStatusString();