Compare commits

...
Sign in to create a new pull request.

25 commits

Author SHA1 Message Date
rom1504bot
fa6acab0f3
Release 3.49.0 (#650)
* Release 3.49.0

* Update HISTORY.md

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: extremeheat <extreme@protonmail.ch>
2025-10-01 21:21:34 -04:00
extremeheat
b48518a6e7
1.21.111 (#649) 2025-10-01 20:52:10 -04:00
thejfkvis
407756b938
Skin Data Changes (#647) 2025-10-01 20:51:53 -04:00
rom1504bot
0b9c49fedc
Release 3.48.1 (#638)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-08-10 02:31:46 -04:00
TSL534
6b1474d2c6
Update login client skinData (#635)
* Update for the Skin Data in the Login system

* Fix for CI

* CI Fix2

* Fixed comments again for CI

* Update login.js

---------

Co-authored-by: extremeheat <extreme@protonmail.ch>
2025-08-10 01:47:18 -04:00
rom1504bot
6c659feb5d
Release 3.48.0 (#633)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-08-06 14:16:25 -04:00
extremeheat
06fb3de3a0
1.21.100 (#632)
* Update options.js

* Update README.md
2025-08-06 14:05:20 -04:00
rom1504bot
6f06a8996e
Release 3.47.0 (#625)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-07-04 16:48:07 -04:00
Tamás Papp
14daa2d95a
1.21.93 support (#623) 2025-07-04 16:47:12 -04:00
rom1504bot
80751d58a7
Release 3.46.0 (#618)
* Release 3.46.0

* Update HISTORY.md

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: extremeheat <extreme@protonmail.ch>
2025-06-18 21:51:20 -04:00
extremeheat
c66cdd3d62
1.21.90 (#617)
* 1.21.90

* Update README.md
2025-06-18 21:31:21 -04:00
extremeheat
e503c47c79
Start work for 1.21.90 (#616)
* 1.21.90

* update

* remove 1.21.90 in ci
2025-06-18 20:14:38 -04:00
rom1504bot
29ba39343a
Release 3.45.0 (#603)
* Release 3.45.0

* Update HISTORY.md

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: extremeheat <extreme@protonmail.ch>
2025-05-08 20:19:26 -04:00
extremeheat
e71fd513dd
1.21.80 (#602) 2025-05-08 19:51:20 -04:00
LunaryNet2
b6b0bcdd70
Update index.d.ts (#596) 2025-03-31 20:13:27 -04:00
rom1504bot
d88309507d
Release 3.44.0 (#595)
* Release 3.44.0

* Update HISTORY.md

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: extremeheat <extreme@protonmail.ch>
2025-03-26 00:20:38 -04:00
extremeheat
065f41db8c
1.21.70 (#594)
* Update options.js

* Update README.md
2025-03-25 23:38:56 -04:00
rom1504bot
9f11f21991
Release 3.43.1 (#592)
* Release 3.43.1

* Update HISTORY.md

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: extremeheat <extreme@protonmail.ch>
2025-03-19 14:03:47 -04:00
EntifiedOptics
47f342ca95
Fix server not correctly removing clients (#588)
* Properly remove connection from clients list

* Changed misname in onCloseConnection

* Update server.js fix

---------

Co-authored-by: JSbETms <137791538+JSbETms@users.noreply.github.com>
Co-authored-by: extremeheat <extreme@protonmail.ch>
2025-03-18 17:01:49 -04:00
extremeheat
328785d8af
Quicken tests 2025-02-13 15:36:33 -05:00
rom1504bot
d4a9faf153
Release 3.43.0 (#577)
* Release 3.43.0

* Update HISTORY.md

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: extremeheat <extreme@protonmail.ch>
2025-02-11 22:08:50 -05:00
Tamás Papp
eeb5e47e35
1.21.60 support (#570)
* Add support for ItemRegistryPacket (for shield item ID)

* simplify

* lint

* internal test

* update start_game handling

* test: capture events rejections

---------

Co-authored-by: extremeheat <extreme@protonmail.ch>
2025-02-11 21:42:31 -05:00
Slauh!
2d7d32dfd1
Update API.md fix chat message handling (#575) 2025-02-06 13:54:38 -05:00
Max
0ed8e32be8
Fix version feature handling (#572)
* Replace unsupported version with next supported version

* add validity check

---------

Co-authored-by: extremeheat <extreme@protonmail.ch>
2025-01-31 14:02:04 -05:00
Romain Beaumont
75fa085e86
node 22 (#568) 2025-01-26 23:06:36 +01:00
18 changed files with 108 additions and 44 deletions

View file

@ -17,7 +17,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest] os: [ubuntu-latest, windows-latest]
node-version: [18.x] node-version: [22.x]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
timeout-minutes: 14 timeout-minutes: 14
steps: steps:

View file

@ -14,7 +14,7 @@ jobs:
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@master uses: actions/setup-node@master
with: with:
node-version: 18.0.0 node-version: 22.0.0
- name: Install Github Actions helper - name: Install Github Actions helper
run: npm i gh-helpers run: npm i gh-helpers
# The env vars contain the relevant trigger information, so we don't need to pass it # The env vars contain the relevant trigger information, so we don't need to pass it

View file

@ -1,3 +1,32 @@
## 3.49.0
* [1.21.111 (#649)](https://github.com/PrismarineJS/bedrock-protocol/commit/b48518a6e79e72101fe7136433cbd6277339fc5c) (thanks @Slauh)
* [Skin Data Changes (#647)](https://github.com/PrismarineJS/bedrock-protocol/commit/407756b93880cdda4fdbff194fc4163ceedf4e82) (thanks @thejfkvis)
## 3.48.1
* [Update login client skinData (#635)](https://github.com/PrismarineJS/bedrock-protocol/commit/6b1474d2c6f93b47dee9d4816de59579f82ed5a9) (thanks @TSL534)
## 3.48.0
* [1.21.100 (#632)](https://github.com/PrismarineJS/bedrock-protocol/commit/06fb3de3a0023d03201dbcee7e9178c269462766) (thanks @extremeheat)
## 3.47.0
* [1.21.93 support (#623)](https://github.com/PrismarineJS/bedrock-protocol/commit/14daa2d95aac90ffcc7b42d625e270020ec2f162) (thanks @CreeperG16)
## 3.46.0
* [1.21.90 support (#617)](https://github.com/PrismarineJS/bedrock-protocol/commit/c66cdd3d62d2fa9c581693d8c70d7b41f355b63e) (thanks @CreeperG16)
## 3.45.0
* [1.21.80 (#602)](https://github.com/PrismarineJS/bedrock-protocol/commit/e71fd513ddbd432983f221980080b61e11576965) (thanks @extremeheat)
## 3.44.0
* [1.21.70 (#594)](https://github.com/PrismarineJS/bedrock-protocol/commit/065f41db8cfc8cbd8106bd9e376c899ec25f3f77) (thanks @CreeperG16)
## 3.43.1
* [Fix server not correctly removing clients (#588)](https://github.com/PrismarineJS/bedrock-protocol/commit/47f342ca958ba87a7719783bd5c855cebdd4aa65) (thanks @EntifiedOptics)
## 3.43.0
* [1.21.60 support (#570)](https://github.com/PrismarineJS/bedrock-protocol/commit/eeb5e47e35f31cc571a9a8a491f5a89b27e637f1) (thanks @CreeperG16)
* [Fix version feature handling (#572)](https://github.com/PrismarineJS/bedrock-protocol/commit/0ed8e32be85f05926cd97d5f0317ed004ae5eefa) (thanks @ItsMax123)
## 3.42.3 ## 3.42.3
* [Fix Server `maxPlayers` option (#565)](https://github.com/PrismarineJS/bedrock-protocol/commit/38dc5a256105a44786d5455570d5a130e64ef561) (thanks @extremeheat) * [Fix Server `maxPlayers` option (#565)](https://github.com/PrismarineJS/bedrock-protocol/commit/38dc5a256105a44786d5455570d5a130e64ef561) (thanks @extremeheat)

View file

@ -11,7 +11,7 @@ Minecraft Bedrock Edition (aka MCPE) protocol library, supporting authentication
## Features ## Features
- Supports Minecraft Bedrock version 1.16.201, 1.16.210, 1.16.220, 1.17.0, 1.17.10, 1.17.30, 1.17.40, 1.18.0, 1.18.11, 1.18.30, 1.19.1, 1.19.10, 1.19.20, 1.19.21, 1.19.30, 1.19.40, 1.19.41, 1.19.50, 1.19.60, 1.19.62, 1.19.63, 1.19.70, 1.19.80, 1.20.0, 1.20.10, 1.20.30, 1.20.40, 1.20.50, 1.20.61, 1.20.71, 1.20.80, 1.21.0, 1.21.2, 1.21.21, 1.21.30, 1.21.42, 1.21.50 - Supports Minecraft Bedrock version 1.16.201, 1.16.210, 1.16.220, 1.17.0, 1.17.10, 1.17.30, 1.17.40, 1.18.0, 1.18.11, 1.18.30, 1.19.1, 1.19.10, 1.19.20, 1.19.21, 1.19.30, 1.19.40, 1.19.41, 1.19.50, 1.19.60, 1.19.62, 1.19.63, 1.19.70, 1.19.80, 1.20.0, 1.20.10, 1.20.30, 1.20.40, 1.20.50, 1.20.61, 1.20.71, 1.20.80, 1.21.0, 1.21.2, 1.21.21, 1.21.30, 1.21.42, 1.21.50, 1.21.60, 1.21.70, 1.21.80, 1.21.90, 1.21.93, 1.21.100, 1.21.111
- Parse and serialize packets as JavaScript objects - Parse and serialize packets as JavaScript objects
- Automatically respond to keep-alive packets - Automatically respond to keep-alive packets
- [Proxy and mitm connections](docs/API.md#proxy-docs) - [Proxy and mitm connections](docs/API.md#proxy-docs)

View file

@ -142,7 +142,7 @@ client.on('text', (packet) => {
// names and as explained in the "Protocol doc" section below, fields are all case sensitive! // names and as explained in the "Protocol doc" section below, fields are all case sensitive!
client.on('add_player', (packet) => { client.on('add_player', (packet) => {
client.queue('text', { client.queue('text', {
type: 'chat', needs_translation: false, source_name: client.username, xuid: '', platform_chat_id: '', type: 'chat', needs_translation: false, source_name: client.username, xuid: '', platform_chat_id: '', filtered_message: '',
message: `Hey, ${packet.username} just joined!` message: `Hey, ${packet.username} just joined!`
}) })
}) })

2
index.d.ts vendored
View file

@ -3,7 +3,7 @@ import { Realm } from 'prismarine-realms'
import { ServerDeviceCodeResponse } from 'prismarine-auth' import { ServerDeviceCodeResponse } from 'prismarine-auth'
declare module 'bedrock-protocol' { declare module 'bedrock-protocol' {
type Version = '1.21.42' | '1.21.30' | '1.21.2' | '1.21.0' | '1.20.80' | '1.20.71' | '1.20.61' | '1.20.50' | '1.20.40' | '1.20.30' | '1.20.10' | '1.20.0' | '1.19.80' | '1.19.70' | '1.19.63' | '1.19.62' | '1.19.60' | '1.19.51' | '1.19.50' | '1.19.41' | '1.19.40' | '1.19.31' | '1.19.30' | '1.19.22' | '1.19.21' | '1.19.20' | '1.19.11' | '1.19.10' | '1.19.2' | '1.19.1' | '1.18.31' | '1.18.30' | '1.18.12' | '1.18.11' | '1.18.10' | '1.18.2' | '1.18.1' | '1.18.0' | '1.17.41' | '1.17.40' | '1.17.34' | '1.17.30' | '1.17.11' | '1.17.10' | '1.17.0' | '1.16.220' | '1.16.210' | '1.16.201' type Version = '1.21.93' | '1.21.90' | '1.21.80' | '1.21.70' | '1.21.60' | '1.21.50' | '1.21.42' | '1.21.30' | '1.21.2' | '1.21.0' | '1.20.80' | '1.20.71' | '1.20.61' | '1.20.50' | '1.20.40' | '1.20.30' | '1.20.10' | '1.20.0' | '1.19.80' | '1.19.70' | '1.19.63' | '1.19.62' | '1.19.60' | '1.19.51' | '1.19.50' | '1.19.41' | '1.19.40' | '1.19.31' | '1.19.30' | '1.19.22' | '1.19.21' | '1.19.20' | '1.19.11' | '1.19.10' | '1.19.2' | '1.19.1' | '1.18.31' | '1.18.30' | '1.18.12' | '1.18.11' | '1.18.10' | '1.18.2' | '1.18.1' | '1.18.0' | '1.17.41' | '1.17.40' | '1.17.34' | '1.17.30' | '1.17.11' | '1.17.10' | '1.17.0' | '1.16.220' | '1.16.210' | '1.16.201'
export interface Options { export interface Options {
// The string version to start the client or server as // The string version to start the client or server as

View file

@ -1,6 +1,6 @@
{ {
"name": "bedrock-protocol", "name": "bedrock-protocol",
"version": "3.42.3", "version": "3.49.0",
"description": "Minecraft Bedrock Edition protocol library", "description": "Minecraft Bedrock Edition protocol library",
"main": "index.js", "main": "index.js",
"types": "index.d.ts", "types": "index.d.ts",

View file

@ -61,7 +61,9 @@ class Client extends Connection {
try { try {
const mcData = require('minecraft-data')('bedrock_' + this.options.version) const mcData = require('minecraft-data')('bedrock_' + this.options.version)
this.features = { this.features = {
compressorInHeader: mcData.supportFeature('compressorInPacketHeader') compressorInHeader: mcData.supportFeature('compressorInPacketHeader'),
itemRegistryPacket: mcData.supportFeature('itemRegistryPacket'),
newLoginIdentityFields: mcData.supportFeature('newLoginIdentityFields')
} }
} catch (e) { } catch (e) {
throw new Error(`Unsupported version: '${this.options.version}', no data available`) throw new Error(`Unsupported version: '${this.options.version}', no data available`)
@ -145,9 +147,18 @@ class Client extends Connection {
...this.accessToken // Mojang + Xbox JWT from auth ...this.accessToken // Mojang + Xbox JWT from auth
] ]
const encodedChain = JSON.stringify({ chain }) let encodedChain
if (this.features.newLoginIdentityFields) { // 1.21.90+
debug('Auth chain', chain) encodedChain = JSON.stringify({
Certificate: JSON.stringify({ chain }),
// 0 = normal, 1 = ss, 2 = offline
AuthenticationType: this.options.offline ? 2 : 0,
Token: ''
})
} else {
encodedChain = JSON.stringify({ chain })
}
debug('Auth chain', encodedChain)
this.write('login', { this.write('login', {
protocol_version: this.options.protocolVersion, protocol_version: this.options.protocolVersion,
@ -241,7 +252,9 @@ class Client extends Connection {
break break
case 'start_game': case 'start_game':
this.startGameData = pakData.params this.startGameData = pakData.params
this.startGameData.itemstates.forEach(state => { // fallsthrough
case 'item_registry': // 1.21.60+ send itemstates in item_registry packet
pakData.params.itemstates?.forEach(state => {
if (state.name === 'minecraft:shield') { if (state.name === 'minecraft:shield') {
this.serializer.proto.setVariable('ShieldItemID', state.runtime_id) this.serializer.proto.setVariable('ShieldItemID', state.runtime_id)
this.deserializer.proto.setVariable('ShieldItemID', state.runtime_id) this.deserializer.proto.setVariable('ShieldItemID', state.runtime_id)

View file

@ -28,18 +28,22 @@ class Connection extends EventEmitter {
} }
versionLessThan (version) { versionLessThan (version) {
if (typeof version === 'string' && !Versions[version]) throw Error('Unknown version: ' + version)
return this.options.protocolVersion < (typeof version === 'string' ? Versions[version] : version) return this.options.protocolVersion < (typeof version === 'string' ? Versions[version] : version)
} }
versionGreaterThan (version) { versionGreaterThan (version) {
if (typeof version === 'string' && !Versions[version]) throw Error('Unknown version: ' + version)
return this.options.protocolVersion > (typeof version === 'string' ? Versions[version] : version) return this.options.protocolVersion > (typeof version === 'string' ? Versions[version] : version)
} }
versionGreaterThanOrEqualTo (version) { versionGreaterThanOrEqualTo (version) {
if (typeof version === 'string' && !Versions[version]) throw Error('Unknown version: ' + version)
return this.options.protocolVersion >= (typeof version === 'string' ? Versions[version] : version) return this.options.protocolVersion >= (typeof version === 'string' ? Versions[version] : version)
} }
versionLessThanOrEqualTo (version) { versionLessThanOrEqualTo (version) {
if (typeof version === 'string' && !Versions[version]) throw Error('Unknown version: ' + version)
return this.options.protocolVersion <= (typeof version === 'string' ? Versions[version] : version) return this.options.protocolVersion <= (typeof version === 'string' ? Versions[version] : version)
} }
@ -66,9 +70,17 @@ class Connection extends EventEmitter {
} }
} }
_processOutbound (name, params) {
if (name === 'item_registry') {
this.updateItemPalette(params.itemstates)
} else if (name === 'start_game' && params.itemstates) {
this.updateItemPalette(params.itemstates)
}
}
write (name, params) { write (name, params) {
this.outLog?.(name, params) this.outLog?.(name, params)
if (name === 'start_game') this.updateItemPalette(params.itemstates) this._processOutbound(name, params)
const batch = new Framer(this) const batch = new Framer(this)
const packet = this.serializer.createPacketBuffer({ name, params }) const packet = this.serializer.createPacketBuffer({ name, params })
batch.addEncodedPacket(packet) batch.addEncodedPacket(packet)
@ -82,7 +94,7 @@ class Connection extends EventEmitter {
queue (name, params) { queue (name, params) {
this.outLog?.('Q <- ', name, params) this.outLog?.('Q <- ', name, params)
if (name === 'start_game') this.updateItemPalette(params.itemstates) this._processOutbound(name, params)
const packet = this.serializer.createPacketBuffer({ name, params }) const packet = this.serializer.createPacketBuffer({ name, params })
if (name === 'level_chunk') { if (name === 'level_chunk') {
// Skip queue, send ASAP // Skip queue, send ASAP

View file

@ -36,7 +36,6 @@ module.exports = (client, server, options) => {
client.createClientUserChain = (privateKey) => { client.createClientUserChain = (privateKey) => {
let payload = { let payload = {
...skinData, ...skinData,
SkinGeometryDataEngineVersion: client.versionGreaterThanOrEqualTo('1.17.30') ? '' : undefined,
ClientRandomId: Date.now(), ClientRandomId: Date.now(),
CurrentInputMode: 1, CurrentInputMode: 1,
@ -47,19 +46,20 @@ module.exports = (client, server, options) => {
GameVersion: options.version || '1.16.201', GameVersion: options.version || '1.16.201',
GuiScale: -1, GuiScale: -1,
LanguageCode: 'en_GB', // TODO locale LanguageCode: 'en_GB', // TODO locale
GraphicsMode: 1, // 1:simple, 2:fancy, 3:advanced, 4:ray_traced
PlatformOfflineId: '', PlatformOfflineId: '',
PlatformOnlineId: '', // chat PlatformOnlineId: '', // chat
// PlayFabID is the PlayFab ID produced for the skin. PlayFab is the company that hosts the Marketplace, // PlayFabID is the PlayFab ID produced for the skin. PlayFab is the company that hosts the Marketplace,
// skins and other related features from the game. This ID is the ID of the skin used to store the skin // skins and other related features from the game. This ID is the ID of the skin used to store the skin
// inside of PlayFab. // inside of PlayFab.The playfab ID is always lowercased.
PlayFabId: nextUUID().replace(/-/g, '').slice(0, 16), // 1.16.210 PlayFabId: nextUUID().replace(/-/g, '').slice(0, 16).toLowerCase(), // 1.16.210
SelfSignedId: nextUUID(), SelfSignedId: nextUUID(),
ServerAddress: `${options.host}:${options.port}`, ServerAddress: `${options.host}:${options.port}`,
ThirdPartyName: client.profile.name, ThirdPartyName: client.profile.name, // Gamertag
ThirdPartyNameOnly: false, ThirdPartyNameOnly: client.versionGreaterThanOrEqualTo('1.21.90') ? undefined : false,
UIProfile: 0, UIProfile: 0,
IsEditorMode: false, IsEditorMode: false,
@ -67,9 +67,9 @@ module.exports = (client, server, options) => {
OverrideSkin: client.versionGreaterThanOrEqualTo('1.19.62') ? false : undefined, OverrideSkin: client.versionGreaterThanOrEqualTo('1.19.62') ? false : undefined,
CompatibleWithClientSideChunkGen: client.versionGreaterThanOrEqualTo('1.19.80') ? false : undefined, CompatibleWithClientSideChunkGen: client.versionGreaterThanOrEqualTo('1.19.80') ? false : undefined,
MaxViewDistance: client.versionGreaterThanOrEqualTo('1.21.40') ? 0 : undefined, MaxViewDistance: client.versionGreaterThanOrEqualTo('1.21.42') ? 0 : undefined,
MemoryTier: client.versionGreaterThanOrEqualTo('1.21.40') ? 0 : undefined, MemoryTier: client.versionGreaterThanOrEqualTo('1.21.42') ? 0 : undefined,
PlatformType: client.versionGreaterThanOrEqualTo('1.21.40') ? 0 : undefined PlatformType: client.versionGreaterThanOrEqualTo('1.21.42') ? 0 : undefined
} }
const customPayload = options.skinData || {} const customPayload = options.skinData || {}
payload = { ...payload, ...customPayload } payload = { ...payload, ...customPayload }

View file

@ -3,12 +3,12 @@ const mcData = require('minecraft-data')
// Minimum supported version (< will be kicked) // Minimum supported version (< will be kicked)
const MIN_VERSION = '1.16.201' const MIN_VERSION = '1.16.201'
// Currently supported verson. Note, clients with newer versions can still connect as long as data is in minecraft-data // Currently supported verson. Note, clients with newer versions can still connect as long as data is in minecraft-data
const CURRENT_VERSION = '1.21.50' const CURRENT_VERSION = '1.21.111'
const Versions = Object.fromEntries(mcData.versions.bedrock.filter(e => e.releaseType === 'release').map(e => [e.minecraftVersion, e.version])) const Versions = Object.fromEntries(mcData.versions.bedrock.filter(e => e.releaseType === 'release').map(e => [e.minecraftVersion, e.version]))
// Skip some low priority versions (middle major) on Github Actions to allow faster CI // Skip some low priority versions (middle major) on Github Actions to allow faster CI
const skippedVersionsOnGithubCI = ['1.16.210', '1.17.10', '1.17.30', '1.18.11', '1.19.10', '1.19.20', '1.19.30', '1.19.40', '1.19.50', '1.19.60', '1.19.63', '1.19.70', '1.20.10', '1.20.15', '1.20.30', '1.20.40', '1.20.50', '1.20.61', '1.20.71'] const skippedVersionsOnGithubCI = ['1.16.210', '1.17.10', '1.17.30', '1.18.11', '1.19.10', '1.19.20', '1.19.30', '1.19.40', '1.19.50', '1.19.60', '1.19.63', '1.19.70', '1.20.10', '1.20.15', '1.20.30', '1.20.40', '1.20.50', '1.20.61', '1.20.71', '1.21.2', '1.21.20', '1.21.30', '1.21.42', '1.21.50', '1.21.60', '1.21.70', '1.21.80', '1.21.90']
const testedVersions = process.env.CI ? Object.keys(Versions).filter(v => !skippedVersionsOnGithubCI.includes(v)) : Object.keys(Versions) const testedVersions = process.env.CI ? Object.keys(Versions).filter(v => !skippedVersionsOnGithubCI.includes(v)) : Object.keys(Versions)
const defaultOptions = { const defaultOptions = {

View file

@ -33,7 +33,8 @@ class Server extends EventEmitter {
try { try {
const mcData = require('minecraft-data')('bedrock_' + version) const mcData = require('minecraft-data')('bedrock_' + version)
this.features = { this.features = {
compressorInHeader: mcData.supportFeature('compressorInPacketHeader') compressorInHeader: mcData.supportFeature('compressorInPacketHeader'),
newLoginIdentityFields: mcData.supportFeature('newLoginIdentityFields')
} }
} catch (e) { } catch (e) {
throw new Error(`Unsupported version: '${version}', no data available`) throw new Error(`Unsupported version: '${version}', no data available`)
@ -89,12 +90,10 @@ class Server extends EventEmitter {
this.emit('connect', player) this.emit('connect', player)
} }
onCloseConnection = (inetAddr, reason) => { onCloseConnection = (conn, reason) => {
this.conLog('Connection closed: ', inetAddr?.address, reason) this.conLog('Connection closed: ', conn.address, reason)
this.clients[conn.address]?.close()
delete this.clients[inetAddr]?.connection // Prevent close loop delete this.clients[conn.address]
this.clients[inetAddr?.address ?? inetAddr]?.close()
delete this.clients[inetAddr]
this.clientCount-- this.clientCount--
} }

View file

@ -78,11 +78,18 @@ class Player extends Connection {
// Parse login data // Parse login data
const tokens = body.params.tokens const tokens = body.params.tokens
const authChain = JSON.parse(tokens.identity)
const skinChain = tokens.client
try { try {
var { key, userData, skinData } = this.decodeLoginJWT(authChain.chain, skinChain) // eslint-disable-line const skinChain = tokens.client
const authChain = JSON.parse(tokens.identity)
let chain
if (authChain.Certificate) { // 1.21.90+
chain = JSON.parse(authChain.Certificate).chain
} else if (authChain.chain) {
chain = authChain.chain
} else {
throw new Error('Invalid login packet: missing chain or Certificate')
}
var { key, userData, skinData } = this.decodeLoginJWT(chain, skinChain) // eslint-disable-line
} catch (e) { } catch (e) {
debug(this.address, e) debug(this.address, e)
this.disconnect('Server authentication error') this.disconnect('Server authentication error')

View file

@ -63,7 +63,11 @@ async function startTest (version = CURRENT_VERSION, ok) {
// client.queue('inventory_transaction', get('packets/inventory_transaction.json')) // client.queue('inventory_transaction', get('packets/inventory_transaction.json'))
client.queue('player_list', get('packets/player_list.json')) client.queue('player_list', get('packets/player_list.json'))
client.queue('start_game', get('packets/start_game.json')) client.queue('start_game', get('packets/start_game.json'))
client.queue('item_component', { entries: [] }) if (client.versionLessThan('1.21.60')) {
client.queue('item_component', { entries: [] })
} else {
client.queue('item_registry', get('packets/item_registry.json'))
}
client.queue('set_spawn_position', get('packets/set_spawn_position.json')) client.queue('set_spawn_position', get('packets/set_spawn_position.json'))
client.queue('set_time', { time: 5433771 }) client.queue('set_time', { time: 5433771 })
client.queue('set_difficulty', { difficulty: 1 }) client.queue('set_difficulty', { difficulty: 1 })
@ -97,11 +101,11 @@ async function startTest (version = CURRENT_VERSION, ok) {
loop = setInterval(() => { loop = setInterval(() => {
client.write('network_chunk_publisher_update', { coordinates: { x: 646, y: 130, z: 77 }, radius: 64 }) client.write('network_chunk_publisher_update', { coordinates: { x: 646, y: 130, z: 77 }, radius: 64 })
}, 9500) }, 6500)
setTimeout(() => { setTimeout(() => {
client.write('play_status', { status: 'player_spawn' }) client.write('play_status', { status: 'player_spawn' })
}, 6000) }, 3000)
// Respond to tick synchronization packets // Respond to tick synchronization packets
client.on('tick_sync', (packet) => { client.on('tick_sync', (packet) => {

View file

@ -3,6 +3,7 @@
const { timedTest } = require('./internal') const { timedTest } = require('./internal')
const { testedVersions } = require('../src/options') const { testedVersions } = require('../src/options')
const { sleep } = require('../src/datatypes/util') const { sleep } = require('../src/datatypes/util')
require('events').captureRejections = true
describe('internal client/server test', function () { describe('internal client/server test', function () {
const vcount = testedVersions.length const vcount = testedVersions.length

View file

@ -22,12 +22,12 @@ function proxyTest (version, raknetBackend = 'raknet-native', timeout = 1000 * 4
console.debug('Client has authenticated') console.debug('Client has authenticated')
setTimeout(() => { setTimeout(() => {
client.disconnect('Hello world !') client.disconnect('Hello world !')
}, 1000) // allow some time for client to connect }, 500) // allow some time for client to connect
}) })
}) })
console.debug('Server started', server.options.version) console.debug('Server started', server.options.version)
await new Promise(resolve => setTimeout(resolve, 1000)) await new Promise(resolve => setTimeout(resolve, 500))
const relay = new Relay({ const relay = new Relay({
version, version,
@ -46,7 +46,7 @@ function proxyTest (version, raknetBackend = 'raknet-native', timeout = 1000 * 4
await relay.listen() await relay.listen()
console.debug('Proxy started', server.options.version) console.debug('Proxy started', server.options.version)
await new Promise(resolve => setTimeout(resolve, 1000)) await new Promise(resolve => setTimeout(resolve, 500))
const client = createClient({ host: '127.0.0.1', port: CLIENT_PORT, version, username: 'Boat', offline: true, raknetBackend, skipPing: true }) const client = createClient({ host: '127.0.0.1', port: CLIENT_PORT, version, username: 'Boat', offline: true, raknetBackend, skipPing: true })
console.debug('Client started') console.debug('Client started')
@ -58,7 +58,7 @@ function proxyTest (version, raknetBackend = 'raknet-native', timeout = 1000 * 4
server.close() server.close()
relay.close() relay.close()
console.log('✔ OK') console.log('✔ OK')
sleep(500).then(res) sleep(200).then(res)
}) })
}, timeout, () => { throw Error('timed out') }) }, timeout, () => { throw Error('timed out') })
} }

View file

@ -11,7 +11,7 @@ describe('proxies client/server', function () {
it('proxies ' + version, async () => { it('proxies ' + version, async () => {
console.debug(version) console.debug(version)
await proxyTest(version) await proxyTest(version)
await sleep(1000) await sleep(100)
console.debug('Done', version) console.debug('Done', version)
}) })
} }

View file

@ -15,7 +15,6 @@ function createProtocol (version) {
const compiler = new ProtoDefCompiler() const compiler = new ProtoDefCompiler()
const protocol = mcData('bedrock_' + version).protocol.types const protocol = mcData('bedrock_' + version).protocol.types
compiler.addTypes(require('../src/datatypes/compiler-minecraft')) compiler.addTypes(require('../src/datatypes/compiler-minecraft'))
compiler.addTypes(require('prismarine-nbt/zigzag').compiler)
compiler.addTypesToCompile(protocol) compiler.addTypesToCompile(protocol)
fs.writeFileSync('./read.js', 'module.exports = ' + compiler.readCompiler.generate().replace('() =>', 'native =>')) fs.writeFileSync('./read.js', 'module.exports = ' + compiler.readCompiler.generate().replace('() =>', 'native =>'))
@ -39,7 +38,7 @@ require('minecraft-data/bin/generate_data')
// If no argument, build everything // If no argument, build everything
if (!process.argv[2]) { if (!process.argv[2]) {
convert('latest') convert('bedrock', 'latest')
for (const version of versions) { for (const version of versions) {
main(version) main(version)
} }