From 7204e1f1dd94743c969424de40a1a485a2af9f4f Mon Sep 17 00:00:00 2001 From: Michael Burgess Date: Sun, 9 Aug 2026 14:49:12 -0400 Subject: [PATCH] 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. --- README.md | 5 +++- .../stargate/paper/gate/GateManager.java | 28 +++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5779297..79a01d1 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,10 @@ material, unsealed interior, too far from the sign, etc. - Travel is **one-way**: only the gate you dialed *from* can send anything anywhere. Walking (or wandering, or drifting) into its event horizon teleports whatever entered to the destination, arriving just clear of its iris (never inside it) and - still facing whatever direction it was already moving, so entering forward always + clear of any wall too - if the gate sits close to a wall (built inside a room, say), + the plugin checks the landing spot is actually open space and searches forward + along the entry direction for one instead of embedding the arrival in solid block. + It still faces whatever direction it was already moving, so entering forward always means exiting forward. The destination's horizon is visible but not walkable - stepping into it does nothing, same as a real Stargate only running one direction at a time. diff --git a/stargate-paper/src/main/java/dev/skywalker3200/stargate/paper/gate/GateManager.java b/stargate-paper/src/main/java/dev/skywalker3200/stargate/paper/gate/GateManager.java index 147dfa1..195bda9 100644 --- a/stargate-paper/src/main/java/dev/skywalker3200/stargate/paper/gate/GateManager.java +++ b/stargate-paper/src/main/java/dev/skywalker3200/stargate/paper/gate/GateManager.java @@ -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); } }