)
set(common_SRCS
+ inventorymanager.cpp
mods.cpp
serverremoteplayer.cpp
content_abm.cpp
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")
infostream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
return NULL;
}
+#endif
void Client::inventoryAction(InventoryAction *a)
{
sendInventoryAction(a);
#include "clientobject.h"
#include "utility.h" // For IntervalLimiter
#include "gamedef.h"
+#include "inventorymanager.h"
struct MeshMakeData;
class IGameDef;
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
#include "utility.h"
#include "gamedef.h"
#include "inventory.h"
+#include "inventorymanager.h" // checkItemCombination
CraftPointerInput::~CraftPointerInput()
{
#include <IGUIStaticText.h>
#include <IGUIFont.h>
#include "log.h"
+#include "inventorymanager.h"
void drawInventoryItem(video::IVideoDriver *driver,
gui::IGUIFont *font,
#include "modalMenu.h"
class ITextureSource;
+class InventoryContext;
+class InventoryManager;
void drawInventoryItem(video::IVideoDriver *driver,
gui::IGUIFont *font,
#include "scriptapi.h"
#include "strfnd.h"
#include "nameidmapping.h" // For loading legacy MaterialItems
-#include "serverremoteplayer.h"
/*
InventoryItem
//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"));
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
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);
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
--- /dev/null
+/*
+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;
+}
+
+
--- /dev/null
+/*
+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
+
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;
}
}
+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
*/
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);
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");
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");
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);
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);
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);
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;
{
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;
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;
{
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);
}
/*
- 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
*/
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;
}
//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");
//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");
//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");
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;
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")
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;
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()
{
#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;
/*
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();