From 42c687ae3787794603a1d00aaf62e2d3f6f65772 Mon Sep 17 00:00:00 2001 From: Romain Beaumont Date: Sun, 27 Oct 2024 21:31:59 +0100 Subject: [PATCH 1/4] support 1.21.3 --- .github/workflows/ci.yml | 1 + docs/README.md | 2 +- src/version.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93ef806..c5e526d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,5 +56,6 @@ jobs: distribution: 'adopt' - name: Install dependencies run: npm install + - run: cd node_modules && cd minecraft-data && mv minecraft-data minecraft-data-old && git clone -b pc1.21.3 https://github.com/GroobleDierne/minecraft-data.git --depth 1 && node bin/generate_data.js - name: Run tests run: npm run mochaTest -- -g ${{ matrix.mcVersion }}v diff --git a/docs/README.md b/docs/README.md index 9736002..f8cb78a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,7 +13,7 @@ Parse and serialize minecraft packets, plus authentication and encryption. * Supports Minecraft PC version 1.7.10, 1.8.8, 1.9 (15w40b, 1.9, 1.9.1-pre2, 1.9.2, 1.9.4), 1.10 (16w20a, 1.10-pre1, 1.10, 1.10.1, 1.10.2), 1.11 (16w35a, 1.11, 1.11.2), 1.12 (17w15a, 17w18b, 1.12-pre4, 1.12, 1.12.1, 1.12.2), and 1.13 (17w50a, 1.13, 1.13.1, 1.13.2-pre1, 1.13.2-pre2, 1.13.2), 1.14 (1.14, 1.14.1, 1.14.3, 1.14.4) - , 1.15 (1.15, 1.15.1, 1.15.2) and 1.16 (20w13b, 20w14a, 1.16-rc1, 1.16, 1.16.1, 1.16.2, 1.16.3, 1.16.4, 1.16.5), 1.17 (21w07a, 1.17, 1.17.1), 1.18 (1.18, 1.18.1 and 1.18.2), 1.19 (1.19, 1.19.1, 1.19.2, 1.19.3, 1.19.4, 1.20, 1.20.1, 1.20.2, 1.20.3, 1.20.4, 1.20.5, 1.20.6, 1.21.1) + , 1.15 (1.15, 1.15.1, 1.15.2) and 1.16 (20w13b, 20w14a, 1.16-rc1, 1.16, 1.16.1, 1.16.2, 1.16.3, 1.16.4, 1.16.5), 1.17 (21w07a, 1.17, 1.17.1), 1.18 (1.18, 1.18.1 and 1.18.2), 1.19 (1.19, 1.19.1, 1.19.2, 1.19.3, 1.19.4), 1.20 (1.20, 1.20.1, 1.20.2, 1.20.3, 1.20.4, 1.20.5, 1.20.6), 1.21 (1.21, 1.21.1, 1.21.3) * Parses all packets and emits events with packet fields as JavaScript objects. * Send a packet by supplying fields as a JavaScript object. diff --git a/src/version.js b/src/version.js index 327c242..29d71e7 100644 --- a/src/version.js +++ b/src/version.js @@ -2,5 +2,5 @@ module.exports = { defaultVersion: '1.21.1', - supportedVersions: ['1.7', '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.2', '1.19', '1.19.2', '1.19.3', '1.19.4', '1.20', '1.20.1', '1.20.2', '1.20.4', '1.20.6', '1.21.1'] + supportedVersions: ['1.7', '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.2', '1.19', '1.19.2', '1.19.3', '1.19.4', '1.20', '1.20.1', '1.20.2', '1.20.4', '1.20.6', '1.21.1', '1.21.3'] } From 11d8dd22a11fcc63bb8a92fd273e1a26c0bfa062 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Thu, 14 Nov 2024 07:38:19 +0000 Subject: [PATCH 2/4] Add bitflags, registryEntryHolder and registryEntryHolderSet types --- src/datatypes/compiler-minecraft.js | 149 +++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 1 deletion(-) diff --git a/src/datatypes/compiler-minecraft.js b/src/datatypes/compiler-minecraft.js index ba4db3e..099b3bb 100644 --- a/src/datatypes/compiler-minecraft.js +++ b/src/datatypes/compiler-minecraft.js @@ -1,3 +1,4 @@ +/* eslint-disable no-return-assign */ const UUID = require('uuid-1345') const minecraft = require('./minecraft') @@ -41,7 +42,7 @@ module.exports = { code += '}' return compiler.wrapCode(code) }], - arrayWithLengthOffset: ['parametrizable', (compiler, array) => { + arrayWithLengthOffset: ['parametrizable', (compiler, array) => { // TODO: remove let code = '' if (array.countType) { code += 'const { value: count, size: countSize } = ' + compiler.callType(array.countType) + '\n' @@ -61,6 +62,56 @@ module.exports = { code += '}\n' code += 'return { value: data, size }' return compiler.wrapCode(code) + }], + bitflags: ['parametrizable', (compiler, { type, flags, shift, big }) => { + let fstr = JSON.stringify(flags) + if (Array.isArray(flags)) { + fstr = '{' + for (const [k, v] of Object.entries(flags)) fstr += `"${v}": ${big ? (1n << BigInt(k)) : (1 << k)}` + (big ? 'n,' : ',') + fstr += '}' + } else if (shift) { + fstr = '{' + for (const key in flags) fstr += `"${key}": ${1 << flags[key]},` + fstr += '}' + } + return compiler.wrapCode(` + const { value: _value, size } = ${compiler.callType(type, 'offset')} + const value = { _value } + const flags = ${fstr} + for (const key in flags) { + value[key] = (_value & flags[key]) == flags[key] + } + return { value, size } + `.trim()) + }], + registryEntryHolder: ['parametrizable', (compiler, opts) => { + let code = '' + code += 'const { value: n, size: nSize } = ' + compiler.callType('varint') + '\n' + code += 'if (n !== 0) {' + code += ` return { value: { ${opts.baseName}: n - 1 }, size: nSize }` + code += '} else {' + code += ` const holder = ${compiler.callType(opts.otherwise.type)}` + code += ` return { value: { ${opts.otherwise.name}: holder.data }, size: nSize + holder.size }` + code += '}' + return compiler.wrapCode(code) + }], + registryEntryHolderSet: ['parametrizable', (compiler, opts) => { + let code = '' + code += 'const { value: n, size: nSize } = ' + compiler.callType('varint') + '\n' + code += 'if (n === 0) {' + code += ` const base = ${compiler.callType(opts.base.type)}` + code += ` return { value: { ${opts.base.type}: base.value }, size: base.size + nSize }` + code += '} else {' + code += ' const set = []' + code += ' let accSize = nSize' + code += ' for (let i = 0; i < n - 1; i++) {' + code += ` const entry = ${compiler.callType(opts.otherwise.type)}` + code += ' set.push(entry.value)' + code += ' accSize += entry.size' + code += ' }' + code += ` return { value: { ${opts.otherwise.name}: set }, size: accSize }` + code += '}' + return compiler.wrapCode(code) }] }, Write: { @@ -106,6 +157,54 @@ module.exports = { code += '}\n' code += 'return offset' return compiler.wrapCode(code) + }], + bitflags: ['parametrizable', (compiler, { type, flags, shift, big }) => { + let fstr = JSON.stringify(flags) + if (Array.isArray(flags)) { + fstr = '{' + for (const [k, v] of Object.entries(flags)) fstr += `"${v}": ${big ? (1n << BigInt(k)) : (1 << k)}` + (big ? 'n,' : ',') + fstr += '}' + } else if (shift) { + fstr = '{' + for (const key in flags) fstr += `"${key}": ${1 << flags[key]},` + fstr += '}' + } + return compiler.wrapCode(` + const flags = ${fstr} + let val = value._value ${big ? '|| 0n' : ''} + for (const key in flags) { + if (value[key]) val |= flags[key] + } + return (ctx.${type})(val, buffer, offset) + `.trim()) + }], + registryEntryHolder: ['parametrizable', (compiler, opts) => { + let code = '' + const baseName = `value.${opts.baseName}` + const otherwiseName = `value.${opts.otherwise.name}` + code += `if (${baseName}) {` + code += ' offset = ' + compiler.callType(`${baseName} + 1`, 'varint') + '\n' + code += `} else if (${otherwiseName}) {` + code += ' offset = ' + compiler.callType(`${otherwiseName}`, opts.otherwise.type) + '\n' + code += `} else throw new Error('registryEntryHolder type requires "${baseName}" or "${otherwiseName}" fields to be set')` + code += 'return offset' + return compiler.wrapCode(code) + }], + registryEntryHolderSet: ['parametrizable', (compiler, opts) => { + let code = '' + const baseName = `value.${opts.base.name}` + const otherwiseName = `value.${opts.otherwise.name}` + code += `if (${baseName}) {` + code += ' offset = ' + compiler.callType(0, 'varint') + '\n' + code += ' offset = ' + compiler.callType(`${baseName}`, opts.base.type) + '\n' + code += `} else if (${otherwiseName}) {` + code += ' offset = ' + compiler.callType(`${otherwiseName}.length + 1`, 'varint') + '\n' + code += ` for (let i = 0; i < ${otherwiseName}.length; i++) {` + code += ` offset = ${compiler.callType(opts.otherwise.type)}` + code += ' }' + code += `} else throw new Error('registryEntryHolder type requires "${baseName}" or "${otherwiseName}" fields to be set')` + code += 'return offset' + return compiler.wrapCode(code) }] }, SizeOf: { @@ -149,6 +248,54 @@ module.exports = { } code += 'return size' return compiler.wrapCode(code) + }], + bitflags: ['parametrizable', (compiler, { type, flags, shift, big }) => { + let fstr = JSON.stringify(flags) + if (Array.isArray(flags)) { + fstr = '{' + for (const [k, v] of Object.entries(flags)) fstr += `"${v}": ${big ? (1n << BigInt(k)) : (1 << k)}` + (big ? 'n,' : ',') + fstr += '}' + } else if (shift) { + fstr = '{' + for (const key in flags) fstr += `"${key}": ${1 << flags[key]},` + fstr += '}' + } + return compiler.wrapCode(` + const flags = ${fstr} + let val = value._value ${big ? '|| 0n' : ''} + for (const key in flags) { + if (value[key]) val |= flags[key] + } + return (ctx.${type})(val) + `.trim()) + }], + registryEntryHolder: ['parametrizable', (compiler, opts) => { + let code = 'let size = 0' + const baseName = `value.${opts.baseName}` + const otherwiseName = `value.${opts.otherwise.name}` + code += `if (${baseName}) {` + code += ' size += ' + compiler.callType(`${baseName} + 1`, 'varint') + '\n' + code += `} else if (${otherwiseName}) {` + code += ' size += ' + compiler.callType(`${otherwiseName}`, opts.otherwise.type) + '\n' + code += `} else throw new Error('registryEntryHolder type requires "${baseName}" or "${otherwiseName}" fields to be set')` + code += 'return size' + return compiler.wrapCode(code) + }], + registryEntryHolderSet: ['parametrizable', (compiler, opts) => { + let code = 'let size = 0' + const baseName = `value.${opts.base.name}` + const otherwiseName = `value.${opts.otherwise.name}` + code += `if (${baseName}) {` + code += ' size += ' + compiler.callType(0, 'varint') + '\n' + code += ' size += ' + compiler.callType(`${baseName}`, opts.base.type) + '\n' + code += `} else if (${otherwiseName}) {` + code += ' size += ' + compiler.callType(`${otherwiseName}.length + 1`, 'varint') + '\n' + code += ` for (let i = 0; i < ${otherwiseName}.length; i++) {` + code += ` size += ${compiler.callType(opts.otherwise.type)}` + code += ' }' + code += `} else throw new Error('registryEntryHolder type requires "${baseName}" or "${otherwiseName}" fields to be set')` + code += 'return size' + return compiler.wrapCode(code) }] } } From fc763bb44c5e227b25df8ed54d9e49062cc4b246 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Thu, 14 Nov 2024 23:56:58 +0000 Subject: [PATCH 3/4] Fix spacing in compiler types --- src/datatypes/compiler-minecraft.js | 140 +++++++++++++++------------- 1 file changed, 75 insertions(+), 65 deletions(-) diff --git a/src/datatypes/compiler-minecraft.js b/src/datatypes/compiler-minecraft.js index 099b3bb..5cccdb4 100644 --- a/src/datatypes/compiler-minecraft.js +++ b/src/datatypes/compiler-minecraft.js @@ -85,33 +85,33 @@ module.exports = { `.trim()) }], registryEntryHolder: ['parametrizable', (compiler, opts) => { - let code = '' - code += 'const { value: n, size: nSize } = ' + compiler.callType('varint') + '\n' - code += 'if (n !== 0) {' - code += ` return { value: { ${opts.baseName}: n - 1 }, size: nSize }` - code += '} else {' - code += ` const holder = ${compiler.callType(opts.otherwise.type)}` - code += ` return { value: { ${opts.otherwise.name}: holder.data }, size: nSize + holder.size }` - code += '}' - return compiler.wrapCode(code) + return compiler.wrapCode(` +const { value: n, size: nSize } = ${compiler.callType('varint')} +if (n !== 0) { + return { value: { ${opts.baseName}: n - 1 }, size: nSize } +} else { + const holder = ${compiler.callType(opts.otherwise.type)} + return { value: { ${opts.otherwise.name}: holder.data }, size: nSize + holder.size } +} + `.trim()) }], registryEntryHolderSet: ['parametrizable', (compiler, opts) => { - let code = '' - code += 'const { value: n, size: nSize } = ' + compiler.callType('varint') + '\n' - code += 'if (n === 0) {' - code += ` const base = ${compiler.callType(opts.base.type)}` - code += ` return { value: { ${opts.base.type}: base.value }, size: base.size + nSize }` - code += '} else {' - code += ' const set = []' - code += ' let accSize = nSize' - code += ' for (let i = 0; i < n - 1; i++) {' - code += ` const entry = ${compiler.callType(opts.otherwise.type)}` - code += ' set.push(entry.value)' - code += ' accSize += entry.size' - code += ' }' - code += ` return { value: { ${opts.otherwise.name}: set }, size: accSize }` - code += '}' - return compiler.wrapCode(code) + return compiler.wrapCode(` + const { value: n, size: nSize } = ${compiler.callType('varint')} + if (n === 0) { + const base = ${compiler.callType(opts.base.type)} + return { value: { ${opts.base.type}: base.value }, size: base.size + nSize } + } else { + const set = [] + let accSize = nSize + for (let i = 0; i < n - 1; i++) { + const entry = ${compiler.callType(opts.otherwise.type)} + set.push(entry.value) + accSize += entry.size + } + return { value: { ${opts.otherwise.name}: set }, size: accSize } + } + `.trim()) }] }, Write: { @@ -179,32 +179,36 @@ module.exports = { `.trim()) }], registryEntryHolder: ['parametrizable', (compiler, opts) => { - let code = '' const baseName = `value.${opts.baseName}` const otherwiseName = `value.${opts.otherwise.name}` - code += `if (${baseName}) {` - code += ' offset = ' + compiler.callType(`${baseName} + 1`, 'varint') + '\n' - code += `} else if (${otherwiseName}) {` - code += ' offset = ' + compiler.callType(`${otherwiseName}`, opts.otherwise.type) + '\n' - code += `} else throw new Error('registryEntryHolder type requires "${baseName}" or "${otherwiseName}" fields to be set')` - code += 'return offset' - return compiler.wrapCode(code) + return compiler.wrapCode(` +if (${baseName}) { + offset = ${compiler.callType(`${baseName} + 1`, 'varint')} +} else if (${otherwiseName}) { + offset = ${compiler.callType(`${otherwiseName}`, opts.otherwise.type)} +} else { + throw new Error('registryEntryHolder type requires "${baseName}" or "${otherwiseName}" fields to be set') +} +return offset + `.trim()) }], registryEntryHolderSet: ['parametrizable', (compiler, opts) => { - let code = '' const baseName = `value.${opts.base.name}` const otherwiseName = `value.${opts.otherwise.name}` - code += `if (${baseName}) {` - code += ' offset = ' + compiler.callType(0, 'varint') + '\n' - code += ' offset = ' + compiler.callType(`${baseName}`, opts.base.type) + '\n' - code += `} else if (${otherwiseName}) {` - code += ' offset = ' + compiler.callType(`${otherwiseName}.length + 1`, 'varint') + '\n' - code += ` for (let i = 0; i < ${otherwiseName}.length; i++) {` - code += ` offset = ${compiler.callType(opts.otherwise.type)}` - code += ' }' - code += `} else throw new Error('registryEntryHolder type requires "${baseName}" or "${otherwiseName}" fields to be set')` - code += 'return offset' - return compiler.wrapCode(code) + return compiler.wrapCode(` +if (${baseName}) { + offset = ${compiler.callType(0, 'varint')} + offset = ${compiler.callType(`${baseName}`, opts.base.type)} +} else if (${otherwiseName}) { + offset = ${compiler.callType(`${otherwiseName}.length + 1`, 'varint')} + for (let i = 0; i < ${otherwiseName}.length; i++) { + offset = ${compiler.callType(opts.otherwise.type)} + } +} else { + throw new Error('registryEntryHolder type requires "${baseName}" or "${otherwiseName}" fields to be set') +} +return offset + `.trim()) }] }, SizeOf: { @@ -270,32 +274,38 @@ module.exports = { `.trim()) }], registryEntryHolder: ['parametrizable', (compiler, opts) => { - let code = 'let size = 0' const baseName = `value.${opts.baseName}` const otherwiseName = `value.${opts.otherwise.name}` - code += `if (${baseName}) {` - code += ' size += ' + compiler.callType(`${baseName} + 1`, 'varint') + '\n' - code += `} else if (${otherwiseName}) {` - code += ' size += ' + compiler.callType(`${otherwiseName}`, opts.otherwise.type) + '\n' - code += `} else throw new Error('registryEntryHolder type requires "${baseName}" or "${otherwiseName}" fields to be set')` - code += 'return size' - return compiler.wrapCode(code) + return compiler.wrapCode(` +let size = 0 +if (${baseName}) { + size += ${compiler.callType(`${baseName} + 1`, 'varint')} +} else if (${otherwiseName}) { + size += ${compiler.callType(`${otherwiseName}`, opts.otherwise.type)} +} else { + throw new Error('registryEntryHolder type requires "${baseName}" or "${otherwiseName}" fields to be set') +} +return size + `.trim()) }], registryEntryHolderSet: ['parametrizable', (compiler, opts) => { - let code = 'let size = 0' const baseName = `value.${opts.base.name}` const otherwiseName = `value.${opts.otherwise.name}` - code += `if (${baseName}) {` - code += ' size += ' + compiler.callType(0, 'varint') + '\n' - code += ' size += ' + compiler.callType(`${baseName}`, opts.base.type) + '\n' - code += `} else if (${otherwiseName}) {` - code += ' size += ' + compiler.callType(`${otherwiseName}.length + 1`, 'varint') + '\n' - code += ` for (let i = 0; i < ${otherwiseName}.length; i++) {` - code += ` size += ${compiler.callType(opts.otherwise.type)}` - code += ' }' - code += `} else throw new Error('registryEntryHolder type requires "${baseName}" or "${otherwiseName}" fields to be set')` - code += 'return size' - return compiler.wrapCode(code) + return compiler.wrapCode(` +let size = 0 +if (${baseName}) { + size += ${compiler.callType(0, 'varint')} + size += ${compiler.callType(`${baseName}`, opts.base.type)} +} else if (${otherwiseName}) { + size += ${compiler.callType(`${otherwiseName}.length + 1`, 'varint')} + for (let i = 0; i < ${otherwiseName}.length; i++) { + size += ${compiler.callType(opts.otherwise.type)} + } +} else { + throw new Error('registryEntryHolder type requires "${baseName}" or "${otherwiseName}" fields to be set') +} +return size + `.trim()) }] } } From 60ba34ddedc35768d1c7aded928d1df70f253823 Mon Sep 17 00:00:00 2001 From: extremeheat Date: Sat, 16 Nov 2024 20:50:50 -0500 Subject: [PATCH 4/4] Update compiler-minecraft.js --- src/datatypes/compiler-minecraft.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/datatypes/compiler-minecraft.js b/src/datatypes/compiler-minecraft.js index 5cccdb4..ec812ff 100644 --- a/src/datatypes/compiler-minecraft.js +++ b/src/datatypes/compiler-minecraft.js @@ -100,7 +100,7 @@ if (n !== 0) { const { value: n, size: nSize } = ${compiler.callType('varint')} if (n === 0) { const base = ${compiler.callType(opts.base.type)} - return { value: { ${opts.base.type}: base.value }, size: base.size + nSize } + return { value: { ${opts.base.name}: base.value }, size: base.size + nSize } } else { const set = [] let accSize = nSize