Get highest y block not returning highest block.

Discussion in 'Spigot Plugin Development' started by G0ldManPox, Jun 12, 2016.

  1. I have been working on this problem for hours. When I call getHighestBlockYAt(x , z), it actually doesn't consider trees.
    For example, when I teleport a player to this location, they actually are teleported into a leaf block. Apparently, in 1.8.8, this causes them to be teleported into the ground and take suffocation damage. Is there a work around for this? I believe this happens because the chunk doesn't populate correctly or they actually fall through the leaf blocks while they are being teleported. Any advice would be helpful.
    I believe my method for checking the location is airtight.
    Code (Text):
    private boolean validate(Location loc){
            boolean valid = true;
            Block landBlock = loc.clone().add(0, -1, 0).getBlock();
            Block oneAboveLand = loc.clone().getBlock();
            Block twoAboveLand = loc.clone().add(0, 1, 0).getBlock();

                for(BlockFace face : faces){

                        break checkLoop;

                    else if(oneAboveLand.getRelative(face).getType()!=(Material.AIR)){
                        break checkLoop;

                    else if(twoAboveLand.getRelative(face).getType()!=(Material.AIR)){
                        valid = false;
                        break checkLoop;


            return valid;

    private final Set<Material> VALID_SPAWN_BLOCKS = ImmutableSet.of(
    private BlockFace[] faces = new BlockFace[] {
                BlockFace.SELF, BlockFace.EAST, BlockFace.NORTH, BlockFace.SOUTH,
                BlockFace.WEST, BlockFace.NORTH_EAST, BlockFace.SOUTH_EAST, BlockFace.SOUTH_WEST, BlockFace.NORTH_WEST};

  2. The highest block is loaded when the chunk loads, so it's not that accurate. You could create a custom method that goes from y 255 to 0 to check the highest block manually.
  3. You're teleporting to the highest block, so of course you're inside it. One above #getHighestBlock is what you teleport to.

    Code (Java):
    Block oneAboveLand = loc.clone().getBlock();
    If `loc` is from #getHighestBlock, you are mistaken in thinking that this is one above it.
  4. Tried that, I made a method that did that, and it still did not work correctly. I still ran into the same issue of the trees not populating. Also, I tried using nms and listening for a chunk load and then getting the highest block, but that also did not work.

    Incorrect, I checked. highestYBlock actually does return the air block above the land block. No need to add 1 to it. Besides I have tried that, but still did not fix the leaf issue. Thanks though.
  5. Not incorrect, it's literally right in the documentation:

    Note non-empty, aka it is not air.
    • Agree Agree x 1
  6. The documentation might say so, but in real testing, that is not the case.
    As evidence, I added this piece of code: Bukkit.broadcastMessage(oneAboveLand.getType().toString());

    It returned this:
    Code (Text):
    12.06 17:14:09 [Server] INFO AIR
    12.06 17:14:09 [Server] INFO AIR
    12.06 17:14:05 [Server] INFO AIR
    12.06 17:14:03 [Server] INFO AIR
    12.06 17:14:02 [Server] INFO AIR
    12.06 17:13:58 [Server] INFO AIR
    12.06 17:13:55 [Server] INFO LONG_GRASS
    12.06 17:13:55 [Server] INFO AIR
    12.06 17:13:52 [Server] INFO AIR
    12.06 17:13:49 [Server] INFO AIR
    12.06 17:13:49 [Server] INFO AIR
    12.06 17:13:45 [Server] INFO AIR
    12.06 17:13:42 [Server] INFO AIR
    • Agree Agree x 1
  7. Then show more code.
  8. Code (Java):
        if(sender instanceof Player){
            Location loc = ((Player)sender).getLocation();
            Block block = loc.getWorld().getHighestBlockAt(loc);
            sender.sendMessage(ChatColor.translateAlternateColorCodes('&', " The highest block at your location is &a"+block.getType()+"&8 (&7"+block.getX()+"&8,&7 "+block.getY()+"&8,&7 "+block.getZ()+"&8)"));
        return true;
  9. Seems to be a spigot bug then, should report it on their JIRA.
  10. I am on 1.8.8. Interesting how leaves are ignored in that regard.

    However I found a non-elegant (dangerous) solution if anyone is interested.
    The idea is, after teleporting the player, call this function to clear the blocks around them (so they don't suffocate in a block). In case they aren't online then add them to list. When they login, call the function again. Again, not a very pretty solution.
    Code (Text):
    private void safeCheck(OfflinePlayer p){

            new BukkitRunnable() {

                public void run() {

                        Player target = (Player) p;
                        Block atLand = target.getLocation().clone().add(0, -1, 0).getBlock();
                        Block oneAboveLand = target.getLocation().getBlock();
                        Block twoAboveLand = target.getLocation().clone().add(0, 1, 0).getBlock();
                        Block threeAboveLand = target.getLocation().clone().add(0, 2, 0).getBlock();

                        for(BlockFace face : faces){

            }.runTaskLater(plugin, 5L);
  11. getHighestBlockY gets a value from the chunk heightmap, which utterly ignores anything added by biome decorators, players or other modification.
  12. Code (Text):
    public Location getHighestBock(World world, int x, int z){
       int i = 255;
          if(new Location(world, x, i, z).getBlock().getType()!=Material.AIR)
             return new Location(world, x, i, z).add(0,1,0);
       return new Location(world, x, 1, z);