Open richbirch opened 3 years ago
https://minecraft.gamepedia.com/Bedrock_Edition_level_format sounds like bedrock uses zlib-compressed nbt (which should be supported.)
I don't have bedrock edition and have never tested with it, are you able to post a failing level.dat and then myself or somebody else may be able to debug it.
Documented here https://wiki.vg/NBT#Bedrock_edition are (hopefully all) changes to the nbt format with the Bedrock edition. To make your life annoying values are Little-endian, and sometimes use VarInts.
I'm finding it hard to find a canonical description of the level.dat data format - but the the leveldb_mcpe repository also seems to support the snappy compression format. Could this be what the header is indicating?
Actually I think the file may be uncompressed:
00000000 08 00 00 00 b9 08 00 00 0a 00 00 08 0d 00 42 69 |..............Bi|
00000010 6f 6d 65 4f 76 65 72 72 69 64 65 00 00 01 12 00 |omeOverride.....|
00000020 43 65 6e 74 65 72 4d 61 70 73 54 6f 4f 72 69 67 |CenterMapsToOrig|
00000030 69 6e 00 01 1e 00 43 6f 6e 66 69 72 6d 65 64 50 |in....ConfirmedP|
00000040 6c 61 74 66 6f 72 6d 4c 6f 63 6b 65 64 43 6f 6e |latformLockedCon|
00000050 74 65 6e 74 00 03 0a 00 44 69 66 66 69 63 75 6c |tent....Difficul|
00000060 74 79 01 00 00 00 08 0f 00 46 6c 61 74 57 6f 72 |ty.......FlatWor|
Which seems to conform to 4 bytes (LE) of a version (8) followed by 4 bytes LE which correspond to the size of the file - 8. Assuming the tags are 2 byte LE you then get a TAG_Compound, TAG_String, 13 byte length and the first string starting with 'B'.
Confirmed. With a quick and dirty hack to https://github.com/chmod222/cNBT to skip 8 bytes and byte swap everything (including the strings) I was able to parse a valid set of NBT tags:
TAG_Compound("")
{
TAG_String("edirrevOemoiB"):
TAG_Byte("nigirOoTspaMretneC"): 0
TAG_Byte("tnetnoCdekcoLmroftalPdemrifnoC"): 0
TAG_Int("ytluciffiD"): 1
TAG_String("sreyaLdlroWtalF"):
llun
TAG_Byte("epyTemaGecroF"): 0
TAG_Int("epyTemaG"): 0
TAG_Int("rotareneG"): 1
TAG_String("noisreVyrotnevnI"): 1.61.1
TAG_Byte("tsacdaorBNAL"): 1
TAG_Byte("tnetnItsacdaorBNAL"): 1
TAG_Long("deyalPtsaL"): 1632749302
TAG_String("emaNleveL"): level kcordeB
TAG_Int("XnigirOdlroWdetimiL"): 292
TAG_Int("YnigirOdlroWdetimiL"): 32767
TAG_Int("ZnigirOdlroWdetimiL"): 16
TAG_List("noisreVtneilCelbitapmoCmuminiM") [TAG_INT]
So it looks like all (?) that needs doing is a) recognise a Bedrock header and b) read LE bytes for most of the tag data.
Fantastic work! Thanks @stsquad
@richbirch well the hack was the easy bit. The reason I hacked it in the C library was it was the quickest way for me to test the theory. The real fix requires doing a bit of re-factoring to nbted so the low level tag accessors can take the endianess required. However my rust is very much beginner level at the moment so it will have to wait until I get a decent free weekend to work on it.
Thanks for looking at this @stsquad. I've actually dived in and coded a parser for this file myself in my preferred language, Scala. It only took a couple of hours thanks to the hints you gave above. My next step is to convert parsed data back to the level.dat format so I can update values as required.
The exciting thing is that this opens up the possibility of doing things like creating a flat world on a server without having to first create it locally and then upload the world to the server.
For those just wanting to edit NBT files for MC Bedrock, I found a working NBT editor as of 27/10/24 for MCB 1.21 https://github.com/Offroaders123/Dovetail
Hi
Do you plan to support bedrock edition level.dat files? Currently when I try to open them I get:
It'd be awesome to be able to change settings via a command line tool
Thanks Rich