Example #1
0
    def get_chunk_boxes(
        self,
        selection: Union[SelectionGroup, SelectionBox],
        dimension: Dimension,
        create_missing_chunks=False,
    ) -> Generator[Tuple[Chunk, SelectionBox], None, None]:
        """Given a selection will yield chunks and SubSelectionBoxes into that chunk

        :param selection: SelectionGroup or SelectionBox into the world
        :param dimension: The dimension to take effect in (defaults to overworld)
        :param create_missing_chunks: If a chunk does not exist an empty one will be created (defaults to false)
        """

        if isinstance(selection, SelectionBox):
            selection = SelectionGroup([selection])
        selection: SelectionGroup
        for (cx, cz), box in selection.sub_sections(self.sub_chunk_size):
            try:
                chunk = self.get_chunk(cx, cz, dimension)
            except ChunkDoesNotExist:
                if create_missing_chunks:
                    chunk = Chunk(cx, cz)
                    self.put_chunk(chunk, dimension)
                else:
                    continue
            except ChunkLoadError:
                continue

            yield chunk, box
Example #2
0
    def decode(self, cx: int, cz: int,
               section: SchematicChunk) -> Tuple["Chunk", AnyNDArray]:
        chunk = Chunk(cx, cz)
        block_palette, blocks = numpy.unique(
            (section.blocks << 4) + (section.data & 0xF), return_inverse=True)
        blocks = blocks.reshape(section.blocks.shape)
        palette = numpy.empty(len(block_palette) + 1, dtype=numpy.object)
        palette[0] = (0, 0)
        for index, block_num in enumerate(block_palette):
            palette[index + 1] = (block_num >> 4, block_num & 0xF)

        box = section.selection.create_moved_box((cx * 16, 0, cz * 16),
                                                 subtract=True)
        chunk.blocks[box.slice] = blocks + 1
        for b in section.block_entities:
            b = self._decode_block_entity(b, self._block_entity_id_type,
                                          self._block_entity_coord_type)
            if b is not None:
                chunk.block_entities.insert(b)
        for b in section.entities:
            b = self._decode_entity(b, self._block_entity_id_type,
                                    self._block_entity_coord_type)
            if b is not None:
                chunk.entities.append(b)

        return chunk, palette
Example #3
0
    def decode(self, cx: int, cz: int,
               data: SpongeSchemChunk) -> Tuple["Chunk", AnyNDArray]:
        """
        Create an amulet.api.chunk.Chunk object from raw data given by the format
        :param cx: chunk x coordinate
        :param cz: chunk z coordinate
        :param data: Raw chunk data provided by the format.
        :return: Chunk object in version-specific format, along with the block_palette for that chunk.
        """
        palette = numpy.empty(len(data.palette) + 1, dtype=object)
        palette[0] = Block(namespace="minecraft", base_name="air")
        palette[1:] = data.palette[:]

        chunk = Chunk(cx, cz)
        box = data.selection.create_moved_box((cx * 16, 0, cz * 16),
                                              subtract=True)
        chunk.blocks[box.slice] = data.blocks + 1
        for b in data.block_entities:
            b = self._decode_block_entity(b, self._block_entity_id_type,
                                          self._block_entity_coord_type)
            if b is not None:
                chunk.block_entities.insert(b)
        for e in data.entities:
            e = self._decode_entity(e, self._block_entity_id_type,
                                    self._block_entity_coord_type)
            if e is not None:
                chunk.entities.append(e)

        return chunk, palette
Example #4
0
    def decode(
        self, cx: int, cz: int, section: MCStructureChunk
    ) -> Tuple["Chunk", AnyNDArray]:
        palette = numpy.empty(len(section.palette) + 1, dtype=numpy.object)
        palette[0] = (
            (
                17563649,
                Block(
                    namespace="minecraft",
                    base_name="air",
                    properties={"block_data": amulet_nbt.TAG_Int(0)},
                ),
            ),
        )

        for index, blocks in enumerate(section.palette):
            block_layers: List[Tuple[Optional[int], Block]] = []
            for block in blocks:
                namespace, base_name = block["name"].value.split(":", 1)
                if "version" in block:
                    version: Optional[int] = block["version"].value
                else:
                    version = None

                if "states" in block:  # 1.13 format
                    properties = block["states"].value
                    if version is None:
                        version = 17694720  # 1, 14, 0, 0
                else:
                    properties = {"block_data": amulet_nbt.TAG_Int(block["val"].value)}
                block_layers.append(
                    (
                        version,
                        Block(
                            namespace=namespace,
                            base_name=base_name,
                            properties=properties,
                        ),
                    )
                )
            palette[index + 1] = block_layers

        chunk = Chunk(cx, cz)
        box = section.selection.create_moved_box((cx * 16, 0, cz * 16), subtract=True)
        chunk.blocks[box.slice] = section.blocks + 1
        for b in section.block_entities:
            b = self._decode_block_entity(
                b, self._block_entity_id_type, self._block_entity_coord_type
            )
            if b is not None:
                chunk.block_entities.insert(b)
        for b in section.entities:
            b = self._decode_entity(
                b, self._block_entity_id_type, self._block_entity_coord_type
            )
            if b is not None:
                chunk.entities.append(b)

        return chunk, palette
Example #5
0
 def create_chunks(
     world: BaseLevel,
     dimension: Dimension,
     selection: SelectionGroup,
 ):
     for cx, cz in selection.chunk_locations():
         if not world.has_chunk(cx, cz, dimension):
             world.put_chunk(Chunk(cx, cz), dimension)
Example #6
0
 def _init_decode(cx: int, cz: int, data: NBTFile) -> Tuple[Chunk, TAG_Compound]:
     """Get the decode started by creating a chunk object."""
     chunk = Chunk(cx, cz)
     assert isinstance(data.value, TAG_Compound), "Raw data must be a compound."
     chunk.misc = {
         # store the chunk data so that any non-versioned data can get saved back
         "java_chunk_data": data.value
     }
     return chunk, data.value
def initialize_world(world: World):
    minxcoord = -1000
    minzcoord = -1000
    maxxcoord = 5000
    maxzcoord = 7000
    minx, minz = block_coords_to_chunk_coords(minxcoord, minzcoord)
    maxx, maxz = block_coords_to_chunk_coords(maxxcoord, maxzcoord)
    for x in range(minx, maxx):
        for z in range(minz, maxz):
            world.put_chunk(Chunk(x, z))
Example #8
0
    def create_chunk(self, cx: int, cz: int, dimension: Dimension) -> Chunk:
        """
        Create an empty chunk and put it at the given location.

        If a chunk exists at the given location it will be overwritten.

        :param cx: The X coordinate of the chunk
        :param cz: The Z coordinate of the chunk
        :param dimension: The dimension to put the chunk in.
        :return: The newly created :class:`Chunk`.
        """
        chunk = Chunk(cx, cz)
        self.put_chunk(chunk, dimension)
        return chunk
def set_block(world: World, x: int, y: int, z: int, block: str):
    if not (0 <= y <= 255):
        raise IndexError("The supplied Y coordinate must be between 0 and 255")

    cx, cz = block_coords_to_chunk_coords(x, z)

    try:
        chunk = world.get_chunk(cx, cz)
    except ChunkDoesNotExist:
        world.put_chunk(Chunk(cx, cz))
        chunk = world.get_chunk(cx, cz)

    offset_x, offset_z = x - 16 * cx, z - 16 * cz
    chunk.blocks[offset_x, y, offset_z] = world.palette.get_add_block(
        Block(namespace="universal_minecraft", base_name=block))
    # print("set block x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " to block " + block)
    chunk.changed = True
Example #10
0
    def decode(self, cx: int, cz: int,
               data: List[ConstructionSection]) -> Tuple["Chunk", AnyNDArray]:
        """
        Create an amulet.api.chunk.Chunk object from raw data given by the format
        :param cx: chunk x coordinate
        :param cz: chunk z coordinate
        :param data: Raw chunk data provided by the format.
        :return: Chunk object in version-specific format, along with the block_palette for that chunk.
        """
        chunk = Chunk(cx, cz)
        palette = []
        for section in data:
            if any(s == 0 for s in section.shape):
                continue
            if section.blocks is not None:
                shapex, shapey, shapez = section.shape
                sx = section.sx % 16
                sy = section.sy
                sz = section.sz % 16
                chunk.blocks[sx:sx + shapex, sy:sy + shapey,
                             sz:sz + shapez, ] = section.blocks.astype(
                                 numpy.uint32) + len(palette)
                chunk.block_entities.update(section.block_entities)
            chunk.entities.extend(section.entities)
            palette += section.palette

        np_palette, inverse = numpy.unique(palette, return_inverse=True)
        np_palette = numpy.insert(
            np_palette,
            0,
            Block(
                namespace="minecraft",
                base_name="air",
                properties={"block_data": amulet_nbt.TAG_Int(0)},
            ),
        )
        inverse += 1
        np_palette: AnyNDArray
        inverse: numpy.ndarray
        for cy in chunk.blocks.sub_chunks:
            chunk.blocks.add_sub_chunk(
                cy,
                inverse[chunk.blocks.get_sub_chunk(cy)].astype(numpy.uint32))
        return chunk, np_palette
Example #11
0
def delete_chunk(
    world: "BaseLevel",
    dimension: Dimension,
    source_box: SelectionGroup,
    load_original: bool = True,
):
    chunks = [(cx, cz) for (cx, cz) in source_box.chunk_locations()
              if world.has_chunk(cx, cz, dimension)]
    iter_count = len(chunks)
    for count, (cx, cz) in enumerate(chunks):
        world.delete_chunk(cx, cz, dimension)

        if not load_original:
            # this part is kind of hacky.
            # Work out a propery API to do this.
            key = dimension, cx, cz
            if key not in world.chunks._history_database:
                world.chunks._register_original_entry(key, Chunk(cx, cz))

        yield (count + 1) / iter_count
Example #12
0
    def decode(
        self, cx: int, cz: int, data: List[ConstructionSection]
    ) -> Tuple["Chunk", AnyNDArray]:
        chunk = Chunk(cx, cz)
        palette = []
        for section in data:
            if any(s == 0 for s in section.shape):
                continue
            if section.blocks is not None:
                shapex, shapey, shapez = section.shape
                sx = section.sx - ((section.sx >> 4) << 4)
                sy = section.sy
                sz = section.sz - ((section.sz >> 4) << 4)
                chunk.blocks[
                    sx : sx + shapex, sy : sy + shapey, sz : sz + shapez,
                ] = section.blocks.astype(numpy.uint32) + len(palette)
                chunk.block_entities.update(section.block_entities)
            chunk.entities.extend(section.entities)
            palette += section.palette

        np_palette, inverse = numpy.unique(palette, return_inverse=True)
        np_palette = numpy.insert(
            np_palette,
            0,
            Block(
                namespace="minecraft",
                base_name="air",
                properties={"block_data": amulet_nbt.TAG_Int(0)},
            ),
        )
        inverse += 1
        np_palette: AnyNDArray
        inverse: numpy.ndarray
        for cy in chunk.blocks.sub_chunks:
            chunk.blocks.add_sub_chunk(
                cy, inverse[chunk.blocks.get_sub_chunk(cy)].astype(numpy.uint32)
            )
        return chunk, np_palette
Example #13
0
    def decode(
        self, cx: int, cz: int, data: SchematicChunk
    ) -> Tuple["Chunk", AnyNDArray]:
        """
        Create an amulet.api.chunk.Chunk object from raw data given by the format
        :param cx: chunk x coordinate
        :param cz: chunk z coordinate
        :param data: Raw chunk data provided by the format.
        :return: Chunk object in version-specific format, along with the block_palette for that chunk.
        """
        chunk = Chunk(cx, cz)
        block_palette, blocks = numpy.unique(
            (data.blocks << 4) + (data.data & 0xF), return_inverse=True
        )
        blocks = blocks.reshape(data.blocks.shape)
        palette = numpy.empty(len(block_palette) + 1, dtype=object)
        palette[0] = (0, 0)
        for index, block_num in enumerate(block_palette):
            palette[index + 1] = (block_num >> 4, block_num & 0xF)

        box = data.selection.create_moved_box((cx * 16, 0, cz * 16), subtract=True)
        chunk.blocks[box.slice] = blocks + 1
        for b in data.block_entities:
            b = self._decode_block_entity(
                b, self._block_entity_id_type, self._block_entity_coord_type
            )
            if b is not None:
                chunk.block_entities.insert(b)
        for b in data.entities:
            b = self._decode_entity(
                b, self._block_entity_id_type, self._block_entity_coord_type
            )
            if b is not None:
                chunk.entities.append(b)

        return chunk, palette
Example #14
0
    def decode(self, cx: int, cz: int,
               data: Dict[bytes, bytes]) -> Tuple[Chunk, AnyNDArray]:
        # chunk_key_base = struct.pack("<ii", cx, cz)

        chunk = Chunk(cx, cz)
        chunk_palette = numpy.empty(0, dtype=object)

        if self.features["terrain"].startswith(
                "2f"):  # ["2farray", "2f1palette", "2fnpalette"]
            subchunks = [
                data.get(b"\x2F" + bytes([i]), None) for i in range(16)
            ]
            chunk.blocks, chunk_palette = self._load_subchunks(subchunks)
        elif self.features["terrain"] == "30array":
            chunk_data = data.get(b"\x30", None)
            if chunk_data is not None:
                block_ids = numpy.frombuffer(chunk_data[:2**15],
                                             dtype=numpy.uint8).astype(
                                                 numpy.uint16)
                block_data = from_nibble_array(
                    numpy.frombuffer(chunk_data[2**15:2**15 + 2**14],
                                     dtype=numpy.uint8))

                # there is other data here but we are going to skip over it
                combined_palette, block_array = fast_unique(
                    numpy.transpose(
                        ((block_ids << 4) + block_data).reshape(16, 16, 128),
                        (0, 2, 1)))
                chunk.blocks = {
                    i: block_array[:, i * 16:(i + 1) * 16, :]
                    for i in range(8)
                }
                palette: AnyNDArray = numpy.array(
                    [combined_palette >> 4, combined_palette & 15]).T
                chunk_palette = numpy.empty(len(palette), dtype=object)
                for i, b in enumerate(palette):
                    chunk_palette[i] = ((None, tuple(b)), )

        else:
            raise Exception

        if self.features["finalised_state"] == "int0-2":
            if b"\x36" in data:
                val = struct.unpack("<i", data[b"\x36"])[0]
            else:
                val = 2
            chunk.status = val

        if self.features["data_2d"] in [
                "height512|biome256",
                "unused_height512|biome256",
        ]:
            d2d = data.get(b"\x2D", b"\x00" * 768)
            height, biome = d2d[:512], d2d[512:]
            if self.features["data_2d"] == "height512|biome256":
                pass  # TODO: put this data somewhere
            chunk.biomes = numpy.frombuffer(biome,
                                            dtype="uint8").reshape(16, 16)

        # TODO: impliment key support
        # \x2D  heightmap and biomes
        # \x31  block entity
        # \x32  entity
        # \x33  ticks
        # \x34  block extra data
        # \x35  biome state
        # \x39  7 ints and an end (03)? Honestly don't know what this is
        # \x3A  fire tick?

        # \x2E  2d legacy
        # \x30  legacy terrain

        # unpack block entities and entities
        if self.features["block_entities"] == "31list":
            block_entities = self._unpack_nbt_list(data.get(b"\x31", b""))
            chunk.block_entities = self._decode_block_entities(block_entities)

        if self.features["entities"] == "32list" and amulet.entity_support:
            entities = self._unpack_nbt_list(data.get(b"\x32", b""))
            chunk.entities = self._decode_entities(entities)

        return chunk, chunk_palette
Example #15
0
    def decode(self, cx: int, cz: int,
               data: MCStructureChunk) -> Tuple["Chunk", AnyNDArray]:
        """
        Create an amulet.api.chunk.Chunk object from raw data given by the format
        :param cx: chunk x coordinate
        :param cz: chunk z coordinate
        :param data: Raw chunk data provided by the format.
        :return: Chunk object in version-specific format, along with the block_palette for that chunk.
        """
        palette = numpy.empty(len(data.palette) + 1, dtype=object)
        palette[0] = ((
            17563649,
            Block(
                namespace="minecraft",
                base_name="air",
                properties={"block_data": amulet_nbt.TAG_Int(0)},
            ),
        ), )

        for index, blocks in enumerate(data.palette):
            block_layers: List[Tuple[Optional[int], Block]] = []
            for block in blocks:
                namespace, base_name = block["name"].value.split(":", 1)
                if "version" in block:
                    version: Optional[int] = block["version"].value
                else:
                    version = None

                if "states" in block:  # 1.13 format
                    properties = block["states"].value
                    if version is None:
                        version = 17694720  # 1, 14, 0, 0
                else:
                    properties = {
                        "block_data": amulet_nbt.TAG_Int(block["val"].value)
                    }
                block_layers.append((
                    version,
                    Block(
                        namespace=namespace,
                        base_name=base_name,
                        properties=properties,
                    ),
                ))
            palette[index + 1] = block_layers

        chunk = Chunk(cx, cz)
        box = data.selection.create_moved_box((cx * 16, 0, cz * 16),
                                              subtract=True)
        chunk.blocks[box.slice] = data.blocks + 1
        for b in data.block_entities:
            b = self._decode_block_entity(b, self._block_entity_id_type,
                                          self._block_entity_coord_type)
            if b is not None:
                chunk.block_entities.insert(b)
        for b in data.entities:
            b = self._decode_entity(b, self._block_entity_id_type,
                                    self._block_entity_coord_type)
            if b is not None:
                chunk.entities.append(b)

        return chunk, palette
Example #16
0
import amulet
from amulet.api.errors import ChunkLoadError, ChunkDoesNotExist
from amulet.api.chunk import Chunk

# load the level
level = amulet.load_level("level")

# create a new chunk at cx=1, cz=2. This is an empty chunk containing no data.
new_chunk = Chunk(1, 2)

# populate the chunk with any data you want (if any)

# add the newly created chunk to the given dimension.
level.put_chunk(new_chunk, "minecraft:overworld")

# we have changed the chunk data so we need to set this value otherwise it won't get saved.
new_chunk.changed = True

# save the changes to the world
level.save()

# close the world
level.close()
    def decode(self, cx: int, cz: int, data: Dict[bytes, bytes],
               bounds: Tuple[int, int]) -> Tuple[Chunk, AnyNDArray]:
        """
        Create an amulet.api.chunk.Chunk object from raw data given by the format
        :param cx: chunk x coordinate
        :param cz: chunk z coordinate
        :param data: Raw chunk data provided by the format.
        :param bounds: The minimum and maximum height of the chunk.
        :return: Chunk object in version-specific format, along with the block_palette for that chunk.
        """
        chunk = Chunk(cx, cz)
        chunk_palette = numpy.empty(0, dtype=object)
        chunk.misc = {"bedrock_chunk_data": data}

        data.pop(b"v", None)
        data.pop(b",", None)

        if self._features["terrain"].startswith(
                "2f"):  # ["2farray", "2f1palette", "2fnpalette"]
            subchunks = {}
            for key in data.copy().keys():
                if len(key) == 2 and key[0:1] == b"\x2F":
                    cy = struct.unpack("b", key[1:2])[0]
                    subchunks[self._chunk_key_to_sub_chunk(
                        cy, bounds[0] >> 4)] = data.pop(key)
            chunk.blocks, chunk_palette = self._load_subchunks(subchunks)
        elif self._features["terrain"] == "30array":
            chunk_data = data.pop(b"\x30", None)
            if chunk_data is not None:
                block_ids = numpy.frombuffer(chunk_data[:2**15],
                                             dtype=numpy.uint8).astype(
                                                 numpy.uint16)
                block_data = from_nibble_array(
                    numpy.frombuffer(chunk_data[2**15:2**15 + 2**14],
                                     dtype=numpy.uint8))

                # there is other data here but we are going to skip over it
                combined_palette, block_array = fast_unique(
                    numpy.transpose(
                        ((block_ids << 4) + block_data).reshape(16, 16, 128),
                        (0, 2, 1)))
                chunk.blocks = {
                    i: block_array[:, i * 16:(i + 1) * 16, :]
                    for i in range(8)
                }
                palette: AnyNDArray = numpy.array(
                    [combined_palette >> 4, combined_palette & 15]).T
                chunk_palette = numpy.empty(len(palette), dtype=object)
                for i, b in enumerate(palette):
                    chunk_palette[i] = ((None, tuple(b)), )

        else:
            raise Exception

        if self._features["finalised_state"] == "int0-2":
            state = data.pop(b"\x36", None)
            val = 2
            if isinstance(state, bytes):
                if len(state) == 1:
                    # old versions of the game store this as a byte
                    val = struct.unpack("b", state)[0]
                elif len(state) == 4:
                    # newer versions store it as an int
                    val = struct.unpack("<i", state)[0]
            chunk.status = val

        if b"+" in data:
            height, biome = self._decode_height_3d_biomes(
                data[b"+"], bounds[0] >> 4)
            chunk.misc["height"] = height
            chunk.biomes = biome
        elif b"\x2D" in data:
            d2d = data[b"\x2D"]
            height, biome = (
                numpy.frombuffer(d2d[:512], "<i2").reshape((16, 16)),
                d2d[512:],
            )
            chunk.misc["height"] = height
            chunk.biomes = numpy.frombuffer(biome,
                                            dtype="uint8").reshape(16, 16).T

        # TODO: implement key support
        # \x2D  heightmap and biomes
        # \x31  block entity
        # \x32  entity
        # \x33  ticks
        # \x34  block extra data
        # \x35  biome state
        # \x39  7 ints and an end (03)? Honestly don't know what this is
        # \x3A  fire tick?

        # \x2E  2d legacy
        # \x30  legacy terrain

        # unpack block entities and entities
        if self._features["block_entities"] == "31list":
            block_entities = self._unpack_nbt_list(data.pop(b"\x31", b""))
            chunk.block_entities = self._decode_block_entity_list(
                block_entities)

        if self._features["entities"] == "32list" and amulet.entity_support:
            entities = self._unpack_nbt_list(data.pop(b"\x32", b""))
            chunk.entities = self._decode_entity_list(entities)

        return chunk, chunk_palette
Example #18
0
    def decode(self, cx: int, cz: int,
               data: amulet_nbt.NBTFile) -> Tuple["Chunk", AnyNDArray]:
        """
        Create an amulet.api.chunk.Chunk object from raw data given by the format.
        :param cx: chunk x coordinate
        :param cz: chunk z coordinate
        :param data: amulet_nbt.NBTFile
        :return: Chunk object in version-specific format, along with the block_palette for that chunk.
        """
        misc = {}
        chunk = Chunk(cx, cz)

        if self.features["last_update"] == "long":
            misc["last_update"] = (data["Level"].get(
                "LastUpdate", amulet_nbt.TAG_Long(0)).value)

        if self.features["status"] in ["j13", "j14"]:
            chunk.status = data["Level"]["Status"].value
        else:
            status = "empty"
            if (self.features["terrain_populated"] == "byte"
                    and data["Level"].get("TerrainPopulated",
                                          amulet_nbt.TAG_Byte()).value):
                status = "decorated"
            if (self.features["light_populated"] == "byte"
                    and data["Level"].get("LightPopulated",
                                          amulet_nbt.TAG_Byte()).value):
                status = "postprocessed"

            chunk.status = status

        if self.features["V"] == "byte":
            misc["V"] = data["Level"]["V"].value

        if self.features["inhabited_time"] == "long":
            misc["inhabited_time"] = (data["Level"].get(
                "InhabitedTime", amulet_nbt.TAG_Long(0)).value)

        if self.features["biomes"] is not None:
            biomes = data["Level"].get("Biomes",
                                       amulet_nbt.TAG_Int_Array()).value
            if self.features["biomes"] == "256BA":
                biomes = biomes.astype(numpy.uint8)
            elif self.features["biomes"] in ["256IA", "1024IA"]:
                biomes = biomes.astype(numpy.uint32)

            chunk.biomes = biomes

        if self.features["height_map"] == "256IA":
            misc["height_map256IA"] = data["Level"]["HeightMap"].value
        elif self.features["height_map"] in [
                "C|36LA|V1",
                "C|36LA|V2",
                "C|36LA|V3",
                "C|36LA|V4",
        ]:
            if "Heightmaps" in data["Level"]:
                misc["height_mapC|36LA"] = data["Level"]["Heightmaps"]

        if "Sections" in data["Level"]:
            if self.features["blocks"] in [
                    "Sections|(Blocks,Data,Add)",
                    "Sections|(BlockStates,Palette)",
            ]:
                chunk.blocks, palette = self._decode_blocks(
                    data["Level"]["Sections"])
            else:
                raise Exception(
                    f'Unsupported block format {self.features["blocks"]}')

            if self.features["block_light"] == "Sections|2048BA":
                misc["block_light"] = {
                    section["Y"].value: section["BlockLight"]
                    for section in data["Level"]["Sections"]
                    if "BlockLight" in section
                }

            if self.features["sky_light"] == "Sections|2048BA":
                misc["sky_light"] = {
                    section["Y"].value: section["SkyLight"]
                    for section in data["Level"]["Sections"]
                    if "SkyLight" in section
                }
        else:
            palette = numpy.array(
                [Block(namespace="minecraft", base_name="air")])

        if self.features["entities"] == "list":
            if amulet.entity_support:
                chunk.entities = self._decode_entities(data["Level"].get(
                    "Entities", amulet_nbt.TAG_List()))
            else:
                misc["java_entities_temp"] = self._decode_entities(
                    data["Level"].get("Entities", amulet_nbt.TAG_List()))

        if self.features["block_entities"] == "list":
            chunk.block_entities = self._decode_block_entities(
                data["Level"].get("TileEntities", amulet_nbt.TAG_List()))

        if self.features["tile_ticks"] == "list":
            misc["tile_ticks"] = data["Level"].get("TileTicks",
                                                   amulet_nbt.TAG_List())

        if self.features["liquid_ticks"] == "list":
            if "LiquidTicks" in data["Level"]:
                misc["liquid_ticks"] = data["Level"]["LiquidTicks"]

        if self.features["liquids_to_be_ticked"] == "16list|list":
            if "LiquidsToBeTicked" in data["Level"]:
                misc["liquids_to_be_ticked"] = data["Level"][
                    "LiquidsToBeTicked"]

        if self.features["to_be_ticked"] == "16list|list":
            if "ToBeTicked" in data["Level"]:
                misc["to_be_ticked"] = data["Level"]["ToBeTicked"]

        if self.features["post_processing"] == "16list|list":
            if "PostProcessing" in data["Level"]:
                misc["post_processing"] = data["Level"]["PostProcessing"]

        if self.features["structures"] == "compound":
            if "Structures" in data["Level"]:
                misc["structures"] = data["Level"]["Structures"]

        chunk.misc = misc

        return chunk, palette
Example #19
0
 def create_chunk(self, cx: int, cz: int, dimension: Dimension) -> Chunk:
     chunk = Chunk(cx, cz)
     self.put_chunk(chunk, dimension)
     return chunk
            else:
                print("Not enough arguments given. Format must be:")
                print("convert <origin_world_path> <destination_world_path>")

        elif mode == "create":
            if len(args) >= 4:
                world_path = args[1]
                cx, cz = int(args[2]), int(args[3])

                print(f"Loading world at {world_path}")
                world = load_world(world_path)
                if (cx, cz) in world.world_wrapper.all_chunk_coords():
                    world.delete_chunk(*(cx, cz))
                world.save()

                chunk = Chunk(cx, cz)
                bedrock = world.palette.get_add_block(
                    Block(namespace="universal_minecraft", base_name="bedrock")
                )
                stone = world.palette.get_add_block(
                    Block(namespace="universal_minecraft", base_name="stone")
                )
                dirt = world.palette.get_add_block(
                    Block(namespace="universal_minecraft", base_name="dirt")
                )
                grass = world.palette.get_add_block(
                    Block(namespace="universal_minecraft", base_name="grass_block")
                )

                chunk.blocks[:, 0, :] = bedrock
                chunk.blocks[:, 1:3, :] = stone
Example #21
0
def paste_iter(
    world: "World",
    dimension: Dimension,
    structure: Structure,
    location: BlockCoordinates,
    scale: FloatTriplet,
    rotation: FloatTriplet,
    copy_air=True,
    copy_water=True,
    copy_lava=True,
):
    gab = numpy.vectorize(world.palette.get_add_block, otypes=[numpy.uint32])
    lut = gab(structure.palette.blocks())
    filtered_mode = not all([copy_air, copy_lava, copy_water])
    filtered_blocks = []
    if not copy_air:
        filtered_blocks.append("universal_minecraft:air")
    if not copy_water:
        filtered_blocks.append("universal_minecraft:water")
    if not copy_lava:
        filtered_blocks.append("universal_minecraft:lava")
    if filtered_mode:
        paste_blocks = numpy.array([
            any(sub_block.namespaced_name not in filtered_blocks
                for sub_block in block.block_tuple)
            for block in structure.palette.blocks()
        ])
    else:
        paste_blocks = None

    rotation_point = numpy.floor(
        (structure.selection.max + structure.selection.min) / 2).astype(int)

    if any(rotation) or any(s != 1 for s in scale):
        yield 0, "Rotating!"
        transformed_structure = yield from structure.transform_iter(
            scale, rotation)
        rotation_point = (numpy.matmul(
            transform_matrix((0, 0, 0), scale,
                             -numpy.radians(numpy.flip(rotation)), "zyx"),
            numpy.array([*rotation_point, 1]),
        ).T[:3].round().astype(int))
    else:
        transformed_structure = structure

    offset = location - rotation_point
    moved_min_location = transformed_structure.selection.min + offset

    iter_count = len(
        list(transformed_structure.get_moved_chunk_slices(moved_min_location)))
    count = 0

    yield 0, "Pasting!"
    for (
            src_chunk,
            src_slices,
            src_box,
        (dst_cx, dst_cz),
            dst_slices,
            dst_box,
    ) in transformed_structure.get_moved_chunk_slices(moved_min_location):
        try:
            dst_chunk = world.get_chunk(dst_cx, dst_cz, dimension)
        except ChunkDoesNotExist:
            dst_chunk = Chunk(dst_cx, dst_cz)
            world.put_chunk(dst_chunk, dimension)
        except ChunkLoadError:
            continue
        remove_block_entities = []
        for block_entity_location in dst_chunk.block_entities.keys():
            if block_entity_location in dst_box:
                if copy_air:
                    remove_block_entities.append(block_entity_location)
                else:
                    chunk_block_entity_location = (
                        numpy.array(block_entity_location) - offset)
                    chunk_block_entity_location[[0, 2]] %= 16
                    if paste_blocks[src_chunk.blocks[tuple(
                            chunk_block_entity_location)]]:
                        remove_block_entities.append(block_entity_location)
        for block_entity_location in remove_block_entities:
            del dst_chunk.block_entities[block_entity_location]
        for block_entity_location, block_entity in src_chunk.block_entities.items(
        ):
            if block_entity_location in src_box:
                dst_chunk.block_entities.insert(
                    block_entity.new_at_location(*offset +
                                                 block_entity_location))

        if not copy_air:
            # dst_blocks_copy = dst_chunk.blocks[dst_slices]
            # mask = paste_blocks[src_chunk.blocks[src_slices]]
            # dst_blocks_copy[mask] = lut[src_chunk.blocks[src_slices]][mask]

            dst_blocks_copy = numpy.asarray(dst_chunk.blocks[dst_slices])
            mask = paste_blocks[src_chunk.blocks[src_slices]]
            dst_blocks_copy[mask] = lut[src_chunk.blocks[src_slices]][mask]
            dst_chunk.blocks[dst_slices] = dst_blocks_copy
        else:
            dst_chunk.blocks[dst_slices] = lut[src_chunk.blocks[src_slices]]
        dst_chunk.changed = True

        count += 1
        yield count / iter_count