From 1e248a464614965ff7d08921707425f275c73e0d Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Sat, 3 Nov 2018 19:08:31 +0100 Subject: [PATCH] bugfixes --- convert.lua | 31 +++++++++++------ internal.lua | 98 +++++++++++++++++++++++++++++++++------------------- tube_api.lua | 26 +++++++------- 3 files changed, 95 insertions(+), 60 deletions(-) diff --git a/convert.lua b/convert.lua index 2162405..945f509 100644 --- a/convert.lua +++ b/convert.lua @@ -25,30 +25,39 @@ function Tube:on_convert_tube(convert_tube_clbk) self.convert_tube_clbk = convert_tube_clbk end -function Tube:convert_to_tubelib2(pos1, dir1) - local pos2, dir2, cnt = self:convert_tube_line(pos1, dir1) - self:add_meta_data(pos1, pos2, dir1, dir2, cnt) +-- Register legacy tube nodes. +function Tube:add_legacy_node_names(names) + for _,name in ipairs(names) do + self.legacy_node_names[name] = true + end end function Tube:convert_tube_line(pos, dir) local convert_next_tube = function(self, 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 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 + if self.legacy_node_names[node.name] then + local dir1, dir2, num + if self.convert_tube_clbk then + dir1, dir2, num = self.convert_tube_clbk(npos, node.name, node.param2) 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 local cnt = 0 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) if not new_dir then break end pos, dir = new_pos, new_dir diff --git a/internal.lua b/internal.lua index 984e735..779bcec 100644 --- a/internal.lua +++ b/internal.lua @@ -114,6 +114,30 @@ end 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") function Tube:encode_param2(dir1, dir2, num_conn) if dir1 > dir2 then @@ -124,13 +148,16 @@ function Tube:encode_param2(dir1, dir2, num_conn) end -- Return dir1, dir2, num_conn -function Tube:decode_param2(param2) +function Tube:decode_param2(pos, 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 + -- determine dirs via surrounding nodes + return self:determine_dir1_dir2_and_num_conn(pos) + end -- 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) 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 +-- Return the param2 stored tube dirs or 5,6 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) + return self:decode_param2(pos, node.param2) end - return 0,0 + return 5,6 end -- Return pos for a primary_node and true if num_conn < 2, else false function Tube:friendly_primary_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 + local _,_,num_conn = self:decode_param2(npos, node.param2) -- tube node with max one connection? return npos, (num_conn or 2) < 2 end @@ -184,7 +204,7 @@ end function Tube:update_head_tube(pos1, pos2, dir2, num_tubes) local node = get_node_lvm(pos1) 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 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) @@ -340,8 +360,7 @@ end function Tube:add_tube_dir(pos, dir) local npos, node = self:get_next_node(pos, dir) if self.primary_node_names[node.name] then - local d1, d2, num = self:decode_param2(node.param2) - if not num then return end + local d1, d2, num = self:decode_param2(npos, node.param2) -- not already connected to the new tube? dir = Turn180Deg[dir] if d1 ~= dir and dir ~= d2 then @@ -366,8 +385,7 @@ end function Tube:del_tube_dir(pos, dir) local npos, node = self:get_next_node(pos, dir) if self.primary_node_names[node.name] then - local d1, d2, num = self:decode_param2(node.param2) - if not num then return end + local d1, d2, num = self:decode_param2(npos, node.param2) return npos, d1, d2, math.max(num - 1, 0) end end @@ -377,7 +395,8 @@ end 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) + local dir1, dir2, num_conn = + self:decode_param2(out_tbl.pos, out_tbl.node.param2) if Turn180Deg[dir] == dir1 then out_tbl.dir = dir2 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 local npos, node = self:get_next_node(pos, dir) 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 return npos, dir2 else @@ -419,14 +438,26 @@ function Tube:find_peer_tube_head(node_tbl) return pos, dir, cnt end --- Set tube to a 2 connection node without meta data -function Tube:set_2_conn_tube(pos) - local npos, node = self:get_next_node(pos) +function Tube:determine_next_node(pos, dir) + local npos, node = self:get_next_node(pos, dir) if self.primary_node_names[node.name] then - local dir1, dir2, _ = self:decode_param2(node.param2) - node.param2 = self:encode_param2(dir1, dir2, 2) - minetest.set_node(npos, node) - M(npos):from_table(nil) + -- determine dirs on two ways + local da1,da2,numa = self:decode_param2(npos, node.param2) + local db1,db2,numb = self:determine_dir1_dir2_and_num_conn(npos) + -- 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 @@ -435,13 +466,8 @@ end -- return head-pos and number of nodes function Tube:repair_tube_line(pos, dir) local repair_next_tube = function(self, pos, dir) - local npos, node = self:get_next_node(pos, dir) - 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 + local npos, dir1, dir2 = self:determine_next_node(pos, dir) + if dir1 then M(npos):from_table(nil) if Turn180Deg[dir] == dir1 then return npos, dir2 @@ -449,7 +475,7 @@ function Tube:repair_tube_line(pos, dir) return npos, dir1 end end - return self:get_next_teleport_node(npos) + return self:get_next_teleport_node(pos, dir) end local cnt = 0 @@ -473,7 +499,7 @@ function Tube:store_teleport_data(pos, peer_pos) return meta:get_int("tube_dir") 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 local meta = M(node_tbl.pos) local spos = meta:get_string("peer_pos") @@ -483,7 +509,7 @@ function Tube:get_peer_tube_head(node_tbl) -- repair tube line local pos2, dir2, cnt = self:find_peer_tube_head(node_tbl) 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 end end diff --git a/tube_api.lua b/tube_api.lua index 16b7f86..ca730bd 100644 --- a/tube_api.lua +++ b/tube_api.lua @@ -72,6 +72,7 @@ function Tube:new(attr) max_tube_length = attr.max_tube_length or 1000, primary_node_names = Tbl(attr.primary_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, clbk_after_place_tube = attr.after_place_tube, pairingList = {}, -- teleporting nodes @@ -93,7 +94,6 @@ end -- Function returns the new pos or nil function Tube:primary_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 return npos end @@ -128,7 +128,7 @@ end function Tube:get_connected_node_pos(pos, dir) local node = {} 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 end return vector.add(pos, tubelib2.Dir6dToVector[dir or 0]), dir @@ -147,7 +147,7 @@ end function Tube:get_tube_end_pos(pos, dir) local node = {} 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 return pos, dir end @@ -229,7 +229,7 @@ end -- To be called after a tube node is removed. 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) @@ -245,16 +245,16 @@ function Tube:after_dig_tube(pos, oldnode, oldmetadata) 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) - local d1, d2 = self:get_tube_dirs(pos) - if d1 ~= 0 then - self:set_2_conn_tube(pos) - local npos1, dir1, cnt1 = self:repair_tube_line(pos, d1) - local npos2, dir2, cnt2 = self:repair_tube_line(pos, d2) - self:add_meta_data(npos1, npos2, dir1, dir2, cnt1+cnt2+1) - return npos1, npos2, dir1, dir2, cnt1, cnt2 - end + -- determine the dirs from pointed pos + local npos, d1, d2 = self:determine_next_node(pos) + M(pos):from_table(nil) -- delete meta data + local npos1, dir1, cnt1 = self:repair_tube_line(pos, d1) + local npos2, dir2, cnt2 = self:repair_tube_line(pos, d2) + self:add_meta_data(npos1, npos2, dir1, dir2, cnt1+cnt2+1) + return npos1, npos2, d1, d2, cnt1, cnt2 end