Spongeapi: Get Highest Block at Specific Location

Created on 1 Oct 2016  路  20Comments  路  Source: SpongePowered/SpongeAPI

In Bukkit there was a World.getHighestBlockAt(Location) and World.getHighestBlockYAt(Location) method, which returned the highest non air block at the given location and the Y position of that block respectively.

Unless there is some other really easy way to do this, I think these methods should be added to API

world

Most helpful comment

There are actually 2 height values that may be useful, one of them is the one that ignores transparent blocks (including glass) and the other that is called precipitation heightmap which ignores non-solid blocks like tall grass or torches but doesn't ignore glass.

Both of them make sense in different situation. It seems like precipitation heightmap is actually more useful - it's the top block that entities won't fall through.

Minecraft implements both of them by simply getting value from internal heighmap so it would always be more efficient than iterating.

All 20 comments

PS for any devs looking at this, Internally it is net.minecraft.world.getHeight(BlockPos)

@kmecpp

Out of curiosity, what were these generally used for?

I used them for optimizing things that needed to check for specific actions in blocks that may be intensive other wise.

I used it in CraftBook for Bukkit in the Snow feature, to determine where the snow should form. It's basically a convenience method.

I would use them to check whether skylight is accessible for our old servers teleport system, it would "beam up" players as a balance check against people teleporting out of mineshafts.

It's also useful for working out where to teleport people to when given 2d co-ordinates.

I'm not at a computer to check right now, but what does this do internally? Does it just iterate over the column?

It does make sense to mirror this if it does anything different like caching.

There is no caching it simply iterates.

There is no caching it simply iterates.

Then there is no need to expose this.

Well there a too many too easy to implement features connected to this.

  • Highest block below height X,
  • Also ignore leaves or grass
  • ignore floating blocks
  • ...

So it should be the plugins job to do this. If the plugin needs help it can use the block ray for help. Maybe we can add a helper method for column iterating there if necessary.

World.getHeight(BlockPos) does not iterate, it returns the current value from an internal height map of the chunk.

In that case, it makes sense to expose this.

_Edit: I was thinking on the old getHeight method before the names were all changed in the .19.4 mcp update._

The current getHeight method is the highest block with a 'LightOpacity' which is not zero so it will skip things like glass or carpets.

Honestly most of the time getting the highest skylight block is what people want, they are just not thinking about it.

If the two methods were in and documented, it would make people think twice about choosing which one.

Additionally if you make people iterate themselves, you have the problem of cubic chunks, whilst Minecraft might not make any optimizations for highest block, cubic chunks would be able to skip any chunks not generated.
@Barteks2x

iterating thru a column is poorly inefficient compared to a binary greater-than-less-than search anyways - maximum of 8 guesses vs iterating up an average of 80 from base, or down an average of 170 from the top, etc :) But at least this value is in the minecraft data as-is.

@theboomer except that you can't binary search for the height because you have no idea if the actual height is greater than or less than your current search position.

not as directly, but you can if looking for a location with some extreme value that then is different later. If its got the value needed, its that height or lower; if its the compliment, its higher than that value. You'd have to track the "sofar minimum and maximum" possibly, to know if you checked in the wrong direction and backstep the other way to envelope the point. So maybe max of 9 or 10 chops instead of 8 due to some extra some back-and-forth. I did it a long time ago with one of the lighting properties myself as a challange, but lost that code
But again in this case, its info readily pulled from the internal chunk archetecture nbt, and not a concern.

Just for completeness sake: A quasi-binary quasi-recursive search for boundary blocks like this. Find a way to describe a boundary in terms of a binary-test condition that transitions as it would iterating from one end or the other, and it can be found this way, 100% of the time in exactly 8 tests for 256 spaces.

http://image.prntscr.com/image/2ef726ba28c9450a8e0701df22e1c02c.png

There are actually 2 height values that may be useful, one of them is the one that ignores transparent blocks (including glass) and the other that is called precipitation heightmap which ignores non-solid blocks like tall grass or torches but doesn't ignore glass.

Both of them make sense in different situation. It seems like precipitation heightmap is actually more useful - it's the top block that entities won't fall through.

Minecraft implements both of them by simply getting value from internal heighmap so it would always be more efficient than iterating.

So getHightestLitBlock and getHighestBlock?

I'd say getHighestOpaqueBlock and getHighestSolidBlock, respectively.

@theboomer The problem is communication, I'm pretty sure most people are aware of what a binary search is.

Deamon's assumption was that people were looking for the true highest block, not the highest non-transparent block.

Was this page helpful?
0 / 5 - 0 ratings