由 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 语法自检通过。
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