mirror of
https://github.com/minetest/minetest.git
synced 2024-12-24 15:12:23 +01:00
Add InvRef and InvStack (currently untested and unusable)
This commit is contained in:
parent
70ed371d0c
commit
103173fc9b
@ -94,6 +94,7 @@ configure_file(
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(common_SRCS
|
set(common_SRCS
|
||||||
|
inventorymanager.cpp
|
||||||
mods.cpp
|
mods.cpp
|
||||||
serverremoteplayer.cpp
|
serverremoteplayer.cpp
|
||||||
content_abm.cpp
|
content_abm.cpp
|
||||||
|
@ -1782,6 +1782,34 @@ InventoryContext *Client::getInventoryContext()
|
|||||||
return &m_inventory_context;
|
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)
|
Inventory* Client::getInventory(InventoryContext *c, std::string id)
|
||||||
{
|
{
|
||||||
if(id == "current_player")
|
if(id == "current_player")
|
||||||
@ -1810,6 +1838,7 @@ Inventory* Client::getInventory(InventoryContext *c, std::string id)
|
|||||||
infostream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
|
infostream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
void Client::inventoryAction(InventoryAction *a)
|
void Client::inventoryAction(InventoryAction *a)
|
||||||
{
|
{
|
||||||
sendInventoryAction(a);
|
sendInventoryAction(a);
|
||||||
|
@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "clientobject.h"
|
#include "clientobject.h"
|
||||||
#include "utility.h" // For IntervalLimiter
|
#include "utility.h" // For IntervalLimiter
|
||||||
#include "gamedef.h"
|
#include "gamedef.h"
|
||||||
|
#include "inventorymanager.h"
|
||||||
|
|
||||||
struct MeshMakeData;
|
struct MeshMakeData;
|
||||||
class IGameDef;
|
class IGameDef;
|
||||||
@ -245,7 +246,9 @@ public:
|
|||||||
|
|
||||||
InventoryContext *getInventoryContext();
|
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);
|
void inventoryAction(InventoryAction *a);
|
||||||
|
|
||||||
// Gets closest object pointed by the shootline
|
// Gets closest object pointed by the shootline
|
||||||
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "gamedef.h"
|
#include "gamedef.h"
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
|
#include "inventorymanager.h" // checkItemCombination
|
||||||
|
|
||||||
CraftPointerInput::~CraftPointerInput()
|
CraftPointerInput::~CraftPointerInput()
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <IGUIStaticText.h>
|
#include <IGUIStaticText.h>
|
||||||
#include <IGUIFont.h>
|
#include <IGUIFont.h>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "inventorymanager.h"
|
||||||
|
|
||||||
void drawInventoryItem(video::IVideoDriver *driver,
|
void drawInventoryItem(video::IVideoDriver *driver,
|
||||||
gui::IGUIFont *font,
|
gui::IGUIFont *font,
|
||||||
|
@ -27,6 +27,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "modalMenu.h"
|
#include "modalMenu.h"
|
||||||
|
|
||||||
class ITextureSource;
|
class ITextureSource;
|
||||||
|
class InventoryContext;
|
||||||
|
class InventoryManager;
|
||||||
|
|
||||||
void drawInventoryItem(video::IVideoDriver *driver,
|
void drawInventoryItem(video::IVideoDriver *driver,
|
||||||
gui::IGUIFont *font,
|
gui::IGUIFont *font,
|
||||||
|
@ -37,7 +37,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "scriptapi.h"
|
#include "scriptapi.h"
|
||||||
#include "strfnd.h"
|
#include "strfnd.h"
|
||||||
#include "nameidmapping.h" // For loading legacy MaterialItems
|
#include "nameidmapping.h" // For loading legacy MaterialItems
|
||||||
#include "serverremoteplayer.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
InventoryItem
|
InventoryItem
|
||||||
@ -567,6 +566,22 @@ void InventoryList::clearItems()
|
|||||||
//setDirty(true);
|
//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
|
void InventoryList::serialize(std::ostream &os) const
|
||||||
{
|
{
|
||||||
//os.imbue(std::locale("C"));
|
//os.imbue(std::locale("C"));
|
||||||
@ -1041,458 +1056,4 @@ const s32 Inventory::getListIndex(const std::string &name) const
|
|||||||
return -1;
|
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
|
//END
|
||||||
|
178
src/inventory.h
178
src/inventory.h
@ -419,6 +419,7 @@ public:
|
|||||||
InventoryList(std::string name, u32 size);
|
InventoryList(std::string name, u32 size);
|
||||||
~InventoryList();
|
~InventoryList();
|
||||||
void clearItems();
|
void clearItems();
|
||||||
|
void setSize(u32 newsize);
|
||||||
void serialize(std::ostream &os) const;
|
void serialize(std::ostream &os) const;
|
||||||
void deSerialize(std::istream &is, IGameDef *gamedef);
|
void deSerialize(std::istream &is, IGameDef *gamedef);
|
||||||
|
|
||||||
@ -513,182 +514,5 @@ private:
|
|||||||
core::array<InventoryList*> m_lists;
|
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
|
#endif
|
||||||
|
|
||||||
|
544
src/inventorymanager.cpp
Normal file
544
src/inventorymanager.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
228
src/inventorymanager.h
Normal file
228
src/inventorymanager.h
Normal file
@ -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
|
||||||
|
|
@ -204,6 +204,20 @@ static v2f read_v2f(lua_State *L, int index)
|
|||||||
return p;
|
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)
|
static v3f readFloatPos(lua_State *L, int index)
|
||||||
{
|
{
|
||||||
v3f pos;
|
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
|
ToolDiggingProperties
|
||||||
*/
|
*/
|
||||||
@ -835,12 +911,9 @@ static int l_register_tool(lua_State *L)
|
|||||||
luaL_checktype(L, 2, LUA_TTABLE);
|
luaL_checktype(L, 2, LUA_TTABLE);
|
||||||
int table = 2;
|
int table = 2;
|
||||||
|
|
||||||
// Get server from registry
|
// Get the writable tool definition manager from the server
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
|
||||||
Server *server = (Server*)lua_touserdata(L, -1);
|
|
||||||
// And get the writable tool definition manager from the server
|
|
||||||
IWritableToolDefManager *tooldef =
|
IWritableToolDefManager *tooldef =
|
||||||
server->getWritableToolDefManager();
|
get_server(L)->getWritableToolDefManager();
|
||||||
|
|
||||||
ToolDefinition def = read_tool_definition(L, table);
|
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);
|
luaL_checktype(L, 2, LUA_TTABLE);
|
||||||
int table = 2;
|
int table = 2;
|
||||||
|
|
||||||
// Get server from registry
|
// Get the writable CraftItem definition manager from the server
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
|
||||||
Server *server = (Server*)lua_touserdata(L, -1);
|
|
||||||
// And get the writable CraftItem definition manager from the server
|
|
||||||
IWritableCraftItemDefManager *craftitemdef =
|
IWritableCraftItemDefManager *craftitemdef =
|
||||||
server->getWritableCraftItemDefManager();
|
get_server(L)->getWritableCraftItemDefManager();
|
||||||
|
|
||||||
// Check if on_drop is defined
|
// Check if on_drop is defined
|
||||||
lua_getfield(L, table, "on_drop");
|
lua_getfield(L, table, "on_drop");
|
||||||
@ -907,12 +977,9 @@ static int l_register_node(lua_State *L)
|
|||||||
luaL_checktype(L, 2, LUA_TTABLE);
|
luaL_checktype(L, 2, LUA_TTABLE);
|
||||||
int nodedef_table = 2;
|
int nodedef_table = 2;
|
||||||
|
|
||||||
// Get server from registry
|
// Get the writable node definition manager from the server
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
|
||||||
Server *server = (Server*)lua_touserdata(L, -1);
|
|
||||||
// And get the writable node definition manager from the server
|
|
||||||
IWritableNodeDefManager *nodedef =
|
IWritableNodeDefManager *nodedef =
|
||||||
server->getWritableNodeDefManager();
|
get_server(L)->getWritableNodeDefManager();
|
||||||
|
|
||||||
// Get default node definition from registry
|
// Get default node definition from registry
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
|
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 name = luaL_checkstring(L, 1);
|
||||||
std::string convert_to = luaL_checkstring(L, 2);
|
std::string convert_to = luaL_checkstring(L, 2);
|
||||||
|
|
||||||
// Get server from registry
|
// Get the writable node definition manager from the server
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
|
||||||
Server *server = (Server*)lua_touserdata(L, -1);
|
|
||||||
// And get the writable node definition manager from the server
|
|
||||||
IWritableNodeDefManager *nodedef =
|
IWritableNodeDefManager *nodedef =
|
||||||
server->getWritableNodeDefManager();
|
get_server(L)->getWritableNodeDefManager();
|
||||||
|
|
||||||
nodedef->setAlias(name, convert_to);
|
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 name = luaL_checkstring(L, 1);
|
||||||
std::string convert_to = luaL_checkstring(L, 2);
|
std::string convert_to = luaL_checkstring(L, 2);
|
||||||
|
|
||||||
// Get server from registry
|
// Get the writable tool definition manager from the server
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
|
||||||
Server *server = (Server*)lua_touserdata(L, -1);
|
|
||||||
// And get the writable tool definition manager from the server
|
|
||||||
IWritableToolDefManager *tooldef =
|
IWritableToolDefManager *tooldef =
|
||||||
server->getWritableToolDefManager();
|
get_server(L)->getWritableToolDefManager();
|
||||||
|
|
||||||
tooldef->setAlias(name, convert_to);
|
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 name = luaL_checkstring(L, 1);
|
||||||
std::string convert_to = luaL_checkstring(L, 2);
|
std::string convert_to = luaL_checkstring(L, 2);
|
||||||
|
|
||||||
// Get server from registry
|
// Get the writable CraftItem definition manager from the server
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
|
||||||
Server *server = (Server*)lua_touserdata(L, -1);
|
|
||||||
// And get the writable CraftItem definition manager from the server
|
|
||||||
IWritableCraftItemDefManager *craftitemdef =
|
IWritableCraftItemDefManager *craftitemdef =
|
||||||
server->getWritableCraftItemDefManager();
|
get_server(L)->getWritableCraftItemDefManager();
|
||||||
|
|
||||||
craftitemdef->setAlias(name, convert_to);
|
craftitemdef->setAlias(name, convert_to);
|
||||||
|
|
||||||
@ -1202,12 +1260,9 @@ static int l_register_craft(lua_State *L)
|
|||||||
luaL_checktype(L, 1, LUA_TTABLE);
|
luaL_checktype(L, 1, LUA_TTABLE);
|
||||||
int table0 = 1;
|
int table0 = 1;
|
||||||
|
|
||||||
// Get server from registry
|
// Get the writable craft definition manager from the server
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
|
||||||
Server *server = (Server*)lua_touserdata(L, -1);
|
|
||||||
// And get the writable craft definition manager from the server
|
|
||||||
IWritableCraftDefManager *craftdef =
|
IWritableCraftDefManager *craftdef =
|
||||||
server->getWritableCraftDefManager();
|
get_server(L)->getWritableCraftDefManager();
|
||||||
|
|
||||||
std::string output;
|
std::string output;
|
||||||
int width = 0;
|
int width = 0;
|
||||||
@ -1295,8 +1350,7 @@ static int l_chat_send_all(lua_State *L)
|
|||||||
{
|
{
|
||||||
const char *text = luaL_checkstring(L, 1);
|
const char *text = luaL_checkstring(L, 1);
|
||||||
// Get server from registry
|
// Get server from registry
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
Server *server = get_server(L);
|
||||||
Server *server = (Server*)lua_touserdata(L, -1);
|
|
||||||
// Send
|
// Send
|
||||||
server->notifyPlayers(narrow_to_wide(text));
|
server->notifyPlayers(narrow_to_wide(text));
|
||||||
return 0;
|
return 0;
|
||||||
@ -1308,8 +1362,7 @@ static int l_chat_send_player(lua_State *L)
|
|||||||
const char *name = luaL_checkstring(L, 1);
|
const char *name = luaL_checkstring(L, 1);
|
||||||
const char *text = luaL_checkstring(L, 2);
|
const char *text = luaL_checkstring(L, 2);
|
||||||
// Get server from registry
|
// Get server from registry
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
Server *server = get_server(L);
|
||||||
Server *server = (Server*)lua_touserdata(L, -1);
|
|
||||||
// Send
|
// Send
|
||||||
server->notifyPlayer(name, narrow_to_wide(text));
|
server->notifyPlayer(name, narrow_to_wide(text));
|
||||||
return 0;
|
return 0;
|
||||||
@ -1320,8 +1373,7 @@ static int l_get_player_privs(lua_State *L)
|
|||||||
{
|
{
|
||||||
const char *name = luaL_checkstring(L, 1);
|
const char *name = luaL_checkstring(L, 1);
|
||||||
// Get server from registry
|
// Get server from registry
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
Server *server = get_server(L);
|
||||||
Server *server = (Server*)lua_touserdata(L, -1);
|
|
||||||
// Do it
|
// Do it
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
int table = lua_gettop(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}
|
#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
|
NodeMetaRef
|
||||||
*/
|
*/
|
||||||
@ -2189,41 +2567,7 @@ private:
|
|||||||
if(player == NULL) return 0;
|
if(player == NULL) return 0;
|
||||||
// Do it
|
// Do it
|
||||||
InventoryItem *item0 = player->getWieldedItem();
|
InventoryItem *item0 = player->getWieldedItem();
|
||||||
if(item0 == NULL){
|
push_stack_item(L, item0);
|
||||||
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);
|
|
||||||
}
|
|
||||||
return 1;
|
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;
|
//infostream<<"scriptapi_environment_on_placenode"<<std::endl;
|
||||||
StackUnroller stack_unroller(L);
|
StackUnroller stack_unroller(L);
|
||||||
|
|
||||||
// Get server from registry
|
// Get the writable node definition manager from the server
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
|
||||||
Server *server = (Server*)lua_touserdata(L, -1);
|
|
||||||
// And get the writable node definition manager from the server
|
|
||||||
IWritableNodeDefManager *ndef =
|
IWritableNodeDefManager *ndef =
|
||||||
server->getWritableNodeDefManager();
|
get_server(L)->getWritableNodeDefManager();
|
||||||
|
|
||||||
// Get minetest.registered_on_placenodes
|
// Get minetest.registered_on_placenodes
|
||||||
lua_getglobal(L, "minetest");
|
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;
|
//infostream<<"scriptapi_environment_on_dignode"<<std::endl;
|
||||||
StackUnroller stack_unroller(L);
|
StackUnroller stack_unroller(L);
|
||||||
|
|
||||||
// Get server from registry
|
// Get the writable node definition manager from the server
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
|
||||||
Server *server = (Server*)lua_touserdata(L, -1);
|
|
||||||
// And get the writable node definition manager from the server
|
|
||||||
IWritableNodeDefManager *ndef =
|
IWritableNodeDefManager *ndef =
|
||||||
server->getWritableNodeDefManager();
|
get_server(L)->getWritableNodeDefManager();
|
||||||
|
|
||||||
// Get minetest.registered_on_dignodes
|
// Get minetest.registered_on_dignodes
|
||||||
lua_getglobal(L, "minetest");
|
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;
|
//infostream<<"scriptapi_environment_on_punchnode"<<std::endl;
|
||||||
StackUnroller stack_unroller(L);
|
StackUnroller stack_unroller(L);
|
||||||
|
|
||||||
// Get server from registry
|
// Get the writable node definition manager from the server
|
||||||
lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
|
|
||||||
Server *server = (Server*)lua_touserdata(L, -1);
|
|
||||||
// And get the writable node definition manager from the server
|
|
||||||
IWritableNodeDefManager *ndef =
|
IWritableNodeDefManager *ndef =
|
||||||
server->getWritableNodeDefManager();
|
get_server(L)->getWritableNodeDefManager();
|
||||||
|
|
||||||
// Get minetest.registered_on_punchnodes
|
// Get minetest.registered_on_punchnodes
|
||||||
lua_getglobal(L, "minetest");
|
lua_getglobal(L, "minetest");
|
||||||
|
@ -2458,7 +2458,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
craftresult and immediately moved to the free slot.
|
craftresult and immediately moved to the free slot.
|
||||||
*/
|
*/
|
||||||
do{
|
do{
|
||||||
Inventory *inv_to = getInventory(&c, ma->to_inv);
|
Inventory *inv_to = InventoryManager::getInventory(&c, ma->to_inv);
|
||||||
if(!inv_to) break;
|
if(!inv_to) break;
|
||||||
InventoryList *list_to = inv_to->getList(ma->to_list);
|
InventoryList *list_to = inv_to->getList(ma->to_list);
|
||||||
if(!list_to) break;
|
if(!list_to) break;
|
||||||
@ -3517,6 +3517,68 @@ void Server::onMapEditEvent(MapEditEvent *event)
|
|||||||
m_unsent_map_edit_queue.push_back(e);
|
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)
|
Inventory* Server::getInventory(InventoryContext *c, std::string id)
|
||||||
{
|
{
|
||||||
if(id == "current_player")
|
if(id == "current_player")
|
||||||
@ -3534,12 +3596,10 @@ Inventory* Server::getInventory(InventoryContext *c, std::string id)
|
|||||||
p.X = stoi(fn.next(","));
|
p.X = stoi(fn.next(","));
|
||||||
p.Y = stoi(fn.next(","));
|
p.Y = stoi(fn.next(","));
|
||||||
p.Z = stoi(fn.next(","));
|
p.Z = stoi(fn.next(","));
|
||||||
NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
|
|
||||||
if(meta)
|
InventoryLocation loc;
|
||||||
return meta->getInventory();
|
loc.setNodeMeta(p);
|
||||||
infostream<<"nodemeta at ("<<p.X<<","<<p.Y<<","<<p.Z<<"): "
|
return getInventory(loc);
|
||||||
<<"no metadata found"<<std::endl;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
infostream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
|
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(","));
|
p.Z = stoi(fn.next(","));
|
||||||
v3s16 blockpos = getNodeBlockPos(p);
|
v3s16 blockpos = getNodeBlockPos(p);
|
||||||
|
|
||||||
NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
|
InventoryLocation loc;
|
||||||
if(meta)
|
loc.setNodeMeta(p);
|
||||||
meta->inventoryModified();
|
setInventoryModified(loc);
|
||||||
|
|
||||||
MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
|
|
||||||
if(block)
|
|
||||||
block->raiseModified(MOD_STATE_WRITE_NEEDED);
|
|
||||||
|
|
||||||
setBlockNotSent(blockpos);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
infostream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
|
infostream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
core::list<PlayerInfo> Server::getPlayerInfo()
|
core::list<PlayerInfo> Server::getPlayerInfo()
|
||||||
{
|
{
|
||||||
|
@ -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 "serialization.h" // For SER_FMT_VER_INVALID
|
||||||
#include "serverremoteplayer.h"
|
#include "serverremoteplayer.h"
|
||||||
#include "mods.h"
|
#include "mods.h"
|
||||||
|
#include "inventorymanager.h"
|
||||||
struct LuaState;
|
struct LuaState;
|
||||||
typedef struct lua_State lua_State;
|
typedef struct lua_State lua_State;
|
||||||
class IWritableToolDefManager;
|
class IWritableToolDefManager;
|
||||||
@ -413,8 +414,8 @@ public:
|
|||||||
/*
|
/*
|
||||||
Shall be called with the environment and the connection locked.
|
Shall be called with the environment and the connection locked.
|
||||||
*/
|
*/
|
||||||
Inventory* getInventory(InventoryContext *c, std::string id);
|
Inventory* getInventory(const InventoryLocation &loc);
|
||||||
void inventoryModified(InventoryContext *c, std::string id);
|
void setInventoryModified(const InventoryLocation &loc);
|
||||||
|
|
||||||
// Connection must be locked when called
|
// Connection must be locked when called
|
||||||
std::wstring getStatusString();
|
std::wstring getStatusString();
|
||||||
|
Loading…
Reference in New Issue
Block a user