Search code examples
pythonminecraftfile-handling

How can read Minecraft .mca files so that in python I can extract individual blocks?


I can't find a way of reading the Minecraft world files in a way that i could use in python

I've looked around the internet but can find no tutorials and only a few libraries that claim that they can do this but never actually work

from nbt import *
nbtfile = nbt.NBTFile("r.0.0.mca",'rb')

I expected this to work but instead I got errors about the file not being compressed or something of the sort

Full error:

Traceback (most recent call last):
  File "C:\Users\rober\Desktop\MinePy\MinecraftWorldReader.py", line 2, in <module>
    nbtfile = nbt.NBTFile("r.0.0.mca",'rb')
  File "C:\Users\rober\AppData\Local\Programs\Python\Python36-32\lib\site-packages\nbt\nbt.py", line 628, in __init__
    self.parse_file()
  File "C:\Users\rober\AppData\Local\Programs\Python\Python36-32\lib\site-packages\nbt\nbt.py", line 652, in parse_file
    type = TAG_Byte(buffer=self.file)
  File "C:\Users\rober\AppData\Local\Programs\Python\Python36-32\lib\site-packages\nbt\nbt.py", line 99, in __init__
    self._parse_buffer(buffer)
  File "C:\Users\rober\AppData\Local\Programs\Python\Python36-32\lib\site-packages\nbt\nbt.py", line 105, in _parse_buffer
    self.value = self.fmt.unpack(buffer.read(self.fmt.size))[0]
  File "C:\Users\rober\AppData\Local\Programs\Python\Python36-32\lib\gzip.py", line 276, in read
    return self._buffer.read(size)
  File "C:\Users\rober\AppData\Local\Programs\Python\Python36-32\lib\_compression.py", line 68, in readinto
    data = self.read(len(byte_view))
  File "C:\Users\rober\AppData\Local\Programs\Python\Python36-32\lib\gzip.py", line 463, in read
    if not self._read_gzip_header():
  File "C:\Users\rober\AppData\Local\Programs\Python\Python36-32\lib\gzip.py", line 411, in _read_gzip_header
    raise OSError('Not a gzipped file (%r)' % magic)
OSError: Not a gzipped file (b'\x00\x00')

Solution

  • Use anvil parser. (Install with pip install anvil-parser)

    Reading

    import anvil
    
    region = anvil.Region.from_file('r.0.0.mca')
    
    # You can also provide the region file name instead of the object
    chunk = anvil.Chunk.from_region(region, 0, 0)
    
    # If `section` is not provided, will get it from the y coords
    # and assume it's global
    block = chunk.get_block(0, 0, 0)
    
    print(block) # <Block(minecraft:air)>
    print(block.id) # air
    print(block.properties) # {}
    

    https://pypi.org/project/anvil-parser/