83 lines
2.2 KiB
Lua
83 lines
2.2 KiB
Lua
local modname = minetest.get_current_modname()
|
|
|
|
local api = load_file("api")
|
|
|
|
local function get_meta_table (pos)
|
|
return minetest.get_meta(pos):to_table()
|
|
end
|
|
|
|
local function set_meta (pos, meta_table)
|
|
local meta = minetest.get_meta(pos)
|
|
for key, value in pairs(meta_table) do
|
|
local fn = nil
|
|
if type(value) == "string" then fn = "set_string" end
|
|
if type(value) == "int" then fn = "set_int" end
|
|
if type(value) == "float" then fn = "set_float" end
|
|
if fn then
|
|
meta[fn](key, value)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function attempt_input (pos)
|
|
-- TODO: add max limit for amount of nodes inside funnel inventory.
|
|
local above = pos + blockgame.vector.dirs.up
|
|
if minetest.get_node(above).name == "air" then return false end
|
|
|
|
local node = minetest.get_node(above)
|
|
local meta = get_meta_table(above)
|
|
local value = {
|
|
node = node,
|
|
meta = meta,
|
|
}
|
|
|
|
local success = api.push(pos, value)
|
|
if not success then return false end
|
|
minetest.remove_node(above)
|
|
return true
|
|
end
|
|
|
|
local function attempt_output (pos)
|
|
local below = pos + blockgame.vector.dirs.down
|
|
if minetest.get_node(below).name ~= "air" then return false end
|
|
|
|
local value = api.pop(pos)
|
|
if not value then return nil end
|
|
|
|
local node = value.node
|
|
local meta = value.meta
|
|
minetest.set_node(below, node)
|
|
set_meta(below, meta)
|
|
|
|
return true
|
|
end
|
|
|
|
blockgame.register_abm({
|
|
label = "funnel nodes",
|
|
nodenames = {modname .. ":funnel"},
|
|
interval = 1,
|
|
chance = 1,
|
|
catch_up = false,
|
|
action = function (pos)
|
|
-- NOTE: metadata storage might not work, and funnels might not be able to pick up other funnels successfully.
|
|
attempt_input(pos)
|
|
attempt_output(pos)
|
|
end,
|
|
})
|
|
|
|
|
|
|
|
-- NOTE: the documentation says `register_on_placenode` is "not recommended"; what else could be used for this?
|
|
minetest.register_on_placenode(function (pos)
|
|
local below = pos + blockgame.vector.dirs.down
|
|
if minetest.get_node(below).name ~= modname .. ":funnel" then return end
|
|
attempt_input(below)
|
|
end)
|
|
|
|
-- NOTE: the documentation says `register_on_dignode` is "not recommended"; what else could be used for this?
|
|
minetest.register_on_dignode(function (pos)
|
|
local above = pos + blockgame.vector.dirs.up
|
|
if minetest.get_node(above).name ~= modname .. ":funnel" then return end
|
|
attempt_output(above)
|
|
end)
|