Skip to content

Instantly share code, notes, and snippets.

@agrif
Created March 5, 2012 03:20
Show Gist options
  • Save agrif/1976292 to your computer and use it in GitHub Desktop.
Save agrif/1976292 to your computer and use it in GitHub Desktop.
## MCRegion to Anvil converter
##
## to use:
##
## Download http://libredstone.org/libredstone-0.0.0.tar.bz2, run
## ./configure.sh
## and
## make
## Make sure you have python and numpy installed. Then download
## this script into ./bindings/, cd into there, and run:
##
## python mcregion_to_anvil.py path/to/old/ output/
##
## If you'd like, both paths can be the same, in which case level.dat
## is backed up to level.dat_mcr. Also if you'd like, you can `make
## install` libredstone then run this script from anywhere.
##
## It's like Jens' converter, but it produces a usable level.dat for
## (e.g.) Minecraft Overviewer. Also it's not java, which can be nice
## sometimes. Still no biomes though.
import redstone as rs
import numpy
import os.path, os
import sys
import shutil
if len(sys.argv) != 3:
sys.stderr.write('Usage: {cmd} <src> <dest>\n'.format(cmd=sys.argv[0]))
sys.exit(1)
_, src, dest = sys.argv
src = os.path.expanduser(src)
dest = os.path.expanduser(dest)
if not os.path.exists(src):
sys.stderr.write('Usage: {cmd} <src> <dest>\n'.format(cmd=sys.argv[0]))
sys.exit(1)
# make the destination directory
if not os.path.exists(dest):
os.mkdir(dest)
#
# convert level.dat
#
if dest == src:
shutil.copyfile(os.path.join(src, 'level.dat'), os.path.join(src, 'level.dat_mcr'))
dat = rs.NBT.parse_from_file(os.path.join(src, 'level.dat'))
dat['Data']['version'].value = 19133
dat.write_to_file(os.path.join(dest, 'level.dat'))
#
# create and convert region files
#
def old_data_bytes(s):
dat = numpy.frombuffer(s, dtype=numpy.uint8)
return dat.reshape((16, 16, 128))
def old_data_nibbles(s):
dat = numpy.frombuffer(s, dtype=numpy.uint8)
dat = dat.reshape((16, 16, 64))
dat_expanded = numpy.empty((16, 16, 128), dtype=numpy.uint8)
dat_expanded[:,:,::2] = dat & 0x0F
dat_expanded[:,:,1::2] = (dat & 0xF0) >> 4
return dat_expanded
def new_data_bytes(a):
return numpy.swapaxes(a, 0, 2).tostring()
def new_data_nibbles(a):
a = numpy.swapaxes(a, 0, 2)
dat = numpy.empty((16, 16, 8), dtype=numpy.uint8)
dat[:,:,:] = (a[:,:,::2] & 0x0F) | ((a[:,:,1::2] & 0x0F) << 4)
return dat.tostring()
def convert_chunk(dat):
# convert height map
height = map(ord, dat['Level']['HeightMap'].value)
dat['Level']['HeightMap'] = rs.Tag.new0(rs.TAG_INT_ARRAY)
dat['Level']['HeightMap'].value = height
# get current data arrays
blocks = old_data_bytes(dat['Level']['Blocks'].value)
data = old_data_nibbles(dat['Level']['Data'].value)
skylight = old_data_nibbles(dat['Level']['SkyLight'].value)
blocklight = old_data_nibbles(dat['Level']['BlockLight'].value)
# delete current data arrays
del dat['Level']['Blocks']
del dat['Level']['Data']
del dat['Level']['SkyLight']
del dat['Level']['BlockLight']
# add the Sections tag
dat['Level']['Sections'] = rs.Tag.new0(rs.TAG_LIST)
dat['Level']['Sections'].list_set_type(rs.TAG_COMPOUND)
# iterate through all possible sections
for y in xrange(8):
sec_blocks = blocks[:,:,16*y:16*y + 16]
if not sec_blocks.any():
continue
sec_data = data[:,:,16*y:16*y + 16]
sec_skylight = skylight[:,:,16*y:16*y + 16]
sec_blocklight = blocklight[:,:,16*y:16*y + 16]
section = rs.Tag.new0(rs.TAG_COMPOUND)
section['Y'] = rs.Tag.new0(rs.TAG_BYTE)
section['Y'].value = y
section['Blocks'] = rs.Tag.new0(rs.TAG_BYTE_ARRAY)
section['Data'] = rs.Tag.new0(rs.TAG_BYTE_ARRAY)
section['SkyLight'] = rs.Tag.new0(rs.TAG_BYTE_ARRAY)
section['BlockLight'] = rs.Tag.new0(rs.TAG_BYTE_ARRAY)
section['Blocks'].value = new_data_bytes(sec_blocks)
section['Data'].value = new_data_nibbles(sec_data)
section['SkyLight'].value = new_data_nibbles(sec_skylight)
section['BlockLight'].value = new_data_nibbles(sec_blocklight)
dat['Level']['Sections'].list_insert(0, section)
dat['Level']['Sections'].list_reverse()
return dat
destregiondir = os.path.join(dest, 'region')
if not os.path.exists(destregiondir):
os.mkdir(destregiondir)
for mcr in os.listdir(os.path.join(src, 'region')):
try:
_, rx, rz, _ = mcr.split('.')
rx = int(rx)
rz = int(rz)
except:
continue
srcmcr = os.path.join(src, 'region', mcr)
destmca = os.path.join(dest, 'region', 'r.{x}.{z}.mca'.format(x=rx, z=rz))
if os.path.exists(destmca):
os.unlink(destmca)
reg = rs.Region.open(srcmcr)
destreg = rs.Region.open(destmca, True)
print "converting", mcr
for x in xrange(32):
for z in xrange(32):
if not reg.contains_chunk(x, z):
continue
dat = rs.NBT.parse_from_region(reg, x, z)
newdat = convert_chunk(dat)
newdat.write_to_region(destreg, x, z)
destreg.flush()
@jkantner
Copy link

Not working for me. I keep getting:

Traceback (most recent call last):
  File "mcregion_to_anvil.py", line 22, in <module>
    import redstone as rs
  File "/Users/jon/Downloads/libredstone-0.0.0/bindings/redstone.py", line 35, in <module>
    rs = ctypes.CDLL(find_library('redstone'))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 365, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: dlopen(libredstone.dylib, 6): image not found

I ran python mcregion_to_anvil.py /Users/jon/Downloads/libredstone-0.0.0/bindings/input/target_world /Users/jon/Downloads/libredstone-0.0.0/bindings/output in the bindings folder, and output is where I want the converted file to appear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment