|
17 | 17 | """ |
18 | 18 |
|
19 | 19 | import array |
| 20 | +import struct |
20 | 21 | from math import floor |
21 | 22 |
|
22 | 23 | from spockbot.mcp.bbuff import BoundBuffer |
| 24 | +from spockbot.mcp.datautils import unpack_varint |
| 25 | + |
23 | 26 |
|
24 | 27 |
|
25 | 28 | DIMENSION_NETHER = -0x01 |
@@ -134,9 +137,46 @@ def set(self, x, z, d): |
134 | 137 |
|
135 | 138 |
|
136 | 139 | class ChunkDataShort(ChunkData): |
137 | | - """ A 16x16x16 array for storing block IDs/Metadata. """ |
| 140 | + """ A 16x16x16 array for storing block IDs and metadata. """ |
138 | 141 | length = 16 * 16 * 16 * 2 |
139 | | - ty = 'H' |
| 142 | + ty = 'H' # protocol allows larger block types |
| 143 | + |
| 144 | + def unpack(self, buff): |
| 145 | + block_bits = buff.read(1)[0] |
| 146 | + uses_palette = block_bits > 0 |
| 147 | + |
| 148 | + if uses_palette: |
| 149 | + palette_len = unpack_varint(buff) |
| 150 | + palette = [unpack_varint(buff) for i in range(palette_len)] |
| 151 | + else: # use global palette |
| 152 | + block_bits = 13 |
| 153 | + |
| 154 | + data_longs = unpack_varint(buff) |
| 155 | + block_data = [struct.unpack('>Q', buff.read(8))[0] |
| 156 | + for i in range(data_longs)] |
| 157 | + |
| 158 | + self.fill() |
| 159 | + blocks = self.data |
| 160 | + max_value = (1 << block_bits) - 1 |
| 161 | + for i in range(4096): |
| 162 | + start_long = (i * block_bits) // 64 |
| 163 | + start_offset = (i * block_bits) % 64 |
| 164 | + end_long = ((i + 1) * block_bits - 1) // 64 |
| 165 | + if start_long == end_long: |
| 166 | + block = (block_data[start_long] >> start_offset) & max_value |
| 167 | + else: |
| 168 | + end_offset = 64 - start_offset |
| 169 | + block = (block_data[start_long] >> start_offset |
| 170 | + | block_data[end_long] << end_offset |
| 171 | + ) & max_value |
| 172 | + |
| 173 | + if uses_palette: # convert to global palette |
| 174 | + blocks[i] = palette[block] |
| 175 | + else: |
| 176 | + blocks[i] = block |
| 177 | + |
| 178 | + def pack(self): |
| 179 | + raise NotImplementedError('1.9 block data packing not implemented') |
140 | 180 |
|
141 | 181 |
|
142 | 182 | class ChunkDataNibble(ChunkData): |
|
0 commit comments