2018-10-05 21:55:40 +02:00
|
|
|
--[[
|
|
|
|
|
|
|
|
Tube Library 2
|
|
|
|
==============
|
|
|
|
|
|
|
|
Copyright (C) 2018 Joachim Stolberg
|
|
|
|
|
|
|
|
LGPLv2.1+
|
|
|
|
See LICENSE.txt for more information
|
|
|
|
|
|
|
|
internal.lua
|
|
|
|
|
|
|
|
]]--
|
|
|
|
|
|
|
|
-- for lazy programmers
|
2018-10-06 21:46:38 +02:00
|
|
|
local S = minetest.pos_to_string
|
|
|
|
local P = minetest.string_to_pos
|
2018-10-05 21:55:40 +02:00
|
|
|
local M = minetest.get_meta
|
|
|
|
|
|
|
|
|
|
|
|
--
|
|
|
|
-- Tubelib2 specific 6D directions (1 = North, 2 = East, 3 = South, 4 = West, 5 = Down, 6 = Up)
|
|
|
|
--
|
|
|
|
-- All 6D dirs are the view from the node to the outer side
|
|
|
|
-- Tubes are based on two node types, "angled" and "straight" tubes.
|
|
|
|
--
|
|
|
|
-- +-------+
|
|
|
|
-- / /| +-------+
|
|
|
|
-- +-------+ | / /|
|
|
|
|
-- | | | / / |
|
|
|
|
-- | | | +-------+ |
|
|
|
|
-- | | | | | |
|
|
|
|
-- | | | | |/ |
|
|
|
|
-- | | + +-------+| +
|
|
|
|
-- | |/ | |/
|
|
|
|
-- +-------+ +------+
|
|
|
|
--
|
|
|
|
-- All other nodes are build by means of axis/rotation variants based on param2
|
|
|
|
-- (paramtype2 == "facedir").
|
2018-10-06 13:29:47 +02:00
|
|
|
--
|
|
|
|
-- The 3 free MSB bits of param2 of tube nodes are used to store the number of connections (0..2).
|
|
|
|
--
|
|
|
|
-- The data of the peer head tube are stored as meta data: "peer_pos" and "peer_dir"
|
2018-10-05 21:55:40 +02:00
|
|
|
|
|
|
|
|
2018-10-14 21:28:31 +02:00
|
|
|
local Turn180Deg = {[0]=0,3,4,1,2,6,5}
|
2018-10-20 19:19:44 +02:00
|
|
|
tubelib2.Turn180Deg = Turn180Deg
|
2018-10-05 21:55:40 +02:00
|
|
|
|
|
|
|
-- To calculate param2 based on dir6d information
|
|
|
|
local DirToParam2 = {
|
|
|
|
-- dir1 / dir2 ==> param2 / type (Angled/Straight)
|
|
|
|
[12] = {11, "A"},
|
|
|
|
[13] = {12, "S"},
|
|
|
|
[14] = {14, "A"},
|
|
|
|
[15] = { 8, "A"},
|
|
|
|
[16] = {10, "A"},
|
|
|
|
[23] = { 7, "A"},
|
|
|
|
[24] = {21, "S"},
|
|
|
|
[25] = { 3, "A"},
|
|
|
|
[26] = {19, "A"},
|
|
|
|
[34] = { 5, "A"},
|
|
|
|
[35] = { 0, "A"},
|
|
|
|
[36] = {20, "A"},
|
|
|
|
[45] = {15, "A"},
|
|
|
|
[46] = {13, "A"},
|
|
|
|
[56] = { 4, "S"},
|
|
|
|
}
|
|
|
|
|
|
|
|
-- To retrieve dir6d values from the nodes param2
|
|
|
|
local Param2ToDir = {}
|
|
|
|
for k,item in pairs(DirToParam2) do
|
|
|
|
Param2ToDir[item[1]] = k
|
|
|
|
end
|
|
|
|
|
|
|
|
-- For neighbour position calculation
|
2018-10-14 21:28:31 +02:00
|
|
|
local Dir6dToVector = {[0] =
|
|
|
|
{x=0, y=0, z=0},
|
2018-10-05 21:55:40 +02:00
|
|
|
{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},
|
|
|
|
}
|
|
|
|
|
2018-10-14 21:28:31 +02:00
|
|
|
tubelib2.Dir6dToVector = Dir6dToVector
|
|
|
|
|
2018-10-05 21:55:40 +02:00
|
|
|
local VectorToDir6d = {
|
|
|
|
[{x=0, y=0, z=1}] = 1,
|
|
|
|
[{x=1, y=0, z=0}] = 2,
|
|
|
|
[{x=0, y=0, z=-1}] = 3,
|
|
|
|
[{x=-1, y=0, z=0}] = 4,
|
|
|
|
[{x=0, y=-1, z=0}] = 5,
|
|
|
|
[{x=0, y=1, z=0}] = 6,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
--
|
|
|
|
-- Local Functions
|
|
|
|
--
|
|
|
|
|
|
|
|
local function Tbl(list)
|
|
|
|
local tbl = {}
|
|
|
|
for _,item in ipairs(list) do
|
|
|
|
tbl[item] = true
|
|
|
|
end
|
|
|
|
return tbl
|
|
|
|
end
|
|
|
|
|
2018-10-06 13:29:47 +02:00
|
|
|
-- Return val in the range of min and max
|
2018-10-05 21:55:40 +02:00
|
|
|
local function range(val, min, max)
|
|
|
|
if val > max then return max end
|
|
|
|
if val < min then return min end
|
|
|
|
return val
|
|
|
|
end
|
|
|
|
|
|
|
|
local function get_node_lvm(pos)
|
|
|
|
local node = minetest.get_node_or_nil(pos)
|
|
|
|
if node then
|
|
|
|
return node
|
|
|
|
end
|
|
|
|
local vm = minetest.get_voxel_manip()
|
|
|
|
local MinEdge, MaxEdge = vm:read_from_map(pos, pos)
|
|
|
|
local data = vm:get_data()
|
|
|
|
local param2_data = vm:get_param2_data()
|
|
|
|
local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
|
|
|
|
local idx = area:index(pos.x, pos.y, pos.z)
|
|
|
|
node = {
|
|
|
|
name = minetest.get_name_from_content_id(data[idx]),
|
|
|
|
param2 = param2_data[idx]
|
|
|
|
}
|
|
|
|
return node
|
|
|
|
end
|
|
|
|
|
2018-10-06 13:29:47 +02:00
|
|
|
|
2018-10-05 21:55:40 +02:00
|
|
|
--
|
|
|
|
-- Tubelib2 Methods
|
|
|
|
--
|
|
|
|
|
|
|
|
local Tube = tubelib2.Tube
|
|
|
|
|
2018-10-06 13:29:47 +02:00
|
|
|
-- Return param2 and tube type ("A"/"S")
|
2018-10-05 21:55:40 +02:00
|
|
|
function Tube:encode_param2(dir1, dir2, num_conn)
|
|
|
|
if dir1 > dir2 then
|
|
|
|
dir1, dir2 = dir2, dir1
|
|
|
|
end
|
|
|
|
local param2, _type = unpack(DirToParam2[dir1 * 10 + dir2] or {0, "S"})
|
|
|
|
return (num_conn * 32) + param2, _type
|
|
|
|
end
|
|
|
|
|
2018-10-06 13:29:47 +02:00
|
|
|
-- Return dir1, dir2, num_conn
|
2018-10-05 21:55:40 +02:00
|
|
|
function Tube:decode_param2(param2)
|
|
|
|
local val = Param2ToDir[param2 % 32]
|
|
|
|
if val then
|
|
|
|
local dir1, dir2 = math.floor(val / 10), val % 10
|
|
|
|
local num_conn = math.floor(param2 / 32)
|
|
|
|
return dir1, dir2, num_conn
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-14 21:28:31 +02:00
|
|
|
-- Return node next to pos in direction 'dir'
|
|
|
|
function Tube:get_next_node(pos, dir)
|
|
|
|
local npos = vector.add(pos, Dir6dToVector[dir or 0])
|
|
|
|
return npos, get_node_lvm(npos)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Check if node has a connection on the given dir
|
|
|
|
function Tube:connected(pos, dir)
|
|
|
|
local npos = vector.add(pos, Dir6dToVector[dir or 0])
|
|
|
|
local node = get_node_lvm(npos)
|
|
|
|
return self.primary_node_names[node.name] or self.secondary_node_names[node.name]
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Return the param2 stored tube dirs or 0,0
|
|
|
|
function Tube:get_tube_dirs(pos)
|
|
|
|
local node = get_node_lvm(pos)
|
|
|
|
if self.primary_node_names[node.name] then
|
|
|
|
return self:decode_param2(node.param2)
|
|
|
|
end
|
|
|
|
return 0,0
|
|
|
|
end
|
|
|
|
|
2018-10-06 13:29:47 +02:00
|
|
|
-- Return pos for a primary_node and true if num_conn < 2, else false
|
2018-10-05 21:55:40 +02:00
|
|
|
function Tube:friendly_primary_node(pos, dir)
|
2018-10-14 21:28:31 +02:00
|
|
|
local npos, node = self:get_next_node(pos, dir)
|
2018-10-05 21:55:40 +02:00
|
|
|
local _,_,num_conn = self:decode_param2(node.param2)
|
|
|
|
if self.primary_node_names[node.name] then
|
2018-10-06 13:29:47 +02:00
|
|
|
-- tube node with max one connection?
|
2018-10-15 20:05:41 +02:00
|
|
|
return npos, (num_conn or 2) < 2
|
2018-10-05 21:55:40 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-14 21:28:31 +02:00
|
|
|
-- Jump over the teleport nodes to the next tube node
|
|
|
|
function Tube:get_next_teleport_node(pos, dir)
|
|
|
|
local npos = vector.add(pos, Dir6dToVector[dir or 0])
|
|
|
|
local meta = M(npos)
|
|
|
|
local s = meta:get_string("tele_pos")
|
|
|
|
if s ~= "" then
|
|
|
|
local tele_pos = P(s)
|
|
|
|
local tube_dir = M(tele_pos):get_int("tube_dir")
|
|
|
|
if tube_dir ~= 0 then
|
|
|
|
return tele_pos, tube_dir
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-06 13:29:47 +02:00
|
|
|
-- Update meta data and number of connections in param2
|
|
|
|
-- pos1 is the node to be updated with the data pos2, dir2, num_tubes
|
|
|
|
function Tube:update_head_tube(pos1, pos2, dir2, num_tubes)
|
2018-10-14 21:28:31 +02:00
|
|
|
local node = get_node_lvm(pos1)
|
|
|
|
if self.primary_node_names[node.name] then
|
|
|
|
local d1, d2, num = self:decode_param2(node.param2)
|
2018-10-20 19:19:44 +02:00
|
|
|
if d1 and d2 then
|
|
|
|
num = (self:connected(pos1, d1) and 1 or 0) + (self:connected(pos1, d2) and 1 or 0)
|
|
|
|
node.param2 = self:encode_param2(d1, d2, num)
|
|
|
|
minetest.set_node(pos1, node)
|
|
|
|
if self.show_infotext then
|
|
|
|
M(pos1):set_string("infotext", S(pos2).." / "..num_tubes.." tubes")
|
|
|
|
end
|
|
|
|
M(pos1):set_string("peer_pos", S(pos2))
|
|
|
|
M(pos1):set_int("peer_dir", dir2)
|
2018-10-14 21:28:31 +02:00
|
|
|
end
|
2018-10-06 13:29:47 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Add meta data on both tube sides pos1 and pos2
|
|
|
|
-- dir1/dir2 are the tube output directions (inventory nodes)
|
|
|
|
function Tube:add_meta_data(pos1, pos2, dir1, dir2, num_tubes)
|
|
|
|
self:update_head_tube(pos1, pos2, dir2, num_tubes)
|
2018-10-20 19:19:44 +02:00
|
|
|
if not vector.equals(pos1, pos2) then
|
|
|
|
self:update_head_tube(pos2, pos1, dir1, num_tubes)
|
|
|
|
end
|
2018-10-06 13:29:47 +02:00
|
|
|
end
|
|
|
|
|
2018-10-14 21:28:31 +02:00
|
|
|
-- Delete meta data on both tube sides.
|
|
|
|
-- If dir is nil, pos is the position of one head node.
|
|
|
|
function Tube:del_meta_data(pos, dir)
|
|
|
|
local npos = vector.add(pos, Dir6dToVector[dir or 0])
|
|
|
|
local speer_pos = M(npos):get_string("peer_pos")
|
|
|
|
if speer_pos ~= "" then
|
|
|
|
local meta = M(pos)
|
|
|
|
if meta:get_string("peer_pos") ~= "" then
|
|
|
|
meta:from_table(nil)
|
|
|
|
end
|
|
|
|
meta = M(P(speer_pos))
|
|
|
|
if meta:get_string("peer_pos") ~= "" then
|
|
|
|
meta:from_table(nil)
|
|
|
|
end
|
|
|
|
return true
|
2018-10-06 13:29:47 +02:00
|
|
|
end
|
2018-10-14 21:28:31 +02:00
|
|
|
return false
|
2018-10-06 13:29:47 +02:00
|
|
|
end
|
|
|
|
|
2018-10-05 21:55:40 +02:00
|
|
|
function Tube:fdir(player)
|
|
|
|
local pitch = player:get_look_pitch()
|
2018-10-16 20:21:41 +02:00
|
|
|
if pitch > 1.1 and self.allowed_6d_dirs[6] then -- up?
|
2018-10-05 21:55:40 +02:00
|
|
|
return 6
|
2018-10-16 20:21:41 +02:00
|
|
|
elseif pitch < -1.1 and self.allowed_6d_dirs[5] then -- down?
|
2018-10-05 21:55:40 +02:00
|
|
|
return 5
|
2018-10-16 20:21:41 +02:00
|
|
|
elseif not self.allowed_6d_dirs[1] then
|
|
|
|
return 6
|
2018-10-05 21:55:40 +02:00
|
|
|
else
|
|
|
|
return minetest.dir_to_facedir(player:get_look_dir()) + 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function Tube:get_player_data(placer, pointed_thing)
|
|
|
|
if placer and pointed_thing and pointed_thing.type == "node" then
|
|
|
|
if placer:get_player_control().sneak then
|
2018-10-16 20:21:41 +02:00
|
|
|
return pointed_thing.under, self:fdir(placer)
|
2018-10-05 21:55:40 +02:00
|
|
|
else
|
2018-10-16 20:21:41 +02:00
|
|
|
return nil, self:fdir(placer)
|
2018-10-05 21:55:40 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
-- Check all 6 possible positions for known nodes considering preferred_pos
|
|
|
|
-- and the players fdir and return dir1, dir2 and the number of tubes to connect to (0..2).
|
|
|
|
function Tube:determine_tube_dirs(pos, preferred_pos, fdir)
|
|
|
|
local tbl = {}
|
|
|
|
local allowed = table.copy(self.allowed_6d_dirs)
|
|
|
|
|
|
|
|
-- Check for primary nodes (tubes)
|
|
|
|
for dir = 1,6 do
|
|
|
|
if allowed[dir] then
|
|
|
|
local npos, friendly = self:friendly_primary_node(pos, dir)
|
|
|
|
if npos then
|
|
|
|
if not friendly then
|
|
|
|
allowed[dir] = false
|
|
|
|
else
|
|
|
|
if preferred_pos and vector.equals(npos, preferred_pos) then
|
|
|
|
preferred_pos = nil
|
|
|
|
table.insert(tbl, 1, dir)
|
|
|
|
else
|
|
|
|
table.insert(tbl, dir)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- If no tube around the pointed pos and player prefers a position,
|
|
|
|
-- then the new tube shall point to the player.
|
|
|
|
if #tbl == 0 and preferred_pos and fdir and allowed[Turn180Deg[fdir]] then
|
|
|
|
tbl[1] = Turn180Deg[fdir]
|
|
|
|
-- Already 2 dirs found?
|
|
|
|
elseif #tbl >= 2 then
|
|
|
|
return tbl[1], tbl[2], 2
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Check for secondary nodes (chests and so on)
|
|
|
|
for dir = 1,6 do
|
|
|
|
if allowed[dir] then
|
|
|
|
local npos = self:secondary_node(pos, dir)
|
|
|
|
if npos then
|
|
|
|
if preferred_pos and vector.equals(npos, preferred_pos) then
|
|
|
|
preferred_pos = nil
|
|
|
|
table.insert(tbl, 2, dir)
|
|
|
|
else
|
|
|
|
table.insert(tbl, dir)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- player pointed to an unknown node to force the tube orientation?
|
|
|
|
if preferred_pos and fdir then
|
|
|
|
if tbl[1] == Turn180Deg[fdir] and allowed[fdir] then
|
|
|
|
tbl[2] = fdir
|
|
|
|
elseif allowed[Turn180Deg[fdir]] then
|
|
|
|
tbl[2] = Turn180Deg[fdir]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- dir1, dir2 still unknown?
|
|
|
|
if fdir then
|
|
|
|
if #tbl == 0 and allowed[Turn180Deg[fdir]] then
|
|
|
|
tbl[1] = Turn180Deg[fdir]
|
|
|
|
end
|
|
|
|
if #tbl == 1 and allowed[Turn180Deg[tbl[1]]] then
|
|
|
|
tbl[2] = Turn180Deg[tbl[1]]
|
|
|
|
elseif #tbl == 1 and tbl[1] ~= Turn180Deg[fdir] and allowed[Turn180Deg[fdir]] then
|
|
|
|
tbl[2] = Turn180Deg[fdir]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if #tbl >= 2 and tbl[1] ~= tbl[2] then
|
|
|
|
local num_tubes = (self:connected(pos, tbl[1]) and 1 or 0) +
|
|
|
|
(self:connected(pos, tbl[2]) and 1 or 0)
|
|
|
|
return tbl[1], tbl[2], math.min(2, num_tubes)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-06 13:29:47 +02:00
|
|
|
-- format and return given data as table
|
2018-10-05 21:55:40 +02:00
|
|
|
function Tube:tube_data_to_table(pos, dir1, dir2, num_tubes)
|
2018-10-15 20:05:41 +02:00
|
|
|
local param2, tube_type = self:encode_param2(dir1, dir2, num_tubes)
|
|
|
|
return pos, param2, tube_type, num_tubes
|
2018-10-05 21:55:40 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
|
2018-10-06 13:29:47 +02:00
|
|
|
-- Determine a tube side without connection, increment the number of connections
|
|
|
|
-- and return the new data to be able to update the node:
|
|
|
|
-- new_pos, dir1, dir2, num_connections (1, 2)
|
2018-10-05 21:55:40 +02:00
|
|
|
function Tube:add_tube_dir(pos, dir)
|
2018-10-14 21:28:31 +02:00
|
|
|
local npos, node = self:get_next_node(pos, dir)
|
2018-10-05 21:55:40 +02:00
|
|
|
if self.primary_node_names[node.name] then
|
|
|
|
local d1, d2, num = self:decode_param2(node.param2)
|
|
|
|
-- not already connected to the new tube?
|
|
|
|
dir = Turn180Deg[dir]
|
|
|
|
if d1 ~= dir and dir ~= d2 then
|
|
|
|
if num == 0 then
|
|
|
|
d1 = dir
|
|
|
|
elseif num == 1 then
|
|
|
|
-- determine, which of d1, d2 has already a connection
|
|
|
|
if self:connected(npos, d1) then
|
|
|
|
d2 = dir
|
|
|
|
else
|
|
|
|
d1 = dir
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return npos, d1, d2, math.min(num + 1, 2)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-06 13:29:47 +02:00
|
|
|
-- Decrement the number of tube connections
|
|
|
|
-- and return the new data to be able to update the node:
|
|
|
|
-- new_pos, dir1, dir2, num_connections (0, 1)
|
2018-10-05 21:55:40 +02:00
|
|
|
function Tube:del_tube_dir(pos, dir)
|
2018-10-14 21:28:31 +02:00
|
|
|
local npos, node = self:get_next_node(pos, dir)
|
2018-10-05 21:55:40 +02:00
|
|
|
if self.primary_node_names[node.name] then
|
|
|
|
local d1, d2, num = self:decode_param2(node.param2)
|
|
|
|
return npos, d1, d2, math.max(num - 1, 0)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-14 21:28:31 +02:00
|
|
|
-- Store the node data in out_tbl for later use
|
|
|
|
-- and return true/false
|
|
|
|
function Tube:is_tube_head(pos, dir, out_tbl)
|
|
|
|
out_tbl.pos, out_tbl.node = self:get_next_node(pos, dir)
|
|
|
|
if self.primary_node_names[out_tbl.node.name] then
|
|
|
|
local dir1, dir2, num_conn = self:decode_param2(out_tbl.node.param2)
|
|
|
|
if Turn180Deg[dir] == dir1 then
|
|
|
|
out_tbl.dir = dir2
|
|
|
|
else
|
|
|
|
out_tbl.dir = dir1
|
2018-10-06 21:46:38 +02:00
|
|
|
end
|
2018-10-14 21:28:31 +02:00
|
|
|
return true
|
2018-10-06 21:46:38 +02:00
|
|
|
end
|
2018-10-14 21:28:31 +02:00
|
|
|
return false
|
|
|
|
end
|
2018-10-05 21:55:40 +02:00
|
|
|
|
2018-10-06 13:29:47 +02:00
|
|
|
-- Go down the tube to the end position and
|
|
|
|
-- return pos, dir to the next node, and num tubes
|
2018-10-14 21:28:31 +02:00
|
|
|
function Tube:find_peer_tube_head(node_tbl)
|
2018-10-06 13:29:47 +02:00
|
|
|
local get_next_tube = function(self, pos, dir)
|
|
|
|
-- Return pos and dir to the next node of the tube node at pos/dir
|
2018-10-14 21:28:31 +02:00
|
|
|
local npos, node = self:get_next_node(pos, dir)
|
2018-10-06 13:29:47 +02:00
|
|
|
if self.primary_node_names[node.name] then
|
2018-10-06 21:46:38 +02:00
|
|
|
local dir1, dir2, num = self:decode_param2(node.param2)
|
2018-10-06 13:29:47 +02:00
|
|
|
if Turn180Deg[dir] == dir1 then
|
|
|
|
return npos, dir2
|
|
|
|
else
|
|
|
|
return npos, dir1
|
|
|
|
end
|
|
|
|
end
|
2018-10-06 21:46:38 +02:00
|
|
|
|
2018-10-14 21:28:31 +02:00
|
|
|
return self:get_next_teleport_node(npos)
|
2018-10-06 13:29:47 +02:00
|
|
|
end
|
|
|
|
|
2018-10-05 21:55:40 +02:00
|
|
|
local cnt = 0
|
2018-10-14 21:28:31 +02:00
|
|
|
local pos = node_tbl.pos
|
|
|
|
local dir = node_tbl.dir
|
2018-10-06 13:29:47 +02:00
|
|
|
|
2018-10-05 21:55:40 +02:00
|
|
|
while cnt <= self.max_tube_length do
|
2018-10-06 13:29:47 +02:00
|
|
|
local new_pos, new_dir = get_next_tube(self, pos, dir)
|
2018-10-05 21:55:40 +02:00
|
|
|
if not new_dir then break end
|
|
|
|
pos, dir = new_pos, new_dir
|
|
|
|
cnt = cnt + 1
|
|
|
|
end
|
2018-10-06 13:29:47 +02:00
|
|
|
return pos, dir, cnt
|
2018-10-05 21:55:40 +02:00
|
|
|
end
|
|
|
|
|
2018-10-06 13:29:47 +02:00
|
|
|
-- Set tube to a 2 connection node without meta data
|
|
|
|
function Tube:set_2_conn_tube(pos)
|
2018-10-14 21:28:31 +02:00
|
|
|
local npos, node = self:get_next_node(pos)
|
2018-10-05 21:55:40 +02:00
|
|
|
if self.primary_node_names[node.name] then
|
2018-10-06 13:29:47 +02:00
|
|
|
local dir1, dir2, _ = self:decode_param2(node.param2)
|
|
|
|
node.param2 = self:encode_param2(dir1, dir2, 2)
|
|
|
|
minetest.set_node(npos, node)
|
2018-10-05 21:55:40 +02:00
|
|
|
M(npos):from_table(nil)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-10-06 13:29:47 +02:00
|
|
|
-- Do a correction of param2 and delete meta data of all 2-conn-tubes,
|
|
|
|
-- update the meta data of the head tubes and
|
|
|
|
-- return head-pos and number of nodes
|
2018-10-05 21:55:40 +02:00
|
|
|
function Tube:repair_tube_line(pos, dir)
|
2018-10-06 13:29:47 +02:00
|
|
|
local repair_next_tube = function(self, pos, dir)
|
2018-10-14 21:28:31 +02:00
|
|
|
local npos, node = self:get_next_node(pos, dir)
|
2018-10-06 13:29:47 +02:00
|
|
|
if self.primary_node_names[node.name] then
|
|
|
|
local dir1, dir2, num = self:decode_param2(node.param2)
|
|
|
|
if num ~= 2 then
|
|
|
|
node.param2 = self:encode_param2(dir1, dir2, 2)
|
|
|
|
minetest.set_node(npos, node)
|
|
|
|
end
|
|
|
|
M(npos):from_table(nil)
|
|
|
|
if Turn180Deg[dir] == dir1 then
|
|
|
|
return npos, dir2
|
|
|
|
else
|
|
|
|
return npos, dir1
|
|
|
|
end
|
|
|
|
end
|
2018-10-14 21:28:31 +02:00
|
|
|
return self:get_next_teleport_node(npos)
|
2018-10-06 13:29:47 +02:00
|
|
|
end
|
|
|
|
|
2018-10-05 21:55:40 +02:00
|
|
|
local cnt = 0
|
|
|
|
if not dir then return pos, cnt end
|
|
|
|
while cnt <= self.max_tube_length do
|
2018-10-06 13:29:47 +02:00
|
|
|
local new_pos, new_dir = repair_next_tube(self, pos, dir)
|
2018-10-05 21:55:40 +02:00
|
|
|
if not new_dir then break end
|
|
|
|
pos, dir = new_pos, new_dir
|
|
|
|
cnt = cnt + 1
|
|
|
|
end
|
2018-10-06 13:29:47 +02:00
|
|
|
return pos, dir, cnt
|
2018-10-05 21:55:40 +02:00
|
|
|
end
|
|
|
|
|
2018-10-06 21:46:38 +02:00
|
|
|
-- Pairing helper function
|
|
|
|
function Tube:store_teleport_data(pos, peer_pos)
|
|
|
|
local meta = M(pos)
|
|
|
|
meta:set_string("tele_pos", S(peer_pos))
|
|
|
|
meta:set_string("channel", nil)
|
|
|
|
meta:set_string("formspec", nil)
|
|
|
|
meta:set_string("infotext", "Connected with "..S(peer_pos))
|
2018-10-14 21:28:31 +02:00
|
|
|
return meta:get_int("tube_dir")
|
|
|
|
end
|
|
|
|
|
|
|
|
function Tube:get_peer_tube_head(node_tbl)
|
|
|
|
-- if meta data is available, return peer_pos, peer_pos
|
|
|
|
local meta = M(node_tbl.pos)
|
|
|
|
local spos = meta:get_string("peer_pos")
|
|
|
|
if spos ~= "" then
|
|
|
|
return P(spos), meta:get_int("peer_dir")
|
|
|
|
end
|
|
|
|
-- repair tube line
|
|
|
|
local pos2, dir2, cnt = self:find_peer_tube_head(node_tbl)
|
2018-10-20 19:19:44 +02:00
|
|
|
if pos2 then
|
|
|
|
self:add_meta_data(node_tbl.pos, pos2, Turn180Deg[node_tbl.dir], dir2, cnt)
|
|
|
|
return pos2, dir2
|
|
|
|
end
|
2018-10-06 21:46:38 +02:00
|
|
|
end
|
2018-10-14 21:28:31 +02:00
|
|
|
|
2018-10-20 19:19:44 +02:00
|
|
|
-- pos is the position of the removed node
|
|
|
|
-- dir1, dir2 are the neighbor sides to be checked for meta data
|
|
|
|
-- oldmetadata is also used to check for meta data
|
|
|
|
-- If meta data is found (peer_pos), it is used to determine the tube head.
|
2018-10-14 21:28:31 +02:00
|
|
|
function Tube:delete_tube_meta_data(pos, dir1, dir2, oldmetadata)
|
|
|
|
-- tube with two connections?
|
|
|
|
if dir2 then
|
|
|
|
local res
|
|
|
|
if dir1 then
|
|
|
|
local npos = self:find_peer_tube_head({pos=pos, dir=dir1})
|
|
|
|
if not self:del_meta_data(npos) then
|
|
|
|
-- try the other direction
|
|
|
|
npos = self:find_peer_tube_head({pos=pos, dir=dir2})
|
|
|
|
self:del_meta_data(npos)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
-- removed node with meta data?
|
|
|
|
elseif oldmetadata and oldmetadata.fields and oldmetadata.fields.peer_pos then
|
|
|
|
local npos = P(oldmetadata.fields.peer_pos)
|
|
|
|
self:del_meta_data(npos)
|
|
|
|
elseif dir1 then
|
|
|
|
local npos = vector.add(pos, Dir6dToVector[dir1])
|
|
|
|
-- node with peer meta data?
|
|
|
|
if not self:del_meta_data(npos) then
|
|
|
|
-- try teleport node
|
|
|
|
local tele_pos, tube_dir = self:get_next_teleport_node(npos)
|
|
|
|
if tele_pos then
|
|
|
|
local npos = self:find_peer_tube_head({pos=tele_pos, dir=tube_dir})
|
|
|
|
self:del_meta_data(npos)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|