From 9122048b22af75fd7173ce57b8ae8d94b8a4590c Mon Sep 17 00:00:00 2001 From: fullwall Date: Sun, 19 Jun 2022 12:02:48 +0800 Subject: [PATCH] Add canStand**(block) --- .../api/ai/TeleportStuckAction.java | 18 +++------ .../api/astar/pathfinder/BlockSource.java | 9 +++++ .../astar/pathfinder/FlyingBlockExaminer.java | 7 ++-- .../pathfinder/MinecraftBlockExaminer.java | 40 ++++++++++++------- .../astar/pathfinder/SwimmingExaminer.java | 5 ++- .../citizensnpcs/api/hpastar/HPAGraph.java | 6 +-- 6 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/main/java/net/citizensnpcs/api/ai/TeleportStuckAction.java b/src/main/java/net/citizensnpcs/api/ai/TeleportStuckAction.java index c8349780..d6308cb6 100644 --- a/src/main/java/net/citizensnpcs/api/ai/TeleportStuckAction.java +++ b/src/main/java/net/citizensnpcs/api/ai/TeleportStuckAction.java @@ -13,34 +13,26 @@ private TeleportStuckAction() { // singleton } - private boolean canStand(Block block) { - return MinecraftBlockExaminer.canStandIn(block.getType()) - && MinecraftBlockExaminer.canStandIn(block.getRelative(BlockFace.UP).getType()); - } - @Override public boolean run(NPC npc, Navigator navigator) { if (!npc.isSpawned()) return false; Location base = navigator.getTargetAsLocation(); - if (base == null || npc.getEntity().getWorld() == base.getWorld() - && npc.getEntity().getLocation(CACHE_LOC).distanceSquared(base) <= RANGE) + if (base == null || base.getWorld() != npc.getEntity().getWorld()) return true; - Block block = base.getBlock(); + Block block = base.getBlock().getRelative(BlockFace.DOWN); int iterations = 0; - while (!canStand(block)) { + while (!MinecraftBlockExaminer.canStandOn(block)) { if (iterations++ >= MAX_ITERATIONS) { - block = base.getBlock(); + block = base.getBlock().getRelative(BlockFace.DOWN); break; } block = block.getRelative(BlockFace.UP); } - npc.teleport(block.getLocation(), TeleportCause.PLUGIN); + npc.teleport(block.getRelative(BlockFace.UP).getLocation(), TeleportCause.PLUGIN); return false; } - private static final Location CACHE_LOC = new Location(null, 0, 0, 0); public static TeleportStuckAction INSTANCE = new TeleportStuckAction(); private static final int MAX_ITERATIONS = 10; - private static final double RANGE = 10; } diff --git a/src/main/java/net/citizensnpcs/api/astar/pathfinder/BlockSource.java b/src/main/java/net/citizensnpcs/api/astar/pathfinder/BlockSource.java index c7c8859f..d04d371b 100644 --- a/src/main/java/net/citizensnpcs/api/astar/pathfinder/BlockSource.java +++ b/src/main/java/net/citizensnpcs/api/astar/pathfinder/BlockSource.java @@ -2,11 +2,20 @@ import org.bukkit.Material; import org.bukkit.World; +import org.bukkit.block.Block; import org.bukkit.util.Vector; import net.citizensnpcs.api.util.BoundingBox; public abstract class BlockSource { + public Block getBlock(int x, int y, int z) { + return getWorld().getBlockAt(x, y, z); + } + + public Block getBlock(Vector position) { + return getWorld().getBlockAt(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + } + public abstract BoundingBox getCollisionBox(int x, int y, int z); public BoundingBox getCollisionBox(Vector pos) { diff --git a/src/main/java/net/citizensnpcs/api/astar/pathfinder/FlyingBlockExaminer.java b/src/main/java/net/citizensnpcs/api/astar/pathfinder/FlyingBlockExaminer.java index fb336ac1..377816aa 100644 --- a/src/main/java/net/citizensnpcs/api/astar/pathfinder/FlyingBlockExaminer.java +++ b/src/main/java/net/citizensnpcs/api/astar/pathfinder/FlyingBlockExaminer.java @@ -3,6 +3,7 @@ import java.util.List; import org.bukkit.Material; +import org.bukkit.block.Block; import org.bukkit.util.Vector; import com.google.common.collect.Lists; @@ -43,9 +44,9 @@ public List getNeighbours(BlockSource source, PathPoint point) { @Override public PassableState isPassable(BlockSource source, PathPoint point) { Vector pos = point.getVector(); - Material above = source.getMaterialAt(pos.clone().add(UP)); - Material in = source.getMaterialAt(pos); - if (MinecraftBlockExaminer.isLiquid(above, in)) { + Block above = source.getBlock(pos.clone().add(UP)); + Block in = source.getBlock(pos); + if (MinecraftBlockExaminer.isLiquid(above.getType(), in.getType())) { return PassableState.UNPASSABLE; } return PassableState.fromBoolean(MinecraftBlockExaminer.canStandIn(above, in)); 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 30c72330..ca67fed7 100644 --- a/src/main/java/net/citizensnpcs/api/astar/pathfinder/MinecraftBlockExaminer.java +++ b/src/main/java/net/citizensnpcs/api/astar/pathfinder/MinecraftBlockExaminer.java @@ -11,6 +11,7 @@ import org.bukkit.block.BlockFace; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Waterlogged; +import org.bukkit.block.data.type.Slab; import org.bukkit.util.Vector; import com.google.common.base.Function; @@ -52,14 +53,14 @@ public PassableState isPassable(BlockSource source, PathPoint point) { if (!SpigotUtil.checkYSafe(pos.getBlockY(), source.getWorld())) { return PassableState.UNPASSABLE; } - Material above = source.getMaterialAt(pos.getBlockX(), pos.getBlockY() + 1, pos.getBlockZ()); + Block above = source.getBlock(pos.getBlockX(), pos.getBlockY() + 1, pos.getBlockZ()); Material below = source.getMaterialAt(pos.getBlockX(), pos.getBlockY() - 1, pos.getBlockZ()); - Material in = source.getMaterialAt(pos); - boolean canStand = canStandOn(below) || isLiquid(in, below) || isClimbable(below); + Block in = source.getBlock(pos); + boolean canStand = canStandOn(below) || isLiquid(in.getType(), below) || isClimbable(below); if (!canStand) { return PassableState.UNPASSABLE; } - if (isClimbable(in) && (isClimbable(above) || isClimbable(below))) { + if (isClimbable(in.getType()) && (isClimbable(above.getType()) || isClimbable(below))) { point.addCallback(new LadderClimber()); } else if (!canStandIn(above) || !canStandIn(in)) { return PassableState.UNPASSABLE; @@ -133,6 +134,20 @@ private static boolean canJumpOn(Material mat) { return !NOT_JUMPABLE.contains(mat); } + public static boolean canStandIn(Block... blocks) { + boolean passable = true; + for (Block block : blocks) { + passable &= !block.getType().isSolid(); + if (block.getType().name().contains("_SLAB")) { + Slab slab = (Slab) block.getBlockData(); + if (slab.getType() != Slab.Type.BOTTOM) { + passable = false; + } + } + } + return passable; + } + public static boolean canStandIn(Material... mat) { boolean passable = true; for (Material m : mat) { @@ -143,8 +158,8 @@ public static boolean canStandIn(Material... 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()); + boolean standable = canStandOn(block.getType()); + return standable && canStandIn(up, up.getRelative(BlockFace.UP)); } public static boolean canStandOn(Material mat) { @@ -170,7 +185,7 @@ public static Location findRandomValidLocation(Location base, int xrange, int yr continue; } Block block = base.getWorld().getBlockAt(x, y, z); - if (MinecraftBlockExaminer.canStandOn(block)) { + if (canStandOn(block)) { if (filter != null && !filter.apply(block)) { continue; } @@ -190,9 +205,9 @@ public static Location findValidLocation(Location location, int radius) { if (!base.getWorld().isChunkLoaded(base.getX() + x >> 4, base.getZ() + z >> 4)) { continue; } - Block relative = base.getRelative(x, y, z); - if (canStandOn(relative.getRelative(BlockFace.DOWN))) { - return relative.getLocation(); + Block offset = base.getRelative(x, y, z); + if (canStandOn(offset.getRelative(BlockFace.DOWN))) { + return offset.getLocation(); } } } @@ -264,11 +279,6 @@ public static boolean isLiquidOrInLiquid(Block block) { } } - public static boolean validPosition(Block in) { - return canStandIn(in.getType()) && canStandIn(in.getRelative(BlockFace.UP).getType()) - && canStandOn(in.getRelative(BlockFace.DOWN).getType()); - } - private static final Set CLIMBABLE = EnumSet.of(Material.LADDER, Material.VINE); private static final Set LIQUIDS = EnumSet.of(Material.WATER, Material.LAVA); private static final Set NOT_JUMPABLE = EnumSet.of(Material.SPRUCE_FENCE, Material.BIRCH_FENCE, diff --git a/src/main/java/net/citizensnpcs/api/astar/pathfinder/SwimmingExaminer.java b/src/main/java/net/citizensnpcs/api/astar/pathfinder/SwimmingExaminer.java index 2631f972..0d8e154f 100644 --- a/src/main/java/net/citizensnpcs/api/astar/pathfinder/SwimmingExaminer.java +++ b/src/main/java/net/citizensnpcs/api/astar/pathfinder/SwimmingExaminer.java @@ -1,6 +1,7 @@ package net.citizensnpcs.api.astar.pathfinder; import org.bukkit.Material; +import org.bukkit.block.Block; import org.bukkit.entity.Entity; import org.bukkit.entity.Squid; import org.bukkit.entity.WaterMob; @@ -44,8 +45,8 @@ public PassableState isPassable(BlockSource source, PathPoint point) { if (isWaterMob(npc.getEntity())) { return PassableState.PASSABLE; } - Material above = source.getMaterialAt(vector.clone().add(UP)); - return isSwimmableLiquid(above) || MinecraftBlockExaminer.canStandIn(above) ? PassableState.PASSABLE + Block block = source.getBlock(vector.clone().add(UP)); + return isSwimmableLiquid(block.getType()) || MinecraftBlockExaminer.canStandIn(block) ? PassableState.PASSABLE : PassableState.UNPASSABLE; } diff --git a/src/main/java/net/citizensnpcs/api/hpastar/HPAGraph.java b/src/main/java/net/citizensnpcs/api/hpastar/HPAGraph.java index 816d5a45..993ce95f 100644 --- a/src/main/java/net/citizensnpcs/api/hpastar/HPAGraph.java +++ b/src/main/java/net/citizensnpcs/api/hpastar/HPAGraph.java @@ -8,7 +8,6 @@ import java.util.Queue; import org.bukkit.Location; -import org.bukkit.Material; import com.google.common.collect.HashMultimap; import com.google.common.collect.Lists; @@ -213,10 +212,7 @@ public boolean walkable(int x, int y, int z) { if (y == 0) { return false; } - Material in = blockSource.getMaterialAt(x, y, z), on = blockSource.getMaterialAt(x, y - 1, z), - above = blockSource.getMaterialAt(x, y + 1, z); - return MinecraftBlockExaminer.canStandOn(on) && MinecraftBlockExaminer.canStandIn(in) - && MinecraftBlockExaminer.canStandIn(above); + return MinecraftBlockExaminer.canStandOn(blockSource.getWorld().getBlockAt(x, y - 1, z)); } private static int BASE_CLUSTER_SIZE = (int) (2 * Math.pow(2, 3));