ljfa-ag / libnbtplusplus

A C++ library for Minecraft's file format NBT
GNU Lesser General Public License v3.0
78 stars 25 forks source link

Little endian negative long encoding doesn't match Minecraft #12

Closed zydeco closed 1 year ago

zydeco commented 6 years ago

I've found that Minecraft Bedrock Edition encodes negative little endian longs different than expected: For example, creating a level with seed -123456789 will encode it in level.dat as EB 32 A4 F8 00 00 00 00, which is read by this library as 4171510507. The same can be seen with the worldStartCount value in level.dat, on a newly generated world it's encoded as FE FF FF FF 00 00 00 00, apparently meaning -2.

With positive values, such as any positive seed, or the timestamp in LastPlayed it seems to work correctly, presumably because they values themselves aren't bigger than 32-bit.

tl;dr:

name value in level.dat read by minecraft read by libnbtplusplus correct?
RandomSeed EB32A4F800000000 -123456789 4171510507 šŸ‘Ž
RandomSeed 15CD5B0700000000 123456789 123456789 šŸ‘
worldStartCount FEFFFFFF00000000 -2? 4294967294 šŸ‘Ž
LastPlayed CF94015B00000000 2018-05-20 1526830287 šŸ‘

This is based on level.dat files from different versions of Minecraft 1.2 to 1.4 for iOS and Windows 10. It seems Minecraft is treating the 64-bit long as 32-bit, and ignoring the rest, it seems related to this minecraft bug: https://bugs.mojang.com/browse/MCPE-7091?jql=text%20~%20%22TAG_Long%22, which was ultimately resolved by limiting the seed to 32 bits.

zydeco commented 6 years ago

More puzzlingly, this only happens in level.dat: the NBTs with players seem to encode it correctly; at least instances of -1 are encoded as FFFFFFFFFFFFFFFF.

ljfa-ag commented 6 years ago

Well that seems more like a problem on Minecraft Bedrock Edition's side. I'm not sure if I should accommodate to that.

I guess you can just cast to int32_t to get the right value.