diff --git a/src/minecraft/connection/javascript.ts b/src/minecraft/connection/javascript.ts index 7508133..a933724 100644 --- a/src/minecraft/connection/javascript.ts +++ b/src/minecraft/connection/javascript.ts @@ -22,7 +22,7 @@ import { ConnectionState } from '.' import { getLoginPacket, handleEncryptionRequest } from './shared' -import { readVarInt, writeVarInt, resolveHostname } from '../utils' +import { readVarInt, writeVarInt, resolveHostname, protocolMap } from '../utils' import packetIds from '../packets/ids' export declare interface JavaScriptServerConnection { @@ -153,17 +153,52 @@ const initiateJavaScriptConnection = async ( packet.id === 0x02 && conn.state === ConnectionState.LOGIN /* Login Success */ ) { + if (version >= protocolMap['1.20.2']) { + conn + .writePacket(0x03 /* Login Acknowledged */, Buffer.from([])) + .catch(err => conn.emit('error', err)) + conn.state = ConnectionState.CONFIGURATION + } else conn.state = ConnectionState.PLAY + } else if ( + packet.id === + packetIds.CLIENTBOUND_FINISH_CONFIGURATION(version) && + conn.state === ConnectionState.CONFIGURATION + ) { + conn + .writePacket(0x02 /* Finish Configuration */, Buffer.from([])) + .catch(err => conn.emit('error', err)) conn.state = ConnectionState.PLAY } else if ( - packet.id === packetIds.CLIENTBOUND_KEEP_ALIVE(version) + packet.id === + packetIds.CLIENTBOUND_START_CONFIGURATION(version) && + conn.state === ConnectionState.PLAY + ) { + const ackPacketId = + packetIds.SERVERBOUND_CONFIGURATION_ACKNOWLEDGED(version) + conn + .writePacket(ackPacketId ?? 0, Buffer.from([])) + .catch(err => conn.emit('error', err)) + conn.state = ConnectionState.CONFIGURATION + } else if ( + (packet.id === packetIds.CLIENTBOUND_KEEP_ALIVE_PLAY(version) && + conn.state === ConnectionState.PLAY) || + (packet.id === + packetIds.CLIENTBOUND_KEEP_ALIVE_CONFIGURATION(version) && + conn.state === ConnectionState.CONFIGURATION) ) { - const id = packetIds.SERVERBOUND_KEEP_ALIVE(version) + const id = + conn.state === ConnectionState.PLAY + ? packetIds.SERVERBOUND_KEEP_ALIVE_PLAY(version) + : packetIds.SERVERBOUND_KEEP_ALIVE_CONFIGURATION(version) conn .writePacket(id ?? 0, packet.data) .catch(err => conn.emit('error', err)) } else if ( - // Disconnect (login) or Disconnect (play) + // Disconnect (login), Disconnect (configuration) or Disconnect (play) (packet.id === 0x00 && conn.state === ConnectionState.LOGIN) || + (packet.id === + packetIds.CLIENTBOUND_DISCONNECT_CONFIGURATION(version) && + conn.state === ConnectionState.CONFIGURATION) || (packet.id === packetIds.CLIENTBOUND_DISCONNECT_PLAY(version) && conn.state === ConnectionState.PLAY) ) { diff --git a/src/minecraft/connection/native.ts b/src/minecraft/connection/native.ts index 178fbbf..83f43cc 100644 --- a/src/minecraft/connection/native.ts +++ b/src/minecraft/connection/native.ts @@ -11,7 +11,7 @@ import { } from '.' import { concatPacketData, type Packet } from '../packet' import { getLoginPacket, handleEncryptionRequest } from './shared' -import { readVarInt, writeVarInt, resolveHostname } from '../utils' +import { readVarInt, writeVarInt, resolveHostname, protocolMap } from '../utils' import packetIds from '../packets/ids' const { ConnectionModule } = NativeModules @@ -92,13 +92,29 @@ export class NativeServerConnection // Set Compression and Keep Alive are handled in native for now. // When modifying this code, apply the same changes to the JavaScript back-end. if ( - packet.id === 0x02 && - this.state === ConnectionState.LOGIN /* Login Success */ + packet.id === 0x02 /* Login Success */ && + this.state === ConnectionState.LOGIN ) { - this.state = ConnectionState.PLAY + this.state = + version >= protocolMap['1.20.2'] + ? ConnectionState.CONFIGURATION // Ack sent by native code + : ConnectionState.PLAY } else if ( - // Disconnect (login) or Disconnect (play) + packet.id === packetIds.CLIENTBOUND_FINISH_CONFIGURATION(version) && + this.state === ConnectionState.CONFIGURATION + ) { + this.state = ConnectionState.PLAY // Ack sent by native code + } else if ( + packet.id === packetIds.CLIENTBOUND_START_CONFIGURATION(version) && + this.state === ConnectionState.PLAY + ) { + this.state = ConnectionState.CONFIGURATION // Ack sent by native code + } else if ( + // Disconnect (login), Disconnect (configuration) or Disconnect (play) (packet.id === 0x00 && this.state === ConnectionState.LOGIN) || + (packet.id === + packetIds.CLIENTBOUND_DISCONNECT_CONFIGURATION(version) && + this.state === ConnectionState.CONFIGURATION) || (packet.id === packetIds.CLIENTBOUND_DISCONNECT_PLAY(version) && this.state === ConnectionState.PLAY) ) { diff --git a/src/minecraft/packets/ids.ts b/src/minecraft/packets/ids.ts index 1ff7660..b14625c 100644 --- a/src/minecraft/packets/ids.ts +++ b/src/minecraft/packets/ids.ts @@ -9,7 +9,9 @@ const generateIdFunction = } const packetIds = { + // =================== // Clientbound (login) + // =================== CLIENTBOUND_SET_COMPRESSION: generateIdFunction([ [protocolMap['1.16.4'], 0x03] ]), @@ -26,10 +28,30 @@ const packetIds = { [protocolMap['1.16.4'], 0x00] ]), + // =========================== + // Clientbound (configuration) + // =========================== + CLIENTBOUND_DISCONNECT_CONFIGURATION: generateIdFunction([ + [protocolMap['1.20.2'], 0x01] + ]), + CLIENTBOUND_FINISH_CONFIGURATION: generateIdFunction([ + [protocolMap['1.20.2'], 0x02] + ]), + CLIENTBOUND_KEEP_ALIVE_CONFIGURATION: generateIdFunction([ + [protocolMap['1.20.2'], 0x03] + ]), + + // =========================== + // Serverbound (configuration) + // =========================== + SERVERBOUND_KEEP_ALIVE_CONFIGURATION: generateIdFunction([ + [protocolMap['1.20.2'], 0x03] + ]), + // ================== // Clientbound (play) // ================== - CLIENTBOUND_KEEP_ALIVE: generateIdFunction([ + CLIENTBOUND_KEEP_ALIVE_PLAY: generateIdFunction([ [protocolMap['1.19.4'], 0x23], [protocolMap['1.19.3'], 0x1f], [protocolMap['1.19.1'], 0x20], @@ -110,11 +132,14 @@ const packetIds = { [protocolMap['1.19'], 0x2d], [protocolMap['1.17'], 0x30] ]), + CLIENTBOUND_START_CONFIGURATION: generateIdFunction([ + [protocolMap['1.20.2'], 0x65] + ]), // ================== // Serverbound (play) // ================== - SERVERBOUND_KEEP_ALIVE: generateIdFunction([ + SERVERBOUND_KEEP_ALIVE_PLAY: generateIdFunction([ [protocolMap['1.19.4'], 0x12], [protocolMap['1.19.3'], 0x11], [protocolMap['1.19.1'], 0x12], @@ -163,6 +188,9 @@ const packetIds = { [protocolMap['1.19.1'], 0x20], [protocolMap['1.19'], 0x1f], [protocolMap['1.17'], 0x1d] + ]), + SERVERBOUND_CONFIGURATION_ACKNOWLEDGED: generateIdFunction([ + [protocolMap['1.20.2'], 0x0b] ]) } diff --git a/src/minecraft/utils.ts b/src/minecraft/utils.ts index 50f7f10..dcd665d 100644 --- a/src/minecraft/utils.ts +++ b/src/minecraft/utils.ts @@ -17,6 +17,7 @@ export const protocolMap = { '1.19.4': 762, '1.20': 763, '1.20.1': 763, + '1.20.2': 764, latest: 763, auto: -1 }