From ab1fd60d396efb3b2bd9edc23f2e9e0b8a644656 Mon Sep 17 00:00:00 2001 From: BONNe Date: Tue, 28 Nov 2023 18:55:42 +0200 Subject: [PATCH] Fixes end portal finding issue when entering from side There was a bug in the code that prevented to finding of a portal location if the player entered from the side. It can happen only if the portal frame is removed, but as in vanilla it is possible, then it needs to be addressed. The fix itself is simple: instead of checking just up from the starting location, the code will check all blocks in 10x10x10 square from the starting location and find the "closest" portal location. This will fix #2237 --- .../teleports/AbstractTeleportListener.java | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/listeners/teleports/AbstractTeleportListener.java b/src/main/java/world/bentobox/bentobox/listeners/teleports/AbstractTeleportListener.java index 36f8ef266..4105d71b3 100644 --- a/src/main/java/world/bentobox/bentobox/listeners/teleports/AbstractTeleportListener.java +++ b/src/main/java/world/bentobox/bentobox/listeners/teleports/AbstractTeleportListener.java @@ -274,9 +274,38 @@ public abstract class AbstractTeleportListener // If the from is not a portal, then we have to find it if (!fromLocation.getBlock().getType().equals(Material.END_PORTAL)) { - // Find the portal - due to speed, it is possible that the player will be below or above the portal - for (k = toWorld.getMinHeight(); (k < fromWorld.getMaxHeight()) && - !fromWorld.getBlockAt(x, k, z).getType().equals(Material.END_PORTAL); k++); + // Search portal block 5 blocks in all directions from starting location. Return the first one. + boolean continueSearch = true; + + // simplistic search pattern to look at all blocks from the middle outwards by preferring + // Y location first, then Z and as last X + // Proper implementation would require queue and distance calculation. + + for (int offsetX = 0; continueSearch && offsetX < 10; offsetX++) + { + // Change sign based on mod value. + int posX = x + ((offsetX % 2 == 0) ? 1 : -1) * (offsetX / 2); + + for (int offsetZ = 0; continueSearch && offsetZ < 10; offsetZ++) + { + // Change sign based on mod value. + int posZ = z + ((offsetZ % 2 == 0) ? 1 : -1) * (offsetZ / 2); + + for (int offsetY = 0; continueSearch && offsetY < 10; offsetY++) + { + // Change sign based on mod value. + int posY = y + ((offsetY % 2 == 0) ? 1 : -1) * (offsetY / 2); + + if (fromWorld.getBlockAt(posX, posY, posZ).getType().equals(Material.END_PORTAL)) + { + i = posX; + j = posZ; + k = posY; + continueSearch = false; + } + } + } + } } // Find the maximum x and z corner @@ -289,7 +318,7 @@ public abstract class AbstractTeleportListener // OBSIDIAN // and player is placed on second air block above obsidian. // If Y coordinate is below 2, then obsidian platform is not generated and player falls in void. - return new Location(toWorld, i, Math.max(toWorld.getMinHeight() + 2, k), j); + return new Location(toWorld, i, Math.min(toWorld.getMaxHeight() - 2, Math.max(toWorld.getMinHeight() + 2, k)), j); }