package com.supaham.commons.bukkit.raytracing; import com.supaham.commons.bukkit.utils.ImmutableBlockVector; import com.supaham.commons.bukkit.utils.ImmutableVector; import com.supaham.commons.bukkit.utils.ReflectionUtils; import org.bukkit.block.BlockFace; import org.bukkit.entity.Entity; import java.lang.reflect.Field; /** * Represents a possible moving object position, used by {@link RayTracing}. * * @since 0.3.5 */ public class MovingObjectPosition { private Type type; private BlockFace direction; private ImmutableBlockVector blockPosition; private ImmutableVector position; private Entity entity; private MovingObjectPosition() {} protected static MovingObjectPosition from(Object object) { return MakeFrom.from(object); } public MovingObjectPosition(Type type, BlockFace direction, ImmutableBlockVector blockPosition, ImmutableVector position, Entity entity) { this.type = type; this.direction = direction; this.blockPosition = blockPosition; this.position = position; this.entity = entity; } @Override public String toString() { return "MovingObjectPosition{" + "type=" + this.type + ", dir=" + this.direction + ", blockPos=" + this.blockPosition + ", pos=" + this.position + ", entity=" + this.entity + '}'; } /** * Returns the type of this object ray trace result. * * @return type */ public Type getType() { return type; } /** * Gets the {@link BlockFace} of where the block was hit. * * @return block face */ public BlockFace getDirection() { return direction; } /** * Returns an {@link ImmutableBlockVector} of where the block hit * * @return block vector */ public ImmutableBlockVector getBlockPosition() { return blockPosition; } /** * Returns an {@link ImmutableVector} representing the exact position the ray trace hit. * * @return vector */ public ImmutableVector getPosition() { return position; } /** * Returns the {@link Entity} that was hit as a result of the ray trace. * * @return entity */ public Entity getEntity() { return entity; } /** * Represents a type of event that a {@link MovingObjectPosition} consists of. */ public enum Type { /** * Represents a miss event, where no block or entity was found. This only happens if the ray * trace specifies returning the last collidable block */ MISS, /** * Represents a block hit event. */ BLOCK, /** * Represents an entity hit event. */ ENTITY } private static final class MakeFrom { private static Field blockPos; private static Field type; private static Field direction; private static Field pos; private static Field entity; static { Class nmsMOP = ReflectionUtils.getNMSClass("MovingObjectPosition"); try { blockPos = nmsMOP.getDeclaredField("e"); blockPos.setAccessible(true); type = nmsMOP.getDeclaredField("type"); direction = nmsMOP.getDeclaredField("direction"); pos = nmsMOP.getDeclaredField("pos"); entity = nmsMOP.getDeclaredField("entity"); } catch (NoSuchFieldException e) { e.printStackTrace(); } } public static MovingObjectPosition from(Object object) { try { MovingObjectPosition mop = new MovingObjectPosition(); Type type = Type.valueOf(((Enum) MakeFrom.type.get(object)).name()); mop.type = type; //noinspection ConstantConditions mop.position = new ImmutableVector(ReflectionUtils.fromNMSVec3D(MakeFrom.pos.get(object))); if (type == Type.ENTITY) { mop.entity = ReflectionUtils.getBukkitEntity(MakeFrom.entity.get(object)); } else { mop.blockPosition = new ImmutableBlockVector( ReflectionUtils.fromNMSBlockPosition(MakeFrom.blockPos.get(object))); mop.direction = BlockFace.valueOf(((Enum) MakeFrom.direction.get(object)).name()); } return mop; } catch (IllegalAccessException e) { e.printStackTrace(); return null; } } } }