Mineflayer服务器操作可能引起超时panic
Little_YangYang

触发方式

在服务器中,如果使用类似openContainer()函数,与容器进行window交互,代码逻辑中会等待window打开,然而由于服务器权限问题,并不会返回权限错误或其他提示,导致window长时间无法打开,进而使openContainer长时间阻塞,被守护Kill,panic报错Error: Event windowOpen did not fire within timeout of 20000ms

解决办法

使用try catch的方式阻止崩溃,权限问题如何探测还没有什么好的思路。

简略代码

1
2
3
4
5
6
7
8
9
10
class Bot {
private bot: mineflayer.Bot;

public getBot(): mineflayer.Bot {
if (!this.bot) {
throw new Error("Bot is not initialized");
}
return this.bot;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
async function findAllChests(bot: Bot, direction: 'left' | 'right'): Promise<Vec3[]> {
const chest_id = bot.getMCData().blocksByName['chest'].id;
return bot.getBot().findBlocks({
matching: function (block: Block) {
return block.type === chest_id && (block.getProperties().type === 'single' || block.getProperties().type === 'left');
},
useExtraInfo: true,
maxDistance: 64,
count: 100
});
}

async function openChest(bot: Bot, chestPostionVec3: Vec3) {
const chest = bot.getBot().blockAt(chestPostionVec3);
await bot.getBot().pathfinder.goto(new GoalNear(chestPostionVec3.x, chestPostionVec3.y, chestPostionVec3.z, 1));

if (chest) {
bot.logger.info('open chest:', chestPostionVec3);
// 需要使用try catch block来捕捉panic
try {
// 触发在此处,长时间await
let chestWindow = await bot.getBot().openContainer(chest);
let items = chestWindow.containerItems();
bot.logger.info('chest position: ', chestPostionVec3, 'items:', items.map(item => item.customName? item.customName : item.name));
bot.getBot().closeWindow(chestWindow);
} catch (error) {
bot.logger.error('Failed to open chest\n', error);
}
}
}

async function scanChest(bot: Bot, direction: 'left' | 'right') {
let chests = await findAllChests(bot, direction);
bot.logger.info('Found chests: ' + chests.length, chests);
for (let chest of chests) {
await openChest(bot, chest);
}
}