From 4866ee899b0e84be220d18babda813ccc2063a6d Mon Sep 17 00:00:00 2001 From: TonytheMacaroni Date: Wed, 6 Sep 2023 19:24:16 -0400 Subject: [PATCH] Add predicate for blocks when raytracing --- .../world/level/BlockGetter.java.patch | 22 +++++++++--- .../org/bukkit/craftbukkit/CraftWorld.java | 34 +++++++++++++++---- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/world/level/BlockGetter.java.patch b/paper-server/patches/sources/net/minecraft/world/level/BlockGetter.java.patch index 07f7382aca..b3ea51c1e2 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/BlockGetter.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/BlockGetter.java.patch @@ -30,7 +30,7 @@ FluidState getFluidState(BlockPos pos); default int getLightEmission(BlockPos pos) { -@@ -59,10 +69,19 @@ +@@ -59,10 +69,25 @@ }); } @@ -40,6 +40,12 @@ - FluidState fluid = this.getFluidState(blockposition); + // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace + default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) { ++ // Paper start - Add predicate for blocks when raytracing ++ return clip(raytrace1, blockposition, null); ++ } ++ ++ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition, java.util.function.Predicate canCollide) { ++ // Paper end - Add predicate for blocks when raytracing + // Paper start - Prevent raytrace from loading chunks + BlockState iblockdata = this.getBlockStateIfLoaded(blockposition); + if (iblockdata == null) { @@ -49,12 +55,12 @@ + return BlockHitResult.miss(raytrace1.getTo(), Direction.getApproximateNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo())); + } + // Paper end - Prevent raytrace from loading chunks -+ if (iblockdata.isAir()) return null; // Paper - Perf: 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 - Perf: optimise air cases & check canCollide predicate + FluidState fluid = iblockdata.getFluidState(); // Paper - Perf: don't need to go to world state again Vec3 vec3d = raytrace1.getFrom(); Vec3 vec3d1 = raytrace1.getTo(); VoxelShape voxelshape = raytrace1.getBlockShape(iblockdata, this, blockposition); -@@ -73,6 +92,12 @@ +@@ -73,6 +98,18 @@ double d1 = movingobjectpositionblock1 == null ? Double.MAX_VALUE : raytrace1.getFrom().distanceToSqr(movingobjectpositionblock1.getLocation()); return d0 <= d1 ? movingobjectpositionblock : movingobjectpositionblock1; @@ -62,12 +68,18 @@ + // CraftBukkit end + + default BlockHitResult clip(ClipContext context) { ++ // Paper start - Add predicate for blocks when raytracing ++ return clip(context, (java.util.function.Predicate) null); ++ } ++ ++ default BlockHitResult clip(ClipContext context, java.util.function.Predicate canCollide) { ++ // Paper end - Add predicate for blocks when raytracing + 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 - Add predicate for blocks when raytracing }, (raytrace1) -> { Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo()); -@@ -145,7 +170,7 @@ +@@ -145,7 +182,7 @@ double d13 = d10 * (i1 > 0 ? 1.0D - Mth.frac(d4) : Mth.frac(d4)); double d14 = d11 * (j1 > 0 ? 1.0D - Mth.frac(d5) : Mth.frac(d5)); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 231089eab8..a36470d9e9 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -1097,9 +1097,15 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, double raySize, Predicate filter) { + // Paper start - Add predicate for blocks when raytracing + 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 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 - Add predicate for blocks when raytracing Preconditions.checkArgument(direction != null, "Vector direction cannot be null"); direction.checkFinite(); @@ -1149,9 +1155,16 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public RayTraceResult rayTraceBlocks(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks) { + // Paper start - Add predicate for blocks when raytracing + 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 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 - Add predicate for blocks when raytracing Preconditions.checkArgument(direction != null, "Vector direction cannot be null"); direction.checkFinite(); @@ -1164,16 +1177,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 - Add predicate for blocks when raytracing 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), CollisionContext.empty())); + HitResult nmsHitResult = this.getHandle().clip(new ClipContext(startPos, endPos, ignorePassableBlocks ? ClipContext.Block.COLLIDER : ClipContext.Block.OUTLINE, CraftFluidCollisionMode.toNMS(fluidCollisionMode), CollisionContext.empty()), canCollide); // Paper - Add predicate for blocks when raytracing return CraftRayTraceResult.fromNMS(this, nmsHitResult); } @Override public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate filter) { - RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks); + // Paper start - Add predicate for blocks when raytracing + 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 filter, Predicate canCollide) { + RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, canCollide); + // Paper end - Add predicate for blocks when raytracing Vector startVec = null; double blockHitDistance = maxDistance;