diff --git a/docs/API.md b/docs/API.md index 8aadf2e..8900876 100644 --- a/docs/API.md +++ b/docs/API.md @@ -23,6 +23,14 @@ Returns a `Client` instance and connects to the server. | authTitle | *optional* | The client ID to sign in as, defaults to Minecraft for Nintendo Switch. Set false to sign in through Azure. See prismarine-auth | | deviceType | *optional* | The device type to sign in as, defaults to "Nintendo". See prismarine-auth | +The following events are emitted by the client: +* 'status' - When the client's login sequence status has changed +* 'join' - When the client has joined the server after authenticating +* 'spawn' - When the client has spawned into the game world, as it is getting chunks +* 'kick' - The server has kicked the client +* 'close' - The server has closed the connection +* 'error' - An recoverable exception has happened. Not catching will throw an exception + ## be.createServer(options) : Server Returns a `Server` instance and starts listening for clients. All clients will be @@ -88,6 +96,9 @@ Order of server client event emissions: * 'join' - the client is ready to recieve game packets after successful server-client handshake/encryption * 'spawn' - emitted after the client lets the server know that it has successfully spawned + +'error' event is emitted when a catchable exception happens with a client (for example receiving a bad encrypted packet). + ## Client docs You can create a server as such: diff --git a/index.d.ts b/index.d.ts index 7c2360e..a6c71a0 100644 --- a/index.d.ts +++ b/index.d.ts @@ -92,6 +92,11 @@ declare module "bedrock-protocol" { * Close the connection, leave the server. */ close() + + /** + * Send a disconnect packet and close the connection + */ + disconnect() } /** diff --git a/src/client.js b/src/client.js index 3e4c9b6..5909667 100644 --- a/src/client.js +++ b/src/client.js @@ -141,6 +141,15 @@ class Client extends Connection { } } + disconnect (reason = 'Client leaving', hide = false) { + if (this.status === ClientStatus.Disconnected) return + this.write('disconnect', { + hide_disconnect_screen: hide, + message: reason + }) + this.close(reason) + } + close () { if (this.status !== ClientStatus.Disconnected) { this.emit('close') // Emit close once diff --git a/src/handshake/keyExchange.js b/src/handshake/keyExchange.js index a732dc8..8a90041 100644 --- a/src/handshake/keyExchange.js +++ b/src/handshake/keyExchange.js @@ -52,7 +52,7 @@ function KeyExchange (client, server, options) { debug('[encrypt] Starting serverbound encryption', token) const jwt = token?.token if (!jwt) { - throw Error('Server did not return a valid JWT, cannot start encryption!') + throw Error('Server did not return a valid JWT, cannot start encryption') } // No verification here, not needed diff --git a/src/rakWorker.js b/src/rakWorker.js index 06cd736..b67af0b 100644 --- a/src/rakWorker.js +++ b/src/rakWorker.js @@ -40,7 +40,7 @@ function main () { }) raknet.on('raw', (buffer, inetAddr) => { - console.log('Raw packet', buffer, inetAddr) + debug('Raw packet', buffer, inetAddr) }) } else if (evt.type === 'queueEncapsulated') { const sendPacket = new EncapsulatedPacket() diff --git a/src/server.js b/src/server.js index 3a7684e..3192889 100644 --- a/src/server.js +++ b/src/server.js @@ -54,7 +54,8 @@ class Server extends EventEmitter { onEncapsulated = (buffer, address) => { const client = this.clients[address] if (!client) { - throw new Error(`packet from unknown inet addr: ${address}`) + this.emit('error', new Error(`packet from unknown inet addr: ${address}`)) + return } client.handle(buffer) } diff --git a/src/serverPlayer.js b/src/serverPlayer.js index 52693b8..967a9f8 100644 --- a/src/serverPlayer.js +++ b/src/serverPlayer.js @@ -56,8 +56,7 @@ class Player extends Connection { try { var { key, userData, skinData } = this.decodeLoginJWT(authChain.chain, skinChain) // eslint-disable-line } catch (e) { - console.error(e) - console.debug(authChain.chain, skinChain) + debug(this.address, e) this.disconnect('Server authentication error') return } diff --git a/src/transforms/encryption.js b/src/transforms/encryption.js index c878c8d..31f9ae2 100644 --- a/src/transforms/encryption.js +++ b/src/transforms/encryption.js @@ -66,8 +66,10 @@ function createDecryptor (client, iv) { const computedCheckSum = computeCheckSum(packet, client.receiveCounter, client.secretKeyBytes) client.receiveCounter++ - if (Buffer.compare(checksum, computedCheckSum) !== 0) { - throw Error(`Checksum mismatch ${checksum.toString('hex')} != ${computedCheckSum.toString('hex')}`) + if (!checksum.equals(computedCheckSum)) { + client.emit('error', Error(`Checksum mismatch ${checksum.toString('hex')} != ${computedCheckSum.toString('hex')}`)) + client.disconnect('disconnectionScreen.badPacket') + return } Zlib.inflateRaw(chunk, { chunkSize: 1024 * 1024 * 2 }, (err, buffer) => {