dsh-mc-client
仓库地址:https://github.com/DRheEheAMGary/dsh-mc-client
当前版本:1.2.0(窗口客户端自动化可靠性版本,见 CHANGELOG.md)。
给 DeepSeek Harness 的 Minecraft Java 版插件,两种玩法:
- 窗口版:启动
E:\Minecraft 下 PCL2 的 Java 客户端,用真实键鼠操控(需要游戏窗口)。
- 无窗口版(headless):启动一个隐藏控制台的本机 Minecraft 专用服务端 + 一个协议机器人玩家。完全不创建游戏窗口、不渲染画面、不注入桌面键鼠,通过 Minecraft 协议游玩。
当前已在 DSH Desktop 的 desktop profile 安装并激活:include:mc-client。
1.2.0:窗口客户端自动化可靠性
1.2.0 专门修复“在真实客户端上自动化测试不可靠”的问题;无窗口工具的语义完全不变。
核心行为
- 不会被 DSH 抢输入:窗口检测按进程名 / 窗口类 /
isGame 判断,并排除 DSH、Electron 以及标题里带 “Minecraft” 的 DSH 会话窗口。键鼠、文本、聊天执行前会 AttachThreadInput + SetForegroundWindow + BringWindowToTop(Alt 脉冲、临时置顶),并校验 GetForegroundWindow();聚焦失败返回 code:"focus-failed",不会静默把输入发到 DSH。
- 截图只截游戏窗口:优先
PrintWindow(PW_RENDERFULLCONTENT),DSH 窗口盖在上面也不会被截入;只有在 GPU 窗口拒绝 PrintWindow 时才在验证聚焦后回退桌面裁剪,并返回 method:"screen-crop"。
- 聊天可回读:
mc_control {action:"chat"} 发送后从客户端 latest.log 读回最新 ≤10 行 [CHAT],返回 chatLines 和 chatSource;以 / 开头的命令会自动使用 Unicode 输入,避免客户端剪贴板安全策略吞掉前导斜杠。
- 启动并自动进服:
mc_launch {server, waitInGame} 先尝试 --quickPlayMultiplayer;若 26.1 客户端忽略它,则用 OCR 依次点击“多人游戏 → 直连 → 地址 → 加入服务器”,最后根据窗口标题/客户端日志确认真正 inGame。
- 结构化状态:
mc_control {action:"state"} 返回 inGame、screen(mainmenu / multiplayer / inventory / container / none)、最近聊天、客户端日志;visual:true 时 OCR 识别 F3 坐标/生物群系/面向和物品栏。
- 新日志工具:
mc_client_log 自动选择 PCL 版本日志或 ServerMod/client/run dev 客户端日志,支持 tail 和 grep。
工具参数速查
| 工具 | 1.2.0 新增/变化 |
|---|
mc_status | 新增 foregroundWindow、foregroundIsGame、ignoredWindows;windows 只含可信游戏窗口 |
mc_launch | 新增 server、waitInGame、waitGameSeconds;返回 inGame、state、quickPlay、menuFallback |
mc_control | 新增 state、rightclick_hold、leftclick_hold;look 支持绝对 yaw/pitch;chat 支持 waitMs 并回读;screenshot 支持 region;state 支持 visual |
mc_screenshot | 新增 region;返回 method、captureOrigin、captureWidth/Height |
mc_client_log | 新工具:tail(默认 100,≤500)、grep(子串或正则)、source(auto/pcl/dev/custom) |
自测顺序(本机实测通过)
# 0) 服务端已启动(HubSuite dev 示例)
# 端口 25566;dev 客户端在 ServerMod/client,PCL 客户端在 E:\Minecraft
# 1) 启动客户端并自动进服(Quick Play;约 60 秒)
mc_launch {edition:"java", server:"localhost:25566", waitInGame:true, waitGameSeconds:120}
# 2) 确认状态(窗口标题 + 客户端日志)
mc_control {action:"state", visual:false}
# 3) 发命令并从 latest.log 回读聊天
mc_control {action:"chat", text:"/time set day"}
# 4) 只截游戏窗口 + 区域裁剪
mc_screenshot {scope:"window", savePath:"docs/self-test-window.png"}
mc_screenshot {scope:"window", region:{x:240,y:310,width:280,height:110}, savePath:"docs/self-test-region.png"}
# 5) 绝对视角(需要 op/作弊;HubSuite 登录前无法执行命令)
mc_control {action:"look", yaw:90, pitch:0}
# 6) F3/背包状态(可先按 F3 / E)
mc_control {action:"state", visual:true}
# 7) 读取客户端日志
mc_client_log {grep:"CHAT|HubSuite|ERROR", tail:50}
完整实测输出与限制见 docs/client-verification-1.2.0.md。
无窗口游玩(原有功能)
原理
调用方(DSH agent / 工具)
│ JSON 工具调用
▼
mc_headless ── 下载/启动 vanilla 专用服务端(隐藏控制台,127.0.0.1)
│ + 把玩家存档复制成服务端世界(可选)
▼
mc_bot ── mineflayer 协议机器人 ── Minecraft 协议 ──► 服务端
(没有客户端窗口、没有渲染、没有桌面输入)
机器人是一个真实的服务器玩家:有坐标、血量、饥饿度、物品栏,可以走路、跳跃、挖掘、放方块、攻击、聊天、执行 /命令、寻路。服务端和机器人都在后台进程里运行。
快速开始
# 1) 新世界(26.1.2,默认版本)
mc_headless { "action": "start" }
# 或者:把你现有的 26.1.2 单人存档复制进无窗口世界(推荐先在同一版本保存一次)
mc_headless {
"action": "start",
"version": "26.1.2",
"worldSource": "E:\\Minecraft\\.minecraft\\versions\\26.1.2\\saves\\新的世界 (1)"
}
# 2) 查看机器人状态
mc_bot { "action": "state" }
# 3) 玩:移动、视角、挖掘、聊天、命令、寻路
mc_bot { "action": "move", "keys": ["forward", "sprint"], "durationMs": 2000 }
mc_bot { "action": "look", "dx": 90, "dy": 10 }
mc_bot { "action": "dig", "offset": { "y": -1 } }
mc_bot { "action": "chat", "text": "hello from the windowless world" }
mc_bot { "action": "command", "text": "/time set day" }
mc_bot { "action": "goto", "x": 100, "y": 70, "z": 100, "range": 2 }
# 3) 观察世界:F3 信息 + 周围方块状态
mc_debug {}
mc_blocks { "mode": "looking", "maxDistance": 8 }
mc_blocks { "mode": "at", "offset": { "y": -1 } }
mc_blocks { "mode": "scan", "radius": 4, "verticalRadius": 3 }
mc_blocks { "mode": "find", "name": "diamond_ore", "radius": 32, "count": 5 }
# 4) 收尾(机器人下线 + 服务端优雅停止)
mc_headless { "action": "stop" }
连接已有的离线模式服务器(不启动本地服务端):
mc_headless {
"action": "start",
"mode": "connect",
"host": "127.0.0.1",
"port": 25565,
"version": "26.1.2"
}
工具
| 工具 | 作用 |
|---|
mc_headless | status / start / stop;本地服务端下载、启动、世界复制、机器人连接 |
mc_bot | state / chat / command / move / look / dig / place / use / attack / equip / drop / goto / stop |
mc_blocks | 观察方块:looking(视线射线)、at(指定坐标/相对位置)、scan(范围扫描 + 每种方块计数)、find(按名字找最近方块) |
mc_debug | 无窗口版 F3 信息:维度、生物群系、XYZ/眼位、方块/区块坐标、朝向 yaw/pitch、光照、时间/天气、服务器/延迟、实体等 |
mc_status | 窗口版:检查 Java/Bedrock、PCL 路径、可信游戏窗口、前台窗口、客户端日志 |
mc_launch | 窗口版:启动 PCL2 最近版本 Java 客户端 / PCL2 启动器 / Bedrock;可带 server + waitInGame 自动进服 |
mc_control | 窗口版:真实键鼠、绝对/相对视角、聊天回读、状态、聚焦、窗口、关闭、截图裁剪 |
mc_screenshot | 窗口版:只截游戏窗口(PrintWindow)或整屏;支持 region 裁剪 |
mc_client_log | 窗口版:读取 PCL/dev 客户端 latest.log,支持 tail/grep |
已验证行为(本机实测)
使用 mc_headless + mc_bot 完整跑通:
- 自动下载并启动 Minecraft 26.1.2 专用服务端(Java 25,隐藏控制台,
127.0.0.1:25599);
- 把现有存档
E:\Minecraft\.minecraft\versions\26.1.2\saves\新的世界 (1) 复制为无窗口世界(原存档不变),服务端从该存档启动;
- 协议机器人
DSHBot 加入,血量 20 / 饥饿 20,出生坐标 (-8.5, 70, 9.5);
/time set day 生效(服务器反馈 Set minecraft:overworld to time marker minecraft:day);
- 前进 1.5 秒移动 7.36 格,视角旋转,挖掉脚下方块(
grass_block);
- 聊天消息出现在服务器日志:
<DSHBot> hello from windowless minecraft;
goto 寻路到 (-4, 63, 17) 成功(range 1);
mc_debug 返回 F3 信息:Minecraft 26.1.2 (protocol 775)、dark_forest 生物群系、XYZ/Block/Chunk、Facing: north、光照、时间、服务器 ping、178 个实体等;
mc_blocks 的 at/looking/scan/find 均返回方块状态:名称、displayName、stateId、metadata、属性(如 axis/facing)、生物群系、方块光/天空光、硬度、可挖掘、材质等;
- 放置方块(
place)后再次查询确认目标位置变成 dirt;attack 命中 2.69 格外的猪;drop 成功丢弃物品;
mc_headless stop 优雅关闭机器人和服务端。
详细记录:docs/headless-verification.md
窗口版(原有功能)
用于必须看到/操作真实游戏画面的场景:
mc_launch 重放 PCL2 的 PCL/LatestLaunch.bat,启动 E:\Minecraft 下最近一次 Java 版本(含账号),或打开 PCL2 UI;
- 带服务器参数时:
mc_launch { "edition": "java", "server": "localhost:25566", "waitInGame": true },先试 Quick Play,失败则 OCR 菜单回退,并明确返回是否真的进入游戏;
mc_control 用 Win32 SendInput 真实键鼠操控,支持移动、视角、挖掘/放置、聊天/命令、窗口管理;
- 聊天/命令后自动从
latest.log 回读 [CHAT] 行,便于确认 /hub where、/give、断线和 Mixin 报错;
mc_screenshot 截图到工作区,用 read_image 查看;截图默认只含游戏窗口,可用 region 放大 HUD/物品图标;
- 窗口版想看 F3:
mc_control { "action": "key", "keys": "f3" } 后 mc_control { "action": "state", "visual": true } 可解析坐标/生物群系/面向,或直接截图;无窗口版的 F3 结构化信息用 mc_debug。
验证截图(Java 版通过窗口版工具操控):
Java Edition controlled through the window tools
1.2.0 的窗口识别、聚焦恢复与重叠截图验证:PrintWindow captures only the game window while DSH is foreground
安装 / 卸载
从 GitHub 安装:
git clone https://github.com/DRheEheAMGary/dsh-mc-client.git
cd dsh-mc-client
npm install
# 安装到 DSH profile(把 desktop 换成你的 profile 名)
dsh plugin --profile desktop add .
或者直接使用本机已有的目录:
cd E:\Github\dsh-mc-client
npm install
dsh plugin --profile desktop add "E:\Github\dsh-mc-client"
# 卸载
dsh plugin --profile desktop remove dsh-mc-client
本仓库本身是可安装 bundle(package.json 的 dsh.bundle + cordis.patch.yml)。依赖:mineflayer、mineflayer-pathfinder(已声明在 package.json)。
配置
| 环境变量 | 说明 |
|---|
DSH_MC_HEADLESS_DIR | 无窗口模式的 server jar / 世界 / 日志目录,默认 %LOCALAPPDATA%\dsh-mc-client\headless |
DSH_MC_HEADLESS_JAVA | 指定服务端使用的 java.exe |
DSH_MC_PCL_DIR | 含 PCL2.exe 的目录,默认自动探测 E:\Minecraft |
DSH_MC_MINECRAFT_DIR | .minecraft 目录 |
DSH_MC_LATEST_LAUNCH | LatestLaunch.bat 路径 |
DSH_MC_CLIENT_LOG | 强制指定客户端日志(mc_client_log/聊天回读的自定义来源) |
DSH_MC_DEV_CLIENT_LOG | 指定 Gradle dev 客户端日志,默认探测 E:\Github\ServerMod\client\run\logs\latest.log |
DSH_MC_SERVERMOD_DIR | ServerMod 仓库目录,用于定位 client/run/logs/latest.log |
DSH_MC_BEDROCK_FAMILY / DSH_MC_BEDROCK_APP | 窗口版 Bedrock 包族名 / App ID |
无窗口模式支持的服务端版本(机器人协议版本自动映射,26.1.x 使用 26.1 协议):
26.1.2、26.1.1、26.1、1.21.11、1.21.8、1.21.4、1.21.1、1.20.1
服务端自动选择满足要求的 Java(26.x → Java 25,1.21.x → 21,1.20.1 → 17)。
结构
index.js Host 入口:注册 9 个工具 + /api/mc 路由
lib/mc.js 窗口版共享服务(串行队列、启动、自动进服、状态、输入、截图、关闭)
lib/tools.js 窗口版工具 schema/执行(含 mc_client_log)
lib/winhelper.cs 窗口版 C# Win32 助手(可信窗口、聚焦验证、SendInput、PrintWindow、region)
lib/winhelper.js 助手编译/调用(源码 hash 变化自动重编译)
lib/java.js PCL2/Java 环境发现与 LatestLaunch.bat 重放
lib/logs.js 客户端日志发现、tail/grep、[CHAT] 解析与回读
lib/ocr.js Windows.Media.Ocr 桥(屏幕状态识别/菜单回退)
lib/menu.js OCR 菜单自动进服(多人游戏 → 直连 → 地址 → 加入服务器)
lib/scripts/ocr.ps1 内置 OCR PowerShell 脚本(MIT 适配自 dsh-screen-agent)
lib/headless/server.js 无头专用服务端:Mojang 清单/下载、Java 选择、世界复制、启动/停止
lib/headless/bot.js mineflayer 协议机器人:移动/视角/挖掘/放方块/聊天/寻路 + F3/方块探测
lib/headless/service.js 无窗口模式编排(服务端 + 机器人生命周期)
lib/headless/tools.js mc_headless / mc_bot / mc_blocks / mc_debug 工具 schema
locale/*.json 插件显示名(中/英)
icon.svg 原创图标
docs/ 验证截图、无窗口验证记录、1.2.0 客户端验证记录
dev/ 开发期验证脚本(不随 bundle 发布)
scripts/check.mjs 仓库自检(语法/JSON/manifest/入口导入)
.github/workflows/ci.yml CI:Node 22 上安装依赖并运行自检
CHANGELOG.md 版本变更记录
LICENSE MIT
CONTRIBUTING.md 开发与贡献说明
设计要点:
- 窗口版的“可信游戏窗口”必须同时满足进程、窗口类、
isGame 条件,并排除 DSH/Electron;所有输入前都验证前台窗口,避免把键鼠发进 DSH。
- 截图优先使用
PrintWindow,因此截图内容与窗口是否被遮挡、DSH 是否在前台无关;只有 GPU 拒绝时才回退到已验证聚焦的桌面裁剪。
- 聊天和状态以客户端
latest.log 为准;窗口标题/日志决定 inGame,OCR 只作为菜单点击和 F3/背包装态识别的补充。
- 无窗口模式不创建任何客户端进程,因此没有窗口、没有 GPU 渲染、没有截图需求,也不受桌面分辨率/焦点影响。
- 服务端只监听
127.0.0.1,online-mode=false,并用离线 UUID 把机器人写进 ops.json(因此 /time、/give 等命令可用)。
worldSource 只会复制存档到无窗口服务端目录,不会修改原单人存档。
- 机器人操作与窗口版一样走串行队列;工具输出统一做 lossless JSON 清洗。
- 窗口版的 C# 助手在首次使用时用系统自带
csc.exe 编译,不依赖第三方包;源码 hash 变化会自动重编译。
- OCR 使用 Windows 内置
Windows.Media.Ocr,不需要额外的可执行文件或网络服务。
已知限制
- 窗口版绝对视角
look {yaw,pitch} 通过 /tp @s ~ ~ ~ <yaw> <pitch> 设置旋转,需要 op 或世界开启作弊;命令被拒绝时返回 code:"command-rejected" 和聊天回读。
- 物品栏/容器识别依赖 OCR 关键词与物品提示,不同 GUI 缩放/语言/资源包下可能识别为
screen:"none";此时看截图或使用 visual:false 的状态字段。
- HubSuite 登录/注册界面是服务端自定义 GUI,插件不会保存或猜测密码;截图和日志仍可用,登录需要用户手动完成。
- 客户端日志路径自动探测;如果同时运行多个客户端,可用
DSH_MC_CLIENT_LOG 指定,或先关掉不用的客户端。
- 窗口版仍只重放 PCL “最近一次启动”的版本;要换版本先用 PCL 启动一次,或使用
javaMode:"launcher"。
- 无窗口模式使用 vanilla 专用服务端:Fabric/Forge 模组内容不会加载;模组世界复制后可能缺方块/物品。建议对同版本 vanilla 或轻量存档使用。
- 无窗口模式没有画面可看:状态通过
mc_bot { action: "state" } 返回(坐标、血量、物品栏、聊天记录),没有截图;F3 里的 FPS、渲染距离、JVM 内存等渲染器字段在协议机器人模式下不存在(工具会明确标注 n/a),其余 F3 信息由 mc_debug 提供。
- 方块状态来自服务器下发的区块数据;未加载区块会报告
loaded: false / unloaded 计数,走远后需要等待区块加载再查询。
- 机器人默认不会挖隧道寻路(pathfinder 配置
canDig=false);远距离 goto 可能需要较长时间,可先把 timeoutMs 调大。
- 首次启动需要从 Mojang 下载约 60 MB 的
server.jar;之后复用缓存。
- 本机测试时服务端偶尔出现
Can't keep up! 警告(CPU 竞争),不影响操作;可降低 memoryMb/关闭其他程序。
mode: "connect" 需要目标服务器允许离线登录(online-mode=false);本插件不做 Microsoft 正版登录。
开发说明
dev/ 下保留验证脚本(不随 bundle 安装):
dev/test-headless-service.mjs:无窗口服务端 + 机器人完整冒烟测试(启动、聊天、命令、移动、挖方块、寻路、停止);
dev/test-service.mjs / test-launch-java.mjs / test-java-control.mjs / test-chat.mjs:窗口版验证;
dev/asar-extract.mjs:从 DSH app.asar 提取文件排查;
dev/fix-modules-store.mjs:修复 pnpm store 版本不匹配(见下)。
本机环境修复记录
- 工作区最初因 Windows ACL 缺少
WRITE_OWNER 导致 shell 无法启动,使用 DSH 的 diagnose-windows-sandbox-acl 修好;回滚脚本在 .acl-recovery/(已 gitignore)。
- DSH Desktop 更新后 profile 的 pnpm store 从 v10 变为 v11,导致插件安装被拒。备份
node_modules/.modules.yaml 到 dev/backup-modules.yaml,把 storeDir 改成 v11 后安装成功(pnpm 11.28.5)。
开发与贡献
npm install
node scripts/check.mjs
贡献指南见 CONTRIBUTING.md。CI 会在 Node 22 上安装依赖并运行 node scripts/check.mjs(语法、JSON、插件 manifest 和入口导入检查)。
License
MIT,见 LICENSE。