mirror of
https://github.com/PrismarineJS/node-minecraft-protocol.git
synced 2024-11-14 10:55:05 -05:00
1.19.4 (#1226)
* Rename 'session' (packet) to chat_session_update to fix auth event conflict * impl packet "bundle" grouping, add client.writeBundle(packets) * fix handling, test * test 1.19.4 * 1.19.4 test ci * test ci against mcdata fork * lint * fix delim * fix 1.19.3 being skipped * Update ci.yml * Update package.json --------- Co-authored-by: Romain Beaumont <romain.rom1@gmail.com>
This commit is contained in:
parent
a32a1cf478
commit
2718bc64c0
9 changed files with 94 additions and 28 deletions
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
@ -13,7 +13,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
mcVersion: ['1.7', '1.8', '1.9', '1.10', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17', '1.17.1', '1.18.2', '1.19', '1.19.2', '1.19.3']
|
||||
mcVersion: ['1.7', '1.8', '1.9', '1.10', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17', '1.17.1', '1.18.2', '1.19', '1.19.2', '1.19.3', '1.19.4']
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
tasks:
|
||||
- command: npm install
|
||||
- command: npm install && sdk install java
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
"endian-toggle": "^0.0.0",
|
||||
"lodash.get": "^4.1.2",
|
||||
"lodash.merge": "^4.3.0",
|
||||
"minecraft-data": "^3.21.0",
|
||||
"minecraft-data": "^3.34.0",
|
||||
"minecraft-folder-path": "^1.2.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-rsa": "^0.4.2",
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
'use strict'
|
||||
|
||||
const EventEmitter = require('events').EventEmitter
|
||||
const debug = require('debug')('minecraft-protocol')
|
||||
const compression = require('./transforms/compression')
|
||||
|
@ -30,8 +29,9 @@ class Client extends EventEmitter {
|
|||
this.latency = 0
|
||||
this.hideErrors = hideErrors
|
||||
this.closeTimer = null
|
||||
|
||||
const mcData = require('minecraft-data')(version)
|
||||
this.state = states.HANDSHAKING
|
||||
this._hasBundlePacket = mcData.supportFeature('hasBundlePacket')
|
||||
}
|
||||
|
||||
get state () {
|
||||
|
@ -77,7 +77,13 @@ class Client extends EventEmitter {
|
|||
if (!this.compressor) { this.splitter.pipe(this.deserializer) } else { this.decompressor.pipe(this.deserializer) }
|
||||
this.emit('error', e)
|
||||
})
|
||||
|
||||
this._mcBundle = []
|
||||
const emitPacket = (parsed) => {
|
||||
this.emit('packet', parsed.data, parsed.metadata, parsed.buffer, parsed.fullBuffer)
|
||||
this.emit(parsed.metadata.name, parsed.data, parsed.metadata)
|
||||
this.emit('raw.' + parsed.metadata.name, parsed.buffer, parsed.metadata)
|
||||
this.emit('raw', parsed.buffer, parsed.metadata)
|
||||
}
|
||||
this.deserializer.on('data', (parsed) => {
|
||||
parsed.metadata.name = parsed.data.name
|
||||
parsed.data = parsed.data.params
|
||||
|
@ -87,10 +93,18 @@ class Client extends EventEmitter {
|
|||
const s = JSON.stringify(parsed.data, null, 2)
|
||||
debug(s && s.length > 10000 ? parsed.data : s)
|
||||
}
|
||||
this.emit('packet', parsed.data, parsed.metadata, parsed.buffer, parsed.fullBuffer)
|
||||
this.emit(parsed.metadata.name, parsed.data, parsed.metadata)
|
||||
this.emit('raw.' + parsed.metadata.name, parsed.buffer, parsed.metadata)
|
||||
this.emit('raw', parsed.buffer, parsed.metadata)
|
||||
if (parsed.metadata.name === 'bundle_delimiter') {
|
||||
if (this._mcBundle.length) {
|
||||
this._mcBundle.forEach(emitPacket)
|
||||
this._mcBundle = []
|
||||
} else { // Start bundle
|
||||
this._mcBundle.push(parsed)
|
||||
}
|
||||
} else if (this._mcBundle.length) {
|
||||
this._mcBundle.push(parsed)
|
||||
} else {
|
||||
emitPacket(parsed)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -221,6 +235,12 @@ class Client extends EventEmitter {
|
|||
this.serializer.write({ name, params })
|
||||
}
|
||||
|
||||
writeBundle (packets) {
|
||||
if (this._hasBundlePacket) this.write('bundle_delimiter', {})
|
||||
for (const [name, params] of packets) this.write(name, params)
|
||||
if (this._hasBundlePacket) this.write('bundle_delimiter', {})
|
||||
}
|
||||
|
||||
writeRaw (buffer) {
|
||||
const stream = this.compressor === null ? this.framer : this.compressor
|
||||
if (!stream.writable) { return }
|
||||
|
|
|
@ -19,7 +19,7 @@ module.exports = function (client, options) {
|
|||
uuid: uuid.v4fast()
|
||||
}
|
||||
|
||||
client.write('session', {
|
||||
client.write('chat_session_update', {
|
||||
sessionUUID: client._session.uuid,
|
||||
expireTime: client.profileKeys ? BigInt(client.profileKeys.expiresOn.getTime()) : undefined,
|
||||
publicKey: client.profileKeys ? client.profileKeys.public.export({ type: 'spki', format: 'der' }) : undefined,
|
||||
|
|
|
@ -76,7 +76,7 @@ module.exports = function (client, server, options) {
|
|||
}
|
||||
}
|
||||
|
||||
client.on('session', (packet) => {
|
||||
client.on('chat_session_update', (packet) => {
|
||||
client._session = {
|
||||
index: 0,
|
||||
uuid: packet.sessionUuid
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
|
||||
module.exports = {
|
||||
defaultVersion: '1.19.3',
|
||||
supportedVersions: ['1.7', '1.8', '1.9', '1.10', '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']
|
||||
defaultVersion: '1.19.4',
|
||||
supportedVersions: ['1.7', '1.8', '1.9', '1.10', '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']
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ const values = {
|
|||
}
|
||||
Object.keys(typeArgs).forEach(function (index) {
|
||||
const v = typeArgs[index].name === 'type' && typeArgs[index].type === 'string' && typeArgs[2] !== undefined &&
|
||||
typeArgs[2].type !== undefined
|
||||
typeArgs[2].type !== undefined
|
||||
? (typeArgs[2].type[1].fields['minecraft:crafting_shapeless'] === undefined ? 'crafting_shapeless' : 'minecraft:crafting_shapeless')
|
||||
: getValue(typeArgs[index].type, results)
|
||||
if (typeArgs[index].anon) {
|
||||
|
@ -96,6 +96,15 @@ const values = {
|
|||
delete results['..']
|
||||
return results
|
||||
},
|
||||
vec3f: {
|
||||
x: 0, y: 0, z: 0
|
||||
},
|
||||
vec3f64: {
|
||||
x: 0, y: 0, z: 0
|
||||
},
|
||||
vec4f: {
|
||||
x: 0, y: 0, z: 0, w: 0
|
||||
},
|
||||
count: 1, // TODO : might want to set this to a correct value
|
||||
bool: true,
|
||||
f64: 99999.2222,
|
||||
|
@ -266,8 +275,7 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
Object.keys(packets[state]).forEach(function (direction) {
|
||||
Object.keys(packets[state][direction].types)
|
||||
.filter(function (packetName) {
|
||||
return packetName !== 'packet' &&
|
||||
packetName.startsWith('packet_')
|
||||
return packetName !== 'packet' && packetName.startsWith('packet_')
|
||||
})
|
||||
.forEach(function (packetName) {
|
||||
packetInfo = packets[state][direction].types[packetName]
|
||||
|
|
|
@ -62,23 +62,23 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
// removed `dimension`
|
||||
// removed `dimensionCodec`
|
||||
registryCodec: {
|
||||
"type": "compound",
|
||||
"name": "",
|
||||
"value": {}
|
||||
type: 'compound',
|
||||
name: '',
|
||||
value: {}
|
||||
},
|
||||
worldType: "minecraft:overworld",
|
||||
worldType: 'minecraft:overworld',
|
||||
death: undefined
|
||||
// more to be added
|
||||
}
|
||||
}
|
||||
|
||||
function sendBroadcastMessage(server, clients, message, sender) {
|
||||
function sendBroadcastMessage (server, clients, message, sender) {
|
||||
if (mcData.supportFeature('signedChat')) {
|
||||
server.writeToClients(clients, 'player_chat', {
|
||||
plainMessage: message,
|
||||
signedChatContent: '',
|
||||
unsignedChatContent: JSON.stringify({ text: message }),
|
||||
type: 0,
|
||||
type: 0,
|
||||
senderUuid: 'd3527a0b-bc03-45d5-a878-2aafdd8c8a43', // random
|
||||
senderName: JSON.stringify({ text: sender }),
|
||||
senderTeam: undefined,
|
||||
|
@ -96,7 +96,7 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
|
||||
describe('mc-server ' + version.minecraftVersion, function () {
|
||||
this.timeout(5000)
|
||||
this.beforeAll(async function() {
|
||||
this.beforeAll(async function () {
|
||||
PORT = await getPort()
|
||||
console.log(`Using port for tests: ${PORT}`)
|
||||
})
|
||||
|
@ -214,7 +214,7 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
sample: []
|
||||
},
|
||||
description: {
|
||||
extra: [ { color: 'red', text: 'Red text' } ],
|
||||
extra: [{ color: 'red', text: 'Red text' }],
|
||||
bold: true,
|
||||
text: 'Example chat mesasge'
|
||||
}
|
||||
|
@ -278,7 +278,7 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
version: version.minecraftVersion,
|
||||
port: PORT
|
||||
})
|
||||
client.on('packet', (data, {name})=>{
|
||||
client.on('packet', (data, { name }) => {
|
||||
if (name === 'success') {
|
||||
assert.strictEqual(data.uuid, notchUUID, 'UUID')
|
||||
server.close()
|
||||
|
@ -333,7 +333,7 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
}))
|
||||
|
||||
const p1Join = await player1.nextMessage('player2')
|
||||
|
||||
|
||||
assert.strictEqual(p1Join, '{"text":"player2 joined the game."}')
|
||||
|
||||
player2.chat('hi')
|
||||
|
@ -441,7 +441,7 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
|
||||
sendBroadcastMessage(server, Object.values(server.clients), 'A message from the server.')
|
||||
|
||||
let results = await Promise.all([player1.nextMessage(), player2.nextMessage()])
|
||||
const results = await Promise.all([player1.nextMessage(), player2.nextMessage()])
|
||||
for (const msg of results) {
|
||||
assert.strictEqual(msg, '{"text":"A message from the server."}')
|
||||
}
|
||||
|
@ -452,5 +452,43 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
server.close()
|
||||
})
|
||||
})
|
||||
|
||||
it('supports bundle packet', function (done) {
|
||||
const server = mc.createServer({
|
||||
'online-mode': false,
|
||||
version: version.minecraftVersion,
|
||||
port: PORT
|
||||
})
|
||||
server.on('login', function (client) {
|
||||
client.on('end', function (reason) {
|
||||
assert.strictEqual(reason, 'ServerShutdown')
|
||||
})
|
||||
client.write('login', loginPacket(client, server))
|
||||
client.writeBundle([
|
||||
['update_time', { age: 1, time: 2 }],
|
||||
['close_window', { windowId: 0 }]
|
||||
])
|
||||
})
|
||||
server.on('close', done)
|
||||
server.on('listening', function () {
|
||||
const client = mc.createClient({
|
||||
username: 'lalalal',
|
||||
host: '127.0.0.1',
|
||||
version: version.minecraftVersion,
|
||||
port: PORT
|
||||
})
|
||||
client.on('update_time', function () {
|
||||
// Below handler synchronously defined should be guaranteed to be called after the above one
|
||||
const d1 = Date.now()
|
||||
client.on('close_window', function () {
|
||||
server.close()
|
||||
const d2 = Date.now()
|
||||
if (mcData.supportFeature('hasBundlePacket') && (d2 - d1) > 1) {
|
||||
throw new Error(`bundle packet constituents did not arrive at once : ${d1}, ${d2}`)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue