dsh-minecraft-agent
Verifieddsh-minecraft-agent · v1.1.0 · MIT
Minecraft agent for DSH: drive a real 1.20.1 Forge client over a localhost bridge — chat, gather modded blocks by registry name, build, and work the client GUI.
Install
dsh plugin add dsh-minecraft-agent Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Published to npm without a public repository. Inspect the package contents before installing.
Tags
Creators
Readme
Minecraft 智能体(@local/dsh-mc-agent)
让 DSH 智能体进入 Minecraft 1.20.1 Forge 世界:与玩家聊天、采集原版与模组物品、搭建建筑、放置/破坏方块、操作客户端界面。所有能力都通过 mc_* 工具暴露给智能体。
插件有两个后端,同一套工具、同一套任务与蓝图代码,只是"手"接在哪里:
| 后端 | 怎么用 | 能看到什么 |
|---|---|---|
| 客户端桥(推荐,模组环境必用) | mc_join backend=forge,或不带参数(自动探测) |
一台真实 Forge 客户端里的全部内容:create:cogwheel、ae2:controller、gtceu:... 都能按真实注册名查找、挖掘、放置 |
| 协议客户端 | mc_join address=play.example.com:25565 |
原版服务器上的原版内容;1.20.1 协议不发送方块/物品注册表,模组内容只能看到数字 ID |
不带 backend 也不带 address 时,插件先探测本机桥(ping);桥在就用桥,否则按协议后端报错并提示怎么装桥。
配套的 Forge 客户端 mod 在 mcbridge-mod/,构建产物为 build/libs/dsh-mc-bridge-1.0.0.jar(约 33 KB)。
1. 为什么模组服必须走客户端桥
- 协议层:Forge 握手要求带
FML3标记,带上之后还要完成fml:loginwrapper协商。 - 注册表层(根本原因):Minecraft 1.20.1 的协议完全不同步方块/物品注册表(注册表同步是 1.20.2 才有的)。真实客户端能用模组方块,是因为它本地装了同一批模组。协议客户端只能看到数字状态 ID,200+ 模组的自定义内容连名字都拿不到。
所以"按注册名操作模组方块"只有一条路:控制逻辑跑在真实客户端内部。那正是 mcbridge-mod 做的事——它在客户端里开一个 localhost TCP 端口,说换行分隔 JSON 协议,所有请求都投递到客户端 tick 线程执行。
实测(207 个 jar / 247 个 mod id 的整合包):桥接客户端在 minecraft:overworld 的方块普查里直接返回
create:shaft、create:gearbox、create:andesite_belt_funnel、createsifter:brass_sifter、create:cogwheel、create:large_cogwheel,
背包里是 ae2:controller、advanced_ae:quantum_core、tconstruct:...、create:wrench 等——这些名字协议后端一个都拿不到。
2. 安装
插件以 npm 包 dsh-minecraft-agent 的形式发布,package.json 里声明了 dsh.bundle.patch,所以 DSH 的插件管理器能把它当作一个 profile bundle 安装、启用、卸载。
# 一条命令装进当前 profile(需要 danger-full-access 或本次批准)
plugin_manager action=install_bundle target=dsh-minecraft-agent
# 也可以直接给本地 tarball 或绝对路径:
plugin_manager action=install_bundle target=D:/share/dsh-minecraft-agent-1.1.0.tgz
安装后重启 DSH Desktop(Loader 会缓存模块),mc_* 工具才会出现。卸载用 action=remove_bundle。
手动安装(不经过插件管理器,适合本地开发)——编辑 %USERPROFILE%\.dsh\profiles\desktop\package.json:
{
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-minecraft-agent"] } },
"dependencies": { "dsh-minecraft-agent": "link:D:/dsh/minecraft-agent" }
}
然后在该目录执行 pnpm install。注意 cordis.patch.yml 里插入的行 name: 必须与 profile 里用的包名一致,否则 Loader 解析不到这个模块。
依赖:桥后端零第三方依赖(plugin.js 与 lib/ 只 import Node 内置模块;mineflayer、pathfinder、prismarine-chat、vec3、prismarine-nbt 都是按需动态加载的),所以只驱动自己的客户端时不需要装任何东西。它们被声明为 optionalDependencies,pnpm 会自动尝试安装;不想要这份体积就装完删掉,桥照常工作,等要用协议后端(mc_join address=...)或读旧版 .schematic 时再装回来。
客户端 mod
# 从源码构建(需要 JDK 17),产物 build/libs/dsh-mc-bridge-1.0.0.jar
$env:JAVA_HOME = "<JDK17 路径>"
cd mcbridge-mod
<gradle 8.1.1>\bin\gradle.bat --no-daemon build
# 放进整合包实例的 mods 目录,然后重启游戏
Copy-Item build\libs\dsh-mc-bridge-1.0.0.jar "I:\Program Files\mc\.minecraft\versions\1.20.1-Forge_47.4.160\mods\" -Force
然后在 DSH 里:
mc_join # 自动接到本机客户端
mc_observe radius=16 # 看世界:方块普查、玩家、实体、聊天
mc_chat message=大家好
mod 启动时会写 <gameDir>/dsh-bridge/status.json({"port":25577,"status":"listening",...}),端口可用 -Ddshmcbridge.port=... 覆盖,绑定地址用 -Ddshmcbridge.bind=...(默认只绑 127.0.0.1)。
客户端停在 Forge 启动警告界面怎么办
整合包经常在进游戏前弹一个 "Loading Error" 界面(列出 mod 加载警告),不点按钮就不会继续。桥可以在这种情况下工作:
mc_control action=screen # 列出界面上的所有控件(含本地化后的按钮文字与索引)
mc_control action=screen_click index=1 # 点第 1 个控件;或 text=continue 按文字/翻译键匹配
mc_control action=open_world world=创造1 # 直接加载某个存档(异步,随后轮询 mc_observe)
注意:Forge 这个界面的按钮是用已经本地化的字面量构造的(Component.literal(...)),翻译键在运行时已经丢失,所以中文客户端上 text=continue 匹配不到——请看 action=screen 返回的按钮列表,用其中一段文字或索引来点。
3. 工具
| 工具 | 作用 |
|---|---|
mc_join |
连接:backend=forge(客户端桥)/ address=host:port(协议)/ 两者都不给则先试桥 |
mc_state |
连接状态、坐标、血量、背包、未回复的消息 |
mc_observe |
周围世界:方块普查、玩家、实体、掉落物、最近聊天 |
mc_chat |
公屏说话、私聊、执行服务器命令,并读回服务器回应 |
mc_goto |
走到坐标或玩家身边(可后台执行) |
mc_collect |
采集资源:找方块→挖→捡掉落物,默认后台运行 |
mc_inventory |
列出/统计/丢弃物品、进食(eat 在桥后端会明确报错,见第 7 节) |
mc_build |
按蓝图放置方块(内联清单 / 形状生成器 / .schem 原理图) |
mc_task |
查看、等待、取消后台长任务 |
mc_control |
断开连接、load_registry、scan_mods、forge_report、界面操作(screen / screen_click / open_world) |
长任务(挖一组矿、走一千格)在后台运行,所以机器人可以一边挖矿一边和玩家聊天。
建造蓝图三种来源
- 内联清单 —— 直接给
{x, y, z, block}列表。 - 形状生成器 ——
wall、floor、box、hollow_box、tower、pyramid。 - 原理图文件 —— WorldEdit
.schem(调色板 + varint)与旧版 MCEdit.schematic。
放置前会先做材料核对,然后从下往上、由近到远放置;单块失败不会中断整体,最后逐条报告失败原因。dryRun=true 只出方案不动手。
4. 登录方式(协议后端)
auth=offline(默认):离线/皮肤站/局域网服务器,用户名随意。auth=microsoft:正版验证服务器,走微软设备码流程,首次需要在浏览器完成一次登录,令牌会被缓存。
客户端桥不需要登录参数:它用的是你已经登进去的那个客户端本体。
5. 配置
cordis.patch.yml 中的 config:
| 键 | 默认 | 说明 |
|---|---|---|
defaultUsername |
DSH_Agent |
默认游戏名(协议后端用;桥后端以客户端的真实玩家名为准) |
defaultVersion |
1.20.1 |
默认协议版本 |
defaultAuth |
offline |
默认登录方式 |
maxLogLines |
400 |
事件环形缓冲长度 |
autoConnect |
空 | 填 host:port 则在插件激活时自动以协议后端连接 |
bridgeHost / bridgePort |
127.0.0.1 / 25577 |
客户端桥地址;mc_join port=... 可临时覆盖 |
6. 协议后端的模组补偿手段
协议后端仍然保留,用于连普通服务器。它看不到注册表,但可以:
mc_control action=scan_mods path="<整合包 mods 目录>" # 解析 mods.toml,列出 mod id
mc_control action=load_registry path="<registry.json>" # {"blocks":{"<状态ID>":"modid:block_name"}}
mc_collect block=create:cogwheel count=8
桥后端不需要这份映射:客户端自己就能解析每一个名字。
7. 已知边界
- 没有寻路。
goto朝目标直线走、遇阻跳跃,走不到会如实返回"未到达"。绕过障碍需要真正的路径规划,尚未实现。 - 单人游戏窗口失焦会暂停(原版行为),暂停期间整合服务端不 tick,挖方块和行走不会推进。用桥操作时请让游戏窗口保持前台(状态里
stats.paused会如实报告)。 eat未实现(会明确报错,不假装成功):进食需要持续右键,桥目前只暴露点击级交互。- 容器存取与合成只在协议后端实现(桥后端会明确报错):桥能交互单个方块,但还没有打开容器/工作台界面。
- 机器人不会自动躲避岩浆、怪物、摔落。
mc_build单次默认最多 200 块,超大建筑需多次调用。
8. 首次启用需要重启一次
Cordis Loader 会缓存已加载的插件模块:插件被加载过一次之后,即使磁盘上的文件已更新,正在运行的 Host 也不会重新读取(实测 plugin_manager 关掉再打开仍复用旧模块,因为 ESM 模块缓存按 URL 命中)。因此更新插件代码后请重启一次 DSH Desktop。
重启后用下面这条确认新代码已生效(它应当去连桥端口,而不是去 dial 那个地址):
mc_join address=127.0.0.1:29999 backend=forge
# 新代码:报错里是 25577(桥端口);旧代码:报错里是 29999
9. 架构
plugin.js 插件入口:注册工具、提示词段落、生命周期清理(HMR 复用会话)
lib/tools.js 10 个 mc_* 工具 + 后端自动探测
lib/client.js 协议后端:连接、聊天收发(含 1.20.1 收信兼容层)、寻路、挖掘、放置
lib/bridge-client.js 桥传输:换行分隔 JSON、gen 关联、超时、重连
lib/bridge-session.js 桥会话:把客户端 bridge 的 JSON 映射成与协议后端相同的接口
lib/tasks.js 后台长任务:collect / mine / follow / goto / deposit / craft(后端无关)
lib/blueprint.js 蓝图:内联清单、形状生成器、.schem / .schematic 解码
lib/build.js 建造执行:材料核对、分层排序、逐块失败报告
lib/mods.js 模组映射文件 + mods 目录扫描(纯 JS ZIP + mods.toml 解析)
lib/log.js 有界事件环形缓冲(支持游标增量读取)
lib/text.js 聊天组件→纯文本、坐标解析、超时/延迟工具
几个值得一提的实现细节:
- 桥的 I/O 全部走 UTF-8,所以中文存档名(
创造1)、中文聊天都原样过桥。 mineflayer-pathfinder只保留单一副本:依赖锁定精确版本,避免 pnpm 装出多份Movements导致寻路与采集静默失败。- 1.20.1 收信兼容层:1.20.1 的
player_chat没有formattedMessage/senderName,system_chat也没有formattedMessage,Mineflayer 的解析器会抛异常并丢掉全部服务器聊天。lib/client.js直接监听原始包自行解码,test/probe-chat-decode.mjs是可复跑证据。 - 任务层不假设 Mineflayer:背包、位置、找方块、拾取都通过会话接口(
inventorySummary/findBlocks/collectDrops/findPlayerPosition)走,两个后端各自实现。
10. 测试
node --test test/units.test.js test/plugin.test.js test/bridge.test.js test/forge-backend.test.js
node --test test/live.test.js # 真实 1.20.1 回环服务器的协议全链路
test/units.test.js—— 文本、日志、蓝图生成器、.schem解码、模组映射。test/plugin.test.js—— 按 Loader 方式加载插件:工具清单、Standard Schema 配置校验、参数校验、断开时的报错质量、桥自动探测、screen_click/open_world、卸载清理。test/bridge.test.js—— 桥传输:gen 关联、乱序回复、超时、错误映射、重连、未关联消息。test/forge-backend.test.js—— Forge 服务器探测与协议后端共存。test/live.test.js—— 真实 1.20.1 回环服务器:登录、出生、聊天收发、模组方块按映射解析、工具全链路。test/bridge-live.test.js—— 对着真正跑起来的客户端(DSH_BRIDGE_PORT=<端口>,DSH_WORLD=<存档名>让它自己进存档,DSH_DIG=1才做破坏性步骤):$env:DSH_BRIDGE_PORT='25588'; $env:DSH_WORLD='创造1'; $env:DSH_DIG='1' node --test test/bridge-live.test.jstest/probe-tools.mjs—— 手动探针,不做断言,把工具的真实回答逐条打印出来(node test/probe-tools.mjs 25588 --dig)。
test/helpers/fake-bridge.js 提供了一个假桥,让传输层、会话层、工具层都能在没有 Minecraft 的情况下测试。