mirror of
https://github.com/PaperMC/Paper.git
synced 2025-05-19 05:30:23 -07:00
Add RayTraceConfigurationBuilder (#11907)
This commit is contained in:
parent
336ea9dfeb
commit
939bb7828f
@ -0,0 +1,112 @@
|
|||||||
|
package io.papermc.paper.raytracing;
|
||||||
|
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
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.checkerframework.checker.index.qual.NonNegative;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder for configuring a raytrace with a starting location
|
||||||
|
* and direction.
|
||||||
|
*/
|
||||||
|
@NullMarked
|
||||||
|
public interface PositionedRayTraceConfigurationBuilder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the starting location.
|
||||||
|
*
|
||||||
|
* @param start the new starting location
|
||||||
|
* @return a reference to this object
|
||||||
|
*/
|
||||||
|
@Contract(value = "_ -> this", mutates = "this")
|
||||||
|
PositionedRayTraceConfigurationBuilder start(Location start);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the direction.
|
||||||
|
*
|
||||||
|
* @param direction the new direction
|
||||||
|
* @return a reference to this object
|
||||||
|
*/
|
||||||
|
@Contract(value = "_ -> this", mutates = "this")
|
||||||
|
PositionedRayTraceConfigurationBuilder direction(Vector direction);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the maximum distance.
|
||||||
|
*
|
||||||
|
* @param maxDistance the new maxDistance
|
||||||
|
* @return a reference to this object
|
||||||
|
*/
|
||||||
|
@Contract(value = "_ -> this", mutates = "this")
|
||||||
|
PositionedRayTraceConfigurationBuilder maxDistance(@NonNegative double maxDistance);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
@Contract(value = "_ -> this", mutates = "this")
|
||||||
|
PositionedRayTraceConfigurationBuilder fluidCollisionMode(FluidCollisionMode fluidCollisionMode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
* <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
|
||||||
|
*/
|
||||||
|
@Contract(value = "_ -> this", mutates = "this")
|
||||||
|
PositionedRayTraceConfigurationBuilder ignorePassableBlocks(boolean ignorePassableBlocks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the size of the raytrace when looking for entity collisions.
|
||||||
|
*
|
||||||
|
* @param raySize the new raytrace size
|
||||||
|
* @return a reference to this object
|
||||||
|
*/
|
||||||
|
@Contract(value = "_ -> this", mutates = "this")
|
||||||
|
PositionedRayTraceConfigurationBuilder raySize(@NonNegative double raySize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current entity filter when looking for entity collisions.
|
||||||
|
*
|
||||||
|
* @param entityFilter predicate for entities the ray can potentially collide with
|
||||||
|
* @return a reference to this object
|
||||||
|
*/
|
||||||
|
@Contract(value = "_ -> this", mutates = "this")
|
||||||
|
PositionedRayTraceConfigurationBuilder entityFilter(Predicate<? super Entity> entityFilter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current block filter when looking for block collisions.
|
||||||
|
*
|
||||||
|
* @param blockFilter predicate for blocks the ray can potentially collide with
|
||||||
|
* @return a reference to this object
|
||||||
|
*/
|
||||||
|
@Contract(value = "_ -> this", mutates = "this")
|
||||||
|
PositionedRayTraceConfigurationBuilder blockFilter(Predicate<? super Block> blockFilter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the targets for the rayTrace.
|
||||||
|
*
|
||||||
|
* @param first the first target
|
||||||
|
* @param others the other targets
|
||||||
|
* @return a reference to this object
|
||||||
|
*/
|
||||||
|
@Contract(value = "_, _ -> this", mutates = "this")
|
||||||
|
PositionedRayTraceConfigurationBuilder targets(RayTraceTarget first, RayTraceTarget... others);
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package io.papermc.paper.raytracing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of Targets a builder can target.
|
||||||
|
*/
|
||||||
|
public enum RayTraceTarget {
|
||||||
|
ENTITY,
|
||||||
|
BLOCK
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package org.bukkit;
|
package org.bukkit;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilder;
|
||||||
import org.bukkit.generator.ChunkGenerator;
|
import org.bukkit.generator.ChunkGenerator;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -1938,6 +1939,20 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
|||||||
@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);
|
@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
|
// Paper end
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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
|
||||||
|
*/
|
||||||
|
@Nullable RayTraceResult rayTrace(@NotNull Consumer<PositionedRayTraceConfigurationBuilder> builderConsumer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the default spawn {@link Location} of this world
|
* Gets the default spawn {@link Location} of this world
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
package io.papermc.paper.raytracing;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.OptionalDouble;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
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.jspecify.annotations.NullMarked;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
@NullMarked
|
||||||
|
public class PositionedRayTraceConfigurationBuilderImpl implements PositionedRayTraceConfigurationBuilder {
|
||||||
|
|
||||||
|
public @Nullable Location start;
|
||||||
|
public @Nullable Vector direction;
|
||||||
|
public OptionalDouble maxDistance = OptionalDouble.empty();
|
||||||
|
public FluidCollisionMode fluidCollisionMode = FluidCollisionMode.NEVER;
|
||||||
|
public boolean ignorePassableBlocks;
|
||||||
|
public double raySize = 0.0D;
|
||||||
|
public @Nullable Predicate<? super Entity> entityFilter;
|
||||||
|
public @Nullable Predicate<? super Block> blockFilter;
|
||||||
|
public EnumSet<RayTraceTarget> targets = EnumSet.noneOf(RayTraceTarget.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionedRayTraceConfigurationBuilder start(final Location start) {
|
||||||
|
Preconditions.checkArgument(start != null, "start must not be null");
|
||||||
|
this.start = start.clone();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionedRayTraceConfigurationBuilder direction(final Vector direction) {
|
||||||
|
Preconditions.checkArgument(direction != null, "direction must not be null");
|
||||||
|
this.direction = direction.clone();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionedRayTraceConfigurationBuilder maxDistance(final double maxDistance) {
|
||||||
|
Preconditions.checkArgument(maxDistance >= 0, "maxDistance must be non-negative");
|
||||||
|
this.maxDistance = OptionalDouble.of(maxDistance);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionedRayTraceConfigurationBuilder fluidCollisionMode(final FluidCollisionMode fluidCollisionMode) {
|
||||||
|
Preconditions.checkArgument(fluidCollisionMode != null, "fluidCollisionMode must not be null");
|
||||||
|
this.fluidCollisionMode = fluidCollisionMode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionedRayTraceConfigurationBuilder ignorePassableBlocks(final boolean ignorePassableBlocks) {
|
||||||
|
this.ignorePassableBlocks = ignorePassableBlocks;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionedRayTraceConfigurationBuilder raySize(final double raySize) {
|
||||||
|
Preconditions.checkArgument(raySize >= 0, "raySize must be non-negative");
|
||||||
|
this.raySize = raySize;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionedRayTraceConfigurationBuilder entityFilter(final Predicate<? super Entity> entityFilter) {
|
||||||
|
Preconditions.checkArgument(entityFilter != null, "entityFilter must not be null");
|
||||||
|
this.entityFilter = entityFilter;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionedRayTraceConfigurationBuilder blockFilter(final Predicate<? super Block> blockFilter) {
|
||||||
|
Preconditions.checkArgument(blockFilter != null, "blockFilter must not be null");
|
||||||
|
this.blockFilter = blockFilter;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionedRayTraceConfigurationBuilder targets(final RayTraceTarget first, final RayTraceTarget... others) {
|
||||||
|
Preconditions.checkArgument(first != null, "first must not be null");
|
||||||
|
Preconditions.checkArgument(others != null, "others must not be null");
|
||||||
|
this.targets = EnumSet.of(first, others);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
@ -6,9 +6,12 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.mojang.datafixers.util.Pair;
|
import com.mojang.datafixers.util.Pair;
|
||||||
import io.papermc.paper.FeatureHooks;
|
import io.papermc.paper.FeatureHooks;
|
||||||
|
import io.papermc.paper.raytracing.RayTraceTarget;
|
||||||
import io.papermc.paper.registry.RegistryAccess;
|
import io.papermc.paper.registry.RegistryAccess;
|
||||||
import io.papermc.paper.registry.RegistryKey;
|
import io.papermc.paper.registry.RegistryKey;
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||||
|
import io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilder;
|
||||||
|
import io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilderImpl;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -1248,6 +1251,26 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
|||||||
return blockHit;
|
return blockHit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RayTraceResult rayTrace(Consumer<PositionedRayTraceConfigurationBuilder> builderConsumer) {
|
||||||
|
PositionedRayTraceConfigurationBuilderImpl builder = new PositionedRayTraceConfigurationBuilderImpl();
|
||||||
|
|
||||||
|
builderConsumer.accept(builder);
|
||||||
|
Preconditions.checkArgument(builder.start != null, "Start location cannot be null");
|
||||||
|
Preconditions.checkArgument(builder.direction != null, "Direction vector cannot be null");
|
||||||
|
Preconditions.checkArgument(builder.maxDistance.isPresent(), "Max distance must be set");
|
||||||
|
Preconditions.checkArgument(!builder.targets.isEmpty(), "At least one target");
|
||||||
|
|
||||||
|
final double maxDistance = builder.maxDistance.getAsDouble();
|
||||||
|
if (builder.targets.contains(RayTraceTarget.ENTITY)) {
|
||||||
|
if (builder.targets.contains(RayTraceTarget.BLOCK)) {
|
||||||
|
return this.rayTrace(builder.start, builder.direction, maxDistance, builder.fluidCollisionMode, builder.ignorePassableBlocks, builder.raySize, builder.entityFilter, builder.blockFilter);
|
||||||
|
}
|
||||||
|
return this.rayTraceEntities(builder.start, builder.direction, maxDistance, builder.raySize, builder.entityFilter);
|
||||||
|
}
|
||||||
|
return this.rayTraceBlocks(builder.start, builder.direction, maxDistance, builder.fluidCollisionMode, builder.ignorePassableBlocks, builder.blockFilter);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Player> getPlayers() {
|
public List<Player> getPlayers() {
|
||||||
List<Player> list = new ArrayList<Player>(this.world.players().size());
|
List<Player> list = new ArrayList<Player>(this.world.players().size());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user