lyizai
|
1b958cb804
|
fix: 自动恢复不再因一次失败的尝试而永久丢失
1.9.3 的 tick() 里先取走 resumeConfig 再调 start(),而 start() 在
「已进入世界但还没完成登录」时会直接返回 false(isReady() 要求 loggedIn)。
本服掉线频繁、重连后常常短暂处于这个状态,于是第一次失败的尝试就把这次恢复
永久丢掉了,任务再也不会自己接上 —— 实测监控里任务长时间停在
「机器人尚未就绪(未连接 / 未进入世界)」就是这个原因。
现在:① 等 bm.isReady() 才尝试;② 只有 start() 真的返回 true 才清掉登记,
失败时保留并在下一 tick 继续试,日志打「自动恢复未成功(…),稍后重试」。
顺带:服务器上保存的 pathing.maxDropDown 被改成了 64(钳制上限),
而原版摔落伤害超过 3 格后每格 1 点、23 格必死 —— 实测机器人正是
「fell from a high place」摔死并重生回王城,白走了 100 多格。
已在服务器配置上改回 4(代码默认本来就是 3)。
测试 477 → 478。
|
2026-10-01 17:22:11 +08:00 |
|
lyizai
|
2ae2833568
|
feat: 补上出站包一直漏报的 hasHorizontalCollision(1.10.0)
针对「机器人一直在走、净位移却只有物理速度的 1/5」这个现象。
mineflayer 在 physics.js 里把 flags.hasHorizontalCollision 写成 undefined
(源码注释还标着「1.21.3+」),位标志序列化后恒为 0 —— 而原版客户端在水平碰到
方块时会上报 1。机器人在崎岖地形上几乎一直在水平碰撞,却始终上报「没碰撞」,
正是反作弊 Prediction 最容易判错的形态:服务端按「该碰撞」预测、客户端说
「没碰撞」,于是被判异常并拉回。
物理引擎其实早已算出真实值(moveEntity 里给 entity.isCollidedHorizontally 赋值),
只是从没被发出去。现在在 _fixOutboundOnGround 里按真实值补上,由
grim.reportHorizontalCollision(默认开)控制。
实测依据(王城外山区,2 秒粒度采样 120 秒):
- controls 几乎每 tick 都是 forward+sprint,velocity 约 0.2~3 格/秒;
- 净位移只有 48.6 格 / 120 秒 = 0.405 格/秒,差额就是被服务端拉回的部分。
顺带把 _fixOutboundOnGround 拆成 _fixOnGroundFlag / _fixHorizontalCollisionFlag
两个职责单一的方法;控制台配置面板新增对应开关,
packetStats.horizontalCollisionFixed 暴露补写次数。
测试 473 → 477。
|
2026-10-01 17:04:25 +08:00 |
|
lyizai
|
0bed12e189
|
feat: 掉线重连后自动恢复扩地任务(autoResumeAfterReconnect)
本服会周期性把机器人踢下线(实测约 1~6 分钟一次,踢出原因是
"An internal error occurred in your connection"),每次都会走到「世界已退出,任务停止」。
原来的行为是就此停住 —— 机器人虽然能被原点自救送回真实世界(实测 4/4 成功),
却再也不会继续扩地,于是永远停在原地。
现在世界退出时把本次任务的配置记下来(resumeConfig),
重新进入世界后自动 start() 接上;状态文案改为「世界已退出,等待重连后自动恢复」,
并打印「已重新进入世界,自动恢复扩地任务」。
只有因世界退出而停的那次会登记:手动停止 / 到开垦时段外 / 耐久保护停机
都会在 stop() 里清空 resumeConfig,不会被重连重新拉起。
开关 autoResumeAfterReconnect 默认开启,可关。
测试 470 → 473。
|
2026-10-01 16:34:56 +08:00 |
|
lyizai
|
5513ef9f5f
|
fix: 物理录制器区分「被服务端推回」与「输入没进物理」
原来 frozenTicks 只看「有输入 + tick 级无位移 + 物理没报告碰撞」,
但服务端推回发生在 tick 之间,tick 级位移同样是 0 —— 实测大厅里就是这个形态:
collidedHorizontally = false、frozenTicks = 194,而物理其实每 tick 都在动。
现在再按水平速度是否非零细分:
- pushedBackTicks:速度非零 → 物理确实动了,位移被服务端位置包抹掉;
- frozenTicks:速度也是 0 → 这才是「输入根本没进物理」。
类注释里的判定表也同步改成三分法(被挡住 / 被推回 / 输入没生效)。
测试 469 → 470。
|
2026-10-01 16:28:14 +08:00 |
|
lyizai
|
3a508f6818
|
fix: 高度偏好默认关闭 —— 它让寻路器完全规划不出路径(自动扩地的直接拦路虎)
实测定位:高度偏好的启发值实现与 mineflayer-pathfinder 的内部约定冲突。
该库每次 compute() 返回 partial 时,用 h 最小的节点当 partial 路径的终点
(astar.js: if (neighborNode.h < this.bestNode.h) this.bestNode = neighborNode),
而 AltitudeGoal 把 h 减去了 权重 × y,于是「又高又偏」的节点 h 反而更小,
partial 路径被引向高处而不是目标附近 —— A* 一直在算、永不收敛,
机器人一次移动指令都发不出来。
王城平台上的对照实测(其余配置完全相同):
- altitudePreference = true → inputTicks = 0,任务永远停在「寻路超时,重新寻路」
- altitudePreference = false → inputTicks = 237,立刻开始移动
顺带排除:searchRadius 从 -1 改到 128 对结果没有任何影响,
所以不是「搜索空间无界」导致的;pathfinder 与 manual 两种执行器表现一致。
改动:
- expansionConfig 默认 altitudePreference 改为 false,并在注释里写清原因与
「想重新启用应该怎么做」(把偏置改成低处加移动代价,保持启发值只反映真实距离);
- AltitudeGoal 的类注释补上完整推导与实测数据,避免以后有人又把它打开;
- 新增回归用例:断言默认关闭,并用启发值差值把「为什么必然出问题」固化下来。
测试 468 → 469,全绿。
|
2026-10-01 00:34:51 +08:00 |
|
lyizai
|
b2b0317af7
|
feat: 新增物理 tick 录制,把「走不动」的三种原因切开(1.9.0)
抓包已经证明「手动按键时客户端坐标一字未变、服务端入站位置包为 0」,
问题在 prismarine-physics 这一层;但抓包只能看到「发出去的包」,
看不到物理引擎内部读到了什么输入、算出了什么、有没有真的移动。
本提交补上这最后一块拼图。
新增 src/core/physicsRecorder.js + 控制台接口
(POST /api/bots/:id/physics/start|stop、GET /api/bots/:id/physics):
逐 tick 记录位置增量、速度、onGround、isCollidedHorizontally、控制键快照、
脚下/脚部/头部方块名、physicsEnabled;汇总给出四个判定计数:
- inputTicks 有移动输入的 tick 数
- inputMovedTicks 其中真的产生了水平位移的
- blockedTicks 有输入、没位移、物理报告碰撞 → 被方块挡住(地形)
- frozenTicks 有输入、没位移、物理没报告碰撞 → 输入根本没进物理
即:抓包看「发了什么」,本录制器看「物理读到了什么、动没动」,两者配合即可定位。
细节:
- 录制开始时先取一次当前位置作基线,避免第一个 tick 因「没有上一 tick 可比」
被误判成「有输入但没动」;
- 滚动缓冲只保留最近 240 个 tick(约 12 秒),只放内存、不写盘;
- 录制全程 try 包裹,诊断自身出异常绝不影响物理循环;
- FakeBot 补上与 mineflayer 一致的 controlState(带 getter 的实时控制键代理)。
测试:451 → 468 个用例(含三种故障判定的回归用例与控制台接口用例),全绿。
|
2026-09-30 21:05:38 +08:00 |
|
lyizai
|
8ab2d59eb0
|
feat: 新增出站包抓取,供「走不动」逐包对照(TODO 假设 5)
线上实测确认手动执行器(1.7.0 备选方案)不能解决「走不动」:前 20 秒走 13 格后
即卡在「执行中断(stuck)→重规划→缩短段长→跳过目标→重新规划同一目标」的死循环。
只靠 packetStats.outboundTypes 的计数看不出「发出去的内容对不对」,所以补一个
能录原始出站序列、并能在「能走」与「走不动」两种状态下 diff 的诊断能力。
新增 src/core/packetCapture.js:
- 只在录制期间挂钩 client.write,其余时间零开销(该钩子每个出站包都要过一遍);
- 录到的内容做降深 + 截断的 JSON 化处理,向量对象只留坐标
(move_minecart 这类包能带上万个浮点数,不处理会把缓冲区撑爆);
- 只放内存、有上限(默认 4000 包),不写盘。
接口(控制台):
- POST /api/bots/:id/capture/start(可带 seconds 到点自动停止)
- POST /api/bots/:id/capture/stop
- GET /api/bots/:id/capture(支持 ?types= 与 ?limit=)
顺带修掉两个先前就存在的问题:
- scripts/check-protocol.js 其实一直跑不通:minecraft-data 的
types.packet[1][1].type[1].fields[包名] 给的是类型名字符串,
要再去 types[名字] 取 ['container', [字段...]] 才能展开,原实现直接 .map() 必然抛错;
另有读 node_modules 少一层 '..' 的路径问题。
- 两条租约用例(expansionController / targetLease)的时序余量只有 15ms,
全量并行跑测试时偶发失败;改为 TTL 400ms 配 280ms 睡眠,各留 120ms 余量,
断言内容不变。
测试:436 → 451 个用例,连续 16 轮全量运行全绿。
|
2026-09-29 22:01:02 +08:00 |
|
lyizai
|
51664c55b6
|
feat: 1.7.0 落地 TODO 全部待办(地面修正 / 手动执行器 / 自救 / 回城 / 租约 / 通知)
按 TODO.md 的优先级把待办全部落地为代码,详见 CHANGELOG 的 [1.7.0]。
- 「走不动」攻关:地面状态修正(syncGroundToPhysics / trustSetbackOnGround)、
出站包类型分布、备选执行器 manualMover(只借 A* 规划、自己按键执行)
- 原点自救分两轮并统计成败;回城前评估「原地是否更差」并记录前后坐标
- 新增目标区块租约表(targetLease)避免多机器人撞同一块
- 定时消息支持 cron 与「期望回复」确认;新增人工介入 Webhook 通知(notifier)
- 大地图后台预热与视野裁剪;控制台日志按帧批量写入、配置面板支持搜索
顺带修掉两个影响部署的细节:
- 部署脚本(deploy.js / ssh-helper.js)改为也能从 .env 读 SSH 凭据 ——
在命令行传密码会留在 shell 历史与进程列表里,写进已被忽略的 .env 更安全;
显式环境变量仍然优先。.env.example 补上占位符并说明这些只在本机用。
- package.json / package-lock.json 版本对齐到 1.7.0(此前停留在 1.1.0,
与 CHANGELOG 的语义化版本声明脱节)。
测试:368 → 436 个用例,`npm test` 与 `npm run check` 全绿。
|
2026-09-28 22:46:39 +08:00 |
|
lyizai
|
8d1b8d5122
|
docs: 部署方法固化进仓库(一键部署脚本 + 完整运维文档)
之前部署用的 SSH 助手放在系统临时目录里,重启就丢了,下一位接手时根本拿不到。
现在把它搬进仓库并补齐文档:
新增
- scripts/ssh-helper.js:SSH 执行与 SFTP 上传。Windows 自带 OpenSSH 但没有
sshpass/plink,无法非交互传密码,所以用 ssh2 直接实现协议层。
凭据全部走环境变量(SSH_HOST/SSH_PORT/SSH_USER/SSH_PASS),脚本里不含任何密钥;
ssh2 是 devDependencies,未安装时提示安装而不是裸崩
- scripts/deploy.js:一键部署 —— 打包 → 上传 → 远程执行 update.sh →
轮询确认控制台返回 200,任一步失败都明确报错。可选 DEPLOY_APP / DEPLOY_PORT
- npm scripts:deploy、ssh
文档
- TODO.md 新增「部署方法」章节:一键部署与手动部署两种步骤、辅助脚本说明、
update.sh 的行为、pm2 与日志的常用运维命令(含回滚)、服务器上关键文件清单、
新增环境变量时的三件事(.env 真实值 + .env.example 占位符 + 确认 gitignore)
- README「部署到服务器」开头加一键更新说明,并指向 TODO.md 的完整章节
- 顺带提醒旧版 Fabric 模组源码在临时目录里会被清理,接手后建议先备份
测试 368 全绿;一键部署已实跑验证(4/4 校验通过,控制台 200 OK)。
|
2026-09-28 20:45:08 +08:00 |
|
lyizai
|
39624da2d5
|
feat: 支持多机器人挂机、开拓日志、公屏完整日志与大地图
多机器人(src/bot/botPool.js、src/config/botsConfig.js)
- .env 用 MC_BOTS 一次配置多个账号(JSON 数组或 用户名:密码 逗号分隔),未配置时回退单机器人
- 每个机器人独立连接 / 登录 / 扩地状态机,共享一份领土数据服务与运行日志
- 密码只从 .env 读取;data/bots.json 只存启用状态、备注名、自动开始与各自的配置覆盖
- 每个机器人可覆盖全局配置(策略 / 目标邦国 / 目标数量等),未覆盖字段回退全局默认
开拓日志(src/core/expansionLog.js)
- 逐条记录开拓玩家、邦国、区块、方块坐标、时间与判定来源,追加写入 data/expansion-log.jsonl
- 支持按机器人 / 邦国 / 时间筛选、统计、导出带 BOM 的 CSV,超过 16MB 自动轮转
游戏公屏完整日志与聊天框(src/core/chatLog.js)
- 每个机器人的全部公屏 / 系统 / 动作栏消息按机器人分文件留档,自身发出的聊天与指令同样留档
- 控制台新增公屏聊天页签与消息发送框
登录验证门禁
- 游戏侧:未完成登录验证时拒绝发送指令 / 聊天,isReady() 也不放行扩地任务;
新增 server.loginConfirmTimeoutMs 兜底,避免服务器不回提示导致永远卡在未登录
- 控制台侧:新增 WEB_PASSWORD 与 /api/login、/api/session,页面登录框验证通过才允许操作
大地图(src/core/bigMapService.js)
- 爬取服务器地图站点(squaremap)的瓦片图片与领土标记,一张图上看全部机器人坐标
- 坐标系对源站实测标定并用 27 个王城交叉验证;瓦片磁盘缓存,层级 0 启动预爬取、更高层级按需穿透
- 领土按 markers.json 原始多边形绘制(预编译 Path2D,even-odd 保留孔洞),叠加王城与机器人标签
配套改造
- TerritoryModel 新增 flyingChunksOf / ownChunksOf,邦国归属改为按名称显式传入,
不再依赖全局 selfStateName(多机器人会互相覆盖)
- Web 接口以 /api/bots/:id/... 为主,原单机器人接口保留为默认机器人的等价别名
- 新增 scripts/check-web-ids.js 校验前端元素引用一致性
测试从 154 增至 242,全部通过。
|
2026-09-27 21:22:57 +08:00 |
|
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 |
|