告别数字ID!手把手教你修复mcpi库以适配Minecraft 1.13+的Python自动化脚本
告别数字ID!手把手教你修复mcpi库以适配Minecraft 1.13+的Python自动化脚本
当你在Minecraft 1.13+版本中兴奋地运行Python自动化脚本时,突然发现 setBlock() 函数无法正常工作——这可能是由于官方mcpi库(1.2.0版本)尚未适配新版命名空间ID系统导致的。本文将带你深入问题本质,从定位库文件到修改关键代码,最终实现Python脚本与新版Minecraft的无缝协作。
1. 理解Minecraft 1.13的ID系统变革
2018年发布的Minecraft 1.13("水域更新")对游戏底层进行了重大调整,其中最影响自动化脚本的就是方块ID系统的重构:
- 旧版(1.12及之前) :使用纯数字ID(如
1表示石头,48表示苔石) - 新版(1.13+) :采用命名空间ID(如
minecraft:stone、minecraft:mossy_cobblestone)
这种变化导致依赖数字ID的旧版mcpi库在调用 setBlock() 等函数时会抛出类型错误。通过 pip show mcpi 命令可以确认当前安装的库版本:
$ pip show mcpi
Name: mcpi
Version: 1.2.0
Summary: Minecraft Pi edition Python library
...
注意:虽然JuicyRaspberryPie插件已更新支持1.16.5,但Python端的mcpi库自2017年后就未再更新
2. 定位并修改mcpi库文件
2.1 查找库安装位置
首先需要找到mcpi库的实际安装路径。在Python交互环境中执行:
>>> import mcpi
>>> print(mcpi.__file__)
/usr/local/lib/python3.9/site-packages/mcpi/__init__.py
得到的路径即为库的安装目录,关键文件 minecraft.py 通常位于同级目录下。
2.2 识别问题函数
打开 minecraft.py 文件,搜索 setBlock 和 setBlocks 函数,会发现它们都调用了 intFloor() 方法进行类型转换:
def setBlock(self, *args):
"""Set block (x,y,z,id,[data])"""
self.conn.send(b"world.setBlock", intFloor(args))
def setBlocks(self, *args):
"""Set a cuboid of blocks (x0,y0,z0,x1,y1,z1,id,[data])"""
self.conn.send(b"world.setBlocks", intFloor(args))
intFloor() 会将所有参数强制转换为整数,这正是导致新版命名空间ID无法正常工作的罪魁祸首。
2.3 实施修复方案
修改这两个函数,移除 intFloor 调用,直接传递原始参数:
def setBlock(self, *args):
"""Set block (x,y,z,id,[data])"""
self.conn.send(b"world.setBlock", args)
def setBlocks(self, *args):
"""Set a cuboid of blocks (x0,y0,z0,x1,y1,z1,id,[data])"""
self.conn.send(b"world.setBlocks", args)
保存文件后,建议在同一目录创建 __init__.py 文件(如果不存在),确保修改能被正确加载:
# /usr/local/lib/python3.9/site-packages/mcpi/__init__.py
from .minecraft import Minecraft
from . import block
from . import entity
from . import event
from . import util
from . import vec3
3. 测试修复效果
3.1 基础功能验证
创建一个测试脚本 test_block.py :
from mcpi.minecraft import Minecraft
mc = Minecraft.create()
pos = mc.player.getTilePos()
# 使用命名空间ID放置方块
mc.setBlock(pos.x+1, pos.y, pos.z, "minecraft:diamond_block")
mc.setBlocks(pos.x+2, pos.y, pos.z,
pos.x+4, pos.y+2, pos.z,
"minecraft:redstone_block")
运行后应在游戏中看到钻石块和红石块组成的结构,证明基础功能已修复。
3.2 边界情况测试
为确保修改的健壮性,建议测试以下场景:
- 混合参数类型 :坐标使用浮点数,ID使用字符串
- 特殊方块 :含NBT数据的方块(如带文字的告示牌)
- 批量操作 :大规模
setBlocks调用性能
示例测试用例:
# 测试浮点坐标和特殊方块
mc.setBlock(pos.x+1.5, pos.y+0.3, pos.z-2.8,
"minecraft:oak_sign[rotation=8]{Text1:'Hello'}")
# 性能测试:生成100x100平台
import time
start = time.time()
mc.setBlocks(pos.x, pos.y-1, pos.z,
pos.x+99, pos.y-1, pos.z+99,
"minecraft:grass_block")
print(f"耗时:{time.time()-start:.2f}秒")
4. 高级应用与优化技巧
4.1 构建辅助函数库
为简化常用操作,可以创建自定义工具库。例如 mc_utils.py :
from mcpi.minecraft import Minecraft
from mcpi import block
class Builder:
def __init__(self, mc):
self.mc = mc
def pyramid(self, x, y, z, size, material):
"""生成金字塔结构"""
for i in range(size):
self.mc.setBlocks(x+i, y+i, z+i,
x+size*2-i, y+i, z+size*2-i,
material)
self.mc.setBlocks(x+i+1, y+i, z+i+1,
x+size*2-i-1, y+i, z+size*2-i-1,
block.AIR.id)
# 使用示例
mc = Minecraft.create()
builder = Builder(mc)
pos = mc.player.getTilePos()
builder.pyramid(pos.x, pos.y, pos.z, 10, "minecraft:gold_block")
4.2 性能优化策略
当处理大型建筑时,可采用以下优化手段:
- 批量操作 :优先使用
setBlocks而非多次setBlock - 异步执行 :将耗时操作放入单独线程
- 区块预计算 :先在内存中构建结构数据,再一次性提交
示例异步生成器:
import threading
def async_build(mc, blueprint):
def worker():
for x, y, z, block_id in blueprint:
mc.setBlock(x, y, z, block_id)
threading.Thread(target=worker).start()
# 使用示例
blueprint = [(pos.x+i, pos.y, pos.z, "minecraft:glass") for i in range(100)]
async_build(mc, blueprint)
4.3 错误处理与日志记录
增强脚本的健壮性:
import logging
logging.basicConfig(filename='mc_script.log', level=logging.INFO)
def safe_set_block(mc, x, y, z, block_id):
try:
mc.setBlock(x, y, z, block_id)
logging.info(f"成功放置 {block_id} 在 ({x}, {y}, {z})")
except Exception as e:
logging.error(f"放置方块失败: {str(e)}")
# 自动重试或执行备用方案
5. 兼容性处理与未来维护
5.1 多版本兼容方案
如果需要同时支持新旧版本,可以实现版本检测和自动适配:
def smart_set_block(mc, x, y, z, block):
"""智能选择设置方块的方式"""
if isinstance(block, int): # 数字ID
mc.setBlock(x, y, z, block)
elif isinstance(block, str): # 命名空间ID
if hasattr(mc, '_modified_api'): # 已修复的库
mc.setBlock(x, y, z, block)
else: # 未修复的旧库
raise RuntimeError("需要先修复mcpi库以支持命名空间ID")
5.2 创建补丁系统
为方便团队协作和后续更新,可以制作自动化补丁脚本 patch_mcpi.py :
import os
import fileinput
def patch_mcpi_lib():
lib_path = os.path.dirname(os.__file__)
mcpi_path = os.path.join(lib_path, 'site-packages', 'mcpi', 'minecraft.py')
replacements = [
('self.conn.send(b"world.setBlock", intFloor(args))',
'self.conn.send(b"world.setBlock", args)'),
('self.conn.send(b"world.setBlocks", intFloor(args))',
'self.conn.send(b"world.setBlocks", args)')
]
for line in fileinput.input(mcpi_path, inplace=True):
for old, new in replacements:
line = line.replace(old, new)
print(line, end='')
if __name__ == '__main__':
patch_mcpi_lib()
print("mcpi库已成功打补丁!")
运行此脚本将自动完成所有必要的修改,无需手动编辑库文件。
更多推荐


所有评论(0)