fix: 定位「寻路恒定 47 节点」的根因(专属配置被冻结)并改为按进度判超时

找到「寻路怎么调都只探索 47 个节点」的真凶
- 启动任务时若带了配置,会被整份存为该机器人的专属配置覆盖。它是一份**完整快照**,
  等于把当时那一刻的全局配置冻结在这个机器人身上,之后改全局配置再也影响不到它。
  实测这台机器人的覆盖里 allowBreak/allowParkour 都是 false,所以我前面所有
  「放开挖方块 / 跑酷 / 不限搜索半径」的排查全部无效,一直在跟同一份旧配置较劲。
- 清除覆盖后寻路器的邻居生成数从 **2 变成 15**,机器人开始真正移动。
- 现在保存覆盖时会明确记一条日志(含策略/邦国/数量),说明「此后全局改动不影响它」。
- 新增「清除专属配置」按钮与 POST /api/bots/:id/settings/clear-config,
  并在配置面板提示该机器人是否有专属覆盖 —— 这是「改了全局却没生效」的唯一退路。

寻路超时改为按进度判定
- 原来只看墙钟时间:目标常在几百格外,而寻路速度受地形与反作弊回弹影响可能只有
  正常步行的十分之一,于是「走得慢但在稳步接近」会被误判成卡死,然后 /u return
  回城把进度全部清零。现在只要与目标的曼哈顿距离有实质缩短就重置这一段计时。
- 首次观察只记录距离基准、不续期,保证「原地不动」仍会照常超时。

新增寻路诊断(排查这类问题的关键手段)
- GET /api/bots/:id/status 的 pathingDiag 暴露:起点可走邻居数与具体坐标、
  寻路器能否通过 world.getBlock 读到方块、四向可见距离。
- 邻居数极少(如 2)说明不是目标太远,而是移动生成器从起点就找不到分支,
  此时调任何搜索参数都没用。

测试 355 -> 360,全部通过。
这个提交包含在:
lyizai
2026-09-28 19:43:15 +08:00
父节点 42a9dd6cf0
当前提交 0783249d1e
共修改 9 个文件,包含 251 行新增和 8 行删除
+41 -5
查看文件
@@ -510,19 +510,42 @@ function collectConfig() {
async function loadConfig() {
try {
if ($('chkBotOverride').checked && selectedBotId) {
if (selectedBotId) {
const res = await api('/api/bots/' + encodeURIComponent(selectedBotId) + '/settings');
currentConfig = res.data.config;
} else {
const res = await api('/api/config');
currentConfig = res.data;
updateOverrideHint(res.data);
if ($('chkBotOverride').checked) {
currentConfig = res.data.config;
renderConfig();
return;
}
}
const res = await api('/api/config');
currentConfig = res.data;
renderConfig();
} catch (err) {
toast('读取配置失败:' + err.message, true);
}
}
/**
* 提示「该机器人是否有一份专属配置覆盖」。
*
* 专属配置是一份完整快照,存下之后全局配置的改动就再也影响不到这个机器人 ——
* 不提示的话,很容易出现「我明明改了全局设置,它却还是老行为」的困惑。
*
* @param {object} setting `/api/bots/:id/settings` 的 data
*/
function updateOverrideHint(setting) {
const hint = $('overrideHint');
const text = $('overrideHintText');
if (!hint || !text) return;
const has = !!(setting && setting.hasOverrides);
hint.classList.toggle('hidden', !has);
if (has) {
text.textContent = '该机器人有一份专属配置(完整快照),全局配置的改动不会影响它。';
}
}
async function saveConfig() {
try {
const config = collectConfig();
@@ -2494,6 +2517,19 @@ function bindEvents() {
$('btnSaveConfig').addEventListener('click', saveConfig);
$('btnReloadConfig').addEventListener('click', loadConfig);
$('chkBotOverride').addEventListener('change', loadConfig);
$('btnClearOverride').addEventListener('click', async () => {
if (!selectedBotId) return;
try {
const res = await api('/api/bots/' + encodeURIComponent(selectedBotId) + '/settings/clear-config', {
method: 'POST'
});
toast(res.message || '已清除');
updateOverrideHint(res.data);
await loadConfig();
} catch (err) {
toast('清除失败:' + err.message, true);
}
});
$('configTabs').addEventListener('click', (e) => {
const tab = e.target.closest('.tab');