Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RayTraceConfigurationBuilder #11907

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
notTamion marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
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.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 {

/**
* 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
*/
@Contract("_ -> this")
PositionedRayTraceConfigurationBuilder start(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
*/
@Contract("_ -> this")
PositionedRayTraceConfigurationBuilder direction(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
*/
@Contract("_ -> this")
PositionedRayTraceConfigurationBuilder maxDistance(double maxDistance);

/**
* Gets the FluidCollisionMode when looking for block collisions.
*
* @return the FluidCollisionMode
*/
FluidCollisionMode fluidCollisionMode();

/**
* Sets the FluidCollisionMode when looking for block collisions.
*
* @param fluidCollisionMode the new FluidCollisionMode
* @return a reference to this object
*/
@Contract("_ -> this")
PositionedRayTraceConfigurationBuilder fluidCollisionMode(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
*/
@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
*/
@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
*/
@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
*/
@Contract("_ -> this")
PositionedRayTraceConfigurationBuilder blockFilter(@Nullable Predicate<? super Block> blockFilter);

/**
* Gets the current set targets.
*
* @return the targets
*/
@Nullable
List<RayTraceTarget> targets();

/**
* Sets the targets for the rayTrace.
*
* @return a reference to this object
*/
@Contract("_, _ -> this")
PositionedRayTraceConfigurationBuilder targets(RayTraceTarget first, RayTraceTarget... others);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.papermc.paper.raytracing;

/**
* List of Targets a builder can target.
*/
public enum RayTraceTarget {
ENTITIES,
BLOCKS
}
24 changes: 24 additions & 0 deletions paper-api/src/main/java/org/bukkit/World.java
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -1938,6 +1939,29 @@ 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 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 Consumer<PositionedRayTraceConfigurationBuilder> builderConsumer);

/**
* Gets the default spawn {@link Location} of this world
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
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.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;
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<RayTraceTarget> targets;

public PositionedRayTraceConfigurationBuilderImpl(World world) {
this.world = world;
}


@Override
public @NotNull Location start() {
return this.start;
}

@Override
public PositionedRayTraceConfigurationBuilder start(final @NotNull Location start) {
this.start = start;
return this;
}

@Override
public @NotNull 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 @Nullable List<RayTraceTarget> targets() {
return this.targets;
}

@Override
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(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());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
import io.papermc.paper.FeatureHooks;
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;
Expand Down Expand Up @@ -1246,6 +1248,15 @@ public RayTraceResult rayTrace(io.papermc.paper.math.Position start, Vector dire
return blockHit;
}

@Override
public @org.jetbrains.annotations.Nullable RayTraceResult rayTrace(Consumer<PositionedRayTraceConfigurationBuilder> builderConsumer) {
PositionedRayTraceConfigurationBuilderImpl builder = new PositionedRayTraceConfigurationBuilderImpl(this);

builderConsumer.accept(builder);

return builder.cast();
}

@Override
public List<Player> getPlayers() {
List<Player> list = new ArrayList<Player>(this.world.players().size());
Expand Down
Loading