From c0c077b7e95bce89bdd2f83cba69bb37d5641644 Mon Sep 17 00:00:00 2001 From: AI Bengineering <301548888+aibengineering@users.noreply.github.com> Date: Wed, 12 Aug 2026 14:50:03 +1000 Subject: [PATCH 1/2] fix: signal player loaded before spawn Java Edition 1.21.4 added the serverbound player_loaded packet. Send it before Mineflayer's spawn event on initial load and respawn so callers cannot interact while vanilla still ignores player actions. Reproduce on unmodified upstream: npm run mocha_test -- test/externalTest.js --grep '^mineflayer_external 1\.21\.4v crafting$' --retries 0 The full-title grep limits Mocha to that one version and test even though externalTest.js declares every supported version. Upstream fails after 20 seconds waiting for windowOpen; this change passes the same single test. --- lib/plugins/health.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/plugins/health.js b/lib/plugins/health.js index ba35b73952..02675e7072 100644 --- a/lib/plugins/health.js +++ b/lib/plugins/health.js @@ -1,5 +1,10 @@ module.exports = inject +// Added in Java Edition 1.21.4. Mojang specifies that the client sends this +// after the initial terrain-loading screen and again after respawn: +// https://feedback.minecraft.net/hc/en-us/articles/32385811139085-Minecraft-Java-Edition-1-21-4-The-Garden-Awakens +const PLAYER_LOADED_VERSION = '1.21.4' + function inject (bot, options) { bot.isAlive = true @@ -10,6 +15,12 @@ function inject (bot, options) { bot._client.once('update_health', (packet) => { if (packet.health > 0) { + // Vanilla waits for this packet before accepting player actions. Send it + // before exposing spawn to callers, because spawn is Mineflayer's signal + // that they may begin interacting with the server. + if (bot.registry.version['>='](PLAYER_LOADED_VERSION)) { + bot._client.write('player_loaded', {}) + } bot.emit('spawn') } }) @@ -28,6 +39,9 @@ function inject (bot, options) { bot.respawn() } else if (bot.health > 0 && !bot.isAlive) { bot.isAlive = true + if (bot.registry.version['>='](PLAYER_LOADED_VERSION)) { + bot._client.write('player_loaded', {}) + } bot.emit('spawn') } }) From ee3cd38a872d0287a49ed751cdbfb655e0267f18 Mon Sep 17 00:00:00 2001 From: AI Bengineering <301548888+aibengineering@users.noreply.github.com> Date: Wed, 12 Aug 2026 19:58:35 +1000 Subject: [PATCH 2/2] refactor: gate player loaded with feature flag --- lib/plugins/health.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/plugins/health.js b/lib/plugins/health.js index 02675e7072..2c1b7cfa8b 100644 --- a/lib/plugins/health.js +++ b/lib/plugins/health.js @@ -1,10 +1,5 @@ module.exports = inject -// Added in Java Edition 1.21.4. Mojang specifies that the client sends this -// after the initial terrain-loading screen and again after respawn: -// https://feedback.minecraft.net/hc/en-us/articles/32385811139085-Minecraft-Java-Edition-1-21-4-The-Garden-Awakens -const PLAYER_LOADED_VERSION = '1.21.4' - function inject (bot, options) { bot.isAlive = true @@ -18,7 +13,7 @@ function inject (bot, options) { // Vanilla waits for this packet before accepting player actions. Send it // before exposing spawn to callers, because spawn is Mineflayer's signal // that they may begin interacting with the server. - if (bot.registry.version['>='](PLAYER_LOADED_VERSION)) { + if (bot.supportFeature('sendsPlayerLoadedPacket')) { bot._client.write('player_loaded', {}) } bot.emit('spawn') @@ -39,7 +34,7 @@ function inject (bot, options) { bot.respawn() } else if (bot.health > 0 && !bot.isAlive) { bot.isAlive = true - if (bot.registry.version['>='](PLAYER_LOADED_VERSION)) { + if (bot.supportFeature('sendsPlayerLoadedPacket')) { bot._client.write('player_loaded', {}) } bot.emit('spawn')