示例#1
0
    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)
示例#2
0
    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)
示例#3
0
 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)
示例#4
0
    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])
示例#6
0
    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