Minecraft Java Edition 网页控制台机器人,纯 Node.js 实现,基于 Mineflayer + Express + SocketIO。 启动后在浏览器中可视化控制 Bot。
┌──────────────────────────────────────────────┐
│ Node.js 控制层 (server.js) │
│ - Express 静态文件服务 │
│ - SocketIO 实时 WebSocket 通信 │
│ - Mineflayer 协议代理 │
│ - Ollama AI 客户端 │
│ - AI 自主控制模块 │
│ - 聊天命令系统(**command) │
│ - 聊天日志记录 │
│ - 状态轮询 & 事件转发 │
│ │ TCP │
└────┼──────────────────────────────────────────┘
│
Minecraft 服务器
- Mineflayer 协议代理:Node.js Mineflayer 处理所有 MC 协议细节,兼容多版本
- Web 控制台:SocketIO 实时 Web 面板,可视化移动控制、视角转动、状态监控
- 控制台访问鉴权:网页控制台默认需要密码访问(
web_auth_enabled/web_password),防止未授权控制 - 画面渲染:集成 prismarine-viewer,在浏览器中实时渲染机器人第一人称视角画面
- 聊天监听与命令响应:监听公聊/私聊消息,响应
command_prefix开头的玩家指令 - AI 集成(Ollama / OpenAI 兼容 API):支持 AI 自动回复公聊/私聊(可配置回复模式)、AI 自主控制 Bot 行为(Function Calling),提供商可在 config 中切换
- 聊天日志记录:玩家聊天/系统消息/命令等按日期每天一个文件写入(本地零点自动切换),单个文件无大小限制,可通过 config 开关控制
- 权限控制:信任玩家白名单,可限制高风险指令仅信任玩家使用
- WASD 移动 & 寻路:方向移动、跳跃、疾跑、平面/空间寻路、持续跟随(地面/飞行自动切换、空中避障、载具追踪)
- 视角转动:D-pad 方向键/键盘箭头增量旋转视角,支持绝对角度设置和看向玩家
- 动作交互:攻击实体、挖掘方块、放置方块(射线精确计算放置面)、与方块/实体交互(开门/开箱/骑乘等)、使用物品、潜行、疾跑、丢物品、切格子
- 背包管理:背包物品移入快捷栏、装备/卸下物品(支持一键卸下全部)
- 实体交互:骑乘、飞行模式(创造/旁观,速度与原版一致)
- 状态查询:实时查询 Bot 位置/血量/饱食度/手持物品/潜行/疾跑/爬行/骑乘状态
- 自动恢复:死亡自动重生、断连自动重连(指数退避)、连接超时检测(15s)、Web 面板一键重启
mcbot-web/
├── server.js # 单文件入口:Express + SocketIO + Mineflayer + Viewer + Ollama AI
├── templates/
│ └── index.html # Web 控制台前端页面
├── config.json # 配置文件
├── config.example.json # 配置文件模板
├── package.json # Node.js 依赖
├── scripts/
│ └── example.js # 自定义脚本示例(**run example 运行)
├── tools/mp3midi/ # MP3 → MIDI 离线转换工具(Basic Pitch)
├── logs/ # 聊天日志目录(自动创建)
└── README.md
- Node.js 18+
- 目标 Minecraft 服务器需启用离线模式(offline mode)
- (可选)Ollama 本地运行,用于 AI 功能
git clone https://github.com/RSSeeker/mcbot-nodejs.git
cd mcbot-nodejs
npm install复制 config.example.json 为 config.json 并编辑:
{
"server": {
"host": "服务器地址",
"port": 25565,
"version": "1.21.4"
},
"bot": {
"username": "Bot名称",
"password": "登录密码(无密码留空)"
},
"command_prefix": "**",
"web_auth_enabled": true,
"web_password": "你的控制台密码",
"reply_mode": "whisper",
"track_players": ["玩家名1", "玩家名2"],
"trusted_players": ["玩家名1"],
"trusted_commands": ["ai", "aiclear", "aicontrol", "aidelay", "aimode", "aimodel", "aimodels", "attack", "cancel", "cmd", "dig", "drop", "dropall", "equip", "fly", "follow", "give", "goto", "help", "interact", "itemid", "jump", "look", "move", "movetohotbar", "pickblock", "ping", "place", "respawn", "restart", "rotate", "run", "scriptlist", "send", "slot", "sneak", "sprint", "stop", "unequip", "unequipall", "use", "usehold"],
"viewer_port": 3000,
"viewer_view_distance": 10,
"log_chat_enabled": true,
"log_dir": "./logs",
"ai_enabled": true,
"ai_provider": "ollama",
"ollama": {
"host": "http://localhost:11434",
"model": "qwen3:8b",
"system_prompt": "你是一个 Minecraft 游戏中的 AI 助手机器人。",
"timeout": 60000,
"max_history": 20
},
"external_api": {
"url": "https://api.openai.com/v1/chat/completions",
"api_key": "sk-你的API密钥",
"model": "gpt-4o-mini",
"system_prompt": "你是一个 Minecraft 游戏中的 AI 助手机器人。",
"timeout": 60000,
"max_history": 20
},
"keybindings": {
"forward": "w",
"left": "a",
"back": "s",
"right": "d",
"jump": " ",
"sneak": "shift",
"sprint": "control",
"drop": "q",
"interact": "e",
"attack": "f",
"pick_block": "b",
"fly": "v",
"rotate_left": "arrowleft",
"rotate_right": "arrowright",
"rotate_up": "arrowup",
"rotate_down": "arrowdown"
}
}| 字段 | 说明 |
|---|---|
server.host |
Minecraft 服务器地址 |
server.port |
服务器端口 |
server.version |
游戏版本 |
bot.username |
Bot 用户名 |
bot.password |
登录密码(离线模式留空) |
command_prefix |
游戏内指令前缀,可改为 !、/ 等 |
web_auth_enabled |
网页控制台是否要求密码,默认 true;设 false 关闭鉴权 |
web_password |
网页控制台访问密码;留空且鉴权开启时启动随机生成并打印在控制台 |
reply_mode |
AI 回复模式:whisper(私聊)或 public(公屏 @提问者) |
track_players |
追踪玩家列表,Bot 会跟随/响应这些玩家 |
trusted_players |
信任玩家白名单,空数组 [] 表示信任所有玩家 |
trusted_commands |
仅信任玩家可执行的指令列表(如 restart、cmd 等) |
viewer_port |
画面渲染 HTTP 端口,默认 3000 |
viewer_view_distance |
画面渲染区块视距,范围 2-20,默认 10 |
log_chat_enabled |
是否启用聊天日志记录,默认 true |
log_dir |
日志文件存放目录,默认 ./logs |
ai_enabled |
是否启用 AI 功能,设为 false 可完全关闭 |
ai_provider |
AI 提供商:"ollama" 或 "external_api"(默认 ollama) |
ollama.host |
Ollama 服务地址 |
ollama.model |
使用的 AI 模型名称 |
ollama.system_prompt |
AI 系统提示词 |
ollama.timeout |
AI 请求超时(毫秒) |
ollama.max_history |
每个会话保留的对话历史条数 |
external_api.url |
外部 API 地址(OpenAI 兼容格式),为空则禁用 |
external_api.api_key |
外部 API 密钥 |
external_api.model |
外部 API 模型名称 |
external_api.system_prompt |
外部 API 系统提示词 |
external_api.timeout |
外部 API 请求超时(毫秒) |
external_api.max_history |
外部 API 每个会话保留的对话历史条数 |
keybindings |
Web 键盘绑定配置,值设为 "" 可禁用该按键 |
npm start启动后在浏览器打开 http://localhost:5001(首次会提示输入控制台密码,即 config.json 的 web_password;关闭鉴权则无需输入),可视控制面板功能包括:
- 连接配置:网页顶部填写服务器/用户名/密码/画面端口/视距/追踪玩家等
- 画面渲染:点击"画面"按钮在浏览器中实时渲染 Bot 第一人称视角
- 移动控制:D-pad 方向键 + 跳跃/潜行/疾跑切换按钮,支持键盘快捷键(可在 config.json 中自定义按键绑定)
- 定时移动:独立的方向+时长模块,Bot 按指定方向移动指定毫秒后自动停止
- 视角转动:独立的视角 D-pad,键盘方向键控制,支持 Yaw/Pitch 精确输入和看向玩家/坐标
- 状态面板:实时显示坐标、血量、饱食度、视角、手持物品、潜行/疾跑/爬行/骑乘/飞行状态
- 物品栏:快捷栏 1-9 点击切换,一键移入背包物品
- 动作按钮:攻击、连击、挖掘、持续挖、放置、交互、使用、长按使用、丢弃、全丢、选取方块、飞行、取消、重生
- 定时动作:攻击/挖掘/长按使用 + 持续时间,到期自动停止
- 聊天面板:实时公聊/私聊/系统消息,支持聊天输入和 Minecraft 指令执行
- AI 对话:与 AI 模型对话,支持模型切换下拉框、自动回复开关、历史清除
- 寻路/跟随:输入坐标或玩家名进行导航,支持跟随距离设置
- 装备控制:指定物品名装备到指定槽位,一键卸下全部
- Ping 模块:输入服务器地址(留空即当前服务器)查询服务器信息
- 重启:Bot 连接后一键进程级重启
| 命令 | 说明 |
|---|---|
**help |
列出所有可用命令 |
**send <消息> |
让 Bot 发送公聊消息 |
**cmd <指令> |
让 Bot 执行 Minecraft 指令 |
**ping [地址:端口] |
Ping 服务器(无参数=当前,有参数=外部服务器) |
**restart |
进程级重启 Bot |
**run <脚本名> [参数] |
运行 scripts/ 目录下的自定义 JS 脚本 |
**respawn |
重生 |
| 命令 | 说明 |
|---|---|
**move <方向> [毫秒] |
移动:forward/back/left/right,默认1000ms |
**jump |
跳跃 |
**stop |
停止所有移动和运行中的脚本 |
**goto <x> <z> |
平面寻路(保持当前高度);**goto <x> <y> <z> 空间飞行寻路(需创造/旁观模式,自动检测墙后/地下目标并绕行) |
**follow <玩家> [距离] |
持续跟随:地面走路,玩家上天/桥上时自动切换飞行,含避障、卡住自动脱困、远距离自动 /tp、载具追踪(**follow stop 停止) |
**fly [on/off] |
切换飞行模式(创造/旁观,水平 10.9 / 垂直 3.9 格/秒,与原版创造一致) |
| 命令 | 说明 |
|---|---|
**look <yaw> [pitch] |
设置绝对视角角度 |
**look at <玩家名> |
看向指定玩家 |
**rotate <水平°> [垂直°] |
旋转视角(增量角度,如 **rotate 90 -30) |
| 命令 | 说明 |
|---|---|
**attack [时间] |
攻击视线中的实体,时间参数指定长按毫秒数 |
**dig [时间] |
挖掘视线中的方块,时间参数指定长按毫秒数 |
**place |
放置方块(对准方块表面) |
**interact |
与方块/实体交互(开门/开箱/拉杆/村民交易/骑乘载具等) |
**use |
使用手持物品(快速点击) |
**usehold [时间] |
长按使用手持物品(吃东西等),默认2000ms |
**sneak |
切换潜行状态(蹲下/起身) |
**sprint |
切换疾跑状态 |
**drop |
丢出手持物品 |
**dropall |
丢出全部物品 |
**cancel |
取消所有操作 |
| 命令 | 说明 |
|---|---|
**slot <1-9> |
切换到快捷栏第 N 格 |
**equip <物品名> <槽位> |
装备物品到指定槽位(hand/off-hand/head/torso/legs/feet) |
**unequip <槽位> |
卸下指定槽位的物品 |
**unequipall |
一键卸下全部装备(背包有空间时) |
**movetohotbar |
将背包物品移入快捷栏的空位 |
**pickblock |
选取准星方块(创造模式直接拿,生存模式切背包) |
**itemid |
显示手中物品的名称和 ID |
**give <物品名> [数量] |
从创造物品栏获取物品(仅创造模式,数量 1-64) |
| 命令 | 说明 |
|---|---|
**ai <消息> |
与 AI 对话 |
**aimode [on/off] |
切换 AI 自动回复公聊 |
**aimodel [模型名] |
切换/查看 AI 模型 |
**aimodels |
列出可用 AI 模型 |
**aiclear |
清除 AI 对话历史 |
**aicontrol [on/off/status] |
AI 自主控制 Bot 行为 |
**aidelay <毫秒> |
设置 AI 自主控制间隔(1000-30000) |
指令前缀通过
config.json中的command_prefix修改。
启用 log_chat_enabled 后,日志按日期写入 log_dir 目录下的 chat_YYYY-MM-DD.log 文件(本地零点自动切换新一天的文件),单个文件无大小限制、按行追加记录。
日志记录的事件类型:
| 类型 | 内容 |
|---|---|
SYSTEM |
系统消息 |
CHAT |
玩家公聊 |
JOIN / LEAVE |
玩家进出 |
LOGIN / SPAWN |
Bot 登录/出生 |
KICK / DEATH / DISCONNECT |
Bot 状态变化 |
ERROR |
Bot 错误 |
BOT_CHAT / BOT_CMD |
网页端发送的聊天/指令 |
COMMAND / CMD_REPLY |
玩家命令及回复 |
AI_REPLY |
AI 自动回复 |
WHISPER |
Bot 私聊 |
ACTION |
Bot 执行的动作 |
通过 **run <脚本名> 命令运行 scripts/ 目录下的 JS 脚本,实现自定义机器人操控。
// scripts/your_script.js
module.exports = async function(bot, context) {
const { reply, args, log, config } = context;
// bot — Mineflayer Bot 实例,可调用所有 API
// context.reply(msg) — 回复消息给命令发送者
// context.args — 脚本参数数组
// context.log(level, msg) — 写入服务端日志
// context.config — 当前配置对象
// context.sleep(ms) — 可中断的等待,被 **stop 停止时会立即抛出
// context.isCancelled() / context.cancelled — 是否已被 **stop 中断
bot.chat('Hello!');
reply('脚本执行成功!');
};游戏内发送 **stop 会停止所有正在运行的脚本。脚本只需使用 context.sleep() 代替 setTimeout,或在循环里检查 context.isCancelled(),即可被 **stop 立即中断;不使用这些 API 的脚本会在下一次自身的检查点退出。
**run example
**run example 参数1 参数2- 网页控制台默认需要密码(
web_password),公网部署时请务必修改默认密码并保持鉴权开启(web_auth_enabled: true) - 建议将
run加入trusted_commands,仅信任玩家可执行 - 脚本拥有
bot完整控制权,请勿运行不可信来源的脚本
用 Spotify 的 Basic Pitch 把 MP3/WAV 转成
MIDI,再走 **run playmidi 演奏。转换后会自动做演奏向简化:合并同音高重叠音符、
复音数 ≤12、最短音长 ≥0.05s、量化到 20 ticks(120BPM / 480PPQ)。默认使用较灵敏的
转谱阈值(onset 0.3 / frame 0.15),主旋律和弱音不容易被漏掉;Basic Pitch 只转音高
不做鼓,所以另外用频段+打击分离粗提鼓点(basedrum/snare/hat,写入 MIDI 第 10 轨,
playmidi 会自动映射成打击乐音色),复杂混音下鼓提取是近似结果,可用 --no-drums 关闭。
另外,MIDI 长音在游戏里只会响一声就断,转换时会自动把 ≥0.5s 的长音按 0.15s 间隔拆成
连续的同音重复来模拟持续发声(--sustain 0 可关闭,间隔和门槛可调)。
Windows 上 basic-pitch 必须用 Python 3.10(3.11+ 会依赖 TensorFlow,Windows 没有
可用 wheel;3.10 走 onnxruntime)。项目已建好虚拟环境 .venv-mp3midi/,需要重装时:
py -3.10 -m venv .venv-mp3midi
.venv-mp3midi\Scripts\pip install -r tools\mp3midi\requirements.txt把音频文件放进项目根目录的 mp3/ 文件夹,然后:
.venv-mp3midi\Scripts\python tools\mp3midi\convert.py mp3\歌曲.mp3
.venv-mp3midi\Scripts\python tools\mp3midi\convert.py mp3\歌曲.mp3 --stem vocals| 参数 | 说明 |
|---|---|
--stem vocals|accompaniment |
先做 Spleeter/Demucs 人声分离再转谱(可选,需另装) |
--max-poly N |
最大复音数,默认 12 |
--min-note S |
最短音长(秒),默认 0.05 |
--grid T |
量化粒度(tick,120BPM / 480PPQ),默认 20 |
--onset F / --frame F |
Basic Pitch 起音/音框阈值(默认 0.3 / 0.15,越低越灵敏) |
--no-drums |
不提取鼓点 |
--sustain S |
长音重复间隔秒(默认 0.15,填 0 关闭,长音只响一声) |
--sustain-min S |
多长的音才算长音(默认 0.5s,短于它的不拆) |
-o 目录 |
输出目录,默认 midi/ |
结果输出到 midi/<歌名>.mid,游戏内直接:
**run playmidi <歌名>.mid播放时支持子文件夹与实时控制:
**run playmidi miditest/<歌名>.mid # 播放 midi/miditest/ 文件夹下的歌
**run playmidi list [文件夹] # 列出 midi/(或某子文件夹)下的 .mid 文件与子文件夹
**run playmidi next / prev # 播放中切到下一首 / 上一首
**run playmidi pause / resume # 播放中暂停 / 继续播放中再运行 **run playmidi <另一首歌> 会直接切换到那首歌并从头播放(自动恢复暂停、优先级高于 next/prev),
不会提示“正在播放中”。
列表/随机/上一首/下一首都只在“起始歌曲所在文件夹”内循环,不会跨文件夹;
子文件夹里的歌用 <文件夹>/<歌曲> 指定即可,无需提前登记。
游戏内也可以不手动转,直接用 playmusic 一条命令自动识别并播放(音频临时文件,播完即删)。
playmusic 为 DEMO 演示脚本:未经过长时间/多 bot 场景充分测试,转换耗时与效果因歌而异,
生产使用前请自行验证。用法:
**run playmusic <歌曲.mp3>
**run playmusic <歌曲.mp3> | 2 | pitch # 其余参数与 playmidi 相同,用 | 分隔
**run playmusic next / prev / pause / resume # 播放中控制正在播放的播放器(下一首/上一首/暂停/继续)playmusic 会自动识别文件类型并分配播放器;播放中再运行 **run playmusic <另一首> 会直接切到那首歌
(若是不同类型会先停掉旧的播放器再播新的,避免两个播放器并发冲突):
| 类型 | 查找位置 | 播放器 |
|---|---|---|
.nbs |
songs/ |
playnbs |
.mid / .midi |
midi/ |
playmidi |
| 音频(mp3/wav/flac/ogg/m4a/aac/opus) | mp3/(也支持绝对路径) |
自动转 MIDI 后 playmidi |
不带扩展名时依次尝试 songs/<名>.nbs → midi/<名>.mid → mp3/<名>.<音频格式>。
playnbs / playmidi 也都支持子文件夹(songs/子文件夹/<歌名>、midi/子文件夹/<歌名>),
列表/随机/上一首/下一首只在单个文件夹内循环。
音频文件会转进临时目录 midi/.playmusic/,播放结束、被
**stop 或出错后自动删除,不会在 midi/ 根目录留下文件。
提示:整首歌(人声+伴奏混在一起)转出来会比较“脏”。伴奏乐用 --stem accompaniment,
只要主旋律用 --stem vocals;失真重、鼓点密的歌建议先换伴奏版或降噪再转。
subbot 脚本用于生成/卸载可持久化的子 bot,并让它们执行指令。子 bot 是独立的 mineflayer 客户端
(offline 登录、自动注册/登录、切 unicode 键盘、传送到主 bot 本体),会话保存在主 bot 上。
**run subbot create | <名字> | [数量] # 生成子 bot(默认1个;数量>1 时名字+序号,如 foo、foo2、foo3)
**run subbot remove | <名字>... | all # 卸载子 bot(all 卸载全部)
**run subbot list # 列出所有子 bot 及状态
**run subbot run | <名字> | <指令> # 让子 bot 自己执行指令
**run subbot relay | <名字> | <**指令> # 把 ** 指令交给主 bot 框架执行
**run subbot help # 查看用法子 bot 是一个独立客户端:run 的 ** 指令由子 bot 自己执行(不再依赖主 bot 转发),
且子 bot 也会自己处理玩家私聊/公聊发给它的 ** 指令(仅限 trusted_players 里的玩家,未配置则不响应)。
run 的指令语义:
| 指令开头 | 行为 |
|---|---|
/xxx |
子 bot 直接发送,服务器以子 bot 身份执行该 MC 指令 |
**xxx |
子 bot 在自己连接上执行(独立 bot);不支持的用 relay 转给主 bot |
| 其他 | 子 bot 公聊发送 |
子 bot 自己支持的 ** 指令:**help、**cmd <MC>、**send <消息>、**msg <玩家> <消息>、
**go <玩家名>、**id、**quit。
例:
**run subbot create | worker | 3 # 生成 worker、worker2、worker3
**run subbot run | worker | /give @p diamond 5 # 让 worker 自己执行 /give
**run subbot run | worker | **cmd /time set day # 让 worker 自己执行 /time set day
**run subbot run | worker | **msg Steve hi # 让 worker 私聊 Steve
**run subbot relay | worker | **list # 交给主 bot 框架执行 **list
**run subbot remove | worker2 # 卸载 worker2注意:子 bot 名不能与主 bot 同名、不能含非法字符;主 bot 重启后 bot.__subbots 会清空,
请先用 **run subbot remove all 清理残留的在线子 bot。
playmidi / playnbs 开始播放前会优先复用 subbot 已生成的子 bot(bot.__subbots 里在线的):
够用就直接用它们当演奏小号,不足才新建;播放结束后只卸载本次新建的 bot,保留已存在的子 bot。
例:先用 **run subbot create | worker | 3 生成 3 个子 bot,再 **run playmidi <歌>——
单曲需要不到 3 个 bot 时会直接复用 worker/worker2/worker3,不再重复登录小号,播完也不卸载它们。
Bot 启动后 15 秒内未成功连接服务器,会自动断开并提示超时,避免进程卡死。
- mineflayer — Minecraft 协议客户端库
- mineflayer-pathfinder — 寻路与移动插件
- prismarine-viewer — 基于 Three.js 的 Minecraft 世界渲染器
- @napi-rs/canvas — Rust 实现的 Canvas 库,为 viewer 提供渲染后端
- webpack — 模块打包工具,用于构建 viewer 前端资源
- express — HTTP 服务器
- socket.io — WebSocket 实时通信
MIT
