From fa693c8a5e99e88d27ae1eb3a10d349385607519 Mon Sep 17 00:00:00 2001 From: U9G Date: Fri, 4 Sep 2026 20:54:53 -0400 Subject: [PATCH] test: connect the bot only after the nether forceload has finished The warm-up forceload blocks the server's main thread until all 49 nether chunks are FULL. Status pings are answered off-thread, so pingUntilReady resolved while the main thread was still generating, and the bot connected into a server that could not process its login. When generation took more than 30s the login-phase connection hit netty's ReadTimeoutHandler(30) and the whole version failed in the before-all hook ("lost connection: Timed out" on the GameProfile). CI hit this three times on 1.16.5-1.19.3 with 30.9-32.3s stalls; versions where the stall stayed near 20s passed. Wait for the console's "Marked N chunks in minecraft:the_nether" line as well as the ping before begin(), so no connection exists while the main thread is blocked. Versions without the execute command skip the wait. --- test/externalTest.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/test/externalTest.js b/test/externalTest.js index ebe0bcf2f..17e5900f6 100644 --- a/test/externalTest.js +++ b/test/externalTest.js @@ -9,7 +9,7 @@ const path = require('path') const { getPort } = require('./common/util') const trace = require('./common/trace') -const { once } = require('../lib/promise_utils') +const { once, onceWithCleanup } = require('../lib/promise_utils') // set this to false if you want to test without starting a server automatically const START_THE_SERVER = true @@ -128,16 +128,23 @@ for (const supportedVersion of mineflayer.testedVersions) { wrap.writeServer('seed\n') // The nether test's portal travel otherwise generates these chunks // synchronously on the main thread while its clock runs. forceload - // itself blocks the main thread until every chunk is FULL, so it - // must run before the bot connects; pings are served off-thread, - // so the stall stays inside this hook's budget. 7x7 chunks covers - // the portal placement scan and every chunk the test's waits touch. + // itself blocks the main thread until every chunk is FULL, and a + // connection that is mid-login while it blocks hits the server's + // 30s read timeout, so the bot must not connect until the server + // reports the chunks loaded. Pings are served off-thread, so the + // stall stays inside this hook's budget. 7x7 chunks covers the + // portal placement scan and every chunk the test's waits touch. + let netherLoaded = Promise.resolve() if (registry.supportFeature('hasExecuteCommand')) { + netherLoaded = onceWithCleanup(wrap, 'line', { + timeout: 120000, + checkCondition: line => /Marked \d+ chunks in minecraft:the_nether/.test(line) + }) wrap.writeServer('execute in minecraft:the_nether run forceload add -48 -48 63 63\n') } console.log(`pinging ${version.minecraftVersion} port : ${PORT}`) trace.log('server started, pinging') - pingUntilReady(PORT, '127.0.0.1', supportedVersion).then(results => { + Promise.all([pingUntilReady(PORT, '127.0.0.1', supportedVersion), netherLoaded]).then(([results]) => { console.log('pong') trace.log('pong', { latency: results.latency }) assert.ok(results.latency >= 0)