This commit is contained in:
Joachim Stolberg 2018-11-03 19:08:31 +01:00
parent ce3a3330bc
commit 1e248a4646
3 changed files with 95 additions and 60 deletions

@ -25,30 +25,39 @@ function Tube:on_convert_tube(convert_tube_clbk)
self.convert_tube_clbk = convert_tube_clbk self.convert_tube_clbk = convert_tube_clbk
end end
function Tube:convert_to_tubelib2(pos1, dir1) -- Register legacy tube nodes.
local pos2, dir2, cnt = self:convert_tube_line(pos1, dir1) function Tube:add_legacy_node_names(names)
self:add_meta_data(pos1, pos2, dir1, dir2, cnt) for _,name in ipairs(names) do
self.legacy_node_names[name] = true
end
end end
function Tube:convert_tube_line(pos, dir) function Tube:convert_tube_line(pos, dir)
local convert_next_tube = function(self, pos, dir) local convert_next_tube = function(self, pos, dir)
local npos, node = self:get_next_node(pos, dir) local npos, node = self:get_next_node(pos, dir)
local dir1, dir2, num = self.convert_tube_clbk(npos, node.name, node.param2) if self.legacy_node_names[node.name] then
if dir1 then local dir1, dir2, num
self.clbk_after_place_tube(self:tube_data_to_table(npos, dir1, if self.convert_tube_clbk then
dir2 or tubelib2.Turn180Deg[dir1], num)) dir1, dir2, num = self.convert_tube_clbk(npos, node.name, node.param2)
if tubelib2.Turn180Deg[dir] == dir1 then
return npos, dir2
else else
return npos, dir1 dir1, dir2, num = self:determine_dir1_dir2_and_num_conn(npos)
end
if dir1 then
self.clbk_after_place_tube(self:tube_data_to_table(npos, dir1,
dir2 or tubelib2.Turn180Deg[dir1], num))
if tubelib2.Turn180Deg[dir] == dir1 then
return npos, dir2
else
return npos, dir1
end
end end
end end
end end
local cnt = 0 local cnt = 0
if not dir then return pos, cnt end if not dir then return pos, cnt end
while cnt <= self.max_tube_length do while cnt <= 100000 do
local new_pos, new_dir = convert_next_tube(self, pos, dir) local new_pos, new_dir = convert_next_tube(self, pos, dir)
if not new_dir then break end if not new_dir then break end
pos, dir = new_pos, new_dir pos, dir = new_pos, new_dir

@ -114,6 +114,30 @@ end
local Tube = tubelib2.Tube local Tube = tubelib2.Tube
-- 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]
or self.legacy_node_names[node.name]
end
-- Determine dirs via surrounding nodes
function Tube:determine_dir1_dir2_and_num_conn(pos)
local dirs = {}
for dir = 1, 6 do
if self:connected(pos, dir) then
dirs[#dirs+1] = dir
end
end
if #dirs == 1 then
return dirs[1], nil, 1
elseif #dirs == 2 then
return dirs[1], dirs[2], 2
end
end
-- Return param2 and tube type ("A"/"S") -- Return param2 and tube type ("A"/"S")
function Tube:encode_param2(dir1, dir2, num_conn) function Tube:encode_param2(dir1, dir2, num_conn)
if dir1 > dir2 then if dir1 > dir2 then
@ -124,13 +148,16 @@ function Tube:encode_param2(dir1, dir2, num_conn)
end end
-- Return dir1, dir2, num_conn -- Return dir1, dir2, num_conn
function Tube:decode_param2(param2) function Tube:decode_param2(pos, param2)
local val = Param2ToDir[param2 % 32] local val = Param2ToDir[param2 % 32]
if val then if val then
local dir1, dir2 = math.floor(val / 10), val % 10 local dir1, dir2 = math.floor(val / 10), val % 10
local num_conn = math.floor(param2 / 32) local num_conn = math.floor(param2 / 32)
return dir1, dir2, num_conn return dir1, dir2, num_conn
end end
-- determine dirs via surrounding nodes
return self:determine_dir1_dir2_and_num_conn(pos)
end end
-- Return node next to pos in direction 'dir' -- Return node next to pos in direction 'dir'
@ -139,27 +166,20 @@ function Tube:get_next_node(pos, dir)
return npos, get_node_lvm(npos) return npos, get_node_lvm(npos)
end end
-- Check if node has a connection on the given dir -- Return the param2 stored tube dirs or 5,6
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) function Tube:get_tube_dirs(pos)
local node = get_node_lvm(pos) local node = get_node_lvm(pos)
if self.primary_node_names[node.name] then if self.primary_node_names[node.name] then
return self:decode_param2(node.param2) return self:decode_param2(pos, node.param2)
end end
return 0,0 return 5,6
end end
-- Return pos for a primary_node and true if num_conn < 2, else false -- Return pos for a primary_node and true if num_conn < 2, else false
function Tube:friendly_primary_node(pos, dir) function Tube:friendly_primary_node(pos, dir)
local npos, node = self:get_next_node(pos, dir) local npos, node = self:get_next_node(pos, dir)
local _,_,num_conn = self:decode_param2(node.param2)
if self.primary_node_names[node.name] then if self.primary_node_names[node.name] then
local _,_,num_conn = self:decode_param2(npos, node.param2)
-- tube node with max one connection? -- tube node with max one connection?
return npos, (num_conn or 2) < 2 return npos, (num_conn or 2) < 2
end end
@ -184,7 +204,7 @@ end
function Tube:update_head_tube(pos1, pos2, dir2, num_tubes) function Tube:update_head_tube(pos1, pos2, dir2, num_tubes)
local node = get_node_lvm(pos1) local node = get_node_lvm(pos1)
if self.primary_node_names[node.name] then if self.primary_node_names[node.name] then
local d1, d2, num = self:decode_param2(node.param2) local d1, d2, num = self:decode_param2(pos1, node.param2)
if d1 and d2 then if d1 and d2 then
num = (self:connected(pos1, d1) and 1 or 0) + (self:connected(pos1, d2) and 1 or 0) 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) node.param2 = self:encode_param2(d1, d2, num)
@ -340,8 +360,7 @@ end
function Tube:add_tube_dir(pos, dir) function Tube:add_tube_dir(pos, dir)
local npos, node = self:get_next_node(pos, dir) local npos, node = self:get_next_node(pos, dir)
if self.primary_node_names[node.name] then if self.primary_node_names[node.name] then
local d1, d2, num = self:decode_param2(node.param2) local d1, d2, num = self:decode_param2(npos, node.param2)
if not num then return end
-- not already connected to the new tube? -- not already connected to the new tube?
dir = Turn180Deg[dir] dir = Turn180Deg[dir]
if d1 ~= dir and dir ~= d2 then if d1 ~= dir and dir ~= d2 then
@ -366,8 +385,7 @@ end
function Tube:del_tube_dir(pos, dir) function Tube:del_tube_dir(pos, dir)
local npos, node = self:get_next_node(pos, dir) local npos, node = self:get_next_node(pos, dir)
if self.primary_node_names[node.name] then if self.primary_node_names[node.name] then
local d1, d2, num = self:decode_param2(node.param2) local d1, d2, num = self:decode_param2(npos, node.param2)
if not num then return end
return npos, d1, d2, math.max(num - 1, 0) return npos, d1, d2, math.max(num - 1, 0)
end end
end end
@ -377,7 +395,8 @@ end
function Tube:is_tube_head(pos, dir, out_tbl) function Tube:is_tube_head(pos, dir, out_tbl)
out_tbl.pos, out_tbl.node = self:get_next_node(pos, dir) out_tbl.pos, out_tbl.node = self:get_next_node(pos, dir)
if self.primary_node_names[out_tbl.node.name] then if self.primary_node_names[out_tbl.node.name] then
local dir1, dir2, num_conn = self:decode_param2(out_tbl.node.param2) local dir1, dir2, num_conn =
self:decode_param2(out_tbl.pos, out_tbl.node.param2)
if Turn180Deg[dir] == dir1 then if Turn180Deg[dir] == dir1 then
out_tbl.dir = dir2 out_tbl.dir = dir2
else else
@ -395,7 +414,7 @@ function Tube:find_peer_tube_head(node_tbl)
-- Return pos and dir to the next node of the tube node at pos/dir -- Return pos and dir to the next node of the tube node at pos/dir
local npos, node = self:get_next_node(pos, dir) local npos, node = self:get_next_node(pos, dir)
if self.primary_node_names[node.name] then if self.primary_node_names[node.name] then
local dir1, dir2, num = self:decode_param2(node.param2) local dir1, dir2, num = self:decode_param2(npos, node.param2)
if Turn180Deg[dir] == dir1 then if Turn180Deg[dir] == dir1 then
return npos, dir2 return npos, dir2
else else
@ -419,14 +438,26 @@ function Tube:find_peer_tube_head(node_tbl)
return pos, dir, cnt return pos, dir, cnt
end end
-- Set tube to a 2 connection node without meta data function Tube:determine_next_node(pos, dir)
function Tube:set_2_conn_tube(pos) local npos, node = self:get_next_node(pos, dir)
local npos, node = self:get_next_node(pos)
if self.primary_node_names[node.name] then if self.primary_node_names[node.name] then
local dir1, dir2, _ = self:decode_param2(node.param2) -- determine dirs on two ways
node.param2 = self:encode_param2(dir1, dir2, 2) local da1,da2,numa = self:decode_param2(npos, node.param2)
minetest.set_node(npos, node) local db1,db2,numb = self:determine_dir1_dir2_and_num_conn(npos)
M(npos):from_table(nil) -- both identical?
if da1 == db1 and da2 == db2 then
return npos, da1, da2
end
-- test if stored dirs point to valid nodes
if self:connected(npos, da1) and self:connected(npos, da2) then
return npos, da1, da2
end
-- use and store the determined dirs
if db1 and db2 then
node.param2 = self:encode_param2(db1,db2,numb)
minetest.set_node(npos, node)
return npos, db1, db2
end
end end
end end
@ -435,13 +466,8 @@ end
-- return head-pos and number of nodes -- return head-pos and number of nodes
function Tube:repair_tube_line(pos, dir) function Tube:repair_tube_line(pos, dir)
local repair_next_tube = function(self, pos, dir) local repair_next_tube = function(self, pos, dir)
local npos, node = self:get_next_node(pos, dir) local npos, dir1, dir2 = self:determine_next_node(pos, dir)
if self.primary_node_names[node.name] then if dir1 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) M(npos):from_table(nil)
if Turn180Deg[dir] == dir1 then if Turn180Deg[dir] == dir1 then
return npos, dir2 return npos, dir2
@ -449,7 +475,7 @@ function Tube:repair_tube_line(pos, dir)
return npos, dir1 return npos, dir1
end end
end end
return self:get_next_teleport_node(npos) return self:get_next_teleport_node(pos, dir)
end end
local cnt = 0 local cnt = 0
@ -473,7 +499,7 @@ function Tube:store_teleport_data(pos, peer_pos)
return meta:get_int("tube_dir") return meta:get_int("tube_dir")
end end
function Tube:get_peer_tube_head(node_tbl) function Tube:get_peer_tube_head(node_tbl, dir)
-- if meta data is available, return peer_pos, peer_pos -- if meta data is available, return peer_pos, peer_pos
local meta = M(node_tbl.pos) local meta = M(node_tbl.pos)
local spos = meta:get_string("peer_pos") local spos = meta:get_string("peer_pos")
@ -483,7 +509,7 @@ function Tube:get_peer_tube_head(node_tbl)
-- repair tube line -- repair tube line
local pos2, dir2, cnt = self:find_peer_tube_head(node_tbl) local pos2, dir2, cnt = self:find_peer_tube_head(node_tbl)
if pos2 then if pos2 then
self:add_meta_data(node_tbl.pos, pos2, Turn180Deg[node_tbl.dir], dir2, cnt+1) self:add_meta_data(node_tbl.pos, pos2, Turn180Deg[dir], dir2, cnt+1)
return pos2, dir2 return pos2, dir2
end end
end end

@ -72,6 +72,7 @@ function Tube:new(attr)
max_tube_length = attr.max_tube_length or 1000, max_tube_length = attr.max_tube_length or 1000,
primary_node_names = Tbl(attr.primary_node_names or {}), primary_node_names = Tbl(attr.primary_node_names or {}),
secondary_node_names = Tbl(attr.secondary_node_names or {}), secondary_node_names = Tbl(attr.secondary_node_names or {}),
legacy_node_names = Tbl(attr.legacy_node_names or {}),
show_infotext = attr.show_infotext or false, show_infotext = attr.show_infotext or false,
clbk_after_place_tube = attr.after_place_tube, clbk_after_place_tube = attr.after_place_tube,
pairingList = {}, -- teleporting nodes pairingList = {}, -- teleporting nodes
@ -93,7 +94,6 @@ end
-- Function returns the new pos or nil -- Function returns the new pos or nil
function Tube:primary_node(pos, dir) function Tube:primary_node(pos, dir)
local npos, node = self:get_next_node(pos, dir) local npos, node = self:get_next_node(pos, dir)
local _,_,num_conn = self:decode_param2(node.param2)
if self.primary_node_names[node.name] then if self.primary_node_names[node.name] then
return npos return npos
end end
@ -128,7 +128,7 @@ end
function Tube:get_connected_node_pos(pos, dir) function Tube:get_connected_node_pos(pos, dir)
local node = {} local node = {}
if self:is_tube_head(pos, dir, node) then if self:is_tube_head(pos, dir, node) then
local npos, ndir = self:get_peer_tube_head(node) local npos, ndir = self:get_peer_tube_head(node, dir)
return vector.add(npos, tubelib2.Dir6dToVector[ndir or 0]), ndir return vector.add(npos, tubelib2.Dir6dToVector[ndir or 0]), ndir
end end
return vector.add(pos, tubelib2.Dir6dToVector[dir or 0]), dir return vector.add(pos, tubelib2.Dir6dToVector[dir or 0]), dir
@ -147,7 +147,7 @@ end
function Tube:get_tube_end_pos(pos, dir) function Tube:get_tube_end_pos(pos, dir)
local node = {} local node = {}
if self:is_tube_head(pos, nil, node) then if self:is_tube_head(pos, nil, node) then
return self:get_peer_tube_head(node) return self:get_peer_tube_head(node, dir)
end end
return pos, dir return pos, dir
end end
@ -229,7 +229,7 @@ end
-- To be called after a tube node is removed. -- To be called after a tube node is removed.
function Tube:after_dig_tube(pos, oldnode, oldmetadata) function Tube:after_dig_tube(pos, oldnode, oldmetadata)
local dir1, dir2, num_tubes = self:decode_param2(oldnode.param2) local dir1, dir2, num_tubes = self:decode_param2(pos, oldnode.param2)
self:delete_tube_meta_data(pos, dir1, dir2, oldmetadata) self:delete_tube_meta_data(pos, dir1, dir2, oldmetadata)
@ -245,16 +245,16 @@ function Tube:after_dig_tube(pos, oldnode, oldmetadata)
end end
-- To be called from a repair tool in the case of a "WorldEdit" corrupted tube line. -- To be called from a repair tool in the case of a "WorldEdit" or with
-- legacy nodes corrupted tube line.
function Tube:tool_repair_tubes(pos) function Tube:tool_repair_tubes(pos)
local d1, d2 = self:get_tube_dirs(pos) -- determine the dirs from pointed pos
if d1 ~= 0 then local npos, d1, d2 = self:determine_next_node(pos)
self:set_2_conn_tube(pos) M(pos):from_table(nil) -- delete meta data
local npos1, dir1, cnt1 = self:repair_tube_line(pos, d1) local npos1, dir1, cnt1 = self:repair_tube_line(pos, d1)
local npos2, dir2, cnt2 = self:repair_tube_line(pos, d2) local npos2, dir2, cnt2 = self:repair_tube_line(pos, d2)
self:add_meta_data(npos1, npos2, dir1, dir2, cnt1+cnt2+1) self:add_meta_data(npos1, npos2, dir1, dir2, cnt1+cnt2+1)
return npos1, npos2, dir1, dir2, cnt1, cnt2 return npos1, npos2, d1, d2, cnt1, cnt2
end
end end