From aa2bfe94723abccba4fa228b647e06a3e1852042 Mon Sep 17 00:00:00 2001 From: Treer Date: Sat, 8 Feb 2020 15:54:52 +1100 Subject: [PATCH] prevent obscure portal behaviour bug If a portal is being ignited and portal frame near-but-not-at its destination was found that was active and already linked back to the local portal, it would cause the local portal to be extinguished. (Required the remote portal to somehow be in a different state from the portal it was linking to) --- portal_api.lua | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/portal_api.lua b/portal_api.lua index 2f5be3c..9abe801 100644 --- a/portal_api.lua +++ b/portal_api.lua @@ -1095,8 +1095,17 @@ local function locate_or_build_portal(portal_definition, suggested_wormholePos, result_orientation = found_orientation if is_ignited then - if DEBUG then minetest.chat_send_all(" Build unnecessary: already a lit portal at " .. minetest.pos_to_string(found_anchorPos) .. ", orientation " .. result_orientation .. ". Extinguishing...") end - extinguish_portal(found_anchorPos, portal_definition.frame_node_name, false) + -- We're about to link to this portal, so if it's already linked to a different portal then + -- extinguish it, to update the state of the about-to-be-orphaned portal. + local result_target_str = minetest.get_meta(result_anchorPos):get_string("target") + local result_target = minetest.string_to_pos(result_target_str) + if result_target ~= nil and vector.equals(result_target, destination_wormholePos) then + -- don't extinguish the portal the player is teleporting from + if DEBUG then minetest.chat_send_all(" Build unnecessary: already a lit portal that links back here at " .. minetest.pos_to_string(found_anchorPos) .. ", orientation " .. result_orientation) end + else + if DEBUG then minetest.chat_send_all(" Build unnecessary: already a lit portal at " .. minetest.pos_to_string(found_anchorPos) .. ", orientation " .. result_orientation .. ", linking to " .. result_target_str .. ". Extinguishing...") end + extinguish_portal(found_anchorPos, portal_definition.frame_node_name, false) + end else if DEBUG then minetest.chat_send_all(" Build unnecessary: already an unlit portal at " .. minetest.pos_to_string(found_anchorPos) .. ", orientation " .. result_orientation) end end @@ -1283,15 +1292,28 @@ local function ensure_remote_portal_then_teleport(playerName, portal_definition, if not vector.equals(destination_wormholePos, new_dest_wormholePos) then -- Update the local portal's target to match where the existing remote portal was found - destination_wormholePos = new_dest_wormholePos - if DEBUG then minetest.chat_send_all(" updating target to where remote portal was found - " .. minetest.pos_to_string(destination_wormholePos)) end - set_portal_metadata( - portal_definition, - local_anchorPos, - local_orientation, - destination_wormholePos - ) + if minetest.get_meta(local_anchorPos):get_string("target") == "" then + -- The local portal has been extinguished! + -- Abort setting its metadata as that assumes it is active. + -- This shouldn't happen and may indicate a bug, I trap it incase when the destination + -- portal was found and extinguished, it somehow linked back to the local portal in a + -- misaligned fashion that wasn't recognized as being the local portal and caused the + -- local portal to also be extinguished. + local message = "Local portal at " .. minetest.pos_to_string(local_anchorPos) .. " was extinguished while linking to existing portal at " .. minetest.pos_to_string(new_dest_anchorPos) + minetest.log("error", message) + if DEBUG then minetest.chat_send_all("!ERROR! - " .. message) end + else + destination_wormholePos = new_dest_wormholePos + if DEBUG then minetest.chat_send_all(" updating target to where remote portal was found - " .. minetest.pos_to_string(destination_wormholePos)) end + + set_portal_metadata( + portal_definition, + local_anchorPos, + local_orientation, + destination_wormholePos + ) + end end minetest.after(0.1, ensure_remote_portal_then_teleport, playerName, portal_definition, local_anchorPos, local_orientation, destination_wormholePos) end