Skip to content

dsh-minecraft-agent

Verified

dsh-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. 为什么模组服必须走客户端桥

  1. 协议层:Forge 握手要求带 FML3 标记,带上之后还要完成 fml:loginwrapper 协商。
  2. 注册表层(根本原因):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)

长任务(挖一组矿、走一千格)在后台运行,所以机器人可以一边挖矿一边和玩家聊天。

建造蓝图三种来源

  1. 内联清单 —— 直接给 {x, y, z, block} 列表。
  2. 形状生成器 —— wall、floor、box、hollow_box、tower、pyramid。
  3. 原理图文件 —— 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               聊天组件→纯文本、坐标解析、超时/延迟工具

几个值得一提的实现细节:

  1. 桥的 I/O 全部走 UTF-8,所以中文存档名(创造1)、中文聊天都原样过桥。
  2. mineflayer-pathfinder 只保留单一副本:依赖锁定精确版本,避免 pnpm 装出多份 Movements 导致寻路与采集静默失败。
  3. 1.20.1 收信兼容层:1.20.1 的 player_chat 没有 formattedMessage/senderName,system_chat 也没有 formattedMessage,Mineflayer 的解析器会抛异常并丢掉全部服务器聊天。lib/client.js 直接监听原始包自行解码,test/probe-chat-decode.mjs 是可复跑证据。
  4. 任务层不假设 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.js
    
  • test/probe-tools.mjs —— 手动探针,不做断言,把工具的真实回答逐条打印出来(node test/probe-tools.mjs 25588 --dig)。

test/helpers/fake-bridge.js 提供了一个假桥,让传输层、会话层、工具层都能在没有 Minecraft 的情况下测试。