Minetest-Tubelib/init.lua

177 lines
4.6 KiB
Lua

--[[
Tube Library
============
Copyright (C) 2017 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
History:
see init.lua
]]--
tubelib = {
NodeTypes = {},
}
tubelib.debug = true
tubelib.knownNodes = {
["tubelib:tube1"] = true,
["tubelib:tube2"] = true,
["tubelib:tube3"] = true,
["tubelib:tube4"] = true,
["tubelib:tube5"] = true,
["tubelib:tube6"] = true,
["default:chest_locked"] = true,
["default:chest"] = true,
}
tubelib.legacyNodes = {
["default:chest_locked"] = true,
["default:chest"] = true,
}
dofile(minetest.get_modpath("tubelib") .. "/tubes.lua")
dofile(minetest.get_modpath("tubelib") .. "/command.lua")
dofile(minetest.get_modpath("tubelib") .. "/button.lua")
dofile(minetest.get_modpath("tubelib") .. "/lamp.lua")
function tubelib.get_key_str(pos)
pos = minetest.pos_to_string(pos)
return '"'..string.sub(pos, 2, -2)..'"'
end
-- determine neighbor position based on current pos, node facedir
-- and the side F(orward), R(ight), B(ackward), L(eft), D(own), U(p)
function tubelib.get_pos(pos, facedir, side)
local offs = {F=0, R=1, B=2, L=3, D=4, U=5}
local _pos = table.copy(pos)
facedir = (facedir + offs[side]) % 4
local dir = core.facedir_to_dir(facedir)
return vector.add(_pos, dir)
end
-- determine position like "tubelib.get_pos", but
-- consider tubes in addition
function tubelib.get_pos_ext(pos, facedir, side)
local dst_pos = tubelib.get_pos(pos, facedir, side)
local node = minetest.get_node(dst_pos)
if node and string.find(node.name, "tubelib:tube") then
dst_pos = minetest.string_to_pos(minetest.get_meta(dst_pos):get_string("dest_pos"))
node = minetest.get_node(dst_pos)
end
return node, dst_pos
end
-- 6D variant of the facedir to dir conversion
function tubelib.facedir_to_dir(facedir)
local table = {[0] =
{x=0, y=0, z=1},
{x=1, y=0, z=0},
{x=0, y=0, z=-1},
{x=-1, y=0, z=0},
{x=0, y=-1, z=0},
{x=0, y=1, z=0},
}
return table[facedir]
end
local function get_facedir(placer)
if placer then
return minetest.dir_to_facedir(placer:get_look_dir(), false)
end
return 0
end
local function legacy_node(node)
if node and tubelib.legacyNodes[node.name] then
return true
end
return false
end
-------------------------------------------------------------------
-- Registration functions
-------------------------------------------------------------------
-- Register node name for tube push/pull calls
-- Call this function only at load time!
function tubelib.register_node_name(name)
tubelib.knownNodes[name] = true
end
-------------------------------------------------------------------
-- Client side API functions
-------------------------------------------------------------------
function tubelib.pull_items(pos, facedir, sides)
for _,side in ipairs(sides) do
local node, src_pos = tubelib.get_pos_ext(pos, facedir, side)
local key = tubelib.get_key_str(src_pos)
if tubelib.NodeTypes[node.name] and tubelib.NodeTypes[node.name].start_clbk then
return tubelib.NodeTypes[node.name].pull_clbk(src_pos)
elseif legacy_node(node) then
local meta = minetest.get_meta(src_pos)
local inv = meta:get_inventory()
return tubelib.get_item(inv, "main")
end
end
return nil
end
function tubelib.push_items(pos, facedir, sides, items)
for _,side in ipairs(sides) do
local node, dst_pos = tubelib.get_pos_ext(pos, facedir, side)
local key = tubelib.get_key_str(dst_pos)
if tubelib.NodeTypes[node.name] and tubelib.NodeTypes[node.name].start_clbk then
return tubelib.NodeTypes[node.name].push_clbk(dst_pos, items)
elseif legacy_node(node) then
local meta = minetest.get_meta(dst_pos)
local inv = meta:get_inventory()
return tubelib.put_item(inv, "main", items)
elseif node and node.name == "air" then
minetest.add_item(dst_pos, items)
return true
end
end
return false
end
-------------------------------------------------------------------
-- Server side helper functions
-------------------------------------------------------------------
function tubelib.get_item(inv, listname)
if inv:is_empty(listname) then
--print("nil")
return nil
end
local stack, slot
local size = inv:get_size(listname)
local offs = math.random(size)
--print("tubelib.get_item", offs)
for idx = 1, size do
local slot = ((idx + offs) % size) + 1
local items = inv:get_stack(listname, slot)
if items:get_count() > 0 then
local taken = items:take_item(1)
inv:set_stack(listname, slot, items)
return taken
end
end
return nil
end
function tubelib.put_item(inv, listname, items)
if inv:room_for_item(listname, items) then
inv:add_item(listname, items)
return true
end
return false
end