diff --git a/src/main/java/net/citizensnpcs/api/ai/goals/WanderGoal.java b/src/main/java/net/citizensnpcs/api/ai/goals/WanderGoal.java index d6043e01..237f2af1 100644 --- a/src/main/java/net/citizensnpcs/api/ai/goals/WanderGoal.java +++ b/src/main/java/net/citizensnpcs/api/ai/goals/WanderGoal.java @@ -32,7 +32,6 @@ public class WanderGoal extends BehaviorGoalAdapter implements Listener { private boolean forceFinish; private final NPC npc; private boolean paused; - private final Random random = new Random(); private final Supplier> tree; private int xrange; private int yrange; @@ -47,26 +46,21 @@ private WanderGoal(NPC npc, int xrange, int yrange, Supplier() { + @Override + public Boolean apply(Block block) { + if ((block.getRelative(BlockFace.UP).isLiquid() || block.getRelative(0, 2, 0).isLiquid()) + && npc.getNavigator().getDefaultParameters().avoidWater()) { + return false; + } + long[] pt = { block.getX(), block.getY(), block.getZ() }; + if (tree != null && tree.get() != null && !tree.get().queryIntersect(pt, pt).hasNext()) { + return false; + } + return true; + } + }, RANDOM); if (found == null && fallback != null) { return fallback.apply(npc); } @@ -157,4 +151,7 @@ public static WanderGoal createWithNPCAndRangeAndTreeAndFallback(NPC npc, int xr Supplier> tree, Function fallback) { return new WanderGoal(npc, xrange, yrange, tree, fallback); } + + private static final Location NPC_LOCATION = new Location(null, 0, 0, 0); + private static final Random RANDOM = new Random(); } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/api/astar/pathfinder/MinecraftBlockExaminer.java b/src/main/java/net/citizensnpcs/api/astar/pathfinder/MinecraftBlockExaminer.java index f7ec62f4..51fd30dd 100644 --- a/src/main/java/net/citizensnpcs/api/astar/pathfinder/MinecraftBlockExaminer.java +++ b/src/main/java/net/citizensnpcs/api/astar/pathfinder/MinecraftBlockExaminer.java @@ -2,7 +2,9 @@ import java.util.EnumSet; import java.util.ListIterator; +import java.util.Random; import java.util.Set; +import java.util.function.Function; import org.bukkit.Location; import org.bukkit.Material; @@ -123,6 +125,34 @@ public static boolean canStandOn(Material mat) { return !UNWALKABLE.contains(mat) && mat.isSolid(); } + public static Location findRandomValidLocation(Location base, int xrange, int yrange) { + return findRandomValidLocation(base, xrange, yrange, null, new Random()); + } + + public static Location findRandomValidLocation(Location base, int xrange, int yrange, + Function filter) { + return findRandomValidLocation(base, xrange, yrange, filter, new Random()); + } + + public static Location findRandomValidLocation(Location base, int xrange, int yrange, + Function filter, Random random) { + Location found = null; + for (int i = 0; i < 10; i++) { + int x = base.getBlockX() + random.nextInt(2 * xrange) - xrange; + int y = base.getBlockY() + random.nextInt(2 * yrange) - yrange; + int z = base.getBlockZ() + random.nextInt(2 * xrange) - xrange; + Block block = base.getWorld().getBlockAt(x, y, z); + if (MinecraftBlockExaminer.canStandOn(block)) { + if (filter != null && !filter.apply(block)) { + continue; + } + found = block.getLocation().add(0, 1, 0); + break; + } + } + return found; + } + public static Location findValidLocation(Location location, int radius) { Block base = location.getBlock(); if (canStandOn(base.getRelative(BlockFace.DOWN)))