Skip to content

Commit

Permalink
Add RayTraceConfiguration
Browse files Browse the repository at this point in the history
  • Loading branch information
notTamion committed Jan 4, 2025
1 parent edde726 commit 48c4d68
Show file tree
Hide file tree
Showing 5 changed files with 351 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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 {
}
25 changes: 25 additions & 0 deletions paper-api/src/main/java/org/bukkit/World.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down
12 changes: 12 additions & 0 deletions paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
import io.papermc.paper.FeatureHooks;
import io.papermc.paper.raytracing.RayTraceConfiguration;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.io.File;
Expand Down Expand Up @@ -1246,6 +1247,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());
Expand Down

0 comments on commit 48c4d68

Please sign in to comment.