aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0924-Add-predicate-for-blocks-when-raytracing.patch
blob: 712ca7a8c84db30d05377cce330dc6ee555b437e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TonytheMacaroni <tonythemacaroni123@gmail.com>
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 c978f3b2d42f512e982f289e76c2422e41b7eec6..bb8e962e63c7a2d931f9bd7f7c002aa35cfa5fd3 100644
--- a/src/main/java/net/minecraft/world/level/BlockGetter.java
+++ b/src/main/java/net/minecraft/world/level/BlockGetter.java
@@ -70,6 +70,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 - Add predicate for blocks when raytracing
+        return clip(raytrace1, blockposition, null);
+    }
+
+    default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition, java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) {
+            // Paper end - Add predicate for blocks when raytracing
             // Paper start - Prevent raytrace from loading chunks
             BlockState iblockdata = this.getBlockStateIfLoaded(blockposition);
             if (iblockdata == null) {
@@ -79,7 +85,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 - 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();
@@ -95,8 +101,14 @@ public interface BlockGetter extends LevelHeightAccessor {
     // CraftBukkit end
 
     default BlockHitResult clip(ClipContext context) {
+        // Paper start - Add predicate for blocks when raytracing
+        return clip(context, (java.util.function.Predicate<org.bukkit.block.Block>) null);
+    }
+
+    default BlockHitResult clip(ClipContext context, java.util.function.Predicate<? super org.bukkit.block.Block> 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());
 
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 18c1cceb9e8b2873b24134a9e012633616634aae..3abb776f546edb84307f374943427be02dc4c911 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1136,9 +1136,15 @@ public class CraftWorld extends CraftRegionAccessor implements World {
 
     @Override
     public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, double raySize, Predicate<? super Entity> 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<? super 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 - Add predicate for blocks when raytracing
 
         Preconditions.checkArgument(direction != null, "Vector direction cannot be null");
         direction.checkFinite();
@@ -1188,9 +1194,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<? super 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 - Add predicate for blocks when raytracing
 
         Preconditions.checkArgument(direction != null, "Vector direction cannot be null");
         direction.checkFinite();
@@ -1203,16 +1216,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<? super Entity> 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<? super Entity> filter, Predicate<? super Block> 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;