package com.supaham.commons.bukkit.utils; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.Supplier; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.BlockFace; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.util.Vector; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import javax.annotation.Nonnull; /** * Utility methods for working with {@link Entity} instances. This class contains methods such as * {@link #getFreeLocation(LivingEntity)}, and more. * * @since 0.1 */ public class EntityUtils { /** * Returns a free safe location above or at the given {@link LivingEntity}'s location. * * @param entity entity to get free space for * * @return a location with the required free space * * @see LocationUtils#getFreeLocation(Location, double) */ public static Location getFreeLocation(@Nonnull LivingEntity entity) { checkNotNull(entity, "entity cannot be null."); return LocationUtils.getFreeLocation(entity.getLocation(), entity.getEyeHeight(true)); } /* ================================ * >> GUAVA implementations * ================================ */ /** * Gets a new {@link EntitiesSupplier} which returns all entities in a {@link Chunk}. * * @param chunk chunk to get entities from * * @return entities supplier * * @see #multiChunkEntities(Collection) */ public static EntitiesSupplier singleChunkEntities(@Nonnull Chunk chunk) { return multiChunkEntities(chunk); } /** * Gets a new {@link EntitiesSupplier} which returns all entities in an array of {@link Chunk}s. * * @param chunks chunks to get entities from * * @return entities supplier * * @see #multiChunkEntities(Collection) */ public static EntitiesSupplier multiChunkEntities(@Nonnull Chunk... chunks) { return new ChunkEntitiesSupplier(Arrays.asList(chunks)); } /** * Gets a new {@link EntitiesSupplier} which returns all entities in a collection of {@link * Chunk}s. * * @param chunks chunks to get entities from * * @return entities supplier */ public static EntitiesSupplier multiChunkEntities(@Nonnull Collection<Chunk> chunks) { return new ChunkEntitiesSupplier(chunks); } /** * Gets a new {@link EntitiesSupplier} which returns all entities in a {@link World}. * * @param world world to get entities from * * @return entities supplier */ public static EntitiesSupplier worldEntities(@Nonnull World world) { return new WorldEntitiesSupplier(world); } /** * Clears all potions effects on a {@link LivingEntity}. * * @param entity entity to remove effects from * * @return the removed {@link PotionEffect}s, if any, otherwise empty */ public static Collection<PotionEffect> clearPotionEffects(@Nonnull LivingEntity entity, @Nonnull PotionEffectType... ignore) { checkNotNull(entity, "entity cannot be null."); Collection<PotionEffect> effects = entity.getActivePotionEffects(); Iterator<PotionEffect> it = effects.iterator(); while (it.hasNext()) { PotionEffect potionEffect = it.next(); for (PotionEffectType type : ignore) { if (potionEffect.getType().equals(type)) { it.remove(); } } entity.removePotionEffect(potionEffect.getType()); } return effects; } public static boolean isOnGround(@Nonnull Entity entity) { return !(entity instanceof Player) ? entity.isOnGround() : entity.getLocation().getBlock() .getRelative(BlockFace.DOWN).getType().isSolid(); } public static Vector getDirection(LivingEntity entity, boolean eye) { return getDirection(entity, eye, 1); } public static Vector getDirection(LivingEntity entity, boolean eye, double multiply) { return (eye ? entity.getEyeLocation() : entity.getLocation()).toVector() .add(entity.getLocation().getDirection().multiply(multiply)); } public static interface EntitySupplier extends Supplier<Entity> {} public static interface EntitiesSupplier extends Supplier<Collection<Entity>> {} private static class ChunkEntitiesSupplier implements EntitiesSupplier { private final Collection<Chunk> chunks; public ChunkEntitiesSupplier(Collection<Chunk> chunks) { this.chunks = checkNotNull(chunks, "chunk cannot be null."); } @Override public Collection<Entity> get() { ArrayList<Entity> entities = new ArrayList<>(); for (Chunk chunk : chunks) { entities.addAll(Arrays.asList(chunk.getEntities())); } return entities; } } private static class WorldEntitiesSupplier implements EntitiesSupplier { private final World world; public WorldEntitiesSupplier(World world) { this.world = checkNotNull(world, "world cannot be null."); } @Override public Collection<Entity> get() { return world.getEntities(); } } }