package com.github.jamesnorris.ablockalypse.utility; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.regex.Pattern; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.OfflinePlayer; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.Chest; import org.bukkit.block.DoubleChest; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; public class BukkitUtility { public static int[] swords = new int[] {268, 283, 272, 267, 276}; private static Random rand = new Random(); private static String nms_version = "v1.5.2"; static { String bukkitVersion = Bukkit.getVersion(); String cleanedVersion = bukkitVersion.split(Pattern.quote("(MC:"))[1].split(Pattern.quote(")"))[0].trim(); nms_version = "v" + cleanedVersion; } public static Location floorLivingEntity(LivingEntity entity) { Location eyeLoc = entity.getEyeLocation().clone(); double eyeHeight = entity.getEyeHeight(); Location floor = eyeLoc.clone().subtract(0, Math.floor(eyeHeight) + .5, 0); for (int y = eyeLoc.getBlockY(); y > 0; y--) { Location loc = new Location(floor.getWorld(), floor.getX(), y, floor.getZ(), floor.getYaw(), floor.getPitch()); if (!loc.getBlock().isEmpty()) { floor = loc; break; } } return eyeLoc.clone().subtract(0, eyeLoc.getY() - floor.getY() - 2 * eyeHeight, 0); } public static OfflinePlayer forceObtainPlayer(String name) { OfflinePlayer player = Bukkit.getPlayer(name); if (player == null) { return Bukkit.getOfflinePlayer(name); } if (player == null || !player.hasPlayedBefore()) { // npes will be thrown... player doesnt exist and never did (why was it saved?) return null; } return player; } public static Location fromString(String loc) { loc = loc.substring(loc.indexOf("{") + 1); loc = loc.substring(loc.indexOf("{") + 1); String worldName = loc.substring(loc.indexOf("=") + 1, loc.indexOf("}")); loc = loc.substring(loc.indexOf(",") + 1); String xCoord = loc.substring(loc.indexOf("=") + 1, loc.indexOf(",")); loc = loc.substring(loc.indexOf(",") + 1); String yCoord = loc.substring(loc.indexOf("=") + 1, loc.indexOf(",")); loc = loc.substring(loc.indexOf(",") + 1); String zCoord = loc.substring(loc.indexOf("=") + 1, loc.indexOf(",")); loc = loc.substring(loc.indexOf(",") + 1); String pitch = loc.substring(loc.indexOf("=") + 1, loc.indexOf(",")); loc = loc.substring(loc.indexOf(",") + 1); String yaw = loc.substring(loc.indexOf("=") + 1, loc.indexOf("}")); return new Location(Bukkit.getWorld(worldName), Double.parseDouble(xCoord), Double.parseDouble(yCoord), Double.parseDouble(zCoord), Float.parseFloat(yaw), Float.parseFloat(pitch)); } public static Block getHighestEmptyBlockUnder(Location loc) { for (int y = loc.getBlockY(); y > 0; y--) { Location floor = new Location(loc.getWorld(), loc.getX(), y, loc.getZ(), loc.getYaw(), loc.getPitch()); Block block = floor.getBlock(); if (!block.isEmpty()) { return block; } } return loc.getBlock(); } public static List<Entity> getNearbyEntities(Location loc, double x, double y, double z) { List<Entity> entities = new ArrayList<Entity>(); for (Chunk chunk : getRelativeChunks(loc.getChunk())) { for (Entity entity : chunk.getEntities()) { Location entLoc = entity.getLocation(); if (Math.abs(entLoc.getX() - loc.getX()) <= x && Math.abs(entLoc.getY() - loc.getY()) <= y && Math.abs(entLoc.getZ() - loc.getZ()) <= z && !entities.contains(entity)) { entities.add(entity); } } } return entities; } public static Location getNearbyLocation(Location loc, double minXdif, double maxXdif, double minYdif, double maxYdif, double minZdif, double maxZdif) { double modX = difInRandDirection(maxXdif, minXdif); double modY = difInRandDirection(maxXdif, minXdif); double modZ = difInRandDirection(maxXdif, minXdif); return loc.clone().add(modX, modY, modZ); } public static String getNMSVersionSlug() { return nms_version; } /** * Gets all nearby chunks * @param chunk The chunk to find relatives * @return All nearby chunks, including the one passed as a parameter */ public static Chunk[] getRelativeChunks(Chunk chunk) { World world = chunk.getWorld(); return new Chunk[] {chunk, world.getChunkAt(chunk.getX() - 16, chunk.getZ() - 16), world.getChunkAt(chunk.getX() - 16, chunk.getZ()), world.getChunkAt(chunk.getX(), chunk.getZ() - 16), world.getChunkAt(chunk.getX(), chunk.getZ()), world.getChunkAt(chunk.getX() + 16, chunk.getZ() - 16), world.getChunkAt(chunk.getX() - 16, chunk.getZ() + 16), world.getChunkAt(chunk.getX() + 16, chunk.getZ()), world.getChunkAt(chunk.getX(), chunk.getZ() + 16)}; } public static Block getSecondChest(Block b) { BlockFace[] faces = new BlockFace[] {BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST}; for (BlockFace face : faces) { Block bl = b.getRelative(face); if (bl.getState() instanceof Chest || bl.getState() instanceof DoubleChest) { return bl; } } return null; } public static boolean isDoubleChest(Block block) { if (block == null || !(block.getState() instanceof Chest)) { return false; } Chest chest = (Chest) block.getState(); return chest.getInventory().getContents().length == 54; } public static boolean isEnchantableLikeSwords(ItemStack item) { for (int id : swords) { if (item.getTypeId() == id) { return true; } } return false; } public static boolean locationMatch(Location loc1, Location loc2) { boolean nearX = Math.floor(loc1.getBlockX()) == Math.floor(loc2.getBlockX()); boolean nearY = Math.floor(loc1.getBlockY()) == Math.floor(loc2.getBlockY()); boolean nearZ = Math.floor(loc1.getBlockZ()) == Math.floor(loc2.getBlockZ()); return nearX && nearY && nearZ; } public static boolean locationMatch(Location loc1, Location loc2, int distance) {// TODO this method is exact, fix return Math.abs(loc1.getX() - loc2.getX()) <= distance && Math.abs(loc1.getY() - loc2.getY()) <= distance && Math.abs(loc1.getZ() - loc2.getZ()) <= distance; } public static boolean locationMatchExact(Location loc1, Location loc2) { return locationMatchExact(loc1, loc2, 0); } public static boolean locationMatchExact(Location loc1, Location loc2, double distance) { return loc1.distanceSquared(loc2) <= Math.pow(distance, 2); } public static void setChestOpened(List<Player> players, Block block, boolean opened) { if (block == null || !(block.getState() instanceof Chest)) { return; } byte open = opened ? (byte) 1 : (byte) 0; for (Player player : players) { player.playNote(block.getLocation(), (byte) 1, open); if (isDoubleChest(block)) { player.playNote(getSecondChest(block).getLocation(), (byte) 1, open); } } } public static void setChestOpened(Player player, Block block, boolean opened) { if (block == null || !(block.getState() instanceof Chest)) { return; } byte open = opened ? (byte) 1 : (byte) 0; player.playNote(block.getLocation(), (byte) 1, open); if (isDoubleChest(block)) { player.playNote(getSecondChest(block).getLocation(), (byte) 1, open); } } private static double difInRandDirection(double max, double min) { return (rand.nextBoolean() ? 1 : -1) * (rand.nextDouble() * Math.abs(max - min) + Math.abs(min)); } }