Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bedrock edition level.dat #4

Open
richbirch opened this issue Dec 6, 2020 · 10 comments
Open

Bedrock edition level.dat #4

richbirch opened this issue Dec 6, 2020 · 10 comments

Comments

@richbirch
Copy link

richbirch commented Dec 6, 2020

Hi

Do you plan to support bedrock edition level.dat files? Currently when I try to open them I get:

Error: Unable to parse level.dat_old, are you sure it's an NBT file?
	caused by: Unknown compression format where first byte is 8
For help, run with --help or read the manpage.

It'd be awesome to be able to change settings via a command line tool

Thanks
Rich

@C4K3
Copy link
Owner

C4K3 commented Dec 7, 2020

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.

@richbirch
Copy link
Author

Thanks for the quick response. Here's a zipped copy

level.zip

@MalbaCato
Copy link

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.

@stsquad
Copy link

stsquad commented Oct 5, 2021

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?

@stsquad
Copy link

stsquad commented Oct 5, 2021

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'.

@stsquad
Copy link

stsquad commented Oct 5, 2021

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.

@richbirch
Copy link
Author

Fantastic work! Thanks @stsquad

@stsquad
Copy link

stsquad commented Oct 7, 2021

@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.

@richbirch
Copy link
Author

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.

Offroaders123 added a commit to Offroaders123/NBTify that referenced this issue Jun 28, 2022
Changes:
- A few more changes to what I've been working on for the last few days. This commit makes the tag reading methods for the Reader more consistent, and de-abstracts the logic for reading the bytes from the data buffer. It was challenging for me to find where the function calls were when I first looked into the original NBT.js library, so while a bit repetitive, I took those function calls out of the extra `read()` method and moved their logic directly into their own tag methods, to better show what they were doing to get the byte data using the `DataView`.
- I also renamed some of the Reader attributes, just to make them a little more readable too. I have nothing against camelcase haha, but it's sometimes easier to just have to remember one word for a variable in some spots.
- Simplified the header checking functions! Took out a few extra steps that get you to the same place.

Got some inspiration and help from a few different places for these last few commits:
https://github.com/janispritzkau/nbt-ts
https://gist.github.com/jonathanlurie/04fa6343e64f750d03072ac92584b5df (Will be using this soon, thought I'd add it now just in case I lose track of it)
C4K3/nbted#4
https://stackoverflow.com/questions/30229522/how-can-i-join-an-array-of-numbers-into-1-concatenated-number
https://stackoverflow.com/questions/54019143/issue-with-combining-large-array-of-numbers-into-one-single-number
Offroaders123 added a commit to Offroaders123/NBTify that referenced this issue Jun 28, 2022
Changes:
- A few more changes to what I've been working on for the last few days. This commit makes the tag reading methods for the Reader more consistent, and de-abstracts the logic for reading the bytes from the data buffer. It was challenging for me to find where the function calls were when I first looked into the original NBT.js library, so while a bit repetitive, I took those function calls out of the extra `read()` method and moved their logic directly into their own tag methods, to better show what they were doing to get the byte data using the `DataView`.
- I also renamed some of the Reader attributes, just to make them a little more readable too. I have nothing against camelcase haha, but it's sometimes easier to just have to remember one word for a variable in some spots.
- Simplified the header checking functions! Took out a few extra steps that get you to the same place.

Got some inspiration and help from a few different places for these last few commits:
https://github.com/janispritzkau/nbt-ts
https://gist.github.com/jonathanlurie/04fa6343e64f750d03072ac92584b5df (Will be using this soon, thought I'd add it now just in case I lose track of it)
C4K3/nbted#4
https://stackoverflow.com/questions/30229522/how-can-i-join-an-array-of-numbers-into-1-concatenated-number
https://stackoverflow.com/questions/54019143/issue-with-combining-large-array-of-numbers-into-one-single-number
Offroaders123 added a commit to Offroaders123/NBTify that referenced this issue Sep 23, 2022
Changes:
- A few more changes to what I've been working on for the last few days. This commit makes the tag reading methods for the Reader more consistent, and de-abstracts the logic for reading the bytes from the data buffer. It was challenging for me to find where the function calls were when I first looked into the original NBT.js library, so while a bit repetitive, I took those function calls out of the extra `read()` method and moved their logic directly into their own tag methods, to better show what they were doing to get the byte data using the `DataView`.
- I also renamed some of the Reader attributes, just to make them a little more readable too. I have nothing against camelcase haha, but it's sometimes easier to just have to remember one word for a variable in some spots.
- Simplified the header checking functions! Took out a few extra steps that get you to the same place.

Got some inspiration and help from a few different places for these last few commits:
https://github.com/janispritzkau/nbt-ts
https://gist.github.com/jonathanlurie/04fa6343e64f750d03072ac92584b5df (Will be using this soon, thought I'd add it now just in case I lose track of it)
C4K3/nbted#4
https://stackoverflow.com/questions/30229522/how-can-i-join-an-array-of-numbers-into-1-concatenated-number
https://stackoverflow.com/questions/54019143/issue-with-combining-large-array-of-numbers-into-one-single-number
@Tazrian-K
Copy link

Tazrian-K commented Oct 27, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants