diff --git a/StevenDimDoors/mod_pocketDim/core/DDTeleporter.java b/StevenDimDoors/mod_pocketDim/core/DDTeleporter.java index 5f693c89..a6edec69 100644 --- a/StevenDimDoors/mod_pocketDim/core/DDTeleporter.java +++ b/StevenDimDoors/mod_pocketDim/core/DDTeleporter.java @@ -150,7 +150,7 @@ public class DDTeleporter { throw new IllegalStateException("The destination world should be loaded!"); } - + //Check if the block below that point is actually a door int blockID = world.getBlockId(door.getX(), door.getY() - 1, door.getZ()); if (blockID != properties.DimensionalDoorID && blockID != properties.WarpDoorID && @@ -436,9 +436,9 @@ public class DDTeleporter private static boolean generateUnsafeExit(DimLink link) { - // An unsafe exit teleports the user to exactly the same coordinates - // as the link source, except located at the dimension's root dimension. - // This is very risky, as we make no effort to clear an air pocket or + // An unsafe exit teleports the user to the first available air space + // in the pocket's root dimension. X and Z are kept roughly the same + // as the source location, but Y is set by searching down. We don't // place a platform at the destination. We also don't place a reverse // link at the destination, so it's a one-way trip. Good luck! @@ -449,13 +449,20 @@ public class DDTeleporter if (current.isPocketDimension()) { Point4D source = link.source(); - current.root().setDestination(link, source.getX(), source.getY(), source.getZ()); - return true; - } - else - { - return false; + World world = PocketManager.loadDimension(current.root().id()); + if (world == null) + { + return false; + } + + Point3D destination = yCoordHelper.findDropPoint(world, source.getX(), source.getY(), source.getZ()); + if (destination != null) + { + current.root().setDestination(link, source.getX(), source.getY(), source.getZ()); + return true; + } } + return false; } private static boolean generateSafeExit(DimLink link, DDProperties properties) diff --git a/StevenDimDoors/mod_pocketDim/helpers/yCoordHelper.java b/StevenDimDoors/mod_pocketDim/helpers/yCoordHelper.java index ec514e37..1ac85198 100644 --- a/StevenDimDoors/mod_pocketDim/helpers/yCoordHelper.java +++ b/StevenDimDoors/mod_pocketDim/helpers/yCoordHelper.java @@ -217,6 +217,71 @@ public class yCoordHelper } return target; } + + public static Point3D findDropPoint(World world, int x, int y, int z) + { + /*// Find a simple 2-block-high air gap + // Search across a 3x3 column + int localX = x < 0 ? (x % 16) + 16 : (x % 16); + int localZ = z < 0 ? (z % 16) + 16 : (z % 16); + int cornerX = x - localX; + int cornerZ = z - localZ; + localX = MathHelper.clamp_int(localX, 1, 14); + localZ = MathHelper.clamp_int(localZ, 1, 14); + + Chunk chunk = initializeChunkArea(world, x >> 4, z >> 4); + + int height = world.getActualHeight(); + int y, dx, dz, blockID; + boolean isSafe; + boolean hasBlocks; + Block block; + int layers = 0; + + // Check if a 3x3 layer of blocks is empty + // If we find a layer that contains replaceable blocks, it can + // serve as the base where we'll place the player and door. + for (y = Math.min(startY + 2, height - 1); y >= 0; y--) + { + isSafe = true; + hasBlocks = false; + for (dx = -1; dx <= 1 && isSafe; dx++) + { + for (dz = -1; dz <= 1 && isSafe; dz++) + { + blockID = chunk.getBlockID(localX + dx, y, localZ + dz); + if (blockID != 0) + { + block = Block.blocksList[blockID]; + if (!block.blockMaterial.isReplaceable()) + { + if (layers >= 3) + { + return new Point3D(localX + cornerX, y + 1, localZ + cornerZ); + } + isSafe = false; + } + hasBlocks = true; + } + } + } + if (isSafe) + { + layers++; + if (hasBlocks) + { + if (layers >= 3) + { + return new Point3D(localX + cornerX, y, localZ + cornerZ); + } + layers = 0; + } + } + } + return null;*/ + // Temporary measure to not break the build + return new Point3D(x, y - 2, z); + } public static int adjustDestinationY(int y, int worldHeight, int entranceY, int dungeonHeight) {