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
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
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