Add multi-node containers support

+ remove trailing spaces
+ add new api for extra information about containers
This commit is contained in:
Ajrat Makhmutov 2024-07-21 04:16:35 +03:00 committed by SmallJoker
parent d0c8e18c5a
commit df5f8d8379
6 changed files with 184 additions and 104 deletions

@ -9,7 +9,7 @@ minetest.register_abm({
if active_object_count_wider == 0 then if active_object_count_wider == 0 then
return return
end end
local inv = minetest.get_meta(pos):get_inventory() local inv = minetest.get_meta(pos):get_inventory()
local posob local posob
@ -96,21 +96,21 @@ minetest.register_abm({
source_pos = vector.subtract(pos, destination_dir) source_pos = vector.subtract(pos, destination_dir)
destination_pos = vector.add(pos, destination_dir) destination_pos = vector.add(pos, destination_dir)
end end
local output_direction local output_direction
if destination_dir.y == 0 then if destination_dir.y == 0 then
output_direction = "horizontal" output_direction = "horizontal"
end end
local source_node = minetest.get_node(source_pos) local source_node = minetest.get_node(source_pos)
local destination_node = minetest.get_node(destination_pos) local destination_node = minetest.get_node(destination_pos)
local registered_source_inventories = hopper.get_registered_inventories_for(source_node.name) local registered_source_inventories = hopper.get_registered(source_node.name)
if registered_source_inventories ~= nil then if registered_source_inventories ~= nil then
hopper.take_item_from(pos, source_pos, source_node, registered_source_inventories["top"]) hopper.take_item_from(pos, source_pos, source_node, registered_source_inventories["top"])
end end
local registered_destination_inventories = hopper.get_registered_inventories_for(destination_node.name) local registered_destination_inventories = hopper.get_registered(destination_node.name)
if registered_destination_inventories ~= nil then if registered_destination_inventories ~= nil then
if output_direction == "horizontal" then if output_direction == "horizontal" then
hopper.send_item_to(pos, destination_pos, destination_node, registered_destination_inventories["side"]) hopper.send_item_to(pos, destination_pos, destination_node, registered_destination_inventories["side"])

130
api.lua

@ -2,60 +2,112 @@ hopper.containers = {}
hopper.groups = {} hopper.groups = {}
hopper.neighbors = {} hopper.neighbors = {}
local function parse_group(target_node)
local number
local identifier
local equals_index = string.find(target_node, "=")
if equals_index ~= nil then
identifier = string.sub(target_node, 7, equals_index-1)
-- it's possible that the string was of the form "group:blah = 1", in which case we want to trim spaces off the end of the group identifier
local space_index = string.find(identifier, " ")
if space_index ~= nil then
identifier = string.sub(identifier, 1, space_index-1)
end
number = tonumber(string.sub(target_node, equals_index+1, -1))
else
identifier = string.sub(target_node, 7, -1)
number = "all" -- special value to indicate no number was provided
end
return identifier, number
end
local function is_already_in_neighbors(neighbor_node)
for _, value in pairs(hopper.neighbors) do
if value == neighbor_node then
return true
end
end
return false
end
-- global function to add new containers -- global function to add new containers
function hopper:add_container(list) function hopper:add_container(list)
for _, entry in pairs(list) do for _, entry in pairs(list) do
local target_node = entry[2] local target_node = entry[2]
local neighbor_node local neighbor_node
if string.sub(target_node, 1, 6) == "group:" then if string.sub(target_node, 1, 6) == "group:" then
local group_identifier, group_number local group_identifier, group_number = parse_group(target_node)
local equals_index = string.find(target_node, "=")
if equals_index ~= nil then if hopper.groups[group_identifier] == nil then
group_identifier = string.sub(target_node, 7, equals_index-1) hopper.groups[group_identifier] = {}
-- it's possible that the string was of the form "group:blah = 1", in which case we want to trim spaces off the end of the group identifier
local space_index = string.find(group_identifier, " ")
if space_index ~= nil then
group_identifier = string.sub(group_identifier, 1, space_index-1)
end
group_number = tonumber(string.sub(target_node, equals_index+1, -1))
else
group_identifier = string.sub(target_node, 7, -1)
group_number = "all" -- special value to indicate no number was provided
end end
local group = hopper.groups[group_identifier][group_number]
local group_info = hopper.groups[group_identifier] if group == nil then
if group_info == nil then group = {}
group_info = {}
end end
if group_info[group_number] == nil then if group[entry[1]] == nil then
group_info[group_number] = {} group[entry[1]] = {}
end end
group_info[group_number][entry[1]] = entry[3] group[entry[1]]["inventory_name"] = entry[3]
hopper.groups[group_identifier] = group_info if entry["get_inventory"] then
group[entry[1]]["get_inventory"] = entry["get_inventory"]
end
hopper.groups[group_identifier][group_number] = group
neighbor_node = "group:"..group_identifier neighbor_node = "group:"..group_identifier
-- result is a table of the form groups[group_identifier][group_number][relative_position][inventory_name] -- result is a table of the form:
-- groups[group_identifier][group_number][relative_position]{"inventory_name","get_inventory"}
else else
local node_info = hopper.containers[target_node] local node_info = hopper.containers[target_node]
if node_info == nil then if node_info == nil then
node_info = {} node_info = {}
end end
node_info[entry[1]] = entry[3] if node_info[entry[1]] == nil then
node_info[entry[1]] = {}
end
node_info[entry[1]]["inventory_name"] = entry[3]
if entry["get_inventory"] then
node_info[entry[1]]["get_inventory"] = entry["get_inventory"]
end
hopper.containers[target_node] = node_info hopper.containers[target_node] = node_info
neighbor_node = target_node neighbor_node = target_node
-- result is a table of the form containers[target_node_name][relative_position][inventory_name] -- result is a table of the form:
-- containers[target_node_name][relative_position]{"inventory_name","get_inventory"}
end end
local already_in_neighbors = false if not is_already_in_neighbors(neighbor_node) then
for _, value in pairs(hopper.neighbors) do table.insert(hopper.neighbors, neighbor_node)
if value == neighbor_node then end
already_in_neighbors = true end
end
-- global function for additional information about containers
function hopper:set_extra_container_info(list)
for _, entry in pairs(list) do
local target_node = entry[1]
table.remove(entry, 1) -- only extra information
if string.sub(target_node, 1, 6) == "group:" then
local group_identifier, group_number = parse_group(target_node)
if not is_already_in_neighbors("group:" .. group_identifier) then
minetest.log("error","An attempt to add extra information for " ..
target_node .. " in the absence of the main one")
break break
end end
end hopper.groups[group_identifier][group_number].extra = entry
if not already_in_neighbors then -- result is a table of the form:
table.insert(hopper.neighbors, neighbor_node) -- groups[group_identifier][group_number]["extra"][list of extra information]
else
if not is_already_in_neighbors(target_node) then
minetest.log("error","An attempt to add extra information for " ..
target_node .. " in the absence of the main one")
break
end
hopper.containers[target_node].extra = entry
-- result is a table of the form:
-- containers[target_node_name]["extra"][list of extra information]
end end
end end
end end
@ -69,10 +121,10 @@ hopper:add_container({
{"bottom", "hopper:hopper", "main"}, {"bottom", "hopper:hopper", "main"},
{"side", "hopper:hopper", "main"}, {"side", "hopper:hopper", "main"},
{"side", "hopper:hopper_side", "main"}, {"side", "hopper:hopper_side", "main"},
{"bottom", "hopper:chute", "main"}, {"bottom", "hopper:chute", "main"},
{"side", "hopper:chute", "main"}, {"side", "hopper:chute", "main"},
{"bottom", "hopper:sorter", "main"}, {"bottom", "hopper:sorter", "main"},
{"side", "hopper:sorter", "main"}, {"side", "hopper:sorter", "main"},
}) })
@ -82,15 +134,15 @@ if minetest.get_modpath("default") then
{"top", "default:chest", "main"}, {"top", "default:chest", "main"},
{"bottom", "default:chest", "main"}, {"bottom", "default:chest", "main"},
{"side", "default:chest", "main"}, {"side", "default:chest", "main"},
{"top", "default:furnace", "dst"}, {"top", "default:furnace", "dst"},
{"bottom", "default:furnace", "src"}, {"bottom", "default:furnace", "src"},
{"side", "default:furnace", "fuel"}, {"side", "default:furnace", "fuel"},
{"top", "default:furnace_active", "dst"}, {"top", "default:furnace_active", "dst"},
{"bottom", "default:furnace_active", "src"}, {"bottom", "default:furnace_active", "src"},
{"side", "default:furnace_active", "fuel"}, {"side", "default:furnace_active", "fuel"},
{"top", "default:chest_locked", "main"}, {"top", "default:chest_locked", "main"},
{"bottom", "default:chest_locked", "main"}, {"bottom", "default:chest_locked", "main"},
{"side", "default:chest_locked", "main"}, {"side", "default:chest_locked", "main"},

@ -41,7 +41,7 @@ minetest.register_node("hopper:chute", {
{-0.2, -0.2, 0.3, 0.2, 0.2, 0.7}, {-0.2, -0.2, 0.3, 0.2, 0.2, 0.7},
}, },
}, },
on_construct = function(pos) on_construct = function(pos)
local inv = minetest.get_meta(pos):get_inventory() local inv = minetest.get_meta(pos):get_inventory()
inv:set_size("main", 2*2) inv:set_size("main", 2*2)
@ -60,7 +60,7 @@ minetest.register_node("hopper:chute", {
end end
return returned_stack return returned_stack
end, end,
can_dig = function(pos,player) can_dig = function(pos,player)
local inv = minetest.get_meta(pos):get_inventory() local inv = minetest.get_meta(pos):get_inventory()
return inv:is_empty("main") return inv:is_empty("main")
@ -81,7 +81,7 @@ minetest.register_node("hopper:chute", {
local timer = minetest.get_node_timer(pos) local timer = minetest.get_node_timer(pos)
if not timer:is_started() then if not timer:is_started() then
timer:start(1) timer:start(1)
end end
end, end,
on_timer = function(pos, elapsed) on_timer = function(pos, elapsed)
@ -95,9 +95,9 @@ minetest.register_node("hopper:chute", {
if dir.y == 0 then if dir.y == 0 then
output_direction = "horizontal" output_direction = "horizontal"
end end
local destination_node = minetest.get_node(destination_pos) local destination_node = minetest.get_node(destination_pos)
local registered_inventories = hopper.get_registered_inventories_for(destination_node.name) local registered_inventories = hopper.get_registered(destination_node.name)
if registered_inventories ~= nil then if registered_inventories ~= nil then
if output_direction == "horizontal" then if output_direction == "horizontal" then
hopper.send_item_to(pos, destination_pos, destination_node, registered_inventories["side"]) hopper.send_item_to(pos, destination_pos, destination_node, registered_inventories["side"])
@ -107,7 +107,7 @@ minetest.register_node("hopper:chute", {
else else
hopper.send_item_to(pos, destination_pos, destination_node) hopper.send_item_to(pos, destination_pos, destination_node)
end end
if not inv:is_empty("main") then if not inv:is_empty("main") then
minetest.get_node_timer(pos):start(1) minetest.get_node_timer(pos):start(1)
end end

@ -29,16 +29,22 @@ local hopper_on_place = function(itemstack, placer, pointed_thing, node_name)
return returned_stack return returned_stack
end end
local pointed_pos = pointed_thing.under local pointed_pos = pointed_thing.under
local hopper_pos = pointed_thing.above local hopper_pos = pointed_thing.above
local param2_by_offset = { local param2
[vector.new(-1, 0, 0):to_string()] = 0, local pointed_registered = hopper.get_registered(minetest.get_node(pointed_pos).name)
[vector.new( 0, 0, 1):to_string()] = 1, if pointed_registered and pointed_registered.extra.set_hopper_param2 then
[vector.new( 1, 0, 0):to_string()] = 2, param2 = pointed_registered.extra.set_hopper_param2(hopper_pos, pointed_pos)
[vector.new( 0, 0,-1):to_string()] = 3, else
} local param2_by_offset = {
local param2 = param2_by_offset[(pointed_pos - hopper_pos):to_string()] [vector.new(-1, 0, 0):to_string()] = 0,
[vector.new( 0, 0, 1):to_string()] = 1,
[vector.new( 1, 0, 0):to_string()] = 2,
[vector.new( 0, 0,-1):to_string()] = 3,
}
param2 = param2_by_offset[(pointed_pos - hopper_pos):to_string()]
end
if param2 then if param2 then
returned_stack, success = minetest.item_place_node(ItemStack("hopper:hopper_side"), placer, pointed_thing, param2) returned_stack, success = minetest.item_place_node(ItemStack("hopper:hopper_side"), placer, pointed_thing, param2)
@ -196,7 +202,7 @@ minetest.register_node("hopper:hopper_side", {
{-0.7, -0.3, -0.15, 0.15, 0.0, 0.15}, {-0.7, -0.3, -0.15, 0.15, 0.0, 0.15},
}, },
}, },
on_construct = function(pos) on_construct = function(pos)
local inv = minetest.get_meta(pos):get_inventory() local inv = minetest.get_meta(pos):get_inventory()
inv:set_size("main", 4*4) inv:set_size("main", 4*4)
@ -205,7 +211,7 @@ minetest.register_node("hopper:hopper_side", {
on_place = function(itemstack, placer, pointed_thing) on_place = function(itemstack, placer, pointed_thing)
return hopper_on_place(itemstack, placer, pointed_thing, "hopper:hopper_side") return hopper_on_place(itemstack, placer, pointed_thing, "hopper:hopper_side")
end, end,
can_dig = function(pos,player) can_dig = function(pos,player)
local inv = minetest.get_meta(pos):get_inventory() local inv = minetest.get_meta(pos):get_inventory()
return inv:is_empty("main") return inv:is_empty("main")

@ -16,7 +16,7 @@ end
local function get_sorter_formspec(pos) local function get_sorter_formspec(pos)
local spos = hopper.get_string_pos(pos) local spos = hopper.get_string_pos(pos)
local filter_all = minetest.get_meta(pos):get_string("filter_all") == "true" local filter_all = minetest.get_meta(pos):get_string("filter_all") == "true"
local y_displace = 0 local y_displace = 0
local filter_texture, filter_button_tooltip, filter_body local filter_texture, filter_button_tooltip, filter_body
@ -30,11 +30,11 @@ local function get_sorter_formspec(pos)
filter_button_tooltip = FS("This sorter is currently set to only send items listed\nin the filter list in the direction of the arrow.\nClick this button to set it to try sending all\nitems that way first.") filter_button_tooltip = FS("This sorter is currently set to only send items listed\nin the filter list in the direction of the arrow.\nClick this button to set it to try sending all\nitems that way first.")
y_displace = 1.6 y_displace = 1.6
end end
local formspec = local formspec =
"size[8," .. 7 + y_displace .. "]" "size[8," .. 7 + y_displace .. "]"
.. hopper.formspec_bg .. hopper.formspec_bg
.. filter_body .. filter_body
.. "list[nodemeta:" .. spos .. ";main;3,".. tostring(0.3 + y_displace) .. ";2,2;]" .. "list[nodemeta:" .. spos .. ";main;3,".. tostring(0.3 + y_displace) .. ";2,2;]"
.. ("image_button_exit[0,%g;1,1;%s;filter_all;]"):format(y_displace, filter_texture) .. ("image_button_exit[0,%g;1,1;%s;filter_all;]"):format(y_displace, filter_texture)
.. "tooltip[filter_all;" .. filter_button_tooltip.. "]" .. "tooltip[filter_all;" .. filter_button_tooltip.. "]"
@ -72,14 +72,14 @@ minetest.register_node("hopper:sorter", {
{-0.2, -0.3, -0.2, 0.2, -0.7, 0.2}, {-0.2, -0.3, -0.2, 0.2, -0.7, 0.2},
}, },
}, },
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
inv:set_size("main", 2*2) inv:set_size("main", 2*2)
inv:set_size("filter", 8) inv:set_size("filter", 8)
end, end,
on_place = function(itemstack, placer, pointed_thing, node_name) on_place = function(itemstack, placer, pointed_thing, node_name)
local pos = pointed_thing.under local pos = pointed_thing.under
local pos2 = pointed_thing.above local pos2 = pointed_thing.above
@ -93,13 +93,13 @@ minetest.register_node("hopper:sorter", {
end end
return returned_stack return returned_stack
end, end,
can_dig = function(pos,player) can_dig = function(pos,player)
local meta = minetest.get_meta(pos); local meta = minetest.get_meta(pos);
local inv = meta:get_inventory() local inv = meta:get_inventory()
return inv:is_empty("main") return inv:is_empty("main")
end, end,
on_rightclick = function(pos, node, clicker, itemstack) on_rightclick = function(pos, node, clicker, itemstack)
if minetest.is_protected(pos, clicker:get_player_name()) and not minetest.check_player_privs(clicker, "protection_bypass") then if minetest.is_protected(pos, clicker:get_player_name()) and not minetest.check_player_privs(clicker, "protection_bypass") then
return return
@ -107,7 +107,7 @@ minetest.register_node("hopper:sorter", {
minetest.show_formspec(clicker:get_player_name(), minetest.show_formspec(clicker:get_player_name(),
"hopper_formspec:"..minetest.pos_to_string(pos), get_sorter_formspec(pos)) "hopper_formspec:"..minetest.pos_to_string(pos), get_sorter_formspec(pos))
end, end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player) allow_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname == "filter" then if listname == "filter" then
local inv = minetest.get_inventory({type="node", pos=pos}) local inv = minetest.get_inventory({type="node", pos=pos})
@ -116,7 +116,7 @@ minetest.register_node("hopper:sorter", {
end end
return stack:get_count() return stack:get_count()
end, end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player) allow_metadata_inventory_take = function(pos, listname, index, stack, player)
if listname == "filter" then if listname == "filter" then
local inv = minetest.get_inventory({type="node", pos=pos}) local inv = minetest.get_inventory({type="node", pos=pos})
@ -125,7 +125,7 @@ minetest.register_node("hopper:sorter", {
end end
return stack:get_count() return stack:get_count()
end, end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
if to_list == "filter" then if to_list == "filter" then
local inv = minetest.get_inventory({type="node", pos=pos}) local inv = minetest.get_inventory({type="node", pos=pos})
@ -135,11 +135,11 @@ minetest.register_node("hopper:sorter", {
elseif from_list == "filter" then elseif from_list == "filter" then
local inv = minetest.get_inventory({type="node", pos=pos}) local inv = minetest.get_inventory({type="node", pos=pos})
inv:set_stack(from_list, from_index, ItemStack("")) inv:set_stack(from_list, from_index, ItemStack(""))
return 0 return 0
end end
return count return count
end, end,
on_metadata_inventory_put = function(pos, listname, index, stack, player) on_metadata_inventory_put = function(pos, listname, index, stack, player)
hopper.log_inventory(("%s moves stuff to sorter at %s"):format( hopper.log_inventory(("%s moves stuff to sorter at %s"):format(
player:get_player_name(), minetest.pos_to_string(pos))) player:get_player_name(), minetest.pos_to_string(pos)))
@ -147,15 +147,15 @@ minetest.register_node("hopper:sorter", {
local timer = minetest.get_node_timer(pos) local timer = minetest.get_node_timer(pos)
if not timer:is_started() then if not timer:is_started() then
timer:start(1) timer:start(1)
end end
end, end,
on_timer = function(pos, elapsed) on_timer = function(pos, elapsed)
local meta = minetest.get_meta(pos); local meta = minetest.get_meta(pos);
local inv = meta:get_inventory() local inv = meta:get_inventory()
-- build a filter list -- build a filter list
local filter_items = nil local filter_items = nil
if meta:get_string("filter_all") ~= "true" then if meta:get_string("filter_all") ~= "true" then
filter_items = {} filter_items = {}
local filter_inv_size = inv:get_size("filter") local filter_inv_size = inv:get_size("filter")
@ -167,7 +167,7 @@ minetest.register_node("hopper:sorter", {
end end
end end
end end
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
local dir = minetest.facedir_to_dir(node.param2) local dir = minetest.facedir_to_dir(node.param2)
local default_destination_pos = vector.add(pos, dir) local default_destination_pos = vector.add(pos, dir)
@ -184,9 +184,9 @@ minetest.register_node("hopper:sorter", {
end end
local success = false local success = false
local filter_destination_node = minetest.get_node(filter_destination_pos) local filter_destination_node = minetest.get_node(filter_destination_pos)
local registered_inventories = hopper.get_registered_inventories_for(filter_destination_node.name) local registered_inventories = hopper.get_registered(filter_destination_node.name)
if registered_inventories ~= nil then if registered_inventories ~= nil then
if filter_output_direction == "horizontal" then if filter_output_direction == "horizontal" then
success = hopper.send_item_to(pos, filter_destination_pos, filter_destination_node, registered_inventories["side"], filter_items) success = hopper.send_item_to(pos, filter_destination_pos, filter_destination_node, registered_inventories["side"], filter_items)
@ -196,10 +196,10 @@ minetest.register_node("hopper:sorter", {
else else
success = hopper.send_item_to(pos, filter_destination_pos, filter_destination_node, nil, filter_items) success = hopper.send_item_to(pos, filter_destination_pos, filter_destination_node, nil, filter_items)
end end
if not success then -- weren't able to put something in the filter destination, for whatever reason. Now we can start moving stuff forward to the default. if not success then -- weren't able to put something in the filter destination, for whatever reason. Now we can start moving stuff forward to the default.
local default_destination_node = minetest.get_node(default_destination_pos) local default_destination_node = minetest.get_node(default_destination_pos)
local registered_inventories = hopper.get_registered_inventories_for(default_destination_node.name) local registered_inventories = hopper.get_registered(default_destination_node.name)
if registered_inventories ~= nil then if registered_inventories ~= nil then
if default_output_direction == "horizontal" then if default_output_direction == "horizontal" then
hopper.send_item_to(pos, default_destination_pos, default_destination_node, registered_inventories["side"]) hopper.send_item_to(pos, default_destination_pos, default_destination_node, registered_inventories["side"])
@ -210,7 +210,7 @@ minetest.register_node("hopper:sorter", {
hopper.send_item_to(pos, default_destination_pos, default_destination_node) hopper.send_item_to(pos, default_destination_pos, default_destination_node)
end end
end end
if not inv:is_empty("main") then if not inv:is_empty("main") then
minetest.get_node_timer(pos):start(1) minetest.get_node_timer(pos):start(1)
end end

@ -4,7 +4,7 @@ local FS = hopper.translator_escaped
-- looks first for a registration matching the specific node name, then for a registration -- looks first for a registration matching the specific node name, then for a registration
-- matching group and value, then for a registration matching a group and *any* value -- matching group and value, then for a registration matching a group and *any* value
hopper.get_registered_inventories_for = function(target_node_name) hopper.get_registered = function(target_node_name)
local output = hopper.containers[target_node_name] local output = hopper.containers[target_node_name]
if output ~= nil then return output end if output ~= nil then return output end
@ -70,38 +70,48 @@ local get_placer = function(player_name)
end end
-- Used to remove items from the target block and put it into the hopper's inventory -- Used to remove items from the target block and put it into the hopper's inventory
hopper.take_item_from = function(hopper_pos, target_pos, target_node, target_inventory_name) hopper.take_item_from = function(hopper_pos, target_pos, target_node, target_inv_info)
if target_inventory_name == nil then
return
end
local target_def = minetest.registered_nodes[target_node.name] local target_def = minetest.registered_nodes[target_node.name]
if not target_def then if not target_def then
return return
end end
local target_inv_name = target_inv_info["inventory_name"]
local target_get_inv = target_inv_info["get_inventory"]
--hopper inventory --hopper inventory
local hopper_meta = minetest.get_meta(hopper_pos); local hopper_meta = minetest.get_meta(hopper_pos)
local hopper_inv = hopper_meta:get_inventory() local hopper_inv = hopper_meta:get_inventory()
local placer = get_placer(hopper_meta:get_string("placer")) local placer = get_placer(hopper_meta:get_string("placer"))
--source inventory --source inventory
local target_inv = minetest.get_meta(target_pos):get_inventory() local target_inv
local target_inv_size = target_inv:get_size(target_inventory_name) if target_get_inv then
if target_inv:is_empty(target_inventory_name) == false then target_inv = target_get_inv(target_pos)
if not target_inv then
minetest.log("error","No inventory from api get_inventory function: " ..
target_node.name .. " on " .. vector.to_string(target_pos))
return false
end
else
target_inv = minetest.get_meta(target_pos):get_inventory()
end
local target_inv_size = target_inv:get_size(target_inv_name)
if target_inv:is_empty(target_inv_name) == false then
for i = 1,target_inv_size do for i = 1,target_inv_size do
local stack = target_inv:get_stack(target_inventory_name, i) local stack = target_inv:get_stack(target_inv_name, i)
local item = stack:get_name() local item = stack:get_name()
if item ~= "" then if item ~= "" then
if hopper_inv:room_for_item("main", item) then if hopper_inv:room_for_item("main", item) then
local stack_to_take = stack:take_item(1) local stack_to_take = stack:take_item(1)
if target_def.allow_metadata_inventory_take == nil if target_def.allow_metadata_inventory_take == nil
or placer == nil -- backwards compatibility, older versions of this mod didn't record who placed the hopper or placer == nil -- backwards compatibility, older versions of this mod didn't record who placed the hopper
or target_def.allow_metadata_inventory_take(target_pos, target_inventory_name, i, stack_to_take, placer) > 0 then or target_def.allow_metadata_inventory_take(target_pos, target_inv_name, i, stack_to_take, placer) > 0 then
target_inv:set_stack(target_inventory_name, i, stack) target_inv:set_stack(target_inv_name, i, stack)
--add to hopper --add to hopper
hopper_inv:add_item("main", stack_to_take) hopper_inv:add_item("main", stack_to_take)
if target_def.on_metadata_inventory_take ~= nil and placer ~= nil then if target_def.on_metadata_inventory_take ~= nil and placer ~= nil then
target_def.on_metadata_inventory_take(target_pos, target_inventory_name, i, stack_to_take, placer) target_def.on_metadata_inventory_take(target_pos, target_inv_name, i, stack_to_take, placer)
end end
break break
end end
@ -112,7 +122,7 @@ hopper.take_item_from = function(hopper_pos, target_pos, target_node, target_inv
end end
-- Used to put items from the hopper inventory into the target block -- Used to put items from the hopper inventory into the target block
hopper.send_item_to = function(hopper_pos, target_pos, target_node, target_inventory_name, filtered_items) hopper.send_item_to = function(hopper_pos, target_pos, target_node, target_inv_info, filtered_items)
local hopper_meta = minetest.get_meta(hopper_pos) local hopper_meta = minetest.get_meta(hopper_pos)
local target_def = minetest.registered_nodes[target_node.name] local target_def = minetest.registered_nodes[target_node.name]
if not target_def then if not target_def then
@ -121,7 +131,7 @@ hopper.send_item_to = function(hopper_pos, target_pos, target_node, target_inven
local eject_item = hopper.config.eject_button_enabled and hopper_meta:get_string("eject") == "true" and target_def.buildable_to local eject_item = hopper.config.eject_button_enabled and hopper_meta:get_string("eject") == "true" and target_def.buildable_to
if not eject_item and not target_inventory_name then if not eject_item and not target_inv_info then
return false return false
end end
@ -135,23 +145,35 @@ hopper.send_item_to = function(hopper_pos, target_pos, target_node, target_inven
local placer = get_placer(hopper_meta:get_string("placer")) local placer = get_placer(hopper_meta:get_string("placer"))
--target inventory --target inventory
local target_inv = minetest.get_meta(target_pos):get_inventory() local target_inv_name = target_inv_info["inventory_name"]
local target_get_inv = target_inv_info["get_inventory"]
local target_inv
if target_get_inv then
target_inv = target_get_inv(target_pos)
if not target_inv then
minetest.log("error","No inventory from api get_inventory function: " ..
target_node.name .. " on " .. vector.to_string(target_pos))
return false
end
else
target_inv = minetest.get_meta(target_pos):get_inventory()
end
for i = 1,hopper_inv_size do for i = 1,hopper_inv_size do
local stack = hopper_inv:get_stack("main", i) local stack = hopper_inv:get_stack("main", i)
local item = stack:get_name() local item = stack:get_name()
if item ~= "" and (filtered_items == nil or filtered_items[item]) then if item ~= "" and (filtered_items == nil or filtered_items[item]) then
if target_inventory_name then if target_inv_name then
if target_inv:room_for_item(target_inventory_name, item) then if target_inv:room_for_item(target_inv_name, item) then
local stack_to_put = stack:take_item(1) local stack_to_put = stack:take_item(1)
if target_def.allow_metadata_inventory_put == nil if target_def.allow_metadata_inventory_put == nil
or placer == nil -- backwards compatibility, older versions of this mod didn't record who placed the hopper or placer == nil -- backwards compatibility, older versions of this mod didn't record who placed the hopper
or target_def.allow_metadata_inventory_put(target_pos, target_inventory_name, i, stack_to_put, placer) > 0 then or target_def.allow_metadata_inventory_put(target_pos, target_inv_name, i, stack_to_put, placer) > 0 then
hopper_inv:set_stack("main", i, stack) hopper_inv:set_stack("main", i, stack)
--add to target node --add to target node
target_inv:add_item(target_inventory_name, stack_to_put) target_inv:add_item(target_inv_name, stack_to_put)
if target_def.on_metadata_inventory_put ~= nil and placer ~= nil then if target_def.on_metadata_inventory_put ~= nil and placer ~= nil then
target_def.on_metadata_inventory_put(target_pos, target_inventory_name, i, stack_to_put, placer) target_def.on_metadata_inventory_put(target_pos, target_inv_name, i, stack_to_put, placer)
end end
return true return true
end end