def _sub_chunks(
        self, blocks: Blocks
    ) -> List[Tuple[numpy.ndarray, Tuple[int, int, int]]]:
        """Create sub-chunk arrays that extend into the neighbour sub-chunks by one block.

        :param blocks: The Blocks array for the chunk.
        :return: A list of tuples containing the larger block array and the location of the sub-chunk
        """
        sub_chunks = []
        neighbour_chunks = {}
        for dx, dz in ((-1, 0), (1, 0), (0, -1), (0, 1)):
            try:
                neighbour_chunks[(dx, dz)] = self._level.get_chunk(
                    self.cx + dx, self.cz + dz, self.dimension
                ).blocks
            except ChunkLoadError:
                continue

        for cy in blocks.sub_chunks:
            sub_chunk = blocks.get_sub_chunk(cy)
            larger_blocks = numpy.zeros(
                sub_chunk.shape + numpy.array((2, 2, 2)), sub_chunk.dtype
            )
            sub_chunk_box = SelectionBox.create_sub_chunk_box(self.cx, cy, self.cz)
            if self._level.selection_bounds.intersects(sub_chunk_box):
                boxes = self._level.selection_bounds.intersection(sub_chunk_box)
                for box in boxes.selection_boxes:
                    larger_blocks[1:-1, 1:-1, 1:-1][
                        box.sub_chunk_slice(self.cx, cy, self.cz)
                    ] = sub_chunk[box.sub_chunk_slice(self.cx, cy, self.cz)]
                for chunk_offset, neighbour_blocks in neighbour_chunks.items():
                    if cy not in neighbour_blocks:
                        continue
                    if chunk_offset == (-1, 0):
                        larger_blocks[0, 1:-1, 1:-1] = neighbour_blocks.get_sub_chunk(
                            cy
                        )[-1, :, :]
                    elif chunk_offset == (1, 0):
                        larger_blocks[-1, 1:-1, 1:-1] = neighbour_blocks.get_sub_chunk(
                            cy
                        )[0, :, :]
                    elif chunk_offset == (0, -1):
                        larger_blocks[1:-1, 1:-1, 0] = neighbour_blocks.get_sub_chunk(
                            cy
                        )[:, :, -1]
                    elif chunk_offset == (0, 1):
                        larger_blocks[1:-1, 1:-1, -1] = neighbour_blocks.get_sub_chunk(
                            cy
                        )[:, :, 0]
                if cy - 1 in blocks:
                    larger_blocks[1:-1, 0, 1:-1] = blocks.get_sub_chunk(cy - 1)[
                        :, -1, :
                    ]
                if cy + 1 in blocks:
                    larger_blocks[1:-1, -1, 1:-1] = blocks.get_sub_chunk(cy + 1)[
                        :, 0, :
                    ]
                sub_chunks.append((larger_blocks, (0, cy * 16, 0)))
        return sub_chunks
예제 #2
0
    def _sub_chunks(
        self, blocks: Blocks
    ) -> List[Tuple[numpy.ndarray, numpy.ndarray, Tuple[int, int, int]]]:
        sub_chunks = []
        neighbour_chunks = {}
        for dx, dz in ((-1, 0), (1, 0), (0, -1), (0, 1)):
            try:
                neighbour_chunks[(dx, dz)] = self._level.get_chunk(
                    self.cx + dx, self.cz + dz, self.dimension).blocks
            except ChunkLoadError:
                continue

        for cy in blocks.sub_chunks:
            sub_chunk = blocks.get_sub_chunk(cy)
            larger_blocks = numpy.zeros(
                sub_chunk.shape + numpy.array((2, 2, 2)), sub_chunk.dtype)
            sub_chunk_box = SelectionBox.create_sub_chunk_box(
                self.cx, cy, self.cz)
            if self._level.selection_bounds.intersects(sub_chunk_box):
                boxes = self._level.selection_bounds.intersection(
                    sub_chunk_box)
                for box in boxes.selection_boxes:
                    larger_blocks[1:-1, 1:-1, 1:-1][box.sub_chunk_slice(
                        self.cx, cy, self.cz)] = sub_chunk[box.sub_chunk_slice(
                            self.cx, cy, self.cz)]
                for chunk_offset, neighbour_blocks in neighbour_chunks.items():
                    if cy not in neighbour_blocks:
                        continue
                    if chunk_offset == (-1, 0):
                        larger_blocks[0, 1:-1,
                                      1:-1] = neighbour_blocks.get_sub_chunk(
                                          cy)[-1, :, :]
                    elif chunk_offset == (1, 0):
                        larger_blocks[-1, 1:-1,
                                      1:-1] = neighbour_blocks.get_sub_chunk(
                                          cy)[0, :, :]
                    elif chunk_offset == (0, -1):
                        larger_blocks[1:-1, 1:-1,
                                      0] = neighbour_blocks.get_sub_chunk(
                                          cy)[:, :, -1]
                    elif chunk_offset == (0, 1):
                        larger_blocks[1:-1, 1:-1,
                                      -1] = neighbour_blocks.get_sub_chunk(
                                          cy)[:, :, 0]
                if cy - 1 in blocks:
                    larger_blocks[1:-1, 0,
                                  1:-1] = blocks.get_sub_chunk(cy - 1)[:,
                                                                       -1, :]
                if cy + 1 in blocks:
                    larger_blocks[1:-1, -1,
                                  1:-1] = blocks.get_sub_chunk(cy + 1)[:, 0, :]
                unique_blocks = numpy.unique(larger_blocks)
                sub_chunks.append(
                    (larger_blocks, unique_blocks, (0, cy * 16, 0)))
        return sub_chunks
    def _encode_blocks(
        self, blocks: Blocks, palette: AnyNDArray
    ) -> amulet_nbt.TAG_List:
        sections = amulet_nbt.TAG_List()
        for cy in range(16):
            if cy in blocks:
                block_sub_array = numpy.transpose(
                    blocks.get_sub_chunk(cy), (1, 2, 0)
                ).ravel()

                sub_palette_, block_sub_array = numpy.unique(
                    block_sub_array, return_inverse=True
                )
                sub_palette = self._encode_palette(palette[sub_palette_])
                if (
                    len(sub_palette) == 1
                    and sub_palette[0]["Name"].value == "minecraft:air"
                ):
                    continue

                section = amulet_nbt.TAG_Compound()
                section["Y"] = amulet_nbt.TAG_Byte(cy)
                if self.features["long_array_format"] == "compact":
                    section["BlockStates"] = amulet_nbt.TAG_Long_Array(
                        encode_long_array(block_sub_array)
                    )
                elif self.features["long_array_format"] == "1.16":
                    section["BlockStates"] = amulet_nbt.TAG_Long_Array(
                        encode_long_array(block_sub_array, dense=False)
                    )
                section["Palette"] = sub_palette
                sections.append(section)

        return sections
예제 #4
0
    def _sub_chunks(
        self, blocks: Blocks
    ) -> List[Tuple[numpy.ndarray, numpy.ndarray, Tuple[int, int, int]]]:
        sub_chunks = []
        neighbour_chunks = {}
        for dx, dz in ((-1, 0), (1, 0), (0, -1), (0, 1)):
            try:
                neighbour_chunks[(dx,
                                  dz)] = self._render_world.world.get_chunk(
                                      self.cx + dx, self.cz + dz,
                                      self.dimension).blocks
            except ChunkLoadError:
                continue

        for cy in blocks.sub_chunks:
            sub_chunk = blocks.get_sub_chunk(cy)
            larger_blocks = numpy.zeros(
                sub_chunk.shape + numpy.array((2, 2, 2)), sub_chunk.dtype)
            larger_blocks[1:-1, 1:-1, 1:-1] = sub_chunk
            for chunk_offset, neighbour_blocks in neighbour_chunks.items():
                if cy not in neighbour_blocks:
                    continue
                if chunk_offset == (-1, 0):
                    larger_blocks[0, 1:-1,
                                  1:-1] = neighbour_blocks.get_sub_chunk(cy)[
                                      -1, :, :]
                elif chunk_offset == (1, 0):
                    larger_blocks[-1, 1:-1,
                                  1:-1] = neighbour_blocks.get_sub_chunk(cy)[
                                      0, :, :]
                elif chunk_offset == (0, -1):
                    larger_blocks[1:-1, 1:-1,
                                  0] = neighbour_blocks.get_sub_chunk(cy)[:, :,
                                                                          -1]
                elif chunk_offset == (0, 1):
                    larger_blocks[1:-1, 1:-1,
                                  -1] = neighbour_blocks.get_sub_chunk(
                                      cy)[:, :, 0]
            if cy - 1 in blocks:
                larger_blocks[1:-1, 0,
                              1:-1] = blocks.get_sub_chunk(cy - 1)[:, -1, :]
            if cy + 1 in blocks:
                larger_blocks[1:-1, -1,
                              1:-1] = blocks.get_sub_chunk(cy + 1)[:, 0, :]
            unique_blocks = numpy.unique(larger_blocks)
            sub_chunks.append((larger_blocks, unique_blocks, (0, cy * 16, 0)))
        return sub_chunks