diff --git a/internal.lua b/internal.lua index 5d109ac..f321ade 100644 --- a/internal.lua +++ b/internal.lua @@ -13,8 +13,8 @@ ]]-- -- for lazy programmers -local P = minetest.pos_to_string -local S = minetest.string_to_pos +local S = minetest.pos_to_string +local P = minetest.string_to_pos local M = minetest.get_meta @@ -195,9 +195,9 @@ function Tube:update_head_tube(pos1, pos2, dir2, num_tubes) node.param2 = self:encode_param2(d1, d2, num) minetest.set_node(pos1, node) if self.show_infotext then - M(pos1):set_string("infotext", P(pos2).." / "..num_tubes.." tubes") + M(pos1):set_string("infotext", S(pos2).." / "..num_tubes.." tubes") end - M(pos1):set_string("peer_pos", P(pos2)) + M(pos1):set_string("peer_pos", S(pos2)) M(pos1):set_int("peer_dir", dir2) end @@ -211,7 +211,7 @@ end -- Delete meta data on both tube sides -- pos is the position of one head node function Tube:del_meta_data(pos) - local peer_pos = S(M(pos):get_string("peer_pos")) + local peer_pos = P(M(pos):get_string("peer_pos")) if peer_pos then M(pos):from_table(nil) M(peer_pos):from_table(nil) @@ -370,6 +370,19 @@ function Tube:get_tube_dirs(pos) end end +-- Jump over the teleport nodes to the next tube node +function Tube:get_next_teleport_node(pos, dir) + local meta = M(pos) + 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 + -- Go down the tube to the end position and -- return pos, dir to the next node, and num tubes @@ -377,14 +390,16 @@ function Tube:find_tube_head(pos) local get_next_tube = function(self, pos, dir) -- Return pos and dir to the next node of the tube node at pos/dir local npos, node = get_next_node(pos, dir) - local dir1, dir2, num = self:decode_param2(node.param2) if self.primary_node_names[node.name] then + local dir1, dir2, num = self:decode_param2(node.param2) if Turn180Deg[dir] == dir1 then return npos, dir2 else return npos, dir1 end end + + return Tube:get_next_teleport_node(npos, dir, node) end local cnt = 0 @@ -401,7 +416,6 @@ function Tube:find_tube_head(pos) while cnt <= self.max_tube_length do local new_pos, new_dir = get_next_tube(self, pos, dir) if not new_dir then break end - print(P(new_pos), new_dir) pos, dir = new_pos, new_dir cnt = cnt + 1 end @@ -438,6 +452,8 @@ function Tube:repair_tube_line(pos, dir) return npos, dir1 end end + + return Tube:get_next_teleport_node(npos, dir, node) end local cnt = 0 @@ -451,4 +467,11 @@ function Tube:repair_tube_line(pos, dir) return pos, dir, cnt end - +-- 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)) +end diff --git a/textures/tubelib2_conn.png b/textures/tubelib2_conn.png new file mode 100644 index 0000000..a272396 Binary files /dev/null and b/textures/tubelib2_conn.png differ diff --git a/textures/tubelib2_hole.png b/textures/tubelib2_hole.png index 572754b..96193dd 100644 Binary files a/textures/tubelib2_hole.png and b/textures/tubelib2_hole.png differ diff --git a/textures/tubelib2_tele.png b/textures/tubelib2_tele.png new file mode 100644 index 0000000..965b836 Binary files /dev/null and b/textures/tubelib2_tele.png differ diff --git a/textures/tubelib2_tool.png b/textures/tubelib2_tool.png index 2ec1235..594dc1f 100644 Binary files a/textures/tubelib2_tool.png and b/textures/tubelib2_tool.png differ diff --git a/textures/tubelib2_tube.png b/textures/tubelib2_tube.png index cdc5932..ee4b142 100644 Binary files a/textures/tubelib2_tube.png and b/textures/tubelib2_tube.png differ diff --git a/tube_api.lua b/tube_api.lua index 29d3ce4..7af628c 100644 --- a/tube_api.lua +++ b/tube_api.lua @@ -13,8 +13,8 @@ ]]-- -- for lazy programmers -local P = minetest.pos_to_string -local S = minetest.string_to_pos +local S = minetest.pos_to_string +local P = minetest.string_to_pos local M = minetest.get_meta @@ -41,6 +41,7 @@ function Tube:new(attr) primary_node_names = Tbl(attr.primary_node_names or {}), secondary_node_names = Tbl(attr.secondary_node_names or {}), show_infotext = attr.show_infotext or false, + pairingList = {}, -- teleporting nodes } setmetatable(o, self) self.__index = self @@ -68,7 +69,7 @@ end function Tube:get_tube_end_pos(pos) local spos = M(pos):get_string("peer_pos") if spos ~= "" then - return S(spos), M(pos):get_int("peer_dir") + return P(spos), M(pos):get_int("peer_dir") end local npos, dir, num = self:find_tube_head(pos) self:update_head_tube(pos, npos, dir, num) @@ -89,7 +90,6 @@ function Tube:update_tubes_after_place_node(pos, placer, pointed_thing) if num_tubes >= 1 then local npos, d1, d2, num = self:add_tube_dir(pos, dir1) if npos then - --print("update_tubes_after_place_node: d1, d2, num", d1, d2, num) tbl[#tbl+1] = self:tube_data_to_table(npos, d1, d2, num) end end @@ -97,7 +97,6 @@ function Tube:update_tubes_after_place_node(pos, placer, pointed_thing) if num_tubes >= 2 then local npos, d1, d2, num = self:add_tube_dir(pos, dir2) if npos then - --print("update_tubes_after_place_node: d1, d2, num", d1, d2, num) tbl[#tbl+1] = self:tube_data_to_table(npos, d1, d2, num) end end @@ -128,11 +127,13 @@ end -- To be called from a repair tool in the case of a "WorldEdit" corrupted tube line. function Tube:repair_tubes(pos) local d1, d2 = self:get_tube_dirs(pos) - 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 + if d1 and d2 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 end @@ -152,3 +153,43 @@ function Tube:remove_tube(pos, sound) if npos2 then self:repair_tubes(npos2) end end end + +function Tube:prepare_pairing(pos, tube_dir, sFormspec) + local meta = M(pos) + meta:set_int("tube_dir", tube_dir) + meta:set_string("channel", nil) + meta:set_string("infotext", "Unconnected") + meta:set_string("formspec", sFormspec) +end + +function Tube:pairing(pos, channel) + if self.pairingList[channel] and pos ~= self.pairingList[channel] then + -- store peer position on both nodes + local peer_pos = self.pairingList[channel] + self:store_teleport_data(pos, peer_pos) + self:store_teleport_data(peer_pos, pos) + self.pairingList[channel] = nil + return true + else + self.pairingList[channel] = pos + local meta = M(pos) + meta:set_string("channel", channel) + meta:set_string("infotext", "Unconnected ("..channel..")") + return false + end +end + +function Tube:stop_pairing(pos, sFormspec) + -- unpair peer node + local s = M(pos):get_string("peer_pos") + if s ~= "" then + local peer_pos = P(s) + local peer_meta = M(peer_pos) + if peer_meta then + peer_meta:set_string("channel", nil) + peer_meta:set_string("tele_pos", nil) + peer_meta:set_string("formspec", sFormspec) + peer_meta:set_string("infotext", "Unconnected") + end + end +end diff --git a/tube_test.lua b/tube_test.lua index becca46..f17ae25 100644 --- a/tube_test.lua +++ b/tube_test.lua @@ -15,8 +15,8 @@ ]]-- -- for lazy programmers -local P = minetest.pos_to_string -local S = minetest.string_to_pos +local S = minetest.pos_to_string +local P = minetest.string_to_pos local M = minetest.get_meta -- Test tubes @@ -41,10 +41,8 @@ minetest.register_node("tubelib2:tubeS", { after_place_node = function(pos, placer, itemstack, pointed_thing) local nodes = Tube:update_tubes_after_place_node(pos, placer, pointed_thing) - --print("nodes"..dump(nodes)) if #nodes > 0 then for _,item in ipairs(nodes) do - --print("after_place_node", item.type, item.param2) minetest.set_node(item.pos, {name = "tubelib2:tube"..item.type, param2 = item.param2}) end return false @@ -56,7 +54,6 @@ minetest.register_node("tubelib2:tubeS", { after_dig_node = function(pos, oldnode, oldmetadata, digger) for _,item in ipairs(Tube:update_tubes_after_dig_node(pos, oldnode)) do - --print("after_dig_node", item.type, item.param2) minetest.set_node(item.pos, {name = "tubelib2:tube"..item.type, param2 = item.param2}) end end, @@ -70,6 +67,7 @@ minetest.register_node("tubelib2:tubeS", { }, }, node_placement_prediction = "", -- important! + on_rotate = screwdriver.disallow, -- important! paramtype = "light", sunlight_propagates = true, is_ground_content = false, @@ -90,7 +88,6 @@ minetest.register_node("tubelib2:tubeA", { after_dig_node = function(pos, oldnode, oldmetadata, digger) for _,item in ipairs(Tube:update_tubes_after_dig_node(pos, oldnode)) do - --print("after_dig_node", item.type, item.param2) minetest.set_node(item.pos, {name = "tubelib2:tube"..item.type, param2 = item.param2}) end end, @@ -104,14 +101,58 @@ minetest.register_node("tubelib2:tubeA", { {-2/8, -2/8, -4/8, 2/8, 2/8, -2/8}, }, }, + --on_rotate = screwdriver.disallow, -- important! paramtype = "light", sunlight_propagates = true, is_ground_content = false, - groups = {crumbly = 3, cracky = 3, snappy = 3, not_in_creative_inventory=1}, + groups = {crumbly = 3, cracky = 3, snappy = 3}, --not_in_creative_inventory=1}, sounds = default.node_sound_glass_defaults(), drop = "tubelib2:tubeS", }) +local sFormspec = "size[7.5,3]".. + "field[0.5,1;7,1;channel;Enter channel string;]" .. + "button_exit[2,2;3,1;exit;Save]" + + +minetest.register_node("tubelib2:teleporter", { + description = "Tubelib2 Teleporter", + tiles = { + -- up, down, right, left, back, front + 'tubelib2_tele.png', + 'tubelib2_tele.png', + 'tubelib2_tele.png', + 'tubelib2_tele.png', + 'tubelib2_tele.png', + 'tubelib2_conn.png', + }, + + after_place_node = function(pos, placer) + Tube:pairing(pos, sFormspec) + -- the tube_dir calculation depends on the player look-dir and the hole side of the node + local tube_dir = ((minetest.dir_to_facedir(placer:get_look_dir()) + 2) % 4) + 1 + Tube:prepare_pairing(pos, tube_dir, sFormspec) + end, + + on_receive_fields = function(pos, formname, fields, player) + if fields.channel ~= nil then + Tube:pairing(pos, fields.channel) + end + end, + + on_destruct = function(pos) + Tube:stop_pairing(pos, sFormspec) + end, + + paramtype2 = "facedir", -- important! + on_rotate = screwdriver.disallow, -- important! + paramtype = "light", + sunlight_propagates = true, + is_ground_content = false, + groups = {crumbly = 3, cracky = 3, snappy = 3}, + sounds = default.node_sound_glass_defaults(), +}) + local function read_test_type(itemstack, placer, pointed_thing) local param2 if pointed_thing.type == "node" then @@ -152,7 +193,7 @@ local function TEST_add_tube_dir(itemstack, placer, pointed_thing) local pos = pointed_thing.above local fdir = Tube:fdir(placer) local npos, d1, d2, num = Tube:add_tube_dir(pos, fdir) - print("npos, d1, d2, num", npos and P(npos), d1, d2, num) + print("npos, d1, d2, num", npos and S(npos), d1, d2, num) end end @@ -162,7 +203,7 @@ local function TEST_del_tube_dir(itemstack, placer, pointed_thing) local pos = pointed_thing.above local fdir = Tube:fdir(placer) local npos, d1, d2, num = Tube:del_tube_dir(pos, fdir) - print("npos, d1, d2, num", npos and P(npos), d1, d2, num) + print("npos, d1, d2, num", npos and S(npos), d1, d2, num) end end @@ -179,11 +220,15 @@ local function repair_tubes(itemstack, placer, pointed_thing) local pos = pointed_thing.under if placer:get_player_control().sneak then local end_pos, dir = Tube:get_tube_end_pos(pos) - minetest.chat_send_player(placer:get_player_name(), "[Tubelib2] end_pos = "..P(end_pos)..", dir = "..dir) + if end_pos and dir then + minetest.chat_send_player(placer:get_player_name(), "[Tubelib2] end_pos = "..S(end_pos)..", dir = "..dir) + end else local pos1, pos2, dir1, dir2, cnt1, cnt2 = Tube:repair_tubes(pos) - minetest.chat_send_player(placer:get_player_name(), "[Tubelib2] 1: "..P(pos1)..", dir = "..dir1..", "..cnt1.." tubes") - minetest.chat_send_player(placer:get_player_name(), "[Tubelib2] 2: "..P(pos2)..", dir = "..dir2..", "..cnt2.." tubes") + if pos1 and pos2 then + minetest.chat_send_player(placer:get_player_name(), "[Tubelib2] 1: "..S(pos1)..", dir = "..dir1..", "..cnt1.." tubes") + minetest.chat_send_player(placer:get_player_name(), "[Tubelib2] 2: "..S(pos2)..", dir = "..dir2..", "..cnt2.." tubes") + end end end end