fix: bad collision shape parsing

This commit is contained in:
mworzala 2023-12-01 21:59:50 +02:00
parent d8ef618d08
commit 666bb98957
No known key found for this signature in database
GPG Key ID: B148F922E64797C7
5 changed files with 66 additions and 34 deletions

View File

@ -25,6 +25,7 @@ public class Main {
public static void main(String[] args) { public static void main(String[] args) {
System.setProperty("minestom.use-new-chunk-sending", "true"); System.setProperty("minestom.use-new-chunk-sending", "true");
System.setProperty("minestom.experiment.pose-updates", "true");
MinecraftServer minecraftServer = MinecraftServer.init(); MinecraftServer minecraftServer = MinecraftServer.init();

View File

@ -161,27 +161,55 @@ public final class BoundingBox implements Shape {
return relativeEnd().z(); return relativeEnd().z();
} }
public enum AxisMask {
X,
Y,
Z,
NONE
}
public Iterator<Point> getBlocks(Point point) { public Iterator<Point> getBlocks(Point point) {
return new PointIterator(this, point); return new PointIterator(this, point, AxisMask.NONE, 0);
}
public Iterator<Point> getBlocks(Point point, AxisMask axisMask, double axis) {
return new PointIterator(this, point, axisMask, axis);
} }
static class PointIterator implements Iterator<Point> { static class PointIterator implements Iterator<Point> {
int x = 0; private final double sx, sy, sz;
int y = 0; double x, y, z;
int z = 0; private double minX, minY, minZ, maxX, maxY, maxZ;
private final int minX, minY, minZ, maxX, maxY, maxZ; public PointIterator(BoundingBox boundingBox, Point p, AxisMask axisMask, double axis) {
public PointIterator(BoundingBox boundingBox, Point p) {
minX = (int) Math.floor(boundingBox.minX() + p.x()); minX = (int) Math.floor(boundingBox.minX() + p.x());
minY = (int) Math.floor(boundingBox.minY() + p.y()); minY = (int) Math.floor(boundingBox.minY() + p.y());
minZ = (int) Math.floor(boundingBox.minZ() + p.z()); minZ = (int) Math.floor(boundingBox.minZ() + p.z());
maxX = (int) Math.floor(boundingBox.maxX() + p.x()); maxX = (int) Math.floor(boundingBox.maxX() + p.x());
maxY = (int) Math.floor(boundingBox.maxY() + p.y()); maxY = (int) Math.floor(boundingBox.maxY() + p.y());
maxZ = (int) Math.floor(boundingBox.maxZ() + p.z()); maxZ = (int) Math.floor(boundingBox.maxZ() + p.z());
x = minX; x = minX;
y = minY; y = minY;
z = minZ; 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 @Override
@ -191,7 +219,7 @@ public final class BoundingBox implements Shape {
@Override @Override
public Point next() { public Point next() {
var res = new Vec(x, y, z); var res = new Vec(x + sx, y + sy, z + sz);
x++; x++;
if (x > maxX) { if (x > maxX) {
@ -202,7 +230,6 @@ public final class BoundingBox implements Shape {
z++; z++;
} }
} }
return res; return res;
} }
} }

View File

@ -61,7 +61,7 @@ public final class ShapeImpl implements Shape {
this.blockOcclusion = fullFaces; this.blockOcclusion = fullFaces;
} }
static private BoundingBox[] parseRegistryBoundingBoxString(String str) { private static BoundingBox[] parseRegistryBoundingBoxString(String str) {
final Matcher matcher = PATTERN.matcher(str); final Matcher matcher = PATTERN.matcher(str);
DoubleList vals = new DoubleArrayList(); DoubleList vals = new DoubleArrayList();
while (matcher.find()) { while (matcher.find()) {

View File

@ -804,7 +804,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
var pos = iter.next(); var pos = iter.next();
var hit = instance.getBlock(pos, Block.Getter.Condition.TYPE) var hit = instance.getBlock(pos, Block.Getter.Condition.TYPE)
.registry().collisionShape() .registry().collisionShape()
.intersectBox(position.sub(pos), bb); .intersectBox(position.sub(pos.blockX(), pos.blockY(), pos.blockZ()), bb);
if (hit) return false; if (hit) return false;
} }

View File

@ -54,7 +54,10 @@ public class BlockIterator implements Iterator<Point> {
*/ */
public BlockIterator(@NotNull Vec start, @NotNull Vec direction, double yOffset, double maxDistance, boolean smooth) { public BlockIterator(@NotNull Vec start, @NotNull Vec direction, double yOffset, double maxDistance, boolean smooth) {
start = start.add(0, yOffset, 0); 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; if (direction.isZero()) this.foundEnd = true;
this.smooth = smooth; this.smooth = smooth;
@ -75,21 +78,17 @@ public class BlockIterator implements Iterator<Point> {
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 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 //calculate step and initial sideDist
if (ray.x() < 0) { if (ray.x() < 0) sideDistX = (start.x() - mapX) * deltaDistX;
sideDistX = (start.x() - mapX) * deltaDistX; else if (ray.x() > 0) sideDistX = (mapX + signums[0] - start.x()) * deltaDistX;
} else { else sideDistX = Double.MAX_VALUE;
sideDistX = (mapX + 1.0 - start.x()) * deltaDistX;
} if (ray.y() < 0) sideDistY = (start.y() - mapY) * deltaDistY;
if (ray.y() < 0) { else if (ray.y() > 0) sideDistY = (mapY + signums[1] - start.y()) * deltaDistY;
sideDistY = (start.y() - mapY) * deltaDistY; else sideDistY = Double.MAX_VALUE;
} else {
sideDistY = (mapY + 1.0 - start.y()) * deltaDistY; if (ray.z() < 0) sideDistZ = (start.z() - mapZ) * deltaDistZ;
} else if (ray.z() > 0) sideDistZ = (mapZ + signums[2] - start.z()) * deltaDistZ;
if (ray.z() < 0) { else sideDistZ = Double.MAX_VALUE;
sideDistZ = (start.z() - mapZ) * deltaDistZ;
} else {
sideDistZ = (mapZ + 1.0 - start.z()) * deltaDistZ;
}
} }
/** /**
@ -204,17 +203,17 @@ public class BlockIterator implements Iterator<Point> {
if (foundEnd) throw new NoSuchElementException(); if (foundEnd) throw new NoSuchElementException();
if (!extraPoints.isEmpty()) { if (!extraPoints.isEmpty()) {
var res = extraPoints.poll(); var res = extraPoints.poll();
if (res.sameBlock(end)) foundEnd = true; if (end != null && res.sameBlock(end)) foundEnd = true;
return res; return res;
} }
var current = new Vec(mapX, mapY, mapZ); 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)); double closest = Math.min(sideDistX, Math.min(sideDistY, sideDistZ));
boolean needsX = sideDistX - closest < 1e-10; boolean needsX = sideDistX - closest < 1e-10 && signums[0] != 0;
boolean needsY = sideDistY - closest < 1e-10; boolean needsY = sideDistY - closest < 1e-10 && signums[1] != 0;
boolean needsZ = sideDistZ - closest < 1e-10; boolean needsZ = sideDistZ - closest < 1e-10 && signums[2] != 0;
if (needsZ) { if (needsZ) {
sideDistZ += deltaDistZ; sideDistZ += deltaDistZ;
@ -232,8 +231,13 @@ public class BlockIterator implements Iterator<Point> {
} }
if (needsX && needsY && needsZ) { 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; 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(), signums[1] + current.y(), current.z()));
extraPoints.add(new Vec(current.x(), current.y(), signums[2] + current.z())); extraPoints.add(new Vec(current.x(), current.y(), signums[2] + current.z()));
} else if (needsX && needsY) { } else if (needsX && needsY) {