Update patches to handle vineflower decompiler (#10406)

* Update patches to handle vineflower decompiler

* update patches again to handle inlined simple lambdas

* update vf again and re-apply/rebuild patches

* update patches after removal of verify-merges flag

* fix compile issue

* remove maven local

* fix some issues

* address more issues

* fix collision patch

* use paperweight release

* more fixes

* update fineflower and fix patches again

* add missing comment descriptor

---------

Co-authored-by: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
This commit is contained in:
Jake Potrebic
2024-04-12 12:14:06 -07:00
parent 99625a6d53
commit 89528bff42
128 changed files with 1079 additions and 1150 deletions

View File

@@ -2470,14 +2470,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/level/BlockCollisions.java
+++ b/src/main/java/net/minecraft/world/level/BlockCollisions.java
@@ -0,0 +0,0 @@ public class BlockCollisions<T> extends AbstractIterator<T> {
VoxelShape voxelShape = blockState.getCollisionShape(this.collisionGetter, this.pos, this.context);
if (voxelShape == Shapes.block()) {
- if (!this.box.intersects((double)i, (double)j, (double)k, (double)i + 1.0D, (double)j + 1.0D, (double)k + 1.0D)) {
+ if (!io.papermc.paper.util.CollisionUtil.voxelShapeIntersect(this.box, (double)i, (double)j, (double)k, (double)i + 1.0D, (double)j + 1.0D, (double)k + 1.0D)) { // Paper - keep vanilla behavior for voxelshape intersection - See comment in CollisionUtil
continue;
}
// Paper end
VoxelShape voxelShape = blockState.getCollisionShape(this.collisionGetter, this.pos, this.context);
if (voxelShape == Shapes.block()) {
- if (this.box.intersects(i, j, k, i + 1.0, j + 1.0, k + 1.0)) {
+ if (io.papermc.paper.util.CollisionUtil.voxelShapeIntersect(this.box, i, j, k, i + 1.0, j + 1.0, k + 1.0)) { // Paper - keep vanilla behavior for voxelshape intersection - See comment in CollisionUtil
return this.resultProvider.apply(this.pos, voxelShape.move(i, j, k));
}
} else {
diff --git a/src/main/java/net/minecraft/world/level/ClipContext.java b/src/main/java/net/minecraft/world/level/ClipContext.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/ClipContext.java
@@ -2508,7 +2508,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end - optimise collisions
+
default boolean noCollision(AABB box) {
return this.noCollision((Entity)null, box);
return this.noCollision(null, box);
}
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
@@ -2522,8 +2522,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (shape.isEmpty()) {
- return true;
- } else {
- for(Entity entity : this.getEntities(except, shape.bounds())) {
- if (!entity.isRemoved() && entity.blocksBuilding && (except == null || !entity.isPassengerOfSameVehicle(except)) && Shapes.joinIsNotEmpty(shape, Shapes.create(entity.getBoundingBox()), BooleanOp.AND)) {
- for (Entity entity : this.getEntities(except, shape.bounds())) {
- if (!entity.isRemoved()
- && entity.blocksBuilding
- && (except == null || !entity.isPassengerOfSameVehicle(except))
- && Shapes.joinIsNotEmpty(shape, Shapes.create(entity.getBoundingBox()), BooleanOp.AND)) {
- return false;
+ return false;
+ }
@@ -2561,7 +2564,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
default List<VoxelShape> getEntityCollisions(@Nullable Entity entity, AABB box) {
- if (box.getSize() < 1.0E-7D) {
- if (box.getSize() < 1.0E-7) {
- return List.of();
+ // Paper start - optimise collisions
+ // first behavior change is to correctly check for empty AABB
@@ -2580,21 +2583,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ entities = this.getEntities(entity, box, null);
} else {
- Predicate<Entity> predicate = entity == null ? EntitySelector.CAN_BE_COLLIDED_WITH : EntitySelector.NO_SPECTATORS.and(entity::canCollideWith);
- List<Entity> list = this.getEntities(entity, box.inflate(1.0E-7D), predicate);
- List<Entity> list = this.getEntities(entity, box.inflate(1.0E-7), predicate);
- if (list.isEmpty()) {
- return List.of();
- } else {
- ImmutableList.Builder<VoxelShape> builder = ImmutableList.builderWithExpectedSize(list.size());
- Builder<VoxelShape> builder = ImmutableList.builderWithExpectedSize(list.size());
-
- for(Entity entity2 : list) {
- for (Entity entity2 : list) {
- builder.add(Shapes.create(entity2.getBoundingBox()));
- }
+ entities = this.getHardCollidingEntities(entity, box, null);
+ }
+
+ final List<VoxelShape> ret = new java.util.ArrayList<>(Math.min(25, entities.size()));
- return builder.build();
+ final List<VoxelShape> ret = new java.util.ArrayList<>(Math.min(25, entities.size()));
+
+ for (int i = 0, len = entities.size(); i < len; ++i) {
+ final Entity otherEntity = entities.get(i);
+
@@ -3234,23 +3237,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper end
+
public AABB(BlockPos pos) {
this((double)pos.getX(), (double)pos.getY(), (double)pos.getZ(), (double)(pos.getX() + 1), (double)(pos.getY() + 1), (double)(pos.getZ() + 1));
this(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1);
}
@@ -0,0 +0,0 @@ public class AABB {
}
@Nullable
- private static Direction getDirection(AABB box, Vec3 intersectingVector, double[] traceDistanceResult, @Nullable Direction approachDirection, double deltaX, double deltaY, double deltaZ) {
+ public static Direction getDirection(AABB box, Vec3 intersectingVector, double[] traceDistanceResult, @Nullable Direction approachDirection, double deltaX, double deltaY, double deltaZ) { // Paper - optimise collisions - public
if (deltaX > 1.0E-7D) {
approachDirection = clipPoint(traceDistanceResult, approachDirection, deltaX, deltaY, deltaZ, box.minX, box.minY, box.maxY, box.minZ, box.maxZ, Direction.WEST, intersectingVector.x, intersectingVector.y, intersectingVector.z);
} else if (deltaX < -1.0E-7D) {
- private static Direction getDirection(
+ public static Direction getDirection( // Paper - optimise collisions - public
AABB box, Vec3 intersectingVector, double[] traceDistanceResult, @Nullable Direction approachDirection, double deltaX, double deltaY, double deltaZ
) {
if (deltaX > 1.0E-7) {
diff --git a/src/main/java/net/minecraft/world/phys/shapes/ArrayVoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/ArrayVoxelShape.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/phys/shapes/ArrayVoxelShape.java
+++ b/src/main/java/net/minecraft/world/phys/shapes/ArrayVoxelShape.java
@@ -0,0 +0,0 @@ public class ArrayVoxelShape extends VoxelShape {
this(shape, (DoubleList)DoubleArrayList.wrap(Arrays.copyOf(xPoints, shape.getXSize() + 1)), (DoubleList)DoubleArrayList.wrap(Arrays.copyOf(yPoints, shape.getYSize() + 1)), (DoubleList)DoubleArrayList.wrap(Arrays.copyOf(zPoints, shape.getZSize() + 1)));
);
}
- ArrayVoxelShape(DiscreteVoxelShape shape, DoubleList xPoints, DoubleList yPoints, DoubleList zPoints) {
@@ -3259,8 +3262,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
int i = shape.getXSize() + 1;
int j = shape.getYSize() + 1;
@@ -0,0 +0,0 @@ public class ArrayVoxelShape extends VoxelShape {
} else {
throw (IllegalArgumentException)Util.pauseInIde(new IllegalArgumentException("Lengths of point arrays must be consistent with the size of the VoxelShape."));
new IllegalArgumentException("Lengths of point arrays must be consistent with the size of the VoxelShape.")
);
}
+ this.initCache(); // Paper - optimise collisions
}
@@ -3305,11 +3308,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Paper start - optimise collisions
+ // called with the shape of a VoxelShape, so we can expect the cache to exist
+ final io.papermc.paper.util.collisions.CachedShapeData cache = voxelSet.getOrCreateCachedShapeData();
+
- for (int i = 0; i < bitSetDiscreteVoxelShape.ySize; i++) {
- for (int j = 0; j < bitSetDiscreteVoxelShape.xSize; j++) {
- int k = -1;
+ final int sizeX = cache.sizeX();
+ final int sizeY = cache.sizeY();
+ final int sizeZ = cache.sizeZ();
+
- for (int l = 0; l <= bitSetDiscreteVoxelShape.zSize; l++) {
- if (bitSetDiscreteVoxelShape.isFullWide(j, i, l)) {
- if (coalesce) {
- if (k == -1) {
- k = l;
- }
- } else {
- callback.consume(j, i, l, j + 1, i + 1, l + 1);
+ int indexX;
+ int indexY = 0;
+ int indexZ;
@@ -3339,21 +3353,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } else {
+ // same notes about loop order as the above
+ // this branch is actually important to optimise, as it affects uncached toAabbs() (which affects optimize())
- for(int i = 0; i < bitSetDiscreteVoxelShape.ySize; ++i) {
- for(int j = 0; j < bitSetDiscreteVoxelShape.xSize; ++j) {
- int k = -1;
+
+ // only clone when we may write to it
+ bitset = bitset.clone();
- for(int l = 0; l <= bitSetDiscreteVoxelShape.zSize; ++l) {
- if (bitSetDiscreteVoxelShape.isFullWide(j, i, l)) {
- if (coalesce) {
- if (k == -1) {
- k = l;
- }
- } else {
- callback.consume(j, i, l, j + 1, i + 1, l + 1);
+
+ for (int y = 0; y < sizeY; ++y, indexY += incY) {
+ indexX = indexY;
+ for (int x = 0; x < sizeX; ++x, indexX += incX) {
@@ -3368,17 +3371,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- int n = i;
- bitSetDiscreteVoxelShape.clearZStrip(k, l, j, i);
-
- while(bitSetDiscreteVoxelShape.isZStripFull(k, l, m + 1, i)) {
- while (bitSetDiscreteVoxelShape.isZStripFull(k, l, m + 1, i)) {
- bitSetDiscreteVoxelShape.clearZStrip(k, l, m + 1, i);
- ++m;
- m++;
+
+ int lastSetZ = io.papermc.paper.util.collisions.FlatBitsetUtil.firstClear(bitset, firstSetZ, endIndex);
+ if (lastSetZ == -1) {
+ lastSetZ = endIndex;
}
- while(bitSetDiscreteVoxelShape.isXZRectangleFull(j, m + 1, k, l, n + 1)) {
- for(int o = j; o <= m; ++o) {
- while (bitSetDiscreteVoxelShape.isXZRectangleFull(j, m + 1, k, l, n + 1)) {
- for (int o = j; o <= m; o++) {
- bitSetDiscreteVoxelShape.clearZStrip(k, l, o, n + 1);
+ io.papermc.paper.util.collisions.FlatBitsetUtil.clearRange(bitset, firstSetZ, lastSetZ);
+
@@ -3408,7 +3411,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
}
- ++n;
- n++;
+ ++endY;
+
+ // passed, so we can clear it
@@ -3426,7 +3429,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
}
}
-
+ // Paper end - optimise collisions
}
@@ -3539,8 +3541,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
@@ -0,0 +0,0 @@ public final class Shapes {
public static final double EPSILON = 1.0E-7D;
public static final double BIG_EPSILON = 1.0E-6D;
public static final double EPSILON = 1.0E-7;
public static final double BIG_EPSILON = 1.0E-6;
private static final VoxelShape BLOCK = Util.make(() -> {
- DiscreteVoxelShape discreteVoxelShape = new BitSetDiscreteVoxelShape(1, 1, 1);
- discreteVoxelShape.fill(0, 0, 0);
@@ -3555,8 +3557,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ );
+ // Paper end - optimise collisions - force arrayvoxelshape
});
public static final VoxelShape INFINITY = box(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
private static final VoxelShape EMPTY = new ArrayVoxelShape(new BitSetDiscreteVoxelShape(0, 0, 0), (DoubleList)(new DoubleArrayList(new double[]{0.0D})), (DoubleList)(new DoubleArrayList(new double[]{0.0D})), (DoubleList)(new DoubleArrayList(new double[]{0.0D})));
public static final VoxelShape INFINITY = box(
Double.NEGATIVE_INFINITY,
@@ -0,0 +0,0 @@ public final class Shapes {
new DoubleArrayList(new double[]{0.0})
);
+ // Paper start - optimise collisions - force arrayvoxelshape
+ private static final DoubleArrayList[] PARTS_BY_BITS = new DoubleArrayList[] {
@@ -3588,13 +3593,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
@@ -0,0 +0,0 @@ public final class Shapes {
public static VoxelShape create(double minX, double minY, double minZ, double maxX, double maxY, double maxZ) {
if (!(maxX - minX < 1.0E-7D) && !(maxY - minY < 1.0E-7D) && !(maxZ - minZ < 1.0E-7D)) {
if (!(maxX - minX < 1.0E-7) && !(maxY - minY < 1.0E-7) && !(maxZ - minZ < 1.0E-7)) {
- int i = findBits(minX, maxX);
- int j = findBits(minY, maxY);
- int k = findBits(minZ, maxZ);
- if (i >= 0 && j >= 0 && k >= 0) {
- if (i == 0 && j == 0 && k == 0) {
- return block();
- if (i < 0 || j < 0 || k < 0) {
- return new ArrayVoxelShape(
- BLOCK.shape,
- DoubleArrayList.wrap(new double[]{minX, maxX}),
- DoubleArrayList.wrap(new double[]{minY, maxY}),
- DoubleArrayList.wrap(new double[]{minZ, maxZ})
- );
- } else if (i == 0 && j == 0 && k == 0) {
- return block();
+ // Paper start - optimise collisions
+ // force ArrayVoxelShape in every case
+ final int bitsX = findBits(minX, maxX);
@@ -3603,12 +3614,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (bitsX >= 0 && bitsY >= 0 && bitsZ >= 0) {
+ if (bitsX == 0 && bitsY == 0 && bitsZ == 0) {
+ return BLOCK;
} else {
- int l = 1 << i;
- int m = 1 << j;
- int n = 1 << k;
- BitSetDiscreteVoxelShape bitSetDiscreteVoxelShape = BitSetDiscreteVoxelShape.withFilledBounds(l, m, n, (int)Math.round(minX * (double)l), (int)Math.round(minY * (double)m), (int)Math.round(minZ * (double)n), (int)Math.round(maxX * (double)l), (int)Math.round(maxY * (double)m), (int)Math.round(maxZ * (double)n));
- return new CubeVoxelShape(bitSetDiscreteVoxelShape);
+ } else {
+ final int sizeX = 1 << bitsX;
+ final int sizeY = 1 << bitsY;
+ final int sizeZ = 1 << bitsZ;
@@ -3623,15 +3629,28 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ PARTS_BY_BITS[bitsY],
+ PARTS_BY_BITS[bitsZ]
+ );
}
+ }
} else {
- return new ArrayVoxelShape(BLOCK.shape, (DoubleList)DoubleArrayList.wrap(new double[]{minX, maxX}), (DoubleList)DoubleArrayList.wrap(new double[]{minY, maxY}), (DoubleList)DoubleArrayList.wrap(new double[]{minZ, maxZ}));
- int l = 1 << i;
- int m = 1 << j;
- int n = 1 << k;
- BitSetDiscreteVoxelShape bitSetDiscreteVoxelShape = BitSetDiscreteVoxelShape.withFilledBounds(
- l,
- m,
- n,
- (int)Math.round(minX * l),
- (int)Math.round(minY * m),
- (int)Math.round(minZ * n),
- (int)Math.round(maxX * l),
- (int)Math.round(maxY * m),
- (int)Math.round(maxZ * n)
+ return new ArrayVoxelShape(
+ BLOCK.shape,
+ minX == 0.0 && maxX == 1.0 ? io.papermc.paper.util.CollisionUtil.ZERO_ONE : DoubleArrayList.wrap(new double[] { minX, maxX }),
+ minY == 0.0 && maxY == 1.0 ? io.papermc.paper.util.CollisionUtil.ZERO_ONE : DoubleArrayList.wrap(new double[] { minY, maxY }),
+ minZ == 0.0 && maxZ == 1.0 ? io.papermc.paper.util.CollisionUtil.ZERO_ONE : DoubleArrayList.wrap(new double[] { minZ, maxZ })
+ );
);
- return new CubeVoxelShape(bitSetDiscreteVoxelShape);
}
+ // Paper end - optimise collisions
} else {
@@ -3699,9 +3718,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- } else {
- IndexMerger indexMerger = createIndexMerger(1, one.getCoords(Direction.Axis.X), two.getCoords(Direction.Axis.X), bl, bl2);
- IndexMerger indexMerger2 = createIndexMerger(indexMerger.size() - 1, one.getCoords(Direction.Axis.Y), two.getCoords(Direction.Axis.Y), bl, bl2);
- IndexMerger indexMerger3 = createIndexMerger((indexMerger.size() - 1) * (indexMerger2.size() - 1), one.getCoords(Direction.Axis.Z), two.getCoords(Direction.Axis.Z), bl, bl2);
- BitSetDiscreteVoxelShape bitSetDiscreteVoxelShape = BitSetDiscreteVoxelShape.join(one.shape, two.shape, indexMerger, indexMerger2, indexMerger3, function);
- return (VoxelShape)(indexMerger instanceof DiscreteCubeMerger && indexMerger2 instanceof DiscreteCubeMerger && indexMerger3 instanceof DiscreteCubeMerger ? new CubeVoxelShape(bitSetDiscreteVoxelShape) : new ArrayVoxelShape(bitSetDiscreteVoxelShape, indexMerger.getList(), indexMerger2.getList(), indexMerger3.getList()));
- IndexMerger indexMerger3 = createIndexMerger(
- (indexMerger.size() - 1) * (indexMerger2.size() - 1), one.getCoords(Direction.Axis.Z), two.getCoords(Direction.Axis.Z), bl, bl2
- );
- BitSetDiscreteVoxelShape bitSetDiscreteVoxelShape = BitSetDiscreteVoxelShape.join(
- one.shape, two.shape, indexMerger, indexMerger2, indexMerger3, function
- );
- return (VoxelShape)(indexMerger instanceof DiscreteCubeMerger
- && indexMerger2 instanceof DiscreteCubeMerger
- && indexMerger3 instanceof DiscreteCubeMerger
- ? new CubeVoxelShape(bitSetDiscreteVoxelShape)
- : new ArrayVoxelShape(bitSetDiscreteVoxelShape, indexMerger.getList(), indexMerger2.getList(), indexMerger3.getList()));
- }
- }
+ return io.papermc.paper.util.CollisionUtil.joinUnoptimized(one, two, function); // Paper - optimise collisions
@@ -3720,19 +3747,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- boolean bl3 = predicate.apply(true, false);
- boolean bl4 = predicate.apply(false, true);
-
- for(Direction.Axis axis : AxisCycle.AXIS_VALUES) {
- if (shape1.max(axis) < shape2.min(axis) - 1.0E-7D) {
- for (Direction.Axis axis : AxisCycle.AXIS_VALUES) {
- if (shape1.max(axis) < shape2.min(axis) - 1.0E-7) {
- return bl3 || bl4;
- }
-
- if (shape2.max(axis) < shape1.min(axis) - 1.0E-7D) {
- if (shape2.max(axis) < shape1.min(axis) - 1.0E-7) {
- return bl3 || bl4;
- }
- }
-
- IndexMerger indexMerger = createIndexMerger(1, shape1.getCoords(Direction.Axis.X), shape2.getCoords(Direction.Axis.X), bl3, bl4);
- IndexMerger indexMerger2 = createIndexMerger(indexMerger.size() - 1, shape1.getCoords(Direction.Axis.Y), shape2.getCoords(Direction.Axis.Y), bl3, bl4);
- IndexMerger indexMerger3 = createIndexMerger((indexMerger.size() - 1) * (indexMerger2.size() - 1), shape1.getCoords(Direction.Axis.Z), shape2.getCoords(Direction.Axis.Z), bl3, bl4);
- IndexMerger indexMerger2 = createIndexMerger(
- indexMerger.size() - 1, shape1.getCoords(Direction.Axis.Y), shape2.getCoords(Direction.Axis.Y), bl3, bl4
- );
- IndexMerger indexMerger3 = createIndexMerger(
- (indexMerger.size() - 1) * (indexMerger2.size() - 1), shape1.getCoords(Direction.Axis.Z), shape2.getCoords(Direction.Axis.Z), bl3, bl4
- );
- return joinIsNotEmpty(indexMerger, indexMerger2, indexMerger3, shape1.shape, shape2.shape, predicate);
- }
- } else {
@@ -3742,7 +3773,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return io.papermc.paper.util.CollisionUtil.isJoinNonEmpty(shape1, shape2, predicate); // Paper - optimise collisions
}
private static boolean joinIsNotEmpty(IndexMerger mergedX, IndexMerger mergedY, IndexMerger mergedZ, DiscreteVoxelShape shape1, DiscreteVoxelShape shape2, BooleanOp predicate) {
private static boolean joinIsNotEmpty(
@@ -0,0 +0,0 @@ public final class Shapes {
}
@@ -3758,6 +3789,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+
+ if (shape.isEmpty() | neighbor.isEmpty()) {
+ return false;
+ }
+
+ // we optimise getOpposite, so we can use it
+ // secondly, use our cache to retrieve sliced shape
+ final VoxelShape newFirst = shape.getFaceShapeClamped(direction);
+ if (newFirst.isEmpty()) {
return false;
- } else {
- Direction.Axis axis = direction.getAxis();
@@ -3765,15 +3803,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- VoxelShape voxelShape = axisDirection == Direction.AxisDirection.POSITIVE ? shape : neighbor;
- VoxelShape voxelShape2 = axisDirection == Direction.AxisDirection.POSITIVE ? neighbor : shape;
- BooleanOp booleanOp = axisDirection == Direction.AxisDirection.POSITIVE ? BooleanOp.ONLY_FIRST : BooleanOp.ONLY_SECOND;
- return DoubleMath.fuzzyEquals(voxelShape.max(axis), 1.0D, 1.0E-7D) && DoubleMath.fuzzyEquals(voxelShape2.min(axis), 0.0D, 1.0E-7D) && !joinIsNotEmpty(new SliceShape(voxelShape, axis, voxelShape.shape.getSize(axis) - 1), new SliceShape(voxelShape2, axis, 0), booleanOp);
- return DoubleMath.fuzzyEquals(voxelShape.max(axis), 1.0, 1.0E-7)
- && DoubleMath.fuzzyEquals(voxelShape2.min(axis), 0.0, 1.0E-7)
- && !joinIsNotEmpty(new SliceShape(voxelShape, axis, voxelShape.shape.getSize(axis) - 1), new SliceShape(voxelShape2, axis, 0), booleanOp);
}
+
+ // we optimise getOpposite, so we can use it
+ // secondly, use our cache to retrieve sliced shape
+ final VoxelShape newFirst = shape.getFaceShapeClamped(direction);
+ if (newFirst.isEmpty()) {
+ return false;
+ }
+ final VoxelShape newSecond = neighbor.getFaceShapeClamped(direction.getOpposite());
+ if (newSecond.isEmpty()) {
+ return false;
@@ -3791,10 +3824,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- boolean bl;
- int i;
- if (direction.getAxisDirection() == Direction.AxisDirection.POSITIVE) {
- bl = DoubleMath.fuzzyEquals(shape.max(axis), 1.0D, 1.0E-7D);
- bl = DoubleMath.fuzzyEquals(shape.max(axis), 1.0, 1.0E-7);
- i = shape.shape.getSize(axis) - 1;
- } else {
- bl = DoubleMath.fuzzyEquals(shape.min(axis), 0.0D, 1.0E-7D);
- bl = DoubleMath.fuzzyEquals(shape.min(axis), 0.0, 1.0E-7);
- i = 0;
- }
+ return shape.getFaceShapeClamped(direction); // Paper - optimise collisions
@@ -3828,7 +3861,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- Direction.AxisDirection axisDirection = direction.getAxisDirection();
- VoxelShape voxelShape = axisDirection == Direction.AxisDirection.POSITIVE ? one : two;
- VoxelShape voxelShape2 = axisDirection == Direction.AxisDirection.POSITIVE ? two : one;
- if (!DoubleMath.fuzzyEquals(voxelShape.max(axis), 1.0D, 1.0E-7D)) {
- if (!DoubleMath.fuzzyEquals(voxelShape.max(axis), 1.0, 1.0E-7)) {
- voxelShape = empty();
- }
+ // Paper start - optimise collisions
@@ -3837,14 +3870,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return true;
+ }
- if (!DoubleMath.fuzzyEquals(voxelShape2.min(axis), 0.0D, 1.0E-7D)) {
- if (!DoubleMath.fuzzyEquals(voxelShape2.min(axis), 0.0, 1.0E-7)) {
- voxelShape2 = empty();
- }
+ if (one.isEmpty() & two.isEmpty()) {
+ return false;
+ }
- return !joinIsNotEmpty(block(), joinUnoptimized(new SliceShape(voxelShape, axis, voxelShape.shape.getSize(axis) - 1), new SliceShape(voxelShape2, axis, 0), BooleanOp.OR), BooleanOp.ONLY_FIRST);
- return !joinIsNotEmpty(
- block(),
- joinUnoptimized(new SliceShape(voxelShape, axis, voxelShape.shape.getSize(axis) - 1), new SliceShape(voxelShape2, axis, 0), BooleanOp.OR),
- BooleanOp.ONLY_FIRST
- );
- } else {
+ // we optimise getOpposite, so we can use it
+ // secondly, use our cache to retrieve sliced shape
@@ -3876,17 +3913,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
public static boolean faceShapeOccludes(VoxelShape one, VoxelShape two) {
- if (one != block() && two != block()) {
- if (one.isEmpty() && two.isEmpty()) {
- return false;
- } else {
- return !joinIsNotEmpty(block(), joinUnoptimized(one, two, BooleanOp.OR), BooleanOp.ONLY_FIRST);
- }
- } else {
- return one == block()
- || two == block()
- || (!one.isEmpty() || !two.isEmpty()) && !joinIsNotEmpty(block(), joinUnoptimized(one, two, BooleanOp.OR), BooleanOp.ONLY_FIRST);
+ // Paper start - optimise collisions
+ if (one.occludesFullBlockIfCached() || two.occludesFullBlockIfCached()) {
return true;
}
+ return true;
+ }
+
+ final boolean s1Empty = one.isEmpty();
+ final boolean s2Empty = two.isEmpty();
@@ -3937,7 +3970,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ private double offsetX;
+ private double offsetY;
+ private double offsetZ;
+ private AABB singleAABBRepresentation;
+ @Nullable private AABB singleAABBRepresentation;
+ private double[] rootCoordinatesX;
+ private double[] rootCoordinatesY;
+ private double[] rootCoordinatesZ;
@@ -4335,15 +4368,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- if (this.isEmpty()) {
- throw (UnsupportedOperationException)Util.pauseInIde(new UnsupportedOperationException("No bounds for empty shape."));
- } else {
- return new AABB(this.min(Direction.Axis.X), this.min(Direction.Axis.Y), this.min(Direction.Axis.Z), this.max(Direction.Axis.X), this.max(Direction.Axis.Y), this.max(Direction.Axis.Z));
- return new AABB(
- this.min(Direction.Axis.X),
- this.min(Direction.Axis.Y),
- this.min(Direction.Axis.Z),
- this.max(Direction.Axis.X),
- this.max(Direction.Axis.Y),
- this.max(Direction.Axis.Z)
- );
+ // Paper start - optimise collisions
+ if (this.isEmpty) {
+ throw Util.pauseInIde(new UnsupportedOperationException("No bounds for empty shape."));
}
+ }
+ AABB cached = this.cachedBounds;
+ if (cached != null) {
+ return cached;
+ }
}
+
+ final io.papermc.paper.util.collisions.CachedShapeData shapeData = this.cachedShapeData;
+
@@ -4378,26 +4418,32 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public boolean isEmpty() {
- return this.shape.isEmpty();
+ return this.isEmpty; // Paper - optimise collisions
}
+ }
+
+ // Paper start - optimise collisions
+ private static DoubleList offsetList(final DoubleList src, final double by) {
+ if (src instanceof OffsetDoubleList offsetDoubleList) {
+ return new OffsetDoubleList(offsetDoubleList.delegate, by + offsetDoubleList.offset);
+ }
+ return new OffsetDoubleList(src, by);
+ }
}
+ // Paper end - optimise collisions
+
public VoxelShape move(double x, double y, double z) {
- return (VoxelShape)(this.isEmpty() ? Shapes.empty() : new ArrayVoxelShape(this.shape, (DoubleList)(new OffsetDoubleList(this.getCoords(Direction.Axis.X), x)), (DoubleList)(new OffsetDoubleList(this.getCoords(Direction.Axis.Y), y)), (DoubleList)(new OffsetDoubleList(this.getCoords(Direction.Axis.Z), z))));
- return (VoxelShape)(this.isEmpty()
- ? Shapes.empty()
- : new ArrayVoxelShape(
+ // Paper start - optimise collisions
+ if (this.isEmpty) {
+ return Shapes.empty();
+ }
+
+ final ArrayVoxelShape ret = new ArrayVoxelShape(
+ this.shape,
this.shape,
- new OffsetDoubleList(this.getCoords(Direction.Axis.X), x),
- new OffsetDoubleList(this.getCoords(Direction.Axis.Y), y),
- new OffsetDoubleList(this.getCoords(Direction.Axis.Z), z)
- ));
+ offsetList(this.getCoords(Direction.Axis.X), x),
+ offsetList(this.getCoords(Direction.Axis.Y), y),
+ offsetList(this.getCoords(Direction.Axis.Z), z)
@@ -4414,9 +4460,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public VoxelShape optimize() {
- VoxelShape[] voxelShapes = new VoxelShape[]{Shapes.empty()};
- this.forAllBoxes((minX, minY, minZ, maxX, maxY, maxZ) -> {
- voxelShapes[0] = Shapes.joinUnoptimized(voxelShapes[0], Shapes.box(minX, minY, minZ, maxX, maxY, maxZ), BooleanOp.OR);
- });
- this.forAllBoxes(
- (minX, minY, minZ, maxX, maxY, maxZ) -> voxelShapes[0] = Shapes.joinUnoptimized(
- voxelShapes[0], Shapes.box(minX, minY, minZ, maxX, maxY, maxZ), BooleanOp.OR
- )
- );
- return voxelShapes[0];
+ // Paper start - optimise collisions
+ // Optimise merge strategy to increase the number of simple joins, and additionally forward the toAabbs cache
@@ -4487,7 +4535,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public void forAllEdges(Shapes.DoubleLineConsumer consumer) {
@@ -0,0 +0,0 @@ public abstract class VoxelShape {
}, true);
);
}
+ // Paper start - optimise collisions
@@ -4510,9 +4558,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
public List<AABB> toAabbs() {
- List<AABB> list = Lists.newArrayList();
- this.forAllBoxes((x1, y1, z1, x2, y2, z2) -> {
- list.add(new AABB(x1, y1, z1, x2, y2, z2));
- });
- this.forAllBoxes((x1, y1, z1, x2, y2, z2) -> list.add(new AABB(x1, y1, z1, x2, y2, z2)));
- return list;
+ // Paper start - optimise collisions
+ io.papermc.paper.util.collisions.CachedToAABBs cachedToAABBs = this.cachedToAABBs;
@@ -4536,7 +4582,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public double min(Direction.Axis axis, double from, double to) {
@@ -0,0 +0,0 @@ public abstract class VoxelShape {
}) - 1;
return Mth.binarySearch(0, this.shape.getSize(axis) + 1, i -> coord < this.get(axis, i)) - 1;
}
+ // Paper start - optimise collisions
@@ -4568,11 +4614,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
return null;
- } else {
- Vec3 vec3 = end.subtract(start);
- if (vec3.lengthSqr() < 1.0E-7D) {
- if (vec3.lengthSqr() < 1.0E-7) {
- return null;
- } else {
- Vec3 vec32 = start.add(vec3.scale(0.001D));
- return this.shape.isFullWide(this.findIndex(Direction.Axis.X, vec32.x - (double)pos.getX()), this.findIndex(Direction.Axis.Y, vec32.y - (double)pos.getY()), this.findIndex(Direction.Axis.Z, vec32.z - (double)pos.getZ())) ? new BlockHitResult(vec32, Direction.getNearest(vec3.x, vec3.y, vec3.z).getOpposite(), pos, true) : AABB.clip(this.toAabbs(), start, end, pos);
- Vec3 vec32 = start.add(vec3.scale(0.001));
- return this.shape
- .isFullWide(
- this.findIndex(Direction.Axis.X, vec32.x - pos.getX()),
- this.findIndex(Direction.Axis.Y, vec32.y - pos.getY()),
- this.findIndex(Direction.Axis.Z, vec32.z - pos.getZ())
- )
- ? new BlockHitResult(vec32, Direction.getNearest(vec3.x, vec3.y, vec3.z).getOpposite(), pos, true)
- : AABB.clip(this.toAabbs(), start, end, pos);
+ }
+
+ final Vec3 directionOpposite = end.subtract(start);
@@ -4615,10 +4668,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- if (vec3s[0] == null || target.distanceToSqr(d, e, f) < target.distanceToSqr(vec3s[0])) {
- vec3s[0] = new Vec3(d, e, f);
- }
+ }
- });
- return Optional.of(vec3s[0]);
}
+
+ Vec3 ret = null;
+ double retDistance = Double.MAX_VALUE;
+
@@ -4634,7 +4687,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ ret = new Vec3(x, y, z);
+ retDistance = dist;
+ }
}
+ }
+
+ return Optional.ofNullable(ret);
+ // Paper end - optimise collisions