mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-06 00:07:56 +01:00
Add ray tracing and bounding box API
By: blablubbabc <lukas@wirsindwir.de>
This commit is contained in:
parent
0283ef18f5
commit
55523cfcfc
20
paper-api/src/main/java/org/bukkit/FluidCollisionMode.java
Normal file
20
paper-api/src/main/java/org/bukkit/FluidCollisionMode.java
Normal file
@ -0,0 +1,20 @@
|
||||
package org.bukkit;
|
||||
|
||||
/**
|
||||
* Determines the collision behavior when fluids get hit during ray tracing.
|
||||
*/
|
||||
public enum FluidCollisionMode {
|
||||
|
||||
/**
|
||||
* Ignore fluids.
|
||||
*/
|
||||
NEVER,
|
||||
/**
|
||||
* Only collide with source fluid blocks.
|
||||
*/
|
||||
SOURCE_ONLY,
|
||||
/**
|
||||
* Collide with all fluids.
|
||||
*/
|
||||
ALWAYS;
|
||||
}
|
@ -7,6 +7,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.Block;
|
||||
@ -17,7 +18,9 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.material.MaterialData;
|
||||
import org.bukkit.metadata.Metadatable;
|
||||
import org.bukkit.plugin.messaging.PluginMessageRecipient;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Consumer;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
@ -425,18 +428,232 @@ public interface World extends PluginMessageRecipient, Metadatable {
|
||||
public List<Player> getPlayers();
|
||||
|
||||
/**
|
||||
* Returns a list of entities within a bounding box centered around a Location.
|
||||
*
|
||||
* Some implementations may impose artificial restrictions on the size of the search bounding box.
|
||||
* Returns a list of entities within a bounding box centered around a
|
||||
* Location.
|
||||
* <p>
|
||||
* This may not consider entities in currently unloaded chunks. Some
|
||||
* implementations may impose artificial restrictions on the size of the
|
||||
* search bounding box.
|
||||
*
|
||||
* @param location The center of the bounding box
|
||||
* @param x 1/2 the size of the box along x axis
|
||||
* @param y 1/2 the size of the box along y axis
|
||||
* @param z 1/2 the size of the box along z axis
|
||||
* @return the collection of entities near location. This will always be a non-null collection.
|
||||
* @return the collection of entities near location. This will always be a
|
||||
* non-null collection.
|
||||
*/
|
||||
public Collection<Entity> getNearbyEntities(Location location, double x, double y, double z);
|
||||
|
||||
/**
|
||||
* Returns a list of entities within a bounding box centered around a
|
||||
* Location.
|
||||
* <p>
|
||||
* This may not consider entities in currently unloaded chunks. Some
|
||||
* implementations may impose artificial restrictions on the size of the
|
||||
* search bounding box.
|
||||
*
|
||||
* @param location The center of the bounding box
|
||||
* @param x 1/2 the size of the box along x axis
|
||||
* @param y 1/2 the size of the box along y axis
|
||||
* @param z 1/2 the size of the box along z axis
|
||||
* @param filter only entities that fulfill this predicate are considered,
|
||||
* or <code>null</code> to consider all entities
|
||||
* @return the collection of entities near location. This will always be a
|
||||
* non-null collection.
|
||||
*/
|
||||
public Collection<Entity> getNearbyEntities(Location location, double x, double y, double z, Predicate<Entity> filter);
|
||||
|
||||
/**
|
||||
* Returns a list of entities within the given bounding box.
|
||||
* <p>
|
||||
* This may not consider entities in currently unloaded chunks. Some
|
||||
* implementations may impose artificial restrictions on the size of the
|
||||
* search bounding box.
|
||||
*
|
||||
* @param boundingBox the bounding box
|
||||
* @return the collection of entities within the bounding box, will always
|
||||
* be a non-null collection
|
||||
*/
|
||||
public Collection<Entity> getNearbyEntities(BoundingBox boundingBox);
|
||||
|
||||
/**
|
||||
* Returns a list of entities within the given bounding box.
|
||||
* <p>
|
||||
* This may not consider entities in currently unloaded chunks. Some
|
||||
* implementations may impose artificial restrictions on the size of the
|
||||
* search bounding box.
|
||||
*
|
||||
* @param boundingBox the bounding box
|
||||
* @param filter only entities that fulfill this predicate are considered,
|
||||
* or <code>null</code> to consider all entities
|
||||
* @return the collection of entities within the bounding box, will always
|
||||
* be a non-null collection
|
||||
*/
|
||||
public Collection<Entity> getNearbyEntities(BoundingBox boundingBox, Predicate<Entity> filter);
|
||||
|
||||
/**
|
||||
* Performs a ray trace that checks for entity collisions.
|
||||
* <p>
|
||||
* This may not consider entities in currently unloaded chunks. Some
|
||||
* implementations may impose artificial restrictions on the maximum
|
||||
* distance.
|
||||
*
|
||||
* @param start the start position
|
||||
* @param direction the ray direction
|
||||
* @param maxDistance the maximum distance
|
||||
* @return the closest ray trace hit result, or <code>null</code> if there
|
||||
* is no hit
|
||||
* @see #rayTraceEntities(Location, Vector, double, double, Predicate)
|
||||
*/
|
||||
public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance);
|
||||
|
||||
/**
|
||||
* Performs a ray trace that checks for entity collisions.
|
||||
* <p>
|
||||
* This may not consider entities in currently unloaded chunks. Some
|
||||
* implementations may impose artificial restrictions on the maximum
|
||||
* distance.
|
||||
*
|
||||
* @param start the start position
|
||||
* @param direction the ray direction
|
||||
* @param maxDistance the maximum distance
|
||||
* @param raySize entity bounding boxes will be uniformly expanded (or
|
||||
* shrinked) by this value before doing collision checks
|
||||
* @return the closest ray trace hit result, or <code>null</code> if there
|
||||
* is no hit
|
||||
* @see #rayTraceEntities(Location, Vector, double, double, Predicate)
|
||||
*/
|
||||
public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, double raySize);
|
||||
|
||||
/**
|
||||
* Performs a ray trace that checks for entity collisions.
|
||||
* <p>
|
||||
* This may not consider entities in currently unloaded chunks. Some
|
||||
* implementations may impose artificial restrictions on the maximum
|
||||
* distance.
|
||||
*
|
||||
* @param start the start position
|
||||
* @param direction the ray direction
|
||||
* @param maxDistance the maximum distance
|
||||
* @param filter only entities that fulfill this predicate are considered,
|
||||
* or <code>null</code> to consider all entities
|
||||
* @return the closest ray trace hit result, or <code>null</code> if there
|
||||
* is no hit
|
||||
* @see #rayTraceEntities(Location, Vector, double, double, Predicate)
|
||||
*/
|
||||
public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, Predicate<Entity> filter);
|
||||
|
||||
/**
|
||||
* Performs a ray trace that checks for entity collisions.
|
||||
* <p>
|
||||
* This may not consider entities in currently unloaded chunks. Some
|
||||
* implementations may impose artificial restrictions on the maximum
|
||||
* distance.
|
||||
*
|
||||
* @param start the start position
|
||||
* @param direction the ray direction
|
||||
* @param maxDistance the maximum distance
|
||||
* @param raySize entity bounding boxes will be uniformly expanded (or
|
||||
* shrinked) by this value before doing collision checks
|
||||
* @param filter only entities that fulfill this predicate are considered,
|
||||
* or <code>null</code> to consider all entities
|
||||
* @return the closest ray trace hit result, or <code>null</code> if there
|
||||
* is no hit
|
||||
*/
|
||||
public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, double raySize, Predicate<Entity> filter);
|
||||
|
||||
/**
|
||||
* Performs a ray trace that checks for block collisions using the blocks'
|
||||
* precise collision shapes.
|
||||
* <p>
|
||||
* This takes collisions with passable blocks into account, but ignores
|
||||
* fluids.
|
||||
* <p>
|
||||
* This may cause loading of chunks! Some implementations may impose
|
||||
* artificial restrictions on the maximum distance.
|
||||
*
|
||||
* @param start the start location
|
||||
* @param direction the ray direction
|
||||
* @param maxDistance the maximum distance
|
||||
* @return the ray trace hit result, or <code>null</code> if there is no hit
|
||||
* @see #rayTraceBlocks(Location, Vector, double, FluidCollisionMode, boolean)
|
||||
*/
|
||||
public RayTraceResult rayTraceBlocks(Location start, Vector direction, double maxDistance);
|
||||
|
||||
/**
|
||||
* Performs a ray trace that checks for block collisions using the blocks'
|
||||
* precise collision shapes.
|
||||
* <p>
|
||||
* This takes collisions with passable blocks into account.
|
||||
* <p>
|
||||
* This may cause loading of chunks! Some implementations may impose
|
||||
* artificial restrictions on the maximum distance.
|
||||
*
|
||||
* @param start the start location
|
||||
* @param direction the ray direction
|
||||
* @param maxDistance the maximum distance
|
||||
* @param fluidCollisionMode the fluid collision mode
|
||||
* @return the ray trace hit result, or <code>null</code> if there is no hit
|
||||
* @see #rayTraceBlocks(Location, Vector, double, FluidCollisionMode, boolean)
|
||||
*/
|
||||
public RayTraceResult rayTraceBlocks(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode);
|
||||
|
||||
/**
|
||||
* Performs a ray trace that checks for block collisions using the blocks'
|
||||
* precise collision shapes.
|
||||
* <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 location
|
||||
* @param direction the ray direction
|
||||
* @param maxDistance the maximum distance
|
||||
* @param fluidCollisionMode the fluid collision mode
|
||||
* @param ignorePassableBlocks whether to ignore passable but collidable
|
||||
* blocks (ex. tall grass, signs, fluids, ..)
|
||||
* @return the ray trace hit result, or <code>null</code> if there is no hit
|
||||
*/
|
||||
public RayTraceResult rayTraceBlocks(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks);
|
||||
|
||||
/**
|
||||
* 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 location
|
||||
* @param direction the ray direction
|
||||
* @param maxDistance the maximum distance
|
||||
* @param fluidCollisionMode the fluid collision mode
|
||||
* @param ignorePassableBlocks whether to ignore passable but collidable
|
||||
* blocks (ex. tall grass, signs, fluids, ..)
|
||||
* @param raySize entity bounding boxes will be uniformly expanded (or
|
||||
* shrinked) by this value before doing collision checks
|
||||
* @param filter only entities that fulfill this predicate are considered,
|
||||
* or <code>null</code> to consider all entities
|
||||
* @return the closest ray trace hit result with either a block or an
|
||||
* entity, or <code>null</code> if there is no hit
|
||||
*/
|
||||
public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate<Entity> filter);
|
||||
|
||||
/**
|
||||
* Gets the unique name of this world
|
||||
*
|
||||
|
@ -3,12 +3,15 @@ package org.bukkit.block;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.metadata.Metadatable;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* Represents a block. This is a live object, and only one Block may exist for
|
||||
@ -369,4 +372,16 @@ public interface Block extends Metadatable {
|
||||
* @return <code>true</code> if passable
|
||||
*/
|
||||
boolean isPassable();
|
||||
|
||||
/**
|
||||
* Performs a ray trace that checks for collision with this specific block
|
||||
* in its current state using its precise collision shape.
|
||||
*
|
||||
* @param start the start location
|
||||
* @param direction the ray direction
|
||||
* @param maxDistance the maximum distance
|
||||
* @param fluidCollisionMode the fluid collision mode
|
||||
* @return the ray trace hit result, or <code>null</code> if there is no hit
|
||||
*/
|
||||
RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode);
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package org.bukkit.block;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* Represents the face of a block
|
||||
*/
|
||||
@ -67,6 +69,19 @@ public enum BlockFace {
|
||||
return modZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the normal vector corresponding to this block face.
|
||||
*
|
||||
* @return the normal vector
|
||||
*/
|
||||
public Vector getDirection() {
|
||||
Vector direction = new Vector(modX, modY, modZ);
|
||||
if (modX != 0 || modY != 0 || modZ != 0) {
|
||||
direction.normalize();
|
||||
}
|
||||
return direction;
|
||||
}
|
||||
|
||||
public BlockFace getOppositeFace() {
|
||||
switch (this) {
|
||||
case NORTH:
|
||||
|
@ -18,6 +18,7 @@ import org.bukkit.block.banner.Pattern;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.BlockVector;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@ -39,6 +40,7 @@ public class ConfigurationSerialization {
|
||||
registerClass(Pattern.class);
|
||||
registerClass(Location.class);
|
||||
registerClass(AttributeModifier.class);
|
||||
registerClass(BoundingBox.class);
|
||||
}
|
||||
|
||||
protected ConfigurationSerialization(Class<? extends ConfigurationSerializable> clazz) {
|
||||
|
@ -9,6 +9,7 @@ import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.material.Directional;
|
||||
import org.bukkit.metadata.Metadatable;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.List;
|
||||
@ -69,6 +70,16 @@ public interface Entity extends Metadatable, CommandSender, Nameable {
|
||||
*/
|
||||
public double getWidth();
|
||||
|
||||
/**
|
||||
* Gets the entity's current bounding box.
|
||||
* <p>
|
||||
* The returned bounding box reflects the entity's current location and
|
||||
* size.
|
||||
*
|
||||
* @return the entity's current bounding box
|
||||
*/
|
||||
public BoundingBox getBoundingBox();
|
||||
|
||||
/**
|
||||
* Returns true if the entity is supported by a block. This value is a
|
||||
* state updated by the server and is not recalculated unless the entity
|
||||
|
@ -5,14 +5,18 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.attribute.Attributable;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.projectiles.ProjectileSource;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* Represents a living entity, such as a monster or player
|
||||
@ -46,7 +50,7 @@ public interface LivingEntity extends Attributable, Entity, Damageable, Projecti
|
||||
* Gets all blocks along the living entity's line of sight.
|
||||
* <p>
|
||||
* This list contains all blocks from the living entity's eye position to
|
||||
* target inclusive.
|
||||
* target inclusive. This method considers all blocks as 1x1x1 in size.
|
||||
*
|
||||
* @param transparent HashSet containing all transparent block Materials (set to
|
||||
* null for only air)
|
||||
@ -59,6 +63,10 @@ public interface LivingEntity extends Attributable, Entity, Damageable, Projecti
|
||||
|
||||
/**
|
||||
* Gets the block that the living entity has targeted.
|
||||
* <p>
|
||||
* This method considers all blocks as 1x1x1 in size. To take exact block
|
||||
* collision shapes into account, see {@link #getTargetBlockExact(int,
|
||||
* FluidCollisionMode)}.
|
||||
*
|
||||
* @param transparent HashSet containing all transparent block Materials (set to
|
||||
* null for only air)
|
||||
@ -71,7 +79,8 @@ public interface LivingEntity extends Attributable, Entity, Damageable, Projecti
|
||||
/**
|
||||
* Gets the last two blocks along the living entity's line of sight.
|
||||
* <p>
|
||||
* The target block will be the last block in the list.
|
||||
* The target block will be the last block in the list. This method
|
||||
* considers all blocks as 1x1x1 in size.
|
||||
*
|
||||
* @param transparent HashSet containing all transparent block Materials (set to
|
||||
* null for only air)
|
||||
@ -82,6 +91,68 @@ public interface LivingEntity extends Attributable, Entity, Damageable, Projecti
|
||||
*/
|
||||
public List<Block> getLastTwoTargetBlocks(Set<Material> transparent, int maxDistance);
|
||||
|
||||
/**
|
||||
* Gets the block that the living entity has targeted.
|
||||
* <p>
|
||||
* This takes the blocks' precise collision shapes into account. Fluids are
|
||||
* ignored.
|
||||
* <p>
|
||||
* This may cause loading of chunks! Some implementations may impose
|
||||
* artificial restrictions on the maximum distance.
|
||||
*
|
||||
* @param maxDistance the maximum distance to scan
|
||||
* @return block that the living entity has targeted
|
||||
* @see #getTargetBlockExact(int, org.bukkit.FluidCollisionMode)
|
||||
*/
|
||||
public Block getTargetBlockExact(int maxDistance);
|
||||
|
||||
/**
|
||||
* Gets the block that the living entity has targeted.
|
||||
* <p>
|
||||
* This takes the blocks' precise collision shapes into account.
|
||||
* <p>
|
||||
* This may cause loading of chunks! Some implementations may impose
|
||||
* artificial restrictions on the maximum distance.
|
||||
*
|
||||
* @param maxDistance the maximum distance to scan
|
||||
* @param fluidCollisionMode the fluid collision mode
|
||||
* @return block that the living entity has targeted
|
||||
* @see #rayTraceBlocks(double, FluidCollisionMode)
|
||||
*/
|
||||
public Block getTargetBlockExact(int maxDistance, FluidCollisionMode fluidCollisionMode);
|
||||
|
||||
/**
|
||||
* Performs a ray trace that provides information on the targeted block.
|
||||
* <p>
|
||||
* This takes the blocks' precise collision shapes into account. Fluids are
|
||||
* ignored.
|
||||
* <p>
|
||||
* This may cause loading of chunks! Some implementations may impose
|
||||
* artificial restrictions on the maximum distance.
|
||||
*
|
||||
* @param maxDistance the maximum distance to scan
|
||||
* @return information on the targeted block, or <code>null</code> if there
|
||||
* is no targeted block in range
|
||||
* @see #rayTraceBlocks(double, FluidCollisionMode)
|
||||
*/
|
||||
public RayTraceResult rayTraceBlocks(double maxDistance);
|
||||
|
||||
/**
|
||||
* Performs a ray trace that provides information on the targeted block.
|
||||
* <p>
|
||||
* This takes the blocks' precise collision shapes into account.
|
||||
* <p>
|
||||
* This may cause loading of chunks! Some implementations may impose
|
||||
* artificial restrictions on the maximum distance.
|
||||
*
|
||||
* @param maxDistance the maximum distance to scan
|
||||
* @param fluidCollisionMode the fluid collision mode
|
||||
* @return information on the targeted block, or <code>null</code> if there
|
||||
* is no targeted block in range
|
||||
* @see World#rayTraceBlocks(Location, Vector, double, FluidCollisionMode)
|
||||
*/
|
||||
public RayTraceResult rayTraceBlocks(double maxDistance, FluidCollisionMode fluidCollisionMode);
|
||||
|
||||
/**
|
||||
* Returns the amount of air that the living entity has remaining, in
|
||||
* ticks.
|
||||
|
@ -39,7 +39,9 @@ public class BlockIterator implements Iterator<Block> {
|
||||
private BlockFace thirdFace;
|
||||
|
||||
/**
|
||||
* Constructs the BlockIterator
|
||||
* Constructs the BlockIterator.
|
||||
* <p>
|
||||
* This considers all blocks as 1x1x1 in size.
|
||||
*
|
||||
* @param world The world to use for tracing
|
||||
* @param start A Vector giving the initial location for the trace
|
||||
@ -220,7 +222,9 @@ public class BlockIterator implements Iterator<Block> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the BlockIterator
|
||||
* Constructs the BlockIterator.
|
||||
* <p>
|
||||
* This considers all blocks as 1x1x1 in size.
|
||||
*
|
||||
* @param loc The location for the start of the ray trace
|
||||
* @param yOffset The trace begins vertically offset from the start vector
|
||||
@ -235,6 +239,8 @@ public class BlockIterator implements Iterator<Block> {
|
||||
|
||||
/**
|
||||
* Constructs the BlockIterator.
|
||||
* <p>
|
||||
* This considers all blocks as 1x1x1 in size.
|
||||
*
|
||||
* @param loc The location for the start of the ray trace
|
||||
* @param yOffset The trace begins vertically offset from the start vector
|
||||
@ -247,6 +253,8 @@ public class BlockIterator implements Iterator<Block> {
|
||||
|
||||
/**
|
||||
* Constructs the BlockIterator.
|
||||
* <p>
|
||||
* This considers all blocks as 1x1x1 in size.
|
||||
*
|
||||
* @param loc The location for the start of the ray trace
|
||||
*/
|
||||
@ -257,6 +265,8 @@ public class BlockIterator implements Iterator<Block> {
|
||||
|
||||
/**
|
||||
* Constructs the BlockIterator.
|
||||
* <p>
|
||||
* This considers all blocks as 1x1x1 in size.
|
||||
*
|
||||
* @param entity Information from the entity is used to set up the trace
|
||||
* @param maxDistance This is the maximum distance in blocks for the
|
||||
@ -270,6 +280,8 @@ public class BlockIterator implements Iterator<Block> {
|
||||
|
||||
/**
|
||||
* Constructs the BlockIterator.
|
||||
* <p>
|
||||
* This considers all blocks as 1x1x1 in size.
|
||||
*
|
||||
* @param entity Information from the entity is used to set up the trace
|
||||
*/
|
||||
|
1030
paper-api/src/main/java/org/bukkit/util/BoundingBox.java
Normal file
1030
paper-api/src/main/java/org/bukkit/util/BoundingBox.java
Normal file
File diff suppressed because it is too large
Load Diff
157
paper-api/src/main/java/org/bukkit/util/RayTraceResult.java
Normal file
157
paper-api/src/main/java/org/bukkit/util/RayTraceResult.java
Normal file
@ -0,0 +1,157 @@
|
||||
package org.bukkit.util;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
/**
|
||||
* The hit result of a ray trace.
|
||||
* <p>
|
||||
* Only the hit position is guaranteed to always be available. The availability
|
||||
* of the other attributes depends on what got hit and on the context in which
|
||||
* the ray trace was performed.
|
||||
*/
|
||||
public class RayTraceResult {
|
||||
|
||||
private final Vector hitPosition;
|
||||
|
||||
private final Block hitBlock;
|
||||
private final BlockFace hitBlockFace;
|
||||
private final Entity hitEntity;
|
||||
|
||||
private RayTraceResult(Vector hitPosition, Block hitBlock, BlockFace hitBlockFace, Entity hitEntity) {
|
||||
Validate.notNull(hitPosition, "Hit position is null!");
|
||||
this.hitPosition = hitPosition.clone();
|
||||
this.hitBlock = hitBlock;
|
||||
this.hitBlockFace = hitBlockFace;
|
||||
this.hitEntity = hitEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a RayTraceResult.
|
||||
*
|
||||
* @param hitPosition the hit position
|
||||
*/
|
||||
public RayTraceResult(Vector hitPosition) {
|
||||
this(hitPosition, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a RayTraceResult.
|
||||
*
|
||||
* @param hitPosition the hit position
|
||||
* @param hitBlockFace the hit block face
|
||||
*/
|
||||
public RayTraceResult(Vector hitPosition, BlockFace hitBlockFace) {
|
||||
this(hitPosition, null, hitBlockFace, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a RayTraceResult.
|
||||
*
|
||||
* @param hitPosition the hit position
|
||||
* @param hitBlock the hit block
|
||||
* @param hitBlockFace the hit block face
|
||||
*/
|
||||
public RayTraceResult(Vector hitPosition, Block hitBlock, BlockFace hitBlockFace) {
|
||||
this(hitPosition, hitBlock, hitBlockFace, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a RayTraceResult.
|
||||
*
|
||||
* @param hitPosition the hit position
|
||||
* @param hitEntity the hit entity
|
||||
*/
|
||||
public RayTraceResult(Vector hitPosition, Entity hitEntity) {
|
||||
this(hitPosition, null, null, hitEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a RayTraceResult.
|
||||
*
|
||||
* @param hitPosition the hit position
|
||||
* @param hitEntity the hit entity
|
||||
* @param hitBlockFace the hit block face
|
||||
*/
|
||||
public RayTraceResult(Vector hitPosition, Entity hitEntity, BlockFace hitBlockFace) {
|
||||
this(hitPosition, null, hitBlockFace, hitEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exact position of the hit.
|
||||
*
|
||||
* @return a copy of the exact hit position
|
||||
*/
|
||||
public Vector getHitPosition() {
|
||||
return hitPosition.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hit block.
|
||||
*
|
||||
* @return the hit block, or <code>null</code> if not available
|
||||
*/
|
||||
public Block getHitBlock() {
|
||||
return hitBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hit block face.
|
||||
*
|
||||
* @return the hit block face, or <code>null</code> if not available
|
||||
*/
|
||||
public BlockFace getHitBlockFace() {
|
||||
return hitBlockFace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hit entity.
|
||||
*
|
||||
* @return the hit entity, or <code>null</code> if not available
|
||||
*/
|
||||
public Entity getHitEntity() {
|
||||
return hitEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + hitPosition.hashCode();
|
||||
result = prime * result + ((hitBlock == null) ? 0 : hitBlock.hashCode());
|
||||
result = prime * result + ((hitBlockFace == null) ? 0 : hitBlockFace.hashCode());
|
||||
result = prime * result + ((hitEntity == null) ? 0 : hitEntity.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof RayTraceResult)) return false;
|
||||
RayTraceResult other = (RayTraceResult) obj;
|
||||
if (!hitPosition.equals(other.hitPosition)) return false;
|
||||
if (!Objects.equals(hitBlock, other.hitBlock)) return false;
|
||||
if (!Objects.equals(hitBlockFace, other.hitBlockFace)) return false;
|
||||
if (!Objects.equals(hitEntity, other.hitEntity)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("RayTraceResult [hitPosition=");
|
||||
builder.append(hitPosition);
|
||||
builder.append(", hitBlock=");
|
||||
builder.append(hitBlock);
|
||||
builder.append(", hitBlockFace=");
|
||||
builder.append(hitBlockFace);
|
||||
builder.append(", hitEntity=");
|
||||
builder.append(hitEntity);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ import com.google.common.collect.ImmutableList;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class LocationTest {
|
||||
private static final double δ = 1.0 / 1000000;
|
||||
private static final double delta = 1.0 / 1000000;
|
||||
/**
|
||||
* <pre>
|
||||
* a² + b² = c², a = b
|
||||
@ -166,17 +166,17 @@ public class LocationTest {
|
||||
public void testExpectedPitchYaw() {
|
||||
Location location = getEmptyLocation().setDirection(getVector());
|
||||
|
||||
assertThat((double) location.getYaw(), is(closeTo(yaw, δ)));
|
||||
assertThat((double) location.getPitch(), is(closeTo(pitch, δ)));
|
||||
assertThat((double) location.getYaw(), is(closeTo(yaw, delta)));
|
||||
assertThat((double) location.getPitch(), is(closeTo(pitch, delta)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpectedXYZ() {
|
||||
Vector vector = getLocation().getDirection();
|
||||
|
||||
assertThat(vector.getX(), is(closeTo(x, δ)));
|
||||
assertThat(vector.getY(), is(closeTo(y, δ)));
|
||||
assertThat(vector.getZ(), is(closeTo(z, δ)));
|
||||
assertThat(vector.getX(), is(closeTo(x, delta)));
|
||||
assertThat(vector.getY(), is(closeTo(y, delta)));
|
||||
assertThat(vector.getZ(), is(closeTo(z, delta)));
|
||||
}
|
||||
|
||||
private Vector getVector() {
|
||||
|
206
paper-api/src/test/java/org/bukkit/util/BoundingBoxTest.java
Normal file
206
paper-api/src/test/java/org/bukkit/util/BoundingBoxTest.java
Normal file
@ -0,0 +1,206 @@
|
||||
package org.bukkit.util;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.junit.Test;
|
||||
|
||||
public class BoundingBoxTest {
|
||||
|
||||
private static final double delta = 1.0 / 1000000;
|
||||
|
||||
@Test
|
||||
public void testConstruction() {
|
||||
BoundingBox expected = new BoundingBox(-1, -1, -1, 1, 2, 3);
|
||||
assertThat(expected.getMin(), is(new Vector(-1, -1, -1)));
|
||||
assertThat(expected.getMax(), is(new Vector(1, 2, 3)));
|
||||
assertThat(expected.getCenter(), is(new Vector(0.0D, 0.5D, 1.0D)));
|
||||
assertThat(expected.getWidthX(), is(2.0D));
|
||||
assertThat(expected.getHeight(), is(3.0D));
|
||||
assertThat(expected.getWidthZ(), is(4.0D));
|
||||
assertThat(expected.getVolume(), is(24.0D));
|
||||
|
||||
assertThat(BoundingBox.of(new Vector(-1, -1, -1), new Vector(1, 2, 3)), is(expected));
|
||||
assertThat(BoundingBox.of(new Vector(1, 2, 3), new Vector(-1, -1, -1)), is(expected));
|
||||
assertThat(BoundingBox.of(new Location(null, -1, -1, -1), new Location(null, 1, 2, 3)), is(expected));
|
||||
assertThat(BoundingBox.of(new Vector(0.0D, 0.5D, 1.0D), 1.0D, 1.5D, 2.0D), is(expected));
|
||||
assertThat(BoundingBox.of(new Location(null, 0.0D, 0.5D, 1.0D), 1.0D, 1.5D, 2.0D), is(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContains() {
|
||||
BoundingBox aabb = new BoundingBox(-1, -1, -1, 1, 2, 3);
|
||||
assertThat(aabb.contains(-0.5D, 0.0D, 0.5D), is(true));
|
||||
assertThat(aabb.contains(-1.0D, -1.0D, -1.0D), is(true));
|
||||
assertThat(aabb.contains(1.0D, 2.0D, 3.0D), is(false));
|
||||
assertThat(aabb.contains(-1.0D, 1.0D, 4.0D), is(false));
|
||||
assertThat(aabb.contains(new Vector(-0.5D, 0.0D, 0.5D)), is(true));
|
||||
|
||||
assertThat(aabb.contains(new BoundingBox(-0.5D, -0.5D, -0.5D, 0.5D, 1.0D, 2.0D)), is(true));
|
||||
assertThat(aabb.contains(aabb), is(true));
|
||||
assertThat(aabb.contains(new BoundingBox(-1, -1, -1, 1, 1, 3)), is(true));
|
||||
assertThat(aabb.contains(new BoundingBox(-2, -1, -1, 1, 2, 3)), is(false));
|
||||
assertThat(aabb.contains(new Vector(-0.5D, -0.5D, -0.5D), new Vector(0.5D, 1.0D, 2.0D)), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverlaps() {
|
||||
BoundingBox aabb = new BoundingBox(-1, -1, -1, 1, 2, 3);
|
||||
assertThat(aabb.contains(aabb), is(true));
|
||||
assertThat(aabb.overlaps(new BoundingBox(-2, -2, -2, 0, 0, 0)), is(true));
|
||||
assertThat(aabb.overlaps(new BoundingBox(0.5D, 1.5D, 2.5D, 1, 2, 3)), is(true));
|
||||
assertThat(aabb.overlaps(new BoundingBox(0.5D, 1.5D, 2.5D, 2, 3, 4)), is(true));
|
||||
assertThat(aabb.overlaps(new BoundingBox(-2, -2, -2, -1, -1, -1)), is(false));
|
||||
assertThat(aabb.overlaps(new BoundingBox(1, 2, 3, 2, 3, 4)), is(false));
|
||||
assertThat(aabb.overlaps(new Vector(0.5D, 1.5D, 2.5D), new Vector(1, 2, 3)), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDegenerate() {
|
||||
BoundingBox aabb = new BoundingBox(0, 0, 0, 0, 0, 0);
|
||||
assertThat(aabb.getWidthX(), is(0.0D));
|
||||
assertThat(aabb.getHeight(), is(0.0D));
|
||||
assertThat(aabb.getWidthZ(), is(0.0D));
|
||||
assertThat(aabb.getVolume(), is(0.0D));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShift() {
|
||||
BoundingBox aabb = new BoundingBox(0, 0, 0, 1, 1, 1);
|
||||
assertThat(aabb.clone().shift(1, 2, 3), is(new BoundingBox(1, 2, 3, 2, 3, 4)));
|
||||
assertThat(aabb.clone().shift(-1, -2, -3), is(new BoundingBox(-1, -2, -3, 0, -1, -2)));
|
||||
assertThat(aabb.clone().shift(new Vector(1, 2, 3)), is(new BoundingBox(1, 2, 3, 2, 3, 4)));
|
||||
assertThat(aabb.clone().shift(new Location(null, 1, 2, 3)), is(new BoundingBox(1, 2, 3, 2, 3, 4)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnion() {
|
||||
BoundingBox aabb1 = new BoundingBox(0, 0, 0, 1, 1, 1);
|
||||
assertThat(aabb1.clone().union(new BoundingBox(-2, -2, -2, -1, -1, -1)), is(new BoundingBox(-2, -2, -2, 1, 1, 1)));
|
||||
assertThat(aabb1.clone().union(1, 2, 3), is(new BoundingBox(0, 0, 0, 1, 2, 3)));
|
||||
assertThat(aabb1.clone().union(new Vector(1, 2, 3)), is(new BoundingBox(0, 0, 0, 1, 2, 3)));
|
||||
assertThat(aabb1.clone().union(new Location(null, 1, 2, 3)), is(new BoundingBox(0, 0, 0, 1, 2, 3)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntersection() {
|
||||
BoundingBox aabb = new BoundingBox(-1, -1, -1, 1, 2, 3);
|
||||
assertThat(aabb.clone().intersection(new BoundingBox(-2, -2, -2, 4, 4, 4)), is(aabb));
|
||||
assertThat(aabb.clone().intersection(new BoundingBox(-2, -2, -2, 1, 1, 1)), is(new BoundingBox(-1, -1, -1, 1, 1, 1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpansion() {
|
||||
BoundingBox aabb = new BoundingBox(0, 0, 0, 2, 2, 2);
|
||||
assertThat(aabb.clone().expand(1, 2, 3, 1, 2, 3), is(new BoundingBox(-1, -2, -3, 3, 4, 5)));
|
||||
assertThat(aabb.clone().expand(-1, -2, -3, 1, 2, 3), is(new BoundingBox(1, 2, 3, 3, 4, 5)));
|
||||
assertThat(aabb.clone().expand(1, 2, 3, -1, -2, -3), is(new BoundingBox(-1, -2, -3, 1, 0, -1)));
|
||||
assertThat(aabb.clone().expand(-1, -2, -3, -0.5D, -0.5, -3), is(new BoundingBox(1, 1.5D, 1, 1.5D, 1.5D, 1)));
|
||||
|
||||
assertThat(aabb.clone().expand(1, 2, 3), is(new BoundingBox(-1, -2, -3, 3, 4, 5)));
|
||||
assertThat(aabb.clone().expand(-0.1, -0.5, -2), is(new BoundingBox(0.1D, 0.5D, 1, 1.9D, 1.5D, 1)));
|
||||
assertThat(aabb.clone().expand(new Vector(1, 2, 3)), is(new BoundingBox(-1, -2, -3, 3, 4, 5)));
|
||||
|
||||
assertThat(aabb.clone().expand(1), is(new BoundingBox(-1, -1, -1, 3, 3, 3)));
|
||||
assertThat(aabb.clone().expand(-0.5D), is(new BoundingBox(0.5D, 0.5D, 0.5D, 1.5D, 1.5D, 1.5D)));
|
||||
|
||||
assertThat(aabb.clone().expand(1, 0, 0, 0.5D), is(new BoundingBox(0, 0, 0, 2.5D, 2, 2)));
|
||||
assertThat(aabb.clone().expand(1, 0, 0, -0.5D), is(new BoundingBox(0, 0, 0, 1.5D, 2, 2)));
|
||||
assertThat(aabb.clone().expand(-1, 0, 0, 0.5D), is(new BoundingBox(-0.5D, 0, 0, 2, 2, 2)));
|
||||
assertThat(aabb.clone().expand(-1, 0, 0, -0.5D), is(new BoundingBox(0.5D, 0, 0, 2, 2, 2)));
|
||||
|
||||
assertThat(aabb.clone().expand(0, 1, 0, 0.5D), is(new BoundingBox(0, 0, 0, 2, 2.5D, 2)));
|
||||
assertThat(aabb.clone().expand(0, 1, 0, -0.5D), is(new BoundingBox(0, 0, 0, 2, 1.5D, 2)));
|
||||
assertThat(aabb.clone().expand(0, -1, 0, 0.5D), is(new BoundingBox(0, -0.5D, 0, 2, 2, 2)));
|
||||
assertThat(aabb.clone().expand(0, -1, 0, -0.5D), is(new BoundingBox(0, 0.5D, 0, 2, 2, 2)));
|
||||
|
||||
assertThat(aabb.clone().expand(0, 0, 1, 0.5D), is(new BoundingBox(0, 0, 0, 2, 2, 2.5D)));
|
||||
assertThat(aabb.clone().expand(0, 0, 1, -0.5D), is(new BoundingBox(0, 0, 0, 2, 2, 1.5D)));
|
||||
assertThat(aabb.clone().expand(0, 0, -1, 0.5D), is(new BoundingBox(0, 0, -0.5D, 2, 2, 2)));
|
||||
assertThat(aabb.clone().expand(0, 0, -1, -0.5D), is(new BoundingBox(0, 0, 0.5D, 2, 2, 2)));
|
||||
|
||||
assertThat(aabb.clone().expand(new Vector(1, 0, 0), 0.5D), is(new BoundingBox(0, 0, 0, 2.5D, 2, 2)));
|
||||
assertThat(aabb.clone().expand(BlockFace.EAST, 0.5D), is(new BoundingBox(0, 0, 0, 2.5D, 2, 2)));
|
||||
assertThat(aabb.clone().expand(BlockFace.NORTH_NORTH_WEST, 1.0D), is(aabb.clone().expand(BlockFace.NORTH_NORTH_WEST.getDirection(), 1.0D)));
|
||||
assertThat(aabb.clone().expand(BlockFace.SELF, 1.0D), is(aabb));
|
||||
|
||||
BoundingBox expanded = aabb.clone().expand(BlockFace.NORTH_WEST, 1.0D);
|
||||
assertThat(expanded.getWidthX(), is(closeTo(aabb.getWidthX() + Math.sqrt(0.5D), delta)));
|
||||
assertThat(expanded.getWidthZ(), is(closeTo(aabb.getWidthZ() + Math.sqrt(0.5D), delta)));
|
||||
assertThat(expanded.getHeight(), is(aabb.getHeight()));
|
||||
|
||||
assertThat(aabb.clone().expandDirectional(1, 2, 3), is(new BoundingBox(0, 0, 0, 3, 4, 5)));
|
||||
assertThat(aabb.clone().expandDirectional(-1, -2, -3), is(new BoundingBox(-1, -2, -3, 2, 2, 2)));
|
||||
assertThat(aabb.clone().expandDirectional(new Vector(1, 2, 3)), is(new BoundingBox(0, 0, 0, 3, 4, 5)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRayTrace() {
|
||||
BoundingBox aabb = new BoundingBox(-1, -1, -1, 1, 1, 1);
|
||||
|
||||
assertThat(aabb.rayTrace(new Vector(-2, 0, 0), new Vector(1, 0, 0), 10),
|
||||
is(new RayTraceResult(new Vector(-1, 0, 0), BlockFace.WEST)));
|
||||
assertThat(aabb.rayTrace(new Vector(2, 0, 0), new Vector(-1, 0, 0), 10),
|
||||
is(new RayTraceResult(new Vector(1, 0, 0), BlockFace.EAST)));
|
||||
|
||||
assertThat(aabb.rayTrace(new Vector(0, -2, 0), new Vector(0, 1, 0), 10),
|
||||
is(new RayTraceResult(new Vector(0, -1, 0), BlockFace.DOWN)));
|
||||
assertThat(aabb.rayTrace(new Vector(0, 2, 0), new Vector(0, -1, 0), 10),
|
||||
is(new RayTraceResult(new Vector(0, 1, 0), BlockFace.UP)));
|
||||
|
||||
assertThat(aabb.rayTrace(new Vector(0, 0, -2), new Vector(0, 0, 1), 10),
|
||||
is(new RayTraceResult(new Vector(0, 0, -1), BlockFace.NORTH)));
|
||||
assertThat(aabb.rayTrace(new Vector(0, 0, 2), new Vector(0, 0, -1), 10),
|
||||
is(new RayTraceResult(new Vector(0, 0, 1), BlockFace.SOUTH)));
|
||||
|
||||
assertThat(aabb.rayTrace(new Vector(0, 0, 0), new Vector(1, 0, 0), 10),
|
||||
is(new RayTraceResult(new Vector(1, 0, 0), BlockFace.EAST)));
|
||||
assertThat(aabb.rayTrace(new Vector(0, 0, 0), new Vector(-1, 0, 0), 10),
|
||||
is(new RayTraceResult(new Vector(-1, 0, 0), BlockFace.WEST)));
|
||||
|
||||
assertThat(aabb.rayTrace(new Vector(0, 0, 0), new Vector(0, 1, 0), 10),
|
||||
is(new RayTraceResult(new Vector(0, 1, 0), BlockFace.UP)));
|
||||
assertThat(aabb.rayTrace(new Vector(0, 0, 0), new Vector(0, -1, 0), 10),
|
||||
is(new RayTraceResult(new Vector(0, -1, 0), BlockFace.DOWN)));
|
||||
|
||||
assertThat(aabb.rayTrace(new Vector(0, 0, 0), new Vector(0, 0, 1), 10),
|
||||
is(new RayTraceResult(new Vector(0, 0, 1), BlockFace.SOUTH)));
|
||||
assertThat(aabb.rayTrace(new Vector(0, 0, 0), new Vector(0, 0, -1), 10),
|
||||
is(new RayTraceResult(new Vector(0, 0, -1), BlockFace.NORTH)));
|
||||
|
||||
assertThat(aabb.rayTrace(new Vector(-2, -2, -2), new Vector(1, 0, 0), 10), is(nullValue()));
|
||||
assertThat(aabb.rayTrace(new Vector(-2, -2, -2), new Vector(0, 1, 0), 10), is(nullValue()));
|
||||
assertThat(aabb.rayTrace(new Vector(-2, -2, -2), new Vector(0, 0, 1), 10), is(nullValue()));
|
||||
|
||||
assertThat(aabb.rayTrace(new Vector(0, 0, -3), new Vector(1, 0, 1), 10), is(nullValue()));
|
||||
assertThat(aabb.rayTrace(new Vector(0, 0, -2), new Vector(1, 0, 2), 10),
|
||||
is(new RayTraceResult(new Vector(0.5D, 0, -1), BlockFace.NORTH)));
|
||||
|
||||
// corner/edge hits yield unspecified block face:
|
||||
assertThat(aabb.rayTrace(new Vector(2, 2, 2), new Vector(-1, -1, -1), 10),
|
||||
anyOf(is(new RayTraceResult(new Vector(1, 1, 1), BlockFace.EAST)),
|
||||
is(new RayTraceResult(new Vector(1, 1, 1), BlockFace.UP)),
|
||||
is(new RayTraceResult(new Vector(1, 1, 1), BlockFace.SOUTH))));
|
||||
|
||||
assertThat(aabb.rayTrace(new Vector(-2, -2, -2), new Vector(1, 1, 1), 10),
|
||||
anyOf(is(new RayTraceResult(new Vector(-1, -1, -1), BlockFace.WEST)),
|
||||
is(new RayTraceResult(new Vector(-1, -1, -1), BlockFace.DOWN)),
|
||||
is(new RayTraceResult(new Vector(-1, -1, -1), BlockFace.NORTH))));
|
||||
|
||||
assertThat(aabb.rayTrace(new Vector(0, 0, -2), new Vector(1, 0, 1), 10),
|
||||
anyOf(is(new RayTraceResult(new Vector(1, 0, -1), BlockFace.NORTH)),
|
||||
is(new RayTraceResult(new Vector(1, 0, -1), BlockFace.EAST))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerialization() {
|
||||
BoundingBox aabb = new BoundingBox(-1, -1, -1, 1, 1, 1);
|
||||
Map<String, Object> serialized = aabb.serialize();
|
||||
BoundingBox deserialized = BoundingBox.deserialize(serialized);
|
||||
assertThat(deserialized, is(aabb));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user