def encode( self, chunk: "Chunk", palette: AnyNDArray, max_world_version: Tuple[str, Union[int, Tuple[int, int, int]]], boxes: List[SelectionBox] = None, ) -> List[ConstructionSection]: sections = [] for box in boxes: cx, cz = chunk.cx, chunk.cz for cy in box.chunk_y_locations(): sub_box = box.intersection( SelectionBox.create_sub_chunk_box(cx, cy, cz)) entities = [e for e in chunk.entities if e.location in sub_box] if cy in chunk.blocks: sections.append( ConstructionSection( sub_box.min, sub_box.shape, chunk.blocks[sub_box.chunk_slice(cx, cz)], list(palette), entities, [ e for e in chunk.block_entities if e.location in sub_box ], )) elif entities: sections.append( ConstructionSection(sub_box.min, sub_box.shape, None, [], entities, [])) return sections
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( self, chunk: "Chunk", palette: AnyNDArray, max_world_version: VersionIdentifierType, boxes: List[SelectionBox], ) -> List[ConstructionSection]: """ Take a version-specific chunk and encode it to raw data for the format to store. :param chunk: The already translated version-specfic chunk to encode. :param palette: The block_palette the ids in the chunk correspond to. :type palette: numpy.ndarray[Block] :param max_world_version: The key to use to find the encoder. :param boxes: The volume(s) of the chunk to pack. :return: Raw data to be stored by the Format. """ sections = [] for box in boxes: cx, cz = chunk.cx, chunk.cz for cy in box.chunk_y_locations(): sub_box = box.intersection( SelectionBox.create_sub_chunk_box(cx, cy, cz)) entities = [e for e in chunk.entities if e.location in sub_box] if cy in chunk.blocks: sections.append( ConstructionSection( sub_box.min, sub_box.shape, numpy.asarray(chunk.blocks[sub_box.chunk_slice( cx, cz)]), list(palette), entities, [ e for e in chunk.block_entities if e.location in sub_box ], )) elif entities: sections.append( ConstructionSection(sub_box.min, sub_box.shape, None, [], entities, [])) return sections