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。
这个提交包含在:
+17
@@ -2,6 +2,23 @@
|
|||||||
|
|
||||||
本项目遵循 [约定式提交](https://www.conventionalcommits.org/zh-hans/) 与 [语义化版本](https://semver.org/lang/zh-CN/)。
|
本项目遵循 [约定式提交](https://www.conventionalcommits.org/zh-hans/) 与 [语义化版本](https://semver.org/lang/zh-CN/)。
|
||||||
|
|
||||||
|
## [1.10.1] - 2026-10-01
|
||||||
|
|
||||||
|
修掉 1.9.3 自动恢复里的一个会让恢复永久丢失的缺陷。
|
||||||
|
|
||||||
|
### 修复
|
||||||
|
|
||||||
|
- **`resumeConfig` 在尝试恢复之前就被清掉了**:`tick()` 里先取走待恢复的配置再调
|
||||||
|
`start()`,而 `start()` 在「已进入世界但还没完成登录」时会直接返回 false
|
||||||
|
(`isReady()` 要求 `loggedIn`)。本服掉线频繁、重连后常常短暂处于这个状态,
|
||||||
|
于是**一次失败的尝试就把这次恢复永久丢掉了**,任务再也不会自己接上。
|
||||||
|
现在:① 等 `bm.isReady()` 才尝试;② 只有 `start()` 真的返回 true 才清掉登记,
|
||||||
|
失败时保留并在下一 tick 继续试(日志打「自动恢复未成功(…),稍后重试」)。
|
||||||
|
|
||||||
|
### 测试
|
||||||
|
|
||||||
|
新增 1 个用例(477 → 478):未就绪时不启动也不丢登记,就绪后恢复并清登记。
|
||||||
|
|
||||||
## [1.10.0] - 2026-10-01
|
## [1.10.0] - 2026-10-01
|
||||||
|
|
||||||
补上出站包一直漏报的 `hasHorizontalCollision`,针对「机器人一直在走、却只走出
|
补上出站包一直漏报的 `hasHorizontalCollision`,针对「机器人一直在走、却只走出
|
||||||
|
|||||||
自动生成
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "autostore-bot",
|
"name": "autostore-bot",
|
||||||
"version": "1.10.0",
|
"version": "1.10.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "autostore-bot",
|
"name": "autostore-bot",
|
||||||
"version": "1.10.0",
|
"version": "1.10.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chalk": "^4.1.2",
|
"chalk": "^4.1.2",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "autostore-bot",
|
"name": "autostore-bot",
|
||||||
"version": "1.10.0",
|
"version": "1.10.1",
|
||||||
"description": "AutoStore Bot —— Minecraft 自动扩地机器人(mineflayer 重写版,多机器人挂机,Web 控制台,开拓日志,大地图,Grim 反作弊适配)",
|
"description": "AutoStore Bot —— Minecraft 自动扩地机器人(mineflayer 重写版,多机器人挂机,Web 控制台,开拓日志,大地图,Grim 反作弊适配)",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -237,8 +237,6 @@ class ExpansionController {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.config = requestedConfig;
|
this.config = requestedConfig;
|
||||||
// 显式启动的任务优先于「掉线待恢复」的那一次
|
|
||||||
this.resumeConfig = null;
|
|
||||||
// 现实时间限制:不在允许时段时登记「等待自动开始」,进入时段后由 tick() 自动启动
|
// 现实时间限制:不在允许时段时登记「等待自动开始」,进入时段后由 tick() 自动启动
|
||||||
if (!this.isWithinClaimTime()) {
|
if (!this.isWithinClaimTime()) {
|
||||||
this.pendingStart = requestedConfig;
|
this.pendingStart = requestedConfig;
|
||||||
@@ -360,12 +358,23 @@ class ExpansionController {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 重新进入世界:把被掉线打断的任务接上
|
// 重新进入世界:把被掉线打断的任务接上。
|
||||||
|
// 必须等 isReady()(含登录完成)才试,否则 start() 会直接返回 false;
|
||||||
|
// 而且只有在真的启动成功后才清掉 resumeConfig —— 否则一次失败的尝试
|
||||||
|
// 就会把这次恢复永久丢掉(实测本服掉线频繁,很容易踩到)。
|
||||||
if (this.resumeConfig && !this.isRunning()) {
|
if (this.resumeConfig && !this.isRunning()) {
|
||||||
|
if (!bm.isReady()) return; // 还没就绪,下一 tick 再试
|
||||||
const resume = this.resumeConfig;
|
const resume = this.resumeConfig;
|
||||||
this.resumeConfig = null;
|
|
||||||
this._log('已重新进入世界,自动恢复扩地任务');
|
this._log('已重新进入世界,自动恢复扩地任务');
|
||||||
this.start(resume).catch((err) => this._log('自动恢复任务失败:' + err.message, 'error'));
|
Promise.resolve(this.start(resume))
|
||||||
|
.then((ok) => {
|
||||||
|
if (ok) {
|
||||||
|
this.resumeConfig = null;
|
||||||
|
} else {
|
||||||
|
this._log('自动恢复未成功(' + this.status + '),稍后重试', 'warn');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => this._log('自动恢复任务失败:' + err.message, 'error'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.playerChunk = this._playerChunk();
|
this.playerChunk = this._playerChunk();
|
||||||
|
|||||||
@@ -89,10 +89,12 @@ class FakeBotManager {
|
|||||||
this._model = model;
|
this._model = model;
|
||||||
/** 设为 false 模拟「世界已退出」(掉线 / 被踢 / 被切到登录服) */
|
/** 设为 false 模拟「世界已退出」(掉线 / 被踢 / 被切到登录服) */
|
||||||
this.spawned = true;
|
this.spawned = true;
|
||||||
|
/** 设为 false 模拟「已进入世界但还没完成登录」 */
|
||||||
|
this.ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
isReady() {
|
isReady() {
|
||||||
return true;
|
return this.ready;
|
||||||
}
|
}
|
||||||
|
|
||||||
isSpawned() {
|
isSpawned() {
|
||||||
@@ -168,6 +170,28 @@ test('世界退出后任务暂停,重连进入世界时自动恢复', async ()
|
|||||||
assert.strictEqual(botManager.pathing.pathCalls, 2, '恢复后应重新下发寻路');
|
assert.strictEqual(botManager.pathing.pathCalls, 2, '恢复后应重新下发寻路');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('恢复尝试失败时不会丢掉这次恢复(等就绪后继续试)', async () => {
|
||||||
|
// 回归:本服掉线频繁,重连后常常「已进入世界但还没完成登录」,
|
||||||
|
// 此时 start() 会直接返回 false。若在尝试前就清掉 resumeConfig,
|
||||||
|
// 这次恢复就永久丢了 —— 任务再也不会自己接上。
|
||||||
|
const { controller, botManager, config } = setup();
|
||||||
|
await controller.start(config);
|
||||||
|
botManager.spawned = false;
|
||||||
|
controller.tick(); // 世界退出 → 登记待恢复
|
||||||
|
botManager.spawned = true;
|
||||||
|
botManager.ready = false; // 已进入世界但未就绪
|
||||||
|
controller.tick();
|
||||||
|
assert.strictEqual(controller.isRunning(), false, '未就绪时不应启动');
|
||||||
|
assert.ok(controller.resumeConfig, '未就绪时不能丢掉待恢复的任务');
|
||||||
|
|
||||||
|
botManager.ready = true;
|
||||||
|
controller.tick();
|
||||||
|
// start() 是异步的,等它落地再断言
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
|
assert.strictEqual(controller.isRunning(), true, '就绪后应恢复');
|
||||||
|
assert.strictEqual(controller.resumeConfig, null, '恢复成功后清掉登记');
|
||||||
|
});
|
||||||
|
|
||||||
test('自动恢复可以关闭', async () => {
|
test('自动恢复可以关闭', async () => {
|
||||||
const { controller, botManager, config } = setup({ config: { autoResumeAfterReconnect: false } });
|
const { controller, botManager, config } = setup({ config: { autoResumeAfterReconnect: false } });
|
||||||
await controller.start(config);
|
await controller.start(config);
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户