文件
BotStore/README.md
T
lyizai a12a24c716 feat: 用 Node.js + mineflayer 重构 AutoStore,UI 改为网页控制台并适配 Grim 反作弊
由 Fabric 客户端模组 AutoStore v1.3.1 重构为独立 Node.js 机器人,无需游戏客户端。

核心实现:
- 领土数据:Dynmap markers.json 拉取解析(奇偶填充识别国中飞地)、SimpCore 开放 API 第四数据源、
  带缓存击穿的时间戳请求与内容未变化跳过解析
- 扩地规划:四种策略(方形外扩 / 区域 S 形扫描 / 玩家周围 / 绕国一圈)逐行对照移植,
  接壤判定只算己方领土,飞地优先填补
- 扩地状态机:规划→寻路→等待开垦→成功/失败→下一目标→完成,含超时重试、
  往边上走两步自救、连续超时回城、耐久保护回城
- 生存辅助:自动进食、自动攻击(豁免中立生物)、自动游泳防溺水、自动用船(默认关闭)
- 寻路:Baritone → mineflayer-pathfinder,高度偏好用包装 Goal 等价移植

Grim 反作弊合规层(新增,核心差异点):
- 旋转不超前:接管 bot.look 按 ≤8.6°/tick 推进朝向,消除 mineflayer
  「本地朝向瞬间跳变、数据包滞后补发」导致的 Prediction 分歧
- 攻击三重校验:朝向已同步 + 距离 ≤3.0 格 + 视线可达 + 攻击冷却 + 非骑乘/进食
- 动作互斥:拦下疾跑+潜行、疾跑+使用物品等原版不可能出现的组合
- 物理参数只读自检 + 寻路约束(禁挖/禁放/禁跑酷/禁搭塔/限下落/绕开水域)

网页控制台(新增):
- 状态面板、Canvas 领土地图(缩放/平移/图层)、分组配置表单、实时日志流
- REST + WebSocket 接口,支持 WEB_TOKEN 令牌鉴权

修复:
- containsFuzzy 只取固定长度前缀的末行编辑距离,导致完全相同的子串也匹配不上
- 占领去重依赖 Set.add 返回值(JS 中恒为真),导致同一区块被重复计数
- 非法枚举值不再钳制到最近边界,改为回退默认值

测试:154 个用例,npm test 全绿;npm run check 语法自检通过。
2026-09-27 17:17:41 +08:00

13 KiB
原始文件 Blame 文件历史

AutoStore Bot

Minecraft 自动扩地机器人 —— 由原 Fabric 客户端模组 AutoStore 重构而来: Node.js + mineflayer 实现,UI 从游戏内 GUI 改为网页控制台,并针对装有 Grim 反作弊的服务器做合规适配。

不需要开游戏客户端,一条命令启动,浏览器打开控制台即可开始自动扩地。

npm install
cp .env.example .env   # 填入服务器地址与账号密码
npm start              # 打开 http://127.0.0.1:3081

功能对照

原模组功能 新版实现 说明
远程拉取 markers.json 领土数据 ✅ 带时间戳缓存击穿 + no-cache 头,实测 24 个邦国 / 11.5 万区块 200ms 解析完成
四种扩地策略 ✅ 方形外扩 / 区域 S 形扫描 / 玩家周围 / 绕国一圈
区域扩地严格 S 形扫描 ✅ 起始边取离王城最近的边,由内而外蛇形推进
飞地(疏漏区块)检测与优先填补 ✅ 按 dynmap 奇偶填充规则解析多边形,正确识别国中孔洞
自动寻路前往目标区块 ✅ Baritone → mineflayer-pathfinder,高度偏好启发式等价移植
寻路失败重试 / 往边上走两步 / 连续超时回城 ✅ 状态机与阈值完全一致
运行时接壤校验、目标有效性校验 ✅ 每 tick 校验,避免在无效区块上白费时间
现实时间限制(默认 11:00-22:00) ✅ 改为可配置时段,并支持「到点自动开始」
监听字幕 / 聊天判定开垦结果 ✅ 兼容 title / subtitle / actionBar / Boss 条四条通道
自动进食 ✅
自动攻击敌对生物(豁免中立生物) ✅ 铁傀儡 / 僵尸猪灵永不攻击;末影人 / 蜘蛛默认不打(见下方差异说明)
耐久保护回城 ✅
自动游泳防溺水 ✅ 水中持续按住跳跃键上浮
自动用船过水 ⚠️ 默认关闭 mineflayer 无载具物理,Grim 风险高,详见「行为差异」
实时地图 GUI ✅ 网页版 Canvas 绘制,支持缩放 / 平移 / 图层开关
日志导出 ✅ 网页按钮导出到 data/
SimpCore 开放 API 第四数据源 ✅ 低频轮询 + 手动全服拉取
Grim 反作弊适配 ✅ 新增 见下方专章

Grim 反作弊适配

这是本次重构最核心的工程问题。mineflayer 是第三方协议实现,它的物理引擎(prismarine-physics) 与行为习惯和原版客户端存在偏差,直接跑在 Grim 服务器上会被 Prediction / Reach / NoSlow / MultiActions 等检查标记。本项目用一层 GrimCompat 合规层把所有对外行为收口:

1. 旋转绝不超前(防 Prediction)

mineflayer 的 bot.look() 会立刻把 bot.entity.yaw 改到目标值,而朝向数据包是按 physics.yawSpeed(约 8.6°/tick)逐 tick 补发的。这会造成:

本地已经朝新方向走了  ← 但服务端还以为你朝旧方向

Grim 的 Prediction 检查正是逐 tick 复算玩家位置并与上报位置比对,这种分歧必然被标记。

做法:接管 bot.look / bot.lookAt,只记录目标朝向,在每个 physicsTick 里把 bot.entity.yaw/pitch 按 ≤ 8.6° 的步长推进。这样「本地朝向」永远等于「服务端已收到的朝向」, 最多差 1 tick。awaitRotationSettled() 可等待旋转真正同步完成。

2. 攻击三重校验(防 Reach / LineOfSight / Post)

attackEntity() 出手前依次确认:

  • 朝向已同步 —— 服务端认为你正看着目标(防 Post 检查)
  • 眼睛到目标碰撞箱最近点 ≤ 3.0 格 —— 与生存模式实体交互距离一致
  • 视线可达 —— 射线检测中间没有实心方块遮挡
  • 攻击冷却已好 —— 按手持武器攻速计算(剑 625ms / 斧 1000-1250ms / 空手 250ms)
  • 不在骑乘 / 进食 / 使用物品状态

3. 动作互斥(防 MultiActions)

原版客户端不可能出现的组合一律拦下,并计入「已拦下动作」计数供控制台观察:

  • 疾跑 + 潜行
  • 疾跑 + 使用物品(进食 / 拉弓 / 举盾)
  • 疾跑 + 跳跃(默认放行 —— 这是原版合法动作,Grim 预测支持;实测被标记时可开启 grim.blockSprintJump 退化为普通跳跃)

4. 物理参数只读校验(防「改物理常数绕过预测」)

audit() 会核对 bot.physics 的 gravity / playerSpeed / sprintSpeed / stepHeight / airborneInertia / waterInertia 是否仍为原版值,并检查 physicsEnabled、游戏模式、鞘翅飞行状态。 任何一项异常都会在控制台的「Grim 合规」面板里报警。本项目从不修改物理常量,也从不直接写坐标。

5. 寻路约束

约束 默认 原因
canDig 关闭 Grim 的 FastBreak 检查极严
放置方块(scafoldingBlocks) 关闭 Grim 的 place 类检查极严
allowParkour 关闭 mineflayer 起跳时机与原版有偏差
allow1by1towers 关闭 搭塔过程几乎必被标记
maxDropDown 3 格 避免长距离坠落
liquidCost 200(avoid 模式) mineflayer 液体物理与原版差异最大,优先绕开水域
allowFreeMotion 关闭 禁止自由运动

与原模组的行为差异(重要)

重构过程中有几处有意为之的取舍,请务必了解:

1. 自动用船默认关闭

mineflayer 使用的 prismarine-physics 没有实现载具物理。上船后 mineflayer 会关闭本地物理预测 (bot.on('mount') → shouldUsePhysics = false),机器人位置完全由服务端下发的船实体位置决定, 只能靠 bot.moveVehicle() 驱动船前进。这意味着无法本地预测船的轨迹,Grim 的 Vehicle 类检查 逐 tick 复算载具运动时极易分歧。

因此 waterMode 默认为 avoid(绕开水域),autoBoat 默认为 false。 用船逻辑已完整实现(扫描水域 → 装备船 → 放船 → 登船 → 航行 → 下船 → 打掉回收), 仅在你实测确认该服务器对船宽容时才建议开启(waterMode: 'boat' + autoBoat: true)。

2. 末影人与蜘蛛默认不打

原模组按原版 AI 条件判断(末影人仅被激怒时、蜘蛛仅黑暗中才反击)。mineflayer 拿不到可靠的 「是否被激怒」与「环境亮度」信息,因此默认一律不打(宁可漏打也不误打)。 需要时可用 combat.attackEnderman / combat.attackSpiders 放开。

3. 新增高危生物跳过

监守者 / 末影龙 / 凋灵默认跳过(combat.avoidDangerousMobs)—— 原模组会攻击它们, 但那基本等于自杀。

4. 开垦时段可配置

原模组硬编码 11:00-22:00,现改为 enforceClaimTime + claimStartHour / claimEndHour。

5. 模糊匹配算法修正

原 Java 版的 containsFuzzy 只取固定长度前缀的末行距离,导致 containsFuzzy('开垦中 50%', '开垦中', 0) 返回 false(连完全相同的子串都匹配不上)。本版按注释所述的语义修正为 「存在编辑距离 ≤ maxEdits 的子串」,并补了回归测试。


安装与运行

依赖

  • Node.js 18+(开发与验证使用 Node 24)
  • 无需 Java、无需游戏客户端

步骤

npm install
cp .env.example .env
# 编辑 .env 填入服务器地址、账号、密码
npm start

启动后控制台会打印访问地址(默认 http://127.0.0.1:3081),浏览器打开即可。

环境变量

所有敏感信息只放在 .env(已被 .gitignore 忽略,绝不要提交):

变量 说明
MC_HOST / MC_PORT 服务器地址与端口
MC_VERSION 协议版本,默认 1.21.4
MC_USERNAME 机器人游戏名
MC_AUTH offline(离线服)或 microsoft(正版)
MC_PASSWORD 服务器登录 / 注册密码,供 {password} 占位符使用
WEB_HOST / WEB_PORT 控制台监听地址与端口
WEB_TOKEN 控制台访问令牌;非本机访问必须设置
DYNMAP_BASE / DYNMAP_WORLD 地图数据源根地址与世界目录名
SIMP_API_KEY SimpCore 开放 API Key(可选)

网页控制台

打开控制台后:

  • 左栏:连接状态、任务状态机、领土数据源、Grim 合规面板
  • 中栏:领土地图(Canvas,滚轮缩放 / 拖拽平移 / 图层开关)+ 实时运行日志
  • 右栏:分 7 个标签页的配置表单 + 手动指令输入

顶栏按钮:开始扩地 / 停止 / 重连。

地图图层:己方领土(蓝)、本次占领(绿)、飞地疏漏(红)、当前目标(黄)、机器人(白点)、王城(紫)。

REST / WebSocket 接口

方法 路径 说明
GET /api/status 机器人 / 任务 / 数据源完整状态
GET /api/config 当前配置
POST /api/config 保存并立即应用配置
GET /api/map?full=1 地图数据(full=1 附带全部邦国区块)
GET /api/logs 运行日志
POST /api/logs/export 导出日志到 data/
POST /api/task/start 启动扩地(可带配置覆盖)
POST /api/task/stop 停止扩地
POST /api/map/refresh 手动刷新地图数据
POST /api/api/fetch-all 手动拉取全服领土(重接口)
POST /api/command 发送游戏指令
POST /api/bot/reconnect 重连服务器
WS /ws 实时状态推送(1s)与日志流

配置项

配置保存在 data/autostore.json,可通过控制台表单修改。完整字段见 src/config/expansionConfig.js,分组如下:

分组 内容
策略 扩地策略、目标邦国、目标数量、扩圈上限、区域矩形
超时 寻路 / 等待超时、重试次数、回城阈值、走两步轮数、开垦时段
寻路 疾跑 / 游泳 / 跳跃 / 挖方块 / 放方块、高度偏好、跑酷、搭塔、下落高度、液体代价
生存 自动进食、自动攻击、耐久保护、战斗筛选、水域策略、自动用船
数据 地图刷新间隔、SimpCore API
Grim 合规层全部阈值(见上)
服务器 开垦模式指令、登录 / 注册模板、指令节流、重连

开发

npm test        # 运行测试(Node 内置 test runner,无需额外依赖)
npm run check   # 语法自检(require 全部源码,捕获语法与加载错误)
npm run dev     # 文件变更自动重启

测试覆盖

154 个测试用例,覆盖:

  • 区块坐标编解码(含负数与边界)
  • 领土模型:飞地识别、会话占领、API 数据合并
  • 规划器:四种策略、S 形顺序、接壤只算己方领土(历史 bug 回归)、他国区块切断连通
  • markers.json 解析:奇偶填充孔洞、王城换算、颜色解析
  • 字幕 / 聊天解析:进度、带坐标成功、通用成功、模糊匹配
  • Grim 合规层:旋转限速、动作互斥、攻击冷却表、距离 / 视线校验、物理自检
  • 战斗筛选:中立生物豁免、条件敌对、猪灵金甲判定、耐久保护
  • 寻路服务:Grim 约束是否真正施加到 Movements、高度偏好目标
  • 控制器状态机:完整扩地流程、超时重试、走两步、回城、耐久保护停止、完成
  • Web 控制台:地图负载、REST 接口、令牌鉴权

目录结构

src/
├── index.js                     入口:装配模块、启动 Web 控制台、驱动 tick
├── config/
│   ├── expansionConfig.js       配置默认值 / 校验 / 归一化
│   └── configStore.js           配置 JSON 持久化
├── core/
│   ├── chunkPos.js              区块坐标编解码(整数键,零临时对象)
│   ├── territoryModel.js        领土模型:区块集合、飞地、会话占领、API 合并
│   ├── territoryDataService.js  Dynmap markers.json 拉取与解析
│   ├── simpApiClient.js         SimpCore 开放 API 客户端
│   ├── expansionPlanner.js      四种扩地策略
│   └── subtitleChatMonitor.js   字幕 / 聊天解析与模糊匹配
├── bot/
│   ├── botManager.js            连接、登录、重连、事件归一化
│   ├── grimCompat.js            ★ Grim 反作弊合规层
│   ├── pathingService.js        寻路服务(替代 Baritone)
│   ├── autoCombat.js            战斗筛选与耐久检查
│   ├── autoEat.js               自动进食
│   ├── autoBoat.js              自动用船(默认关闭)
│   └── durabilityGuard.js       耐久保护
├── controller/
│   └── expansionController.js   扩地任务状态机
├── web/
│   ├── server.js                Express + WebSocket
│   └── public/                  控制台前端(原生 HTML/CSS/JS,无构建步骤)
└── util/
    └── logger.js                环形日志缓冲

许可证

MIT