学生端 · STUDENT
🐍 Python API 速查手册
在编辑器里,所有积木最终都会翻译成 Python。本页是 vm 全局对象的完整速查手册——你可以直接写 Python 调用它们,或在"嵌入 Python
脚本"积木中混搭。
0. 运行环境(必看)
Python 由 Pyodide(浏览器内的 WebAssembly 解释器)执行,不在服务器上跑。这件事的实际影响:
- 不会拖垮服务器:哪怕你不小心写了
while True,受影响的只是你自己的浏览器标签。 - 调用游戏的语句被批量发送:
vm.createBlock()这样"影响游戏世界"的方法会先攒在一个命令队列里,整个脚本跑完之后通过POST /api/mc/execute一次性发到服务器执行。所以你看到方块"瞬间出现一片",不是一个一个出现。 - 循环非常便宜:100 万次循环都在浏览器里,服务器侧没有任何开销——只在结束时拿到最终的命令列表。
vm.wait()会切断批次:把"等待之前"作为一个批次发走,"等待之后"再开新批次。这是少数会"阻塞"脚本流的语句。- 事件回调是异步的:
vm.onEvent注册后立刻返回;玩家在游戏里触发条件时,事件回调会被异步调用。
1. 命名空间(值对象)
这些是"取值用"的常量集合。直接当成 Python 对象的属性访问即可,IDE 即使没补全也不会出错——只要服务器认识这个名字就行。
| 命名空间 | 用途 | 常见示例 |
|---|---|---|
Block |
方块/材质 | Block.STONE, Block.OAK_PLANKS, Block.AIR,
Block.NOTHING
|
Item |
物品 | Item.APPLE, Item.DIAMOND_SWORD, Item.DIAMOND_CHESTPLATE
|
Entity |
实体/生物 | Entity.COW, Entity.ZOMBIE, Entity.VILLAGER |
Direction |
朝向(含"左右"等相对方向) | Direction.LEFT, Direction.RIGHT, Direction.UP,
Direction.DOWN, Direction.NORTH, …
|
Side |
侧面(贴块) | Side.UP, Side.NORTH… |
Compass |
罗盘方位 | Compass.N, Compass.S, Compass.E, Compass.W
|
Position / Coordinate |
位置标识 | Position.START, Position.MARK |
📌 多材质循环把 列表
当成"材料"参数即可,建造时会按列表顺序循环取材。例:
vm.createWall(20, 4, [Block.OAK_PLANKS, Block.BIRCH_PLANKS, Block.SPRUCE_PLANKS])
会拼出三色横纹墙。
2. 光标 & 坐标
"光标"是建造方块时的活动笔尖,初始落在玩家脚下。它有 x / y / z、朝向、俯仰角三组状态。理解光标是写好建造脚本的关键。
2.1 属性(直接读)
vm.x,vm.y,vm.z—— 光标当前坐标(int)vm.getX(),vm.getY(),vm.getZ()—— 方法版(一样的值)vm.getPlayerName()—— 当前玩家游戏名vm.getTimeOfDay()—— 世界当前时间(tick;0=日出,6000=正午,12000=日落,18000=午夜)
2.2 位置对象(VisualModder 兼容)
下面三个方法返回 Location 对象(不是数字!)。Location 同时支持 VisualModder 风格的
getX()/getY()/getZ()/getYaw()/getPitch() 和 Pythonic 属性 .x/.y/.z/.yaw/.pitch。
vm.getPlayerPosition() / vm.getPlayerLocation()
脚本开始时玩家的位置(含真实 yaw/pitch)。积木对应:
📊 状态 分类下"玩家 X/Y/Z 坐标"。
vm.getCursorPosition() / vm.getPosition()
光标当前位置(含 yaw/pitch)。积木对应:
📊 状态 分类下"光标 X/Y/Z 坐标"。# 三种取法等价:
player = vm.getPlayerPosition()
x1 = player.getX() # VisualModder 风格
x2 = player.x # Pythonic 属性
x3 = vm.getPlayerPosition().getX() # 直接链式
# 解构:
px, py, pz = vm.getPlayerPosition()
# 用法:在玩家头顶 5 格画块石头
p = vm.getPlayerPosition()
vm.setBlock(p.x, p.y + 5, p.z, Block.STONE)
2.3 移动方法
vm.setCursor(x, y, z)
把光标绝对定位到指定坐标。
vm.moveTo(dx, dy, dz) 或 vm.moveTo(n,
Direction.XXX)
相对平移光标。两种调用:分量式(dx/dy/dz)/ 方向 + 步数。
vm.stepForward(n=1)
沿光标当前朝向向前走 n 步(受 yaw + pitch 影响)。
vm.goDir(n, direction)
朝指定方向走 n 步(与光标当前朝向无关)。
vm.setDirection(direction)
设置光标朝向:罗盘方位(N/S/E/W)或左右。
vm.changeDirection(degrees=90)
基于当前朝向相对旋转 N 度(正数顺时针)。
vm.setInclination(deg) / vm.changeInclination(delta)
设置/调整俯仰角。正数向上看,负数向下看。配合
stepForward 可以"斜着走"。vm.markPosition() / vm.goToMark() /
vm.goToStart()
书签三连:把当前位置存进"标记"、跳回标记、跳回脚本开始时的起始点。
2.4 例:用光标"画"一段台阶
vm.setMaterial(Block.OAK_PLANKS)
for i in range(10):
vm.createBlock()
vm.moveTo(1, Direction.FORWARD) # 前进一格
vm.moveTo(1, Direction.UP) # 上升一格
3. 建造方块
所有"建造类"方法都参考光标的位置与朝向。如果你先调用 vm.setMaterial(Block.XXX),后面不显式传材料的建造方法会自动用它。
3.1 单块/区域
vm.setMaterial(mat) / vm.clearMaterial()
设置/清空"当前建造材质"。
vm.createBlock(block_type=None)
在光标处放一个方块(不传材料就用 setMaterial 设的)。
vm.setBlock(x, y, z, block_type)
不依赖光标,绝对坐标放方块。
vm.fillBlocks(x0, y0, z0, x1, y1, z1, block_type)
填充两点之间的长方体(包含端点)。比循环放方块快得多。
3.2 平面 / 立体
vm.createLine(length, block_type=None)
沿光标当前朝向画一条直线。
vm.createSquare(size, filled, block_type) / vm.createRectangle(w, h, filled, block_type)
正方形/矩形。
filled=True 实心;False 只画边框。vm.createFloor(w, d, block_type)
铺地板(水平面)。
w=宽,d=深。vm.createWall(w, h, block_type)
立一面墙。
vm.createBox(w, h, d, block_type)
空心长方体(六个面)。
vm.createFillBox(w, h, d, block_type)
实心长方体(等同 fillBlocks 的便捷版)。
3.3 曲线 / 几何
vm.createSphere(r, block_type)
球体(光标为球心)。
vm.createCircle(r, filled=True, block_type=None)
水平面上的圆。
vm.createArc(rx, ry, arc_angle, filled, block_type)
椭圆弧。
arc_angle:单位为度,360 即闭合椭圆。vm.createPolygon(sides, rx, ry, arc_angle, filled,
block_type)
多边形或扇形。
vm.createEllipse(a, b, filled, block_type)
椭圆。a/b 是长短半轴。
vm.createStar(points, ir, or, filled, block_type)
星形。points=尖角数;ir/or=内外半径。
3.4 文字 / 像素图
vm.createText(text, size, border_only, block_type)
把文字以"像素"形式拼出来(每像素一个方块)。size 单位为"像素行高"。
vm.createDrawing(grid, materials, material_index=1,
origin=None)
字符串列表当像素图。每个字符对应
materials[字符]。# 三层像素图:1 = 边框石头,0 = 空气
grid = [
"111",
"101",
"111",
]
vm.createDrawing(grid, [Block.AIR, Block.STONE])
3.5 杂项
vm.createChest(item_type)
放一个宝箱并塞入指定物品。
4. 玩家控制
vm.teleportPlayer(x, y, z)
把玩家传送到坐标(不会改变光标)。
vm.giveItem(item_type, amount=1)
给玩家发物品。
vm.giveEquipment(armor_type)
直接装备到对应槽位(盔甲/盾牌)。
vm.setItemInHand(hand, item_type)
把物品塞进主/副手。
hand 取 'main' / 'off'。vm.setGamemode(mode)
改游戏模式:
'survival' / 'creative' / 'adventure' / 'spectator'。vm.healPlayer() / vm.setHealth(amount)
完全治愈 / 设置血量(单位:颗心;20=满血)。
vm.addEffect(effect, duration=30, level=1) / vm.clearEffects()
添加药水效果(持续秒数)/ 清空全部效果。
vm.setFly(enabled) / vm.setXpLevel(level)
开关飞行 / 设置经验等级。
5. 世界 & 时间
vm.setTime(time_type)
日 / 夜 / 黎明 / 黄昏 / 正午 / 午夜。也可传 tick 数值(0-23999)。
vm.setWeather(weather_type)
'clear' / 'rain' / 'thunder'。vm.setDifficulty(difficulty)
'peaceful' / 'easy' / 'normal' / 'hard'。vm.spawnEntity(entity_type)
在光标位置召唤生物。
vm.explode(x, y, z, power=3) / vm.summonLightning(x, y, z)
爆炸 / 雷击。
vm.wait(seconds) / vm.waitRandom(min_sec,
max_sec)
代码内延迟。会切断命令批次——之前的命令立刻发送,之后的命令重新攒。
6. 消息 & 音效
vm.sendMessage(message)
在玩家聊天栏发消息(只发给自己)。
vm.printTitle(title, subtitle="")
屏幕正中大字。慎用——会盖视野。
vm.sendActionbar(message)
动作栏消息(物品栏上方)。比 title 温和。
vm.broadcast(message)
全服广播(所有玩家都看得到)。
vm.playSound(sound_name)
播放指定音效。
vm.playRecord(record_name)
播放唱片(背景音乐型)。
vm.stopSound()
停止所有正在播的音效与唱片。
vm.playNote(instrument, note)
播放红石音符。可以用循环写一段旋律。
7. 世界状态查询
vm.isCurrentBlock(block_type)
光标当前位置是不是指定材质。返回
True/False。vm.getBlockType(x, y, z)
读取某坐标的材质,返回字符串如
"STONE"。vm.isStandingOn(block_type)
玩家是不是站在指定材质上。
vm.isHolding(item) / vm.hasItem(item) / vm.isPlayerFlying()
手持 / 背包 / 飞行 状态。
8. 事件监听
当玩家在 Minecraft 里发言、放置/破坏方块、右键交互时,让 Python 自动跑一段。
vm.onEvent(event_type, filter_str='', *var_names)
event_type 取
chat / break / place / interact;filter_str
过滤条件(如发言含某字、特定方块类型);var_names 是事件传给回调的变量名(如 "player"、"msg")。
vm.onEventEnd()
结束当前事件块(积木自动处理;纯 Python 写法需要手动调用)。
vm.clearEvents()
注销所有事件监听。下次"运行"也会自动清空。
# 监听:聊天里说"打招呼"就回一句
vm.onEvent("chat", "打招呼", "player", "msg")
def _():
vm.sendMessage(f"你好 {player}!你说的是:{msg}")
vm.onEventEnd()
9. 持久值
vm.saveValue(key, val) / vm.readValue(key)
在本玩家命名空间下读写一个键值,跨脚本运行、跨会话保留。
# 记住玩家造了几次塔
count = vm.readValue("tower_count") or 0
count += 1
vm.saveValue("tower_count", count)
vm.sendMessage(f"这是你第 {count} 次造塔!")
10. 烹饪手册(Cookbook)
10.1 用列表轮换材质做彩虹墙
palette = [
Block.RED_STAINED_GLASS,
Block.ORANGE_STAINED_GLASS,
Block.YELLOW_STAINED_GLASS,
Block.GREEN_STAINED_GLASS,
Block.BLUE_STAINED_GLASS,
Block.PURPLE_STAINED_GLASS,
]
vm.createWall(30, 6, palette)
10.2 随机散布的小树林
import random
vm.setMaterial(Block.OAK_LOG)
for _ in range(30):
dx = random.randint(-15, 15)
dz = random.randint(-15, 15)
vm.setCursor(vm.x + dx, vm.y, vm.z + dz)
# 树干 4 高
for _ in range(4):
vm.createBlock()
vm.moveTo(1, Direction.UP)
# 简单树冠
vm.setMaterial(Block.OAK_LEAVES)
vm.createSphere(2)
vm.setMaterial(Block.OAK_LOG)
10.3 用条件读取脚下方块决定接下来怎么走
vm.setMaterial(Block.GRASS_BLOCK)
for i in range(50):
here = vm.getBlockType(vm.x, vm.y - 1, vm.z)
if here == "WATER":
# 遇水就架桥
vm.setCursor(vm.x, vm.y - 1, vm.z)
vm.createBlock(Block.OAK_PLANKS)
vm.setCursor(vm.x, vm.y + 1, vm.z)
vm.moveTo(1, Direction.FORWARD)
10.4 让游戏成为"猜数游戏"主持人
import random
target = random.randint(1, 100)
vm.saveValue("guess_target", target)
vm.broadcast("🎯 我心里想了一个 1~100 的数。聊天框猜!'高 / 低' 提示。")
vm.onEvent("chat", "", "player", "msg")
def _():
t = vm.readValue("guess_target")
try:
n = int(msg)
except:
return
if n == t:
vm.broadcast(f"🎉 {player} 猜中了!是 {t}")
vm.clearEvents()
elif n < t:
vm.sendMessage("太低啦 ↓")
else:
vm.sendMessage("太高啦 ↑")
vm.onEventEnd()
10.5 演示"等待切批次"
for layer in range(5):
vm.createSquare(6, True, Block.STONE)
vm.moveTo(1, Direction.UP)
vm.wait(1) # 每盖一层等 1 秒:玩家会看见塔逐层升起,而不是一闪而成
11. 常见错误与排查
| 现象 | 可能的原因 | 解法 |
|---|---|---|
| 运行没反应 | 用户名没填、服务器掉线、被冻结 | 检查顶部用户名 = 游戏名;问老师;解冻 |
| 方块都堆在一个位置 | 循环里没移动光标 | 在循环体里加一次 vm.moveTo 或 vm.stepForward |
| 事件监听不响应 | 没调 vm.onEventEnd();上次"运行"已注销 |
纯 Python 必须显式 onEventEnd;积木自动处理 |
| 浏览器卡死 | 死循环 | 关闭/刷新标签;用事件代替"持续轮询" |
| 方块类型不识别 | 名字拼错(大小写/下划线) | 查 积木手册,从下拉里选;或服务器版本不含该方块 |
⚠️ 不要在脚本里写
while True
或没出口的死循环它会让你自己的浏览器卡死。需要"持续生效"的场景请用事件监听(vm.onEvent)。