mirror of
https://github.com/luanti-org/luanti.git
synced 2025-08-01 17:38:41 +00:00
Detached inventory callbacks and reworked node metadata callbacks
This commit is contained in:
parent
2ac20982e0
commit
9eaf93d41d
11 changed files with 827 additions and 247 deletions
|
@ -215,10 +215,9 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
|||
}
|
||||
else{
|
||||
invsize.Y = stof(f.next(";"));
|
||||
errorstream<<"WARNING: invsize is deprecated, use size"<<std::endl;
|
||||
f.next("]");
|
||||
}
|
||||
infostream<<"size ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl;
|
||||
infostream<<"Form size ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl;
|
||||
|
||||
padding = v2s32(screensize.Y/40, screensize.Y/40);
|
||||
spacing = v2s32(screensize.Y/12, screensize.Y/13);
|
||||
|
|
|
@ -41,25 +41,25 @@ std::string InventoryLocation::dump() const
|
|||
|
||||
void InventoryLocation::serialize(std::ostream &os) const
|
||||
{
|
||||
switch(type){
|
||||
case InventoryLocation::UNDEFINED:
|
||||
os<<"undefined";
|
||||
break;
|
||||
case InventoryLocation::CURRENT_PLAYER:
|
||||
os<<"current_player";
|
||||
break;
|
||||
case InventoryLocation::PLAYER:
|
||||
os<<"player:"<<name;
|
||||
break;
|
||||
case InventoryLocation::NODEMETA:
|
||||
os<<"nodemeta:"<<p.X<<","<<p.Y<<","<<p.Z;
|
||||
break;
|
||||
case InventoryLocation::DETACHED:
|
||||
os<<"detached:"<<name;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
switch(type){
|
||||
case InventoryLocation::UNDEFINED:
|
||||
os<<"undefined";
|
||||
break;
|
||||
case InventoryLocation::CURRENT_PLAYER:
|
||||
os<<"current_player";
|
||||
break;
|
||||
case InventoryLocation::PLAYER:
|
||||
os<<"player:"<<name;
|
||||
break;
|
||||
case InventoryLocation::NODEMETA:
|
||||
os<<"nodemeta:"<<p.X<<","<<p.Y<<","<<p.Z;
|
||||
break;
|
||||
case InventoryLocation::DETACHED:
|
||||
os<<"detached:"<<name;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryLocation::deSerialize(std::istream &is)
|
||||
|
@ -198,77 +198,96 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
|
|||
<<", to_list=\""<<to_list<<"\""<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Collect information of endpoints
|
||||
*/
|
||||
|
||||
int try_take_count = count;
|
||||
if(try_take_count == 0)
|
||||
try_take_count = list_from->getItem(from_i).count;
|
||||
|
||||
int src_can_take_count = 0xffff;
|
||||
int dst_can_put_count = 0xffff;
|
||||
|
||||
// Handle node metadata move
|
||||
if(from_inv.type == InventoryLocation::NODEMETA &&
|
||||
to_inv.type == InventoryLocation::NODEMETA &&
|
||||
from_inv.p != to_inv.p)
|
||||
/* Query detached inventories */
|
||||
|
||||
// Move occurs in the same detached inventory
|
||||
if(from_inv.type == InventoryLocation::DETACHED &&
|
||||
to_inv.type == InventoryLocation::DETACHED &&
|
||||
from_inv.name == to_inv.name)
|
||||
{
|
||||
errorstream<<"Directly moving items between two nodes is "
|
||||
<<"disallowed."<<std::endl;
|
||||
return;
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
src_can_take_count = scriptapi_detached_inventory_allow_move(
|
||||
L, from_inv.name, from_list, from_i,
|
||||
to_list, to_i, try_take_count, player);
|
||||
dst_can_put_count = src_can_take_count;
|
||||
}
|
||||
else if(from_inv.type == InventoryLocation::NODEMETA &&
|
||||
else
|
||||
{
|
||||
// Destination is detached
|
||||
if(to_inv.type == InventoryLocation::DETACHED)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
ItemStack src_item = list_from->getItem(from_i);
|
||||
src_item.count = try_take_count;
|
||||
dst_can_put_count = scriptapi_detached_inventory_allow_put(
|
||||
L, to_inv.name, to_list, to_i, src_item, player);
|
||||
}
|
||||
// Source is detached
|
||||
if(from_inv.type == InventoryLocation::DETACHED)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
src_can_take_count = scriptapi_detached_inventory_allow_take(
|
||||
L, from_inv.name, from_list, from_i, try_take_count, player);
|
||||
}
|
||||
}
|
||||
|
||||
/* Query node metadata inventories */
|
||||
|
||||
// Both endpoints are nodemeta
|
||||
// Move occurs in the same nodemeta inventory
|
||||
if(from_inv.type == InventoryLocation::NODEMETA &&
|
||||
to_inv.type == InventoryLocation::NODEMETA &&
|
||||
from_inv.p == to_inv.p)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
int count0 = count;
|
||||
if(count0 == 0)
|
||||
count0 = list_from->getItem(from_i).count;
|
||||
infostream<<player->getDescription()<<" moving "<<count0
|
||||
<<" items inside node at "<<PP(from_inv.p)<<std::endl;
|
||||
scriptapi_node_on_metadata_inventory_move(L, from_inv.p,
|
||||
from_list, from_i, to_list, to_i, count0, player);
|
||||
src_can_take_count = scriptapi_nodemeta_inventory_allow_move(
|
||||
L, from_inv.p, from_list, from_i,
|
||||
to_list, to_i, try_take_count, player);
|
||||
dst_can_put_count = src_can_take_count;
|
||||
}
|
||||
// Handle node metadata take
|
||||
else if(from_inv.type == InventoryLocation::NODEMETA)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
int count0 = count;
|
||||
if(count0 == 0)
|
||||
count0 = list_from->getItem(from_i).count;
|
||||
infostream<<player->getDescription()<<" taking "<<count0
|
||||
<<" items from node at "<<PP(from_inv.p)<<std::endl;
|
||||
ItemStack return_stack = scriptapi_node_on_metadata_inventory_take(
|
||||
L, from_inv.p, from_list, from_i, count0, player);
|
||||
if(return_stack.count == 0)
|
||||
infostream<<"Node metadata gave no items"<<std::endl;
|
||||
return_stack = list_to->addItem(to_i, return_stack);
|
||||
list_to->addItem(return_stack); // Force return of everything
|
||||
}
|
||||
// Handle node metadata offer
|
||||
else if(to_inv.type == InventoryLocation::NODEMETA)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
int count0 = count;
|
||||
if(count0 == 0)
|
||||
count0 = list_from->getItem(from_i).count;
|
||||
ItemStack offer_stack = list_from->takeItem(from_i, count0);
|
||||
infostream<<player->getDescription()<<" offering "
|
||||
<<offer_stack.count<<" items to node at "
|
||||
<<PP(to_inv.p)<<std::endl;
|
||||
ItemStack reject_stack = scriptapi_node_on_metadata_inventory_offer(
|
||||
L, to_inv.p, to_list, to_i, offer_stack, player);
|
||||
if(reject_stack.count == offer_stack.count)
|
||||
infostream<<"Node metadata rejected all items"<<std::endl;
|
||||
else if(reject_stack.count != 0)
|
||||
infostream<<"Node metadata rejected some items"<<std::endl;
|
||||
reject_stack = list_from->addItem(from_i, reject_stack);
|
||||
list_from->addItem(reject_stack); // Force return of everything
|
||||
}
|
||||
// Handle regular move
|
||||
else
|
||||
{
|
||||
/*
|
||||
This performs the actual movement
|
||||
|
||||
If something is wrong (source item is empty, destination is the
|
||||
same as source), nothing happens
|
||||
*/
|
||||
list_from->moveItem(from_i, list_to, to_i, count);
|
||||
|
||||
infostream<<"IMoveAction::apply(): moved "
|
||||
// Destination is nodemeta
|
||||
if(to_inv.type == InventoryLocation::NODEMETA)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
ItemStack src_item = list_from->getItem(from_i);
|
||||
src_item.count = try_take_count;
|
||||
dst_can_put_count = scriptapi_nodemeta_inventory_allow_put(
|
||||
L, to_inv.p, to_list, to_i, src_item, player);
|
||||
}
|
||||
// Source is nodemeta
|
||||
if(from_inv.type == InventoryLocation::NODEMETA)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
src_can_take_count = scriptapi_nodemeta_inventory_allow_take(
|
||||
L, from_inv.p, from_list, from_i, try_take_count, player);
|
||||
}
|
||||
}
|
||||
|
||||
/* Modify count according to collected data */
|
||||
int new_count = try_take_count;
|
||||
if(new_count > src_can_take_count)
|
||||
new_count = src_can_take_count;
|
||||
if(new_count > dst_can_put_count)
|
||||
new_count = dst_can_put_count;
|
||||
|
||||
/* If no items will be moved, don't go further */
|
||||
if(new_count == 0)
|
||||
{
|
||||
infostream<<"IMoveAction::apply(): move was completely disallowed: "
|
||||
<<" count="<<count
|
||||
<<" from inv=\""<<from_inv.dump()<<"\""
|
||||
<<" list=\""<<from_list<<"\""
|
||||
|
@ -277,6 +296,98 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
|
|||
<<" list=\""<<to_list<<"\""
|
||||
<<" i="<<to_i
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
count = new_count;
|
||||
|
||||
/*
|
||||
Perform actual move
|
||||
|
||||
If something is wrong (source item is empty, destination is the
|
||||
same as source), nothing happens
|
||||
*/
|
||||
list_from->moveItem(from_i, list_to, to_i, count);
|
||||
|
||||
infostream<<"IMoveAction::apply(): moved "
|
||||
<<" count="<<count
|
||||
<<" from inv=\""<<from_inv.dump()<<"\""
|
||||
<<" list=\""<<from_list<<"\""
|
||||
<<" i="<<from_i
|
||||
<<" to inv=\""<<to_inv.dump()<<"\""
|
||||
<<" list=\""<<to_list<<"\""
|
||||
<<" i="<<to_i
|
||||
<<std::endl;
|
||||
|
||||
/*
|
||||
Report move to endpoints
|
||||
*/
|
||||
|
||||
/* Detached inventories */
|
||||
|
||||
// Both endpoints are same detached
|
||||
if(from_inv.type == InventoryLocation::DETACHED &&
|
||||
to_inv.type == InventoryLocation::DETACHED &&
|
||||
from_inv.name == to_inv.name)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
scriptapi_detached_inventory_on_move(
|
||||
L, from_inv.name, from_list, from_i,
|
||||
to_list, to_i, count, player);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Destination is detached
|
||||
if(to_inv.type == InventoryLocation::DETACHED)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
ItemStack src_item = list_from->getItem(from_i);
|
||||
src_item.count = count;
|
||||
scriptapi_detached_inventory_on_put(
|
||||
L, to_inv.name, to_list, to_i, src_item, player);
|
||||
}
|
||||
// Source is detached
|
||||
if(from_inv.type == InventoryLocation::DETACHED)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
ItemStack src_item = list_from->getItem(from_i);
|
||||
src_item.count = count;
|
||||
scriptapi_detached_inventory_on_take(
|
||||
L, from_inv.name, from_list, from_i, src_item.count, player);
|
||||
}
|
||||
}
|
||||
|
||||
/* Node metadata inventories */
|
||||
|
||||
// Both endpoints are same nodemeta
|
||||
if(from_inv.type == InventoryLocation::NODEMETA &&
|
||||
to_inv.type == InventoryLocation::NODEMETA &&
|
||||
from_inv.p == to_inv.p)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
scriptapi_nodemeta_inventory_on_move(
|
||||
L, from_inv.p, from_list, from_i,
|
||||
to_list, to_i, count, player);
|
||||
}
|
||||
else{
|
||||
// Destination is nodemeta
|
||||
if(to_inv.type == InventoryLocation::NODEMETA)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
ItemStack src_item = list_from->getItem(from_i);
|
||||
src_item.count = count;
|
||||
scriptapi_nodemeta_inventory_on_put(
|
||||
L, to_inv.p, to_list, to_i, src_item, player);
|
||||
}
|
||||
// Source is nodemeta
|
||||
else if(from_inv.type == InventoryLocation::NODEMETA)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
ItemStack src_item = list_from->getItem(from_i);
|
||||
src_item.count = count;
|
||||
scriptapi_nodemeta_inventory_on_take(
|
||||
L, from_inv.p, from_list, from_i, src_item.count, player);
|
||||
}
|
||||
}
|
||||
|
||||
mgr->setInventoryModified(from_inv);
|
||||
|
@ -361,47 +472,61 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
|
|||
return;
|
||||
}
|
||||
|
||||
ItemStack item1;
|
||||
/*
|
||||
Collect information of endpoints
|
||||
*/
|
||||
|
||||
// Handle node metadata take
|
||||
int take_count = list_from->getItem(from_i).count;
|
||||
if(count != 0 && count < take_count)
|
||||
take_count = count;
|
||||
int src_can_take_count = take_count;
|
||||
|
||||
// Source is detached
|
||||
if(from_inv.type == InventoryLocation::DETACHED)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
src_can_take_count = scriptapi_detached_inventory_allow_take(
|
||||
L, from_inv.name, from_list, from_i, take_count, player);
|
||||
}
|
||||
|
||||
// Source is nodemeta
|
||||
if(from_inv.type == InventoryLocation::NODEMETA)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
int count0 = count;
|
||||
if(count0 == 0)
|
||||
count0 = list_from->getItem(from_i).count;
|
||||
infostream<<player->getDescription()<<" dropping "<<count0
|
||||
<<" items from node at "<<PP(from_inv.p)<<std::endl;
|
||||
ItemStack return_stack = scriptapi_node_on_metadata_inventory_take(
|
||||
L, from_inv.p, from_list, from_i, count0, player);
|
||||
if(return_stack.count == 0)
|
||||
infostream<<"Node metadata gave no items"<<std::endl;
|
||||
item1 = return_stack;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Take item from source list
|
||||
if(count == 0)
|
||||
item1 = list_from->changeItem(from_i, ItemStack());
|
||||
else
|
||||
item1 = list_from->takeItem(from_i, count);
|
||||
src_can_take_count = scriptapi_nodemeta_inventory_allow_take(
|
||||
L, from_inv.p, from_list, from_i, take_count, player);
|
||||
}
|
||||
|
||||
// Drop the item and apply the returned ItemStack
|
||||
ItemStack item2 = item1;
|
||||
if(scriptapi_item_on_drop(player->getEnv()->getLua(), item2, player,
|
||||
if(src_can_take_count < take_count)
|
||||
take_count = src_can_take_count;
|
||||
|
||||
int actually_dropped_count = 0;
|
||||
|
||||
// Drop the item
|
||||
ItemStack item1 = list_from->getItem(from_i);
|
||||
if(scriptapi_item_on_drop(player->getEnv()->getLua(), item1, player,
|
||||
player->getBasePosition() + v3f(0,1,0)))
|
||||
{
|
||||
actually_dropped_count = take_count - item1.count;
|
||||
|
||||
if(actually_dropped_count == 0){
|
||||
infostream<<"Actually dropped no items"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't remove from inventory in creative mode
|
||||
if(g_settings->getBool("creative_mode") == true
|
||||
&& from_inv.type == InventoryLocation::PLAYER)
|
||||
item2 = item1; // creative mode
|
||||
&& from_inv.type == InventoryLocation::PLAYER){
|
||||
}
|
||||
else{
|
||||
// Take item from source list
|
||||
ItemStack item2 = list_from->takeItem(from_i, actually_dropped_count);
|
||||
|
||||
list_from->addItem(from_i, item2);
|
||||
|
||||
// Unless we have put the same amount back as we took in the first place,
|
||||
// set inventory modified flag
|
||||
if(item2.count != item1.count)
|
||||
if(item2.count != actually_dropped_count)
|
||||
errorstream<<"Could not take dropped count of items"<<std::endl;
|
||||
|
||||
mgr->setInventoryModified(from_inv);
|
||||
}
|
||||
}
|
||||
|
||||
infostream<<"IDropAction::apply(): dropped "
|
||||
|
@ -409,6 +534,26 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
|
|||
<<" list=\""<<from_list<<"\""
|
||||
<<" i="<<from_i
|
||||
<<std::endl;
|
||||
|
||||
/*
|
||||
Report drop to endpoints
|
||||
*/
|
||||
|
||||
// Source is detached
|
||||
if(from_inv.type == InventoryLocation::DETACHED)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
scriptapi_detached_inventory_on_take(
|
||||
L, from_inv.name, from_list, from_i, actually_dropped_count, player);
|
||||
}
|
||||
|
||||
// Source is nodemeta
|
||||
if(from_inv.type == InventoryLocation::NODEMETA)
|
||||
{
|
||||
lua_State *L = player->getEnv()->getLua();
|
||||
scriptapi_nodemeta_inventory_on_take(
|
||||
L, from_inv.p, from_list, from_i, actually_dropped_count, player);
|
||||
}
|
||||
}
|
||||
|
||||
void IDropAction::clientApply(InventoryManager *mgr, IGameDef *gamedef)
|
||||
|
|
|
@ -4579,8 +4579,8 @@ static int l_get_inventory(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// create_detached_inventory(name)
|
||||
static int l_create_detached_inventory(lua_State *L)
|
||||
// create_detached_inventory_raw(name)
|
||||
static int l_create_detached_inventory_raw(lua_State *L)
|
||||
{
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
if(get_server(L)->createDetachedInventory(name) != NULL){
|
||||
|
@ -4866,7 +4866,7 @@ static const struct luaL_Reg minetest_f [] = {
|
|||
{"chat_send_player", l_chat_send_player},
|
||||
{"get_player_privs", l_get_player_privs},
|
||||
{"get_inventory", l_get_inventory},
|
||||
{"create_detached_inventory", l_create_detached_inventory},
|
||||
{"create_detached_inventory_raw", l_create_detached_inventory_raw},
|
||||
{"get_dig_params", l_get_dig_params},
|
||||
{"get_hit_params", l_get_hit_params},
|
||||
{"get_current_modname", l_get_current_modname},
|
||||
|
@ -5734,7 +5734,128 @@ void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p,
|
|||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
void scriptapi_node_on_metadata_inventory_move(lua_State *L, v3s16 p,
|
||||
/*
|
||||
Node metadata inventory callbacks
|
||||
*/
|
||||
|
||||
// Return number of accepted items to be moved
|
||||
int scriptapi_nodemeta_inventory_allow_move(lua_State *L, v3s16 p,
|
||||
const std::string &from_list, int from_index,
|
||||
const std::string &to_list, int to_index,
|
||||
int count, ServerActiveObject *player)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
INodeDefManager *ndef = get_server(L)->ndef();
|
||||
|
||||
// If node doesn't exist, we don't know what callback to call
|
||||
MapNode node = get_env(L)->getMap().getNodeNoEx(p);
|
||||
if(node.getContent() == CONTENT_IGNORE)
|
||||
return 0;
|
||||
|
||||
// Push callback function on stack
|
||||
if(!get_item_callback(L, ndef->get(node).name.c_str(),
|
||||
"allow_metadata_inventory_move"))
|
||||
return count;
|
||||
|
||||
// function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
// pos
|
||||
push_v3s16(L, p);
|
||||
// from_list
|
||||
lua_pushstring(L, from_list.c_str());
|
||||
// from_index
|
||||
lua_pushinteger(L, from_index + 1);
|
||||
// to_list
|
||||
lua_pushstring(L, to_list.c_str());
|
||||
// to_index
|
||||
lua_pushinteger(L, to_index + 1);
|
||||
// count
|
||||
lua_pushinteger(L, count);
|
||||
// player
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 7, 1, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
return luaL_checkinteger(L, -1);
|
||||
}
|
||||
|
||||
// Return number of accepted items to be put
|
||||
int scriptapi_nodemeta_inventory_allow_put(lua_State *L, v3s16 p,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
INodeDefManager *ndef = get_server(L)->ndef();
|
||||
|
||||
// If node doesn't exist, we don't know what callback to call
|
||||
MapNode node = get_env(L)->getMap().getNodeNoEx(p);
|
||||
if(node.getContent() == CONTENT_IGNORE)
|
||||
return 0;
|
||||
|
||||
// Push callback function on stack
|
||||
if(!get_item_callback(L, ndef->get(node).name.c_str(),
|
||||
"allow_metadata_inventory_put"))
|
||||
return stack.count;
|
||||
|
||||
// Call function(pos, listname, index, stack, player)
|
||||
// pos
|
||||
push_v3s16(L, p);
|
||||
// listname
|
||||
lua_pushstring(L, listname.c_str());
|
||||
// index
|
||||
lua_pushinteger(L, index + 1);
|
||||
// stack
|
||||
LuaItemStack::create(L, stack);
|
||||
// player
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 5, 1, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
return luaL_checkinteger(L, -1);
|
||||
}
|
||||
|
||||
// Return number of accepted items to be taken
|
||||
int scriptapi_nodemeta_inventory_allow_take(lua_State *L, v3s16 p,
|
||||
const std::string &listname, int index, int count,
|
||||
ServerActiveObject *player)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
INodeDefManager *ndef = get_server(L)->ndef();
|
||||
|
||||
// If node doesn't exist, we don't know what callback to call
|
||||
MapNode node = get_env(L)->getMap().getNodeNoEx(p);
|
||||
if(node.getContent() == CONTENT_IGNORE)
|
||||
return 0;
|
||||
|
||||
// Push callback function on stack
|
||||
if(!get_item_callback(L, ndef->get(node).name.c_str(),
|
||||
"allow_metadata_inventory_take"))
|
||||
return count;
|
||||
|
||||
// Call function(pos, listname, index, count, player)
|
||||
// pos
|
||||
push_v3s16(L, p);
|
||||
// listname
|
||||
lua_pushstring(L, listname.c_str());
|
||||
// index
|
||||
lua_pushinteger(L, index + 1);
|
||||
// count
|
||||
lua_pushinteger(L, count);
|
||||
// player
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 5, 1, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
return luaL_checkinteger(L, -1);
|
||||
}
|
||||
|
||||
// Report moved items
|
||||
void scriptapi_nodemeta_inventory_on_move(lua_State *L, v3s16 p,
|
||||
const std::string &from_list, int from_index,
|
||||
const std::string &to_list, int to_index,
|
||||
int count, ServerActiveObject *player)
|
||||
|
@ -5756,18 +5877,26 @@ void scriptapi_node_on_metadata_inventory_move(lua_State *L, v3s16 p,
|
|||
return;
|
||||
|
||||
// function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
// pos
|
||||
push_v3s16(L, p);
|
||||
// from_list
|
||||
lua_pushstring(L, from_list.c_str());
|
||||
// from_index
|
||||
lua_pushinteger(L, from_index + 1);
|
||||
// to_list
|
||||
lua_pushstring(L, to_list.c_str());
|
||||
// to_index
|
||||
lua_pushinteger(L, to_index + 1);
|
||||
// count
|
||||
lua_pushinteger(L, count);
|
||||
// player
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 7, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
ItemStack scriptapi_node_on_metadata_inventory_offer(lua_State *L, v3s16 p,
|
||||
// Report put items
|
||||
void scriptapi_nodemeta_inventory_on_put(lua_State *L, v3s16 p,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player)
|
||||
{
|
||||
|
@ -5780,25 +5909,30 @@ ItemStack scriptapi_node_on_metadata_inventory_offer(lua_State *L, v3s16 p,
|
|||
// If node doesn't exist, we don't know what callback to call
|
||||
MapNode node = get_env(L)->getMap().getNodeNoEx(p);
|
||||
if(node.getContent() == CONTENT_IGNORE)
|
||||
return stack;
|
||||
return;
|
||||
|
||||
// Push callback function on stack
|
||||
if(!get_item_callback(L, ndef->get(node).name.c_str(),
|
||||
"on_metadata_inventory_offer"))
|
||||
return stack;
|
||||
"on_metadata_inventory_put"))
|
||||
return;
|
||||
|
||||
// Call function(pos, listname, index, stack, player)
|
||||
// pos
|
||||
push_v3s16(L, p);
|
||||
// listname
|
||||
lua_pushstring(L, listname.c_str());
|
||||
// index
|
||||
lua_pushinteger(L, index + 1);
|
||||
// stack
|
||||
LuaItemStack::create(L, stack);
|
||||
// player
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 5, 1, 0))
|
||||
if(lua_pcall(L, 5, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
return read_item(L, -1);
|
||||
}
|
||||
|
||||
ItemStack scriptapi_node_on_metadata_inventory_take(lua_State *L, v3s16 p,
|
||||
// Report taken items
|
||||
void scriptapi_nodemeta_inventory_on_take(lua_State *L, v3s16 p,
|
||||
const std::string &listname, int index, int count,
|
||||
ServerActiveObject *player)
|
||||
{
|
||||
|
@ -5811,22 +5945,270 @@ ItemStack scriptapi_node_on_metadata_inventory_take(lua_State *L, v3s16 p,
|
|||
// If node doesn't exist, we don't know what callback to call
|
||||
MapNode node = get_env(L)->getMap().getNodeNoEx(p);
|
||||
if(node.getContent() == CONTENT_IGNORE)
|
||||
return ItemStack();
|
||||
return;
|
||||
|
||||
// Push callback function on stack
|
||||
if(!get_item_callback(L, ndef->get(node).name.c_str(),
|
||||
"on_metadata_inventory_take"))
|
||||
return ItemStack();
|
||||
return;
|
||||
|
||||
// Call function(pos, listname, index, count, player)
|
||||
// pos
|
||||
push_v3s16(L, p);
|
||||
// listname
|
||||
lua_pushstring(L, listname.c_str());
|
||||
// index
|
||||
lua_pushinteger(L, index + 1);
|
||||
// count
|
||||
lua_pushinteger(L, count);
|
||||
// player
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 5, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
/*
|
||||
Detached inventory callbacks
|
||||
*/
|
||||
|
||||
// Retrieves minetest.detached_inventories[name][callbackname]
|
||||
// If that is nil or on error, return false and stack is unchanged
|
||||
// If that is a function, returns true and pushes the
|
||||
// function onto the stack
|
||||
static bool get_detached_inventory_callback(lua_State *L,
|
||||
const std::string &name, const char *callbackname)
|
||||
{
|
||||
lua_getglobal(L, "minetest");
|
||||
lua_getfield(L, -1, "detached_inventories");
|
||||
lua_remove(L, -2);
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
lua_getfield(L, -1, name.c_str());
|
||||
lua_remove(L, -2);
|
||||
// Should be a table
|
||||
if(lua_type(L, -1) != LUA_TTABLE)
|
||||
{
|
||||
errorstream<<"Item \""<<name<<"\" not defined"<<std::endl;
|
||||
lua_pop(L, 1);
|
||||
return false;
|
||||
}
|
||||
lua_getfield(L, -1, callbackname);
|
||||
lua_remove(L, -2);
|
||||
// Should be a function or nil
|
||||
if(lua_type(L, -1) == LUA_TFUNCTION)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if(lua_isnil(L, -1))
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorstream<<"Detached inventory \""<<name<<"\" callback \""
|
||||
<<callbackname<<"\" is not a function"<<std::endl;
|
||||
lua_pop(L, 1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Return number of accepted items to be moved
|
||||
int scriptapi_detached_inventory_allow_move(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &from_list, int from_index,
|
||||
const std::string &to_list, int to_index,
|
||||
int count, ServerActiveObject *player)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
// Push callback function on stack
|
||||
if(!get_detached_inventory_callback(L, name, "allow_move"))
|
||||
return count;
|
||||
|
||||
// function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
// inv
|
||||
InventoryLocation loc;
|
||||
loc.setDetached(name);
|
||||
InvRef::create(L, loc);
|
||||
// from_list
|
||||
lua_pushstring(L, from_list.c_str());
|
||||
// from_index
|
||||
lua_pushinteger(L, from_index + 1);
|
||||
// to_list
|
||||
lua_pushstring(L, to_list.c_str());
|
||||
// to_index
|
||||
lua_pushinteger(L, to_index + 1);
|
||||
// count
|
||||
lua_pushinteger(L, count);
|
||||
// player
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 7, 1, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
return luaL_checkinteger(L, -1);
|
||||
}
|
||||
|
||||
// Return number of accepted items to be put
|
||||
int scriptapi_detached_inventory_allow_put(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
// Push callback function on stack
|
||||
if(!get_detached_inventory_callback(L, name, "allow_put"))
|
||||
return stack.count; // All will be accepted
|
||||
|
||||
// Call function(inv, listname, index, stack, player)
|
||||
// inv
|
||||
InventoryLocation loc;
|
||||
loc.setDetached(name);
|
||||
InvRef::create(L, loc);
|
||||
// listname
|
||||
lua_pushstring(L, listname.c_str());
|
||||
// index
|
||||
lua_pushinteger(L, index + 1);
|
||||
// stack
|
||||
LuaItemStack::create(L, stack);
|
||||
// player
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 5, 1, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
return read_item(L, -1);
|
||||
return luaL_checkinteger(L, -1);
|
||||
}
|
||||
|
||||
// Return number of accepted items to be taken
|
||||
int scriptapi_detached_inventory_allow_take(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &listname, int index, int count,
|
||||
ServerActiveObject *player)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
// Push callback function on stack
|
||||
if(!get_detached_inventory_callback(L, name, "allow_take"))
|
||||
return count; // All will be accepted
|
||||
|
||||
// Call function(inv, listname, index, count, player)
|
||||
// inv
|
||||
InventoryLocation loc;
|
||||
loc.setDetached(name);
|
||||
InvRef::create(L, loc);
|
||||
// listname
|
||||
lua_pushstring(L, listname.c_str());
|
||||
// index
|
||||
lua_pushinteger(L, index + 1);
|
||||
// count
|
||||
lua_pushinteger(L, count);
|
||||
// player
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 5, 1, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
return luaL_checkinteger(L, -1);
|
||||
}
|
||||
|
||||
// Report moved items
|
||||
void scriptapi_detached_inventory_on_move(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &from_list, int from_index,
|
||||
const std::string &to_list, int to_index,
|
||||
int count, ServerActiveObject *player)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
// Push callback function on stack
|
||||
if(!get_detached_inventory_callback(L, name, "on_move"))
|
||||
return;
|
||||
|
||||
// function(inv, from_list, from_index, to_list, to_index, count, player)
|
||||
// inv
|
||||
InventoryLocation loc;
|
||||
loc.setDetached(name);
|
||||
InvRef::create(L, loc);
|
||||
// from_list
|
||||
lua_pushstring(L, from_list.c_str());
|
||||
// from_index
|
||||
lua_pushinteger(L, from_index + 1);
|
||||
// to_list
|
||||
lua_pushstring(L, to_list.c_str());
|
||||
// to_index
|
||||
lua_pushinteger(L, to_index + 1);
|
||||
// count
|
||||
lua_pushinteger(L, count);
|
||||
// player
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 7, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
// Report put items
|
||||
void scriptapi_detached_inventory_on_put(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
// Push callback function on stack
|
||||
if(!get_detached_inventory_callback(L, name, "on_put"))
|
||||
return;
|
||||
|
||||
// Call function(inv, listname, index, stack, player)
|
||||
// inv
|
||||
InventoryLocation loc;
|
||||
loc.setDetached(name);
|
||||
InvRef::create(L, loc);
|
||||
// listname
|
||||
lua_pushstring(L, listname.c_str());
|
||||
// index
|
||||
lua_pushinteger(L, index + 1);
|
||||
// stack
|
||||
LuaItemStack::create(L, stack);
|
||||
// player
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 5, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
// Report taken items
|
||||
void scriptapi_detached_inventory_on_take(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &listname, int index, int count,
|
||||
ServerActiveObject *player)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
// Push callback function on stack
|
||||
if(!get_detached_inventory_callback(L, name, "on_take"))
|
||||
return;
|
||||
|
||||
// Call function(inv, listname, index, count, player)
|
||||
// inv
|
||||
InventoryLocation loc;
|
||||
loc.setDetached(name);
|
||||
InvRef::create(L, loc);
|
||||
// listname
|
||||
lua_pushstring(L, listname.c_str());
|
||||
// index
|
||||
lua_pushinteger(L, index + 1);
|
||||
// count
|
||||
lua_pushinteger(L, count);
|
||||
// player
|
||||
objectref_get_or_create(L, player);
|
||||
if(lua_pcall(L, 5, 0, 0))
|
||||
script_error(L, "error: %s", lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -101,17 +101,66 @@ void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p,
|
|||
const std::string &formname,
|
||||
const std::map<std::string, std::string> &fields,
|
||||
ServerActiveObject *sender);
|
||||
// Moves items
|
||||
void scriptapi_node_on_metadata_inventory_move(lua_State *L, v3s16 p,
|
||||
|
||||
/* Node metadata inventory callbacks */
|
||||
// Return number of accepted items to be moved
|
||||
int scriptapi_nodemeta_inventory_allow_move(lua_State *L, v3s16 p,
|
||||
const std::string &from_list, int from_index,
|
||||
const std::string &to_list, int to_index,
|
||||
int count, ServerActiveObject *player);
|
||||
// Inserts items, returns rejected items
|
||||
ItemStack scriptapi_node_on_metadata_inventory_offer(lua_State *L, v3s16 p,
|
||||
// Return number of accepted items to be put
|
||||
int scriptapi_nodemeta_inventory_allow_put(lua_State *L, v3s16 p,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player);
|
||||
// Takes items, returns taken items
|
||||
ItemStack scriptapi_node_on_metadata_inventory_take(lua_State *L, v3s16 p,
|
||||
// Return number of accepted items to be taken
|
||||
int scriptapi_nodemeta_inventory_allow_take(lua_State *L, v3s16 p,
|
||||
const std::string &listname, int index, int count,
|
||||
ServerActiveObject *player);
|
||||
// Report moved items
|
||||
void scriptapi_nodemeta_inventory_on_move(lua_State *L, v3s16 p,
|
||||
const std::string &from_list, int from_index,
|
||||
const std::string &to_list, int to_index,
|
||||
int count, ServerActiveObject *player);
|
||||
// Report put items
|
||||
void scriptapi_nodemeta_inventory_on_put(lua_State *L, v3s16 p,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player);
|
||||
// Report taken items
|
||||
void scriptapi_nodemeta_inventory_on_take(lua_State *L, v3s16 p,
|
||||
const std::string &listname, int index, int count,
|
||||
ServerActiveObject *player);
|
||||
|
||||
/* Detached inventory callbacks */
|
||||
// Return number of accepted items to be moved
|
||||
int scriptapi_detached_inventory_allow_move(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &from_list, int from_index,
|
||||
const std::string &to_list, int to_index,
|
||||
int count, ServerActiveObject *player);
|
||||
// Return number of accepted items to be put
|
||||
int scriptapi_detached_inventory_allow_put(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player);
|
||||
// Return number of accepted items to be taken
|
||||
int scriptapi_detached_inventory_allow_take(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &listname, int index, int count,
|
||||
ServerActiveObject *player);
|
||||
// Report moved items
|
||||
void scriptapi_detached_inventory_on_move(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &from_list, int from_index,
|
||||
const std::string &to_list, int to_index,
|
||||
int count, ServerActiveObject *player);
|
||||
// Report put items
|
||||
void scriptapi_detached_inventory_on_put(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &listname, int index, ItemStack &stack,
|
||||
ServerActiveObject *player);
|
||||
// Report taken items
|
||||
void scriptapi_detached_inventory_on_take(lua_State *L,
|
||||
const std::string &name,
|
||||
const std::string &listname, int index, int count,
|
||||
ServerActiveObject *player);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue