From c80b06552f30391afd1fedc944bcdcc125ab4569 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Sat, 26 Sep 2026 10:50:21 +0800 Subject: [PATCH] =?UTF-8?q?plan.md=EF=BC=9A=E7=AB=8B=E8=B5=B7=E6=9C=80?= =?UTF-8?q?=E9=A1=B6=E5=B1=82=E7=9B=AE=E7=9A=84=20=E2=80=94=E2=80=94=20?= =?UTF-8?q?=E7=BB=99=20agent=20=E4=B8=80=E5=89=AF=E8=83=BD=E5=9C=A8=20MC?= =?UTF-8?q?=20=E9=87=8C=E6=84=9F=E7=9F=A5=E4=B8=8E=E8=A1=8C=E5=8A=A8?= =?UTF-8?q?=E7=9A=84=E5=B7=A5=E5=85=B7=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户定调:插件目的是「让 agent 可以借助我们提供的工具包去玩我的世界」。 推论三条(改变工程重心): ① API 形状要照 LLM 用法设计,不是照程序员用法 (mineflayer 是给写 bot 的人用的库;我们面向 LLM 直接调用) ② 感知 + 行动缺一不可 ⇒ 状态/事件/操作三层是正式骨架 ③ 渲染是工具之一,不是全部 —— 之前把它当主线是重心错了 新增: §1c 空白测试服(不用现役服;现役 world 15G + mods 64,测不出边界) §1d 面向 LLM 的 API 形状(自省 / 可读返回 / 限量 / 失败要说清为什么) §6 里程碑重排:M0 测试服 → M1 修构建 → M2 协议客户端(真正的门槛) 细渲染降到 M8(已能跑,只是接不上服务端真数据) 拍照降为 M9(验证工具包的用例,不是工具包本身) 已核实的关键事实(写入 plan): · mineflayer 自述 'create minecraft bots with a stable, high level API' 41 个 plugins 全是动作与感知,grep 行为树/目标选择 = 0 命中 ⇒ 它是给 bot 开发者的库;决策在它之外,那是我们该留给 agent 的部分 --- plan.md | 124 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 107 insertions(+), 17 deletions(-) diff --git a/plan.md b/plan.md index 5782f04..a366ddb 100644 --- a/plan.md +++ b/plan.md @@ -5,7 +5,37 @@ --- -## 0. 目标(用户定向,按时间顺序) +## 0. 目的(最顶层,2026-09-26 用户定调) + +> 因为我们的这个插件目的就是为了**让 agent 可以借助我们提供的工具包去玩我的世界**。 + +★ **这是最顶层的目的,下面所有东西都是为它服务的手段。** + +``` +我们提供:一副「能在 MC 世界里感知 + 行动」的**工具包** +agent 提供:决策(该干什么、去哪、为什么)—— 我们**不替它决定** +``` + +推论(三条,改变工程重心): + +1. **工具形状要照 LLM 的用法设计,不是照程序员的用法。** + mineflayer 是 `create minecraft bots with a stable, high level API` —— + 它是给**写 bot 的人**用的库;我们面向的是 **LLM 直接调用**。 + 差别很实:参数要自解释、返回要可读、错误要说清"为什么不行", + 而不是抛个异常让调用者去读栈。 +2. **「能感知 + 能行动」两者缺一不可。** + 只有感知(渲染)⇒ agent 是个观众; + 只有行动(操作)⇒ agent 是瞎子。 + 所以 §1b 的「状态 / 事件 / 操作」三层是**工具包的正式骨架**, + 不是"以后再补"。 +3. **渲染是工具之一,不是全部。** + 细渲染(出图)是工具;粗渲染(常驻感知)是工具; + `move` / `dig` / `place` / `chat` 也是工具。 + 之前把它当主线,是重心错了。 + +--- + +## 0b. 目标(用户定向,按时间顺序) 1. **照相机式渲染**:给一个世界(存档数据 / 服务端),渲染出图。 - 用户原话(2026-09-25):「不起完整客户端」——抽出 MC 的**渲染能力**, @@ -167,6 +197,57 @@ bot.saveScreenshot WorldRenderer.screenshot() 细渲染(单次调 --- +## 1c. 空白测试服(用户 2026-09-26 定向) + +> 我觉得可以**起一个空白新服**用来测试功能,而不是用现在的服。 + +**理由(不只是"干净")**: +- 现有服 `/home/minecraft`:world 15G、mods 64 个、neoforge 1.21.1 —— + 任何协议层改动都可能污染它,且**测不出边界**(模组太多、状态太杂)。 +- 我们要验的是**协议与行为**,需要**可预期**的环境:已知方块集、已知出生点、 + 可重置的世界。 + +**形态(待定,需你定)**: + +| 项 | 选项 | +|---|---| +| 版本 | vanilla 1.21.1(最简,协议最干净) / neoforge 1.21.1(与现有一致) | +| 模组 | 先 0 个(验协议)→ 再逐个加(验 mod 差异) | +| 端口 | 25565(避开现役) / 25566+ | +| 目录 | 与 `/home/minecraft` **同级**(版本隔离:内容根 / 实例 / 运行期) | +| 世界 | 全新生成,固定种子(可预期) | + +★ 磁盘:/home 尚有 136G ⇒ 放得下(现役 world 已 15G,空白服初期只占几十 M)。 + +**它同时是「版本隔离」策略的第二个实例**: +`store/vanilla-1.21.1/` + `instances/test-server/` + `runtime/test-server/` +—— 与我们给 agent 建的实例同一套口径。 + +--- + +## 1d. 面向 LLM 的 API 形状(§0 推论 1 的落点) + +mineflayer 的 API 面向**程序员**;我们面向 **LLM**。具体差别与对策: + +| 维度 | 程序员友好的做法 | LLM 需要的 | 我们的对策 | +|---|---|---|---| +| 参数 | 位置参数 + 选项对象 | **全命名、少量必填** | `find_blocks(matching=..., max_distance=...)` | +| 返回 | 原始对象/布尔 | **可读摘要 + 关键字段** | 附 `describe()`(`BlockHit` 已有) | +| 失败 | 抛异常 | **说清"为什么不行 + 怎么办"** | `source="unloaded"` / `"unknown-state"` 那种自述 | +| 规模 | 返回全部 | **限量 + 计数**(省 token) | 默认 `count=10`,另给 `total` | +| 发现 | 读文档 | **可自省** | `bot.describe()` 列出可用操作与必需参数 | + +★ 已有可借鉴的样本:`BlockHit.describe()` —— 明确区分 + 「未加载」/「超出世界高度」/「unknown(id),本机注册表无此 state id, + 可能来自 mod 方块」/ 正常。**这正是 LLM 需要的说法**: + 不是报错,而是告诉它「这个方块你暂时看不到,为什么」。 + +⚠️ `unknown(id)` 这一点尤其关键(§0 推论):mod 方块的 state id **只有服务端知道**, + 客户端本机注册表里没有 ⇒ 粗渲染遇到它必须**如实说"我不认识"**,不能瞎猜一个。 + 这与「与服务端 mod 物品交互」那条线直接相关。 + +--- + ## 2. 已完成(可复用,有提交) ### 2.1 渲染桥(P8/P9) @@ -453,27 +534,36 @@ shot.rough → ASCII + 线索(给 agent 看它为什么选了这个角度) --- -## 6. 里程碑(建议顺序) +## 6. 里程碑(按 §0 目的重排) + +★ 重心:**「让 agent 能玩」** = 工具包(感知 + 行动)。 +  渲染是工具之一,不是主线;机位/拍照是用例,不是目的。 | # | 内容 | 依赖 | 状态 | |---|---|---|---| -| M1 | 修 G1(build.sh 编译 CP 加 Fabric 库),1.21.1 构建跑通 | — | 🔄 | -| M2 | **抽象模型骨架**:状态/事件/操作三层(照 mineflayer 形状) | — | ⬜ | -| M2a | └ `rough.py` 常驻粗渲染(World 视图 + DDA 视线 + ASCII/线索) | M2 | ⬜ | -| M2b | └ 事件总线(粗粒度 + 细分层) | M2 | ⬜ | -| M3 | 粗渲染自身判据(构造场景;**不要求预测细渲染**) | M2a | ⬜ | -| M4 | `capture_photo()`(**作为第一个用例**:粗搜机位 → 细出图) | M2a, M2b, M3 | ⬜ | -| M5 | 服务端交互(configuration / registry_data / 物品表) | M1 | ⬜ | -| M6 | 聊天框 → agent → 拍照 全链(§5) | M1, M4, M5 | ⬜ | +| **M0** | 起**空白测试服**(§1c),版本隔离三件套 | — | ⬜ | +| **M1** | 修 build.sh 编译 CP(加 Fabric 库)⇒ 1.21.1 构建跑通 | — | 🔄 | +| **M2** | **协议客户端**:连测试服 → configuration → registry_data → 进 play | M0 | ⬜ | +| | (这是最大缺口:现有只到 `login_start` 冒烟级) | | | +| **M3** | **状态层**:World / entities / inventory 从**服务端真状态**来 | M2 | ⬜ | +| **M4** | **事件层**:粗粒度 + 细分层(照 mineflayer,省 token) | M2 | ⬜ | +| **M5** | **操作层**:chat / look / move / dig / place(能改世界) | M2, M3 | ⬜ | +| **M6** | **粗渲染**(常驻感知):基于 M3 的真状态 | M3 | ⬜ | +| **M7** | **LLM 友好的 API 形状**(§1d):自省 / 可读返回 / 限量 | M3–M6 | ⬜ | +| **M8** | **细渲染**(单次调用):出图,带光影 | M2 | ⬜ | +| **M9** | 第一个用例:`capture_photo()`(粗搜机位 → 细出图) | M6, M8 | ⬜ | -**建议先做 M1 + M2**:M1 解阻断;M2 是**主线**(抽象模型骨架), -拍照只是它的第一个用例。M2 做完后 agent 就有常驻感知能力了, -而这正是"日常游玩"的地基。 -★ M3 特意**不叫**"一致性判据":按用户口径粗/细服务于不同问题, - 不要求粗渲染预测细渲染的像素。M3 只验粗渲染**自己**对日常感知问题的正确性 - (构造简单场景,人工可推算)。 +**建议顺序:M0 → M1 → M2**。 +- M0/M1 是解阻断(M1 是我已经查到根因的那个 classpath bug) +- **M2 是真正的门槛**:从「能渲染」到「能玩」,缺的不是渲染,是**完整协议层**。 + mineflayer 的 41 个 plugins 全建立在它之上,我们目前只到 `login_start`。 ---- +★ M8(细渲染)**不是**早期优先级 —— 它已经能跑(Iris 光影 + 地形, + `colors=113546` 是实测),只是**接不上服务端真数据**。等 M2/M3 通了, + 它自然就在链路上。 + +★ M9(拍照)放最后 —— 它是**验证工具包立不立得住**的用例, + 不是工具包本身。 ## 7. 工程纪律(本项目已确立的口径)