Check landing spot is actually open space, not just clear of the iris

computeSafeLanding() pushed the arrival point along the entry
direction only until it cleared the destination's iris footprint - it
never checked whether that spot was solid ground. A gate built close
to a wall (e.g. inside a room/temple) could push the landing straight
into that wall, embedding the player in it - which incidentally let
them walk out through the wall instead of a door, since they're
already clipped partway through it.

Now checks feet AND head height at each step for solid blocks while
searching forward (up to 8 blocks), stopping at the first spot that's
both clear of the iris and open space. Falls back to the furthest
wall-clear point found if nothing satisfies both within range, rather
than the original blind offset.
This commit is contained in:
Michael Burgess
2026-08-09 14:49:12 -04:00
parent 508a3d9b51
commit 7204e1f1dd
2 changed files with 29 additions and 4 deletions
@@ -491,13 +491,35 @@ public class GateManager {
if (dir.lengthSquared() < 0.0001) dir = new Vector(0, 0, 1);
dir.normalize();
for (int i = 0; i < 8 && !irisXZ.isEmpty(); i++) {
long key = ((long) Math.floor(x) << 32) ^ ((long) Math.floor(z) & 0xFFFFFFFFL);
if (!irisXZ.contains(key)) break;
// Push clear of the iris footprint (so arrival doesn't immediately re-trigger the
// teleport) AND clear of any solid block at foot/head height - a wall close behind the
// gate (e.g. built inside a room) can otherwise land the player embedded in it. Falls
// back to the furthest wall-clear spot found if nothing satisfies both within range.
double lastClearX = x, lastClearZ = z;
boolean foundClear = false;
for (int i = 0; i <= 16; i++) {
boolean inIris = irisXZ.contains(((long) Math.floor(x) << 32) ^ ((long) Math.floor(z) & 0xFFFFFFFFL));
Block feet = world.getBlockAt((int) Math.floor(x), (int) Math.floor(y), (int) Math.floor(z));
Block head = feet.getRelative(0, 1, 0);
boolean solid = feet.getType().isSolid() || head.getType().isSolid();
if (!inIris && !solid) {
foundClear = true;
break;
}
if (!solid) {
lastClearX = x;
lastClearZ = z;
}
x += dir.getX() * 0.5;
z += dir.getZ() * 0.5;
}
if (!foundClear) {
x = lastClearX;
z = lastClearZ;
}
return new Location(world, x, y, z, yaw, pitch);
}
}