From b946ad3cefa6c0aa20f6c8b6c8b4f6079f8a975b Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 14 Feb 2017 01:25:02 +0100 Subject: [PATCH] Make hoppers work with all containers ... by massively simplifying the ABM code and using mcl_util code --- mods/mcl_hoppers/init.lua | 326 ++++---------------------------------- mods/mcl_util/init.lua | 30 +++- 2 files changed, 59 insertions(+), 297 deletions(-) diff --git a/mods/mcl_hoppers/init.lua b/mods/mcl_hoppers/init.lua index 1571f7f6..b44cb918 100644 --- a/mods/mcl_hoppers/init.lua +++ b/mods/mcl_hoppers/init.lua @@ -160,155 +160,24 @@ minetest.register_abm({ interval = 1.0, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) + -- Get node pos' for item transfer + local uppos = {x=pos.x,y=pos.y+1,z=pos.z} + local downpos = {x=pos.x,y=pos.y-1,z=pos.z} - local min = {x=pos.x-1,y=pos.y-1,z=pos.z-1} - local max = {x=pos.x+1,y=pos.y+1,z=pos.z+1} - local vm = minetest.get_voxel_manip() - local emin, emax = vm:read_from_map(min,max) - local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax} - local data = vm:get_data() - - local a = vm:get_node_at({x=pos.x,y=pos.y-1,z=pos.z}).name - local b = vm:get_node_at({x=pos.x,y=pos.y+1,z=pos.z}).name - local ag = minetest.get_node_group(a, "shulker_box") - local bg = minetest.get_node_group(b, "shulker_box") - local ashulker = not (ag == 0 or ag == nil) - local bshulker = not (bg == 0 or bg == nil) - - --the mcl_hoppers input - if b == "mcl_chests:chest" or b == "mcl_chests:chest_left" or b == "mcl_chests:chest_right" or bshulker or b == "mcl_hoppers:hopper" or b == "mcl_hoppers:hopper_side" then - --mcl_hoppers inventory - local meta = minetest.get_meta(pos); - local inv = meta:get_inventory() - local invsize = inv:get_size("main") - - --chest/mcl_hoppers/furnace inventory - local meta2 = minetest.get_meta({x=pos.x,y=pos.y+1,z=pos.z}); - local inv2 = meta2:get_inventory() - local invsize2 = inv2:get_size("main") - if inv2:is_empty("main") == false then - for i = 1,invsize2 do - local stack = inv2:get_stack("main", i) - local item = stack:get_name() - if item ~= "" then - if inv:room_for_item("main", item) == false then - --print("no room for items 2") - --return - end - --print(stack:to_string()) - stack:take_item(1) - inv2:set_stack("main", i, stack) - --add to mcl_hoppers - --print("adding item") - inv:add_item("main", item) - break - - end - end - end - end - if b == "mcl_furnaces:furnace" or b == "mcl_furnaces:furnace_active" then - --mcl_hoppers inventory - local meta = minetest.get_meta(pos); - local inv = meta:get_inventory() - local invsize = inv:get_size("main") - - --chest/mcl_hoppers/furnace inventory - local meta2 = minetest.get_meta({x=pos.x,y=pos.y+1,z=pos.z}); - local inv2 = meta2:get_inventory() - local invsize2 = inv2:get_size("dst") - if inv2:is_empty("dst") == false then - - for i = 1,invsize2 do - local stack = inv2:get_stack("dst", i) - local item = stack:get_name() - if item ~= "" then - if inv:room_for_item("main", item) == false then - --print("no room for items") - return - end - --print(stack:to_string()) - stack:take_item(1) - inv2:set_stack("dst", i, stack) - --add to mcl_hoppers - --print("adding item") - inv:add_item("main", item) - break - - end - end - end - end + -- Move an item from the hopper into container below + mcl_util.move_item_container(pos, "main", -1, downpos) - --the mcl_hoppers output - if a == "mcl_chests:chest" or a == "mcl_chests:chest_left" or a == "mcl_chests:chest_right" or ashulker or a == "mcl_hoppers:hopper" or a == "mcl_hoppers:hopper_side" then - --mcl_hoppers inventory - local meta = minetest.get_meta(pos); - local inv = meta:get_inventory() - if inv:is_empty("main") == true then - return - end - local invsize = inv:get_size("main") - - --chest/mcl_hoppers/furnace inventory - local meta2 = minetest.get_meta({x=pos.x,y=pos.y-1,z=pos.z}); - local inv2 = meta2:get_inventory() - local invsize2 = inv2:get_size("main") - - for i = 1,invsize do - local stack = inv:get_stack("main", i) - local item = stack:get_name() - if item ~= "" then - if inv2:room_for_item("main", item) == false then - --print("no room for items") - return - end - stack:take_item(1) - inv:set_stack("main", i, stack) - --add to mcl_hoppers or chest - --print("adding item") - inv2:add_item("main", item) - break - - end - end - --print(inv) - elseif a == "mcl_furnaces:furnace" or a == "mcl_furnaces:furnace_active" then - --print("test") - --room_for_item(listname, stack) - --mcl_hoppers inventory - local meta = minetest.get_meta(pos); - --print(dump(meta:to_table())) - local inv = meta:get_inventory() - if inv:is_empty("main") == true then - return - end - local invsize = inv:get_size("main") - - --chest/mcl_hoppers/furnace inventory - local meta2 = minetest.get_meta({x=pos.x,y=pos.y-1,z=pos.z}); - local inv2 = meta2:get_inventory() - local invsize2 = inv2:get_size("src") - - for i = 1,invsize do - local stack = inv:get_stack("main", i) - local item = stack:get_name() - if item ~= "" then - if inv2:room_for_item("src", item) == false then - --print("no room for items") - return - end - minetest.get_node_timer({x=pos.x,y=pos.y-1,z=pos.z}):start(1.0) - stack:take_item(1) - inv:set_stack("main", i, stack) - --add to mcl_hoppers or chest - --print("adding item") - inv2:add_item("src", item) - break - - end - end + -- Suck an item from the container above into the hopper + local upnode = minetest.get_node(uppos) + local g = minetest.registered_nodes[upnode.name].groups.container + if g == 2 or g == 3 then + -- Typical container inventory + mcl_util.move_item_container(uppos, "main", -1, pos) + elseif g == 4 then + -- Furnace output + mcl_util.move_item_container(uppos, "dst", -1, pos) end + end, }) @@ -319,16 +188,9 @@ minetest.register_abm({ interval = 1.0, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - - local min = {x=pos.x-1,y=pos.y-1,z=pos.z-1} - local max = {x=pos.x+1,y=pos.y+1,z=pos.z+1} - local vm = minetest.get_voxel_manip() - local emin, emax = vm:read_from_map(min,max) - local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax} - local data = vm:get_data() - local face = vm:get_node_at(pos).param2 + -- Determine to which side the hopper is facing, get nodes + local face = minetest.get_node(pos).param2 local front = {} - --print(face) if face == 0 then front = {x=pos.x-1,y=pos.y,z=pos.z} elseif face == 1 then @@ -338,150 +200,24 @@ minetest.register_abm({ elseif face == 3 then front = {x=pos.x,y=pos.y,z=pos.z-1} end - local a = vm:get_node_at(front).name - local b = vm:get_node_at({x=pos.x,y=pos.y+1,z=pos.z}).name - local ag = minetest.get_node_group(a, "shulker_box") - local bg = minetest.get_node_group(b, "shulker_box") - local ashulker = not (ag == 0 or ag == nil) - local bshulker = not (bg == 0 or bg == nil) + local above = {x=pos.x,y=pos.y+1,z=pos.z} - --the mcl_hoppers input - if b == "mcl_chests:chest" or b == "mcl_chests:chest_left" or b == "mcl_chests:chest_right" or bshulker or b == "mcl_hoppers:hopper" or b == "mcl_hoppers:hopper_side" then - --mcl_hoppers inventory - local meta = minetest.get_meta(pos); - local inv = meta:get_inventory() - local invsize = inv:get_size("main") - - --chest/mcl_hoppers/furnace inventory - local meta2 = minetest.get_meta({x=pos.x,y=pos.y+1,z=pos.z}); - local inv2 = meta2:get_inventory() - local invsize2 = inv2:get_size("main") - if inv2:is_empty("main") == false then - for i = 1,invsize2 do - local stack = inv2:get_stack("main", i) - local item = stack:get_name() - if item ~= "" then - if inv:room_for_item("main", item) == false then - --print("no room for items 2") - --return - end - --print(stack:to_string()) - stack:take_item(1) - inv2:set_stack("main", i, stack) - --add to mcl_hoppers - --print("adding item") - inv:add_item("main", item) - break - - end - end - end - end - if b == "mcl_furnaces:furnace" or b == "mcl_furnaces:furnace_active" then - --mcl_hoppers inventory - local meta = minetest.get_meta(pos); - local inv = meta:get_inventory() - local invsize = inv:get_size("main") - - --chest/mcl_hoppers/furnace inventory - local meta2 = minetest.get_meta({x=pos.x,y=pos.y+1,z=pos.z}); - local inv2 = meta2:get_inventory() - local invsize2 = inv2:get_size("dst") - if inv2:is_empty("dst") == false then - for i = 1,invsize2 do - local stack = inv2:get_stack("dst", i) - local item = stack:get_name() - if item ~= "" then - if inv:room_for_item("main", item) == false then - --print("no room for items") - return - end - --print(stack:to_string()) - stack:take_item(1) - inv2:set_stack("dst", i, stack) - --add to mcl_hoppers - --print("adding item") - inv:add_item("main", item) - break - - end - end - end - end + local frontnode = minetest.get_node(front) - --the mcl_hoppers output - if a == "mcl_chests:chest" or a == "mcl_chests:chest_left" or "mcl_chests:chest_right" or ashulker or a == "mcl_hoppers:hopper" or a == "mcl_hoppers:hopper_side" then - --print("test") - --room_for_item(listname, stack) - --mcl_hoppers inventory - local meta = minetest.get_meta(pos); - --print(dump(meta:to_table())) - local inv = meta:get_inventory() - if inv:is_empty("main") == true then - return - end - local invsize = inv:get_size("main") + -- Move an item from the hopper into the container to which the hopper points to + mcl_util.move_item_container(pos, "main", -1, front) - --chest/mcl_hoppers/furnace inventory - local meta2 = minetest.get_meta(front); - local inv2 = meta2:get_inventory() - local invsize2 = inv2:get_size("main") - - for i = 1,invsize do - local stack = inv:get_stack("main", i) - local item = stack:get_name() - if item ~= "" then - if inv2:room_for_item("main", item) == false then - --print("no room for items") - return - end - stack:take_item(1) - inv:set_stack("main", i, stack) - --add to mcl_hoppers or chest - --print("adding item") - inv2:add_item("main", item) - break - - end - end - --print(inv) - elseif a == "mcl_furnaces:furnace" or a == "mcl_furnaces:furnace_active" then - --print("test") - --room_for_item(listname, stack) - --mcl_hoppers inventory - local meta = minetest.get_meta(pos); - --print(dump(meta:to_table())) - local inv = meta:get_inventory() - if inv:is_empty("main") == true then - return - end - local invsize = inv:get_size("main") - - --chest/mcl_hoppers/furnace inventory - local meta2 = minetest.get_meta(front); - local inv2 = meta2:get_inventory() - local invsize2 = inv2:get_size("fuel") - - for i = 1,invsize do - local stack = inv:get_stack("main", i) - local item = stack:get_name() - if item ~= "" then - if inv2:room_for_item("fuel", item) == false then - --print("no room for items") - return - end - stack:take_item(1) - inv:set_stack("main", i, stack) - --add to mcl_hoppers or chest - --print("adding item") - minetest.get_node_timer(front):start(1.0) - inv2:add_item("fuel", item) - break - - end - end + -- Suck an item from the container above into the hopper + local abovenode = minetest.get_node(above) + local g = minetest.registered_nodes[abovenode.name].groups.container + if g == 2 or g == 3 then + -- Typical container inventory + mcl_util.move_item_container(above, "main", -1, pos) + elseif g == 4 then + -- Furnace output + mcl_util.move_item_container(above, "dst", -1, pos) end - end, + end }) minetest.register_craftitem("mcl_hoppers:hopper_item", { diff --git a/mods/mcl_util/init.lua b/mods/mcl_util/init.lua index 916d0bcb..930f71a0 100644 --- a/mods/mcl_util/init.lua +++ b/mods/mcl_util/init.lua @@ -100,13 +100,20 @@ end -- Moves a single item from one inventory to another --- source_inventory: Inventory to take the item from --- source_list: List name of the source inventory from which to take the item ---- source_stack_id: The inventory position ID of the source inventory to take the item from +--- source_stack_id: The inventory position ID of the source inventory to take the item from (-1 for first occupied slot) --- destination_inventory: Put item into this inventory --- destination_list: List name of the destination inventory to which to put the item into -- Returns true on success and false on failure -- Possible failures: No item in source slot, destination inventory full function mcl_util.move_item(source_inventory, source_list, source_stack_id, destination_inventory, destination_list) + if source_stack_id == -1 then + source_stack_id = mcl_util.get_first_occupied_inventory_slot(source_inventory, source_list) + if source_stack_id == nil then + return false + end + end + if not source_inventory:is_empty(source_list) then local stack = source_inventory:get_stack(source_list, source_stack_id) local item = stack:get_name() @@ -126,7 +133,7 @@ end -- Moves a single item from one container node into another. --- source_pos: Position ({x,y,z}) of the node to take the item from --- source_list: List name of the source inventory from which to take the item ---- source_stack_id: The inventory position ID of the source inventory to take the item from +--- source_stack_id: The inventory position ID of the source inventory to take the item from (-1 for first occupied slot) --- destination_pos: Position ({x,y,z}) of the node to put the item into -- Returns true on success and false on failure function mcl_util.move_item_container(source_pos, source_list, source_stack_id, destination_pos) @@ -139,6 +146,13 @@ function mcl_util.move_item_container(source_pos, source_list, source_stack_id, local snodedef = minetest.registered_nodes[minetest.get_node(source_pos).name] local dnodedef = minetest.registered_nodes[minetest.get_node(destination_pos).name] + if source_stack_id == -1 then + source_stack_id = mcl_util.get_first_occupied_inventory_slot(sinv, source_list) + if source_stack_id == nil then + return false + end + end + -- If it's a container, put it into the container if dnodedef.groups.container then if dnodedef.groups.container == 2 or snodedef.groups.continer == 3 then @@ -154,3 +168,15 @@ function mcl_util.move_item_container(source_pos, source_list, source_stack_id, end return false end + +-- Returns the ID of the first non-empty slot in the given inventory list +-- or nil, if inventory is empty. +function mcl_util.get_first_occupied_inventory_slot(inventory, listname) + for i=1, inventory:get_size(listname) do + local stack = inventory:get_stack(listname, i) + if not stack:is_empty() then + return i + end + end + return nil +end