specprotocol 1.4.4 → 1.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bot.js CHANGED
@@ -27,6 +27,7 @@ const encryption_js_1 = require("./protocol/encryption.js");
27
27
  const handshake_js_1 = require("./protocol/states/handshake.js");
28
28
  const login_js_1 = require("./protocol/states/login.js");
29
29
  const play_js_1 = require("./protocol/states/play.js");
30
+ const version_js_1 = require("./protocol/version.js");
30
31
  // World & Entity
31
32
  const world_js_1 = require("./world/world.js");
32
33
  const entity_js_1 = require("./entity/entity.js");
@@ -42,6 +43,7 @@ const block_finder_js_1 = require("./block-finder.js");
42
43
  const plugin_manager_js_1 = require("./plugins/plugin-manager.js");
43
44
  const chat_js_2 = require("./plugins/built-in/chat.js");
44
45
  const combat_js_1 = require("./plugins/built-in/combat.js");
46
+ const MISSING_PACKET_ID = -1;
45
47
  // ─── Bot Class ──────────────────────────────────────────
46
48
  class Bot extends events_js_1.TypedEventEmitter {
47
49
  // Connection
@@ -85,6 +87,13 @@ class Bot extends events_js_1.TypedEventEmitter {
85
87
  weather;
86
88
  // Config
87
89
  options;
90
+ protocolInfo;
91
+ loginClientIds;
92
+ loginServerIds;
93
+ configurationClientIds;
94
+ configurationServerIds;
95
+ playClientIds;
96
+ playServerIds;
88
97
  // Packet handlers for play state
89
98
  packetHandlers = new Map();
90
99
  playPacketListener = null;
@@ -97,15 +106,111 @@ class Bot extends events_js_1.TypedEventEmitter {
97
106
  };
98
107
  constructor(options) {
99
108
  super();
109
+ this.protocolInfo = (0, version_js_1.resolveProtocolInfo)(options.version ?? handshake_js_1.PROTOCOL_VERSION);
100
110
  this.options = {
101
111
  host: options.host,
102
112
  port: options.port ?? 25565,
103
- version: options.version ?? handshake_js_1.PROTOCOL_VERSION,
113
+ version: this.protocolInfo.protocolVersion,
104
114
  viewDistance: options.viewDistance ?? 10,
105
115
  };
106
116
  this.authMode = options.auth ?? 'offline';
107
117
  this._username = options.username;
108
118
  this.logger = new logger_js_1.Logger('Bot', options.logLevel ?? logger_js_1.LogLevel.INFO);
119
+ this.logger.info(`Using protocol ${this.protocolInfo.protocolVersion} (${this.protocolInfo.minecraftVersion})`);
120
+ const missing = MISSING_PACKET_ID;
121
+ const loginToClient = this.protocolInfo.packetMappings.login.toClient;
122
+ const loginToServer = this.protocolInfo.packetMappings.login.toServer;
123
+ const configToClient = this.protocolInfo.packetMappings.configuration?.toClient ?? {};
124
+ const configToServer = this.protocolInfo.packetMappings.configuration?.toServer ?? {};
125
+ const playToClient = this.protocolInfo.packetMappings.play.toClient;
126
+ const playToServer = this.protocolInfo.packetMappings.play.toServer;
127
+ this.loginClientIds = {
128
+ disconnect: (0, version_js_1.resolvePacketId)(loginToClient, ['disconnect']) ?? missing,
129
+ encryptionBegin: (0, version_js_1.resolvePacketId)(loginToClient, ['encryption_begin']) ?? missing,
130
+ success: (0, version_js_1.resolvePacketId)(loginToClient, ['success']) ?? missing,
131
+ compress: (0, version_js_1.resolvePacketId)(loginToClient, ['compress']) ?? missing,
132
+ loginPluginRequest: (0, version_js_1.resolvePacketId)(loginToClient, ['login_plugin_request']) ?? missing,
133
+ };
134
+ this.loginServerIds = {
135
+ loginStart: (0, version_js_1.resolvePacketId)(loginToServer, ['login_start']) ?? missing,
136
+ encryptionBegin: (0, version_js_1.resolvePacketId)(loginToServer, ['encryption_begin']) ?? missing,
137
+ loginPluginResponse: (0, version_js_1.resolvePacketId)(loginToServer, ['login_plugin_response']) ?? missing,
138
+ loginAcknowledged: (0, version_js_1.resolvePacketId)(loginToServer, ['login_acknowledged']) ?? missing,
139
+ };
140
+ this.configurationClientIds = {
141
+ disconnect: (0, version_js_1.resolvePacketId)(configToClient, ['disconnect']) ?? missing,
142
+ finishConfiguration: (0, version_js_1.resolvePacketId)(configToClient, ['finish_configuration']) ?? missing,
143
+ keepAlive: (0, version_js_1.resolvePacketId)(configToClient, ['keep_alive']) ?? missing,
144
+ ping: (0, version_js_1.resolvePacketId)(configToClient, ['ping']) ?? missing,
145
+ customPayload: (0, version_js_1.resolvePacketId)(configToClient, ['custom_payload']) ?? missing,
146
+ registryData: (0, version_js_1.resolvePacketId)(configToClient, ['registry_data']) ?? missing,
147
+ featureFlags: (0, version_js_1.resolvePacketId)(configToClient, ['feature_flags']) ?? missing,
148
+ tags: (0, version_js_1.resolvePacketId)(configToClient, ['tags']) ?? missing,
149
+ selectKnownPacks: (0, version_js_1.resolvePacketId)(configToClient, ['select_known_packs']) ?? missing,
150
+ cookieRequest: (0, version_js_1.resolvePacketId)(configToClient, ['cookie_request']) ?? missing,
151
+ addResourcePack: (0, version_js_1.resolvePacketId)(configToClient, ['add_resource_pack', 'resource_pack_send']) ?? missing,
152
+ serverLinks: (0, version_js_1.resolvePacketId)(configToClient, ['server_links']) ?? missing,
153
+ };
154
+ this.configurationServerIds = {
155
+ finishConfiguration: (0, version_js_1.resolvePacketId)(configToServer, ['finish_configuration']) ?? missing,
156
+ keepAlive: (0, version_js_1.resolvePacketId)(configToServer, ['keep_alive']) ?? missing,
157
+ pong: (0, version_js_1.resolvePacketId)(configToServer, ['pong']) ?? missing,
158
+ selectKnownPacks: (0, version_js_1.resolvePacketId)(configToServer, ['select_known_packs']) ?? missing,
159
+ };
160
+ this.playClientIds = {
161
+ keepAlive: (0, version_js_1.resolvePacketId)(playToClient, ['keep_alive']) ?? missing,
162
+ chunkBatchFinished: (0, version_js_1.resolvePacketId)(playToClient, ['chunk_batch_finished']) ?? missing,
163
+ login: (0, version_js_1.resolvePacketId)(playToClient, ['login']) ?? missing,
164
+ position: (0, version_js_1.resolvePacketId)(playToClient, ['position']) ?? missing,
165
+ updateHealth: (0, version_js_1.resolvePacketId)(playToClient, ['update_health']) ?? missing,
166
+ blockChange: (0, version_js_1.resolvePacketId)(playToClient, ['block_change']) ?? missing,
167
+ bossBar: (0, version_js_1.resolvePacketId)(playToClient, ['boss_bar']) ?? missing,
168
+ spawnEntity: (0, version_js_1.resolvePacketId)(playToClient, ['spawn_entity']) ?? missing,
169
+ entityDestroy: (0, version_js_1.resolvePacketId)(playToClient, ['entity_destroy']) ?? missing,
170
+ relEntityMove: (0, version_js_1.resolvePacketId)(playToClient, ['rel_entity_move']) ?? missing,
171
+ entityMoveLook: (0, version_js_1.resolvePacketId)(playToClient, ['entity_move_look']) ?? missing,
172
+ entityVelocity: (0, version_js_1.resolvePacketId)(playToClient, ['entity_velocity']) ?? missing,
173
+ entityHeadRotation: (0, version_js_1.resolvePacketId)(playToClient, ['entity_head_rotation']) ?? missing,
174
+ gameStateChange: (0, version_js_1.resolvePacketId)(playToClient, ['game_state_change']) ?? missing,
175
+ respawn: (0, version_js_1.resolvePacketId)(playToClient, ['respawn']) ?? missing,
176
+ experience: (0, version_js_1.resolvePacketId)(playToClient, ['experience']) ?? missing,
177
+ updateTime: (0, version_js_1.resolvePacketId)(playToClient, ['update_time']) ?? missing,
178
+ spawnPosition: (0, version_js_1.resolvePacketId)(playToClient, ['spawn_position']) ?? missing,
179
+ openWindow: (0, version_js_1.resolvePacketId)(playToClient, ['open_window']) ?? missing,
180
+ windowItems: (0, version_js_1.resolvePacketId)(playToClient, ['window_items']) ?? missing,
181
+ setSlot: (0, version_js_1.resolvePacketId)(playToClient, ['set_slot']) ?? missing,
182
+ closeWindow: (0, version_js_1.resolvePacketId)(playToClient, ['close_window']) ?? missing,
183
+ ping: (0, version_js_1.resolvePacketId)(playToClient, ['ping']) ?? missing,
184
+ acknowledgePlayerDigging: (0, version_js_1.resolvePacketId)(playToClient, ['acknowledge_player_digging']) ?? missing,
185
+ disconnect: (0, version_js_1.resolvePacketId)(playToClient, ['kick_disconnect']) ?? missing,
186
+ abilities: (0, version_js_1.resolvePacketId)(playToClient, ['abilities']) ?? missing,
187
+ systemChat: (0, version_js_1.resolvePacketId)(playToClient, ['system_chat']) ?? missing,
188
+ profilelessChat: (0, version_js_1.resolvePacketId)(playToClient, ['profileless_chat']) ?? missing,
189
+ legacyChat: (0, version_js_1.resolvePacketId)(playToClient, ['chat']) ?? missing,
190
+ };
191
+ this.playServerIds = {
192
+ keepAlive: (0, version_js_1.resolvePacketId)(playToServer, ['keep_alive']) ?? missing,
193
+ chunkBatchReceived: (0, version_js_1.resolvePacketId)(playToServer, ['chunk_batch_received']) ?? missing,
194
+ teleportConfirm: (0, version_js_1.resolvePacketId)(playToServer, ['teleport_confirm']) ?? missing,
195
+ position: (0, version_js_1.resolvePacketId)(playToServer, ['position']) ?? missing,
196
+ positionLook: (0, version_js_1.resolvePacketId)(playToServer, ['position_look']) ?? missing,
197
+ look: (0, version_js_1.resolvePacketId)(playToServer, ['look']) ?? missing,
198
+ flying: (0, version_js_1.resolvePacketId)(playToServer, ['flying']) ?? missing,
199
+ chat: (0, version_js_1.resolvePacketId)(playToServer, ['chat']) ?? missing,
200
+ chatMessage: (0, version_js_1.resolvePacketId)(playToServer, ['chat_message']) ?? missing,
201
+ chatCommand: (0, version_js_1.resolvePacketId)(playToServer, ['chat_command']) ?? missing,
202
+ useEntity: (0, version_js_1.resolvePacketId)(playToServer, ['use_entity']) ?? missing,
203
+ armAnimation: (0, version_js_1.resolvePacketId)(playToServer, ['arm_animation']) ?? missing,
204
+ entityAction: (0, version_js_1.resolvePacketId)(playToServer, ['entity_action']) ?? missing,
205
+ blockDig: (0, version_js_1.resolvePacketId)(playToServer, ['block_dig']) ?? missing,
206
+ blockPlace: (0, version_js_1.resolvePacketId)(playToServer, ['block_place']) ?? missing,
207
+ useItem: (0, version_js_1.resolvePacketId)(playToServer, ['use_item']) ?? missing,
208
+ heldItemSlot: (0, version_js_1.resolvePacketId)(playToServer, ['held_item_slot']) ?? missing,
209
+ abilities: (0, version_js_1.resolvePacketId)(playToServer, ['abilities']) ?? missing,
210
+ clientCommand: (0, version_js_1.resolvePacketId)(playToServer, ['client_command']) ?? missing,
211
+ closeWindow: (0, version_js_1.resolvePacketId)(playToServer, ['close_window']) ?? missing,
212
+ pong: (0, version_js_1.resolvePacketId)(playToServer, ['pong']) ?? missing,
213
+ };
109
214
  // Initialize subsystems
110
215
  this.world = new world_js_1.World();
111
216
  this.entities = new entity_js_1.EntityManager();
@@ -151,6 +256,20 @@ class Bot extends events_js_1.TypedEventEmitter {
151
256
  get gameMode() { return this._gameMode; }
152
257
  get isAlive() { return this._isAlive; }
153
258
  get position() { return this.entity.position; }
259
+ requirePacketId(packetId, packetName) {
260
+ if (packetId === MISSING_PACKET_ID) {
261
+ throw new Error(`Packet '${packetName}' is unavailable for protocol ${this.options.version} (${this.protocolInfo.minecraftVersion})`);
262
+ }
263
+ return packetId;
264
+ }
265
+ sendPlayPacket(packetId, data, packetName) {
266
+ this.connection.sendPacket(this.requirePacketId(packetId, packetName), data);
267
+ }
268
+ emitChatFromComponent(rawContent, isOverlay) {
269
+ const message = chat_js_1.ChatMessage.parse(rawContent);
270
+ this.emit('chatMessage', message, isOverlay);
271
+ this.emit('chat', message.toString(), isOverlay);
272
+ }
154
273
  // ─── Connect & Login ────────────────────────────────
155
274
  /**
156
275
  * Connect to the server and begin the login process.
@@ -191,7 +310,7 @@ class Bot extends events_js_1.TypedEventEmitter {
191
310
  }
192
311
  // Step 3: Send Login Start
193
312
  this.logger.info(`Logging in as ${this._username} (${uuid})...`);
194
- this.connection.sendPacket(login_js_1.LoginServerboundPackets.LOGIN_START, (0, login_js_1.buildLoginStartPacket)(this._username, uuid));
313
+ this.connection.sendPacket(this.requirePacketId(this.loginServerIds.loginStart, 'login_start'), (0, login_js_1.buildLoginStartPacket)(this._username, uuid, this.options.version));
195
314
  // Step 4: Handle login response packets
196
315
  await this.handleLoginSequence();
197
316
  }
@@ -232,54 +351,64 @@ class Bot extends events_js_1.TypedEventEmitter {
232
351
  }
233
352
  async handleLoginPacket(packet, onComplete) {
234
353
  switch (packet.id) {
235
- case login_js_1.LoginClientboundPackets.ENCRYPTION_REQUEST: {
354
+ case this.loginClientIds.encryptionBegin: {
236
355
  await this.handleEncryptionRequest(packet.data);
237
356
  break;
238
357
  }
239
- case login_js_1.LoginClientboundPackets.SET_COMPRESSION: {
358
+ case this.loginClientIds.compress: {
240
359
  const { threshold } = (0, login_js_1.parseSetCompressionPacket)(packet.data);
241
360
  this.connection.enableCompression(threshold);
242
361
  this.logger.info(`Compression enabled (threshold: ${threshold})`);
243
362
  break;
244
363
  }
245
- case login_js_1.LoginClientboundPackets.LOGIN_SUCCESS: {
246
- const success = (0, login_js_1.parseLoginSuccessPacket)(packet.data);
364
+ case this.loginClientIds.success: {
365
+ const success = (0, login_js_1.parseLoginSuccessPacket)(packet.data, this.options.version);
247
366
  this._username = success.username;
248
367
  this._uuid = success.uuid;
249
368
  this.logger.info(`Login successful! ${success.username} (${success.uuid})`);
250
369
  // Send Login Acknowledged
251
- this.connection.sendPacket(login_js_1.LoginServerboundPackets.LOGIN_ACKNOWLEDGED, (0, login_js_1.buildLoginAcknowledgedPacket)());
370
+ if (this.loginServerIds.loginAcknowledged !== MISSING_PACKET_ID) {
371
+ this.connection.sendPacket(this.loginServerIds.loginAcknowledged, (0, login_js_1.buildLoginAcknowledgedPacket)());
372
+ }
252
373
  // Remove login handler FIRST, then enter Configuration state
253
374
  onComplete();
254
375
  // Enter Configuration state — handle config packets before Play
255
- this.handleConfigurationState().then(() => {
376
+ if (this.protocolInfo.supportsConfigurationState) {
377
+ this.handleConfigurationState().then(() => {
378
+ this.setupPlayStateHandlers();
379
+ this.emit('login');
380
+ }).catch((err) => {
381
+ this.logger.error('Configuration state failed:', err);
382
+ const error = err instanceof Error ? err : new Error(String(err));
383
+ this.emit('error', error);
384
+ this.disconnect();
385
+ });
386
+ }
387
+ else {
256
388
  this.setupPlayStateHandlers();
257
389
  this.emit('login');
258
- }).catch((err) => {
259
- this.logger.error('Configuration state failed:', err);
260
- const error = err instanceof Error ? err : new Error(String(err));
261
- this.emit('error', error);
262
- this.disconnect();
263
- });
390
+ }
264
391
  break;
265
392
  }
266
- case login_js_1.LoginClientboundPackets.DISCONNECT: {
393
+ case this.loginClientIds.disconnect: {
267
394
  const { reason } = (0, login_js_1.parseDisconnectPacket)(packet.data);
268
395
  this.logger.error(`Disconnected during login: ${reason}`);
269
396
  this.emit('kicked', reason);
270
397
  throw new Error(`Disconnected during login: ${reason}`);
271
398
  }
272
- case login_js_1.LoginClientboundPackets.LOGIN_PLUGIN_REQUEST: {
399
+ case this.loginClientIds.loginPluginRequest: {
273
400
  const pluginReq = (0, login_js_1.parseLoginPluginRequestPacket)(packet.data);
274
401
  this.logger.debug(`Login plugin request: ${pluginReq.channel}`);
275
402
  // Respond with "not understood"
276
- this.connection.sendPacket(login_js_1.LoginServerboundPackets.LOGIN_PLUGIN_RESPONSE, (0, login_js_1.buildLoginPluginResponsePacket)(pluginReq.messageId));
403
+ if (this.loginServerIds.loginPluginResponse !== MISSING_PACKET_ID) {
404
+ this.connection.sendPacket(this.loginServerIds.loginPluginResponse, (0, login_js_1.buildLoginPluginResponsePacket)(pluginReq.messageId));
405
+ }
277
406
  break;
278
407
  }
279
408
  }
280
409
  }
281
410
  async handleEncryptionRequest(data) {
282
- const request = (0, login_js_1.parseEncryptionRequestPacket)(data);
411
+ const request = (0, login_js_1.parseEncryptionRequestPacket)(data, this.options.version);
283
412
  this.logger.info('Handling encryption...');
284
413
  // Generate shared secret
285
414
  const sharedSecret = (0, encryption_js_1.generateSharedSecret)();
@@ -294,7 +423,7 @@ class Bot extends events_js_1.TypedEventEmitter {
294
423
  const serverHash = (0, encryption_js_1.computeServerHash)(request.serverId, sharedSecret, request.publicKey);
295
424
  await (0, microsoft_js_1.joinServer)(this.accessToken, this._uuid, serverHash);
296
425
  }
297
- this.connection.sendPacket(login_js_1.LoginServerboundPackets.ENCRYPTION_RESPONSE, (0, login_js_1.buildEncryptionResponsePacket)(encryptedSecret, encryptedToken));
426
+ this.connection.sendPacket(this.requirePacketId(this.loginServerIds.encryptionBegin, 'encryption_begin'), (0, login_js_1.buildEncryptionResponsePacket)(encryptedSecret, encryptedToken));
298
427
  this.connection.enableEncryption(sharedSecret);
299
428
  }
300
429
  // ─── Configuration State ────────────────────────────
@@ -303,7 +432,7 @@ class Bot extends events_js_1.TypedEventEmitter {
303
432
  * In 1.20.2+, the server sends registry data, feature flags, etc. before Play.
304
433
  * When the server sends Finish Configuration (0x03), we transition to Play.
305
434
  *
306
- * 1.21.4 Configuration Clientbound Packet IDs:
435
+ * Example configuration clientbound packet IDs (latest protocol):
307
436
  * 0x00 = Cookie Request
308
437
  * 0x01 = Plugin Message
309
438
  * 0x02 = Disconnect
@@ -341,76 +470,76 @@ class Bot extends events_js_1.TypedEventEmitter {
341
470
  };
342
471
  const configHandler = (packet) => {
343
472
  switch (packet.id) {
344
- case 0x03: {
473
+ case this.configurationClientIds.finishConfiguration: {
345
474
  // Finish Configuration (clientbound)
346
475
  this.logger.info('Configuration complete, entering Play state...');
347
- // Send Acknowledge Finish Configuration (serverbound 0x03)
348
- this.connection.sendPacket(0x03, Buffer.alloc(0));
476
+ // Send Acknowledge Finish Configuration (serverbound)
477
+ this.connection.sendPacket(this.requirePacketId(this.configurationServerIds.finishConfiguration, 'finish_configuration'), Buffer.alloc(0));
349
478
  finish(resolve);
350
479
  break;
351
480
  }
352
- case 0x04: {
481
+ case this.configurationClientIds.keepAlive: {
353
482
  // Keep Alive (clientbound) — must respond or get kicked
354
- const reader = new types_js_1.BufferReader(packet.data);
355
- const keepAliveId = reader.readLong();
356
- this.logger.debug(`Config: Keep alive (${keepAliveId})`);
357
- // Respond with same keep alive ID (serverbound 0x04)
358
- const kaWriter = new types_js_1.BufferWriter();
359
- kaWriter.writeLong(keepAliveId);
360
- this.connection.sendPacket(0x04, kaWriter.toBuffer());
483
+ if (this.configurationServerIds.keepAlive !== MISSING_PACKET_ID) {
484
+ this.connection.sendPacket(this.configurationServerIds.keepAlive, packet.data);
485
+ }
361
486
  break;
362
487
  }
363
- case 0x01: {
488
+ case this.configurationClientIds.customPayload: {
364
489
  // Plugin Message (clientbound) — ignore
365
490
  this.logger.debug('Config: Plugin message received');
366
491
  break;
367
492
  }
368
- case 0x07: {
493
+ case this.configurationClientIds.registryData: {
369
494
  // Registry Data — ignore (we don't track registry data yet)
370
495
  this.logger.debug('Config: Registry data received');
371
496
  break;
372
497
  }
373
- case 0x0C: {
498
+ case this.configurationClientIds.featureFlags: {
374
499
  // Feature Flags — ignore
375
500
  this.logger.debug('Config: Feature flags received');
376
501
  break;
377
502
  }
378
- case 0x0D: {
503
+ case this.configurationClientIds.tags: {
379
504
  // Update Tags — ignore
380
505
  this.logger.debug('Config: Tags update received');
381
506
  break;
382
507
  }
383
- case 0x0E: {
508
+ case this.configurationClientIds.selectKnownPacks: {
384
509
  // Known Packs (clientbound) — respond with empty known packs
385
510
  this.logger.debug('Config: Known packs request');
386
511
  // Send Known Packs response (serverbound 0x07) — empty
387
512
  const knownPacksWriter = new types_js_1.BufferWriter();
388
513
  knownPacksWriter.writeVarInt(0); // 0 known packs
389
- this.connection.sendPacket(0x07, knownPacksWriter.toBuffer());
514
+ if (this.configurationServerIds.selectKnownPacks !== MISSING_PACKET_ID) {
515
+ this.connection.sendPacket(this.configurationServerIds.selectKnownPacks, knownPacksWriter.toBuffer());
516
+ }
390
517
  break;
391
518
  }
392
- case 0x05: {
519
+ case this.configurationClientIds.ping: {
393
520
  // Ping — respond with pong
394
521
  this.logger.debug('Config: Ping received');
395
- this.connection.sendPacket(0x02, packet.data); // Pong (serverbound 0x02)
522
+ if (this.configurationServerIds.pong !== MISSING_PACKET_ID) {
523
+ this.connection.sendPacket(this.configurationServerIds.pong, packet.data);
524
+ }
396
525
  break;
397
526
  }
398
- case 0x00: {
527
+ case this.configurationClientIds.cookieRequest: {
399
528
  // Cookie Request — ignore
400
529
  this.logger.debug('Config: Cookie request');
401
530
  break;
402
531
  }
403
- case 0x09: {
532
+ case this.configurationClientIds.addResourcePack: {
404
533
  // Add Resource Pack — respond with accepted (status 3 = accepted)
405
534
  this.logger.debug('Config: Resource pack request');
406
535
  break;
407
536
  }
408
- case 0x10: {
537
+ case this.configurationClientIds.serverLinks: {
409
538
  // Server Links — ignore
410
539
  this.logger.debug('Config: Server links received');
411
540
  break;
412
541
  }
413
- case 0x02: {
542
+ case this.configurationClientIds.disconnect: {
414
543
  // Disconnect
415
544
  const reader = new types_js_1.BufferReader(packet.data);
416
545
  const reason = reader.readString();
@@ -453,21 +582,25 @@ class Bot extends events_js_1.TypedEventEmitter {
453
582
  }
454
583
  handlePlayPacket(packet) {
455
584
  switch (packet.id) {
456
- case play_js_1.PlayClientboundPackets.KEEP_ALIVE: {
457
- const { keepAliveId } = (0, play_js_1.parseKeepAlive)(packet.data);
458
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.KEEP_ALIVE, (0, play_js_1.buildKeepAlivePacket)(keepAliveId));
585
+ case this.playClientIds.keepAlive: {
586
+ if (this.playServerIds.keepAlive !== MISSING_PACKET_ID) {
587
+ // Keep alive payload type changes by protocol; echo raw payload safely.
588
+ this.connection.sendPacket(this.playServerIds.keepAlive, packet.data);
589
+ }
459
590
  break;
460
591
  }
461
- case play_js_1.PlayClientboundPackets.CHUNK_BATCH_FINISHED: {
592
+ case this.playClientIds.chunkBatchFinished: {
462
593
  // Must respond with chunk_batch_received or server kicks
463
- const writer = new types_js_1.BufferWriter();
464
- writer.writeFloat(20.0); // chunks per tick
465
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.CHUNK_BATCH_RECEIVED, writer.toBuffer());
594
+ if (this.playServerIds.chunkBatchReceived !== MISSING_PACKET_ID) {
595
+ const writer = new types_js_1.BufferWriter();
596
+ writer.writeFloat(20.0); // chunks per tick
597
+ this.connection.sendPacket(this.playServerIds.chunkBatchReceived, writer.toBuffer());
598
+ }
466
599
  break;
467
600
  }
468
- case play_js_1.PlayClientboundPackets.LOGIN: {
601
+ case this.playClientIds.login: {
469
602
  try {
470
- const login = (0, play_js_1.parseLoginPlay)(packet.data);
603
+ const login = (0, play_js_1.parseLoginPlay)(packet.data, this.options.version);
471
604
  this._entityId = login.entityId;
472
605
  this._gameMode = login.gameMode;
473
606
  this.entity.id = login.entityId;
@@ -483,9 +616,9 @@ class Bot extends events_js_1.TypedEventEmitter {
483
616
  }
484
617
  break;
485
618
  }
486
- case play_js_1.PlayClientboundPackets.PLAYER_POSITION: {
619
+ case this.playClientIds.position: {
487
620
  try {
488
- const pos = (0, play_js_1.parsePlayerPosition)(packet.data);
621
+ const pos = (0, play_js_1.parsePlayerPosition)(packet.data, this.options.version);
489
622
  // Apply relative/absolute position based on flags
490
623
  const flags = pos.flags;
491
624
  const x = (flags & 0x01) ? this.entity.position.x + pos.x : pos.x;
@@ -495,7 +628,10 @@ class Bot extends events_js_1.TypedEventEmitter {
495
628
  this.entity.yaw = pos.yaw;
496
629
  this.entity.pitch = pos.pitch;
497
630
  // Must confirm teleportation
498
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.CONFIRM_TELEPORTATION, (0, play_js_1.buildConfirmTeleportationPacket)(pos.teleportId));
631
+ if (this.playServerIds.teleportConfirm !== MISSING_PACKET_ID &&
632
+ pos.teleportId >= 0) {
633
+ this.connection.sendPacket(this.playServerIds.teleportConfirm, (0, play_js_1.buildConfirmTeleportationPacket)(pos.teleportId));
634
+ }
499
635
  this.emit('position', this.entity.position);
500
636
  }
501
637
  catch (err) {
@@ -503,7 +639,7 @@ class Bot extends events_js_1.TypedEventEmitter {
503
639
  }
504
640
  break;
505
641
  }
506
- case play_js_1.PlayClientboundPackets.SET_HEALTH: {
642
+ case this.playClientIds.updateHealth: {
507
643
  const { health, food, saturation } = (0, play_js_1.parseSetHealth)(packet.data);
508
644
  this._health = health;
509
645
  this._food = food;
@@ -524,7 +660,7 @@ class Bot extends events_js_1.TypedEventEmitter {
524
660
  }
525
661
  break;
526
662
  }
527
- case play_js_1.PlayClientboundPackets.BLOCK_UPDATE: {
663
+ case this.playClientIds.blockChange: {
528
664
  try {
529
665
  const update = (0, play_js_1.parseBlockUpdate)(packet.data);
530
666
  this.world.setBlock(update.x, update.y, update.z, update.blockId);
@@ -535,7 +671,7 @@ class Bot extends events_js_1.TypedEventEmitter {
535
671
  }
536
672
  break;
537
673
  }
538
- case play_js_1.PlayClientboundPackets.BOSS_BAR: {
674
+ case this.playClientIds.bossBar: {
539
675
  try {
540
676
  const boss = (0, play_js_1.parseBossBar)(packet.data);
541
677
  this.bossBars.handleBossBar(boss.uuid, boss.action, boss.data);
@@ -545,7 +681,7 @@ class Bot extends events_js_1.TypedEventEmitter {
545
681
  }
546
682
  break;
547
683
  }
548
- case play_js_1.PlayClientboundPackets.SPAWN_ENTITY: {
684
+ case this.playClientIds.spawnEntity: {
549
685
  try {
550
686
  const spawn = (0, play_js_1.parseSpawnEntity)(packet.data);
551
687
  const entity = new entity_js_1.Entity(spawn.entityId, spawn.entityUUID, spawn.type, new vec3_js_1.Vec3(spawn.x, spawn.y, spawn.z));
@@ -559,7 +695,7 @@ class Bot extends events_js_1.TypedEventEmitter {
559
695
  }
560
696
  break;
561
697
  }
562
- case play_js_1.PlayClientboundPackets.REMOVE_ENTITIES: {
698
+ case this.playClientIds.entityDestroy: {
563
699
  try {
564
700
  const { entityIds } = (0, play_js_1.parseRemoveEntities)(packet.data);
565
701
  for (const entityId of entityIds) {
@@ -572,7 +708,7 @@ class Bot extends events_js_1.TypedEventEmitter {
572
708
  }
573
709
  break;
574
710
  }
575
- case play_js_1.PlayClientboundPackets.ENTITY_POSITION: {
711
+ case this.playClientIds.relEntityMove: {
576
712
  try {
577
713
  const pos = (0, play_js_1.parseEntityPosition)(packet.data);
578
714
  const entity = this.entities.get(pos.entityId);
@@ -584,7 +720,7 @@ class Bot extends events_js_1.TypedEventEmitter {
584
720
  catch (_) { /* ignore */ }
585
721
  break;
586
722
  }
587
- case play_js_1.PlayClientboundPackets.ENTITY_POSITION_AND_ROTATION: {
723
+ case this.playClientIds.entityMoveLook: {
588
724
  try {
589
725
  const pos = (0, play_js_1.parseEntityPositionAndRotation)(packet.data);
590
726
  const entity = this.entities.get(pos.entityId);
@@ -598,7 +734,7 @@ class Bot extends events_js_1.TypedEventEmitter {
598
734
  catch (_) { /* ignore */ }
599
735
  break;
600
736
  }
601
- case play_js_1.PlayClientboundPackets.SET_ENTITY_VELOCITY: {
737
+ case this.playClientIds.entityVelocity: {
602
738
  try {
603
739
  const vel = (0, play_js_1.parseEntityVelocity)(packet.data);
604
740
  this.emit('entityVelocity', vel.entityId, new vec3_js_1.Vec3(vel.velocityX, vel.velocityY, vel.velocityZ));
@@ -606,7 +742,7 @@ class Bot extends events_js_1.TypedEventEmitter {
606
742
  catch (_) { /* ignore */ }
607
743
  break;
608
744
  }
609
- case play_js_1.PlayClientboundPackets.ENTITY_HEAD_ROTATION: {
745
+ case this.playClientIds.entityHeadRotation: {
610
746
  try {
611
747
  const rot = (0, play_js_1.parseEntityHeadRotation)(packet.data);
612
748
  const entity = this.entities.get(rot.entityId);
@@ -617,7 +753,7 @@ class Bot extends events_js_1.TypedEventEmitter {
617
753
  catch (_) { /* ignore */ }
618
754
  break;
619
755
  }
620
- case play_js_1.PlayClientboundPackets.GAME_EVENT: {
756
+ case this.playClientIds.gameStateChange: {
621
757
  try {
622
758
  const ev = (0, play_js_1.parseGameEvent)(packet.data);
623
759
  if (ev.event === play_js_1.GameEventType.CHANGE_GAME_MODE) {
@@ -626,14 +762,16 @@ class Bot extends events_js_1.TypedEventEmitter {
626
762
  this.weather.handleGameEvent(ev.event, ev.value);
627
763
  if (ev.event === play_js_1.GameEventType.START_WAITING_FOR_LEVEL_CHUNKS) {
628
764
  // Send position confirmation after chunks start loading
629
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.SET_PLAYER_POSITION_AND_ROTATION, (0, play_js_1.buildSetPlayerPositionAndRotationPacket)(this.entity.position.x, this.entity.position.y, this.entity.position.z, this.entity.yaw, this.entity.pitch, true));
765
+ if (this.playServerIds.positionLook !== MISSING_PACKET_ID) {
766
+ this.connection.sendPacket(this.playServerIds.positionLook, (0, play_js_1.buildSetPlayerPositionAndRotationPacket)(this.entity.position.x, this.entity.position.y, this.entity.position.z, this.entity.yaw, this.entity.pitch, true, this.options.version));
767
+ }
630
768
  }
631
769
  this.emit('gameEvent', ev.event, ev.value);
632
770
  }
633
771
  catch (_) { /* ignore */ }
634
772
  break;
635
773
  }
636
- case play_js_1.PlayClientboundPackets.RESPAWN: {
774
+ case this.playClientIds.respawn: {
637
775
  try {
638
776
  const resp = (0, play_js_1.parseRespawn)(packet.data);
639
777
  this._gameMode = resp.gameMode;
@@ -647,7 +785,7 @@ class Bot extends events_js_1.TypedEventEmitter {
647
785
  }
648
786
  break;
649
787
  }
650
- case play_js_1.PlayClientboundPackets.SET_EXPERIENCE: {
788
+ case this.playClientIds.experience: {
651
789
  try {
652
790
  const exp = (0, play_js_1.parseSetExperience)(packet.data);
653
791
  this._experience = exp.totalExperience;
@@ -657,7 +795,7 @@ class Bot extends events_js_1.TypedEventEmitter {
657
795
  catch (_) { /* ignore */ }
658
796
  break;
659
797
  }
660
- case play_js_1.PlayClientboundPackets.UPDATE_TIME: {
798
+ case this.playClientIds.updateTime: {
661
799
  try {
662
800
  const time = (0, play_js_1.parseUpdateTime)(packet.data);
663
801
  this._worldAge = time.worldAge;
@@ -667,7 +805,7 @@ class Bot extends events_js_1.TypedEventEmitter {
667
805
  catch (_) { /* ignore */ }
668
806
  break;
669
807
  }
670
- case play_js_1.PlayClientboundPackets.SET_DEFAULT_SPAWN_POSITION: {
808
+ case this.playClientIds.spawnPosition: {
671
809
  try {
672
810
  const sp = (0, play_js_1.parseSetDefaultSpawnPosition)(packet.data);
673
811
  this._spawnPosition = new vec3_js_1.Vec3(sp.x, sp.y, sp.z);
@@ -676,7 +814,7 @@ class Bot extends events_js_1.TypedEventEmitter {
676
814
  catch (_) { /* ignore */ }
677
815
  break;
678
816
  }
679
- case play_js_1.PlayClientboundPackets.OPEN_SCREEN: {
817
+ case this.playClientIds.openWindow: {
680
818
  try {
681
819
  const open = (0, play_js_1.parseOpenScreen)(packet.data);
682
820
  this.inventory.openWindow(open.windowId, 0);
@@ -686,7 +824,7 @@ class Bot extends events_js_1.TypedEventEmitter {
686
824
  }
687
825
  break;
688
826
  }
689
- case play_js_1.PlayClientboundPackets.SET_CONTAINER_CONTENT: {
827
+ case this.playClientIds.windowItems: {
690
828
  try {
691
829
  const reader = new types_js_1.BufferReader(packet.data);
692
830
  const windowId = reader.readUByte();
@@ -701,7 +839,7 @@ class Bot extends events_js_1.TypedEventEmitter {
701
839
  }
702
840
  break;
703
841
  }
704
- case play_js_1.PlayClientboundPackets.SET_CONTAINER_SLOT: {
842
+ case this.playClientIds.setSlot: {
705
843
  try {
706
844
  const slot = (0, play_js_1.parseSetContainerSlot)(packet.data);
707
845
  const item = inventory_js_1.Inventory.parseItem(new types_js_1.BufferReader(slot.slotData));
@@ -713,34 +851,36 @@ class Bot extends events_js_1.TypedEventEmitter {
713
851
  }
714
852
  break;
715
853
  }
716
- case play_js_1.PlayClientboundPackets.CONTAINER_CLOSE: {
854
+ case this.playClientIds.closeWindow: {
717
855
  this.inventory.closeWindow();
718
856
  break;
719
857
  }
720
- case play_js_1.PlayClientboundPackets.PING: {
858
+ case this.playClientIds.ping: {
721
859
  try {
722
860
  const reader = new types_js_1.BufferReader(packet.data);
723
861
  const pingId = reader.readInt();
724
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.PONG, (0, play_js_1.buildPongPacket)(pingId));
862
+ if (this.playServerIds.pong !== MISSING_PACKET_ID) {
863
+ this.connection.sendPacket(this.playServerIds.pong, (0, play_js_1.buildPongPacket)(pingId));
864
+ }
725
865
  }
726
866
  catch (_) { /* ignore */ }
727
867
  break;
728
868
  }
729
- case play_js_1.PlayClientboundPackets.ACKNOWLEDGE_BLOCK_CHANGE: {
869
+ case this.playClientIds.acknowledgePlayerDigging: {
730
870
  try {
731
871
  (0, play_js_1.parseAcknowledgeBlockChange)(packet.data);
732
872
  }
733
873
  catch (_) { /* ignore */ }
734
874
  break;
735
875
  }
736
- case play_js_1.PlayClientboundPackets.DISCONNECT: {
876
+ case this.playClientIds.disconnect: {
737
877
  const { reason } = (0, play_js_1.parseDisconnectPlay)(packet.data);
738
878
  this.logger.warn(`Kicked: ${reason}`);
739
879
  this.stopPhysicsTick();
740
880
  this.emit('kicked', reason);
741
881
  break;
742
882
  }
743
- case play_js_1.PlayClientboundPackets.PLAYER_ABILITIES: {
883
+ case this.playClientIds.abilities: {
744
884
  try {
745
885
  const abilities = (0, play_js_1.parsePlayerAbilities)(packet.data);
746
886
  this.logger.debug(`Abilities: flags=${abilities.flags} fly=${abilities.flyingSpeed} walk=${abilities.walkingSpeed}`);
@@ -750,12 +890,29 @@ class Bot extends events_js_1.TypedEventEmitter {
750
890
  }
751
891
  break;
752
892
  }
753
- case play_js_1.PlayClientboundPackets.SYSTEM_CHAT: {
893
+ case this.playClientIds.systemChat: {
754
894
  try {
755
895
  const chat = (0, play_js_1.parseSystemChat)(packet.data);
756
- const message = chat_js_1.ChatMessage.parse(chat.content);
757
- this.emit('chatMessage', message, chat.isOverlay);
758
- this.emit('chat', message.toString(), chat.isOverlay);
896
+ this.emitChatFromComponent(chat.content, chat.isOverlay);
897
+ }
898
+ catch (_) { /* ignore */ }
899
+ break;
900
+ }
901
+ case this.playClientIds.profilelessChat: {
902
+ try {
903
+ const reader = new types_js_1.BufferReader(packet.data);
904
+ const content = reader.readString();
905
+ this.emitChatFromComponent(content, false);
906
+ }
907
+ catch (_) { /* ignore */ }
908
+ break;
909
+ }
910
+ case this.playClientIds.legacyChat: {
911
+ try {
912
+ const reader = new types_js_1.BufferReader(packet.data);
913
+ const content = reader.readString();
914
+ const position = reader.remaining > 0 ? reader.readByte() : 0;
915
+ this.emitChatFromComponent(content, position === 2);
759
916
  }
760
917
  catch (_) { /* ignore */ }
761
918
  break;
@@ -771,7 +928,7 @@ class Bot extends events_js_1.TypedEventEmitter {
771
928
  return;
772
929
  // Send position to server every tick to stay "alive"
773
930
  try {
774
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.SET_PLAYER_POSITION_AND_ROTATION, (0, play_js_1.buildSetPlayerPositionAndRotationPacket)(this.entity.position.x, this.entity.position.y, this.entity.position.z, this.entity.yaw, this.entity.pitch, true));
931
+ this.sendPlayPacket(this.playServerIds.positionLook, (0, play_js_1.buildSetPlayerPositionAndRotationPacket)(this.entity.position.x, this.entity.position.y, this.entity.position.z, this.entity.yaw, this.entity.pitch, true, this.options.version), 'position_look');
775
932
  }
776
933
  catch (_) {
777
934
  this.stopPhysicsTick();
@@ -813,38 +970,49 @@ class Bot extends events_js_1.TypedEventEmitter {
813
970
  * Send a chat message.
814
971
  */
815
972
  chat(message) {
816
- const chatPlugin = this.plugins.get('chat');
817
- if (chatPlugin) {
818
- chatPlugin.chat(message);
973
+ if (this.playServerIds.chatMessage !== MISSING_PACKET_ID) {
974
+ this.sendPlayPacket(this.playServerIds.chatMessage, (0, play_js_1.buildChatMessagePacket)(message, this.options.version), 'chat_message');
975
+ return;
819
976
  }
977
+ if (this.playServerIds.chat !== MISSING_PACKET_ID) {
978
+ this.sendPlayPacket(this.playServerIds.chat, (0, play_js_1.buildChatMessagePacket)(message, this.options.version), 'chat');
979
+ return;
980
+ }
981
+ throw new Error(`Chat is not supported for protocol ${this.options.version}`);
820
982
  }
821
983
  /**
822
984
  * Send a / command (e.g. bot.command('gamemode creative')).
823
985
  */
824
986
  command(cmd) {
825
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.CHAT_COMMAND, (0, play_js_1.buildChatCommandPacket)(cmd));
987
+ if (this.playServerIds.chatCommand !== MISSING_PACKET_ID) {
988
+ try {
989
+ this.sendPlayPacket(this.playServerIds.chatCommand, (0, play_js_1.buildChatCommandPacket)(cmd, this.options.version), 'chat_command');
990
+ return;
991
+ }
992
+ catch (_) {
993
+ // Fallback to plain chat command below.
994
+ }
995
+ }
996
+ this.chat(`/${cmd}`);
826
997
  }
827
998
  /**
828
999
  * Attack an entity.
829
1000
  */
830
1001
  attack(entity) {
831
- const combatPlugin = this.plugins.get('combat');
832
- if (combatPlugin) {
833
- combatPlugin.attack(entity);
834
- }
1002
+ this.attackEntity(entity.id);
835
1003
  }
836
1004
  /**
837
1005
  * Attack entity by ID (raw packet).
838
1006
  */
839
1007
  attackEntity(entityId) {
840
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.INTERACT, (0, play_js_1.buildInteractEntityPacket)(entityId, play_js_1.InteractEntityType.ATTACK, this._isSneaking));
841
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.SWING_ARM, (0, play_js_1.buildSwingArmPacket)(0));
1008
+ this.sendPlayPacket(this.playServerIds.useEntity, (0, play_js_1.buildInteractEntityPacket)(entityId, play_js_1.InteractEntityType.ATTACK, this._isSneaking, undefined, undefined, undefined, undefined, this.options.version), 'use_entity');
1009
+ this.sendPlayPacket(this.playServerIds.armAnimation, (0, play_js_1.buildSwingArmPacket)(0, this.options.version), 'arm_animation');
842
1010
  }
843
1011
  /**
844
1012
  * Right-click / use an entity (villager trade, mount, etc.).
845
1013
  */
846
1014
  useEntity(entityId, hand = 0) {
847
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.INTERACT, (0, play_js_1.buildInteractEntityPacket)(entityId, play_js_1.InteractEntityType.INTERACT, this._isSneaking, undefined, undefined, undefined, hand));
1015
+ this.sendPlayPacket(this.playServerIds.useEntity, (0, play_js_1.buildInteractEntityPacket)(entityId, play_js_1.InteractEntityType.INTERACT, this._isSneaking, undefined, undefined, undefined, hand, this.options.version), 'use_entity');
848
1016
  }
849
1017
  /**
850
1018
  * Set the bot's position (sends position packet to server).
@@ -852,7 +1020,7 @@ class Bot extends events_js_1.TypedEventEmitter {
852
1020
  setPosition(x, y, z, onGround = true) {
853
1021
  this.entity.position = new vec3_js_1.Vec3(x, y, z);
854
1022
  this.entity.onGround = onGround;
855
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.SET_PLAYER_POSITION, (0, play_js_1.buildSetPlayerPositionPacket)(x, y, z, onGround));
1023
+ this.sendPlayPacket(this.playServerIds.position, (0, play_js_1.buildSetPlayerPositionPacket)(x, y, z, onGround, this.options.version), 'position');
856
1024
  }
857
1025
  /**
858
1026
  * Set position and rotation.
@@ -862,7 +1030,7 @@ class Bot extends events_js_1.TypedEventEmitter {
862
1030
  this.entity.yaw = yaw;
863
1031
  this.entity.pitch = pitch;
864
1032
  this.entity.onGround = onGround;
865
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.SET_PLAYER_POSITION_AND_ROTATION, (0, play_js_1.buildSetPlayerPositionAndRotationPacket)(x, y, z, yaw, pitch, onGround));
1033
+ this.sendPlayPacket(this.playServerIds.positionLook, (0, play_js_1.buildSetPlayerPositionAndRotationPacket)(x, y, z, yaw, pitch, onGround, this.options.version), 'position_look');
866
1034
  }
867
1035
  /**
868
1036
  * Look at a position.
@@ -874,21 +1042,21 @@ class Bot extends events_js_1.TypedEventEmitter {
874
1042
  const pitch = -Math.atan2(delta.y, distance) * (180 / Math.PI);
875
1043
  this.entity.yaw = yaw;
876
1044
  this.entity.pitch = pitch;
877
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.SET_PLAYER_POSITION_AND_ROTATION, (0, play_js_1.buildSetPlayerPositionAndRotationPacket)(this.entity.position.x, this.entity.position.y, this.entity.position.z, yaw, pitch, this.entity.onGround));
1045
+ this.sendPlayPacket(this.playServerIds.positionLook, (0, play_js_1.buildSetPlayerPositionAndRotationPacket)(this.entity.position.x, this.entity.position.y, this.entity.position.z, yaw, pitch, this.entity.onGround, this.options.version), 'position_look');
878
1046
  }
879
1047
  /**
880
1048
  * Start/stop sprinting.
881
1049
  */
882
1050
  sprint(enabled) {
883
1051
  this._isSprinting = enabled;
884
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_COMMAND, (0, play_js_1.buildPlayerCommandPacket)(this._entityId, enabled ? play_js_1.PlayerCommandAction.START_SPRINTING : play_js_1.PlayerCommandAction.STOP_SPRINTING));
1052
+ this.sendPlayPacket(this.playServerIds.entityAction, (0, play_js_1.buildPlayerCommandPacket)(this._entityId, enabled ? play_js_1.PlayerCommandAction.START_SPRINTING : play_js_1.PlayerCommandAction.STOP_SPRINTING), 'entity_action');
885
1053
  }
886
1054
  /**
887
1055
  * Start/stop sneaking.
888
1056
  */
889
1057
  sneak(enabled) {
890
1058
  this._isSneaking = enabled;
891
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_COMMAND, (0, play_js_1.buildPlayerCommandPacket)(this._entityId, enabled ? play_js_1.PlayerCommandAction.START_SNEAKING : play_js_1.PlayerCommandAction.STOP_SNEAKING));
1059
+ this.sendPlayPacket(this.playServerIds.entityAction, (0, play_js_1.buildPlayerCommandPacket)(this._entityId, enabled ? play_js_1.PlayerCommandAction.START_SNEAKING : play_js_1.PlayerCommandAction.STOP_SNEAKING), 'entity_action');
892
1060
  }
893
1061
  /**
894
1062
  * Start digging a block.
@@ -896,13 +1064,13 @@ class Bot extends events_js_1.TypedEventEmitter {
896
1064
  dig(x, y, z, face = 1) {
897
1065
  this._actionSequence++;
898
1066
  // Start digging
899
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_ACTION, (0, play_js_1.buildPlayerActionPacket)(play_js_1.PlayerActionStatus.STARTED_DIGGING, x, y, z, face, this._actionSequence));
1067
+ this.sendPlayPacket(this.playServerIds.blockDig, (0, play_js_1.buildPlayerActionPacket)(play_js_1.PlayerActionStatus.STARTED_DIGGING, x, y, z, face, this._actionSequence, this.options.version), 'block_dig');
900
1068
  // Swing arm animation
901
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.SWING_ARM, (0, play_js_1.buildSwingArmPacket)(0));
1069
+ this.sendPlayPacket(this.playServerIds.armAnimation, (0, play_js_1.buildSwingArmPacket)(0, this.options.version), 'arm_animation');
902
1070
  // For creative mode, finish immediately
903
1071
  if (this._gameMode === 1) {
904
1072
  this._actionSequence++;
905
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_ACTION, (0, play_js_1.buildPlayerActionPacket)(play_js_1.PlayerActionStatus.FINISHED_DIGGING, x, y, z, face, this._actionSequence));
1073
+ this.sendPlayPacket(this.playServerIds.blockDig, (0, play_js_1.buildPlayerActionPacket)(play_js_1.PlayerActionStatus.FINISHED_DIGGING, x, y, z, face, this._actionSequence, this.options.version), 'block_dig');
906
1074
  }
907
1075
  }
908
1076
  /**
@@ -910,15 +1078,15 @@ class Bot extends events_js_1.TypedEventEmitter {
910
1078
  */
911
1079
  placeBlock(x, y, z, face = 1, hand = 0) {
912
1080
  this._actionSequence++;
913
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.USE_ITEM_ON, (0, play_js_1.buildUseItemOnPacket)(hand, x, y, z, face, 0.5, 0.5, 0.5, false, false, this._actionSequence));
914
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.SWING_ARM, (0, play_js_1.buildSwingArmPacket)(hand));
1081
+ this.sendPlayPacket(this.playServerIds.blockPlace, (0, play_js_1.buildUseItemOnPacket)(hand, x, y, z, face, 0.5, 0.5, 0.5, false, false, this._actionSequence, this.options.version), 'block_place');
1082
+ this.sendPlayPacket(this.playServerIds.armAnimation, (0, play_js_1.buildSwingArmPacket)(hand, this.options.version), 'arm_animation');
915
1083
  }
916
1084
  /**
917
1085
  * Use the item in hand (eat, throw, shoot bow, etc.).
918
1086
  */
919
1087
  useItem(hand = 0) {
920
1088
  this._actionSequence++;
921
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.USE_ITEM, (0, play_js_1.buildUseItemPacket)(hand, this._actionSequence, this.entity.yaw, this.entity.pitch));
1089
+ this.sendPlayPacket(this.playServerIds.useItem, (0, play_js_1.buildUseItemPacket)(hand, this._actionSequence, this.entity.yaw, this.entity.pitch, this.options.version), 'use_item');
922
1090
  }
923
1091
  /**
924
1092
  * Select a hotbar slot (0-8).
@@ -926,46 +1094,46 @@ class Bot extends events_js_1.TypedEventEmitter {
926
1094
  setHeldItem(slot) {
927
1095
  if (slot < 0 || slot > 8)
928
1096
  throw new Error('Slot must be 0-8');
929
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.SET_HELD_ITEM, (0, play_js_1.buildSetHeldItemPacket)(slot));
1097
+ this.sendPlayPacket(this.playServerIds.heldItemSlot, (0, play_js_1.buildSetHeldItemPacket)(slot), 'held_item_slot');
930
1098
  }
931
1099
  /**
932
1100
  * Swing arm animation.
933
1101
  */
934
1102
  swingArm(hand = 0) {
935
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.SWING_ARM, (0, play_js_1.buildSwingArmPacket)(hand));
1103
+ this.sendPlayPacket(this.playServerIds.armAnimation, (0, play_js_1.buildSwingArmPacket)(hand, this.options.version), 'arm_animation');
936
1104
  }
937
1105
  /**
938
1106
  * Drop the held item.
939
1107
  */
940
1108
  dropItem(dropStack = false) {
941
1109
  this._actionSequence++;
942
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_ACTION, (0, play_js_1.buildPlayerActionPacket)(dropStack ? play_js_1.PlayerActionStatus.DROP_ITEM_STACK : play_js_1.PlayerActionStatus.DROP_ITEM, 0, 0, 0, 0, this._actionSequence));
1110
+ this.sendPlayPacket(this.playServerIds.blockDig, (0, play_js_1.buildPlayerActionPacket)(dropStack ? play_js_1.PlayerActionStatus.DROP_ITEM_STACK : play_js_1.PlayerActionStatus.DROP_ITEM, 0, 0, 0, 0, this._actionSequence, this.options.version), 'block_dig');
943
1111
  }
944
1112
  /**
945
1113
  * Swap items between main and off hand.
946
1114
  */
947
1115
  swapHands() {
948
1116
  this._actionSequence++;
949
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_ACTION, (0, play_js_1.buildPlayerActionPacket)(play_js_1.PlayerActionStatus.SWAP_ITEM_IN_HAND, 0, 0, 0, 0, this._actionSequence));
1117
+ this.sendPlayPacket(this.playServerIds.blockDig, (0, play_js_1.buildPlayerActionPacket)(play_js_1.PlayerActionStatus.SWAP_ITEM_IN_HAND, 0, 0, 0, 0, this._actionSequence, this.options.version), 'block_dig');
950
1118
  }
951
1119
  /**
952
1120
  * Toggle flying (creative/spectator mode).
953
1121
  */
954
1122
  fly(enabled) {
955
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.PLAYER_ABILITIES, (0, play_js_1.buildPlayerAbilitiesServerboundPacket)(enabled));
1123
+ this.sendPlayPacket(this.playServerIds.abilities, (0, play_js_1.buildPlayerAbilitiesServerboundPacket)(enabled, this.options.version), 'abilities');
956
1124
  }
957
1125
  /**
958
1126
  * Respawn after death.
959
1127
  */
960
1128
  respawn() {
961
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.CLIENT_STATUS, (0, play_js_1.buildClientStatusPacket)(play_js_1.ClientStatusAction.PERFORM_RESPAWN));
1129
+ this.sendPlayPacket(this.playServerIds.clientCommand, (0, play_js_1.buildClientStatusPacket)(play_js_1.ClientStatusAction.PERFORM_RESPAWN), 'client_command');
962
1130
  this._isAlive = true;
963
1131
  }
964
1132
  /**
965
1133
  * Close the currently open container.
966
1134
  */
967
1135
  closeContainer(windowId = 0) {
968
- this.connection.sendPacket(play_js_1.PlayServerboundPackets.CLOSE_CONTAINER, (0, play_js_1.buildCloseContainerPacket)(windowId));
1136
+ this.sendPlayPacket(this.playServerIds.closeWindow, (0, play_js_1.buildCloseContainerPacket)(windowId), 'close_window');
969
1137
  }
970
1138
  /**
971
1139
  * Disconnect from the server.