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:
@@ -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.
|
||||
|
||||
+25
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user