/** * For future maintainers: *

* This class was a pain in the ass (yay)! *

* The general idea is to override PathfinderNormal * (or PathfinderAbstract), and modify the method that * calculates the BlockPathTypes (mappings commented in overriden method) * to account for GameDoors present in the zombie's game. *

* Given that we need to pass extra context to these static methods, * we must add the context as params and modify every single call * to the modified method by overriding each individual method and passing the * content defined in the constructor. * * @author Illusion */ public class CustomPathfinderNormal extends WalkNodeEvaluator { private ZombiesPlugin main; private Mob entity; public CustomPathfinderNormal() { } protected static BlockPathTypes getBlockPathTypeRaw(BlockGetter world, BlockPos pos, ZombiesPlugin main, Mob entity) { BlockState blockData = world.getBlockState(pos); Block block = blockData.getBlock(); Material material = blockData.getMaterial(); // BlockPathTypes MAPPINGS (might not be exact): /* a - blocked b - open c - walkable d - walkable_door e - trapdoor f - powder_snow g - danger_powder_snow h - fence i - lava j - water k - water_border l - rail m - unpassable_rail n - danger-fire o - damage-fire p - danger-cactus q - damage-cactus r - danger-other s - damage-other t - door_open u - door_wood_closed v - door_iron_closed w - breach x - leaves y - sticky_honey z - cocoa */ if (blockData.isAir()) { // isAir // --- SECTION START : ZOMBIES --- if (main == null) return BlockPathTypes.OPEN; // Method called before main is set in the constructor Game game = main.getGameManager().getGameFromMob(entity.getBukkitEntity()); if (game == null) return BlockPathTypes.OPEN; World bukkitWorld = game.getGameMapData().getMapTemplate().getSpawnPoint().getWorld(); Location location = new Location(bukkitWorld, pos.getX(), pos.getY(), pos.getZ()); GameDoor door = game.getGameMapData().getDoor(location); if (door == null) return BlockPathTypes.OPEN; if (!game.getGameMapData().getOpenDoors().contains(door)) return BlockPathTypes.BLOCKED; // --- SECTION END : ZOMBIES return BlockPathTypes.OPEN; } else if (!blockData.is(BlockTags.TRAPDOORS) && !blockData.is(Blocks.LILY_PAD) && !blockData.is(Blocks.BIG_DRIPLEAF)) { if (blockData.is(Blocks.POWDER_SNOW)) { return BlockPathTypes.POWDER_SNOW; } else if (blockData.is(Blocks.CACTUS)) { return BlockPathTypes.DAMAGE_CACTUS; } else if (blockData.is(Blocks.SWEET_BERRY_BUSH)) { return BlockPathTypes.DAMAGE_OTHER; } else if (blockData.is(Blocks.HONEY_BLOCK)) { return BlockPathTypes.STICKY_HONEY; } else if (blockData.is(Blocks.COCOA)) { return BlockPathTypes.COCOA; } else { FluidState fluidState = blockData.getFluidState(); // Paper - remove another get type call if (fluidState.is(FluidTags.LAVA)) { return BlockPathTypes.LAVA; } else if (isBurningBlock(blockData)) { return BlockPathTypes.DAMAGE_FIRE; } else if (DoorBlock.isWoodenDoor(blockData) && !blockData.getValue(DoorBlock.OPEN)) { return BlockPathTypes.DOOR_WOOD_CLOSED; } else if (block instanceof DoorBlock && material == Material.METAL && !blockData.getValue(DoorBlock.OPEN)) { return BlockPathTypes.DOOR_IRON_CLOSED; } else if (block instanceof DoorBlock && blockData.getValue(DoorBlock.OPEN)) { return BlockPathTypes.DOOR_OPEN; } else if (block instanceof BaseRailBlock) { return BlockPathTypes.RAIL; } else if (block instanceof LeavesBlock) { return BlockPathTypes.LEAVES; } else if (!blockData.is(BlockTags.FENCES) && !blockData.is(BlockTags.WALLS) && (!(block instanceof FenceGateBlock) || blockData.getValue(FenceGateBlock.OPEN))) { if (!blockData.isPathfindable(world, pos, PathComputationType.LAND)) { return BlockPathTypes.BLOCKED; } else { return fluidState.is(FluidTags.WATER) ? BlockPathTypes.WATER : BlockPathTypes.OPEN; } } else { return BlockPathTypes.FENCE; } } } else { return BlockPathTypes.TRAPDOOR; } } public static BlockPathTypes getBlockPathTypeStatic(BlockGetter world, BlockPos.MutableBlockPos pos, ZombiesPlugin main, Mob entity) { int i = pos.getX(); int j = pos.getY(); int k = pos.getZ(); BlockPathTypes blockPathTypes = getBlockPathTypeRaw(world, pos, main, entity); if (blockPathTypes == BlockPathTypes.OPEN && j >= world.getMinBuildHeight() + 1) { BlockPathTypes blockPathTypes2 = getBlockPathTypeRaw(world, pos.set(i, j - 1, k), main, entity); blockPathTypes = blockPathTypes2 != BlockPathTypes.WALKABLE && blockPathTypes2 != BlockPathTypes.OPEN && blockPathTypes2 != BlockPathTypes.WATER && blockPathTypes2 != BlockPathTypes.LAVA ? BlockPathTypes.WALKABLE : BlockPathTypes.OPEN; if (blockPathTypes2 == BlockPathTypes.DAMAGE_FIRE) { blockPathTypes = BlockPathTypes.DAMAGE_FIRE; } if (blockPathTypes2 == BlockPathTypes.DAMAGE_CACTUS) { blockPathTypes = BlockPathTypes.DAMAGE_CACTUS; } if (blockPathTypes2 == BlockPathTypes.DAMAGE_OTHER) { blockPathTypes = BlockPathTypes.DAMAGE_OTHER; } if (blockPathTypes2 == BlockPathTypes.STICKY_HONEY) { blockPathTypes = BlockPathTypes.STICKY_HONEY; } } if (blockPathTypes == BlockPathTypes.WALKABLE) { blockPathTypes = checkNeighbourBlocks(world, pos.set(i, j, k), blockPathTypes); } return blockPathTypes; } public void setValues(ZombiesPlugin main, Mob entity) { this.main = main; this.entity = entity; } @Override public BlockPathTypes getBlockPathType(BlockGetter world, int x, int y, int z) { return getBlockPathTypeStatic(world, new BlockPos.MutableBlockPos(x, y, z), main, entity); } }