aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTonytheMacaroni <[email protected]>2023-11-04 18:00:51 -0400
committerGitHub <[email protected]>2023-11-04 15:00:51 -0700
commit23860da6c2f306fdc598fb0d09132636c7141dfd (patch)
tree612c364ffabbefde18c9ed2680583c240075ba94
parent8a3980c60bd09eb1d0d21bfc846181a49c0d74df (diff)
downloadPaper-23860da6c2f306fdc598fb0d09132636c7141dfd.tar.gz
Paper-23860da6c2f306fdc598fb0d09132636c7141dfd.zip
Add predicate for block when raytracing (#9691)
* Add predicate for block data when raytracing blocks * Match based on block, instead of block data * Use instanceof instead of casting * Use Position instead of Location, add overload for rayTraceEntities * Implement requested changes * Invert predicate * Cleanup
-rw-r--r--patches/api/0009-Add-Position.patch20
-rw-r--r--patches/api/0444-Add-predicate-for-blocks-when-raytracing.patch119
-rw-r--r--patches/server/0009-MC-Utils.patch8
-rw-r--r--patches/server/0018-Rewrite-chunk-system.patch4
-rw-r--r--patches/server/0267-Catch-JsonParseException-in-Entity-and-TE-names.patch4
-rw-r--r--patches/server/1042-Add-predicate-for-blocks-when-raytracing.patch116
6 files changed, 261 insertions, 10 deletions
diff --git a/patches/api/0009-Add-Position.patch b/patches/api/0009-Add-Position.patch
index 4d6b5f241e..c56e4e0a0e 100644
--- a/patches/api/0009-Add-Position.patch
+++ b/patches/api/0009-Add-Position.patch
@@ -192,10 +192,10 @@ index 0000000000000000000000000000000000000000..93476aaf8d21efb5a30b6d2cc2eeda81
+}
diff --git a/src/main/java/io/papermc/paper/math/Position.java b/src/main/java/io/papermc/paper/math/Position.java
new file mode 100644
-index 0000000000000000000000000000000000000000..300da713dcc303b340efad70efe57facf5422964
+index 0000000000000000000000000000000000000000..26bc5a0fa67855af87c8fd4cd8229b4d9f242740
--- /dev/null
+++ b/src/main/java/io/papermc/paper/math/Position.java
-@@ -0,0 +1,184 @@
+@@ -0,0 +1,191 @@
+package io.papermc.paper.math;
+
+import org.bukkit.Location;
@@ -273,6 +273,13 @@ index 0000000000000000000000000000000000000000..300da713dcc303b340efad70efe57fac
+ boolean isFine();
+
+ /**
++ * Checks if each component of this position is finite.
++ */
++ default boolean isFinite() {
++ return Double.isFinite(this.x()) && Double.isFinite(this.y()) && Double.isFinite(this.z());
++ }
++
++ /**
+ * Returns a position offset by the specified amounts.
+ *
+ * @param x x value to offset
@@ -381,7 +388,7 @@ index 0000000000000000000000000000000000000000..300da713dcc303b340efad70efe57fac
+ }
+}
diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java
-index 7c4db051472fb6a6c6d24092dc6f75487356690a..3b99f359f556e6f2c341d55fa69b7462e69b6546 100644
+index 7c4db051472fb6a6c6d24092dc6f75487356690a..85c342fc50f2fe0ce9a1b3980df9e088c3dea92d 100644
--- a/src/main/java/org/bukkit/Location.java
+++ b/src/main/java/org/bukkit/Location.java
@@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable;
@@ -393,7 +400,7 @@ index 7c4db051472fb6a6c6d24092dc6f75487356690a..3b99f359f556e6f2c341d55fa69b7462
private Reference<World> world;
private double x;
private double y;
-@@ -706,4 +706,26 @@ public class Location implements Cloneable, ConfigurationSerializable {
+@@ -706,4 +706,31 @@ public class Location implements Cloneable, ConfigurationSerializable {
}
return pitch;
}
@@ -415,6 +422,11 @@ index 7c4db051472fb6a6c6d24092dc6f75487356690a..3b99f359f556e6f2c341d55fa69b7462
+ }
+
+ @Override
++ public boolean isFinite() {
++ return io.papermc.paper.math.FinePosition.super.isFinite() && Float.isFinite(this.getYaw()) && Float.isFinite(this.getPitch());
++ }
++
++ @Override
+ public @NotNull Location toLocation(@NotNull World world) {
+ return new Location(world, this.x(), this.y(), this.z(), this.getYaw(), this.getPitch());
+ }
diff --git a/patches/api/0444-Add-predicate-for-blocks-when-raytracing.patch b/patches/api/0444-Add-predicate-for-blocks-when-raytracing.patch
new file mode 100644
index 0000000000..9186690f18
--- /dev/null
+++ b/patches/api/0444-Add-predicate-for-blocks-when-raytracing.patch
@@ -0,0 +1,119 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: TonytheMacaroni <[email protected]>
+Date: Wed, 6 Sep 2023 19:24:53 -0400
+Subject: [PATCH] Add predicate for blocks when raytracing
+
+
+diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
+index 91eb95b04094394e8dc1e3a3343efc63690c87e4..17d404d6d1a5b46b58d612fca38f17e71adee92e 100644
+--- a/src/main/java/org/bukkit/World.java
++++ b/src/main/java/org/bukkit/World.java
+@@ -1714,6 +1714,28 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
+ @Nullable
+ public RayTraceResult rayTraceEntities(@NotNull Location start, @NotNull Vector direction, double maxDistance, double raySize, @Nullable Predicate<Entity> filter);
+
++ // Paper start
++ /**
++ * Performs a ray trace that checks for entity collisions.
++ * <p>
++ * This may not consider entities in currently unloaded chunks. Some
++ * implementations may impose artificial restrictions on the maximum
++ * distance.
++ *
++ * @param start the start position
++ * @param direction the ray direction
++ * @param maxDistance the maximum distance
++ * @param raySize entity bounding boxes will be uniformly expanded (or
++ * shrinked) by this value before doing collision checks
++ * @param filter only entities that fulfill this predicate are considered,
++ * or <code>null</code> to consider all entities
++ * @return the closest ray trace hit result, or <code>null</code> if there
++ * is no hit
++ */
++ @Nullable
++ public RayTraceResult rayTraceEntities(@NotNull io.papermc.paper.math.Position start, @NotNull Vector direction, double maxDistance, double raySize, @Nullable Predicate<Entity> filter);
++ // Paper end
++
+ /**
+ * Performs a ray trace that checks for block collisions using the blocks'
+ * precise collision shapes.
+@@ -1777,6 +1799,35 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
+ @Nullable
+ public RayTraceResult rayTraceBlocks(@NotNull Location start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks);
+
++ // Paper start
++ /**
++ * Performs a ray trace that checks for block collisions using the blocks'
++ * precise collision shapes.
++ * <p>
++ * If collisions with passable blocks are ignored, fluid collisions are
++ * ignored as well regardless of the fluid collision mode.
++ * <p>
++ * Portal blocks are only considered passable if the ray starts within
++ * them. Apart from that collisions with portal blocks will be considered
++ * even if collisions with passable blocks are otherwise ignored.
++ * <p>
++ * This may cause loading of chunks! Some implementations may impose
++ * artificial restrictions on the maximum distance.
++ *
++ * @param start the start position
++ * @param direction the ray direction
++ * @param maxDistance the maximum distance
++ * @param fluidCollisionMode the fluid collision mode
++ * @param ignorePassableBlocks whether to ignore passable but collidable
++ * blocks (ex. tall grass, signs, fluids, ..)
++ * @param canCollide predicate for blocks the ray can potentially collide
++ * with, or <code>null</code> to consider all blocks
++ * @return the ray trace hit result, or <code>null</code> if there is no hit
++ */
++ @Nullable
++ public RayTraceResult rayTraceBlocks(@NotNull io.papermc.paper.math.Position start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, @Nullable Predicate<Block> canCollide);
++ // Paper end
++
+ /**
+ * Performs a ray trace that checks for both block and entity collisions.
+ * <p>
+@@ -1810,6 +1861,43 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
+ @Nullable
+ public RayTraceResult rayTrace(@NotNull Location start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, @Nullable Predicate<Entity> filter);
+
++ // Paper start
++ /**
++ * Performs a ray trace that checks for both block and entity collisions.
++ * <p>
++ * Block collisions use the blocks' precise collision shapes. The
++ * <code>raySize</code> parameter is only taken into account for entity
++ * collision checks.
++ * <p>
++ * If collisions with passable blocks are ignored, fluid collisions are
++ * ignored as well regardless of the fluid collision mode.
++ * <p>
++ * Portal blocks are only considered passable if the ray starts within them.
++ * Apart from that collisions with portal blocks will be considered even if
++ * collisions with passable blocks are otherwise ignored.
++ * <p>
++ * This may cause loading of chunks! Some implementations may impose
++ * artificial restrictions on the maximum distance.
++ *
++ * @param start the start position
++ * @param direction the ray direction
++ * @param maxDistance the maximum distance
++ * @param fluidCollisionMode the fluid collision mode
++ * @param ignorePassableBlocks whether to ignore passable but collidable
++ * blocks (ex. tall grass, signs, fluids, ..)
++ * @param raySize entity bounding boxes will be uniformly expanded (or
++ * shrinked) by this value before doing collision checks
++ * @param filter only entities that fulfill this predicate are considered,
++ * or <code>null</code> to consider all entities
++ * @param canCollide predicate for blocks the ray can potentially collide
++ * with, or <code>null</code> to consider all blocks
++ * @return the closest ray trace hit result with either a block or an
++ * entity, or <code>null</code> if there is no hit
++ */
++ @Nullable
++ public RayTraceResult rayTrace(@NotNull io.papermc.paper.math.Position start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, @Nullable Predicate<Entity> filter, @Nullable Predicate<Block> canCollide);
++ // Paper end
++
+ /**
+ * Gets the default spawn {@link Location} of this world
+ *
diff --git a/patches/server/0009-MC-Utils.patch b/patches/server/0009-MC-Utils.patch
index c25d9309cd..0850a593eb 100644
--- a/patches/server/0009-MC-Utils.patch
+++ b/patches/server/0009-MC-Utils.patch
@@ -3480,10 +3480,10 @@ index 0000000000000000000000000000000000000000..cea9c098ade00ee87b8efc8164ab72f5
+}
diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java
new file mode 100644
-index 0000000000000000000000000000000000000000..9572294a50110f2452090da1f32e0a73edc3db05
+index 0000000000000000000000000000000000000000..19708dee02491e74fb3db6e70911e20a57b09769
--- /dev/null
+++ b/src/main/java/io/papermc/paper/util/MCUtil.java
-@@ -0,0 +1,534 @@
+@@ -0,0 +1,538 @@
+package io.papermc.paper.util;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
@@ -3972,6 +3972,10 @@ index 0000000000000000000000000000000000000000..9572294a50110f2452090da1f32e0a73
+ return Position.block(vector.getX(), vector.getY(), vector.getZ());
+ }
+
++ public static Vec3 toVec3(Position position) {
++ return new Vec3(position.x(), position.y(), position.z());
++ }
++
+ public static boolean isEdgeOfChunk(BlockPos pos) {
+ final int modX = pos.getX() & 15;
+ final int modZ = pos.getZ() & 15;
diff --git a/patches/server/0018-Rewrite-chunk-system.patch b/patches/server/0018-Rewrite-chunk-system.patch
index 58890d5471..1a6f07cd6b 100644
--- a/patches/server/0018-Rewrite-chunk-system.patch
+++ b/patches/server/0018-Rewrite-chunk-system.patch
@@ -15723,7 +15723,7 @@ index cea9c098ade00ee87b8efc8164ab72f5279758f0..197224e31175252d8438a8df585bbb65
+ }
}
diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java
-index 9572294a50110f2452090da1f32e0a73edc3db05..dc2ab968ed010289125ac08f0a9ea85af6f6e8bb 100644
+index 19708dee02491e74fb3db6e70911e20a57b09769..395873f89925b495978d151efe1d91da9ad11b0a 100644
--- a/src/main/java/io/papermc/paper/util/MCUtil.java
+++ b/src/main/java/io/papermc/paper/util/MCUtil.java
@@ -4,17 +4,30 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
@@ -15769,7 +15769,7 @@ index 9572294a50110f2452090da1f32e0a73edc3db05..dc2ab968ed010289125ac08f0a9ea85a
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingQueue;
-@@ -528,6 +544,100 @@ public final class MCUtil {
+@@ -532,6 +548,100 @@ public final class MCUtil {
}
}
diff --git a/patches/server/0267-Catch-JsonParseException-in-Entity-and-TE-names.patch b/patches/server/0267-Catch-JsonParseException-in-Entity-and-TE-names.patch
index 50b2539679..4555657f95 100644
--- a/patches/server/0267-Catch-JsonParseException-in-Entity-and-TE-names.patch
+++ b/patches/server/0267-Catch-JsonParseException-in-Entity-and-TE-names.patch
@@ -13,10 +13,10 @@ Shulkers) may need to be changed in order for it to re-save properly
No more crashing though.
diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java
-index 82a1a87822e3fc323b92e1aa30ddb0cdb351d89c..d02546b18cb689724887b4e85e8d32a18828a4ad 100644
+index e969a0acf06d9265fa75fc07bb637752df468c11..8240bb085b619f257f8c0a25775e0b15068e440f 100644
--- a/src/main/java/io/papermc/paper/util/MCUtil.java
+++ b/src/main/java/io/papermc/paper/util/MCUtil.java
-@@ -648,4 +648,19 @@ public final class MCUtil {
+@@ -652,4 +652,19 @@ public final class MCUtil {
public static int getTicketLevelFor(net.minecraft.world.level.chunk.ChunkStatus status) {
return net.minecraft.server.level.ChunkMap.MAX_VIEW_DISTANCE + net.minecraft.world.level.chunk.ChunkStatus.getDistance(status);
}
diff --git a/patches/server/1042-Add-predicate-for-blocks-when-raytracing.patch b/patches/server/1042-Add-predicate-for-blocks-when-raytracing.patch
new file mode 100644
index 0000000000..f31f9be2f6
--- /dev/null
+++ b/patches/server/1042-Add-predicate-for-blocks-when-raytracing.patch
@@ -0,0 +1,116 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: TonytheMacaroni <[email protected]>
+Date: Wed, 6 Sep 2023 19:24:16 -0400
+Subject: [PATCH] Add predicate for blocks when raytracing
+
+
+diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java
+index 799837c172a5f7856c78e6fe2595c575f3058a5e..e2066c52941d20fe01d3381181c3e5bf2d2ccb9a 100644
+--- a/src/main/java/net/minecraft/world/level/BlockGetter.java
++++ b/src/main/java/net/minecraft/world/level/BlockGetter.java
+@@ -83,6 +83,12 @@ public interface BlockGetter extends LevelHeightAccessor {
+
+ // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace
+ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) {
++ // Paper start
++ return clip(raytrace1, blockposition, null);
++ }
++
++ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition, java.util.function.Predicate<org.bukkit.block.Block> canCollide) {
++ // Paper end
+ // Paper start - Prevent raytrace from loading chunks
+ BlockState iblockdata = this.getBlockStateIfLoaded(blockposition);
+ if (iblockdata == null) {
+@@ -92,7 +98,7 @@ public interface BlockGetter extends LevelHeightAccessor {
+ return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo()));
+ }
+ // Paper end
+- if (iblockdata.isAir()) return null; // Paper - optimise air cases
++ if (iblockdata.isAir() || (canCollide != null && this instanceof LevelAccessor levelAccessor && !canCollide.test(org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, blockposition)))) return null; // Paper - optimise air cases and check canCollide predicate
+ FluidState fluid = iblockdata.getFluidState(); // Paper - don't need to go to world state again
+ Vec3 vec3d = raytrace1.getFrom();
+ Vec3 vec3d1 = raytrace1.getTo();
+@@ -108,8 +114,14 @@ public interface BlockGetter extends LevelHeightAccessor {
+ // CraftBukkit end
+
+ default BlockHitResult clip(ClipContext context) {
++ // Paper start
++ return clip(context, (java.util.function.Predicate<org.bukkit.block.Block>) null);
++ }
++
++ default BlockHitResult clip(ClipContext context, java.util.function.Predicate<org.bukkit.block.Block> canCollide) {
++ // Paper end
+ return (BlockHitResult) BlockGetter.traverseBlocks(context.getFrom(), context.getTo(), context, (raytrace1, blockposition) -> {
+- return this.clip(raytrace1, blockposition); // CraftBukkit - moved into separate method
++ return this.clip(raytrace1, blockposition, canCollide); // CraftBukkit - moved into separate method // Paper - use method with canCollide predicate
+ }, (raytrace1) -> {
+ Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo());
+
+diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+index 5e350fa39f47d54f6048ea89c1317759f122b8ae..746f88db6b78b3c8ec372bfaacb26ec98f3b1163 100644
+--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+@@ -1118,9 +1118,15 @@ public class CraftWorld extends CraftRegionAccessor implements World {
+
+ @Override
+ public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, double raySize, Predicate<Entity> filter) {
++ // Paper start
++ return rayTraceEntities((io.papermc.paper.math.Position) start, direction, maxDistance, raySize, filter);
++ }
++
++ public RayTraceResult rayTraceEntities(io.papermc.paper.math.Position start, Vector direction, double maxDistance, double raySize, Predicate<Entity> filter) {
+ Preconditions.checkArgument(start != null, "Location start cannot be null");
+- Preconditions.checkArgument(this.equals(start.getWorld()), "Location start cannot be in a different world");
+- start.checkFinite();
++ Preconditions.checkArgument(!(start instanceof Location location) || this.equals(location.getWorld()), "Location start cannot be in a different world");
++ Preconditions.checkArgument(start.isFinite(), "Location start is not finite");
++ // Paper end
+
+ Preconditions.checkArgument(direction != null, "Vector direction cannot be null");
+ direction.checkFinite();
+@@ -1170,9 +1176,16 @@ public class CraftWorld extends CraftRegionAccessor implements World {
+
+ @Override
+ public RayTraceResult rayTraceBlocks(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks) {
++ // Paper start
++ return this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, null);
++ }
++
++ @Override
++ public RayTraceResult rayTraceBlocks(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, Predicate<Block> canCollide) {
+ Preconditions.checkArgument(start != null, "Location start cannot be null");
+- Preconditions.checkArgument(this.equals(start.getWorld()), "Location start cannot be in a different world");
+- start.checkFinite();
++ Preconditions.checkArgument(!(start instanceof Location location) || this.equals(location.getWorld()), "Location start cannot be in a different world");
++ Preconditions.checkArgument(start.isFinite(), "Location start is not finite");
++ // Paper end
+
+ Preconditions.checkArgument(direction != null, "Vector direction cannot be null");
+ direction.checkFinite();
+@@ -1185,16 +1198,23 @@ public class CraftWorld extends CraftRegionAccessor implements World {
+ }
+
+ Vector dir = direction.clone().normalize().multiply(maxDistance);
+- Vec3 startPos = CraftLocation.toVec3D(start);
++ Vec3 startPos = io.papermc.paper.util.MCUtil.toVec3(start); // Paper
+ Vec3 endPos = startPos.add(dir.getX(), dir.getY(), dir.getZ());
+- HitResult nmsHitResult = this.getHandle().clip(new ClipContext(startPos, endPos, ignorePassableBlocks ? ClipContext.Block.COLLIDER : ClipContext.Block.OUTLINE, CraftFluidCollisionMode.toNMS(fluidCollisionMode), null));
++ HitResult nmsHitResult = this.getHandle().clip(new ClipContext(startPos, endPos, ignorePassableBlocks ? ClipContext.Block.COLLIDER : ClipContext.Block.OUTLINE, CraftFluidCollisionMode.toNMS(fluidCollisionMode), null), canCollide); // Paper - use method with canCollide predicate
+
+ return CraftRayTraceResult.fromNMS(this, nmsHitResult);
+ }
+
+ @Override
+ public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate<Entity> filter) {
+- RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks);
++ // Paper start
++ return this.rayTrace(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, raySize, filter, null);
++ }
++
++ @Override
++ public RayTraceResult rayTrace(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate<Entity> filter, Predicate<Block> canCollide) {
++ RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, canCollide);
++ // Paper end
+ Vector startVec = null;
+ double blockHitDistance = maxDistance;
+