From 6aa9b4a1de3f9f63ab007f1c6858e46194ae5e49 Mon Sep 17 00:00:00 2001 From: auouymous Date: Mon, 6 Aug 2018 06:55:08 -0600 Subject: [PATCH] Initial commit --- API | 48 +++++++ LICENSE-CC0 | 121 ++++++++++++++++ README.md | 18 +++ default_support.lua | 52 +++++++ depends.txt | 1 + init.lua | 225 +++++++++++++++++++++++++++++ patches/hopper-tenplus1.patch | 262 ++++++++++++++++++++++++++++++++++ 7 files changed, 727 insertions(+) create mode 100644 API create mode 100644 LICENSE-CC0 create mode 100644 README.md create mode 100644 default_support.lua create mode 100644 depends.txt create mode 100644 init.lua create mode 100644 patches/hopper-tenplus1.patch diff --git a/API b/API new file mode 100644 index 0000000..bd24bd4 --- /dev/null +++ b/API @@ -0,0 +1,48 @@ +side is a string: + U = +Y = up/top + D = -Y = down/bottom + N = +Z = north + S = -Z = south + E = +X = east + W = -X = west + +node definition implements all or some of these functions: + + node_io_can_put_item(pos, node, side) -> bool + node_io_can_put_liquid(pos, node, side) -> bool + node_io_can_take_item(pos, node, side) -> bool + node_io_can_take_liquid(pos, node, side) -> bool + + node_io_put_item(pos, node, side, putter, itemstack) + -- returns itemstack with leftovers or cleared + -- putter is a fake player + node_io_put_liquid(pos, node, side, putter, itemstack) + -- itemstack should be a source liquid (in bucket.liquids of bucket mod) + + node_io_room_for_item(pos, node, side, itemstack) -> bool + node_io_room_for_liquid(pos, node, side, itemstack) -> bool + + node_io_take_item(pos, node, side, taker, want_item, want_count) + -- returns an itemstack with <= want_count or nil if inventory is empty or doesn't have want_item + -- taker is a fake player + -- want_item should be nil for any item or contain a string with item name (filtered takes) + -- want_count should be greater than zero + -- returned itemstack shouldn't exceed max stack size, even if want_count does + node_io_take_liquid(pos, node, side, taker, want_liquid, want_count) + + -- items and liquid should not be put back after taken + -- use the following API to check if taken item can be used/stored before taking it + + node_io_get_item_size(pos, node, side) -> number of item inventory slots + -- can be used to iterate over an inventory + -- for i = 1, size do ... end + node_io_get_liquid_size(pos, node, side) -> number of liquid inventory slots + + node_io_get_item_name(pos, node, side, index) -> item name + -- can be used to get the name of the stack in inventory slot, and determine if it will fit in local inventory before taking it + -- want_count parameter for take_*() can be adjusted to only take what will fit in local inventory + node_io_get_liquid_name(pos, node, side, index) -> item name + + -- TODO: support power and signals + +init.lua contains utility functions to query and access nodes diff --git a/LICENSE-CC0 b/LICENSE-CC0 new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/LICENSE-CC0 @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/README.md b/README.md new file mode 100644 index 0000000..11074a4 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +Minetest Node-IO Mod +========== + +Inventory nodes currently must add support for every "pipe" mod. +And those mods usually don't support non-standard inventories. + +This mod aims to provide a common API for "pipe" mods to easily query and access any inventory nodes that has implemented the API. +The inventory nodes are in control and manage what can enter or exit any of their sides. + +This mod implements node-io support for default chest, locked chest and furnace. +If pipeworks mod is installed, the furnace loses support due to being redefined by pipeworks. + + + +Links +========== + +[Download](https://github.com/auouymous/node_io/archive/master.zip) diff --git a/default_support.lua b/default_support.lua new file mode 100644 index 0000000..0fe63e7 --- /dev/null +++ b/default_support.lua @@ -0,0 +1,52 @@ +-- add support for default mod + +if minetest.get_modpath("default") then + print("[Node IO] default support enabled") + + -- chest + node_io.init_main_inventory("default:chest", true) + node_io.init_main_inventory("default:chest_open", true) + -- locked chest + node_io.init_main_inventory("default:chest_locked", false) + node_io.init_main_inventory("default:chest_locked_open", false) + + local function init_furnace(node_name) + local def = {} + + def.node_io_can_put_item = function(pos, node, side) return true end + def.node_io_room_for_item = function(pos, node, side, itemstack) + local inv = minetest.get_meta(pos):get_inventory() + if not inv then return false end + local inv_name + if side == "U" then inv_name = "src" elseif side == "D" then inv_name = "dst" else inv_name = "fuel" end + return inv:room_for_item(inv_name, itemstack) + end + def.node_io_put_item = function(pos, node, side, what, itemstack) + local inv_name + if side == "U" then inv_name = "src" elseif side == "D" then inv_name = "dst" else inv_name = "fuel" end + return node_io.put_item_in_inventory(pos, node, inv_name, what, itemstack) + end + + def.node_io_can_take_item = function(pos, node, side) return true end + def.node_io_get_item_size = function(pos, node, side) + local inv_name + if side == "U" then inv_name = "src" elseif side == "D" then inv_name = "dst" else inv_name = "fuel" end + return node_io.get_inventory_size(pos, inv_name) + end + def.node_io_get_item_name = function(pos, node, side, index) + local inv_name + if side == "U" then inv_name = "src" elseif side == "D" then inv_name = "dst" else inv_name = "fuel" end + return node_io.get_inventory_name(pos, inv_name, index) + end + def.node_io_take_item = function(pos, node, side, what, want_item, want_count) + local inv_name + if side == "U" then inv_name = "src" elseif side == "D" then inv_name = "dst" else inv_name = "fuel" end + return node_io.take_item_from_inventory(pos, node, inv_name, what, want_item, want_count) + end + + minetest.override_item(node_name, def) + end + -- furnace + init_furnace("default:furnace") + init_furnace("default:furnace_active") +end diff --git a/depends.txt b/depends.txt new file mode 100644 index 0000000..5e78c21 --- /dev/null +++ b/depends.txt @@ -0,0 +1 @@ +default? diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..26a9b92 --- /dev/null +++ b/init.lua @@ -0,0 +1,225 @@ +node_io = {} +local MP = minetest.get_modpath("node_io").."/" + + + +-- get target side + +node_io.get_target_side = function(pos, target_pos) + if pos.y > target_pos.y then return "U" end + if pos.y < target_pos.y then return "D" end + + if pos.z > target_pos.z then return "N" end + if pos.z < target_pos.z then return "S" end + + if pos.x > target_pos.x then return "E" end + return "W" +end + +-- get pointed side + +node_io.get_pointed_side = function(pointer, pointed_thing) + local p0 = pointed_thing.under + local p1 = pointed_thing.above + if p0.y == p1.y then + if p0.z > p1.z then return "S" end + if p0.z < p1.z then return "N" end + if p0.x > p1.x then return "W" end + return "E" + elseif p0.y < p1.y then + return "U" + else + return "D" + end +end + + + +-- query API + +node_io.can_put_item = function(pos, node, side) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_can_put_item then return false end + return ndef.node_io_can_put_item(pos, node, side) +end +node_io.can_put_liquid = function(pos, node, side) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_can_put_liquid then return false end + return ndef.node_io_can_put_liquid(pos, node, side) +end + +node_io.can_take_item = function(pos, node, side) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_can_take_item then return false end + return ndef.node_io_can_take_item(pos, node, side) +end +node_io.can_take_liquid = function(pos, node, side) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_can_take_liquid then return false end + return ndef.node_io_can_take_liquid(pos, node, side) +end + +node_io.get_item_size = function(pos, node, side) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_get_item_size then return 0 end + return ndef.node_io_get_item_size(pos, node, side) +end +node_io.get_liquid_size = function(pos, node, side) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_get_liquid_size then return 0 end + return ndef.node_io_get_liquid_size(pos, node, side) +end + +node_io.get_item_name = function(pos, node, side, index) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_get_item_name then return "" end + return ndef.node_io_get_item_name(pos, node, side, index) +end +node_io.get_liquid_name = function(pos, node, side, index) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_get_liquid_name then return "" end + return ndef.node_io_get_liquid_name(pos, node, side, index) +end + + +-- access API + +node_io.put_item = function(pos, node, side, putter, itemstack) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_put_item then return itemstack end + return ndef.node_io_put_item(pos, node, side, putter, itemstack) +end +node_io.put_liquid = function(pos, node, side, putter, itemstack) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_put_liquid then return itemstack end + return ndef.node_io_put_liquid(pos, node, side, putter, itemstack) +end + +node_io.take_item = function(pos, node, side, taker, want_item, want_count) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_take_item then return nil end + return ndef.node_io_take_item(pos, node, side, taker, want_item, want_count) +end +node_io.take_liquid = function(pos, node, side, taker, want_liquid, want_count) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_take_liquid then return nil end + return ndef.node_io_take_liquid(pos, node, side, taker, want_liquid, want_count) +end + +node_io.room_for_item = function(pos, node, side, itemstack) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_room_for_item then return false end + return ndef.node_io_room_for_item(pos, node, side, itemstack) +end +node_io.room_for_liquid = function(pos, node, side, itemstack) + local ndef = minetest.registered_nodes[node.name] + if not ndef.node_io_room_for_liquid then return false end + return ndef.node_io_room_for_liquid(pos, node, side, itemstack) +end + + + +-- functions for mods with inventories to implement API + +node_io.make_itemstack = function(stack, count) + local itemstack = ItemStack(stack:get_name().." "..count) + itemstack:set_wear(stack:get_wear()) + return itemstack +end + +node_io.get_inventory_size = function(pos, inv_name) + local inv = minetest.get_meta(pos):get_inventory() + if not inv then return 0 end + return inv:get_size(inv_name) +end + +node_io.get_inventory_name = function(pos, inv_name, index) + local inv = minetest.get_meta(pos):get_inventory() + if not inv or index < 1 or index > inv:get_size(inv_name) then return nil end + return inv:get_stack(inv_name, index):get_name() +end + +node_io.put_item_in_inventory = function(pos, node, inv_name, putter, itemstack) + local inv = minetest.get_meta(pos):get_inventory() + if not inv or itemstack:is_empty() then return itemstack end + + local leftovers = inv:add_item(inv_name, itemstack) + + local ndef = minetest.registered_nodes[node.name] + if ndef.on_metadata_inventory_put and putter then + ndef.on_metadata_inventory_put(pos, inv_name, 0, itemstack, putter) + -- TODO: 0 is index in inv_name + end + + if leftovers then return leftovers end + itemstack:clear() + return itemstack +end + +node_io.take_item_from_inventory = function(pos, node, inv_name, taker, want_item, want_count) + local inv = minetest.get_meta(pos):get_inventory() + if not inv or inv:is_empty(inv_name) then return nil end + + for i = 1, inv:get_size(inv_name) do + local stack = inv:get_stack(inv_name, i) + local stack_item = stack:get_name() + if stack_item ~= "" and (want_item == nil or stack_item == want_item) then + if stack:get_count() > want_count then + -- stack is larger than wanted + local result_stack = stack:take_item(want_count) + inv:set_stack(inv_name, i, stack) + + local ndef = minetest.registered_nodes[node.name] + if ndef.on_metadata_inventory_take and putter then + ndef.on_metadata_inventory_take(pos, inv_name, i, stack, putter) + end + + return result_stack + else + inv:remove_item(inv_name, stack) + + local ndef = minetest.registered_nodes[node.name] + if ndef.on_metadata_inventory_take and taker then + ndef.on_metadata_inventory_take(pos, inv_name, i, stack, putter) + end + + return stack + end + end + end +end + +node_io.init_main_inventory = function(node_name, allow_take) + local def = {} + + def.node_io_can_put_item = function(pos, node, side) return true end + def.node_io_room_for_item = function(pos, node, side, itemstack) + local inv = minetest.get_meta(pos):get_inventory() + if not inv then return false end + return inv:room_for_item("main", itemstack) + end + def.node_io_put_item = function(pos, node, side, putter, itemstack) + return node_io.put_item_in_inventory(pos, node, "main", putter, itemstack) + end + + if allow_take then + def.node_io_can_take_item = function(pos, node, side) return true end + def.node_io_get_item_size = function(pos, node, side) + return node_io.get_inventory_size(pos, "main") + end + def.node_io_get_item_name = function(pos, node, side, index) + return node_io.get_inventory_name(pos, "main", index) + end + def.node_io_take_item = function(pos, node, side, taker, want_item, want_count) + return node_io.take_item_from_inventory(pos, node, "main", taker, want_item, want_count) + end + end + + minetest.override_item(node_name, def) +end + + + +dofile(MP.."default_support.lua") + +print("[MOD] Node IO loaded") diff --git a/patches/hopper-tenplus1.patch b/patches/hopper-tenplus1.patch new file mode 100644 index 0000000..7ada5ce --- /dev/null +++ b/patches/hopper-tenplus1.patch @@ -0,0 +1,262 @@ +* implement node_io API for https://notabug.org/TenPlus1/hopper mod +* void hopper can target any side of the node +* containers support is commented out but should be restored for compatibility with mods the depend on it + + + +diff --git a/depends.txt b/depends.txt +index 53a9e75..d2b2b18 100644 +--- a/depends.txt ++++ b/depends.txt +@@ -1,3 +1,4 @@ + default + intllib? + lucky_block? ++node_io +diff --git a/init.lua b/init.lua +index 062c739..3fadaee 100644 +--- a/init.lua ++++ b/init.lua +@@ -24,6 +24,7 @@ function check_creative(name) + end + + ++--[[ + -- default containers + local containers = { + +@@ -94,6 +95,7 @@ if minetest.get_modpath("wine") then + {"void", "wine:wine_barrel", "src"}, + }) + end ++]] + + + -- formspec +@@ -225,6 +227,7 @@ minetest.register_node("hopper:hopper", { + on_rotate = screwdriver.disallow, + on_blast = function() end, + }) ++node_io.init_main_inventory("hopper:hopper", true) + + + -- side hopper +@@ -297,6 +300,7 @@ minetest.register_node("hopper:hopper_side", { + on_rotate = screwdriver.rotate_simple, + on_blast = function() end, + }) ++node_io.init_main_inventory("hopper:hopper_side", true) + + + local player_void = {} +@@ -330,7 +334,8 @@ minetest.register_node("hopper:hopper_void", { + + local pos = pointed_thing.under + local name = player:get_player_name() +- local node = minetest.get_node(pos).name ++-- local node = minetest.get_node(pos).name ++ local node = minetest.get_node(pos) + local ok + + if minetest.is_protected(pos, name) then +@@ -338,6 +343,7 @@ minetest.register_node("hopper:hopper_void", { + return itemstack + end + ++--[[ + for _ = 1, #containers do + if node == containers[_][2] then + ok = true +@@ -345,9 +351,12 @@ minetest.register_node("hopper:hopper_void", { + end + + if ok then ++]] ++ if node_io.can_put_item(pos, node) then ++ local side = node_io.get_pointed_side(player, pointed_thing) + minetest.chat_send_player(name, S("Output container set" +- .. " " .. minetest.pos_to_string(pos))) +- player_void[name] = pos ++ .. " " .. minetest.pos_to_string(pos) .. " " .. side)) ++ player_void[name] = {pos = pos, side = side} + else + minetest.chat_send_player(name, S("Not a registered container!")) + player_void[name] = nil +@@ -381,7 +390,8 @@ minetest.register_node("hopper:hopper_void", { + inv:set_size("main", 4*4) + + meta:set_string("owner", name) +- meta:set_string("void", minetest.pos_to_string(player_void[name])) ++ meta:set_string("void", minetest.pos_to_string(player_void[name].pos)) ++ meta:set_string("void_side", player_void[name].side) + + return itemstack + end, +@@ -425,8 +435,10 @@ minetest.register_node("hopper:hopper_void", { + on_rotate = screwdriver.disallow, + on_blast = function() end, + }) ++node_io.init_main_inventory("hopper:hopper_void", true) + + ++--[[ + -- transfer function + local transfer = function(src, srcpos, dst, dstpos) + +@@ -467,6 +479,7 @@ local transfer = function(src, srcpos, dst, dstpos) + end + end + end ++]] + + + -- hopper workings +@@ -502,8 +515,7 @@ minetest.register_abm({ + end + end + +- +- local front ++ local put_pos, put_side + + -- if side hopper check which way spout is facing + if node.name == "hopper:hopper_side" then +@@ -511,19 +523,20 @@ minetest.register_abm({ + local face = minetest.get_node(pos).param2 + + if face == 0 then +- front = {x = pos.x - 1, y = pos.y, z = pos.z} ++ put_pos = {x = pos.x - 1, y = pos.y, z = pos.z} + + elseif face == 1 then +- front = {x = pos.x, y = pos.y, z = pos.z + 1} ++ put_pos = {x = pos.x, y = pos.y, z = pos.z + 1} + + elseif face == 2 then +- front = {x = pos.x + 1, y = pos.y, z = pos.z} ++ put_pos = {x = pos.x + 1, y = pos.y, z = pos.z} + + elseif face == 3 then +- front = {x = pos.x, y = pos.y, z = pos.z - 1} ++ put_pos = {x = pos.x, y = pos.y, z = pos.z - 1} + else + return + end ++ put_side = node_io.get_target_side(pos, put_pos) + + elseif node.name == "hopper:hopper_void" then + +@@ -531,61 +544,89 @@ minetest.register_abm({ + + if not meta then return end + +- front = minetest.string_to_pos(meta:get_string("void")) ++ put_pos = minetest.string_to_pos(meta:get_string("void")) ++ put_side = meta:get_string("void_side") or "U" + + elseif node.name == "hopper:hopper" then + -- otherwise normal hopper, output downwards +- front = {x = pos.x, y = pos.y - 1, z = pos.z} ++ put_pos = {x = pos.x, y = pos.y - 1, z = pos.z} ++ put_side = node_io.get_target_side(pos, put_pos) ++ + else + return + end ++ -- get node at other end of spout ++ local put_node = minetest.get_node(put_pos) ++ if node_io.can_put_item(put_pos, put_node, put_side) then ++ for i = 1, inv:get_size("main") do ++ local stack = inv:get_stack("main", i) ++ local item = stack:get_name() ++ if item ~= "" and node_io.room_for_item(put_pos, put_node, put_side, node_io.make_itemstack(stack, 1)) then ++ node_io.put_item(put_pos, put_node, put_side, nil, stack:take_item(1)) ++ inv:set_stack("main", i, stack) ++ minetest.get_node_timer(put_pos):start(0.5) ++ break ++ end ++ end ++ end + + -- get node above hopper +- local top = minetest.get_node({x = pos.x, y = pos.y + 1, z = pos.z}).name +- +- -- get node at other end of spout +- local out = minetest.get_node(front).name +- +- local where, nod, inv, def ++ local take_pos = {x = pos.x, y = pos.y + 1, z = pos.z} ++ local take_node = minetest.get_node(take_pos) ++ if node_io.can_take_item(take_pos, take_node, "D") then ++ for i = 1, node_io.get_item_size(take_pos, take_node, "D") do ++ local item = node_io.get_item_name(take_pos, take_node, "D", i) ++ if inv:room_for_item("main", ItemStack(item.." 1")) then ++ local itemstack = node_io.take_item(take_pos, take_node, "D", nil, item, 1) ++ if itemstack then ++ inv:add_item("main", itemstack) ++ minetest.get_node_timer(take_pos):start(0.5) ++ break ++ end ++ end ++ end ++ end ++--[[ ++ local target_side, target_node_name, target_inv_name + + -- do for loop here for api check + for n = 1, #containers do + +- where = containers[n][1] +- nod = containers[n][2] +- inv = containers[n][3] ++ target_side = containers[n][1] ++ target_node_name = containers[n][2] ++ target_inv_name = containers[n][3] + + -- from top node into hopper below +- if where == "top" and top == nod ++ if target_side == "top" and take_node_name == target_node_name + and (node.name == "hopper:hopper" + or node.name == "hopper:hopper_side" + or node.name == "hopper:hopper_void") then + +- transfer(inv, {x = pos.x, y = pos.y + 1, z = pos.z}, "main", pos) +- minetest.get_node_timer( +- {x = pos.x, y = pos.y + 1, z = pos.z}):start(0.5) ++ transfer(target_inv_name, take_pos, "main", pos) ++ minetest.get_node_timer(take_pos):start(0.5) + + -- from top hopper into node below +- elseif where == "bottom" and out == nod ++ elseif target_side == "bottom" and put_node_name == target_node_name + and node.name == "hopper:hopper" then + +- transfer("main", pos, inv, front) +- minetest.get_node_timer(front):start(0.5) ++ transfer("main", pos, target_inv_name, put_pos) ++ minetest.get_node_timer(put_pos):start(0.5) + + -- side hopper into container beside +- elseif where == "side" and out == nod ++ elseif target_side == "side" and put_node_name == target_node_name + and node.name == "hopper:hopper_side" then + +- transfer("main", pos, inv, front) +- minetest.get_node_timer(front):start(0.5) ++ transfer("main", pos, target_inv_name, put_pos) ++ minetest.get_node_timer(put_pos):start(0.5) + + -- void hopper to destination container +- elseif where == "void" and out == nod ++ elseif target_side == "void" and put_node_name == target_node_name + and node.name == "hopper:hopper_void" then +- transfer("main", pos, inv, front) +- minetest.get_node_timer(front):start(0.5) ++ transfer("main", pos, target_inv_name, put_pos) ++ minetest.get_node_timer(put_pos):start(0.5) + end + end ++]] + end, + }) +