前言

最近在“香草纪元”这个 Minecraft 整合服里尝试做一个游戏 Agent。最开始的想法其实很简单:能不能让一个 Bot 像普通玩家一样进入服务器,然后我在游戏里对它说“跟着我”“收菜”“去钓鱼”,它就能自己做对应的事情。

如果只是让 AI 回答游戏里的聊天内容,这件事并不复杂。但真正麻烦的地方在于:它不是只要会说话,而是要真的在 Minecraft 世界里行动。

也就是说,这个 Bot 至少需要做到:

  • 能够登录 Forge 1.20.1 整合服;
  • 能够监听游戏聊天,并识别指定玩家的指令;
  • 能够移动、跟随、战斗、种田、钓鱼、吃东西;
  • 能够在卡住、低血量、掉线时进行恢复;
  • 能够被外部 Agent 通过 MCP 或 HTTP API 调用。

这篇文章主要记录这个项目目前的实现思路和踩坑过程。它更像是一篇项目记录,而不是一个从零到一的完整教程。

项目目标

这个项目目前叫 Renge Bot,定位是一个面向 Minecraft Forge 整合服的半自主游戏 Agent。

它和普通的命令机器人不太一样。普通机器人可能只是执行 /say/tp 之类的服务器命令,而 Renge Bot 的目标是尽量像一个真实玩家一样做事。

例如玩家在游戏中发送:

1
收菜

Bot 不应该只是回复“好的,我去收菜”,而是应该:

  1. 识别发送指令的玩家是否有权限;
  2. 停止当前任务;
  3. 移动到玩家附近或目标区域;
  4. 扫描附近成熟作物;
  5. 走到作物旁边;
  6. 挖掉成熟作物;
  7. 尝试补种;
  8. 把执行结果反馈给玩家。

这才比较接近一个“游戏 Agent”的使用体验。

基本项目结构

目前项目主体是 Node.js 写的,核心目录大致如下:

1
2
3
4
5
6
7
8
9
10
11
botFormc
├── bot.js # Bot 入口
├── cli.js # 本地 CLI 控制工具
├── src
│ ├── minecraft-bot.js # Mineflayer 登录与事件处理
│ ├── controller.js # 指令调度与任务控制
│ ├── movement-service.js # 统一移动与寻路执行
│ ├── armor-equipment.js # 自动装备盔甲
│ └── tasks # 各类游戏行为任务
├── forge-bridge # 服务端 Forge World Bridge
└── README.md

其中 Node.js 这边负责:

  • 登录服务器;
  • 接收聊天指令;
  • 管理任务;
  • 控制 Bot 行为;
  • 提供 MCP、HTTP API 和 CLI。

forge-bridge 则是一个只安装在服务端的 Forge Mod,主要用于解决 Mineflayer 在大型 Forge 整合服里无法可靠读取世界信息的问题。

为什么需要 World Bridge

一开始我以为 Mineflayer 可以直接解决大部分问题。毕竟它本身就支持登录 Minecraft,理论上也能读取方块、实体、背包、血量等信息。

但实际接入 Forge 1.20.1 整合服之后,很快就遇到了一个关键问题:整合服的方块状态表和原版并不完全一致。

在这个服务器里,Mod 数量很多,Forge 会扩展方块和物品注册表。Mineflayer 对原版协议支持比较成熟,但面对复杂的 Forge 方块 ID 时,经常会出现:

1
2
3
bot.blockAt() 返回 null
bot.findBlocks() 找不到方块
pathfinder 认为前面没有可走路线

这会直接导致一个很明显的问题:Bot 明明站在地上,前面也有路,但它就是不会走,或者走着走着开始发呆。

为了解决这个问题,项目里加了一个服务端 Forge World Bridge。

它的作用不是帮 Bot 作弊修改世界,而是提供一个可靠的“世界感知接口”。因为它运行在服务端内部,所以能够直接读取服务端真实的方块、碰撞箱、实体和维度信息。

目前 World Bridge 提供的能力包括:

  • 查询指定坐标的方块;
  • 批量查询方块;
  • 查询实体;
  • 根据服务端真实碰撞信息规划路径;
  • 给 Bot 返回可走、可跳、可下落、可开门、可游泳的路径节点。

这样一来,Bot 不再完全依赖 Mineflayer 对区块的解析,而是可以把服务端作为权威数据来源。

当前交互方式

Renge Bot 目前支持几种控制方式。

第一种是游戏内聊天指令。例如:

1
2
3
4
5
6
跟着我
收菜
巡逻
钓鱼
状态
回家

只有白名单玩家的消息会被响应,避免服务器里其他玩家随便控制 Bot。

第二种是本地 CLI,例如:

1
2
3
4
node cli.js status
node cli.js task QDcvd follow
node cli.js task QDcvd farm
node cli.js stop

第三种是 HTTP API。CLI 本质上也是通过 HTTP API 控制已经运行的 Bot,而不是再启动一个新的 Bot 进程。

第四种是 MCP。这样外部 AI Agent 可以把这个 Minecraft Bot 当成一个工具来调用,例如查询状态、发送聊天、启动任务、停止任务等。

这一点比较重要,因为它让 Renge Bot 不只是一个 Minecraft 脚本,而是可以接入更大的 Agent 工作流。

已经实现的行为

目前 Bot 已经实现了一批基础行为,包括:

行为说明
follow跟随指定玩家
idle停止当前任务并待命
farm收获并补种原版成熟作物
fishing寻找水面并循环钓鱼
melee_attack攻击附近敌对生物
patrol巡逻并遇敌攻击
eat血量或饥饿值较低时吃东西
pickup拾取附近掉落物
place_torch在低光照区域插火把
shear剪羊毛
milk给牛挤奶
feed_animal喂养动物
sleep找床睡觉
panic低血量、着火或掉入危险区域时脱困

另外还加了一个比较实用的小功能:如果 Bot 背包里有盔甲,会自动选择更好的盔甲并装备。

这个功能看起来不大,但在实际游戏里很有用。因为 Bot 经常要巡逻、打怪、种田,如果玩家给了它钻石甲,它应该自己穿上,而不是把盔甲一直放在背包里。

行为优先级

Bot 的行为不是简单地按顺序执行,而是分了优先级。

目前大致是:

1
PANIC > CORE > WORK > REST > IDLE

也就是说,如果 Bot 正在种田,但突然血量过低,PANIC 会覆盖当前任务,优先执行脱困或回血逻辑。

这个设计主要是为了避免 Bot 过于“死板”。真实玩家在游戏里也不会在被僵尸围住的时候还坚持收菜,Bot 也应该有类似的反应。

不过这里也需要控制好边界。比如不是所有任务都应该自动攻击怪物,否则玩家只是让它跟随,它却一路追僵尸跑远了,体验反而会变差。

所以后面把攻击逻辑尽量收敛到巡逻、战斗等明确任务里,而不是让所有行为都默认带攻击性。

寻路问题是最大的坑

这个项目目前最折腾的部分不是聊天识别,也不是 MCP,而是寻路。

一开始使用的是 Mineflayer 常见的 pathfinder 思路,但在 Forge 整合服里问题很多。典型表现包括:

  • Bot 走到一格高方块旁边突然变慢;
  • 明明前面是小径,但它一直顶着方块往前走;
  • 走到半砖、台阶、边缘地形时开始卡住;
  • 有时候能走,有时候同一段路又不动了。

这个现象本质上不是“AI 不聪明”,而是 Bot 对世界碰撞和路径节点的理解不够接近服务端真实情况。

后来参考了 Touhou Little Maid 这类实体 AI 的思路。女仆实体的移动不是简单地走到每个方块中心点,而是会结合服务端碰撞箱、下一节点高度、跳跃时机和移动控制器来决定动作。

因此 Renge Bot 的寻路后来改成了更接近下面这种方式:

  1. 由服务端 World Bridge 规划路径;
  2. 路径节点带上 walkjumpfalldoorswim 等动作类型;
  3. Bot 不再死盯每个方块中心,而是提前看向下一个有效节点;
  4. 遇到需要跳跃的节点时提前起跳;
  5. 如果卡住,会把失败节点加入避让列表并重新规划;
  6. 远距离或跨维度时仍然使用 RCON 传送,近距离优先正常行走。

这套逻辑不等于完整移植女仆 Mod,因为 Mineflayer Bot 本质上仍然是一个玩家实体,而不是服务端 Mob 实体。玩家移动要走客户端输入、速度、碰撞同步这一套机制,不能完全照搬 Mob 的 MoveControl

但参考女仆 AI 的思路之后,至少可以明确一个方向:不要把 Minecraft 寻路理解成“二维网格走格子”,而要把它理解成“带碰撞箱和动作类型的三维移动问题”。

种田逻辑的调整

种田也是一个比较典型的例子。

最开始我想让 Bot 像女仆一样自动扫描附近田地,然后直接收获。但实际测试时发现,如果 Bot 只是拿到一批成熟作物坐标,然后不停传送到每个坐标挖掉,这虽然效率很高,却不像真实玩家。

玩家正常收菜一般会:

  • 先走到田边;
  • 看附近有没有成熟作物;
  • 一排一排处理;
  • 遇到水渠、台阶、小路时绕过去;
  • 收完之后再补种。

所以后续逻辑应该尽量改成“先规划路线,再按路线走过去交互”,而不是每个作物点都直接传送。

目前项目里的策略是:远距离可以传送到玩家附近,避免 Bot 半路丢失;但具体执行任务时,优先使用正常移动。只有在跨维度、距离过远、寻路失败或紧急脱困时,才使用 RCON 传送兜底。

目前的效果

目前 Renge Bot 已经可以正常进入服务器,并通过游戏内中文指令执行任务。

例如玩家可以直接说:

1
跟着我

Bot 会移动到玩家附近并开始跟随。

说:

1
巡逻

Bot 会切换到巡逻任务,并在需要时拿出攻击性武器。

说:

1
收菜

Bot 会尝试寻找附近成熟作物并执行收获逻辑。

同时,本地也可以通过 CLI 查询状态:

1
node cli.js status

这样可以看到 Bot 当前坐标、血量、任务状态、World Bridge 是否可用等信息。

当前限制

这个项目虽然已经能跑,但还不能说非常完美。

目前比较明显的限制包括:

  • Forge 整合服中部分模组方块仍然需要额外适配;
  • 钓鱼依赖鱼漂和粒子事件,在模组服上可能不如原版稳定;
  • 复杂地形下寻路仍可能卡住;
  • 部分交互动作仍需要根据玩家真实操作习惯继续微调;
  • World Bridge 需要安装到服务端,因此它不是一个完全纯客户端方案。

不过这些限制基本都属于可以继续迭代的问题。相比一开始 Mineflayer 在整合服里连方块都读不准,现在已经有了一个比较清晰的架构:Mineflayer 负责玩家身份和游戏交互,World Bridge 负责服务端真实世界感知,行为系统负责把玩家指令拆成具体动作。

总结

Renge Bot 这个项目本质上不是一个简单的 Minecraft 脚本,而是一次把 AI Agent 接入真实游戏环境的尝试。

在这个过程中,最有意思的地方是:很多看起来很简单的玩家行为,真正让 Bot 去做时都会变得复杂。

例如“收菜”不是一个单独动作,而是感知、寻路、判断成熟度、挖掘、补种、避障、反馈的组合。

“跟着我”也不是一句命令,而是持续追踪玩家位置、处理距离、维度、卡住、怪物和地形变化的过程。

这也是游戏 Agent 比普通聊天 Agent 更有意思的地方。它不只是生成文本,而是要在一个有物理规则、有状态变化、有失败可能的世界里行动。

目前 Renge Bot 还在继续调整,尤其是寻路和真实玩家行为模拟这一块。后面如果继续完善,可以考虑加入更自然的采集、建造、背包整理、任务队列和长期自主行为。

如果最终能做到玩家在游戏里随口说一句“帮我把这片地整理一下”,Bot 就能真的理解现场并开始干活,那就有点像把一个小型 AI 助手塞进了 Minecraft 世界里。