def _unpack_blocks( translation_manager: "TranslationManager", version_identifier: VersionIdentifierType, chunk: Chunk, block_palette: AnyNDArray, ): """ Unpack the version-specific block_palette into the stringified version where needed. :return: The block_palette converted to block objects. """ version = translation_manager.get_version(*version_identifier) for index, block in enumerate(block_palette): block: Block if version.block.is_waterloggable(block.namespaced_name): properties = block.properties if "waterlogged" in properties: waterlogged = properties["waterlogged"] del properties["waterlogged"] block = Block( namespace=block.namespace, base_name=block.base_name, properties=properties, ) else: waterlogged = amulet_nbt.TAG_String("false") if waterlogged == amulet_nbt.TAG_String("true"): block_palette[index] = block + water else: block_palette[index] = block elif version.block.is_waterloggable(block.namespaced_name, True): block_palette[index] = block + water chunk._block_palette = BlockManager(block_palette)
def _convert_to_save( self, chunk: Chunk, chunk_version: VersionNumberAny, translator: "Translator", recurse: bool = True, ) -> Chunk: """Convert the Chunk in Universal format to a Chunk in the version specific format.""" # create a new streamlined block block_palette and remap the data palette: List[numpy.ndarray] = [] palette_len = 0 for cy in chunk.blocks.sub_chunks: sub_chunk_palette, sub_chunk = numpy.unique( chunk.blocks.get_sub_chunk(cy), return_inverse=True) chunk.blocks.add_sub_chunk( cy, sub_chunk.astype(numpy.uint32).reshape( (16, 16, 16)) + palette_len) palette_len += len(sub_chunk_palette) palette.append(sub_chunk_palette) if palette: chunk_palette, lut = numpy.unique(numpy.concatenate(palette), return_inverse=True) for cy in chunk.blocks.sub_chunks: chunk.blocks.add_sub_chunk( cy, lut.astype(numpy.uint32)[chunk.blocks.get_sub_chunk(cy)]) chunk._block_palette = BlockManager( numpy.vectorize( chunk.block_palette.__getitem__)(chunk_palette)) else: chunk._block_palette = BlockManager() def get_chunk_callback(_: int, __: int) -> Chunk: # conversion from universal should not require any data outside the block return chunk # translate from universal format to version format return translator.from_universal(chunk_version, self.translation_manager, chunk, get_chunk_callback, recurse)
def _unpack_blocks( translation_manager: "TranslationManager", version_identifier: VersionIdentifierType, chunk: Chunk, block_palette: AnyNDArray, ): """ Unpack the version-specific block_palette into the stringified version where needed. :return: The block_palette converted to block objects. """ chunk._block_palette = BlockManager(block_palette)
def _unpack_blocks( translation_manager: "TranslationManager", version_identifier: VersionIdentifierType, chunk: Chunk, block_palette: AnyNDArray, ): """ Unpacks an object array of block data into a numpy object array containing Block objects. :param translation_manager: :param version_identifier: :param chunk: :param block_palette: :type block_palette: numpy.ndarray[ Tuple[ Union[ Tuple[None, Tuple[int, int]], Tuple[None, Block], Tuple[int, Block] ], ... ] ] :return: """ palette_ = BlockManager() for palette_index, entry in enumerate(block_palette): entry: BedrockInterfaceBlockType block = None for version_number, b in entry: version_number: Optional[int] if isinstance(b, tuple): version = translation_manager.get_version( version_identifier[0], version_number or 17563649) b = version.block.ints_to_block(*b) elif isinstance(b, Block): if version_number is not None: properties = b.properties properties["__version__"] = amulet_nbt.TAG_Int( version_number) b = Block(b.namespace, b.base_name, properties, b.extra_blocks) else: raise Exception(f"Unsupported type {b}") if block is None: block = b else: block += b if block is None: raise Exception(f"Empty tuple") palette_.get_add_block(block) chunk._block_palette = palette_
def _unpack_blocks( translation_manager: "TranslationManager", version_identifier: VersionIdentifierType, chunk: Chunk, block_palette: AnyNDArray, ): """ Unpacks an int array of block ids and block data values [[1, 0], [2, 0]] into a numpy array of Block objects. :param version: :param block_palette: :return: """ version = translation_manager.get_version(*version_identifier) chunk._block_palette = BlockManager( [version.block.ints_to_block(*entry) for entry in block_palette])
def _translate( chunk: Chunk, get_chunk_callback: Optional[GetChunkCallback], translate_block: TranslateBlockCallback, translate_entity: TranslateEntityCallback, full_translate: bool, ): if full_translate: todo = [] output_block_entities = [] output_entities = [] finished = BlockManager() palette_mappings = {} # translate each block without using the callback for i, input_block in enumerate(chunk.block_palette): input_block: BlockType ( output_block, output_block_entity, output_entity, extra, ) = translate_block(input_block, None, (0, 0, 0)) if extra and get_chunk_callback: todo.append(i) elif output_block is not None: palette_mappings[i] = finished.get_add_block(output_block) if output_block_entity is not None: for cy in chunk.blocks.sub_chunks: for x, y, z in zip( *numpy.where(chunk.blocks.get_sub_chunk(cy) == i) ): output_block_entities.append( output_block_entity.new_at_location( x + chunk.cx * 16, y + cy * 16, z + chunk.cz * 16, ) ) else: # TODO: this should only happen if the object is an entity, set the block to air pass if output_entity and entity_support: for cy in chunk.blocks.sub_chunks: for x, y, z in zip( *numpy.where(chunk.blocks.get_sub_chunk(cy) == i) ): x += chunk.cx * 16 y += cy * 16 z += chunk.cz * 16 for entity in output_entity: e = copy.deepcopy(entity) e.location += (x, y, z) output_entities.append(e) # re-translate the blocks that require extra information block_mappings = {} for index in todo: for cy in chunk.blocks.sub_chunks: for x, y, z in zip( *numpy.where(chunk.blocks.get_sub_chunk(cy) == index) ): y += cy * 16 def get_block_at( pos: Tuple[int, int, int] ) -> Tuple[Block, Optional[BlockEntity]]: """Get a block at a location relative to the current block""" nonlocal x, y, z, chunk, cy # calculate position relative to chunk base dx, dy, dz = pos dx += x dy += y dz += z abs_x = dx + chunk.cx * 16 abs_y = dy abs_z = dz + chunk.cz * 16 # calculate relative chunk position cx = dx // 16 cz = dz // 16 if cx == 0 and cz == 0: # if it is the current chunk block = chunk.block_palette[chunk.blocks[dx, dy, dz]] return ( block, chunk.block_entities.get((abs_x, abs_y, abs_z)), ) # if it is in a different chunk local_chunk = get_chunk_callback(cx, cz) block = local_chunk.block_palette[ local_chunk.blocks[dx % 16, dy, dz % 16] ] return ( block, local_chunk.block_entities.get((abs_x, abs_y, abs_z)), ) input_block = chunk.block_palette[chunk.blocks[x, y, z]] ( output_block, output_block_entity, output_entity, _, ) = translate_block( input_block, get_block_at, (x + chunk.cx * 16, y, z + chunk.cz * 16), ) if output_block is not None: block_mappings[(x, y, z)] = finished.get_add_block( output_block ) if output_block_entity is not None: output_block_entities.append( output_block_entity.new_at_location( x + chunk.cx * 16, y, z + chunk.cz * 16 ) ) else: # TODO: set the block to air pass if output_entity and entity_support: for entity in output_entity: e = copy.deepcopy(entity) e.location += (x, y, z) output_entities.append(e) if entity_support: for entity in chunk.entities: output_block, output_block_entity, output_entity = translate_entity( entity ) if output_block is not None: block_location = ( int(math.floor(entity.x)), int(math.floor(entity.y)), int(math.floor(entity.z)), ) block_mappings[block_location] = output_block if output_block_entity: output_block_entities.append( output_block_entity.new_at_location(*block_location) ) if output_entity: for e in output_entity: e.location = entity.location output_entities.append(e) for cy in chunk.blocks.sub_chunks: old_blocks = chunk.blocks.get_sub_chunk(cy) new_blocks = numpy.zeros(old_blocks.shape, dtype=old_blocks.dtype) for old, new in palette_mappings.items(): new_blocks[old_blocks == old] = new chunk.blocks.add_sub_chunk(cy, new_blocks) for (x, y, z), new in block_mappings.items(): chunk.blocks[x, y, z] = new chunk.block_entities = output_block_entities chunk.entities = output_entities chunk._block_palette = finished