文件
BotStore/CHANGELOG.md
T
lyizai 0cd65cf9be fix: 修正原点(00)两种原因的判断依据 —— 两种情况下脚下都是基岩
用户指出:死亡被卡到 00 时脚下**也是基岩**,所以原来用
lockBelow === 'bedrock' 区分「登录服」和「死亡卡住」是错的,
会把死亡卡住误判成登录服,于是不做自救、只让用户去输验证码。

改成以「服务器有没有要求输入验证码」为唯一可靠信号:
- 要求验证码 -> 判定为登录服,提示人工发验证码(不做无意义的左右移动)
- 没要求验证码 -> 判定为死亡卡住,自动左右移动触发服务器重新传送

自救本身在两种情况下都无害(在登录服里按左右键不会有后果),
所以即使判断错了也不会把事情弄得更糟。

另外:验证码提示往往比 spawn 晚到,所以 _handleAuthPrompt 里也补了一次判断 ——
若提示到达时机器人正好在原点附近,会明确点出「被反复传送刷屏」正是登录服造成的,
把这个因果关系讲清楚,避免用户只看到传送刷屏而不知原因。

同步修正 TODO.md 与 CHANGELOG 里那条错误结论,并标注「不要用基岩做判断依据」。

测试 363 -> 368,全部通过。
2026-09-28 20:32:49 +08:00

29 KiB
原始文件 Blame 文件历史

更新日志

本项目遵循 约定式提交 与 语义化版本。

[1.6.0] - 2026-09-29

围绕「机器人为什么走不动」做了一轮系统排查,并给破坏性操作加上护栏。

新增

  • 回城护栏:/u return 是破坏性操作 —— 它把机器人拉回安全点, 会清掉玩家在游戏客户端里手动摆好的位置。项目里曾因此反复把机器人 从玩家摆好的位置拉走,排查了很久才定位。现在:
    • returnOnTimeout 默认关闭,不再自动回城
    • 即便打开,returnGraceSeconds(默认 300 秒)内也不执行, 避免把刚摆好的位置清掉
    • returnCommand 可配置(默认 u return),适配不同服务器
    • 每次回城都明确记日志,说明「会丢失当前位置与玩家手动摆好的位置」
    • 因未启用而跳过时也会记一条说明,避免用户以为「怎么不回城了」
  • 区分「被传送到原点」的两种原因(以前在日志里长得一样,常被误判成机器人坏了):
    • 服务器要求输入验证码 → 被切到登录服,必须人工发验证码,给出明确提示
    • 服务器没要求验证码 → 死亡后被卡住,自动左右移动触发服务器重新传送(_escapeFromOrigin())
    • ⚠️ 这两种情况脚下都是基岩,所以不能用「脚下是不是基岩」区分; 唯一可靠信号是服务器有没有发验证码提示。自救在两种情况下都无害, 因此即使判断错了也不会让情况变糟
  • 移动执行诊断 moveDiag:暴露当前按下的控制键、速度、寻路器内部状态 (isMoving / isMining / goal / 剩余路径点数)。这是排查「走不动」的关键手段 —— 能一刀切开「寻路器没执行」与「执行了但服务端不认」。
  • 寻路诊断 pathingDiag:起点可走邻居数、寻路器能否通过 world.getBlock 读到方块、 四向可见距离。

变更

  • _isStandingOnGround() 增加「服务端是否正把我们按在原地」的判断 (_serverPinsUs()):短时间内反复收到几乎相同位置的位置包时, 说明在服务端眼里机器人是站着的,此时以服务端为准更安全

排查结论(已排除的方向,详见 TODO.md)

  • ❌ GrimCompat 的朝向限速不是原因:A/B 实测关闭合规层后回弹频率没有变化 (6.0 vs 5.5 次/秒,位移都是 0)
  • ❌ 疾跑不是原因:关闭后仍是 4.8 次/秒
  • ❌ 世界数据不是原因:实测脚下 stone,blockBelow 正确
  • 🎯 关键线索:寻路时 forward/sprint 确实按下、isMoving=true, 但水平速度恒为 0(velocity.y = -0.078 恰是自由落体第一 tick 的值), 说明速度每 tick 被清零;同时 bot.entity.onGround 被服务端位置包反复置为 false, 物理引擎一直按「空中」处理。下一步应从「让 entity.onGround 与出站包一致」入手。

[1.5.1] - 2026-09-28

接入 API-V2 密钥后按实测响应修正字段名(之前是按文档猜的,跑起来全不对)。

修复

  • API-V2 /players 返回的是对象不是数组:{"online":8,"max":5000,"players":[...]}, 原解析按裸数组处理会拿到空列表;且里面没有坐标与延迟,只有所在世界
  • API-V2 /dragon 的字段是 dragonAlive,不是 alive;也没有 health / phase
  • API-V2 /time 直接给算好的时刻:{world, tick, phase, time12, time24}, 原实现还在用 world_time / day_time / is_day 自己换算,全部取不到
  • API-V2 /players/{name}/equipment 的物品结构: {type, key, amount, damage, maxDurability, unbreakable},装备在 equipment 子对象里。 damage 是已损耗值,原来会把「损耗 157」当成「剩余 157」显示; 现在换算成 remainingDurability 并在界面显示「剩余 / 上限」+ 百分比
  • 限流提示:V2 触发 429 时服务端带 retryAfterSeconds,现在直接告诉用户还要等多少秒 (末影龙接口只有 1 次/分钟,实测超限时提示「还需等待 16 秒」)

新增

  • SimpApiV2Client 支持注入 fetchImpl,便于测试替换网络层

[1.5.0] - 2026-09-28

新增

  • SimpCore 开放 API 数据浏览:以前只用了「邦国领土」这一类接口,控制台也只能看到一行 「已启用 / 未启用」。现在把官方文档里的公开接口都接进来,并做成「查看 API 数据」弹层:
    • 概览:两套密钥的配置状态、请求数、缓存命中、最近 HTTP 状态与错误、健康检查按钮
    • 邦国:27 个邦国的君主 / 成员数 / 区块数 / 领土面积 / 特产 / 王城区块; 点开看成员(职位、职业)、已激活科技、捐献收支、领土统计(忠诚度、最早/最近占领)
    • 玩家:1600+ 名玩家可搜索(邦国 / 职位 / 职业 / 称号),点开看详情与所属邦国
    • 全服:生效加成 / 外交关系 / 封禁记录 / 上下线日志 / 公告历史
    • 实时 V2:在线玩家、游戏时间、末影龙、指定玩家的装备与手持物品
  • SimpApiClient 补齐到官方文档的全量接口(原来只有 7 个,现在 16 个): /info/players、/info/unions/{key}/members、/tech、/contributions、 /info/buffs、/info/diplomacy、/info/bans、/info/logs、/info/announcements
  • SimpApiV2Client(新):/players、/players/{name}/equipment、/time、/dragon。 文档明确 API 与 API-V2 是两套独立、互不通用的密钥体系,因此单独一个实例与配置; V2 配额很小(末影龙仅 1 次/分钟),一律按需查询、不做轮询

变更

  • 快捷发送去掉 /spawn 与 /list,只留 /u return /u claimmode /u restore confirm

修复(解析字段名以实测响应为准)

  • 捐献记录:响应里只有 player_uuid 没有玩家名,现在先用邦国成员表、查不到再退到全服 玩家表补全;时间字段是 contributed_at 不是 created_at;补充 reason(用途)列
  • 公告:message 是 Minecraft 聊天组件的 JSON 字符串,新增 componentToText() 压平成纯文本
  • 封禁:实际字段是 banned_player_name / banned_by_player_name / banned_at / unbanned
  • 日志:实际字段是 username / action / timestamp
  • 玩家表:上下线时间是 last_join_time / last_quit_time
  • 王城坐标:服务端可能返回 null,原来会被 Number(null) 算成 0, 伪装成「王城在世界原点 (0,0)」;现在显式判空返回 null

[1.4.1] - 2026-09-27

变更

  • 控制台输入框不再区分聊天与指令:两者本来就是同一个入口 —— 以 / 开头按游戏指令发送,否则按公屏消息发送。因此删掉了「公屏聊天 / 游戏指令」下拉框 和重复的「快捷公屏消息」输入框,只保留一个输入框 + 快捷发送 + 移动测试。 接口返回新增 kind 字段说明实际走的是哪条路,Toast 也会区分「消息已发送 / 指令已发送」
  • 快捷发送按钮补上 /u restore confirm(配合定时消息常用)

[1.4.0] - 2026-09-27

大地图改为跟随机器人、支持可调图幅;新增定时重复发送消息;控制台界面重做并适配移动端。

新增

  • 定时重复发送消息 / 指令(src/bot/scheduledMessenger.js)
    • 每个机器人可配置多条定时任务,按固定间隔重复发送同一条内容, 例如每 300 秒发一次 /u restore confirm 维持疆土民心
    • 以 / 开头的内容自动按游戏指令发送,否则按公屏消息发送
    • 只在「已连接 + 已通过登录验证」时才发;未就绪的周期直接顺延、不补发, 避免重连后一次性连发多条
    • 与指令节流队列共用,不会绕过 server.commandCooldownMs 刷屏
    • 控制台新增「定时消息」卡片:新增 / 删除 / 启用停用,并显示距下次发送的剩余秒数
    • 接口:GET|POST /api/bots/:id/schedules
  • 大地图跟随机器人 + 可调图幅
    • 爬取与显示区域改为以机器人当前位置为中心(bigMap.followBot,默认开启), 不再傻傻地爬世界原点周边
    • 界面新增「图幅」下拉框(±512 / ±1024 / ±2048 / ±4096 / ±8192 / 全世界), 切换后即时重新对焦并拉取对应范围
    • 新增「爬取周边」按钮:只爬当前图幅内的瓦片。 层级 0 每张瓦片覆盖 4096 格,所以 ±4096 只需 9 张,而全世界要 100 张
    • POST /api/bigmap/crawl 支持 centerX / centerZ / rangeBlocks; GET /api/bigmap 支持 rangeBlocks 与 bot 查询参数
    • 启动预爬取会先等机器人进入世界,以它的位置为中心;等不到才退回世界原点
  • 领土地图以机器人所在邦国为中心
    • 之前初始视图用的是控制器的 playerChunk,而任务启动前它是 (0,0), 导致地图永远停在世界原点附近 —— 完全不是用户关心的位置
    • 现在按「机器人所在区块 → 包含它的邦国 → 该邦国王城 / 外接矩形」定位
  • 控制台界面重做 + 移动端适配
    • 重新设计的深色主题:统一圆角、阴影、焦点态与悬停态,卡片式分层
    • 响应式三档:≥1200px 三栏;≤1200px 两栏(配置栏落到下方并自动分列);≤820px 单栏
    • 移动端:底部导航(状态 / 地图 / 日志 / 配置)一键定位、触控目标放大到 ≥36px、 地图与日志高度按视口自适应、避让底部安全区、Toast 全宽
    • 横屏手机压矮地图高度;尊重系统「减少动效」偏好
    • 「添加玩家」折叠进 details,减少左栏长度
    • 顶栏在窄屏下自动换行,按钮等分排布

变更

  • 大地图默认图幅从「全世界 ±20480」改为「±4096 格」,默认预爬取瓦片数从 100 张降到 9 张
  • 「回到机器人」保留并修正:没有坐标时给出明确提示,而不是静默无反应

修复

  • POST /api/bigmap/crawl 的响应把中心与图幅字段传错(实际爬取是对的,但返回值显示成世界原点)
  • 定时任务保存后接口返回的是原始列表而非归一化结果,导致前端拿不到「剩余秒数」

[1.3.0] - 2026-09-27

按线上实测结果修复「机器人走不动」,并移植旧版机器人已验证的关键补包。

修复

  • 控制台登录按钮点不动(致命):bindEvents() 只在 startApp() 里执行,而 startApp() 只在登录成功后才跑 —— 未登录时登录按钮根本没绑上事件,形成死锁。 现在登录相关按钮在 main() 里无条件绑定
  • 机器人走不动(致命,根因已定位并修复):mineflayer 不发 player_input 包。 1.21.2+ 服务端的移动预测依赖它,原版客户端每 tick 都发,而 mineflayer 只在 骑乘 / 跳下 / 潜行时发,地面移动的 forward / jump / sprint 完全不发。 带反作弊的服务器因此判定「没有任何输入却发生了位移」,每 tick 把玩家拉回原位置。 实测:修复前入站强制位置同步约 17 次/秒、按方向键 2 秒位移 0.00 格; 修复后入站降到 0 次、位移 0.53~1.40 格。 同时补发原版每 tick 末尾的 tick_end 包(反作弊用它判定 tick 边界,mineflayer 完全不发)
  • 寻路插件从未加载:项目从没调用 bot.loadPlugin(pathfinder),bot.pathfinder 恒为 undefined、isReady() 恒为 false,扩地任务连启动都启动不了
  • 寻路事件监听重复注册:configure() 每次配置变更都会重跑并再挂一遍监听, 导致同一事件被处理多次(日志里同一秒出现多条相同事件)
  • 资源包未自动接受:服务器要求资源包时不接会卡在加载界面进不了世界

新增

  • 长距离分段寻路:mineflayer-pathfinder 只能规划已加载区块范围(实测约 8 区块 ≈ 130 格), 而扩地目标常在几十个区块之外,A* 会瞬间返回 noPath。现在会把旅程拆段: 走到已加载范围边缘附近 → 新区块加载 → 再规划下一段。 段长用 bot.blockAt 对未加载区块返回 null 的特性二分探测得到,不依赖世界内部结构
  • 寻路预算可配置:pathing.thinkTimeoutMs / tickTimeoutMs / searchRadius (searchRadius 为负表示不限制剪枝)
  • 位置同步诊断:位置包收发计数、player_input / tick_end 计数、onGround、 游戏模式、维度、脚下方块、六向「脚部 / 头部 / 地面」与可通行判定
  • 手动移动测试:控制台按钮绕开寻路器直接按方向键并回报真实位移
  • 配置界面新增协议补包与寻路预算相关字段

已知限制(重要)

  • 当前所在位置无法寻路:实测机器人站在 (6759, 72, 11926) 时,A* 恒定只展开 47 个节点 就返回 noPath。已逐项排除:挖方块 / 放方块 / 跑酷 / 搭塔 / 开门 / 最大下落(试到 64 格)/ 高度偏好 / 水域代价 / 搜索半径(试到不限制)/ 时间预算 / 依赖版本 (与能正常移动的旧机器人完全一致:mineflayer 4.39.0 + pathfinder 2.4.5 + prismarine-world 3.7.0)。 旧机器人日志证明寻路本身可用(2 次 goal_reached、2 秒走过 8.7 格), 但它当时在 y=-59,而本机器人被 /spawn 放到了 y=72,怀疑是新位置的地形让移动生成器 找不到任何可行走分支。下一步需要把机器人挪到开阔地再试

[1.2.0] - 2026-09-27

首次真正连上线上服务器(Debian 12 + pm2 + 端口 78)后,暴露并修掉了一批 只有实机运行才会发现的缺陷。这些问题的共同点是:单元测试全绿,但机器人根本干不了活。

修复

  • 寻路插件从未加载(致命):项目从没调用过 bot.loadPlugin(pathfinder), 导致 bot.pathfinder 恒为 undefined、isReady() 恒为 false, 扩地任务连启动都启动不了,而界面上只显示一句含糊的「机器人尚未就绪」。 现在在 createBot 之后立刻加载,失败时明确报错
  • 登录门禁死锁:/login、/register、简幻通的 /auth 本身就是登录流程的一部分, 原先的门禁把它们一并拦下,形成「要先登录才能发登录指令」,账号永远卡在未验证状态。 新增 server.preLoginCommands 白名单(默认 login,l,register,reg,auth)
  • 验证码发不出去:部分服务器要求把验证码直接当聊天内容发出去(不是指令), 而 sendChat 同样被登录门禁挡住。现在服务器明确要求验证时会自动放行聊天, 另有 server.allowChatBeforeLogin 给无提示的服务器兜底
  • 配置了登录指令却没密码时永久卡死:.env 里没有密码时程序无法发送任何登录指令, 却把 loggedIn 永久置为 false,控制台连手动指令都发不出去。 现在走与「服务器不回提示」一致的兜底逻辑(超时后按无需登录放行),并在日志里说明
  • 离线时指令被静默丢弃却回报「已发送」:bot.chat() 在未连接时无处可发。 现在 canSendCommand() 要求已连接并进入世界,失败信息区分 「未连接」「登录被服务器拒绝」「未通过登录验证」三种情况
  • 「被服务器传送」日志洪水:账号未完成服务器验证时服务端每 tick 强推一次位置, 实测 3 分钟刷出 748 行日志,几十分钟就会冲光日志环形缓冲并把 WebSocket 打满。 现在首次立即记录、其余按 30 秒窗口聚合,断开连接时刷出未汇总计数
  • 外站账号绑定流程无法识别:原先只认 /login 与 /register, 遇到要求 /auth <UID> <验证码> 或扫码绑定的服务器时,表现只是静默的死循环。 现在命中相关提示会输出可操作的中文告警(每个连接只提示一次), 并新增 server.authCommand 模板供有固定验证码的服务器自动过验证
  • 重连无退避:连续被踢时每 10 秒硬撞服务器。现在按指数退避 (server.reconnectMaxDelayMs,默认上限 120 秒),成功进入世界后计数清零
  • 控制台瓦片 URL 与后端路由不一致:前端请求 /api/bigmap/tile/:z/:x_y.png, 后端路由为 /api/bigmap/tile/:z/:x/:y.png

新增

  • 控制台添加 / 移除玩家:不必改 .env 重启,直接在界面上填玩家名 + 密码即可挂新账号。 密码只写入服务器本地凭据文件 data/bots.credentials.json(权限强制 0600), 不进仓库、不出现在任何接口响应里;.env 与凭据文件同名时以 .env 为准。 .env 里配置的账号不允许从控制台移除(否则重启后会「复活」)
  • 手动移动测试:控制台可按前 / 后 / 左 / 右 / 跳 2 秒并显示真实位移, 用于区分「寻路器算不出路径」与「客户端根本走不动」这两种完全不同的故障 (绕开寻路器直接走控制键)
  • 位置同步诊断:snapshot 暴露位置包收发计数、onGround、游戏模式、维度、 脚下方块与六向实心情况,/api/bots/:id/status 可直接看到
  • 按世界数据修正出站 onGround(grim.reportOnGroundFromWorld,默认开启): mineflayer 收到服务端 position 包时会把 entity.onGround 置为 false, 在频繁下发位置包的服务器上会导致客户端持续上报「站在地上却在空中」。 现在发包前用脚下方块复核,只有确实不一致时才改写
  • scripts/check-protocol.js:核对 mineflayer 写出的包名 / 字段名与目标版本协议是否一致

已知限制(重要)

  • 本服上 mineflayer 客户端无法移动:实测(DiLiDaLaDaLa,已绑定简幻通、登录正常) 按方向键 2 秒位移 0.00~0.02 格;服务端每 tick 回弹一次(入站 ~17/s、出站 ~19/s)。 已系统性排除:区块数据缺失、onGround 不一致、Grim 合规层、游戏模式(survival)、 物理引擎未启用、寻路插件缺失、teleport_confirm 协议字段不匹配。 连接、登录、收发指令、收发聊天、公屏日志、大地图爬取均正常,唯独移动被服务端拒绝。 彻底定位需要把客户端的移动包与原生客户端逐字节对比,属于独立的排查工作
  • 同机上原有的 minecraft-bot(端口 91)与该机器人不能同时使用同一账号,会互相踢下线

[1.1.0] - 2026-09-27

新增多机器人挂机、开拓日志、游戏公屏完整日志与大地图。

新增

  • 多机器人同时挂机(src/bot/botPool.js、src/config/botsConfig.js)
    • .env 里用 MC_BOTS 一次配置多个账号(支持 JSON 数组与 用户名:密码 逗号分隔两种写法), 未配置时回退到 MC_USERNAME / MC_PASSWORD 单机器人模式
    • 每个机器人独立连接、独立登录、独立跑扩地状态机;共享同一份领土数据服务与运行日志
    • 密码只从 .env 读取:data/bots.json 只存启用状态、备注名、是否自动开始与各自的配置覆盖
    • 每个机器人可有自己的扩地配置覆盖(策略、目标邦国、目标数量等),未覆盖字段回退全局默认
    • 控制台新增机器人列表(连接状态 / 坐标 / 任务 / 已开拓数)、机器人切换、全部开始 / 全部停止
  • 开拓日志(src/core/expansionLog.js)
    • 逐条记录开拓玩家、邦国、区块、方块坐标、时间、判定来源,追加写入 data/expansion-log.jsonl
    • 支持按机器人 / 邦国 / 时间筛选、按机器人统计与今日计数、导出带 BOM 的 CSV
    • 文件超过 16MB 自动轮转为 .1;进程被杀留下的半行在重启时被安全跳过
    • 控制台新增「开拓日志」表格页签,支持筛选、清屏、导出
  • 游戏公屏完整日志 + 聊天框(src/core/chatLog.js)
    • 每个机器人收到的全部公屏 / 系统 / 动作栏消息按机器人分文件落盘(data/chat/<机器人>.jsonl)
    • 本机器人发出的聊天与指令同样留档,可对照「指令发出后服务器回了什么」
    • 控制台新增「公屏聊天」页签(可按机器人或全部机器人查看、关键字筛选、导出)与公屏消息发送框
  • 登录验证门禁
    • 游戏侧:未完成服务器登录验证时拒绝发送指令 / 聊天,且 isReady() 不放行扩地任务; 新增登录结果确认兜底(server.loginConfirmTimeoutMs),避免服务器不回提示导致机器人永远卡在未登录
    • 控制台侧:新增 WEB_PASSWORD 与 /api/login、/api/session,页面弹出登录框, 验证通过后才允许操作各机器人的控制台、聊天框与扩地任务
  • 大地图(src/core/bigMapService.js)
    • 爬取服务器地图站点(squaremap)的瓦片图片与领土标记,拼在一张图上查看所有机器人的坐标
    • 坐标系已对源站实测标定:瓦片 512×512,层级 0 每张覆盖 4096 方块,层级 3 为 1 方块 1 像素 (用 27 个王城坐标交叉验证:正确公式下王城所在瓦片平均海洋占比 28.7%, 错误假设为 41.6% / 47.3% / 76.0%)
    • 瓦片磁盘缓存 data/mapcache/,默认启动时预爬取层级 0(全世界 10×10=100 张), 更高层级按需穿透拉取并永久缓存;/api/bigmap/tile/:z/:x/:y 代理避免跨域
    • 领土以 markers.json 的原始多边形绘制(预编译为 Path2D),叠加本次会话新占领区块、 王城与全部机器人坐标;支持滚轮缩放、拖拽平移、全世界 / 回到机器人一键定位
  • 测试从 154 个增加到 242 个:新增开拓日志、公屏日志、大地图坐标系与缓存、 机器人池与配置隔离、凭据解析、机器人登录门禁、多机器人 Web 接口与登录鉴权等用例

变更

  • TerritoryModel 新增 flyingChunksOf() / ownChunksOf(),邦国归属改为按名称显式传入, 不再依赖全局 selfStateName(多机器人会互相覆盖);同时保留 markers.json 的原始多边形
  • ExpansionPlanner 的己方邦国解析顺序改为「配置里的 stateName → 模型全局 selfStateName」
  • 运行日志统一加机器人名前缀([游戏名] …),多机器人共用一份日志也能分清来源
  • Web 接口改为以 /api/bots/:id/... 为主,原有单机器人接口(/api/task/*、/api/command、 /api/bot/reconnect)保留为默认机器人的等价别名
  • /api/map 支持 ?bot=<id> 按机器人视角返回其邦国、目标与玩家区块

修复

  • 修正控制台地图瓦片 URL 与后端路由不一致的问题(前端请求 /api/bigmap/tile/:z/:x_y.png, 后端路由为 /api/bigmap/tile/:z/:x/:y.png)
  • 「被服务器传送」日志洪水:账号未完成服务器验证时,服务端会每 tick 强推一次位置, 实测 3 分钟刷出 748 行日志,几十分钟就会把 2000 条的日志环形缓冲冲光、并把 WebSocket 打满。 现改为首次立即记录、其余按 30 秒窗口聚合成一条(被服务器传送另有 N 次), 并在连接断开时把未汇总的计数刷出去
  • 外站账号绑定流程无法识别:本项目原先只认 /login 与 /register, 遇到「简幻通」这类要求 /auth <UID> <验证码> 或扫码绑定的服务器时, 表现只是「连上 → 被传送 → 120 秒后被踢 → 重连」的静默死循环,失败原因对用户完全不可见。 现新增 NEED_AUTH_PATTERN 识别,命中后输出可操作的中文告警(每个连接只提示一次), 并新增 server.authCommand 模板供配置固定验证码的服务器自动过验证
  • 重连无退避:连续被踢时每 10 秒硬撞一次服务器。现按指数退避拉长间隔 (server.reconnectMaxDelayMs,默认上限 120 秒),成功进入世界后计数清零
  • 登录门禁死锁:有些服务器的登录流程本身就是指令(/login、/register, 简幻通体系还要先 /auth),原先的门禁把这些指令也一并拦下,导致 「要先登录才能发登录指令」,账号永远卡在未验证状态。 现新增 server.preLoginCommands(默认 login,l,register,reg,auth)白名单, 这些前缀在未验证时也放行;其余指令仍要求已完成验证
  • 离线时指令被静默丢弃却回报「已发送」:bot.chat() 在未连接时无处可发, 原先调用方只会收到「已发送」。现在 canSendCommand() 要求已连接并进入世界, 且失败信息会区分「未连接」「登录被拒」「未通过验证」三种情况并给出对应处理建议

已知限制

  • 多个机器人共享一份领土模型:markers.json 是全服数据,没必要每个机器人各拉一遍; 因此「会话新占领」区块是全局共享的,控制台地图的己方邦国显示的是最近启动的那个机器人的邦国
  • 大地图层级 3 不预爬取:全图 80×80=6400 张瓦片约 200MB,改为按需拉取 + 永久缓存
  • 扫码类账号绑定无法自动化:/auth <UID> <验证码> 的验证码是动态的、扫码更是需要人工, 程序只能明确报错提示;绑定是一次性的,绑定成功后同一账号即可自动登录

[1.0.0] - 2026-02-14

由 Fabric 客户端模组 AutoStore v1.3.1 重构为 Node.js + mineflayer 机器人,UI 改为网页控制台, 并新增 Grim 反作弊合规层。

新增

  • Grim 反作弊合规层(src/bot/grimCompat.js)
    • 旋转不超前:接管 bot.look,把朝向按 ≤ 8.6°/tick 逐步推进,保证本地朝向与服务端已收到的朝向一致, 消除 mineflayer「本地朝向瞬间跳变、数据包滞后补发」导致的 Prediction 分歧
    • 攻击三重校验:朝向已同步 + 距离 ≤ 3.0 格 + 视线可达 + 攻击冷却 + 非骑乘/进食状态
    • 动作互斥:拦下疾跑+潜行、疾跑+使用物品等原版不可能出现的组合(MultiActions)
    • 物理参数只读自检:核对 bot.physics 关键常量、physicsEnabled、游戏模式、鞘翅状态
    • 寻路约束:默认禁止挖方块 / 放方块 / 跑酷 / 1×1 搭塔,限制最大下落高度,推高液体代价优先绕开水域
  • 网页控制台(src/web/)
    • 实时状态面板(连接 / 任务状态机 / 领土数据源 / Grim 合规)
    • Canvas 领土地图:滚轮缩放、拖拽平移、图层开关、回到玩家、全图适配
    • 7 个分组的配置表单,保存即生效
    • 实时日志流、日志导出、手动指令发送
    • REST + WebSocket 接口,支持 WEB_TOKEN 令牌鉴权(定时安全比较)
  • SimpCore 开放 API 第四数据源:低频轮询己方邦国领土明细 + 王城兜底,支持手动拉取全服领土
  • 开垦时段可配置:enforceClaimTime / claimStartHour / claimEndHour(原版硬编码 11:00-22:00)
  • 战斗筛选可配置:combat 分组(索敌半径、末影人 / 蜘蛛 / 猪灵开关、高危生物跳过)
  • 断线自动重连与登录 / 注册指令模板(密码从 .env 读取,支持 {password} 占位符)
  • 154 个测试用例,覆盖坐标编解码、领土模型、规划器、数据解析、合规层、状态机、Web 接口

变更

  • 寻路引擎从 Baritone 换成 mineflayer-pathfinder;高度偏好(GoalXZAltitude)用包装 Goal 的 heuristic = max(0, base - weight × y) 等价移植
  • 区块坐标内部表示从对象改为整数键(x × 2^26 + z),避免数万区块产生海量临时对象
  • 扩地状态机、规划策略、超时重试与回城逻辑与原版逐行对照移植,行为保持一致

修复

  • 修正 containsFuzzy 的模糊匹配:原实现只取固定长度前缀的末行编辑距离, 导致 containsFuzzy('开垦中 50%', '开垦中', 0) 返回 false(完全相同的子串都匹配不上)。 现按注释语义改为「存在编辑距离 ≤ maxEdits 的子串」
  • 修正占领去重:原实现依赖 Set.add 的返回值判断重复,而 JS 的 Set.add 恒返回 Set 对象, 会导致同一区块被重复计数
  • 修正非法枚举值的处理:策略等枚举字段不再「钳制到最近边界」(把非法的 99 静默变成策略 4), 而是回退到默认值

已知限制

  • 自动用船默认关闭:mineflayer 使用的 prismarine-physics 没有载具物理,上船后本地物理预测被关闭, 位置完全由服务端下发的船实体位置决定,Grim 的 Vehicle 检查风险高。 用船逻辑已完整实现,需显式开启 waterMode: 'boat' + autoBoat: true
  • 末影人与蜘蛛默认不打:mineflayer 拿不到可靠的「是否被激怒」与「环境亮度」信息, 宁可漏打也不误打;可用 combat.attackEnderman / combat.attackSpiders 放开
  • 监守者 / 末影龙 / 凋灵默认跳过:原版会攻击它们,但那基本等于自杀