UNPKG

minecraft-protocol

Version:

Parse and serialize minecraft packets, plus authentication and encryption.

75 lines (65 loc) 2.2 kB
'use strict' const [readVarInt, writeVarInt, sizeOfVarInt] = require('protodef').types.varint const Transform = require('readable-stream').Transform module.exports.createSplitter = function () { return new Splitter() } module.exports.createFramer = function () { return new Framer() } class Framer extends Transform { _transform (chunk, enc, cb) { const varIntSize = sizeOfVarInt(chunk.length) const buffer = Buffer.alloc(varIntSize + chunk.length) writeVarInt(chunk.length, buffer, 0) chunk.copy(buffer, varIntSize) this.push(buffer) return cb() } } const LEGACY_PING_PACKET_ID = 0xfe class Splitter extends Transform { constructor () { super() this.buffer = Buffer.alloc(0) this.recognizeLegacyPing = false } _transform (chunk, enc, cb) { this.buffer = Buffer.concat([this.buffer, chunk]) if (this.recognizeLegacyPing && this.buffer[0] === LEGACY_PING_PACKET_ID) { // legacy_server_list_ping packet follows a different protocol format // prefix the encoded varint packet id for the deserializer const header = Buffer.alloc(sizeOfVarInt(LEGACY_PING_PACKET_ID)) writeVarInt(LEGACY_PING_PACKET_ID, header, 0) let payload = this.buffer.slice(1) // remove 0xfe packet id if (payload.length === 0) payload = Buffer.from('\0') // TODO: update minecraft-data to recognize a lone 0xfe, https://github.com/PrismarineJS/minecraft-data/issues/95 this.push(Buffer.concat([header, payload])) return cb() } let offset = 0 let value, size let stop = false try { ({ value, size } = readVarInt(this.buffer, offset)) } catch (e) { if (!(e.partialReadError)) { throw e } else { stop = true } } if (!stop) { while (this.buffer.length >= offset + size + value) { try { this.push(this.buffer.slice(offset + size, offset + size + value)) offset += size + value; ({ value, size } = readVarInt(this.buffer, offset)) } catch (e) { if (e.partialReadError) { break } else { throw e } } } } this.buffer = this.buffer.slice(offset) return cb() } }