From 666bb98957221347c362ae657a3a5ad17a05d09c Mon Sep 17 00:00:00 2001 From: mworzala Date: Fri, 1 Dec 2023 21:59:50 +0200 Subject: [PATCH] fix: bad collision shape parsing --- .../src/main/java/net/minestom/demo/Main.java | 1 + .../server/collision/BoundingBox.java | 45 +++++++++++++---- .../minestom/server/collision/ShapeImpl.java | 2 +- .../net/minestom/server/entity/Player.java | 2 +- .../server/utils/block/BlockIterator.java | 50 ++++++++++--------- 5 files changed, 66 insertions(+), 34 deletions(-) diff --git a/demo/src/main/java/net/minestom/demo/Main.java b/demo/src/main/java/net/minestom/demo/Main.java index bed0f12dd..09e7f4319 100644 --- a/demo/src/main/java/net/minestom/demo/Main.java +++ b/demo/src/main/java/net/minestom/demo/Main.java @@ -25,6 +25,7 @@ public class Main { public static void main(String[] args) { System.setProperty("minestom.use-new-chunk-sending", "true"); + System.setProperty("minestom.experiment.pose-updates", "true"); MinecraftServer minecraftServer = MinecraftServer.init(); diff --git a/src/main/java/net/minestom/server/collision/BoundingBox.java b/src/main/java/net/minestom/server/collision/BoundingBox.java index d7a70c40c..2ac4be065 100644 --- a/src/main/java/net/minestom/server/collision/BoundingBox.java +++ b/src/main/java/net/minestom/server/collision/BoundingBox.java @@ -161,27 +161,55 @@ public final class BoundingBox implements Shape { return relativeEnd().z(); } + public enum AxisMask { + X, + Y, + Z, + NONE + } + public Iterator getBlocks(Point point) { - return new PointIterator(this, point); + return new PointIterator(this, point, AxisMask.NONE, 0); + } + + public Iterator getBlocks(Point point, AxisMask axisMask, double axis) { + return new PointIterator(this, point, axisMask, axis); } static class PointIterator implements Iterator { - int x = 0; - int y = 0; - int z = 0; + private final double sx, sy, sz; + double x, y, z; + private double minX, minY, minZ, maxX, maxY, maxZ; - private final int minX, minY, minZ, maxX, maxY, maxZ; - - public PointIterator(BoundingBox boundingBox, Point p) { + public PointIterator(BoundingBox boundingBox, Point p, AxisMask axisMask, double axis) { minX = (int) Math.floor(boundingBox.minX() + p.x()); minY = (int) Math.floor(boundingBox.minY() + p.y()); minZ = (int) Math.floor(boundingBox.minZ() + p.z()); maxX = (int) Math.floor(boundingBox.maxX() + p.x()); maxY = (int) Math.floor(boundingBox.maxY() + p.y()); maxZ = (int) Math.floor(boundingBox.maxZ() + p.z()); + x = minX; y = minY; z = minZ; + + sx = boundingBox.minX() + p.x() - minX; + sy = boundingBox.minY() + p.y() - minY; + sz = boundingBox.minZ() + p.z() - minZ; + + if (axisMask == AxisMask.X) { + x = axis + p.x(); + minX = x; + maxX = x; + } else if (axisMask == AxisMask.Y) { + y = axis + p.y(); + minY = y; + maxY = y; + } else if (axisMask == AxisMask.Z) { + z = axis + p.z(); + minZ = z; + maxZ = z; + } } @Override @@ -191,7 +219,7 @@ public final class BoundingBox implements Shape { @Override public Point next() { - var res = new Vec(x, y, z); + var res = new Vec(x + sx, y + sy, z + sz); x++; if (x > maxX) { @@ -202,7 +230,6 @@ public final class BoundingBox implements Shape { z++; } } - return res; } } diff --git a/src/main/java/net/minestom/server/collision/ShapeImpl.java b/src/main/java/net/minestom/server/collision/ShapeImpl.java index 8153266bf..61b06f309 100644 --- a/src/main/java/net/minestom/server/collision/ShapeImpl.java +++ b/src/main/java/net/minestom/server/collision/ShapeImpl.java @@ -61,7 +61,7 @@ public final class ShapeImpl implements Shape { this.blockOcclusion = fullFaces; } - static private BoundingBox[] parseRegistryBoundingBoxString(String str) { + private static BoundingBox[] parseRegistryBoundingBoxString(String str) { final Matcher matcher = PATTERN.matcher(str); DoubleList vals = new DoubleArrayList(); while (matcher.find()) { diff --git a/src/main/java/net/minestom/server/entity/Player.java b/src/main/java/net/minestom/server/entity/Player.java index 83d00d2ff..3fd3f5c58 100644 --- a/src/main/java/net/minestom/server/entity/Player.java +++ b/src/main/java/net/minestom/server/entity/Player.java @@ -804,7 +804,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable, var pos = iter.next(); var hit = instance.getBlock(pos, Block.Getter.Condition.TYPE) .registry().collisionShape() - .intersectBox(position.sub(pos), bb); + .intersectBox(position.sub(pos.blockX(), pos.blockY(), pos.blockZ()), bb); if (hit) return false; } diff --git a/src/main/java/net/minestom/server/utils/block/BlockIterator.java b/src/main/java/net/minestom/server/utils/block/BlockIterator.java index 08bab9667..862300958 100644 --- a/src/main/java/net/minestom/server/utils/block/BlockIterator.java +++ b/src/main/java/net/minestom/server/utils/block/BlockIterator.java @@ -54,7 +54,10 @@ public class BlockIterator implements Iterator { */ public BlockIterator(@NotNull Vec start, @NotNull Vec direction, double yOffset, double maxDistance, boolean smooth) { start = start.add(0, yOffset, 0); - end = start.add(direction.normalize().mul(maxDistance)); + + if (maxDistance != 0) end = start.add(direction.normalize().mul(maxDistance)); + else end = null; + if (direction.isZero()) this.foundEnd = true; this.smooth = smooth; @@ -75,21 +78,17 @@ public class BlockIterator implements Iterator { deltaDistZ = (ray.z() == 0) ? 1e30 : Math.abs(1 / ray.z()); // This works by calculating and storing the distance to the next grid intersection on the x, y and z axis //calculate step and initial sideDist - if (ray.x() < 0) { - sideDistX = (start.x() - mapX) * deltaDistX; - } else { - sideDistX = (mapX + 1.0 - start.x()) * deltaDistX; - } - if (ray.y() < 0) { - sideDistY = (start.y() - mapY) * deltaDistY; - } else { - sideDistY = (mapY + 1.0 - start.y()) * deltaDistY; - } - if (ray.z() < 0) { - sideDistZ = (start.z() - mapZ) * deltaDistZ; - } else { - sideDistZ = (mapZ + 1.0 - start.z()) * deltaDistZ; - } + if (ray.x() < 0) sideDistX = (start.x() - mapX) * deltaDistX; + else if (ray.x() > 0) sideDistX = (mapX + signums[0] - start.x()) * deltaDistX; + else sideDistX = Double.MAX_VALUE; + + if (ray.y() < 0) sideDistY = (start.y() - mapY) * deltaDistY; + else if (ray.y() > 0) sideDistY = (mapY + signums[1] - start.y()) * deltaDistY; + else sideDistY = Double.MAX_VALUE; + + if (ray.z() < 0) sideDistZ = (start.z() - mapZ) * deltaDistZ; + else if (ray.z() > 0) sideDistZ = (mapZ + signums[2] - start.z()) * deltaDistZ; + else sideDistZ = Double.MAX_VALUE; } /** @@ -204,17 +203,17 @@ public class BlockIterator implements Iterator { if (foundEnd) throw new NoSuchElementException(); if (!extraPoints.isEmpty()) { var res = extraPoints.poll(); - if (res.sameBlock(end)) foundEnd = true; + if (end != null && res.sameBlock(end)) foundEnd = true; return res; } var current = new Vec(mapX, mapY, mapZ); - if (current.sameBlock(end)) foundEnd = true; + if (end != null && current.sameBlock(end)) foundEnd = true; double closest = Math.min(sideDistX, Math.min(sideDistY, sideDistZ)); - boolean needsX = sideDistX - closest < 1e-10; - boolean needsY = sideDistY - closest < 1e-10; - boolean needsZ = sideDistZ - closest < 1e-10; + boolean needsX = sideDistX - closest < 1e-10 && signums[0] != 0; + boolean needsY = sideDistY - closest < 1e-10 && signums[1] != 0; + boolean needsZ = sideDistZ - closest < 1e-10 && signums[2] != 0; if (needsZ) { sideDistZ += deltaDistZ; @@ -232,8 +231,13 @@ public class BlockIterator implements Iterator { } if (needsX && needsY && needsZ) { - extraPoints.add(new Vec(signums[0] + current.x(), current.y(), current.z())); + extraPoints.add(new Vec(signums[0] + current.x(), signums[1] + current.y(), current.z())); if (smooth) return current; + + extraPoints.add(new Vec(current.x(), signums[1] + current.y(), signums[2] + current.z())); + extraPoints.add(new Vec(signums[0] + current.x(), current.y(), signums[2] + current.z())); + + extraPoints.add(new Vec(signums[0] + current.x(), current.y(), current.z())); extraPoints.add(new Vec(current.x(), signums[1] + current.y(), current.z())); extraPoints.add(new Vec(current.x(), current.y(), signums[2] + current.z())); } else if (needsX && needsY) { @@ -252,4 +256,4 @@ public class BlockIterator implements Iterator { return current; } -} \ No newline at end of file +}