lyizai
1339765152
docs: 记录当前进展与剩下的四个拦路虎
...
修好高度偏好后机器人确实能朝目标走(实测 20 分钟前进 95 格),
但要真正开垦出第一块地还要跨过:
① 几何约束:规划器按到玩家的曼哈顿距离取最近的合法候选,而机器人出生在王城 ——
它在「养老院」这个 33037 区块(约 180×180 区块)的大邦国正中间。
实测最近候选在 53 区块(≈768 格)外,且 targetCount=1 只返回一个候选,
长途跋涉是邦国几何决定的,绕不开。
② 服务器踢人,三种原因都实测到过:
An internal error occurred in your connection(最常见,1~6 分钟一次)、
You are sending too many packets!、Flying is not enabled on this server,
外加未验证时的「验证超时」。实测出站 57.9 个/秒(pong 30.6、协议补包 23.9、
位置包 1.35)。注意协议补包当初的立论依据已被证伪(真因是高度偏好),
它们是否仍必要、是否就是「发包太多」的原因尚未验证。
③ 半路会死:fell from a high place / was slain by Zombie。
摔死已处理 —— 服务器配置里 maxDropDown 被改成 64(钳制上限),
而原版超过 3 格每格 1 点、23 格必死,已改回 4(代码默认本来就是 3)。
被僵尸杀还没处理。
④ 推进速度只有物理速度的 1/5(净位移 0.405 格/秒 vs velocity 0.2~3 格/秒),
差额是被服务端拉回。已补上 hasHorizontalCollision(1.10.0),
该标志确实一直在被漏报(补写计数涨到 1 万+),但提速效果尚未量化验证。
2026-10-01 17:33:23 +08:00
lyizai
ed55308885
docs: 记录突破 —— 修掉高度偏好后扩地真的跑起来了
...
TODO 第 1 节从 🔴 改为 🟢 ,写清根因、生产对照实测与修复后的推进数据。
根因:AltitudeGoal 把高度偏置加在启发值上,而 mineflayer-pathfinder 每次
compute() 返回 partial 时用 h 最小的节点当 partial 路径终点,于是「又高又偏」
的节点胜出,A* 永不收敛,机器人一次移动指令都发不出来。
生产对照(王城平台,其余配置相同):
- altitudePreference = true → inputTicks = 0,永远「寻路超时」
- altitudePreference = false → inputTicks = 237,blockedTicks = 0,每 tick 都在走
第二个拦路虎(1.9.3):服务器每 1~6 分钟踢一次,原来掉线即永久停住;
autoResumeAfterReconnect 现在会在重连后自动接上。
修复后连续 20 分钟实测:距目标 763 → 668 格(前进 95 格),全程未掉线;
原点自救 4/4 成功,每次都能从登录服大厅回到真实世界。
仍待优化:推进速度约 5 格/分钟,卡在「寻路重试耗尽 → 往边上走两步 →
跳过目标 → 重新规划同一目标」的循环里(waitTimeoutSeconds 偏长、
跳过目标后立刻重选同一个目标)。
2026-10-01 16:57:04 +08:00
lyizai
468c719e37
docs: 记录「规划→卡住→清空」死循环的确切机制
...
读 mineflayer-pathfinder 源码定位到:index.js 末尾有「徒劳检测」——
3.5 秒内到不了下一个路径点就 resetPath('stuck') 清空路径。
机器人被墙挡住时必然触发,于是每 3.5 秒一个循环:
路径已生成 → 卡住 → 清空 → 路径已生成 → …
可靠信号:resetPath 每次都会补一对 diggingAborted/diggingCompleted 监听器,
所以日志里出现 MaxListenersExceededWarning: 11 diggingAborted listeners
就说明「路径正在被反复清空」。
另两个清空触发点(排查时注意):
- blockUpdate:路径附近方块一变就 resetPath('block_updated');
- chunkColumnLoad:相邻新区块加载就 resetPath('chunk_loaded'),
服务器频繁传送时会反复触发,A* 的 thinkTimeout 因每次新建 AStar 而永不到期。
结论:只要被墙挡住,就会无限循环「规划→卡住→清空」,既不放弃目标也不脱困。
需要先把它挪到开阔地;长期应累计 path_reset('stuck') 次数,
连续 N 次就判定「此处出不去」并上报 / 换目标。
同时更新当前拦路虎的优先级:第一是机器人被 /u return 送进王城建筑后出不来
(四向只有西面可走、东面头顶是火把),第二才是装备耐久,第三是 /u return 摔伤。
2026-10-01 00:39:46 +08:00
lyizai
c89f4f8f0f
docs: 固化物理录制实测结论 —— 三种「走不动」必须分开看
...
用 1.9.0 新增的物理 tick 录制逐 tick 抓「输入 → 输出」,把三种完全不同的现象区分开了:
- 登录服大厅:物理每 tick 正常走 0.116 格,服务端每 2 tick 推回一次
→ 真回弹,但那是未完成验证的惩罚,不是 bug;
- 真实世界建筑内:物理加速到 0.21 格/tick(≈4.3 格/秒,正常步行速度),
入站位置包 0~1 个(服务端没插手),collidedHorizontally=true、blockedTicks 42~59/60
→ 纯粹是撞墙(地形),不是协议问题;
- 真实世界卡在低处(y=72,王城平台在 y≈146):inputTicks=0,
两种执行器都是 timeout → 寻路器 60 秒规划超时,从未产生可执行路径。
frozenTicks 在所有场景都是 0,说明「输入没进物理」从未出现;
searchRadius 从 -1 改到 128 对结果没有影响。物理引擎、协议补包、Grim 合规层均正常。
当前扩地的真正拦路虎(按优先级):
1. 耐久保护(主手剩余耐久 15% ≤ 15%)一启动就回城停机,需人工修装备;
2. 机器人掉到低处后规划不出路径,需先带回高处;
3. /u return 会造成摔落伤害(实测 health 3.79 → 1.24,更早一次直接摔死)。
2026-10-01 00:17:22 +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
0c6700642e
docs: 固化抓包对照结论 —— 「走不动」在客户端物理层,不是服务端回弹
...
用新增的出站包抓取(1.8.0)做了三组对照 + 四方向逐包序列,结论与 TODO 原有框架相反,
先写进 TODO.md 免得下一个接手的人继续沿错误方向排查。
手动按住方向键 3 秒的实测(任务未启动、机器人空闲):
- 入站位置包 0 个 —— 服务端全程没插手,根本没有「回弹」
- 客户端自己的坐标与朝向一字未变;moveDiag.velocity 恒为 (0, -0.078, 0)
- 而 player_input 位标志是 backward: true —— 控制键确实按下去了
- 四方向位移 forward 0.02 / back 0.00 / left 1.22 / right 1.40(正常应约 12 格)
推论:
- 是客户端物理引擎没有把按键积分成位移(prismarine-physics 的 applyHeading
没有产生水平速度),下一步要加 physicsDiag 直接看 physicsEnabled /
physicsTick 计数 / simulate 前后 onGround / world.getBlock 命中 / control 快照;
- 服务端回弹只在「任务驱动移动」时出现(任务中入站 6/秒、出站 position_look 25/秒),
是伴生现象而非病因,这与「两套地面修正开关对位移毫无影响」的实测一致;
- 原记的「手动按键移动完全正常(forward 2 秒 4~8 格)」已不成立,该基准需重建。
顺带记下两条协议事实:flags.hasHorizontalCollision 恒为 0(mineflayer 写成 undefined),
teleport_confirm.teleportId 是该服务端自定义的大负数。
2026-09-29 22:08:50 +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
0cd65cf9be
fix: 修正原点(00)两种原因的判断依据 —— 两种情况下脚下都是基岩
...
用户指出:死亡被卡到 00 时脚下**也是基岩**,所以原来用
lockBelow === 'bedrock' 区分「登录服」和「死亡卡住」是错的,
会把死亡卡住误判成登录服,于是不做自救、只让用户去输验证码。
改成以「服务器有没有要求输入验证码」为唯一可靠信号:
- 要求验证码 -> 判定为登录服,提示人工发验证码(不做无意义的左右移动)
- 没要求验证码 -> 判定为死亡卡住,自动左右移动触发服务器重新传送
自救本身在两种情况下都无害(在登录服里按左右键不会有后果),
所以即使判断错了也不会把事情弄得更糟。
另外:验证码提示往往比 spawn 晚到,所以 _handleAuthPrompt 里也补了一次判断 ——
若提示到达时机器人正好在原点附近,会明确点出「被反复传送刷屏」正是登录服造成的,
把这个因果关系讲清楚,避免用户只看到传送刷屏而不知原因。
同步修正 TODO.md 与 CHANGELOG 里那条错误结论,并标注「不要用基岩做判断依据」。
测试 363 -> 368,全部通过。
2026-09-28 20:32:49 +08:00
lyizai
9ca80d2f6e
feat: 回城护栏 + 原点自救 + 移动诊断,并留下 TODO 交接文档
...
先纠正上一轮的误判:那个「寻路恒定 47 节点」是机器人卡在百米深坑里造成的,
我把它归因成配置问题并反复触发 /u return 回城,把玩家手动摆好的位置又拉走了 —— 抱歉。
回城护栏(破坏性操作不再自动执行)
- returnOnTimeout 默认关闭;即便打开,returnGraceSeconds(默认 300 秒)内也不执行,
避免把玩家刚在客户端摆好的位置清掉
- returnCommand 可配置(默认 u return);每次回城都明确记日志说明会丢失当前位置
- 因未启用而跳过时也记一条说明,避免用户以为「怎么不回城了」
区分「被传送到原点」的两种原因(以前日志里长得一样,常被误判成机器人坏了)
- 脚下是 bedrock -> 在登录服,必须人工输入验证码,给出明确提示
- 脚下不是基岩 -> 死亡后被卡住,自动左右移动触发服务器重新传送
新增两个诊断字段(排查「走不动」的关键手段)
- moveDiag:当前按下的控制键、速度、寻路器 isMoving/goal/剩余路径点数。
能一刀切开「寻路器没执行」与「执行了但服务端不认」
- pathingDiag:起点可走邻居数、寻路器能否读到方块、四向可见距离
_isStandingOnGround() 增加「服务端是否正把我们按在原地」的判断
排查结论(详见 TODO.md)
- 排除:GrimCompat 朝向限速(A/B 实测关闭后回弹 6.0 -> 5.5 次/秒,无变化)
- 排除:疾跑(关闭后仍 4.8 次/秒)
- 排除:世界数据错误(实测脚下 stone)
- 关键线索:寻路时 forward/sprint 确实按下、isMoving=true,但水平速度恒为 0
(velocity.y=-0.078 恰是自由落体第一 tick 的值,说明速度每 tick 被清零),
且 bot.entity.onGround 被服务端位置包反复置为 false,物理引擎一直按空中处理。
下一步应从「让 entity.onGround 与出站包一致」入手。
TODO.md 面向下一位开发者:包含项目现状与部署、完整证据链、按优先级排好的假设与
验证命令、备选方案(绕开 pathfinder 自己写转向控制器)、以及其它待办。
测试 360 -> 363,全部通过。
2026-09-28 20:21:41 +08:00