mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-12 09:51:12 +01:00
Add ray tracing and bounding box API
This commit is contained in:
parent
a835b03538
commit
4a47be6164
6 changed files with 299 additions and 7 deletions
|
@ -0,0 +1,24 @@
|
||||||
|
package org.bukkit.craftbukkit;
|
||||||
|
|
||||||
|
import org.bukkit.FluidCollisionMode;
|
||||||
|
import net.minecraft.server.FluidCollisionOption;
|
||||||
|
|
||||||
|
public class CraftFluidCollisionMode {
|
||||||
|
|
||||||
|
private CraftFluidCollisionMode() {}
|
||||||
|
|
||||||
|
public static FluidCollisionOption toNMS(FluidCollisionMode fluidCollisionMode) {
|
||||||
|
if (fluidCollisionMode == null) return null;
|
||||||
|
|
||||||
|
switch (fluidCollisionMode) {
|
||||||
|
case ALWAYS:
|
||||||
|
return FluidCollisionOption.ALWAYS;
|
||||||
|
case SOURCE_ONLY:
|
||||||
|
return FluidCollisionOption.SOURCE_ONLY;
|
||||||
|
case NEVER:
|
||||||
|
return FluidCollisionOption.NEVER;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ import java.util.Iterator;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import net.minecraft.server.*;
|
import net.minecraft.server.*;
|
||||||
|
|
||||||
|
@ -22,6 +23,7 @@ import org.bukkit.Chunk;
|
||||||
import org.bukkit.ChunkSnapshot;
|
import org.bukkit.ChunkSnapshot;
|
||||||
import org.bukkit.Difficulty;
|
import org.bukkit.Difficulty;
|
||||||
import org.bukkit.Effect;
|
import org.bukkit.Effect;
|
||||||
|
import org.bukkit.FluidCollisionMode;
|
||||||
import org.bukkit.GameRule;
|
import org.bukkit.GameRule;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Particle;
|
import org.bukkit.Particle;
|
||||||
|
@ -43,6 +45,7 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||||
import org.bukkit.craftbukkit.metadata.BlockMetadataStore;
|
import org.bukkit.craftbukkit.metadata.BlockMetadataStore;
|
||||||
import org.bukkit.craftbukkit.potion.CraftPotionUtil;
|
import org.bukkit.craftbukkit.potion.CraftPotionUtil;
|
||||||
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||||
|
import org.bukkit.craftbukkit.util.CraftRayTraceResult;
|
||||||
import org.bukkit.entity.*;
|
import org.bukkit.entity.*;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.minecart.CommandMinecart;
|
import org.bukkit.entity.minecart.CommandMinecart;
|
||||||
|
@ -62,7 +65,9 @@ import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.messaging.StandardMessenger;
|
import org.bukkit.plugin.messaging.StandardMessenger;
|
||||||
import org.bukkit.potion.PotionData;
|
import org.bukkit.potion.PotionData;
|
||||||
import org.bukkit.potion.PotionType;
|
import org.bukkit.potion.PotionType;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
import org.bukkit.util.Consumer;
|
import org.bukkit.util.Consumer;
|
||||||
|
import org.bukkit.util.RayTraceResult;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
public class CraftWorld implements World {
|
public class CraftWorld implements World {
|
||||||
|
@ -691,19 +696,162 @@ public class CraftWorld implements World {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Entity> getNearbyEntities(Location location, double x, double y, double z) {
|
public Collection<Entity> getNearbyEntities(Location location, double x, double y, double z) {
|
||||||
if (location == null || !location.getWorld().equals(this)) {
|
return this.getNearbyEntities(location, x, y, z, null);
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AxisAlignedBB bb = new AxisAlignedBB(location.getX() - x, location.getY() - y, location.getZ() - z, location.getX() + x, location.getY() + y, location.getZ() + z);
|
@Override
|
||||||
|
public Collection<Entity> getNearbyEntities(Location location, double x, double y, double z, Predicate<Entity> filter) {
|
||||||
|
Validate.notNull(location, "Location is null!");
|
||||||
|
Validate.isTrue(this.equals(location.getWorld()), "Location is from different world!");
|
||||||
|
|
||||||
|
BoundingBox aabb = BoundingBox.of(location, x, y, z);
|
||||||
|
return this.getNearbyEntities(aabb, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Entity> getNearbyEntities(BoundingBox boundingBox) {
|
||||||
|
return this.getNearbyEntities(boundingBox, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Entity> getNearbyEntities(BoundingBox boundingBox, Predicate<Entity> filter) {
|
||||||
|
Validate.notNull(boundingBox, "Bounding box is null!");
|
||||||
|
|
||||||
|
AxisAlignedBB bb = new AxisAlignedBB(boundingBox.getMinX(), boundingBox.getMinY(), boundingBox.getMinZ(), boundingBox.getMaxX(), boundingBox.getMaxY(), boundingBox.getMaxZ());
|
||||||
List<net.minecraft.server.Entity> entityList = getHandle().getEntities((net.minecraft.server.Entity) null, bb, null);
|
List<net.minecraft.server.Entity> entityList = getHandle().getEntities((net.minecraft.server.Entity) null, bb, null);
|
||||||
List<Entity> bukkitEntityList = new ArrayList<org.bukkit.entity.Entity>(entityList.size());
|
List<Entity> bukkitEntityList = new ArrayList<org.bukkit.entity.Entity>(entityList.size());
|
||||||
for (Object entity : entityList) {
|
|
||||||
bukkitEntityList.add(((net.minecraft.server.Entity) entity).getBukkitEntity());
|
for (net.minecraft.server.Entity entity : entityList) {
|
||||||
|
Entity bukkitEntity = entity.getBukkitEntity();
|
||||||
|
if (filter == null || filter.test(bukkitEntity)) {
|
||||||
|
bukkitEntityList.add(bukkitEntity);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return bukkitEntityList;
|
return bukkitEntityList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance) {
|
||||||
|
return this.rayTraceEntities(start, direction, maxDistance, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, double raySize) {
|
||||||
|
return this.rayTraceEntities(start, direction, maxDistance, raySize, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, Predicate<Entity> filter) {
|
||||||
|
return this.rayTraceEntities(start, direction, maxDistance, 0.0D, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, double raySize, Predicate<Entity> filter) {
|
||||||
|
Validate.notNull(start, "Start location is null!");
|
||||||
|
Validate.isTrue(this.equals(start.getWorld()), "Start location is from different world!");
|
||||||
|
start.checkFinite();
|
||||||
|
|
||||||
|
Validate.notNull(direction, "Direction is null!");
|
||||||
|
direction.checkFinite();
|
||||||
|
|
||||||
|
Validate.isTrue(direction.lengthSquared() > 0, "Direction's magnitude is 0!");
|
||||||
|
|
||||||
|
if (maxDistance < 0.0D) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector startPos = start.toVector();
|
||||||
|
Vector dir = direction.clone().normalize().multiply(maxDistance);
|
||||||
|
BoundingBox aabb = BoundingBox.of(startPos, startPos).expandDirectional(dir).expand(raySize);
|
||||||
|
Collection<Entity> entities = this.getNearbyEntities(aabb, filter);
|
||||||
|
|
||||||
|
Entity nearestHitEntity = null;
|
||||||
|
RayTraceResult nearestHitResult = null;
|
||||||
|
double nearestDistanceSq = Double.MAX_VALUE;
|
||||||
|
|
||||||
|
for (Entity entity : entities) {
|
||||||
|
BoundingBox boundingBox = entity.getBoundingBox().expand(raySize);
|
||||||
|
RayTraceResult hitResult = boundingBox.rayTrace(startPos, direction, maxDistance);
|
||||||
|
|
||||||
|
if (hitResult != null) {
|
||||||
|
double distanceSq = startPos.distanceSquared(hitResult.getHitPosition());
|
||||||
|
|
||||||
|
if (distanceSq < nearestDistanceSq) {
|
||||||
|
nearestHitEntity = entity;
|
||||||
|
nearestHitResult = hitResult;
|
||||||
|
nearestDistanceSq = distanceSq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (nearestHitEntity == null) ? null : new RayTraceResult(nearestHitResult.getHitPosition(), nearestHitEntity, nearestHitResult.getHitBlockFace());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RayTraceResult rayTraceBlocks(Location start, Vector direction, double maxDistance) {
|
||||||
|
return this.rayTraceBlocks(start, direction, maxDistance, FluidCollisionMode.NEVER, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RayTraceResult rayTraceBlocks(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode) {
|
||||||
|
return this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RayTraceResult rayTraceBlocks(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks) {
|
||||||
|
Validate.notNull(start, "Start location is null!");
|
||||||
|
Validate.isTrue(this.equals(start.getWorld()), "Start location is from different world!");
|
||||||
|
start.checkFinite();
|
||||||
|
|
||||||
|
Validate.notNull(direction, "Direction is null!");
|
||||||
|
direction.checkFinite();
|
||||||
|
|
||||||
|
Validate.isTrue(direction.lengthSquared() > 0, "Direction's magnitude is 0!");
|
||||||
|
Validate.notNull(fluidCollisionMode, "Fluid collision mode is null!");
|
||||||
|
|
||||||
|
if (maxDistance < 0.0D) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector dir = direction.clone().normalize().multiply(maxDistance);
|
||||||
|
Vec3D startPos = new Vec3D(start.getX(), start.getY(), start.getZ());
|
||||||
|
Vec3D endPos = new Vec3D(start.getX() + dir.getX(), start.getY() + dir.getY(), start.getZ() + dir.getZ());
|
||||||
|
MovingObjectPosition nmsHitResult = this.getHandle().rayTrace(startPos, endPos, CraftFluidCollisionMode.toNMS(fluidCollisionMode), ignorePassableBlocks, false);
|
||||||
|
|
||||||
|
return CraftRayTraceResult.fromNMS(this, nmsHitResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate<Entity> filter) {
|
||||||
|
RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks);
|
||||||
|
Vector startVec = null;
|
||||||
|
double blockHitDistance = maxDistance;
|
||||||
|
|
||||||
|
// limiting the entity search range if we found a block hit:
|
||||||
|
if (blockHit != null) {
|
||||||
|
startVec = start.toVector();
|
||||||
|
blockHitDistance = startVec.distance(blockHit.getHitPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
RayTraceResult entityHit = this.rayTraceEntities(start, direction, blockHitDistance, raySize, filter);
|
||||||
|
if (blockHit == null) {
|
||||||
|
return entityHit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entityHit == null) {
|
||||||
|
return blockHit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot be null as blockHit == null returns above
|
||||||
|
double entityHitDistanceSquared = startVec.distanceSquared(entityHit.getHitPosition());
|
||||||
|
if (entityHitDistanceSquared < (blockHitDistance * blockHitDistance)) {
|
||||||
|
return entityHit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockHit;
|
||||||
|
}
|
||||||
|
|
||||||
public List<Player> getPlayers() {
|
public List<Player> getPlayers() {
|
||||||
List<Player> list = new ArrayList<Player>(world.players.size());
|
List<Player> list = new ArrayList<Player>(world.players.size());
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,9 @@ import java.util.List;
|
||||||
|
|
||||||
import net.minecraft.server.*;
|
import net.minecraft.server.*;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.FluidCollisionMode;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
@ -18,15 +20,18 @@ import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.block.BlockState;
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.block.PistonMoveReaction;
|
import org.bukkit.block.PistonMoveReaction;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.craftbukkit.CraftChunk;
|
import org.bukkit.craftbukkit.CraftFluidCollisionMode;
|
||||||
import org.bukkit.craftbukkit.CraftWorld;
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||||
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||||
|
import org.bukkit.craftbukkit.util.CraftRayTraceResult;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.metadata.MetadataValue;
|
import org.bukkit.metadata.MetadataValue;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.util.BlockVector;
|
import org.bukkit.util.BlockVector;
|
||||||
|
import org.bukkit.util.RayTraceResult;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
public class CraftBlock implements Block {
|
public class CraftBlock implements Block {
|
||||||
private final net.minecraft.server.GeneratorAccess world;
|
private final net.minecraft.server.GeneratorAccess world;
|
||||||
|
@ -602,4 +607,45 @@ public class CraftBlock implements Block {
|
||||||
public boolean isPassable() {
|
public boolean isPassable() {
|
||||||
return this.getData0().getCollisionShape(world, position).isEmpty();
|
return this.getData0().getCollisionShape(world, position).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode) {
|
||||||
|
Validate.notNull(start, "Start location is null!");
|
||||||
|
Validate.isTrue(this.getWorld().equals(start.getWorld()), "Start location is from different world!");
|
||||||
|
start.checkFinite();
|
||||||
|
|
||||||
|
Validate.notNull(direction, "Direction is null!");
|
||||||
|
direction.checkFinite();
|
||||||
|
Validate.isTrue(direction.lengthSquared() > 0, "Direction's magnitude is 0!");
|
||||||
|
|
||||||
|
Validate.notNull(fluidCollisionMode, "Fluid collision mode is null!");
|
||||||
|
if (maxDistance < 0.0D) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector dir = direction.clone().normalize().multiply(maxDistance);
|
||||||
|
Vec3D startPos = new Vec3D(start.getX(), start.getY(), start.getZ());
|
||||||
|
Vec3D endPos = new Vec3D(start.getX() + dir.getX(), start.getY() + dir.getY(), start.getZ() + dir.getZ());
|
||||||
|
|
||||||
|
// Similar to to nms.World#rayTrace:
|
||||||
|
IBlockData blockData = world.getType(position);
|
||||||
|
Fluid fluid = world.b(position); // PAIL getFluid
|
||||||
|
boolean collidableBlock = blockData.getBlock().d(blockData); // PAIL isCollidable
|
||||||
|
boolean collideWithFluid = CraftFluidCollisionMode.toNMS(fluidCollisionMode).d.test(fluid); // PAIL predicate
|
||||||
|
|
||||||
|
if (!collidableBlock && !collideWithFluid) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MovingObjectPosition nmsHitResult = null;
|
||||||
|
if (collidableBlock) {
|
||||||
|
nmsHitResult = net.minecraft.server.Block.a(blockData, world.getMinecraftWorld(), position, startPos, endPos); // PAIL rayTrace
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nmsHitResult == null && collideWithFluid) {
|
||||||
|
nmsHitResult = VoxelShapes.a(0.0D, 0.0D, 0.0D, 1.0D, (double) fluid.f(), 1.0D).a(startPos, endPos, position); // PAIL create, getHeight, rayTrace
|
||||||
|
}
|
||||||
|
|
||||||
|
return CraftRayTraceResult.fromNMS(this.getWorld(), nmsHitResult);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.bukkit.permissions.PermissionAttachment;
|
||||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||||
import org.bukkit.permissions.ServerOperator;
|
import org.bukkit.permissions.ServerOperator;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||||
|
@ -273,6 +274,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||||
return getHandle().width;
|
return getHandle().width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BoundingBox getBoundingBox() {
|
||||||
|
AxisAlignedBB bb = getHandle().getBoundingBox();
|
||||||
|
return new BoundingBox(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isOnGround() {
|
public boolean isOnGround() {
|
||||||
if (entity instanceof EntityArrow) {
|
if (entity instanceof EntityArrow) {
|
||||||
return ((EntityArrow) entity).inGround;
|
return ((EntityArrow) entity).inGround;
|
||||||
|
|
|
@ -36,6 +36,7 @@ import net.minecraft.server.MobEffect;
|
||||||
import net.minecraft.server.MobEffectList;
|
import net.minecraft.server.MobEffectList;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
|
import org.bukkit.FluidCollisionMode;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.attribute.Attribute;
|
import org.bukkit.attribute.Attribute;
|
||||||
|
@ -78,6 +79,7 @@ import org.bukkit.potion.PotionEffect;
|
||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
import org.bukkit.potion.PotionType;
|
import org.bukkit.potion.PotionType;
|
||||||
import org.bukkit.util.BlockIterator;
|
import org.bukkit.util.BlockIterator;
|
||||||
|
import org.bukkit.util.RayTraceResult;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||||
|
@ -170,6 +172,29 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||||
return getLineOfSight(transparent, maxDistance, 2);
|
return getLineOfSight(transparent, maxDistance, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block getTargetBlockExact(int maxDistance) {
|
||||||
|
return this.getTargetBlockExact(maxDistance, FluidCollisionMode.NEVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block getTargetBlockExact(int maxDistance, FluidCollisionMode fluidCollisionMode) {
|
||||||
|
RayTraceResult hitResult = this.rayTraceBlocks(maxDistance, fluidCollisionMode);
|
||||||
|
return (hitResult != null ? hitResult.getHitBlock() : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RayTraceResult rayTraceBlocks(double maxDistance) {
|
||||||
|
return this.rayTraceBlocks(maxDistance, FluidCollisionMode.NEVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RayTraceResult rayTraceBlocks(double maxDistance, FluidCollisionMode fluidCollisionMode) {
|
||||||
|
Location eyeLocation = this.getEyeLocation();
|
||||||
|
Vector direction = eyeLocation.getDirection();
|
||||||
|
return this.getWorld().rayTraceBlocks(eyeLocation, direction, maxDistance, fluidCollisionMode, false);
|
||||||
|
}
|
||||||
|
|
||||||
public int getRemainingAir() {
|
public int getRemainingAir() {
|
||||||
return getHandle().getAirTicks();
|
return getHandle().getAirTicks();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package org.bukkit.craftbukkit.util;
|
||||||
|
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.craftbukkit.block.CraftBlock;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.util.RayTraceResult;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import net.minecraft.server.BlockPosition;
|
||||||
|
import net.minecraft.server.MovingObjectPosition;
|
||||||
|
import net.minecraft.server.MovingObjectPosition.EnumMovingObjectType;
|
||||||
|
import net.minecraft.server.Vec3D;
|
||||||
|
|
||||||
|
public class CraftRayTraceResult {
|
||||||
|
|
||||||
|
private CraftRayTraceResult() {}
|
||||||
|
|
||||||
|
public static RayTraceResult fromNMS(World world, MovingObjectPosition nmsHitResult) {
|
||||||
|
if (nmsHitResult == null || nmsHitResult.type == EnumMovingObjectType.MISS) return null;
|
||||||
|
|
||||||
|
Vec3D nmsHitPos = nmsHitResult.pos;
|
||||||
|
Vector hitPosition = new Vector(nmsHitPos.x, nmsHitPos.y, nmsHitPos.z);
|
||||||
|
BlockFace hitBlockFace = null;
|
||||||
|
|
||||||
|
if (nmsHitResult.direction != null) {
|
||||||
|
hitBlockFace = CraftBlock.notchToBlockFace(nmsHitResult.direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nmsHitResult.entity != null) {
|
||||||
|
Entity hitEntity = nmsHitResult.entity.getBukkitEntity();
|
||||||
|
return new RayTraceResult(hitPosition, hitEntity, hitBlockFace);
|
||||||
|
}
|
||||||
|
|
||||||
|
Block hitBlock = null;
|
||||||
|
BlockPosition nmsBlockPos = nmsHitResult.a(); // PAIL: getBlockPosition
|
||||||
|
if (nmsBlockPos != null && world != null) {
|
||||||
|
hitBlock = world.getBlockAt(nmsBlockPos.getX(), nmsBlockPos.getY(), nmsBlockPos.getZ());
|
||||||
|
}
|
||||||
|
return new RayTraceResult(hitPosition, hitBlock, hitBlockFace);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue