From 96ea26f964b290a6b2cecb239cc1b1129e0d18e9 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sun, 5 Jan 2025 17:03:18 -0500 Subject: [PATCH 1/5] 1.20.3, 1.20.5 support --- config/default-settings.json | 2 +- src/lib/plugins/chat.js | 44 ++++++++++++++++++++++++++++-------- src/lib/plugins/chest.js | 2 +- src/lib/plugins/header.js | 12 ++++++---- src/lib/plugins/login.js | 12 +++++++++- src/lib/plugins/logout.js | 5 ++-- src/lib/plugins/particle.js | 8 ++++++- src/lib/version.js | 2 +- 8 files changed, 66 insertions(+), 21 deletions(-) diff --git a/config/default-settings.json b/config/default-settings.json index a864fc2c..17e32826 100644 --- a/config/default-settings.json +++ b/config/default-settings.json @@ -25,5 +25,5 @@ }, "everybody-op": false, "max-entities":100, - "version": "1.20.2" + "version": "1.20.5" } diff --git a/src/lib/plugins/chat.js b/src/lib/plugins/chat.js index 4aacf0b7..4c1f16bf 100644 --- a/src/lib/plugins/chat.js +++ b/src/lib/plugins/chat.js @@ -1,9 +1,8 @@ +const nbt = require('prismarine-nbt') + module.exports.server = function (serv) { serv.broadcast = (message, { whitelist = serv.players, blacklist = [], system = false } = {}) => { if (whitelist.type === 'player') whitelist = [whitelist] - - if (typeof message === 'string') message = serv.parseClassic(message) - whitelist.filter(w => blacklist.indexOf(w) === -1).forEach(player => { if (!system) player.chat(message) else player.system(message) @@ -43,7 +42,8 @@ module.exports.server = function (serv) { reset: '&r' } - serv.parseClassic = (message) => { + // TODO: update and use prismarine-chat (doesn't yet support NBT chat components beyond decoding them) + serv._createJsonChat = (message) => { if (typeof message === 'object') return message const messageList = [] let text = '' @@ -117,6 +117,29 @@ module.exports.server = function (serv) { } } else return { text: '' } } + + serv._createChatComponent = (text) => { + if (serv.supportFeature('chatPacketsUseNbtComponents')) { + if (typeof text !== 'string') { + if (text.text) text = text.text + else { + serv.debug?.('Cannot yet convert JSON chat messages to NBT ; re-call in plaintext: ' + JSON.stringify(text)) + text = JSON.stringify(text) + } + } + const tag = nbt.comp({ + text: nbt.string(text) + }) + tag.toNetworkFormat = () => tag + return tag + } else { + if (typeof text === 'object') return text + const ret = serv._createJsonChat(text) + ret.toNetworkFormat = () => JSON.stringify(ret) + return ret + } + } + serv._createNetworkEncodedChatComponent = (val) => serv._createChatComponent(val).toNetworkFormat() } module.exports.player = function (player, serv) { @@ -157,9 +180,9 @@ module.exports.player = function (player, serv) { whitelist: serv.players, blacklist: [] }, ({ prefix, text, whitelist, blacklist }) => { - const obj = serv.parseClassic(prefix) + const obj = serv._createJsonChat(prefix) if (!obj.extra) obj.extra = [] - obj.extra.push(serv.parseClassic(text)) + obj.extra.push(serv._createJsonChat(text)) serv.broadcast(obj, { whitelist, blacklist @@ -172,7 +195,7 @@ module.exports.player = function (player, serv) { if (serv.supportFeature('signedChat')) { return player.system(message) } else { - const chatComponent = typeof message === 'string' ? serv.parseClassic(message) : message + const chatComponent = serv._createJsonChat(message) player._client.write('chat', { message: JSON.stringify(chatComponent), position: 0, @@ -188,16 +211,17 @@ module.exports.player = function (player, serv) { } player.system = message => { - const chatComponent = typeof message === 'string' ? serv.parseClassic(message) : message + const chatComponent = serv._createChatComponent(message) if (serv.supportFeature('signedChat')) { player._client.write('system_chat', { - content: JSON.stringify(chatComponent), + // 1.20.3+ writes NBT in chat packets ; below is stringified JSON chat components + content: chatComponent.toNetworkFormat(), type: 1, // chat isActionBar: false }) } else { player._client.write('chat', { - message: JSON.stringify(chatComponent), + message: chatComponent.toNetworkFormat(), position: 2, sender: '0' }) diff --git a/src/lib/plugins/chest.js b/src/lib/plugins/chest.js index 381269ec..9f75e325 100644 --- a/src/lib/plugins/chest.js +++ b/src/lib/plugins/chest.js @@ -51,7 +51,7 @@ module.exports.server = function (serv, { version }) { player._client.write('open_window', { windowId: player.windowId, inventoryType: invType, - windowTitle: JSON.stringify(title) + windowTitle: serv._createChatComponent(title).toNetworkFormat() }) // Sending container content player._client.write('window_items', { diff --git a/src/lib/plugins/header.js b/src/lib/plugins/header.js index e8624138..40525ad2 100644 --- a/src/lib/plugins/header.js +++ b/src/lib/plugins/header.js @@ -1,11 +1,15 @@ module.exports.player = function (player, serv, settings) { - player.playerlistUpdateText = (header, footer) => + player.playerlistUpdateText = function (header, footer) { player._client.write('playerlist_header', { - header: JSON.stringify(header), - footer: JSON.stringify(footer) + header: serv._createChatComponent(header).toNetworkFormat(), + footer: serv._createChatComponent(footer).toNetworkFormat() }) + } + + const header = settings['player-list-text'].header || '' + const footer = settings['player-list-text'].footer || '' if (settings['player-list-text']) { - player.playerlistUpdateText(settings['player-list-text'].header || { text: '' }, settings['player-list-text'].footer || { text: '' }) + player.playerlistUpdateText(header, footer) } } diff --git a/src/lib/plugins/login.js b/src/lib/plugins/login.js index 74a8f0c6..21b9a7e3 100644 --- a/src/lib/plugins/login.js +++ b/src/lib/plugins/login.js @@ -7,6 +7,12 @@ const plugins = require('./index') module.exports.server = function (serv, options) { serv._server.on('connection', (client) => { client.on('error', error => serv.emit('clientError', client, error)) + client.on('state', (now) => { + if (now === 'configuration') { + client.write('feature_flags', { features: ['minecraft:vanilla'] }) + client.write('select_known_packs', { packs: [] }) + } + }) }) serv._server.on('playerJoin', async (client) => { @@ -56,7 +62,10 @@ module.exports.player = async function (player, serv, settings) { const playerData = player._playerData = await playerDat.read(player.uuid, player.spawnPoint, settings.worldFolder) for (const key in playerData.player) player[key] = playerData.player[key] - serv.players.push(player) + if (!player.disconnected) { + // it's possible player gets kicked during login process ; don't add them to the server + serv.players.push(player) + } serv.uuidToPlayer[player.uuid] = player player.loadedChunks = {} } @@ -83,6 +92,7 @@ module.exports.player = async function (player, serv, settings) { // send init data so client will start rendering world player._client.write('login', { ...serv.registry.loginPacket, + enforcesSecureChat: serv._server.options.enforcesSecureChat, entityId: player.id, levelType: 'default', gameMode: player.gameMode, diff --git a/src/lib/plugins/logout.js b/src/lib/plugins/logout.js index ab431a1e..fd145d68 100644 --- a/src/lib/plugins/logout.js +++ b/src/lib/plugins/logout.js @@ -16,9 +16,9 @@ module.exports.player = function (player, serv, { worldFolder }) { }) player._client.on('end', async () => { - if (player && player.username) { + if (!player.disconnected) { player._unloadAllChunks(true /* becasuePlayerLeft */) - serv.broadcast(serv.color.yellow + player.username + ' left the game.') + if (player.username) serv.broadcast(serv.color.yellow + player.username + ' left the game.') serv._sendPlayerEventLeave(player) player.nearbyPlayers().forEach(otherPlayer => otherPlayer.despawnEntities([player])) delete serv.entities[player.id] @@ -28,6 +28,7 @@ module.exports.player = function (player, serv, { worldFolder }) { serv.players.splice(index, 1) } delete serv.uuidToPlayer[player.uuid] + player.disconnected = true } player.save() diff --git a/src/lib/plugins/particle.js b/src/lib/plugins/particle.js index dddef4f9..e6dee0e0 100644 --- a/src/lib/plugins/particle.js +++ b/src/lib/plugins/particle.js @@ -21,7 +21,13 @@ module.exports.server = function (serv) { offsetZ: size.z, particleData: 1.0, particles: count, - data: [] + amount: count, // 1.20.5+ + data: [], + velocityOffset: 0, // 1.20.5+ + particle: { + type: 'bubble', + data: null + } }, players.filter(p => blacklist.indexOf(p) === -1)) } diff --git a/src/lib/version.js b/src/lib/version.js index adea7668..a59e7f0b 100644 --- a/src/lib/version.js +++ b/src/lib/version.js @@ -1,4 +1,4 @@ -const testedVersions = ['1.8.8', '1.9.4', '1.10.2', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17.1', '1.18', '1.18.2', '1.19', '1.19.2', '1.19.3', '1.19.4', '1.20', '1.20.2'] +const testedVersions = ['1.8.8', '1.9.4', '1.10.2', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17.1', '1.18', '1.18.2', '1.19', '1.19.2', '1.19.3', '1.19.4', '1.20', '1.20.2', '1.20.3', '1.20.5'] module.exports = { testedVersions, latestSupportedVersion: testedVersions[testedVersions.length - 1], From 831766fe16137490f566979a3093464228e20713 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sun, 5 Jan 2025 17:39:02 -0500 Subject: [PATCH 2/5] update test --- src/lib/plugins/chat.js | 5 ++++- test/mineflayer.test.js | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lib/plugins/chat.js b/src/lib/plugins/chat.js index 4c1f16bf..9d64d53d 100644 --- a/src/lib/plugins/chat.js +++ b/src/lib/plugins/chat.js @@ -133,7 +133,10 @@ module.exports.server = function (serv) { tag.toNetworkFormat = () => tag return tag } else { - if (typeof text === 'object') return text + if (typeof text === 'object') { + text.toNetworkFormat = () => JSON.stringify(text) + return text + } const ret = serv._createJsonChat(text) ret.toNetworkFormat = () => JSON.stringify(ret) return ret diff --git a/test/mineflayer.test.js b/test/mineflayer.test.js index 212c5e17..b6fb2883 100644 --- a/test/mineflayer.test.js +++ b/test/mineflayer.test.js @@ -365,7 +365,8 @@ squid.testedVersions.forEach((testedVersion, i) => { function waitMessagePromise (message) { return new Promise((resolve) => { const listener = (msg) => { - if (msg.extra[0].text === message) { + const text = msg.extra?.[0].text ?? msg.text + if (text === message) { bot.removeListener('message', listener) resolve() } From 6cc2e1e3bfe40479d5ffc2e2226ea9a6c7ce48dd Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sun, 5 Jan 2025 18:16:55 -0500 Subject: [PATCH 3/5] 1.21 --- config/default-settings.json | 2 +- src/lib/version.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/default-settings.json b/config/default-settings.json index 17e32826..9949b822 100644 --- a/config/default-settings.json +++ b/config/default-settings.json @@ -25,5 +25,5 @@ }, "everybody-op": false, "max-entities":100, - "version": "1.20.5" + "version": "1.21.1" } diff --git a/src/lib/version.js b/src/lib/version.js index a59e7f0b..b3c6d6ee 100644 --- a/src/lib/version.js +++ b/src/lib/version.js @@ -1,4 +1,4 @@ -const testedVersions = ['1.8.8', '1.9.4', '1.10.2', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17.1', '1.18', '1.18.2', '1.19', '1.19.2', '1.19.3', '1.19.4', '1.20', '1.20.2', '1.20.3', '1.20.5'] +const testedVersions = ['1.8.8', '1.9.4', '1.10.2', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17.1', '1.18', '1.18.2', '1.19', '1.19.2', '1.19.3', '1.19.4', '1.20', '1.20.2', '1.20.3', '1.20.5', '1.21.1'] module.exports = { testedVersions, latestSupportedVersion: testedVersions[testedVersions.length - 1], From 7a564e4ff27e04e314f57ae7026b67f9c307a3aa Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sun, 5 Jan 2025 19:42:37 -0500 Subject: [PATCH 4/5] Update package.json to debug zlib --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1f635716..5adedada 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "exit-hook": "^2.2.1", "flatmap": "^0.0.3", "long": "^5.1.0", - "minecraft-protocol": "^1.44.0", + "minecraft-protocol": "extremeheat/node-minecraft-protocol#zlib-error-handling", "moment": "^2.10.6", "needle": "^2.5.0", "node-gzip": "^1.1.2", From 8560185f566a2db6404a3e1667e3e0282d15ce8a Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sun, 5 Jan 2025 22:18:39 -0500 Subject: [PATCH 5/5] Update package.json revert --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5adedada..cb82560e 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "exit-hook": "^2.2.1", "flatmap": "^0.0.3", "long": "^5.1.0", - "minecraft-protocol": "extremeheat/node-minecraft-protocol#zlib-error-handling", + "minecraft-protocol": "^1.50.0", "moment": "^2.10.6", "needle": "^2.5.0", "node-gzip": "^1.1.2",