diff --git a/paper-api/src/main/java/io/papermc/paper/raytrace/BlockCollisionMode.java b/paper-api/src/main/java/io/papermc/paper/raytrace/BlockCollisionMode.java new file mode 100644 index 000000000000..a2dd14244b17 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/raytrace/BlockCollisionMode.java @@ -0,0 +1,25 @@ +package io.papermc.paper.raytrace; + +/** + * Determines the collision behavior when blocks get hit during ray tracing. + */ +public enum BlockCollisionMode { + + /** + * Use the collision shape. + */ + COLLIDER, + /** + * Use the outline shape. + */ + OUTLINE, + /** + * Use the visual shape. + */ + VISUAL, + /** + * Use the shape of a full block, but only consider blocks tagged with {@link org.bukkit.Tag#FALL_DAMAGE_RESETTING}. + */ + FALL_DAMAGE_RESETTING + +} diff --git a/paper-api/src/main/java/io/papermc/paper/raytracing/PositionedRayTraceConfigurationBuilder.java b/paper-api/src/main/java/io/papermc/paper/raytracing/PositionedRayTraceConfigurationBuilder.java index 9d41e5622351..f51110a34d94 100644 --- a/paper-api/src/main/java/io/papermc/paper/raytracing/PositionedRayTraceConfigurationBuilder.java +++ b/paper-api/src/main/java/io/papermc/paper/raytracing/PositionedRayTraceConfigurationBuilder.java @@ -1,6 +1,7 @@ package io.papermc.paper.raytracing; import java.util.function.Predicate; +import io.papermc.paper.raytrace.BlockCollisionMode; import org.bukkit.FluidCollisionMode; import org.bukkit.Location; import org.bukkit.block.Block; @@ -46,9 +47,6 @@ public interface PositionedRayTraceConfigurationBuilder { /** * Sets the FluidCollisionMode when looking for block collisions. - *
- * If collisions with passable blocks are ignored, fluid collisions are - * ignored as well regardless of the fluid collision mode. * * @param fluidCollisionMode the new FluidCollisionMode * @return a reference to this object @@ -56,16 +54,18 @@ public interface PositionedRayTraceConfigurationBuilder { @Contract(value = "_ -> this", mutates = "this") PositionedRayTraceConfigurationBuilder fluidCollisionMode(FluidCollisionMode fluidCollisionMode); + /** + * Sets the BlockCollisionMode when looking for block collisions. + * + * @param blockCollisionMode the new BlockCollisionMode + * @return a reference to this object + */ + @Contract(value = "_ -> this", mutates = "this") + PositionedRayTraceConfigurationBuilder blockCollisionMode(BlockCollisionMode blockCollisionMode); + /** * Sets whether the raytrace should ignore passable blocks when looking for * block collisions. - *
- * If collisions with passable blocks are ignored, fluid collisions are - * ignored as well regardless of the fluid collision mode. - *
- * 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. * * @param ignorePassableBlocks if the raytrace should ignore passable blocks * @return a reference to this object diff --git a/paper-api/src/main/java/org/bukkit/FluidCollisionMode.java b/paper-api/src/main/java/org/bukkit/FluidCollisionMode.java index ae28958941d7..d03a604bccf9 100644 --- a/paper-api/src/main/java/org/bukkit/FluidCollisionMode.java +++ b/paper-api/src/main/java/org/bukkit/FluidCollisionMode.java @@ -13,6 +13,10 @@ public enum FluidCollisionMode { * Only collide with source fluid blocks. */ SOURCE_ONLY, + /** + * Collide only with water. + */ + WATER, /** * Collide with all fluids. */ diff --git a/paper-api/src/main/java/org/bukkit/World.java b/paper-api/src/main/java/org/bukkit/World.java index 015d852d5a0c..b39d2c048fd7 100644 --- a/paper-api/src/main/java/org/bukkit/World.java +++ b/paper-api/src/main/java/org/bukkit/World.java @@ -1844,13 +1844,6 @@ default Iterable extends net.kyori.adventure.audience.Audience> audiences() { * Performs a ray trace that checks for block collisions using the blocks' * precise collision shapes. *
- * If collisions with passable blocks are ignored, fluid collisions are - * ignored as well regardless of the fluid collision mode. - *
- * 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. - *
* This may cause loading of chunks! Some implementations may impose * artificial restrictions on the maximum distance. * @@ -1865,18 +1858,10 @@ default Iterable extends net.kyori.adventure.audience.Audience> audiences() { @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. *
- * If collisions with passable blocks are ignored, fluid collisions are - * ignored as well regardless of the fluid collision mode. - *
- * 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. - *
* This may cause loading of chunks! Some implementations may impose
* artificial restrictions on the maximum distance.
*
@@ -1891,7 +1876,6 @@ default Iterable extends net.kyori.adventure.audience.Audience> audiences() {
* @return the ray trace hit result, or null
if there is no hit
*/
@Nullable RayTraceResult rayTraceBlocks(io.papermc.paper.math.@NotNull Position start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, @Nullable Predicate super Block> canCollide);
- // Paper end
/**
* Performs a ray trace that checks for both block and entity collisions.
@@ -1900,13 +1884,6 @@ default Iterable extends net.kyori.adventure.audience.Audience> audiences() {
* raySize
parameter is only taken into account for entity
* collision checks.
*
- * If collisions with passable blocks are ignored, fluid collisions are - * ignored as well regardless of the fluid collision mode. - *
- * 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. - *
* This may cause loading of chunks! Some implementations may impose * artificial restrictions on the maximum distance. * @@ -1926,7 +1903,6 @@ default Iterable extends net.kyori.adventure.audience.Audience> audiences() { @Nullable public RayTraceResult rayTrace(@NotNull Location start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, @Nullable Predicate super Entity> filter); - // Paper start /** * Performs a ray trace that checks for both block and entity collisions. *
@@ -1934,13 +1910,6 @@ default Iterable extends net.kyori.adventure.audience.Audience> audiences() {
* raySize
parameter is only taken into account for entity
* collision checks.
*
- * If collisions with passable blocks are ignored, fluid collisions are - * ignored as well regardless of the fluid collision mode. - *
- * 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. - *
* This may cause loading of chunks! Some implementations may impose
* artificial restrictions on the maximum distance.
*
@@ -1960,7 +1929,6 @@ default Iterable extends net.kyori.adventure.audience.Audience> audiences() {
* entity, or null
if there is no hit
*/
@Nullable RayTraceResult rayTrace(io.papermc.paper.math.@NotNull Position start, @NotNull Vector direction, double maxDistance, @NotNull FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, @Nullable Predicate super Entity> filter, @Nullable Predicate super Block> canCollide);
- // Paper end
/**
* Performs a ray trace that checks for collisions with the specified
diff --git a/paper-server/src/main/java/io/papermc/paper/raytracing/PositionedRayTraceConfigurationBuilderImpl.java b/paper-server/src/main/java/io/papermc/paper/raytracing/PositionedRayTraceConfigurationBuilderImpl.java
index 3d078858d990..aeb0095ba524 100644
--- a/paper-server/src/main/java/io/papermc/paper/raytracing/PositionedRayTraceConfigurationBuilderImpl.java
+++ b/paper-server/src/main/java/io/papermc/paper/raytracing/PositionedRayTraceConfigurationBuilderImpl.java
@@ -4,6 +4,7 @@
import java.util.EnumSet;
import java.util.OptionalDouble;
import java.util.function.Predicate;
+import io.papermc.paper.raytrace.BlockCollisionMode;
import org.bukkit.FluidCollisionMode;
import org.bukkit.Location;
import org.bukkit.block.Block;
@@ -19,7 +20,7 @@ public class PositionedRayTraceConfigurationBuilderImpl implements PositionedRay
public @Nullable Vector direction;
public OptionalDouble maxDistance = OptionalDouble.empty();
public FluidCollisionMode fluidCollisionMode = FluidCollisionMode.NEVER;
- public boolean ignorePassableBlocks;
+ public BlockCollisionMode blockCollisionMode = BlockCollisionMode.OUTLINE;
public double raySize = 0.0D;
public @Nullable Predicate super Entity> entityFilter;
public @Nullable Predicate super Block> blockFilter;
@@ -53,9 +54,16 @@ public PositionedRayTraceConfigurationBuilder fluidCollisionMode(final FluidColl
return this;
}
+ @Override
+ public PositionedRayTraceConfigurationBuilder blockCollisionMode(final BlockCollisionMode blockCollisionMode) {
+ Preconditions.checkArgument(blockCollisionMode != null, "blockCollisionMode must not be null");
+ this.blockCollisionMode = blockCollisionMode;
+ return this;
+ }
+
@Override
public PositionedRayTraceConfigurationBuilder ignorePassableBlocks(final boolean ignorePassableBlocks) {
- this.ignorePassableBlocks = ignorePassableBlocks;
+ this.blockCollisionMode = ignorePassableBlocks ? BlockCollisionMode.COLLIDER : BlockCollisionMode.OUTLINE;
return this;
}
diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftFluidCollisionMode.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftFluidCollisionMode.java
index 2178d65faede..52cdaffd5224 100644
--- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftFluidCollisionMode.java
+++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftFluidCollisionMode.java
@@ -13,6 +13,8 @@ public static Fluid toNMS(FluidCollisionMode fluidCollisionMode) {
switch (fluidCollisionMode) {
case ALWAYS:
return Fluid.ANY;
+ case WATER:
+ return Fluid.WATER;
case SOURCE_ONLY:
return Fluid.SOURCE_ONLY;
case NEVER:
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 1439d282167d..e239914253fe 100644
--- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1159,6 +1159,10 @@ public RayTraceResult rayTraceBlocks(Location start, Vector direction, double ma
@Override
public RayTraceResult rayTraceBlocks(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, Predicate super Block> canCollide) {
+ return this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks ? io.papermc.paper.raytrace.BlockCollisionMode.COLLIDER : io.papermc.paper.raytrace.BlockCollisionMode.OUTLINE, canCollide);
+ }
+
+ public RayTraceResult rayTraceBlocks(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, io.papermc.paper.raytrace.BlockCollisionMode blockCollisionMode, Predicate super Block> canCollide) {
Preconditions.checkArgument(start != null, "Location start cannot be null");
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");
@@ -1169,6 +1173,7 @@ public RayTraceResult rayTraceBlocks(io.papermc.paper.math.Position start, Vecto
Preconditions.checkArgument(direction.lengthSquared() > 0, "Direction's magnitude (%s) need to be greater than 0", direction.lengthSquared());
Preconditions.checkArgument(fluidCollisionMode != null, "FluidCollisionMode cannot be null");
+ Preconditions.checkArgument(blockCollisionMode != null, "BlockCollisionMode cannot be null");
if (maxDistance < 0.0D) {
return null;
@@ -1177,7 +1182,7 @@ public RayTraceResult rayTraceBlocks(io.papermc.paper.math.Position start, Vecto
Vector dir = direction.clone().normalize().multiply(maxDistance);
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()), canCollide); // Paper - Add predicate for blocks when raytracing
+ HitResult nmsHitResult = this.getHandle().clip(new ClipContext(startPos, endPos, ClipContext.Block.values()[blockCollisionMode.ordinal()], CraftFluidCollisionMode.toNMS(fluidCollisionMode), CollisionContext.empty()), canCollide);
return CraftRayTraceResult.fromNMS(this, nmsHitResult);
}
@@ -1190,8 +1195,11 @@ public RayTraceResult rayTrace(Location start, Vector direction, double maxDista
@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
+ return this.rayTrace(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks ? io.papermc.paper.raytrace.BlockCollisionMode.COLLIDER : io.papermc.paper.raytrace.BlockCollisionMode.OUTLINE, raySize, filter, null);
+ }
+
+ public RayTraceResult rayTrace(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, io.papermc.paper.raytrace.BlockCollisionMode blockCollisionMode, double raySize, Predicate super Entity> filter, Predicate super Block> canCollide) {
+ RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, blockCollisionMode, canCollide);
Vector startVec = null;
double blockHitDistance = maxDistance;
@@ -1232,11 +1240,11 @@ public RayTraceResult rayTrace(Consumer