Skip to content

Commit e3784d1

Browse files
Simeon Kummercursoragent
andcommitted
Fix velocity plugin: don't interfere with initial login configuration
The velocity plugin was activating during the initial 1.20.2+ login configuration phase, which is already handled by node-minecraft-protocol. This caused duplicate finish_configuration packets and disabled physics during login, making the bot unable to spawn on 1.20.2+ servers. Changes: - Only activate configuration phase handling after first spawn - Remove duplicate finish_configuration write (minecraft-protocol handles it) - Remove redundant registry_data/select_known_packs listeners - Fix missing newlines at EOF (lint errors) - Fix object-shorthand lint warnings Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent b9d4e30 commit e3784d1

3 files changed

Lines changed: 38 additions & 66 deletions

File tree

examples/velocity_manual_resourcepack.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,4 @@ bot.on('error', (err) => {
5353
bot.on('kicked', (reason) => {
5454
console.log('Kicked:', reason)
5555
console.log('Note: If kicked during transfer, you may need to enable the velocity plugin')
56-
})
56+
})

examples/velocity_transfer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,4 @@ bot.on('error', (err) => {
6666

6767
bot.on('kicked', (reason) => {
6868
console.log('Kicked:', reason)
69-
})
69+
})

lib/plugins/velocity.js

Lines changed: 36 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
/**
22
* Velocity proxy support for Minecraft 1.20.2+ configuration phase
33
*
4-
* This plugin manages the configuration phase introduced in Minecraft 1.20.2
5-
* and extended in 1.21+, which is required for proper server transfers via
6-
* Velocity proxy.
4+
* This plugin manages the re-configuration phase that occurs during
5+
* server transfers via Velocity proxy. It does NOT interfere with the
6+
* initial login configuration (handled by node-minecraft-protocol).
77
*
8-
* During the configuration phase:
8+
* During re-configuration:
99
* - Gameplay packets (movement, physics) are not allowed
10-
* - Only configuration packets should be sent
11-
* - Resource packs must be handled correctly
10+
* - Resource packs must be accepted for the transfer to complete
1211
*
1312
* Issue: https://github.com/PrismarineJS/mineflayer/issues/3764
1413
*/
@@ -18,7 +17,10 @@ module.exports = inject
1817
function inject (bot) {
1918
// Track whether we're in configuration phase
2019
bot.inConfigurationPhase = false
21-
let configurationFinished = false
20+
21+
// Only activate after the first spawn -- the initial login configuration
22+
// is already handled by node-minecraft-protocol and we must not interfere.
23+
let hasInitiallySpawned = false
2224

2325
// Resource pack response codes
2426
const TEXTURE_PACK_RESULTS = {
@@ -29,13 +31,13 @@ function inject (bot) {
2931
}
3032

3133
/**
32-
* Enter configuration phase
34+
* Enter configuration phase (only for re-entry, not initial login)
3335
*/
3436
function enterConfigurationPhase () {
3537
if (bot.inConfigurationPhase) return
38+
if (!hasInitiallySpawned) return
3639

3740
bot.inConfigurationPhase = true
38-
configurationFinished = false
3941

4042
// Disable physics during configuration to prevent movement packets
4143
if (bot.physicsEnabled !== undefined) {
@@ -54,7 +56,7 @@ function inject (bot) {
5456

5557
bot.inConfigurationPhase = false
5658

57-
// Re-enable physics after configuration
59+
// Re-enable physics after a short delay to let the server finish setup
5860
setTimeout(() => {
5961
if (bot._physicsWasEnabled && !bot._ended) {
6062
bot.physicsEnabled = true
@@ -65,52 +67,39 @@ function inject (bot) {
6567
bot.emit('configurationPhase', 'end')
6668
}
6769

70+
// Mark initial spawn complete -- after this, configuration phase events
71+
// are treated as Velocity re-configuration (server transfers).
72+
bot.once('spawn', () => {
73+
hasInitiallySpawned = true
74+
})
75+
6876
// === CONFIGURATION PHASE DETECTION ===
6977

70-
// Method 1: start_configuration event (1.20.2+)
78+
// start_configuration is sent by the server to re-enter config state (1.20.2+)
7179
bot._client.on('start_configuration', () => {
7280
enterConfigurationPhase()
7381
})
7482

75-
// Method 2: select_known_packs event (1.21+)
76-
bot._client.on('select_known_packs', (packet) => {
77-
enterConfigurationPhase()
78-
// Note: No response needed for select_known_packs
79-
})
80-
81-
// Method 3: registry_data event (1.20.2+)
82-
bot._client.on('registry_data', (packet) => {
83-
// Only enter if not already in configuration phase
84-
// (registry_data can be sent multiple times)
85-
if (!bot.inConfigurationPhase) {
86-
enterConfigurationPhase()
87-
}
88-
})
89-
90-
// Method 4: transfer event (1.20.5+)
91-
bot._client.on('transfer', (packet) => {
83+
// transfer event (1.20.5+) -- server is transferring us
84+
bot._client.on('transfer', () => {
9285
enterConfigurationPhase()
9386
})
9487

9588
// === AUTOMATIC RESOURCE PACK ACCEPTANCE ===
9689

97-
/**
98-
* Automatically accept resource packs during configuration phase
99-
* This is required for Velocity transfers to complete successfully
100-
*/
90+
// Automatically accept resource packs during configuration phase.
91+
// This is required for Velocity transfers to complete -- the server
92+
// waits for SUCCESSFULLY_LOADED before sending finish_configuration.
10193

10294
// Handle add_resource_pack (1.20.3+)
10395
bot._client.prependListener('add_resource_pack', (data) => {
10496
if (!bot.inConfigurationPhase) return
10597

106-
// Send ACCEPTED immediately
10798
bot._client.write('resource_pack_receive', {
10899
uuid: data.uuid,
109100
result: TEXTURE_PACK_RESULTS.ACCEPTED
110101
})
111102

112-
// Send SUCCESSFULLY_LOADED immediately
113-
// Server needs this before sending finish_configuration
114103
bot._client.write('resource_pack_receive', {
115104
uuid: data.uuid,
116105
result: TEXTURE_PACK_RESULTS.SUCCESSFULLY_LOADED
@@ -120,52 +109,35 @@ function inject (bot) {
120109
// Handle resource_pack_send (older versions with UUID support)
121110
bot._client.prependListener('resource_pack_send', (data) => {
122111
if (!bot.inConfigurationPhase) return
123-
if (!data.uuid) return // Only handle UUID-based resource packs
112+
if (!data.uuid) return
124113

125114
const UUID = require('uuid-1345')
126-
const uuid = new UUID(data.uuid)
115+
const resourceUuid = new UUID(data.uuid)
127116

128-
// Send ACCEPTED immediately
129117
bot._client.write('resource_pack_receive', {
130-
uuid: uuid,
118+
uuid: resourceUuid,
131119
result: TEXTURE_PACK_RESULTS.ACCEPTED
132120
})
133121

134-
// Send SUCCESSFULLY_LOADED immediately
135122
bot._client.write('resource_pack_receive', {
136-
uuid: uuid,
123+
uuid: resourceUuid,
137124
result: TEXTURE_PACK_RESULTS.SUCCESSFULLY_LOADED
138125
})
139126
})
140127

141-
// === FINISH CONFIGURATION ===
128+
// === EXIT CONFIGURATION ===
142129

130+
// node-minecraft-protocol already writes the finish_configuration
131+
// acknowledgement and transitions to PLAY state. We just need to
132+
// track it so we can re-enable physics.
143133
bot._client.on('finish_configuration', () => {
144-
configurationFinished = true
145-
146-
// Acknowledge finish_configuration
147-
try {
148-
bot._client.write('finish_configuration', {})
149-
} catch (err) {
150-
// Ignore if packet doesn't exist for this version
151-
}
152-
153-
// Exit configuration phase after a short delay
134+
// Small delay to let the play state fully initialize
154135
setTimeout(() => {
155136
exitConfigurationPhase()
156137
}, 500)
157138
})
158139

159-
// === FALLBACKS ===
160-
161-
// Fallback: Exit on login if we're still in configuration phase
162-
bot.on('login', () => {
163-
if (bot.inConfigurationPhase && configurationFinished) {
164-
exitConfigurationPhase()
165-
}
166-
})
167-
168-
// Fallback: Exit on spawn if we're still in configuration phase
140+
// Fallback: exit on spawn if we're still in configuration phase
169141
bot.on('spawn', () => {
170142
if (bot.inConfigurationPhase) {
171143
exitConfigurationPhase()
@@ -175,6 +147,6 @@ function inject (bot) {
175147
// Cleanup on end
176148
bot.on('end', () => {
177149
bot.inConfigurationPhase = false
178-
configurationFinished = false
150+
delete bot._physicsWasEnabled
179151
})
180-
}
152+
}

0 commit comments

Comments
 (0)