Height map improvements - #97
Open
RecursivePineapple wants to merge 20 commits into
Open
Conversation
Contributor
Co-authored-by: GitHub GTNH Actions <>
Contributor
Co-authored-by: GitHub GTNH Actions <>
This was referenced Aug 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This refactors the heightmap code significantly. Primarily, it removes the staging heightmap and merges the client and server heightmaps into a single data structure. This is to remove the complexity from managing each heightmap separately. There have been many problems caused by some heightmap not updating properly, leading to incorrect heightmap values.
This change fixes the odd worldgen feature heights, and it also fixes the sporadic
Random.nextIntcrashes when populating taiga-like biomes.The new heightmap works by maintaining a stripped down version of an interval tree for each block column. A block with a light opacity greater than 0 blocks the heightmap. When the heightmap code detects these blocks, it adds the Y location to the interval tree for that block column. The interval tree merges runs of blocks together, so a large span of blocks takes up very little memory. It also allows us to quickly query the location of a present block above or below another location.
I'm not sure the opacity check is correct, but it's what the old code did so I kept the logic the same.
Also, I improved the sync code. Several places had unnecessary heightmap syncs - specifically PacketCubeBlockChange and WorldEncoder. The former sent a heightmap update for each S23 block change, which is pointless because the player manager already does this whenever a block changes. Also, WorldEncoder serialized the heightmap data for the whole column each time it encoded a cube. This didn't cause problems because the data was always correct, but it was a lot of wasted bandwidth because heights are already synced when a column is sent to the player.
I got claude to write YIntervalTree initially, since I couldn't find an existing implementation that behaved how I wanted. I also got it to write tests and benchmarks for it, then got it to optimize the tree as much as possible. It still shows up on profiles quite significantly so we'll likely want to restore something similar to the staging heightmap (albeit much simpler), but for now this solution works fine.
Another caveat is that every cube load updates the heightmap, regardless of whether it was newly generated or not. The heightmap values are never removed either, so that skylight propagation is correct even when cubes far up in the world aren't loaded. This can likely be optimized further once we verify the logic of the new system.
There shouldn't be any problems migrating old worlds to this new format, because I renamed the NBT key it uses from
OpacityIndextoHeightMap3D. Since the new key doesn't exist in legacy cubes, nothing will be loaded. As an old world loads, the heightmap will repair itself due to the above logic.fixes: #75
Checklist