Detached inventory callbacks and reworked node metadata callbacks

This commit is contained in:
Perttu Ahola 2012-07-25 02:36:54 +03:00
parent 2ac20982e0
commit 9eaf93d41d
11 changed files with 827 additions and 247 deletions

@ -21,4 +21,5 @@ dofile(minetest.get_modpath("__builtin").."/privileges.lua")
dofile(minetest.get_modpath("__builtin").."/auth.lua") dofile(minetest.get_modpath("__builtin").."/auth.lua")
dofile(minetest.get_modpath("__builtin").."/chatcommands.lua") dofile(minetest.get_modpath("__builtin").."/chatcommands.lua")
dofile(minetest.get_modpath("__builtin").."/static_spawn.lua") dofile(minetest.get_modpath("__builtin").."/static_spawn.lua")
dofile(minetest.get_modpath("__builtin").."/detached_inventory.lua")

@ -16,4 +16,7 @@ minetest.digprop_woodlike = digprop_err
minetest.digprop_leaveslike = digprop_err minetest.digprop_leaveslike = digprop_err
minetest.digprop_glasslike = digprop_err minetest.digprop_glasslike = digprop_err
minetest.node_metadata_inventory_move_allow_all = function()
minetest.log("info", "WARNING: minetest.node_metadata_inventory_move_allow_all is obsolete and does nothing.")
end

@ -0,0 +1,19 @@
-- Minetest: builtin/detached_inventory.lua
minetest.detached_inventories = {}
function minetest.create_detached_inventory(name, callbacks)
local stuff = {}
stuff.name = name
if callbacks then
stuff.allow_move = callbacks.allow_move
stuff.allow_put = callbacks.allow_put
stuff.allow_take = callbacks.allow_take
stuff.on_move = callbacks.on_move
stuff.on_put = callbacks.on_put
stuff.on_take = callbacks.on_take
end
minetest.detached_inventories[name] = stuff
return minetest.create_detached_inventory_raw(name)
end

@ -318,41 +318,6 @@ function minetest.node_dig(pos, node, digger)
end end
end end
function minetest.node_metadata_inventory_move_allow_all(pos, from_list,
from_index, to_list, to_index, count, player)
minetest.log("verbose", "node_metadata_inventory_move_allow_all")
local meta = minetest.env:get_meta(pos)
local inv = meta:get_inventory()
local from_stack = inv:get_stack(from_list, from_index)
local taken_items = from_stack:take_item(count)
inv:set_stack(from_list, from_index, from_stack)
local to_stack = inv:get_stack(to_list, to_index)
to_stack:add_item(taken_items)
inv:set_stack(to_list, to_index, to_stack)
end
function minetest.node_metadata_inventory_offer_allow_all(pos, listname, index, stack, player)
minetest.log("verbose", "node_metadata_inventory_offer_allow_all")
local meta = minetest.env:get_meta(pos)
local inv = meta:get_inventory()
local the_stack = inv:get_stack(listname, index)
the_stack:add_item(stack)
inv:set_stack(listname, index, the_stack)
return ItemStack("")
end
function minetest.node_metadata_inventory_take_allow_all(pos, listname, index, count, player)
minetest.log("verbose", "node_metadata_inventory_take_allow_all")
local meta = minetest.env:get_meta(pos)
local inv = meta:get_inventory()
local the_stack = inv:get_stack(listname, index)
local taken_items = the_stack:take_item(count)
inv:set_stack(listname, index, the_stack)
return taken_items
end
-- This is used to allow mods to redefine minetest.item_place and so on -- This is used to allow mods to redefine minetest.item_place and so on
-- NOTE: This is not the preferred way. Preferred way is to provide enough -- NOTE: This is not the preferred way. Preferred way is to provide enough
-- callbacks to not require redefining global functions. -celeron55 -- callbacks to not require redefining global functions. -celeron55

@ -851,7 +851,8 @@ minetest.get_inventory(location) -> InvRef
^ location = eg. {type="player", name="celeron55"} ^ location = eg. {type="player", name="celeron55"}
{type="node", pos={x=, y=, z=}} {type="node", pos={x=, y=, z=}}
{type="detached", name="creative"} {type="detached", name="creative"}
minetest.create_detached_inventory(name) -> InvRef minetest.create_detached_inventory(name, callbacks) -> InvRef
^ callbacks: See "Detached inventory callbacks"
^ Creates a detached inventory. If it already exists, it is cleared. ^ Creates a detached inventory. If it already exists, it is cleared.
Item handling: Item handling:
@ -1361,35 +1362,25 @@ Node definition (register_node)
^ Called when an UI form (eg. sign text input) returns data ^ Called when an UI form (eg. sign text input) returns data
^ default: nil ^ default: nil
allow_metadata_inventory_move = func(pos, from_list, from_index,
to_list, to_index, count, player),
^ Called when a player wants to move items inside the inventory
^ Return value: number of items allowed to move
allow_metadata_inventory_put = func(pos, listname, index, stack, player),
^ Called when a player wants to put something into the inventory
^ Return value: number of items allowed to put
allow_metadata_inventory_take = func(pos, listname, index, count, player),
^ Called when a player wants to take something out of the inventory
^ Return value: number of items allowed to take
on_metadata_inventory_move = func(pos, from_list, from_index, on_metadata_inventory_move = func(pos, from_list, from_index,
to_list, to_index, count, player), to_list, to_index, count, player),
^ Called when a player wants to move items inside the metadata on_metadata_inventory_put = func(pos, listname, index, stack, player),
^ Should move items, or some items, if permitted. If not, should do
nothing.
^ The engine ensures the action is valid, i.e. the stack fits at the
given position
^ default: minetest.node_metadata_inventory_move_allow_all
on_metadata_inventory_offer = func(pos, listname, index, stack, player),
^ Called when a player wants to put something into the metadata
inventory
^ Should check if the action is permitted (the engine ensures the
action is valid, i.e. the stack fits at the given position)
^ If permitted, modify the metadata inventory and return the
"leftover" stack (normally nil).
^ If not permitted, return itemstack.
^ default: minetest.node_metadata_inventory_offer_allow_all
on_metadata_inventory_take = func(pos, listname, index, count, player), on_metadata_inventory_take = func(pos, listname, index, count, player),
^ Called when a player wants to take something out of the metadata ^ Called after the actual action has happened, according to what was allowed.
inventory ^ No return value
^ Should check if the action is permitted (the engine ensures the
action is valid, i.e. there's a stack of at least “count” items at
that position)
^ If permitted, modify the metadata inventory and return the
stack of items
^ If not permitted, return nil.
^ default: minetest.node_metadata_inventory_take_allow_all
} }
Recipe for register_craft: (shaped) Recipe for register_craft: (shaped)
@ -1446,3 +1437,24 @@ Chatcommand definition (register_chatcommand)
func = function(name, param), -- called when command is run func = function(name, param), -- called when command is run
} }
Detached inventory callbacks
{
allow_move = func(inv, from_list, from_index, to_list, to_index, count, player),
^ Called when a player wants to move items inside the inventory
^ Return value: number of items allowed to move
allow_put = func(inv, listname, index, stack, player),
^ Called when a player wants to put something into the inventory
^ Return value: number of items allowed to put
allow_take = func(inv, listname, index, count, player),
^ Called when a player wants to take something out of the inventory
^ Return value: number of items allowed to take
on_move = func(inv, from_list, from_index, to_list, to_index, count, player),
on_put = func(inv, listname, index, stack, player),
on_take = func(inv, listname, index, count, player),
^ Called after the actual action has happened, according to what was allowed.
^ No return value
}

@ -1150,7 +1150,7 @@ minetest.register_node("default:chest", {
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.env:get_meta(pos) local meta = minetest.env:get_meta(pos)
meta:set_string("formspec", meta:set_string("formspec",
"invsize[8,9;]".. "size[8,9]"..
"list[current_name;main;0,0;8,4;]".. "list[current_name;main;0,0;8,4;]"..
"list[current_player;main;0,5;8,4;]") "list[current_player;main;0,5;8,4;]")
meta:set_string("infotext", "Chest") meta:set_string("infotext", "Chest")
@ -1162,25 +1162,6 @@ minetest.register_node("default:chest", {
local inv = meta:get_inventory() local inv = meta:get_inventory()
return inv:is_empty("main") return inv:is_empty("main")
end, end,
on_metadata_inventory_move = function(pos, from_list, from_index,
to_list, to_index, count, player)
minetest.log("action", player:get_player_name()..
" moves stuff in chest at "..minetest.pos_to_string(pos))
return minetest.node_metadata_inventory_move_allow_all(
pos, from_list, from_index, to_list, to_index, count, player)
end,
on_metadata_inventory_offer = function(pos, listname, index, stack, player)
minetest.log("action", player:get_player_name()..
" moves stuff to chest at "..minetest.pos_to_string(pos))
return minetest.node_metadata_inventory_offer_allow_all(
pos, listname, index, stack, player)
end,
on_metadata_inventory_take = function(pos, listname, index, count, player)
minetest.log("action", player:get_player_name()..
" takes stuff from chest at "..minetest.pos_to_string(pos))
return minetest.node_metadata_inventory_take_allow_all(
pos, listname, index, count, player)
end,
}) })
local function has_locked_chest_privilege(meta, player) local function has_locked_chest_privilege(meta, player)
@ -1207,7 +1188,7 @@ minetest.register_node("default:chest_locked", {
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.env:get_meta(pos) local meta = minetest.env:get_meta(pos)
meta:set_string("formspec", meta:set_string("formspec",
"invsize[8,9;]".. "size[8,9]"..
"list[current_name;main;0,0;8,4;]".. "list[current_name;main;0,0;8,4;]"..
"list[current_player;main;0,5;8,4;]") "list[current_player;main;0,5;8,4;]")
meta:set_string("infotext", "Locked Chest") meta:set_string("infotext", "Locked Chest")
@ -1220,53 +1201,55 @@ minetest.register_node("default:chest_locked", {
local inv = meta:get_inventory() local inv = meta:get_inventory()
return inv:is_empty("main") return inv:is_empty("main")
end, end,
on_metadata_inventory_move = function(pos, from_list, from_index, allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
to_list, to_index, count, player)
local meta = minetest.env:get_meta(pos) local meta = minetest.env:get_meta(pos)
if not has_locked_chest_privilege(meta, player) then if not has_locked_chest_privilege(meta, player) then
minetest.log("action", player:get_player_name().. minetest.log("action", player:get_player_name()..
" tried to access a locked chest belonging to ".. " tried to access a locked chest belonging to "..
meta:get_string("owner").." at ".. meta:get_string("owner").." at "..
minetest.pos_to_string(pos)) minetest.pos_to_string(pos))
return return 0
end end
return count
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
local meta = minetest.env:get_meta(pos)
if not has_locked_chest_privilege(meta, player) then
minetest.log("action", player:get_player_name()..
" tried to access a locked chest belonging to "..
meta:get_string("owner").." at "..
minetest.pos_to_string(pos))
return 0
end
return stack:get_count()
end,
allow_metadata_inventory_take = function(pos, listname, index, count, player)
local meta = minetest.env:get_meta(pos)
if not has_locked_chest_privilege(meta, player) then
minetest.log("action", player:get_player_name()..
" tried to access a locked chest belonging to "..
meta:get_string("owner").." at "..
minetest.pos_to_string(pos))
return 0
end
return count
end,
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
minetest.log("action", player:get_player_name().. minetest.log("action", player:get_player_name()..
" moves stuff in locked chest at "..minetest.pos_to_string(pos)) " moves stuff in locked chest at "..minetest.pos_to_string(pos))
return minetest.node_metadata_inventory_move_allow_all(
pos, from_list, from_index, to_list, to_index, count, player)
end, end,
on_metadata_inventory_offer = function(pos, listname, index, stack, player) on_metadata_inventory_put = function(pos, listname, index, stack, player)
local meta = minetest.env:get_meta(pos)
if not has_locked_chest_privilege(meta, player) then
minetest.log("action", player:get_player_name()..
" tried to access a locked chest belonging to "..
meta:get_string("owner").." at "..
minetest.pos_to_string(pos))
return stack
end
minetest.log("action", player:get_player_name().. minetest.log("action", player:get_player_name()..
" moves stuff to locked chest at "..minetest.pos_to_string(pos)) " moves stuff to locked chest at "..minetest.pos_to_string(pos))
return minetest.node_metadata_inventory_offer_allow_all(
pos, listname, index, stack, player)
end, end,
on_metadata_inventory_take = function(pos, listname, index, count, player) on_metadata_inventory_take = function(pos, listname, index, count, player)
local meta = minetest.env:get_meta(pos)
if not has_locked_chest_privilege(meta, player) then
minetest.log("action", player:get_player_name()..
" tried to access a locked chest belonging to "..
meta:get_string("owner").." at "..
minetest.pos_to_string(pos))
return
end
minetest.log("action", player:get_player_name().. minetest.log("action", player:get_player_name()..
" takes stuff from locked chest at "..minetest.pos_to_string(pos)) " takes stuff from locked chest at "..minetest.pos_to_string(pos))
return minetest.node_metadata_inventory_take_allow_all(
pos, listname, index, count, player)
end, end,
}) })
default.furnace_inactive_formspec = default.furnace_inactive_formspec =
"invsize[8,9;]".. "size[8,9]"..
"image[2,2;1,1;default_furnace_fire_bg.png]".. "image[2,2;1,1;default_furnace_fire_bg.png]"..
"list[current_name;fuel;2,3;1,1;]".. "list[current_name;fuel;2,3;1,1;]"..
"list[current_name;src;2,1;1,1;]".. "list[current_name;src;2,1;1,1;]"..
@ -1405,7 +1388,7 @@ minetest.register_abm({
meta:set_string("infotext","Furnace active: "..percent.."%") meta:set_string("infotext","Furnace active: "..percent.."%")
hacky_swap_node(pos,"default:furnace_active") hacky_swap_node(pos,"default:furnace_active")
meta:set_string("formspec", meta:set_string("formspec",
"invsize[8,9;]".. "size[8,9]"..
"image[2,2;1,1;default_furnace_fire_bg.png^[lowpart:".. "image[2,2;1,1;default_furnace_fire_bg.png^[lowpart:"..
(100-percent)..":default_furnace_fire_fg.png]".. (100-percent)..":default_furnace_fire_fg.png]"..
"list[current_name;fuel;2,3;1,1;]".. "list[current_name;fuel;2,3;1,1;]"..

@ -516,7 +516,7 @@ minetest.register_craft({
--[[minetest.register_on_joinplayer(function(player) --[[minetest.register_on_joinplayer(function(player)
minetest.after(3, function() minetest.after(3, function()
player:set_inventory_formspec("invsize[8,7.5;]".. player:set_inventory_formspec("size[8,7.5]"..
"image[1,0.6;1,2;player.png]".. "image[1,0.6;1,2;player.png]"..
"list[current_player;main;0,3.5;8,4;]".. "list[current_player;main;0,3.5;8,4;]"..
"list[current_player;craft;3,0;3,3;]".. "list[current_player;craft;3,0;3,3;]"..
@ -525,7 +525,29 @@ minetest.register_craft({
end)]] end)]]
-- Create a detached inventory -- Create a detached inventory
local inv = minetest.create_detached_inventory("test_inventory") local inv = minetest.create_detached_inventory("test_inventory", {
allow_move = function(inv, from_list, from_index, to_list, to_index, count, player)
experimental.print_to_everything("allow move asked")
return count -- Allow all
end,
allow_put = function(inv, listname, index, stack, player)
experimental.print_to_everything("allow put asked")
return 1 -- Allow only 1
end,
allow_take = function(inv, listname, index, count, player)
experimental.print_to_everything("allow take asked")
return 4 -- Allow 4 at max
end,
on_move = function(inv, from_list, from_index, to_list, to_index, count, player)
experimental.print_to_everything(player:get_player_name().." moved items")
end,
on_put = function(inv, listname, index, stack, player)
experimental.print_to_everything(player:get_player_name().." put items")
end,
on_take = function(inv, listname, index, count, player)
experimental.print_to_everything(player:get_player_name().." took items")
end,
})
inv:set_size("main", 4*6) inv:set_size("main", 4*6)
inv:add_item("main", "experimental:tester_tool_1") inv:add_item("main", "experimental:tester_tool_1")
inv:add_item("main", "experimental:tnt 5") inv:add_item("main", "experimental:tnt 5")

@ -215,10 +215,9 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
} }
else{ else{
invsize.Y = stof(f.next(";")); invsize.Y = stof(f.next(";"));
errorstream<<"WARNING: invsize is deprecated, use size"<<std::endl;
f.next("]"); 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); padding = v2s32(screensize.Y/40, screensize.Y/40);
spacing = v2s32(screensize.Y/12, screensize.Y/13); spacing = v2s32(screensize.Y/12, screensize.Y/13);

@ -199,69 +199,110 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
return; return;
} }
// Handle node metadata move /*
if(from_inv.type == InventoryLocation::NODEMETA && Collect information of endpoints
to_inv.type == InventoryLocation::NODEMETA && */
from_inv.p != to_inv.p)
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;
/* 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 " lua_State *L = player->getEnv()->getLua();
<<"disallowed."<<std::endl; src_can_take_count = scriptapi_detached_inventory_allow_move(
return; 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 && to_inv.type == InventoryLocation::NODEMETA &&
from_inv.p == to_inv.p) from_inv.p == to_inv.p)
{ {
lua_State *L = player->getEnv()->getLua(); lua_State *L = player->getEnv()->getLua();
int count0 = count; src_can_take_count = scriptapi_nodemeta_inventory_allow_move(
if(count0 == 0) L, from_inv.p, from_list, from_i,
count0 = list_from->getItem(from_i).count; to_list, to_i, try_take_count, player);
infostream<<player->getDescription()<<" moving "<<count0 dst_can_put_count = src_can_take_count;
<<" 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);
} }
// 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 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 = 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<<"\""
<<" i="<<from_i
<<" to inv=\""<<to_inv.dump()<<"\""
<<" list=\""<<to_list<<"\""
<<" i="<<to_i
<<std::endl;
return;
}
count = new_count;
/* /*
This performs the actual movement Perform actual move
If something is wrong (source item is empty, destination is the If something is wrong (source item is empty, destination is the
same as source), nothing happens same as source), nothing happens
@ -277,6 +318,76 @@ void IMoveAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
<<" list=\""<<to_list<<"\"" <<" list=\""<<to_list<<"\""
<<" i="<<to_i <<" i="<<to_i
<<std::endl; <<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); mgr->setInventoryModified(from_inv);
@ -361,54 +472,88 @@ void IDropAction::apply(InventoryManager *mgr, ServerActiveObject *player, IGame
return; 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) if(from_inv.type == InventoryLocation::NODEMETA)
{ {
lua_State *L = player->getEnv()->getLua(); lua_State *L = player->getEnv()->getLua();
int count0 = count; src_can_take_count = scriptapi_nodemeta_inventory_allow_take(
if(count0 == 0) L, from_inv.p, from_list, from_i, take_count, player);
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);
} }
// Drop the item and apply the returned ItemStack if(src_can_take_count < take_count)
ItemStack item2 = item1; take_count = src_can_take_count;
if(scriptapi_item_on_drop(player->getEnv()->getLua(), item2, player,
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))) 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 if(g_settings->getBool("creative_mode") == true
&& from_inv.type == InventoryLocation::PLAYER) && from_inv.type == InventoryLocation::PLAYER){
item2 = item1; // creative mode }
else{
// Take item from source list
ItemStack item2 = list_from->takeItem(from_i, actually_dropped_count);
list_from->addItem(from_i, item2); if(item2.count != actually_dropped_count)
errorstream<<"Could not take dropped count of items"<<std::endl;
// Unless we have put the same amount back as we took in the first place,
// set inventory modified flag
if(item2.count != item1.count)
mgr->setInventoryModified(from_inv); mgr->setInventoryModified(from_inv);
} }
}
infostream<<"IDropAction::apply(): dropped " infostream<<"IDropAction::apply(): dropped "
<<" from inv=\""<<from_inv.dump()<<"\"" <<" from inv=\""<<from_inv.dump()<<"\""
<<" list=\""<<from_list<<"\"" <<" list=\""<<from_list<<"\""
<<" i="<<from_i <<" i="<<from_i
<<std::endl; <<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) void IDropAction::clientApply(InventoryManager *mgr, IGameDef *gamedef)

@ -4579,8 +4579,8 @@ static int l_get_inventory(lua_State *L)
return 1; return 1;
} }
// create_detached_inventory(name) // create_detached_inventory_raw(name)
static int l_create_detached_inventory(lua_State *L) static int l_create_detached_inventory_raw(lua_State *L)
{ {
const char *name = luaL_checkstring(L, 1); const char *name = luaL_checkstring(L, 1);
if(get_server(L)->createDetachedInventory(name) != NULL){ 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}, {"chat_send_player", l_chat_send_player},
{"get_player_privs", l_get_player_privs}, {"get_player_privs", l_get_player_privs},
{"get_inventory", l_get_inventory}, {"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_dig_params", l_get_dig_params},
{"get_hit_params", l_get_hit_params}, {"get_hit_params", l_get_hit_params},
{"get_current_modname", l_get_current_modname}, {"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)); 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 &from_list, int from_index,
const std::string &to_list, int to_index, const std::string &to_list, int to_index,
int count, ServerActiveObject *player) int count, ServerActiveObject *player)
@ -5756,18 +5877,26 @@ void scriptapi_node_on_metadata_inventory_move(lua_State *L, v3s16 p,
return; return;
// function(pos, from_list, from_index, to_list, to_index, count, player) // function(pos, from_list, from_index, to_list, to_index, count, player)
// pos
push_v3s16(L, p); push_v3s16(L, p);
// from_list
lua_pushstring(L, from_list.c_str()); lua_pushstring(L, from_list.c_str());
// from_index
lua_pushinteger(L, from_index + 1); lua_pushinteger(L, from_index + 1);
// to_list
lua_pushstring(L, to_list.c_str()); lua_pushstring(L, to_list.c_str());
// to_index
lua_pushinteger(L, to_index + 1); lua_pushinteger(L, to_index + 1);
// count
lua_pushinteger(L, count); lua_pushinteger(L, count);
// player
objectref_get_or_create(L, player); objectref_get_or_create(L, player);
if(lua_pcall(L, 7, 0, 0)) if(lua_pcall(L, 7, 0, 0))
script_error(L, "error: %s", lua_tostring(L, -1)); 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, const std::string &listname, int index, ItemStack &stack,
ServerActiveObject *player) 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 // If node doesn't exist, we don't know what callback to call
MapNode node = get_env(L)->getMap().getNodeNoEx(p); MapNode node = get_env(L)->getMap().getNodeNoEx(p);
if(node.getContent() == CONTENT_IGNORE) if(node.getContent() == CONTENT_IGNORE)
return stack; return;
// Push callback function on stack // Push callback function on stack
if(!get_item_callback(L, ndef->get(node).name.c_str(), if(!get_item_callback(L, ndef->get(node).name.c_str(),
"on_metadata_inventory_offer")) "on_metadata_inventory_put"))
return stack; return;
// Call function(pos, listname, index, stack, player) // Call function(pos, listname, index, stack, player)
// pos
push_v3s16(L, p); push_v3s16(L, p);
// listname
lua_pushstring(L, listname.c_str()); lua_pushstring(L, listname.c_str());
// index
lua_pushinteger(L, index + 1); lua_pushinteger(L, index + 1);
// stack
LuaItemStack::create(L, stack); LuaItemStack::create(L, stack);
// player
objectref_get_or_create(L, 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)); 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, const std::string &listname, int index, int count,
ServerActiveObject *player) 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 // If node doesn't exist, we don't know what callback to call
MapNode node = get_env(L)->getMap().getNodeNoEx(p); MapNode node = get_env(L)->getMap().getNodeNoEx(p);
if(node.getContent() == CONTENT_IGNORE) if(node.getContent() == CONTENT_IGNORE)
return ItemStack(); return;
// Push callback function on stack // Push callback function on stack
if(!get_item_callback(L, ndef->get(node).name.c_str(), if(!get_item_callback(L, ndef->get(node).name.c_str(),
"on_metadata_inventory_take")) "on_metadata_inventory_take"))
return ItemStack(); return;
// Call function(pos, listname, index, count, player) // Call function(pos, listname, index, count, player)
// pos
push_v3s16(L, p); push_v3s16(L, p);
// listname
lua_pushstring(L, listname.c_str()); lua_pushstring(L, listname.c_str());
// index
lua_pushinteger(L, index + 1); lua_pushinteger(L, index + 1);
// count
lua_pushinteger(L, 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); objectref_get_or_create(L, player);
if(lua_pcall(L, 5, 1, 0)) if(lua_pcall(L, 5, 1, 0))
script_error(L, "error: %s", lua_tostring(L, -1)); 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::string &formname,
const std::map<std::string, std::string> &fields, const std::map<std::string, std::string> &fields,
ServerActiveObject *sender); 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 &from_list, int from_index,
const std::string &to_list, int to_index, const std::string &to_list, int to_index,
int count, ServerActiveObject *player); int count, ServerActiveObject *player);
// Inserts items, returns rejected items // Return number of accepted items to be put
ItemStack scriptapi_node_on_metadata_inventory_offer(lua_State *L, v3s16 p, int scriptapi_nodemeta_inventory_allow_put(lua_State *L, v3s16 p,
const std::string &listname, int index, ItemStack &stack, const std::string &listname, int index, ItemStack &stack,
ServerActiveObject *player); ServerActiveObject *player);
// Takes items, returns taken items // Return number of accepted items to be taken
ItemStack scriptapi_node_on_metadata_inventory_take(lua_State *L, v3s16 p, 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, const std::string &listname, int index, int count,
ServerActiveObject *player); ServerActiveObject *player);