diff --git a/src/client.js b/src/client.js index 5b63c295..74749698 100644 --- a/src/client.js +++ b/src/client.js @@ -30,6 +30,7 @@ class Client extends EventEmitter { this.hideErrors = hideErrors this.closeTimer = null const mcData = require('minecraft-data')(version) + this._supportFeature = mcData.supportFeature this.state = states.HANDSHAKING this._hasBundlePacket = mcData.supportFeature('hasBundlePacket') } diff --git a/src/createServer.js b/src/createServer.js index 4a56c0ad..50ae0a38 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -46,6 +46,7 @@ function createServer (options = {}) { server.onlineModeExceptions = Object.create(null) server.favicon = favicon server.options = options + server._supportFeature = mcData.supportFeature options.registryCodec = options.registryCodec || mcData.registryCodec || mcData.loginPacket?.dimensionCodec // The RSA keypair can take some time to generate diff --git a/src/server.js b/src/server.js index 99cfcbac..46df1042 100644 --- a/src/server.js +++ b/src/server.js @@ -4,6 +4,7 @@ const net = require('net') const EventEmitter = require('events').EventEmitter const Client = require('./client') const states = require('./states') +const nbt = require('prismarine-nbt') const { createSerializer } = require('./transforms/serializer') class Server extends EventEmitter { @@ -26,11 +27,14 @@ class Server extends EventEmitter { self.socketServer.on('connection', socket => { const client = new Client(true, this.version, this.customPackets, this.hideErrors) client._end = client.end - client.end = function end (endReason, fullReason = JSON.stringify({ text: endReason })) { + client.end = function end (endReason, fullReason) { if (client.state === states.PLAY) { + fullReason ||= this._supportFeature('chatPacketsUseNbtComponents') + ? nbt.comp({ text: nbt.string(endReason) }) + : JSON.stringify({ text: endReason }) client.write('kick_disconnect', { reason: fullReason }) } else if (client.state === states.LOGIN) { - client.write('disconnect', { reason: fullReason }) + client.write('disconnect', { reason: fullReason || endReason }) } client._end(endReason) } diff --git a/src/server/login.js b/src/server/login.js index 858b952c..bc578511 100644 --- a/src/server/login.js +++ b/src/server/login.js @@ -7,6 +7,7 @@ const chatPlugin = require('./chat') const { concat } = require('../transforms/binaryStream') const { mojangPublicKeyPem } = require('./constants') const debug = require('debug')('minecraft-protocol') +const nbt = require('prismarine-nbt') /** * @param {import('../index').Client} client @@ -196,7 +197,12 @@ module.exports = function (client, server, options) { client.settings = {} if (client.supportFeature('chainedChatWithHashing')) { // 1.19.1+ + const jsonMotd = JSON.stringify(server.motdMsg ?? { text: server.motd }) + const nbtMotd = nbt.comp({ text: nbt.string(server.motd) }) client.write('server_data', { + motd: client.supportFeature('chatPacketsUseNbtComponents') ? nbtMotd : jsonMotd, + icon: server.favicon, // b64 + iconBytes: server.favicon ? Buffer.from(server.favicon, 'base64') : undefined, previewsChat: options.enableChatPreview, // Note: in 1.20.5+ user must send this with `login` enforcesSecureChat: options.enforceSecureProfile diff --git a/test/serverTest.js b/test/serverTest.js index 5837e765..19760342 100644 --- a/test/serverTest.js +++ b/test/serverTest.js @@ -102,6 +102,7 @@ for (const supportedVersion of mc.supportedVersions) { describe('mc-server ' + supportedVersion + 'v', function () { this.timeout(5000) this.beforeEach(async function () { + console.log('🔻 Starting test', this.currentTest.title) PORT = await getPort() console.log(`Using port for tests: ${PORT}`) }) @@ -411,9 +412,12 @@ for (const supportedVersion of mc.supportedVersions) { }) }) function checkFinish () { - if (serverPlayerDisconnected && clientClosed && serverClosed) done() + if (serverPlayerDisconnected && clientClosed && serverClosed) { + console.log('Kick test is done') + callOnce(done) + } } - }) + }).retries(2) it('gives correct reason for kicking clients when shutting down', function (done) { const server = mc.createServer({ @@ -532,3 +536,10 @@ for (const supportedVersion of mc.supportedVersions) { }) }) } + +function callOnce (fn, ...args) { + console.log('Call Fn', fn.called) + if (fn.called) return + fn(...args) + fn.called = true +}