From d6a56da3d46de5579874a2076fd781c2ec2c6621 Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Sat, 4 Jan 2025 14:42:50 +0100
Subject: [PATCH 01/10] Add RayTraceConfiguration

---
 .../raytracing/RayTraceConfiguration.java     | 206 ++++++++++++++++++
 .../RayTraceConfigurationBuilderImpl.java     |  93 ++++++++
 .../raytracing/RayTraceConfigurationImpl.java |  15 ++
 paper-api/src/main/java/org/bukkit/World.java |  25 +++
 .../org/bukkit/craftbukkit/CraftWorld.java    |  12 +
 5 files changed, 351 insertions(+)
 create mode 100644 paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfiguration.java
 create mode 100644 paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationBuilderImpl.java
 create mode 100644 paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationImpl.java

diff --git a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfiguration.java b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfiguration.java
new file mode 100644
index 000000000000..293ad30b3653
--- /dev/null
+++ b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfiguration.java
@@ -0,0 +1,206 @@
+package io.papermc.paper.raytracing;
+
+import org.bukkit.FluidCollisionMode;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Entity;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Holds information about how to cast a raytrace.
+ */
+public interface RayTraceConfiguration {
+
+    /**
+     * Creates a new builder.
+     *
+     * @return the new builder
+     */
+    @NotNull
+    static Builder builder() {
+        return new RayTraceConfigurationBuilderImpl();
+    }
+
+    /**
+     * Gets the maximum distance.
+     *
+     * @return the maximum distance
+     */
+    double maxDistance();
+
+    /**
+     * Gets the FluidCollisionMode when looking for block collisions.
+     *
+     * @return the FluidCollisionMode
+     */
+    @Nullable
+    FluidCollisionMode fluidCollisionMode();
+
+    /**
+     * Gets if the raytrace will ignore passable blocks when looking for block collisions.
+     *
+     * @return if the raytrace will ignore passable blocks
+     */
+    boolean ignorePassableBlocks();
+
+    /**
+     * Gets the size of the raytrace when looking for entity collisions.
+     *
+     * @return the raytrace size
+     */
+    double raySize();
+
+    /**
+     * Gets the current entity filter.
+     *
+     * @return predicate for entities the ray can potentially collide with, or null to consider all entities
+     */
+    @Nullable
+    Predicate<? super Entity> entityFilter();
+
+    /**
+     * Gets the current block filter.
+     *
+     * @return predicate for blocks the ray can potentially collide with, or null to consider all blocks
+     */
+    @Nullable
+    Predicate<? super Block> blockFilter();
+
+    /**
+     * Gets which RayTraceTargets this configuration was made for.
+     *
+     * @return the targets
+     */
+    @NotNull
+    List<Targets> targets();
+
+    /**
+     * Helps you create a RayTraceConfiguration.
+     */
+    interface Builder {
+
+        /**
+         * Gets the maximum distance.
+         *
+         * @return the maximum distance
+         */
+        double maxDistance();
+
+        /**
+         * Sets the maximum distance.
+         *
+         * @param maxDistance the new maxDistance
+         * @return a reference to this object
+         */
+        @NotNull
+        @Contract("_ -> this")
+        Builder maxDistance(double maxDistance);
+
+        /**
+         * Gets the FluidCollisionMode when looking for block collisions.
+         *
+         * @return the FluidCollisionMode
+         */
+        @Nullable
+        FluidCollisionMode fluidCollisionMode();
+
+        /**
+         * Sets the FluidCollisionMode when looking for block collisions.
+         *
+         * @param fluidCollisionMode the new FluidCollisionMode
+         * @return a reference to this object
+         */
+        @NotNull
+        @Contract("_ -> this")
+        Builder fluidCollisionMode(@Nullable FluidCollisionMode fluidCollisionMode);
+
+        /**
+         * Gets if the raytrace will ignore passable blocks when looking for block collisions.
+         *
+         * @return if the raytrace will ignore passable blocks
+         */
+        boolean ignorePassableBlocks();
+
+        /**
+         * Gets if the raytrace will ignore passable blocks when looking for block collisions.
+         *
+         * @param ignorePassableBlocks if the raytrace should ignore passable blocks
+         * @return a reference to this object
+         */
+        @NotNull
+        @Contract("_ -> this")
+        Builder ignorePassableBlocks(boolean ignorePassableBlocks);
+
+        /**
+         * Gets the size of the raytrace when looking for entity collisions.
+         *
+         * @return the raytrace size
+         */
+        double raySize();
+
+        /**
+         * Sets the size of the raytrace when looking for entity collisions.
+         *
+         * @param raySize the new raytrace size
+         * @return a reference to this object
+         */
+        @NotNull
+        @Contract("_ -> this")
+        Builder raySize(double raySize);
+
+        /**
+         * Gets the current entity filter when looking for entity collisions.
+         *
+         * @return predicate for entities the ray can potentially collide with, or null to consider all entities
+         */
+        @Nullable
+        Predicate<? super Entity> entityFilter();
+
+        /**
+         * Sets the current entity filter when looking for entity collisions.
+         *
+         * @param entityFilter predicate for entities the ray can potentially collide with, or null to consider all entities
+         * @return a reference to this object
+         */
+        @NotNull
+        @Contract("_ -> this")
+        Builder entityFilter(@Nullable Predicate<? super Entity> entityFilter);
+
+        /**
+         * Gets the current block filter when looking for block collisions.
+         *
+         * @return predicate for blocks the ray can potentially collide with, or null to consider all blocks
+         */
+        @Nullable
+        Predicate<? super Block> blockFilter();
+
+        /**
+         * Sets the current block filter when looking for block collisions.
+         *
+         * @param blockFilter predicate for blocks the ray can potentially collide with, or null to consider all blocks
+         * @return a reference to this object
+         */
+        @NotNull
+        @Contract("_ -> this")
+        Builder blockFilter(@Nullable Predicate<? super Block> blockFilter);
+
+        /**
+         * Builds a configuration based on the provided targets.
+         *
+         * @return the configuration
+         */
+        @NotNull
+        RayTraceConfiguration target(@NotNull Targets first, @NotNull Targets... others);
+    }
+
+    /**
+     * List of Targets the builder can target.
+     */
+    enum Targets {
+        ENTITIES,
+        BLOCKS
+    }
+}
diff --git a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationBuilderImpl.java b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationBuilderImpl.java
new file mode 100644
index 000000000000..b6a9e03023ce
--- /dev/null
+++ b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationBuilderImpl.java
@@ -0,0 +1,93 @@
+package io.papermc.paper.raytracing;
+import org.bukkit.FluidCollisionMode;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Entity;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
+
+public class RayTraceConfigurationBuilderImpl implements RayTraceConfiguration.Builder {
+
+    private double maxDistance;
+    private FluidCollisionMode fluidCollisionMode = FluidCollisionMode.NEVER;
+    private boolean ignorePassableBlocks;
+    private double raySize = 0.0D;
+    private Predicate<? super Entity> entityFilter;
+    private Predicate<? super Block> blockFilter;
+
+
+    @Override
+    public double maxDistance() {
+        return maxDistance;
+    }
+
+    @Override
+    public @NotNull RayTraceConfiguration.Builder maxDistance(double maxDistance) {
+        this.maxDistance = maxDistance;
+        return this;
+    }
+
+    @Override
+    public @Nullable FluidCollisionMode fluidCollisionMode() {
+        return fluidCollisionMode;
+    }
+
+    @Override
+    public @NotNull RayTraceConfiguration.Builder fluidCollisionMode(@Nullable FluidCollisionMode fluidCollisionMode) {
+        this.fluidCollisionMode = fluidCollisionMode;
+        return this;
+    }
+
+    @Override
+    public boolean ignorePassableBlocks() {
+        return ignorePassableBlocks;
+    }
+
+    @Override
+    public @NotNull RayTraceConfiguration.Builder ignorePassableBlocks(boolean ignorePassableBlocks) {
+        this.ignorePassableBlocks = ignorePassableBlocks;
+        return this;
+    }
+
+    @Override
+    public double raySize() {
+        return raySize;
+    }
+
+    @Override
+    public @NotNull RayTraceConfiguration.Builder raySize(double raySize) {
+        this.raySize = raySize;
+        return this;
+    }
+
+    @Override
+    public @Nullable Predicate<? super Entity> entityFilter() {
+        return entityFilter;
+    }
+
+    @Override
+    public @NotNull RayTraceConfiguration.Builder entityFilter(@Nullable Predicate<? super Entity> entityFilter) {
+        this.entityFilter = entityFilter;
+        return this;
+    }
+
+    @Override
+    public @Nullable Predicate<? super Block> blockFilter() {
+        return blockFilter;
+    }
+
+    @Override
+    public @NotNull RayTraceConfiguration.Builder blockFilter(@Nullable Predicate<? super Block> blockFilter) {
+        this.blockFilter = blockFilter;
+        return this;
+    }
+
+    @Override
+    public @NotNull RayTraceConfiguration target(@NotNull RayTraceConfiguration.Targets first, @NotNull RayTraceConfiguration.Targets... others) {
+        List<RayTraceConfiguration.Targets> targets = new ArrayList<>(List.of(others)); // Need to make this immutable later
+        targets.add(first);
+        return new RayTraceConfigurationImpl(maxDistance, fluidCollisionMode, ignorePassableBlocks, raySize, entityFilter, blockFilter, targets);
+    }
+}
diff --git a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationImpl.java b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationImpl.java
new file mode 100644
index 000000000000..ffe49cd1ecc9
--- /dev/null
+++ b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationImpl.java
@@ -0,0 +1,15 @@
+package io.papermc.paper.raytracing;
+
+import org.bukkit.FluidCollisionMode;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Entity;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import java.util.List;
+import java.util.function.Predicate;
+
+public record RayTraceConfigurationImpl(double maxDistance, @Nullable FluidCollisionMode fluidCollisionMode,
+                                        boolean ignorePassableBlocks, double raySize,
+                                        @Nullable Predicate<? super Entity> entityFilter, @Nullable Predicate<? super Block> blockFilter,
+                                        @NotNull List<Targets> targets) implements RayTraceConfiguration {
+}
diff --git a/paper-api/src/main/java/org/bukkit/World.java b/paper-api/src/main/java/org/bukkit/World.java
index e99fa923d35b..13eeb8032be5 100644
--- a/paper-api/src/main/java/org/bukkit/World.java
+++ b/paper-api/src/main/java/org/bukkit/World.java
@@ -1938,6 +1938,31 @@ default Iterable<? extends net.kyori.adventure.audience.Audience> audiences() {
     @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 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 config the configuration
+     * @return the closest ray trace hit result with either a block or an
+     *     entity, or <code>null</code> if there is no hit
+     */
+    @Nullable RayTraceResult rayTrace(@NotNull Location start, @NotNull Vector direction, @NotNull io.papermc.paper.raytracing.RayTraceConfiguration config);
+
     /**
      * Gets the default spawn {@link Location} of this world
      *
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 ba32db69c95b..4b3eb4ff81f5 100644
--- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -8,6 +8,7 @@
 import io.papermc.paper.FeatureHooks;
 import io.papermc.paper.registry.RegistryAccess;
 import io.papermc.paper.registry.RegistryKey;
+import io.papermc.paper.raytracing.RayTraceConfiguration;
 import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
 import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
 import java.io.File;
@@ -1248,6 +1249,17 @@ public RayTraceResult rayTrace(io.papermc.paper.math.Position start, Vector dire
         return blockHit;
     }
 
+    @Override
+    public @org.jetbrains.annotations.Nullable RayTraceResult rayTrace(Location start, Vector direction, io.papermc.paper.raytracing.RayTraceConfiguration config) {
+        List<io.papermc.paper.raytracing.RayTraceConfiguration.Targets> targets = config.targets();
+        if (targets.contains(io.papermc.paper.raytracing.RayTraceConfiguration.Targets.ENTITIES)) {
+            if(targets.contains(io.papermc.paper.raytracing.RayTraceConfiguration.Targets.BLOCKS))
+                return this.rayTrace(start, direction, config.maxDistance(), config.fluidCollisionMode(), config.ignorePassableBlocks(), config.raySize(), config.entityFilter(), config.blockFilter());
+            return this.rayTraceEntities(start, direction, config.maxDistance(), config.raySize(), config.entityFilter());
+        }
+        return this.rayTraceBlocks(start, direction, config.maxDistance(), config.fluidCollisionMode(), config.ignorePassableBlocks(), config.blockFilter());
+    }
+
     @Override
     public List<Player> getPlayers() {
         List<Player> list = new ArrayList<Player>(this.world.players().size());

From 0a98c80fef1326d1aab8a2d5633e7882b6d5ce78 Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Sat, 4 Jan 2025 22:14:08 +0100
Subject: [PATCH 02/10] work

---
 ...ositionedRayTraceConfigurationBuilder.java | 174 +++++++++++++++
 .../raytracing/RayTraceConfiguration.java     | 206 ------------------
 .../RayTraceConfigurationBuilderImpl.java     |  93 --------
 .../raytracing/RayTraceConfigurationImpl.java |  15 --
 paper-api/src/main/java/org/bukkit/World.java |   7 +-
 ...ionedRayTraceConfigurationBuilderImpl.java | 134 ++++++++++++
 .../org/bukkit/craftbukkit/CraftWorld.java    |  14 +-
 7 files changed, 317 insertions(+), 326 deletions(-)
 create mode 100644 paper-api/src/main/java/io/papermc/paper/raytracing/PositionedRayTraceConfigurationBuilder.java
 delete mode 100644 paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfiguration.java
 delete mode 100644 paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationBuilderImpl.java
 delete mode 100644 paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationImpl.java
 create mode 100644 paper-server/src/main/java/io/papermc/paper/raytracing/PositionedRayTraceConfigurationBuilderImpl.java

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
new file mode 100644
index 000000000000..6144350e3c45
--- /dev/null
+++ b/paper-api/src/main/java/io/papermc/paper/raytracing/PositionedRayTraceConfigurationBuilder.java
@@ -0,0 +1,174 @@
+package io.papermc.paper.raytracing;
+
+import org.bukkit.FluidCollisionMode;
+import org.bukkit.Location;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Entity;
+import org.bukkit.util.Vector;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import java.util.function.Predicate;
+
+/**
+ * Holds information about how to cast a raytrace.
+ */
+public interface PositionedRayTraceConfigurationBuilder {
+
+    /**
+     * Gets the starting location.
+     *
+     * @return the starting location
+     */
+    @Nullable
+    Location start();
+
+    /**
+     * Sets the starting location.
+     *
+     * @param start the new starting location
+     * @return a reference to this object
+     */
+    @NotNull
+    @Contract("_ -> this")
+    PositionedRayTraceConfigurationBuilder start(@NotNull Location start);
+
+    /**
+     * Gets the direction.
+     *
+     * @return the direction
+     */
+    @Nullable
+    Vector direction();
+
+    /**
+     * Sets the direction.
+     *
+     * @param direction the new direction
+     * @return a reference to this object
+     */
+    @NotNull
+    @Contract("_ -> this")
+    PositionedRayTraceConfigurationBuilder direction(@NotNull Vector direction);
+
+    /**
+     * Gets the maximum distance.
+     *
+     * @return the maximum distance
+     */
+    double maxDistance();
+
+    /**
+     * Sets the maximum distance.
+     *
+     * @param maxDistance the new maxDistance
+     * @return a reference to this object
+     */
+    @NotNull
+    @Contract("_ -> this")
+    PositionedRayTraceConfigurationBuilder maxDistance(double maxDistance);
+
+    /**
+     * Gets the FluidCollisionMode when looking for block collisions.
+     *
+     * @return the FluidCollisionMode
+     */
+    @NotNull
+    FluidCollisionMode fluidCollisionMode();
+
+    /**
+     * Sets the FluidCollisionMode when looking for block collisions.
+     *
+     * @param fluidCollisionMode the new FluidCollisionMode
+     * @return a reference to this object
+     */
+    @NotNull
+    @Contract("_ -> this")
+    PositionedRayTraceConfigurationBuilder fluidCollisionMode(@NotNull FluidCollisionMode fluidCollisionMode);
+
+    /**
+     * Gets if the raytrace will ignore passable blocks when looking for block collisions.
+     *
+     * @return if the raytrace will ignore passable blocks
+     */
+    boolean ignorePassableBlocks();
+
+    /**
+     * Gets if the raytrace will ignore passable blocks when looking for block collisions.
+     *
+     * @param ignorePassableBlocks if the raytrace should ignore passable blocks
+     * @return a reference to this object
+     */
+    @NotNull
+    @Contract("_ -> this")
+    PositionedRayTraceConfigurationBuilder ignorePassableBlocks(boolean ignorePassableBlocks);
+
+    /**
+     * Gets the size of the raytrace when looking for entity collisions.
+     *
+     * @return the raytrace size
+     */
+    double raySize();
+
+    /**
+     * Sets the size of the raytrace when looking for entity collisions.
+     *
+     * @param raySize the new raytrace size
+     * @return a reference to this object
+     */
+    @NotNull
+    @Contract("_ -> this")
+    PositionedRayTraceConfigurationBuilder raySize(double raySize);
+
+    /**
+     * Gets the current entity filter when looking for entity collisions.
+     *
+     * @return predicate for entities the ray can potentially collide with, or null to consider all entities
+     */
+    @Nullable
+    Predicate<? super Entity> entityFilter();
+
+    /**
+     * Sets the current entity filter when looking for entity collisions.
+     *
+     * @param entityFilter predicate for entities the ray can potentially collide with, or null to consider all entities
+     * @return a reference to this object
+     */
+    @NotNull
+    @Contract("_ -> this")
+    PositionedRayTraceConfigurationBuilder entityFilter(@Nullable Predicate<? super Entity> entityFilter);
+
+    /**
+     * Gets the current block filter when looking for block collisions.
+     *
+     * @return predicate for blocks the ray can potentially collide with, or null to consider all blocks
+     */
+    @Nullable
+    Predicate<? super Block> blockFilter();
+
+    /**
+     * Sets the current block filter when looking for block collisions.
+     *
+     * @param blockFilter predicate for blocks the ray can potentially collide with, or null to consider all blocks
+     * @return a reference to this object
+     */
+    @NotNull
+    @Contract("_ -> this")
+    PositionedRayTraceConfigurationBuilder blockFilter(@Nullable Predicate<? super Block> blockFilter);
+
+    /**
+     * Builds a configuration based on the provided targets.
+     *
+     * @return the configuration
+     */
+    @NotNull
+    void target(@NotNull Targets first, @NotNull Targets... others);
+
+    /**
+     * List of Targets the builder can target.
+     */
+    enum Targets {
+        ENTITIES,
+        BLOCKS
+    }
+}
diff --git a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfiguration.java b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfiguration.java
deleted file mode 100644
index 293ad30b3653..000000000000
--- a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfiguration.java
+++ /dev/null
@@ -1,206 +0,0 @@
-package io.papermc.paper.raytracing;
-
-import org.bukkit.FluidCollisionMode;
-import org.bukkit.block.Block;
-import org.bukkit.entity.Entity;
-import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import java.util.List;
-import java.util.function.Predicate;
-
-/**
- * Holds information about how to cast a raytrace.
- */
-public interface RayTraceConfiguration {
-
-    /**
-     * Creates a new builder.
-     *
-     * @return the new builder
-     */
-    @NotNull
-    static Builder builder() {
-        return new RayTraceConfigurationBuilderImpl();
-    }
-
-    /**
-     * Gets the maximum distance.
-     *
-     * @return the maximum distance
-     */
-    double maxDistance();
-
-    /**
-     * Gets the FluidCollisionMode when looking for block collisions.
-     *
-     * @return the FluidCollisionMode
-     */
-    @Nullable
-    FluidCollisionMode fluidCollisionMode();
-
-    /**
-     * Gets if the raytrace will ignore passable blocks when looking for block collisions.
-     *
-     * @return if the raytrace will ignore passable blocks
-     */
-    boolean ignorePassableBlocks();
-
-    /**
-     * Gets the size of the raytrace when looking for entity collisions.
-     *
-     * @return the raytrace size
-     */
-    double raySize();
-
-    /**
-     * Gets the current entity filter.
-     *
-     * @return predicate for entities the ray can potentially collide with, or null to consider all entities
-     */
-    @Nullable
-    Predicate<? super Entity> entityFilter();
-
-    /**
-     * Gets the current block filter.
-     *
-     * @return predicate for blocks the ray can potentially collide with, or null to consider all blocks
-     */
-    @Nullable
-    Predicate<? super Block> blockFilter();
-
-    /**
-     * Gets which RayTraceTargets this configuration was made for.
-     *
-     * @return the targets
-     */
-    @NotNull
-    List<Targets> targets();
-
-    /**
-     * Helps you create a RayTraceConfiguration.
-     */
-    interface Builder {
-
-        /**
-         * Gets the maximum distance.
-         *
-         * @return the maximum distance
-         */
-        double maxDistance();
-
-        /**
-         * Sets the maximum distance.
-         *
-         * @param maxDistance the new maxDistance
-         * @return a reference to this object
-         */
-        @NotNull
-        @Contract("_ -> this")
-        Builder maxDistance(double maxDistance);
-
-        /**
-         * Gets the FluidCollisionMode when looking for block collisions.
-         *
-         * @return the FluidCollisionMode
-         */
-        @Nullable
-        FluidCollisionMode fluidCollisionMode();
-
-        /**
-         * Sets the FluidCollisionMode when looking for block collisions.
-         *
-         * @param fluidCollisionMode the new FluidCollisionMode
-         * @return a reference to this object
-         */
-        @NotNull
-        @Contract("_ -> this")
-        Builder fluidCollisionMode(@Nullable FluidCollisionMode fluidCollisionMode);
-
-        /**
-         * Gets if the raytrace will ignore passable blocks when looking for block collisions.
-         *
-         * @return if the raytrace will ignore passable blocks
-         */
-        boolean ignorePassableBlocks();
-
-        /**
-         * Gets if the raytrace will ignore passable blocks when looking for block collisions.
-         *
-         * @param ignorePassableBlocks if the raytrace should ignore passable blocks
-         * @return a reference to this object
-         */
-        @NotNull
-        @Contract("_ -> this")
-        Builder ignorePassableBlocks(boolean ignorePassableBlocks);
-
-        /**
-         * Gets the size of the raytrace when looking for entity collisions.
-         *
-         * @return the raytrace size
-         */
-        double raySize();
-
-        /**
-         * Sets the size of the raytrace when looking for entity collisions.
-         *
-         * @param raySize the new raytrace size
-         * @return a reference to this object
-         */
-        @NotNull
-        @Contract("_ -> this")
-        Builder raySize(double raySize);
-
-        /**
-         * Gets the current entity filter when looking for entity collisions.
-         *
-         * @return predicate for entities the ray can potentially collide with, or null to consider all entities
-         */
-        @Nullable
-        Predicate<? super Entity> entityFilter();
-
-        /**
-         * Sets the current entity filter when looking for entity collisions.
-         *
-         * @param entityFilter predicate for entities the ray can potentially collide with, or null to consider all entities
-         * @return a reference to this object
-         */
-        @NotNull
-        @Contract("_ -> this")
-        Builder entityFilter(@Nullable Predicate<? super Entity> entityFilter);
-
-        /**
-         * Gets the current block filter when looking for block collisions.
-         *
-         * @return predicate for blocks the ray can potentially collide with, or null to consider all blocks
-         */
-        @Nullable
-        Predicate<? super Block> blockFilter();
-
-        /**
-         * Sets the current block filter when looking for block collisions.
-         *
-         * @param blockFilter predicate for blocks the ray can potentially collide with, or null to consider all blocks
-         * @return a reference to this object
-         */
-        @NotNull
-        @Contract("_ -> this")
-        Builder blockFilter(@Nullable Predicate<? super Block> blockFilter);
-
-        /**
-         * Builds a configuration based on the provided targets.
-         *
-         * @return the configuration
-         */
-        @NotNull
-        RayTraceConfiguration target(@NotNull Targets first, @NotNull Targets... others);
-    }
-
-    /**
-     * List of Targets the builder can target.
-     */
-    enum Targets {
-        ENTITIES,
-        BLOCKS
-    }
-}
diff --git a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationBuilderImpl.java b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationBuilderImpl.java
deleted file mode 100644
index b6a9e03023ce..000000000000
--- a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationBuilderImpl.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package io.papermc.paper.raytracing;
-import org.bukkit.FluidCollisionMode;
-import org.bukkit.block.Block;
-import org.bukkit.entity.Entity;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Predicate;
-
-public class RayTraceConfigurationBuilderImpl implements RayTraceConfiguration.Builder {
-
-    private double maxDistance;
-    private FluidCollisionMode fluidCollisionMode = FluidCollisionMode.NEVER;
-    private boolean ignorePassableBlocks;
-    private double raySize = 0.0D;
-    private Predicate<? super Entity> entityFilter;
-    private Predicate<? super Block> blockFilter;
-
-
-    @Override
-    public double maxDistance() {
-        return maxDistance;
-    }
-
-    @Override
-    public @NotNull RayTraceConfiguration.Builder maxDistance(double maxDistance) {
-        this.maxDistance = maxDistance;
-        return this;
-    }
-
-    @Override
-    public @Nullable FluidCollisionMode fluidCollisionMode() {
-        return fluidCollisionMode;
-    }
-
-    @Override
-    public @NotNull RayTraceConfiguration.Builder fluidCollisionMode(@Nullable FluidCollisionMode fluidCollisionMode) {
-        this.fluidCollisionMode = fluidCollisionMode;
-        return this;
-    }
-
-    @Override
-    public boolean ignorePassableBlocks() {
-        return ignorePassableBlocks;
-    }
-
-    @Override
-    public @NotNull RayTraceConfiguration.Builder ignorePassableBlocks(boolean ignorePassableBlocks) {
-        this.ignorePassableBlocks = ignorePassableBlocks;
-        return this;
-    }
-
-    @Override
-    public double raySize() {
-        return raySize;
-    }
-
-    @Override
-    public @NotNull RayTraceConfiguration.Builder raySize(double raySize) {
-        this.raySize = raySize;
-        return this;
-    }
-
-    @Override
-    public @Nullable Predicate<? super Entity> entityFilter() {
-        return entityFilter;
-    }
-
-    @Override
-    public @NotNull RayTraceConfiguration.Builder entityFilter(@Nullable Predicate<? super Entity> entityFilter) {
-        this.entityFilter = entityFilter;
-        return this;
-    }
-
-    @Override
-    public @Nullable Predicate<? super Block> blockFilter() {
-        return blockFilter;
-    }
-
-    @Override
-    public @NotNull RayTraceConfiguration.Builder blockFilter(@Nullable Predicate<? super Block> blockFilter) {
-        this.blockFilter = blockFilter;
-        return this;
-    }
-
-    @Override
-    public @NotNull RayTraceConfiguration target(@NotNull RayTraceConfiguration.Targets first, @NotNull RayTraceConfiguration.Targets... others) {
-        List<RayTraceConfiguration.Targets> targets = new ArrayList<>(List.of(others)); // Need to make this immutable later
-        targets.add(first);
-        return new RayTraceConfigurationImpl(maxDistance, fluidCollisionMode, ignorePassableBlocks, raySize, entityFilter, blockFilter, targets);
-    }
-}
diff --git a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationImpl.java b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationImpl.java
deleted file mode 100644
index ffe49cd1ecc9..000000000000
--- a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceConfigurationImpl.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.papermc.paper.raytracing;
-
-import org.bukkit.FluidCollisionMode;
-import org.bukkit.block.Block;
-import org.bukkit.entity.Entity;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import java.util.List;
-import java.util.function.Predicate;
-
-public record RayTraceConfigurationImpl(double maxDistance, @Nullable FluidCollisionMode fluidCollisionMode,
-                                        boolean ignorePassableBlocks, double raySize,
-                                        @Nullable Predicate<? super Entity> entityFilter, @Nullable Predicate<? super Block> blockFilter,
-                                        @NotNull List<Targets> targets) implements RayTraceConfiguration {
-}
diff --git a/paper-api/src/main/java/org/bukkit/World.java b/paper-api/src/main/java/org/bukkit/World.java
index 13eeb8032be5..d23b54a3c984 100644
--- a/paper-api/src/main/java/org/bukkit/World.java
+++ b/paper-api/src/main/java/org/bukkit/World.java
@@ -1,6 +1,7 @@
 package org.bukkit;
 
 import java.io.File;
+import io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilder;
 import org.bukkit.generator.ChunkGenerator;
 
 import java.util.ArrayList;
@@ -1955,13 +1956,11 @@ default Iterable<? extends net.kyori.adventure.audience.Audience> audiences() {
      * 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 config the configuration
+     * @param builderConsumer consumer for the builder
      * @return the closest ray trace hit result with either a block or an
      *     entity, or <code>null</code> if there is no hit
      */
-    @Nullable RayTraceResult rayTrace(@NotNull Location start, @NotNull Vector direction, @NotNull io.papermc.paper.raytracing.RayTraceConfiguration config);
+    @Nullable RayTraceResult rayTrace(@NotNull Consumer<PositionedRayTraceConfigurationBuilder> builderConsumer);
 
     /**
      * Gets the default spawn {@link Location} of this world
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
new file mode 100644
index 000000000000..e71ab887ac06
--- /dev/null
+++ b/paper-server/src/main/java/io/papermc/paper/raytracing/PositionedRayTraceConfigurationBuilderImpl.java
@@ -0,0 +1,134 @@
+package io.papermc.paper.raytracing;
+
+import org.bukkit.FluidCollisionMode;
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.util.RayTraceResult;
+import org.bukkit.util.Vector;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import java.util.List;
+import java.util.function.Predicate;
+
+public class PositionedRayTraceConfigurationBuilderImpl implements PositionedRayTraceConfigurationBuilder {
+
+    private World world;
+    private Location start;
+    private Vector direction;
+    private double maxDistance;
+    private org.bukkit.FluidCollisionMode fluidCollisionMode = org.bukkit.FluidCollisionMode.NEVER;
+    private boolean ignorePassableBlocks;
+    private double raySize = 0.0D;
+    private java.util.function.Predicate<? super org.bukkit.entity.Entity> entityFilter;
+    private java.util.function.Predicate<? super org.bukkit.block.Block> blockFilter;
+    private List<Targets> targets;
+
+    public PositionedRayTraceConfigurationBuilderImpl(World world) {
+        this.world = world;
+    }
+
+
+    @Override
+    public @Nullable Location start() {
+        return this.start;
+    }
+
+    @Override
+    public @NotNull PositionedRayTraceConfigurationBuilder start(final @NotNull Location start) {
+        this.start = start;
+        return this;
+    }
+
+    @Override
+    public @Nullable Vector direction() {
+        return this.direction;
+    }
+
+    @Override
+    public @NotNull PositionedRayTraceConfigurationBuilder direction(final @NotNull Vector direction) {
+        this.direction = direction;
+        return this;
+    }
+
+    @Override
+    public double maxDistance() {
+        return maxDistance;
+    }
+
+    @Override
+    public @NotNull PositionedRayTraceConfigurationBuilder maxDistance(double maxDistance) {
+        this.maxDistance = maxDistance;
+        return this;
+    }
+
+    @Override
+    public @NotNull FluidCollisionMode fluidCollisionMode() {
+        return fluidCollisionMode;
+    }
+
+    @Override
+    public @NotNull PositionedRayTraceConfigurationBuilder fluidCollisionMode(@NotNull FluidCollisionMode fluidCollisionMode) {
+        this.fluidCollisionMode = fluidCollisionMode;
+        return this;
+    }
+
+    @Override
+    public boolean ignorePassableBlocks() {
+        return ignorePassableBlocks;
+    }
+
+    @Override
+    public @NotNull PositionedRayTraceConfigurationBuilder ignorePassableBlocks(boolean ignorePassableBlocks) {
+        this.ignorePassableBlocks = ignorePassableBlocks;
+        return this;
+    }
+
+    @Override
+    public double raySize() {
+        return raySize;
+    }
+
+    @Override
+    public @NotNull PositionedRayTraceConfigurationBuilder raySize(double raySize) {
+        this.raySize = raySize;
+        return this;
+    }
+
+    @Override
+    public @Nullable Predicate<? super org.bukkit.entity.Entity> entityFilter() {
+        return entityFilter;
+    }
+
+    @Override
+    public @NotNull PositionedRayTraceConfigurationBuilder entityFilter(@Nullable Predicate<? super org.bukkit.entity.Entity> entityFilter) {
+        this.entityFilter = entityFilter;
+        return this;
+    }
+
+    @Override
+    public @Nullable Predicate<? super org.bukkit.block.Block> blockFilter() {
+        return blockFilter;
+    }
+
+    @Override
+    public @NotNull PositionedRayTraceConfigurationBuilder blockFilter(@Nullable Predicate<? super org.bukkit.block.Block> blockFilter) {
+        this.blockFilter = blockFilter;
+        return this;
+    }
+
+    @Override
+    public void target(final @NotNull Targets first, final @NotNull Targets... others) {
+        java.util.List<PositionedRayTraceConfigurationBuilder.Targets> targets = new java.util.ArrayList<>(java.util.List.of(others));
+        targets.add(first);
+        this.targets = targets;
+    }
+
+    public RayTraceResult cast() {
+        if (targets.contains(Targets.ENTITIES)) {
+            if(targets.contains(Targets.BLOCKS))
+                return world.rayTrace(this.start, this.direction, this.maxDistance(), this.fluidCollisionMode(), this.ignorePassableBlocks(), this.raySize(), this.entityFilter(), this.blockFilter());
+            return world.rayTraceEntities(this.start, this.direction, this.maxDistance(), this.raySize(), this.entityFilter());
+        }
+        return world.rayTraceBlocks(this.start, this.direction, this.maxDistance(), this.fluidCollisionMode(), this.ignorePassableBlocks(), this.blockFilter());
+    }
+}
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 4b3eb4ff81f5..6424b5dea1c8 100644
--- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1250,14 +1250,12 @@ public RayTraceResult rayTrace(io.papermc.paper.math.Position start, Vector dire
     }
 
     @Override
-    public @org.jetbrains.annotations.Nullable RayTraceResult rayTrace(Location start, Vector direction, io.papermc.paper.raytracing.RayTraceConfiguration config) {
-        List<io.papermc.paper.raytracing.RayTraceConfiguration.Targets> targets = config.targets();
-        if (targets.contains(io.papermc.paper.raytracing.RayTraceConfiguration.Targets.ENTITIES)) {
-            if(targets.contains(io.papermc.paper.raytracing.RayTraceConfiguration.Targets.BLOCKS))
-                return this.rayTrace(start, direction, config.maxDistance(), config.fluidCollisionMode(), config.ignorePassableBlocks(), config.raySize(), config.entityFilter(), config.blockFilter());
-            return this.rayTraceEntities(start, direction, config.maxDistance(), config.raySize(), config.entityFilter());
-        }
-        return this.rayTraceBlocks(start, direction, config.maxDistance(), config.fluidCollisionMode(), config.ignorePassableBlocks(), config.blockFilter());
+    public @org.jetbrains.annotations.Nullable RayTraceResult rayTrace(Consumer<io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilder> builderConsumer) {
+        io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilderImpl builder = new io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilderImpl(this);
+
+        builderConsumer.accept(builder);
+
+        return builder.cast();
     }
 
     @Override

From f393d3262b19f55f4cc7266d673040416c1376c5 Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Sat, 4 Jan 2025 22:27:33 +0100
Subject: [PATCH 03/10] some adjustments

---
 ...PositionedRayTraceConfigurationBuilder.java | 16 +++++++++++++---
 ...tionedRayTraceConfigurationBuilderImpl.java | 18 ++++++++++++------
 .../org/bukkit/craftbukkit/CraftWorld.java     |  6 ++++--
 3 files changed, 29 insertions(+), 11 deletions(-)

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 6144350e3c45..2e9efaa174a6 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
@@ -8,6 +8,7 @@
 import org.jetbrains.annotations.Contract;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import java.util.List;
 import java.util.function.Predicate;
 
 /**
@@ -157,12 +158,21 @@ public interface PositionedRayTraceConfigurationBuilder {
     PositionedRayTraceConfigurationBuilder blockFilter(@Nullable Predicate<? super Block> blockFilter);
 
     /**
-     * Builds a configuration based on the provided targets.
+     * Gets the current set targets.
      *
-     * @return the configuration
+     * @return the targets
+     */
+    @Nullable
+    List<Targets> targets();
+
+    /**
+     * Sets the targets for the rayTrace.
+     *
+     * @return a reference to this object
      */
     @NotNull
-    void target(@NotNull Targets first, @NotNull Targets... others);
+    @Contract("_, _ -> this")
+    PositionedRayTraceConfigurationBuilder targets(@NotNull Targets first, @NotNull Targets... others);
 
     /**
      * List of Targets the builder can target.
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 e71ab887ac06..5883aa13eb0f 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
@@ -29,7 +29,7 @@ public PositionedRayTraceConfigurationBuilderImpl(World world) {
 
 
     @Override
-    public @Nullable Location start() {
+    public @NotNull Location start() {
         return this.start;
     }
 
@@ -40,7 +40,7 @@ public PositionedRayTraceConfigurationBuilderImpl(World world) {
     }
 
     @Override
-    public @Nullable Vector direction() {
+    public @NotNull Vector direction() {
         return this.direction;
     }
 
@@ -117,18 +117,24 @@ public double raySize() {
     }
 
     @Override
-    public void target(final @NotNull Targets first, final @NotNull Targets... others) {
+    public @Nullable List<Targets> targets() {
+        return this.targets;
+    }
+
+    @Override
+    public @NotNull PositionedRayTraceConfigurationBuilder targets(final @NotNull Targets first, final @NotNull Targets... others) {
         java.util.List<PositionedRayTraceConfigurationBuilder.Targets> targets = new java.util.ArrayList<>(java.util.List.of(others));
         targets.add(first);
         this.targets = targets;
+        return this;
     }
 
     public RayTraceResult cast() {
         if (targets.contains(Targets.ENTITIES)) {
             if(targets.contains(Targets.BLOCKS))
-                return world.rayTrace(this.start, this.direction, this.maxDistance(), this.fluidCollisionMode(), this.ignorePassableBlocks(), this.raySize(), this.entityFilter(), this.blockFilter());
-            return world.rayTraceEntities(this.start, this.direction, this.maxDistance(), this.raySize(), this.entityFilter());
+                return world.rayTrace(this.start(), this.direction(), this.maxDistance(), this.fluidCollisionMode(), this.ignorePassableBlocks(), this.raySize(), this.entityFilter(), this.blockFilter());
+            return world.rayTraceEntities(this.start(), this.direction(), this.maxDistance(), this.raySize(), this.entityFilter());
         }
-        return world.rayTraceBlocks(this.start, this.direction, this.maxDistance(), this.fluidCollisionMode(), this.ignorePassableBlocks(), this.blockFilter());
+        return world.rayTraceBlocks(this.start(), this.direction(), this.maxDistance(), this.fluidCollisionMode(), this.ignorePassableBlocks(), this.blockFilter());
     }
 }
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 6424b5dea1c8..6b442b2c6693 100644
--- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -9,6 +9,8 @@
 import io.papermc.paper.registry.RegistryAccess;
 import io.papermc.paper.registry.RegistryKey;
 import io.papermc.paper.raytracing.RayTraceConfiguration;
+import io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilder;
+import io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilderImpl;
 import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
 import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
 import java.io.File;
@@ -1250,8 +1252,8 @@ public RayTraceResult rayTrace(io.papermc.paper.math.Position start, Vector dire
     }
 
     @Override
-    public @org.jetbrains.annotations.Nullable RayTraceResult rayTrace(Consumer<io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilder> builderConsumer) {
-        io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilderImpl builder = new io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilderImpl(this);
+    public @org.jetbrains.annotations.Nullable RayTraceResult rayTrace(Consumer<PositionedRayTraceConfigurationBuilder> builderConsumer) {
+        PositionedRayTraceConfigurationBuilderImpl builder = new PositionedRayTraceConfigurationBuilderImpl(this);
 
         builderConsumer.accept(builder);
 

From baf60582400ff3ebd2754d81111b2978e752e0f3 Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Sun, 5 Jan 2025 21:06:35 +0100
Subject: [PATCH 04/10] jspecify and move Targets

---
 ...ositionedRayTraceConfigurationBuilder.java | 33 +++++--------------
 .../paper/raytracing/RayTraceTargets.java     |  9 +++++
 ...ionedRayTraceConfigurationBuilderImpl.java | 15 +++++----
 3 files changed, 25 insertions(+), 32 deletions(-)
 create mode 100644 paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTargets.java

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 2e9efaa174a6..bcfe452cd44b 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
@@ -6,14 +6,15 @@
 import org.bukkit.entity.Entity;
 import org.bukkit.util.Vector;
 import org.jetbrains.annotations.Contract;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
 import java.util.List;
 import java.util.function.Predicate;
 
 /**
  * Holds information about how to cast a raytrace.
  */
+@NullMarked
 public interface PositionedRayTraceConfigurationBuilder {
 
     /**
@@ -30,9 +31,8 @@ public interface PositionedRayTraceConfigurationBuilder {
      * @param start the new starting location
      * @return a reference to this object
      */
-    @NotNull
     @Contract("_ -> this")
-    PositionedRayTraceConfigurationBuilder start(@NotNull Location start);
+    PositionedRayTraceConfigurationBuilder start(Location start);
 
     /**
      * Gets the direction.
@@ -48,9 +48,8 @@ public interface PositionedRayTraceConfigurationBuilder {
      * @param direction the new direction
      * @return a reference to this object
      */
-    @NotNull
     @Contract("_ -> this")
-    PositionedRayTraceConfigurationBuilder direction(@NotNull Vector direction);
+    PositionedRayTraceConfigurationBuilder direction(Vector direction);
 
     /**
      * Gets the maximum distance.
@@ -65,7 +64,6 @@ public interface PositionedRayTraceConfigurationBuilder {
      * @param maxDistance the new maxDistance
      * @return a reference to this object
      */
-    @NotNull
     @Contract("_ -> this")
     PositionedRayTraceConfigurationBuilder maxDistance(double maxDistance);
 
@@ -74,7 +72,6 @@ public interface PositionedRayTraceConfigurationBuilder {
      *
      * @return the FluidCollisionMode
      */
-    @NotNull
     FluidCollisionMode fluidCollisionMode();
 
     /**
@@ -83,9 +80,8 @@ public interface PositionedRayTraceConfigurationBuilder {
      * @param fluidCollisionMode the new FluidCollisionMode
      * @return a reference to this object
      */
-    @NotNull
     @Contract("_ -> this")
-    PositionedRayTraceConfigurationBuilder fluidCollisionMode(@NotNull FluidCollisionMode fluidCollisionMode);
+    PositionedRayTraceConfigurationBuilder fluidCollisionMode(FluidCollisionMode fluidCollisionMode);
 
     /**
      * Gets if the raytrace will ignore passable blocks when looking for block collisions.
@@ -100,7 +96,6 @@ public interface PositionedRayTraceConfigurationBuilder {
      * @param ignorePassableBlocks if the raytrace should ignore passable blocks
      * @return a reference to this object
      */
-    @NotNull
     @Contract("_ -> this")
     PositionedRayTraceConfigurationBuilder ignorePassableBlocks(boolean ignorePassableBlocks);
 
@@ -117,7 +112,6 @@ public interface PositionedRayTraceConfigurationBuilder {
      * @param raySize the new raytrace size
      * @return a reference to this object
      */
-    @NotNull
     @Contract("_ -> this")
     PositionedRayTraceConfigurationBuilder raySize(double raySize);
 
@@ -135,7 +129,6 @@ public interface PositionedRayTraceConfigurationBuilder {
      * @param entityFilter predicate for entities the ray can potentially collide with, or null to consider all entities
      * @return a reference to this object
      */
-    @NotNull
     @Contract("_ -> this")
     PositionedRayTraceConfigurationBuilder entityFilter(@Nullable Predicate<? super Entity> entityFilter);
 
@@ -153,7 +146,6 @@ public interface PositionedRayTraceConfigurationBuilder {
      * @param blockFilter predicate for blocks the ray can potentially collide with, or null to consider all blocks
      * @return a reference to this object
      */
-    @NotNull
     @Contract("_ -> this")
     PositionedRayTraceConfigurationBuilder blockFilter(@Nullable Predicate<? super Block> blockFilter);
 
@@ -163,22 +155,13 @@ public interface PositionedRayTraceConfigurationBuilder {
      * @return the targets
      */
     @Nullable
-    List<Targets> targets();
+    List<RayTraceTargets> targets();
 
     /**
      * Sets the targets for the rayTrace.
      *
      * @return a reference to this object
      */
-    @NotNull
     @Contract("_, _ -> this")
-    PositionedRayTraceConfigurationBuilder targets(@NotNull Targets first, @NotNull Targets... others);
-
-    /**
-     * List of Targets the builder can target.
-     */
-    enum Targets {
-        ENTITIES,
-        BLOCKS
-    }
+    PositionedRayTraceConfigurationBuilder targets(RayTraceTargets first, RayTraceTargets... others);
 }
diff --git a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTargets.java b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTargets.java
new file mode 100644
index 000000000000..77c5ba6758e4
--- /dev/null
+++ b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTargets.java
@@ -0,0 +1,9 @@
+package io.papermc.paper.raytracing;
+
+/**
+ * List of Targets a builder can target.
+ */
+public enum RayTraceTargets {
+    ENTITIES,
+    BLOCKS
+}
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 5883aa13eb0f..1a8cbe080c02 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
@@ -7,6 +7,7 @@
 import org.bukkit.util.Vector;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.function.Predicate;
 
@@ -21,7 +22,7 @@ public class PositionedRayTraceConfigurationBuilderImpl implements PositionedRay
     private double raySize = 0.0D;
     private java.util.function.Predicate<? super org.bukkit.entity.Entity> entityFilter;
     private java.util.function.Predicate<? super org.bukkit.block.Block> blockFilter;
-    private List<Targets> targets;
+    private List<RayTraceTargets> targets;
 
     public PositionedRayTraceConfigurationBuilderImpl(World world) {
         this.world = world;
@@ -34,7 +35,7 @@ public PositionedRayTraceConfigurationBuilderImpl(World world) {
     }
 
     @Override
-    public @NotNull PositionedRayTraceConfigurationBuilder start(final @NotNull Location start) {
+    public PositionedRayTraceConfigurationBuilder start(final @NotNull Location start) {
         this.start = start;
         return this;
     }
@@ -117,21 +118,21 @@ public double raySize() {
     }
 
     @Override
-    public @Nullable List<Targets> targets() {
+    public @Nullable List<RayTraceTargets> targets() {
         return this.targets;
     }
 
     @Override
-    public @NotNull PositionedRayTraceConfigurationBuilder targets(final @NotNull Targets first, final @NotNull Targets... others) {
-        java.util.List<PositionedRayTraceConfigurationBuilder.Targets> targets = new java.util.ArrayList<>(java.util.List.of(others));
+    public @NotNull PositionedRayTraceConfigurationBuilder targets(final @NotNull RayTraceTargets first, final @NotNull RayTraceTargets... others) {
+        List<RayTraceTargets> targets = new ArrayList<>(List.of(others));
         targets.add(first);
         this.targets = targets;
         return this;
     }
 
     public RayTraceResult cast() {
-        if (targets.contains(Targets.ENTITIES)) {
-            if(targets.contains(Targets.BLOCKS))
+        if (targets.contains(RayTraceTargets.ENTITIES)) {
+            if(targets.contains(RayTraceTargets.BLOCKS))
                 return world.rayTrace(this.start(), this.direction(), this.maxDistance(), this.fluidCollisionMode(), this.ignorePassableBlocks(), this.raySize(), this.entityFilter(), this.blockFilter());
             return world.rayTraceEntities(this.start(), this.direction(), this.maxDistance(), this.raySize(), this.entityFilter());
         }

From 39b126703913b024d0499c858c74f999bb56644d Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Tue, 7 Jan 2025 19:46:32 +0100
Subject: [PATCH 05/10] singular

---
 .../PositionedRayTraceConfigurationBuilder.java      |  4 ++--
 .../{RayTraceTargets.java => RayTraceTarget.java}    |  2 +-
 .../PositionedRayTraceConfigurationBuilderImpl.java  | 12 ++++++------
 3 files changed, 9 insertions(+), 9 deletions(-)
 rename paper-api/src/main/java/io/papermc/paper/raytracing/{RayTraceTargets.java => RayTraceTarget.java} (79%)

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 bcfe452cd44b..66de82b0b9b2 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
@@ -155,7 +155,7 @@ public interface PositionedRayTraceConfigurationBuilder {
      * @return the targets
      */
     @Nullable
-    List<RayTraceTargets> targets();
+    List<RayTraceTarget> targets();
 
     /**
      * Sets the targets for the rayTrace.
@@ -163,5 +163,5 @@ public interface PositionedRayTraceConfigurationBuilder {
      * @return a reference to this object
      */
     @Contract("_, _ -> this")
-    PositionedRayTraceConfigurationBuilder targets(RayTraceTargets first, RayTraceTargets... others);
+    PositionedRayTraceConfigurationBuilder targets(RayTraceTarget first, RayTraceTarget... others);
 }
diff --git a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTargets.java b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTarget.java
similarity index 79%
rename from paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTargets.java
rename to paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTarget.java
index 77c5ba6758e4..bfb1df4e5983 100644
--- a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTargets.java
+++ b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTarget.java
@@ -3,7 +3,7 @@
 /**
  * List of Targets a builder can target.
  */
-public enum RayTraceTargets {
+public enum RayTraceTarget {
     ENTITIES,
     BLOCKS
 }
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 1a8cbe080c02..d3b75cd7e7f8 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
@@ -22,7 +22,7 @@ public class PositionedRayTraceConfigurationBuilderImpl implements PositionedRay
     private double raySize = 0.0D;
     private java.util.function.Predicate<? super org.bukkit.entity.Entity> entityFilter;
     private java.util.function.Predicate<? super org.bukkit.block.Block> blockFilter;
-    private List<RayTraceTargets> targets;
+    private List<RayTraceTarget> targets;
 
     public PositionedRayTraceConfigurationBuilderImpl(World world) {
         this.world = world;
@@ -118,21 +118,21 @@ public double raySize() {
     }
 
     @Override
-    public @Nullable List<RayTraceTargets> targets() {
+    public @Nullable List<RayTraceTarget> targets() {
         return this.targets;
     }
 
     @Override
-    public @NotNull PositionedRayTraceConfigurationBuilder targets(final @NotNull RayTraceTargets first, final @NotNull RayTraceTargets... others) {
-        List<RayTraceTargets> targets = new ArrayList<>(List.of(others));
+    public @NotNull PositionedRayTraceConfigurationBuilder targets(final @NotNull RayTraceTarget first, final @NotNull RayTraceTarget... others) {
+        List<RayTraceTarget> targets = new ArrayList<>(List.of(others));
         targets.add(first);
         this.targets = targets;
         return this;
     }
 
     public RayTraceResult cast() {
-        if (targets.contains(RayTraceTargets.ENTITIES)) {
-            if(targets.contains(RayTraceTargets.BLOCKS))
+        if (targets.contains(RayTraceTarget.ENTITIES)) {
+            if(targets.contains(RayTraceTarget.BLOCKS))
                 return world.rayTrace(this.start(), this.direction(), this.maxDistance(), this.fluidCollisionMode(), this.ignorePassableBlocks(), this.raySize(), this.entityFilter(), this.blockFilter());
             return world.rayTraceEntities(this.start(), this.direction(), this.maxDistance(), this.raySize(), this.entityFilter());
         }

From a557574287d2ee98e2f2baf782c3fac298c1fb2a Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Mon, 13 Jan 2025 14:16:25 +0100
Subject: [PATCH 06/10] move some stuff

---
 ...ionedRayTraceConfigurationBuilderImpl.java | 49 ++++++-------------
 .../org/bukkit/craftbukkit/CraftWorld.java    | 15 ++++--
 2 files changed, 25 insertions(+), 39 deletions(-)

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 d3b75cd7e7f8..a29c65bc8f1f 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
@@ -2,18 +2,13 @@
 
 import org.bukkit.FluidCollisionMode;
 import org.bukkit.Location;
-import org.bukkit.World;
-import org.bukkit.util.RayTraceResult;
 import org.bukkit.util.Vector;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.function.Predicate;
 
 public class PositionedRayTraceConfigurationBuilderImpl implements PositionedRayTraceConfigurationBuilder {
 
-    private World world;
     private Location start;
     private Vector direction;
     private double maxDistance;
@@ -24,29 +19,24 @@ public class PositionedRayTraceConfigurationBuilderImpl implements PositionedRay
     private java.util.function.Predicate<? super org.bukkit.block.Block> blockFilter;
     private List<RayTraceTarget> targets;
 
-    public PositionedRayTraceConfigurationBuilderImpl(World world) {
-        this.world = world;
-    }
-
-
     @Override
-    public @NotNull Location start() {
+    public Location start() {
         return this.start;
     }
 
     @Override
-    public PositionedRayTraceConfigurationBuilder start(final @NotNull Location start) {
+    public PositionedRayTraceConfigurationBuilder start(final Location start) {
         this.start = start;
         return this;
     }
 
     @Override
-    public @NotNull Vector direction() {
+    public Vector direction() {
         return this.direction;
     }
 
     @Override
-    public @NotNull PositionedRayTraceConfigurationBuilder direction(final @NotNull Vector direction) {
+    public PositionedRayTraceConfigurationBuilder direction(final Vector direction) {
         this.direction = direction;
         return this;
     }
@@ -57,18 +47,18 @@ public double maxDistance() {
     }
 
     @Override
-    public @NotNull PositionedRayTraceConfigurationBuilder maxDistance(double maxDistance) {
+    public PositionedRayTraceConfigurationBuilder maxDistance(double maxDistance) {
         this.maxDistance = maxDistance;
         return this;
     }
 
     @Override
-    public @NotNull FluidCollisionMode fluidCollisionMode() {
+    public FluidCollisionMode fluidCollisionMode() {
         return fluidCollisionMode;
     }
 
     @Override
-    public @NotNull PositionedRayTraceConfigurationBuilder fluidCollisionMode(@NotNull FluidCollisionMode fluidCollisionMode) {
+    public PositionedRayTraceConfigurationBuilder fluidCollisionMode(FluidCollisionMode fluidCollisionMode) {
         this.fluidCollisionMode = fluidCollisionMode;
         return this;
     }
@@ -79,7 +69,7 @@ public boolean ignorePassableBlocks() {
     }
 
     @Override
-    public @NotNull PositionedRayTraceConfigurationBuilder ignorePassableBlocks(boolean ignorePassableBlocks) {
+    public PositionedRayTraceConfigurationBuilder ignorePassableBlocks(boolean ignorePassableBlocks) {
         this.ignorePassableBlocks = ignorePassableBlocks;
         return this;
     }
@@ -90,52 +80,43 @@ public double raySize() {
     }
 
     @Override
-    public @NotNull PositionedRayTraceConfigurationBuilder raySize(double raySize) {
+    public PositionedRayTraceConfigurationBuilder raySize(double raySize) {
         this.raySize = raySize;
         return this;
     }
 
     @Override
-    public @Nullable Predicate<? super org.bukkit.entity.Entity> entityFilter() {
+    public Predicate<? super org.bukkit.entity.Entity> entityFilter() {
         return entityFilter;
     }
 
     @Override
-    public @NotNull PositionedRayTraceConfigurationBuilder entityFilter(@Nullable Predicate<? super org.bukkit.entity.Entity> entityFilter) {
+    public PositionedRayTraceConfigurationBuilder entityFilter(Predicate<? super org.bukkit.entity.Entity> entityFilter) {
         this.entityFilter = entityFilter;
         return this;
     }
 
     @Override
-    public @Nullable Predicate<? super org.bukkit.block.Block> blockFilter() {
+    public Predicate<? super org.bukkit.block.Block> blockFilter() {
         return blockFilter;
     }
 
     @Override
-    public @NotNull PositionedRayTraceConfigurationBuilder blockFilter(@Nullable Predicate<? super org.bukkit.block.Block> blockFilter) {
+    public PositionedRayTraceConfigurationBuilder blockFilter(Predicate<? super org.bukkit.block.Block> blockFilter) {
         this.blockFilter = blockFilter;
         return this;
     }
 
     @Override
-    public @Nullable List<RayTraceTarget> targets() {
+    public List<RayTraceTarget> targets() {
         return this.targets;
     }
 
     @Override
-    public @NotNull PositionedRayTraceConfigurationBuilder targets(final @NotNull RayTraceTarget first, final @NotNull RayTraceTarget... others) {
+    public PositionedRayTraceConfigurationBuilder targets(final RayTraceTarget first, final RayTraceTarget ... others) {
         List<RayTraceTarget> targets = new ArrayList<>(List.of(others));
         targets.add(first);
         this.targets = targets;
         return this;
     }
-
-    public RayTraceResult cast() {
-        if (targets.contains(RayTraceTarget.ENTITIES)) {
-            if(targets.contains(RayTraceTarget.BLOCKS))
-                return world.rayTrace(this.start(), this.direction(), this.maxDistance(), this.fluidCollisionMode(), this.ignorePassableBlocks(), this.raySize(), this.entityFilter(), this.blockFilter());
-            return world.rayTraceEntities(this.start(), this.direction(), this.maxDistance(), this.raySize(), this.entityFilter());
-        }
-        return world.rayTraceBlocks(this.start(), this.direction(), this.maxDistance(), this.fluidCollisionMode(), this.ignorePassableBlocks(), this.blockFilter());
-    }
 }
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 6b442b2c6693..c4376b6251ec 100644
--- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -6,12 +6,12 @@
 import com.google.common.collect.ImmutableMap;
 import com.mojang.datafixers.util.Pair;
 import io.papermc.paper.FeatureHooks;
+import io.papermc.paper.raytracing.RayTraceTarget;
 import io.papermc.paper.registry.RegistryAccess;
 import io.papermc.paper.registry.RegistryKey;
-import io.papermc.paper.raytracing.RayTraceConfiguration;
+import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
 import io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilder;
 import io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilderImpl;
-import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
 import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
 import java.io.File;
 import java.util.ArrayList;
@@ -1252,12 +1252,17 @@ public RayTraceResult rayTrace(io.papermc.paper.math.Position start, Vector dire
     }
 
     @Override
-    public @org.jetbrains.annotations.Nullable RayTraceResult rayTrace(Consumer<PositionedRayTraceConfigurationBuilder> builderConsumer) {
-        PositionedRayTraceConfigurationBuilderImpl builder = new PositionedRayTraceConfigurationBuilderImpl(this);
+    public RayTraceResult rayTrace(Consumer<PositionedRayTraceConfigurationBuilder> builderConsumer) {
+        PositionedRayTraceConfigurationBuilderImpl builder = new PositionedRayTraceConfigurationBuilderImpl();
 
         builderConsumer.accept(builder);
 
-        return builder.cast();
+        if (builder.targets().contains(RayTraceTarget.ENTITIES)) {
+            if(builder.targets().contains(RayTraceTarget.BLOCKS))
+                return this.rayTrace(builder.start(), builder.direction(), builder.maxDistance(), builder.fluidCollisionMode(), builder.ignorePassableBlocks(), builder.raySize(), builder.entityFilter(), builder.blockFilter());
+            return this.rayTraceEntities(builder.start(), builder.direction(), builder.maxDistance(), builder.raySize(), builder.entityFilter());
+        }
+        return this.rayTraceBlocks(builder.start(), builder.direction(), builder.maxDistance(), builder.fluidCollisionMode(), builder.ignorePassableBlocks(), builder.blockFilter());
     }
 
     @Override

From 17fa8768d8b1b23a8f379adae28fc0928ea326a9 Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Tue, 14 Jan 2025 17:06:59 +0100
Subject: [PATCH 07/10] mutability

---
 .../papermc/paper/raytracing/RayTraceTarget.java   |  4 ++--
 ...PositionedRayTraceConfigurationBuilderImpl.java | 14 ++++++++------
 .../java/org/bukkit/craftbukkit/CraftWorld.java    |  4 ++--
 3 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTarget.java b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTarget.java
index bfb1df4e5983..19820201ce55 100644
--- a/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTarget.java
+++ b/paper-api/src/main/java/io/papermc/paper/raytracing/RayTraceTarget.java
@@ -4,6 +4,6 @@
  * List of Targets a builder can target.
  */
 public enum RayTraceTarget {
-    ENTITIES,
-    BLOCKS
+    ENTITY,
+    BLOCK
 }
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 a29c65bc8f1f..0318cdff0a1e 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
@@ -3,7 +3,9 @@
 import org.bukkit.FluidCollisionMode;
 import org.bukkit.Location;
 import org.bukkit.util.Vector;
+import org.jetbrains.annotations.UnmodifiableView;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.function.Predicate;
 
@@ -21,23 +23,23 @@ public class PositionedRayTraceConfigurationBuilderImpl implements PositionedRay
 
     @Override
     public Location start() {
-        return this.start;
+        return this.start.clone();
     }
 
     @Override
     public PositionedRayTraceConfigurationBuilder start(final Location start) {
-        this.start = start;
+        this.start = start.clone();
         return this;
     }
 
     @Override
     public Vector direction() {
-        return this.direction;
+        return this.direction.clone();
     }
 
     @Override
     public PositionedRayTraceConfigurationBuilder direction(final Vector direction) {
-        this.direction = direction;
+        this.direction = direction.clone();
         return this;
     }
 
@@ -108,8 +110,8 @@ public PositionedRayTraceConfigurationBuilder blockFilter(Predicate<? super org.
     }
 
     @Override
-    public List<RayTraceTarget> targets() {
-        return this.targets;
+    public @UnmodifiableView List<RayTraceTarget> targets() {
+        return Collections.unmodifiableList(this.targets);
     }
 
     @Override
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 c4376b6251ec..d11334779a99 100644
--- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1257,8 +1257,8 @@ public RayTraceResult rayTrace(Consumer<PositionedRayTraceConfigurationBuilder>
 
         builderConsumer.accept(builder);
 
-        if (builder.targets().contains(RayTraceTarget.ENTITIES)) {
-            if(builder.targets().contains(RayTraceTarget.BLOCKS))
+        if (builder.targets().contains(RayTraceTarget.ENTITY)) {
+            if(builder.targets().contains(RayTraceTarget.BLOCK))
                 return this.rayTrace(builder.start(), builder.direction(), builder.maxDistance(), builder.fluidCollisionMode(), builder.ignorePassableBlocks(), builder.raySize(), builder.entityFilter(), builder.blockFilter());
             return this.rayTraceEntities(builder.start(), builder.direction(), builder.maxDistance(), builder.raySize(), builder.entityFilter());
         }

From 191ee04bbb21aa64a987dca2da917fef8ac01c6b Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Wed, 22 Jan 2025 17:44:35 +0100
Subject: [PATCH 08/10] implement requests

---
 .../PositionedRayTraceConfigurationBuilder.java | 12 ++++++++++++
 paper-api/src/main/java/org/bukkit/World.java   | 17 ++++-------------
 ...itionedRayTraceConfigurationBuilderImpl.java |  6 ++++--
 3 files changed, 20 insertions(+), 15 deletions(-)

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 66de82b0b9b2..c843f5e6d3ae 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
@@ -76,6 +76,9 @@ public interface PositionedRayTraceConfigurationBuilder {
 
     /**
      * Sets the FluidCollisionMode when looking for block collisions.
+     * <p>
+     * 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
@@ -92,6 +95,13 @@ public interface PositionedRayTraceConfigurationBuilder {
 
     /**
      * Gets if the raytrace will ignore passable blocks when looking for block collisions.
+     * <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.
      *
      * @param ignorePassableBlocks if the raytrace should ignore passable blocks
      * @return a reference to this object
@@ -101,6 +111,8 @@ public interface PositionedRayTraceConfigurationBuilder {
 
     /**
      * Gets the size of the raytrace when looking for entity collisions.
+     * <p>
+     * Block collisions use the blocks' precise collision shapes.
      *
      * @return the raytrace size
      */
diff --git a/paper-api/src/main/java/org/bukkit/World.java b/paper-api/src/main/java/org/bukkit/World.java
index d23b54a3c984..8784842d14bb 100644
--- a/paper-api/src/main/java/org/bukkit/World.java
+++ b/paper-api/src/main/java/org/bukkit/World.java
@@ -1940,23 +1940,14 @@ default Iterable<? extends net.kyori.adventure.audience.Audience> audiences() {
     // Paper end
 
     /**
-     * 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.
+     * Performs a ray trace that checks for collisions with the specified
+     * targets.
      * <p>
      * This may cause loading of chunks! Some implementations may impose
      * artificial restrictions on the maximum distance.
      *
-     * @param builderConsumer consumer for the builder
+     * @param builderConsumer a consumer to configure the ray trace configuration.
+     *     The received builder is not valid for use outside the consumer
      * @return the closest ray trace hit result with either a block or an
      *     entity, or <code>null</code> if there is no hit
      */
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 0318cdff0a1e..b606977382d6 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,11 +4,13 @@
 import org.bukkit.Location;
 import org.bukkit.util.Vector;
 import org.jetbrains.annotations.UnmodifiableView;
+import org.jspecify.annotations.NullMarked;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.function.Predicate;
 
+@NullMarked
 public class PositionedRayTraceConfigurationBuilderImpl implements PositionedRayTraceConfigurationBuilder {
 
     private Location start;
@@ -23,7 +25,7 @@ public class PositionedRayTraceConfigurationBuilderImpl implements PositionedRay
 
     @Override
     public Location start() {
-        return this.start.clone();
+        return this.start == null ? null : this.start.clone();
     }
 
     @Override
@@ -34,7 +36,7 @@ public PositionedRayTraceConfigurationBuilder start(final Location start) {
 
     @Override
     public Vector direction() {
-        return this.direction.clone();
+        return this.direction == null ? null : this.direction.clone();
     }
 
     @Override

From 29e4bb8a9624bdfbd199b068c3c224d8237d142a Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Wed, 22 Jan 2025 17:47:58 +0100
Subject: [PATCH 09/10] Nullable annotation on vars

---
 .../raytracing/PositionedRayTraceConfigurationBuilderImpl.java | 3 +++
 1 file changed, 3 insertions(+)

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 b606977382d6..faef103afe0b 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
@@ -5,6 +5,7 @@
 import org.bukkit.util.Vector;
 import org.jetbrains.annotations.UnmodifiableView;
 import org.jspecify.annotations.NullMarked;
+import org.jspecify.annotations.Nullable;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -13,7 +14,9 @@
 @NullMarked
 public class PositionedRayTraceConfigurationBuilderImpl implements PositionedRayTraceConfigurationBuilder {
 
+    @Nullable
     private Location start;
+    @Nullable
     private Vector direction;
     private double maxDistance;
     private org.bukkit.FluidCollisionMode fluidCollisionMode = org.bukkit.FluidCollisionMode.NEVER;

From 1242322cde5ff120774932cb2a56a5ca6507b20a Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Wed, 22 Jan 2025 21:44:06 +0100
Subject: [PATCH 10/10] a

---
 ...ositionedRayTraceConfigurationBuilder.java |  7 +++--
 ...ionedRayTraceConfigurationBuilderImpl.java | 31 ++++++++++---------
 .../org/bukkit/craftbukkit/CraftWorld.java    |  2 +-
 3 files changed, 21 insertions(+), 19 deletions(-)

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 c843f5e6d3ae..eb87c12a3f5f 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
@@ -8,7 +8,7 @@
 import org.jetbrains.annotations.Contract;
 import org.jspecify.annotations.NullMarked;
 import org.jspecify.annotations.Nullable;
-import java.util.List;
+import java.util.Set;
 import java.util.function.Predicate;
 
 /**
@@ -94,7 +94,8 @@ public interface PositionedRayTraceConfigurationBuilder {
     boolean ignorePassableBlocks();
 
     /**
-     * Gets if the raytrace will ignore passable blocks when looking for block collisions.
+     * Sets whether the raytrace should ignore passable blocks when looking for
+     * block collisions.
      * <p>
      * If collisions with passable blocks are ignored, fluid collisions are
      * ignored as well regardless of the fluid collision mode.
@@ -167,7 +168,7 @@ public interface PositionedRayTraceConfigurationBuilder {
      * @return the targets
      */
     @Nullable
-    List<RayTraceTarget> targets();
+    Set<RayTraceTarget> targets();
 
     /**
      * Sets the targets for the rayTrace.
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 faef103afe0b..c1d79b81bbd9 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
@@ -2,13 +2,15 @@
 
 import org.bukkit.FluidCollisionMode;
 import org.bukkit.Location;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Entity;
 import org.bukkit.util.Vector;
 import org.jetbrains.annotations.UnmodifiableView;
 import org.jspecify.annotations.NullMarked;
 import org.jspecify.annotations.Nullable;
-import java.util.ArrayList;
 import java.util.Collections;
-import java.util.List;
+import java.util.EnumSet;
+import java.util.Set;
 import java.util.function.Predicate;
 
 @NullMarked
@@ -19,12 +21,13 @@ public class PositionedRayTraceConfigurationBuilderImpl implements PositionedRay
     @Nullable
     private Vector direction;
     private double maxDistance;
-    private org.bukkit.FluidCollisionMode fluidCollisionMode = org.bukkit.FluidCollisionMode.NEVER;
+    private FluidCollisionMode fluidCollisionMode = FluidCollisionMode.NEVER;
     private boolean ignorePassableBlocks;
     private double raySize = 0.0D;
-    private java.util.function.Predicate<? super org.bukkit.entity.Entity> entityFilter;
-    private java.util.function.Predicate<? super org.bukkit.block.Block> blockFilter;
-    private List<RayTraceTarget> targets;
+    private Predicate<? super Entity> entityFilter;
+    private Predicate<? super Block> blockFilter;
+    @Nullable
+    private EnumSet<RayTraceTarget> targets;
 
     @Override
     public Location start() {
@@ -93,37 +96,35 @@ public PositionedRayTraceConfigurationBuilder raySize(double raySize) {
     }
 
     @Override
-    public Predicate<? super org.bukkit.entity.Entity> entityFilter() {
+    public Predicate<? super Entity> entityFilter() {
         return entityFilter;
     }
 
     @Override
-    public PositionedRayTraceConfigurationBuilder entityFilter(Predicate<? super org.bukkit.entity.Entity> entityFilter) {
+    public PositionedRayTraceConfigurationBuilder entityFilter(Predicate<? super Entity> entityFilter) {
         this.entityFilter = entityFilter;
         return this;
     }
 
     @Override
-    public Predicate<? super org.bukkit.block.Block> blockFilter() {
+    public Predicate<? super Block> blockFilter() {
         return blockFilter;
     }
 
     @Override
-    public PositionedRayTraceConfigurationBuilder blockFilter(Predicate<? super org.bukkit.block.Block> blockFilter) {
+    public PositionedRayTraceConfigurationBuilder blockFilter(Predicate<? super Block> blockFilter) {
         this.blockFilter = blockFilter;
         return this;
     }
 
     @Override
-    public @UnmodifiableView List<RayTraceTarget> targets() {
-        return Collections.unmodifiableList(this.targets);
+    public @UnmodifiableView Set<RayTraceTarget> targets() {
+        return this.targets == null ? Set.of() : Collections.unmodifiableSet(this.targets);
     }
 
     @Override
     public PositionedRayTraceConfigurationBuilder targets(final RayTraceTarget first, final RayTraceTarget ... others) {
-        List<RayTraceTarget> targets = new ArrayList<>(List.of(others));
-        targets.add(first);
-        this.targets = targets;
+        this.targets = EnumSet.of(first, others);
         return this;
     }
 }
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 d11334779a99..fbf6fcac6642 100644
--- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1258,7 +1258,7 @@ public RayTraceResult rayTrace(Consumer<PositionedRayTraceConfigurationBuilder>
         builderConsumer.accept(builder);
 
         if (builder.targets().contains(RayTraceTarget.ENTITY)) {
-            if(builder.targets().contains(RayTraceTarget.BLOCK))
+            if (builder.targets().contains(RayTraceTarget.BLOCK))
                 return this.rayTrace(builder.start(), builder.direction(), builder.maxDistance(), builder.fluidCollisionMode(), builder.ignorePassableBlocks(), builder.raySize(), builder.entityFilter(), builder.blockFilter());
             return this.rayTraceEntities(builder.start(), builder.direction(), builder.maxDistance(), builder.raySize(), builder.entityFilter());
         }