Пример #1
0
 def send_air_chunk(self, x, z):
     sections = []
     if x == 0 and z == 0:
         sections = [(BlockArray.empty(self.registry), None)
                     for _ in range(16)]
         sections[9][0][0] = {"name": "minecraft:bedrock"}
     sections_data = self.buff_type.pack_chunk(sections)
     motion_world = PackedArray.empty_height()
     motion_blocking = TagLongArray(PackedArray.empty_height())
     world_surface = TagLongArray(PackedArray.empty_height())
     heightmap = TagRoot({
         "":
         TagCompound({
             "MOTION_BLOCKING": motion_blocking,
             "WORLD_SURFACE": world_surface
         })
     })
     biomes = [27 for _ in range(1024)]
     block_entities = []
     self.send_packet(
         "chunk_data",
         self.buff_type.pack("ii?", x, z, True),
         self.buff_type.pack_chunk_bitmask(sections),
         self.buff_type.pack_nbt(heightmap),  # added in 1.14
         self.buff_type.pack_varint(0),
         b"",
         # b"".join(self.buff_type.pack_varint(biome) for biome in biomes),
         # self.buff_type.pack_array("I", biomes),
         self.buff_type.pack_varint(len(sections_data)),
         sections_data,
         self.buff_type.pack_varint(len(block_entities)),
         b""
         # b"".join(self.buff_type.pack_nbt(entity) for entity in block_entities),
     )
Пример #2
0
def mcaIterator(mca_path, mca_filename):
    registry = OpaqueRegistry(64)  # log2(max block ID)
    with RegionFile(mca_path + mca_filename) as region_file:
        for chunk_x in range(0, 32):
            for chunk_z in range(0, 32):
                try:
                    chunk = region_file.load_chunk(chunk_x, chunk_z)
                    sections = chunk.value[''].value['Level'].value[
                        'Sections'].value
                except (KeyError, ValueError, BufferUnderrun) as e:
                    if type(e) is BufferUnderrun:
                        print("Failed loading chunk:", chunk_x, chunk_z,
                              "Reason:",
                              type(e).__name__, e)
                    continue
                for section in sections:
                    try:
                        blocks = BlockArray.from_nbt(section, registry)
                    except KeyError as e:
                        continue
                    yield {
                        'mca': mca_filename,
                        'x': chunk_x,
                        'z': chunk_z,
                        'y': int.from_bytes(section.value['Y'].to_bytes(),
                                            'big'),
                        'blocks': blocks,
                    }
Пример #3
0
def test_chunk_internals():
    blocks = BlockArray([0] * 4096, 4, [0])

    # Accumulate blocks
    added = []
    for i in range(300):
        block, meta = divmod(i, 16)
        blocks[i] = block, meta
        added.append((block, meta))

        assert blocks[:i + 1] == added

        if i < 256:
            assert len(blocks.palette) == i + 1
            if i < 16:
                assert blocks.bits == 4
            elif i < 32:
                assert blocks.bits == 5
            elif i < 64:
                assert blocks.bits == 6
            elif i < 128:
                assert blocks.bits == 7
            else:
                assert blocks.bits == 8
        else:
            assert blocks.palette is None
            assert blocks.bits == 13

    # Zero the first 100 blocks
    for i in range(100):
        blocks[i] = (0, 0)
    blocks.repack()
    assert len(blocks.palette) == 201
    assert blocks.bits == 8

    # Zero blocks 100-199
    for i in range(100, 200):
        blocks[i] = (0, 0)
    blocks.repack()
    assert len(blocks.palette) == 101
    assert blocks.bits == 7

    # Zero blocks 205 - 300
    for i in range(205, 300):
        blocks[i] = (0, 0)
    blocks.repack()
    assert len(blocks.palette) == 6
    assert blocks.bits == 4

    # Check value
    for i in range(4096):
        if 200 <= i < 205:
            assert blocks[i] == divmod(i, 16)
        else:
            assert blocks[i] == (0, 0)
Пример #4
0
def test_chunk_internals():
    blocks = BlockArray(OpaqueBlockMap(13), [0] * 4096, 4, [0])

    # Accumulate blocks
    added = []
    for i in range(300):
        blocks[i] = i
        added.append(i)

        assert blocks[:i + 1] == added

        if i < 256:
            assert len(blocks.palette) == i + 1
            if i < 16:
                assert blocks.bits == 4
            elif i < 32:
                assert blocks.bits == 5
            elif i < 64:
                assert blocks.bits == 6
            elif i < 128:
                assert blocks.bits == 7
            else:
                assert blocks.bits == 8
        else:
            assert blocks.palette == []
            assert blocks.bits == 13

    # Zero the first 100 blocks
    for i in range(100):
        blocks[i] = 0
    blocks.repack()
    assert len(blocks.palette) == 201
    assert blocks.bits == 8

    # Zero blocks 100-199
    for i in range(100, 200):
        blocks[i] = 0
    blocks.repack()
    assert len(blocks.palette) == 101
    assert blocks.bits == 7

    # Zero blocks 205 - 300
    for i in range(205, 300):
        blocks[i] = 0
    blocks.repack()
    assert len(blocks.palette) == 6
    assert blocks.bits == 4

    # Check value
    for i in range(4096):
        if 200 <= i < 205:
            assert blocks[i] == i
        else:
            assert blocks[i] == 0
Пример #5
0
    def unpack_chunk_section(self):
        """
        Unpacks a chunk section. Returns a sequence of length 4096 (16x16x16).
        """

        non_air, bits = self.unpack('HB')
        palette = self.unpack_chunk_section_palette(bits)
        return BlockArray(
            self.registry,
            self.unpack_array('Q', self.unpack_varint()),
            bits,
            palette,
            non_air)
Пример #6
0
    def unpack_chunk_section(self, overworld=True):
        """
        Unpacks a chunk section. Returns a sequence of length 4096 (16x16x16).
        """

        non_air, value_width = self.unpack('HB')
        palette = self.unpack_chunk_section_palette(value_width)
        array = self.unpack_chunk_section_array(value_width)
        return BlockArray.from_bytes(bytes=array,
                                     palette=palette,
                                     registry=self.registry,
                                     non_air=non_air,
                                     value_width=value_width), None, None
Пример #7
0
def test_chunk_internals():
    blocks = BlockArray(OpaqueRegistry(13), [0]*4096, 4, [0])

    # Accumulate blocks
    added = []
    for i in range(300):
        blocks[i] = i
        added.append(i)

        assert blocks[:i+1] == added

        if i < 256:
            assert len(blocks.palette) == i + 1
            if i < 16:
                assert blocks.bits == 4
            elif i < 32:
                assert blocks.bits == 5
            elif i < 64:
                assert blocks.bits == 6
            elif i < 128:
                assert blocks.bits == 7
            else:
                assert blocks.bits == 8
        else:
            assert blocks.palette == []
            assert blocks.bits == 13

    # Zero the first 100 blocks
    for i in range(100):
        blocks[i] = 0
    blocks.repack()
    assert len(blocks.palette) == 201
    assert blocks.bits == 8

    # Zero blocks 100-199
    for i in range(100, 200):
        blocks[i] = 0
    blocks.repack()
    assert len(blocks.palette) == 101
    assert blocks.bits == 7

    # Zero blocks 205 - 300
    for i in range (205, 300):
        blocks[i] = 0
    blocks.repack()
    assert len(blocks.palette) == 6
    assert blocks.bits == 4

    # Check value
    for i in range(4096):
        if 200 <= i < 205:
            assert blocks[i] == i
        else:
            assert blocks[i] == 0
Пример #8
0
    def packet_downstream_chunk_data(self, buff):
        x, z, contiguous = buff.unpack('ii?')
        bitmask = buff.unpack_varint()
        size = buff.unpack_varint()

        if contiguous:
            chunk = self.chunks[x, z] = {
                'sections': [None] * 16,
                'block_entities': {},
                'block_actions': {}}
        else:
            chunk = self.chunks[x, z]

        for idx in range(16):
            if bitmask & (1 << idx):
                section = buff.unpack_chunk_section(
                    self.dimension == 0)
            elif self.dimension == 0:
                section = (BlockArray.empty(buff.registry),
                           LightArray.empty(),
                           LightArray.empty())
            else:
                section = (BlockArray.empty(buff.registry),
                           LightArray.empty())

            chunk['sections'][idx] = section

        if contiguous:
            chunk['biomes'] = buff.unpack('I' * 256)

        for _ in range(buff.unpack_varint()):
            block_entity = buff.unpack_nbt()
            block_entity_obj = block_entity.to_obj()[""]
            chunk['block_entities'][
                block_entity_obj['x'],
                block_entity_obj['y'],
                block_entity_obj['z']] = block_entity
Пример #9
0
def test_wikivg_example():
    # Example from https://wiki.vg/Chunk_Format#Example
    data = bitstring.BitArray(length=13 * 4096)
    data[
        0:
        64] = '0b0000000000100000100001100011000101001000010000011000100001000001'
    data[
        64:
        128] = '0b0000000100000001100010100111001001100000111101101000110010000111'
    data = data.bytes

    blocks = BlockArray.from_bytes(data, 5, OpaqueRegistry(13), [])
    assert blocks[:24] == [
        1, 2, 2, 3, 4, 4, 5, 6, 6, 4, 8, 0, 7, 4, 3, 13, 15, 16, 9, 14, 10, 12,
        0, 2
    ]
Пример #10
0
def test_wikivg_example():
    # Example from https://wiki.vg/Chunk_Format#Example
    data = bitstring.BitArray(length=13*4096)
    data[0:64]   = '0b0000000100000000000110001000000011000000000001100000000000100000'
    data[64:128] = '0b0000001000000000110100000000011010000000000001001100000000100000'
    data = data.bytes

    blocks = BlockArray.from_bytes(data, [], BitShiftRegistry(13), 10)
    assert blocks[0] == (2, 0)  # grass
    assert blocks[1] == (3, 0)  # dirt
    assert blocks[2] == (3, 0)  # dirt
    assert blocks[3] == (3, 1)  # coarse dirt
    assert blocks[4] == (1, 0)  # stone
    assert blocks[5] == (1, 0)  # stone
    assert blocks[6] == (1, 3)  # diorite
    assert blocks[7] == (13, 0) # gravel
    assert blocks[8] == (13, 0) # gravel
    assert blocks[9] == (1, 0)  # stone
Пример #11
0
    def unpack_chunk_section(self, overworld=True):
        """
        Unpacks a chunk section. Returns a 3-tuple of
        ``(blocks, block_lights, sky_lights)``, where *sky_lights* is ``None``
        when *overworld* is ``False``. The returned values are sequences of
        length 4096 (16x16x16).
        """

        bits = self.unpack('B')
        palette = self.unpack_chunk_section_palette(bits)
        blocks = BlockArray(self.registry,
                            self.unpack_array('Q', self.unpack_varint()), bits,
                            palette, None)
        block_lights = LightArray(self.unpack_array('B', 2048))
        if overworld:
            sky_lights = LightArray(self.unpack_array('B', 2048))
        else:
            sky_lights = None

        return blocks, block_lights, sky_lights
Пример #12
0
    def unpack_chunk_section(self, overworld=True):
        """
        Unpacks a chunk section from the buffer. Returns a 3-tuple of
        ``(blocks, block_lights, sky_lights)``, where *sky_lights* is ``None``
        when *overworld* is ``False``. The returned values are sequences of
        length 4096 (16x16x16).
        """
        bits = self.unpack('B')
        if bits < 4: bits = 4
        elif bits > 8: bits = 13

        palette = [self.unpack_varint() for _ in xrange(self.unpack_varint())]
        blocks = BlockArray(self.unpack('Q' * self.unpack_varint()), bits,
                            palette)
        block_lights = LightArray(self.unpack('B' * 2048))
        if overworld:
            sky_lights = LightArray(self.unpack('B' * 2048))
        else:
            sky_lights = None

        return blocks, block_lights, sky_lights
Пример #13
0
    def unpack_chunk_section(self, overworld=True):
        """
        Unpacks a chunk section. Returns a 3-tuple of
        ``(blocks, block_lights, sky_lights)``, where *sky_lights* is ``None``
        when *overworld* is ``False``. The returned values are sequences of
        length 4096 (16x16x16).
        """

        value_width = self.unpack('B')
        palette = self.unpack_chunk_section_palette(value_width)
        array = self.unpack_chunk_section_array(value_width)
        blocks = BlockArray.from_bytes(bytes=array,
                                       palette=palette,
                                       registry=self.registry,
                                       non_air=None,
                                       value_width=value_width)
        block_lights = PackedArray.from_light_bytes(self.read(2048))
        if overworld:
            sky_lights = PackedArray.from_light_bytes(self.read(2048))
        else:
            sky_lights = None

        return blocks, block_lights, sky_lights
Пример #14
0
def parse_region_file(file, search_blocks):
    print("Start processing", file)
    search_results = []
    with RegionFile(file) as region:
        for x, z in range_xz(0, 32):
            try:
                chunk = region.load_chunk(x, z)
                x_pos = chunk.body.value["Level"].value['xPos'].value
                z_pos = chunk.body.value["Level"].value['zPos'].value
                sections = chunk.body.value["Level"].value["Sections"].value
                for section in sections:
                    blocks = BlockArray(
                        registry,
                        section.value["Blocks"].value,
                        bits=8,
                    )
                    y_pos = section.value['Y'].value

                    for i in range(4096):
                        block_id = blocks.data[i]
                        if block_id in search_blocks:
                            block_x = x_pos * 16 + i % 16
                            block_y = y_pos * 16 + i // 256
                            block_z = z_pos * 16 + i % 256 // 16
                            print(
                                "Block found on index %s on coordinates %s, %s, %s"
                                % (i, block_x, block_y, block_z))

                            search_results.append(
                                (block_id, block_x, block_y, block_z))

            except Exception:  # pylint: disable=broad-except  # catch any occurring errors to prevent script from stopping somewhere parsing the world
                pass

    print("Completed processing", file)
    return search_results