177 lines
4.6 KiB
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
|