Description
Hey!
Thanks for the awesome work on maintaining this iconic project! Im currently trying to move my rendering pipeline to use this version of mcmap.
In that process I discovered a very strange problem: Some chunk sections seem 'scrambled up'. All blocks inside are positioned quite random.
See for example see this render (1.16.4 world):
Note: The images in this issue have been scaled by GitHub, open the image in a new tab to see the full details.
This happens for all sorts of version and server software combinations. But I should note here, that the world savefile that was used here was written by a mineflayer bot. I'm also not sure if its an issue with their implementation of the anvil storage format or with mcmap itself.
I tried to write down how I approached this and where I think might be the cause of the issue.
My first impression was, that something wrote the chunks wrong to disk. So I started up a Minecraft client and loaded the world.
As you can see the red marked section was loaded correctly. This was the same chunk section that rendered wrong before. Its the scrambled up section on the right. Same savefile. Same chunks.
Now I was sure that the chunks wore at least in some kind of readable format on disk. I saved and quitted Minecraft and rendered the world again.
Before | After load & save |
---|---|
![]() |
![]() |
As you can see Minecraft somehow fixed these chunks and as result mcmap was able to render them like it should. You can still see some chunks that are 'scrambled up', these chunks were just not loaded by the client. Note: The Minecraft client generated some new terrain that I cropped away.
The Minecraft client must have altered the chunk section in some form. I opened both worlds using NBT Studio and compared the chunk section in question.
It seems pretty clear what happened here: The chunk section must have been stored in some inefficiency way, the Minecraft client compacted it from 342 down to 256 longs.
I looked at the post116
function. Maybe this function could not deal with this strange case?
mcmap/src/chunk_format_versions/section_format.cpp
Lines 6 to 30 in e4440a7
I added a debug statement to analyse the different blockstates lengths and index_lengths. This were the counts and the lengths that occurred while rendering the world.
1876 [Deep Debug] blockStates length: 256; index_length: 4;
35 [Deep Debug] blockStates length: 342; index_length: 4;
508 [Deep Debug] blockStates length: 342; index_length: 5;
When ignoring all chunk sections that have blockStates->size() == 342
you can see that more then the scrambled sections get removed. When also filtering on the index_length == 4
, we get only the scrambled sections removed.
blockStates->size() == 342 |
&& index_length == 4 |
(inverted) |
---|---|---|
![]() |
![]() |
![]() |
I did not test this behaviour with other blockStates
lengths. From my testing with very different worlds and versions, some sort of error happens in all versions from 1.13 to 1.16.5.
Expand for a test matrix with different versions
Note: This also contains worlds (1.8 - 1.12) that were rendered using a legacy version of mcmap. These dont show this error.
Reminder: These worlds were generated using the specified server software, then 'downloaded' by mineflayer and then rendered.
I tried 'fixing' the chunk reading in mcmap myself, even reimplemented the function heavily inspired from nms code:
for (uint16_t index = 0; index < 4096; index++) {
const uint16_t j = index * index_length;
const uint16_t k = j >> 6;
const uint16_t l = (index + 1) * index_length - 1 >> 6;
const uint16_t i1 = j ^ k << 6;
uint16_t blockIndex = 0;
if (k == l) {
blockIndex = (int) ((unsigned((*blockStates)[k])) >> i1 & mask);
} else {
int j1 = 64 - i1;
blockIndex = (int) (((unsigned((*blockStates)[k])) >> i1 | (*blockStates)[l] << j1) & mask);
}
buffer[index] = blockIndex;
}
Sadly this didnt bring any success and I'm not really sure how to go on from here: It seems that there is an issue how mineflayer writes the chunks to disk. But at the same time Minecraft somehow is able to handle this. I would assume that it would be best to fix this in mineflayer, but I'm not really sure I can pinpoint the bug over there.
Maybe you could give some hints or help getting this resolved? Any help is really appreciated. Thanks for reading this really long issue.