如何用Python读取并修改Minecraft 1.15-1.20区块data数据
Minecraft 1.15-1.20 区块Data数组解析与修改(Python实现)
底层核心机制
- Data数组本质是变长位宽的索引序列,每个索引对应Palette中的方块条目
- 每个索引占用的位宽(
bit_per_entry)由Palette长度决定:- 计算方式:
bit_per_entry = max(4, math.ceil(math.log2(len(palette)))) - 最小位宽为4,这是Minecraft的硬性规定,避免频繁调整位宽带来的性能开销
- 计算方式:
- Data数组以字节流形式存储,所有索引的二进制位连续拼接,最后不足1字节的部分用0补位
数据提取实现(从Data字节数组到Palette索引列表)
步骤
- 计算每个索引的位宽
bit_per_entry - 将Data字节数组转换为大端序的连续二进制位串
- 按
bit_per_entry长度拆分位串,每个片段转成十进制整数,即为Palette索引
代码实现
import math def parse_data(data_bytes, palette): palette_len = len(palette) if palette_len == 0: return [] # 计算每个索引的位宽 bit_per_entry = max(4, math.ceil(math.log2(palette_len))) total_bits = len(data_bytes) * 8 total_entries = total_bits // bit_per_entry # 实际有效索引数 # 将字节数组转为大端序的二进制位串 bit_string = ''.join(f'{byte:08b}' for byte in data_bytes) # 拆分位串并转换为索引 indices = [] for i in range(total_entries): start = i * bit_per_entry end = start + bit_per_entry bit_segment = bit_string[start:end] index = int(bit_segment, 2) indices.append(index) return indices
数据修改实现(从Palette索引列表到Data字节数组)
步骤
- 计算目标位宽
bit_per_entry(同提取逻辑) - 将每个索引转为固定长度的二进制位串(长度为
bit_per_entry,高位补0) - 拼接所有位串,若总长度不是8的倍数,末尾补0对齐到字节
- 将拼接后的位串按每8位一组转成字节,得到最终的Data字节数组
代码实现
def build_data(indices, palette): palette_len = len(palette) if not indices or palette_len == 0: return b'' bit_per_entry = max(4, math.ceil(math.log2(palette_len))) # 每个索引转成固定长度的二进制位串(高位在前) bit_segments = [f'{index:0{bit_per_entry}b}' for index in indices] bit_string = ''.join(bit_segments) # 补位到字节对齐 padding_bits = (8 - len(bit_string) % 8) % 8 bit_string += '0' * padding_bits # 将位串转成字节数组(大端序) data_bytes = bytearray() for i in range(0, len(bit_string), 8): byte_segment = bit_string[i:i+8] byte = int(byte_segment, 2) data_bytes.append(byte) return bytes(data_bytes)
关键注意事项
- 索引合法性:所有索引必须小于Palette长度,否则Minecraft加载区块时会报错
- 字节端序:始终使用大端序处理,这是Minecraft区块存储的标准
- 补位处理:修改后的位串必须补0到字节边界,否则Data数组长度不正确会导致区块损坏
- Palette长度变化:如果修改后Palette长度改变,需要重新计算
bit_per_entry并重新生成Data数组,同时更新区块中的Palette数据
内容的提问来源于stack exchange,提问作者Ilai K
相关产品推荐
相关产品推荐

