implemented put_into_block_inv and take_from_block_inv

This commit is contained in:
Sokomine 2021-12-28 03:15:41 +01:00
parent 09521172ac
commit e61baf7ab5
3 changed files with 150 additions and 1 deletions

View File

@ -214,3 +214,13 @@ but offer the same options/answers as the dialog normally would.
Alternate texts can be converted to normal dialogs, and normal dialogs can
vice versa be converted to alternate texts if only one option/answer points
to them.
Configuration
=============
Please make sure that the tables
yl_speak_up.blacklist_effect_on_block_<type> with <type>:
<interact|place|dig|punch|right_click|put|take>
contain all the blocks which do not allow the NPCs this kind of
interaction.
You may i.e. set the put and take tables for blocks that do extensive
checks on the player object which the NPC simply can't provide.

View File

@ -1,3 +1,15 @@
-- Note: This config file is not intended to be edited directly.
-- Like all my mods, it foremost provides an interface/api so
-- that another mod (i.e. a server specific one written by you)
-- can call functions here and do the settings.
--
-- That way you can update this mod easily and keep your settings
-- in a seperate mod and even override functions there if you
-- want.
--
-- So please use a seperate config mod!
-- Do the NPCs talk right after they spawned?
yl_speak_up.talk_after_spawn = true
@ -56,6 +68,9 @@ yl_speak_up.blacklist_effect_on_block_place = {}
yl_speak_up.blacklist_effect_on_block_dig = {}
yl_speak_up.blacklist_effect_on_block_punch = {}
yl_speak_up.blacklist_effect_on_block_right_click = {}
-- taking something out of the inventory of a block or putting something in
yl_speak_up.blacklist_effect_on_block_put = {}
yl_speak_up.blacklist_effect_on_block_take = {}
-- If some items are for some reasons not at all acceptable as quest items,
-- blacklist them here. The data structure is the same as for the tables above.

View File

@ -131,6 +131,8 @@ yl_speak_up.check_blacklisted = function(how, node_name, node_there)
or (how == "dig" and yl_speak_up.blacklist_effect_on_block_dig[ node_there ])
or (how == "punch" and yl_speak_up.blacklist_effect_on_block_punch[ node_there ])
or (how == "right-click" and yl_speak_up.blacklist_effect_on_block_right_click[ node_there])
or (how == "put" and yl_speak_up.blacklist_effect_on_block_right_click[ node_there])
or (how == "take" and yl_speak_up.blacklist_effect_on_block_right_click[ node_there])
end
-- returns a human-readable text as description of the effects
@ -347,7 +349,129 @@ yl_speak_up.execute_effect = function(player, n_id, o_id, r)
return true
elseif(r.r_type == "put_into_block_inv"
or r.r_type == "take_from_block_inv") then
-- TODO: implement
-- get the inventory of the block
if(not(r.r_pos) or type(r.r_pos) ~= "table"
or not(r.r_pos.x) or not(r.r_pos.y) or not(r.r_pos.z)) then
-- position not found?
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
r.r_type..": No or incorrect position given: "..
minetest.serialize(r.rp_pos)..".")
return false
end
local meta = minetest.get_meta(r.r_pos)
if(not(meta)) then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
r.r_type..": Failed to get metadata at "..
minetest.serialize(r.rp_pos)..".")
return false
end
local inv = meta:get_inventory()
if(not(inv)) then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
r.r_type..": Failed to get inventory at "..
minetest.serialize(r.rp_pos)..".")
return false
end
local inv_name = r.r_inv_list_name
-- get the inventory of the npc
local npc_inv = minetest.get_inventory({type="detached",
name="yl_speak_up_npc_"..tostring(n_id)})
local npc_inv_name = "npc_main"
-- for easier checking
local how_to_interact = "take"
if(r.r_type and r.r_type == "put_into_block_inv") then
how_to_interact = "put"
end
local stack = ItemStack(r.r_itemstack)
-- is there enough room for the item?
if(how_to_interact == "put"
and not(inv:room_for_item(inv_name, stack))) then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
r.r_type..": No room for \""..
minetest.serialize(r.r_itemstack).."\""..
" in node at "..
minetest.serialize(r.r_pos)..", inv list \""..
minetest.serialize(inv_name).."\".")
return false
elseif(how_to_interact == "take"
and not(npc_inv:room_for_item("npc_main", stack))) then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
r.r_type..": NPC has no room for \""..
minetest.serialize(r.r_itemstack).."\".")
return false
end
-- does the item exist?
if(how_to_interact == "put"
and not(npc_inv:contains_item(npc_inv_name, stack, false))) then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
r.r_type..": NPC does not have \""..
minetest.serialize(r.r_itemstack).."\".")
return false
elseif(how_to_interact == "take"
and not(inv:contains_item(inv_name, stack, false))) then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
r.r_type..": Block at "..minetest.serialize(r.r_pos)..
" does not contain \""..tostring(r.r_itemstack).."\" in list \""..
tostring(r.r_inv_list).."\".")
return false
end
-- check the blacklist
local node = minetest.get_node(r.r_pos)
if(not(node) or not(node.name)) then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
r.r_type..": No node found at "..minetest.serialize(r.r_pos)..".")
return false
end
-- do not interact with nodes on the blacklist
if(yl_speak_up.check_blacklisted(how_to_interact, node.name, node.name)) then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
r.r_type..": Blocks of type \""..tostring(node.name).."\" do not allow "..
"interaction of type \""..tostring(r.r_value).."\" for NPC.")
return false
end
-- construct a fake player
local owner_name = yl_speak_up.npc_owner[ n_id ]
if(not(owner_name) or owner_name == "") then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
r.r_type..": NPC does not have an owner. Aborting.")
return false
end
-- act in the name of the owner when accessing inventories
local fake_player = {
get_player_name = function() return owner_name end,
is_player = function() return true end,
is_fake_player = true,
get_wielded_item = function(self, item)
if(self._inventory and def.wield_list) then
return self._inventory:get_stack(def.wield_list, self._wield_index)
end
return ItemStack(self._wielded_item)
end,
}
-- TODO: get the fake player from pipeworks?
local def = minetest.registered_nodes[ node.name ]
if(def and def[ "allow_metadata_inventory_"..how_to_interact ]) then
local res = def[ "allow_metadata_inventory_"..how_to_interact ](
r.r_pos, inv_name, 1,
ItemStack(r.r_itemstack),
fake_player)
if(not(res) or res < ItemStack(r.r_itemstack):get_count()) then
yl_speak_up.debug_msg(player, n_id, o_id, tostring(r.r_id).." "..
r.r_type..": allow_metadata_inventory_"..tostring(how_to_interact)..
" forbits interaction at "..minetest.serialize(r.r_pos)..".")
return false
end
end
-- all ok so far; we can proceed
if(how_to_interact == "put") then
local r1 = npc_inv:remove_item(npc_inv_name, stack)
local r2 = inv:add_item(inv_name, r1)
return true
elseif(how_to_interact == "take") then
local r1 = inv:remove_item(inv_name, stack)
local r2 = npc_inv:add_item(npc_inv_name, r1)
return true
end
return false
elseif(r.r_type == "dialog"
or r.r_type == "on_failure") then