0

Reenable support for old 1.12-era chunks

This commit is contained in:
gmcnew
2018-08-11 00:40:14 +00:00
parent 28dd0589b3
commit 9293fc8751

View File

@@ -119,17 +119,6 @@ class World(object):
"World at %s is not compatible with Overviewer")
% self.worlddir)
# Check for versions of minecraft after the 17w47a changes
if 'Version' in data:
version = int(data['Version']["Id"])
if version < 1519:
raise UnsupportedVersion(
"Sorry, This version of Minecraft-Overviewer only works "
"with versions of Minecraft 1.13 and newer\n"
"This is due to a change in the map chunk format and changes "
"to texture names")
# This isn't much data, around 15 keys and values for vanilla worlds.
self.leveldat = data
@@ -675,6 +664,75 @@ class RegionSet(object):
result = numpy.asarray(result, numpy.uint16)
return result
def _get_blockdata_v113(self, section, unrecognized_block_types):
# Translate each entry in the palette to a 1.2-era (block, data) int pair.
num_palette_entries = len(section['Palette'])
palette_translated = [] # (block, data) pairs, num_palette_entries in length
palette_block_counts = [] # ints, num_palette_entries in length
unrecognized_palette_entries = []
for i in range(num_palette_entries):
key = section['Palette'][i]
palette_block_counts.append(0)
try:
palette_translated.append(self._get_block(key))
except KeyError as e:
# Unknown block type? Track it, treat it as air, and move on.
unrecognized_palette_entries.append(i)
palette_translated.append(self._blockmap['minecraft:air'])
# Turn the BlockStates array into a 16x16x16 numpy matrix of shorts.
blocks = numpy.zeros((4096,), dtype=numpy.uint16)
data = numpy.zeros((4096,), dtype=numpy.uint8)
block_states = self._packed_longarray_to_shorts(section['BlockStates'], 4096)
for i in range(4096):
palette_index = block_states[i]
(blocks[i], data[i]) = palette_translated[palette_index]
palette_block_counts[palette_index] += 1
# Turn the Data array into a 16x16x16 matrix, same as SkyLight
blocks = blocks.reshape((16, 16, 16))
data = data.reshape((16, 16, 16))
for i in unrecognized_palette_entries:
if palette_block_counts[i] > 0:
palette_entry = section['Palette'][i]
k = palette_entry['Name']
if 'Properties' in palette_entry:
k += " %s" % str(palette_entry['Properties'])
unrecognized_block_types[k] = unrecognized_block_types.get(k, 0) + palette_block_counts[i]
return (blocks, data)
def _get_blockdata_v112(self, section):
# Turn the Data array into a 16x16x16 matrix, same as SkyLight
data = numpy.frombuffer(section['Data'], dtype=numpy.uint8)
data = data.reshape((16,16,8))
data_expanded = numpy.empty((16,16,16), dtype=numpy.uint8)
data_expanded[:,:,::2] = data & 0x0F
data_expanded[:,:,1::2] = (data & 0xF0) >> 4
# Turn the Blocks array into a 16x16x16 numpy matrix of shorts,
# adding in the additional block array if included.
blocks = numpy.frombuffer(section['Blocks'], dtype=numpy.uint8)
# Cast up to uint16, blocks can have up to 12 bits of data
blocks = blocks.astype(numpy.uint16)
blocks = blocks.reshape((16,16,16))
if "Add" in section:
# This section has additional bits to tack on to the blocks
# array. Add is a packed array with 4 bits per slot, so
# it needs expanding
additional = numpy.frombuffer(section['Add'], dtype=numpy.uint8)
additional = additional.astype(numpy.uint16).reshape((16,16,8))
additional_expanded = numpy.empty((16,16,16), dtype=numpy.uint16)
additional_expanded[:,:,::2] = (additional & 0x0F) << 8
additional_expanded[:,:,1::2] = (additional & 0xF0) << 4
blocks += additional_expanded
del additional
del additional_expanded
del section['Add'] # Save some memory
return (blocks, data_expanded)
#@log_other_exceptions
def get_chunk(self, x, z):
"""Returns a dictionary object representing the "Level" NBT Compound
@@ -759,47 +817,21 @@ class RegionSet(object):
# Empty is self-explanatory, and liquid_carved and carved seem to correspond
# to SkyLight not being calculated, which results in mostly-black chunks,
# so we'll just pretend they aren't there.
if chunk_data['Status'] in ("empty", "carved", "liquid_carved", "decorated"):
if chunk_data.get("Status", "") in ("empty", "carved", "liquid_carved", "decorated"):
raise ChunkDoesntExist("Chunk %s,%s doesn't exist" % (x,z))
# Turn the Biomes array into a 16x16 numpy array
biomes = numpy.asarray(chunk_data['Biomes'])
try:
biomes = numpy.frombuffer(chunk_data['Biomes'], dtype=numpy.uint8)
biomes = biomes.reshape((16,16))
except KeyError:
# worlds converted by Jeb's program may be missing the Biomes key
biomes = numpy.zeros((16, 16), dtype=numpy.uint8)
chunk_data['Biomes'] = biomes
unrecognized_block_types = {}
for section in chunk_data['Sections']:
# Translate each entry in the palette to a 1.2-era (block, data) int pair.
num_palette_entries = len(section['Palette'])
palette_translated = [] # (block, data) pairs, num_palette_entries in length
palette_block_counts = [] # ints, num_palette_entries in length
unrecognized_palette_entries = []
for i in range(num_palette_entries):
key = section['Palette'][i]
palette_block_counts.append(0)
try:
palette_translated.append(self._get_block(key))
except KeyError as e:
# Unknown block type? Track it, treat it as air, and move on.
unrecognized_palette_entries.append(i)
palette_translated.append(self._blockmap['minecraft:air'])
# Turn the BlockStates array into a 16x16x16 numpy matrix of shorts.
blocks = numpy.zeros((4096,), dtype=numpy.uint16)
data = numpy.zeros((4096,), dtype=numpy.uint8)
block_states = self._packed_longarray_to_shorts(section['BlockStates'], 4096)
for i in range(4096):
palette_index = block_states[i]
(blocks[i], data[i]) = palette_translated[palette_index]
palette_block_counts[palette_index] += 1
# Turn the Data array into a 16x16x16 matrix, same as SkyLight
section['Blocks'] = blocks.reshape((16, 16, 16))
section['Data'] = data.reshape((16, 16, 16))
del blocks
del data
# Turn the skylight array into a 16x16x16 matrix. The array comes
# packed 2 elements per byte, so we need to expand it.
try:
@@ -819,6 +851,13 @@ class RegionSet(object):
blocklight_expanded[:,:,1::2] = (blocklight & 0xF0) >> 4
del blocklight
section['BlockLight'] = blocklight_expanded
if 'Palette' in section:
(blocks, data) = self._get_blockdata_v113(section, unrecognized_block_types)
else:
(blocks, data) = self._get_blockdata_v112(section)
(section['Blocks'], section['Data']) = (blocks, data)
except ValueError:
# iv'e seen at least 1 case where numpy raises a value error during the reshapes. i'm not
# sure what's going on here, but let's treat this as a corrupt chunk error
@@ -827,16 +866,8 @@ class RegionSet(object):
logging.debug("Full traceback:", exc_info=1)
raise nbt.CorruptChunkError()
for i in unrecognized_palette_entries:
if palette_block_counts[i] > 0:
palette_entry = section['Palette'][i]
k = palette_entry['Name']
if 'Properties' in palette_entry:
k += " %s" % str(palette_entry['Properties'])
unrecognized_block_types[k] = unrecognized_block_types.get(k, 0) + palette_block_counts[i]
for k in unrecognized_block_types:
logging.warning("Found %d blocks of unknown type %s" % (unrecognized_block_types[k], k))
logging.debug("Found %d blocks of unknown type %s" % (unrecognized_block_types[k], k))
return chunk_data