package net.aufdemrand.denizen.npc.examiners; import net.aufdemrand.denizen.objects.dMaterial; import net.aufdemrand.denizen.objects.dNPC; import net.citizensnpcs.api.astar.pathfinder.BlockExaminer; import net.citizensnpcs.api.astar.pathfinder.BlockSource; import net.citizensnpcs.api.astar.pathfinder.PathPoint; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.util.Vector; import java.util.*; public class PathBlockExaminer implements BlockExaminer { // Default pathing materials static final List<dMaterial> default_pathing_materials = Arrays.asList(dMaterial.valueOf("gravel"), dMaterial.valueOf("dirt"), dMaterial.valueOf("cobblestone")); List<dMaterial> pathing_materials = new ArrayList<dMaterial>(default_pathing_materials); // Unfortunately for this to work properly, it needs // to have a NPC attached to the Examiner. public PathBlockExaminer(dNPC npc, List<dMaterial> filter) { if (filter != null) { pathing_materials = filter; } this.npc = npc; } dNPC npc; @Override public float getCost(BlockSource source, PathPoint point) { // TODO: Understand cost weight :D Vector pos = point.getVector(); Material above = source.getMaterialAt(pos.clone().add(UP)); Material below = source.getMaterialAt(pos.clone().add(DOWN)); Material in = source.getMaterialAt(pos); // Discourage walking up a Z level if (point.getVector().getBlockY() > npc.getEntity().getLocation().getBlockY()) { return 5f; } // Encourage materials that are not in the filter for (dMaterial mat : pathing_materials) { // Discourage walking through web if (above == Material.WEB || in == Material.WEB) { return 1F; } // Discourage liquid if (isLiquid(above, below, in)) { return 1F; } // Encourage pathing materials if (below == mat.getMaterial()) { return 0F; } } return .5f; } @Override public PassableState isPassable(BlockSource source, PathPoint point) { Vector pos = point.getVector(); Material above = source.getMaterialAt(pos.clone().add(UP)); Material below = source.getMaterialAt(pos.clone().add(DOWN)); Material in = source.getMaterialAt(pos); if (!below.isBlock() || !canStandOn(below)) { return PassableState.UNPASSABLE; } if (!canStandIn(above) || !canStandIn(in)) { return PassableState.UNPASSABLE; } return PassableState.PASSABLE; } public static boolean canStandIn(Material... mat) { return PASSABLE.containsAll(Arrays.asList(mat)); } public static boolean canStandOn(Block block) { Block up = block.getRelative(BlockFace.UP); return canStandOn(block.getType()) && canStandIn(up.getType()) && canStandIn(up.getRelative(BlockFace.UP).getType()); } public static boolean canStandOn(Material mat) { return !UNWALKABLE.contains(mat) && !PASSABLE.contains(mat); } private static boolean contains(Material[] search, Material... find) { for (Material haystack : search) { for (Material needle : find) { if (haystack == needle) { return true; } } } return false; } public static boolean isLiquid(Material... materials) { return contains(materials, Material.WATER, Material.STATIONARY_WATER, Material.LAVA, Material.STATIONARY_LAVA); } private static final Vector DOWN = new Vector(0, -1, 0); private static final Set<Material> PASSABLE = EnumSet.of(Material.AIR, Material.DEAD_BUSH, Material.DETECTOR_RAIL, Material.DIODE, Material.DIODE_BLOCK_OFF, Material.DIODE_BLOCK_ON, Material.FENCE_GATE, Material.ITEM_FRAME, Material.LADDER, Material.LEVER, Material.LONG_GRASS, Material.CARPET, Material.MELON_STEM, Material.NETHER_FENCE, Material.PUMPKIN_STEM, Material.POWERED_RAIL, Material.RAILS, Material.RED_ROSE, Material.RED_MUSHROOM, Material.REDSTONE, Material.REDSTONE_TORCH_OFF, Material.REDSTONE_TORCH_OFF, Material.REDSTONE_WIRE, Material.SIGN, Material.SIGN_POST, Material.SNOW, Material.STRING, Material.STONE_BUTTON, Material.SUGAR_CANE_BLOCK, Material.TRIPWIRE, Material.VINE, Material.WALL_SIGN, Material.WHEAT, Material.WATER, Material.WEB, Material.WOOD_BUTTON, Material.WOODEN_DOOR, Material.STATIONARY_WATER); private static final Set<Material> UNWALKABLE = EnumSet.of(Material.AIR, Material.LAVA, Material.STATIONARY_LAVA, Material.CACTUS); private static final Vector UP = new Vector(0, 1, 0); }