mirror of
https://github.com/PrismarineJS/node-minecraft-protocol.git
synced 2024-11-14 10:55:05 -05:00
[1.19] fix tests and library session code (#1020)
* make tests work, add todo's * clean up, varlong test, additional todo * removed log statements, fix for older versions * Update mcdata * Update ci.yml * Update ci.yml * remove excessive version comments near supportFeature checks Co-authored-by: Romain Beaumont <romain.rom1@gmail.com>
This commit is contained in:
parent
dda12949ef
commit
0ecba87dfe
9 changed files with 330 additions and 123 deletions
|
@ -51,7 +51,8 @@
|
|||
"endian-toggle": "^0.0.0",
|
||||
"lodash.get": "^4.1.2",
|
||||
"lodash.merge": "^4.3.0",
|
||||
"minecraft-data": "^3.7.3",
|
||||
|
||||
"minecraft-data": "^3.8.0",
|
||||
"minecraft-folder-path": "^1.2.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-rsa": "^0.4.2",
|
||||
|
|
|
@ -42,13 +42,29 @@ module.exports = function (client, options) {
|
|||
}
|
||||
|
||||
function sendEncryptionKeyResponse () {
|
||||
const mcData = require('minecraft-data')(client.version)
|
||||
|
||||
const pubKey = mcPubKeyToPem(packet.publicKey)
|
||||
const encryptedSharedSecretBuffer = crypto.publicEncrypt({ key: pubKey, padding: crypto.constants.RSA_PKCS1_PADDING }, sharedSecret)
|
||||
const encryptedVerifyTokenBuffer = crypto.publicEncrypt({ key: pubKey, padding: crypto.constants.RSA_PKCS1_PADDING }, packet.verifyToken)
|
||||
client.write('encryption_begin', {
|
||||
sharedSecret: encryptedSharedSecretBuffer,
|
||||
verifyToken: encryptedVerifyTokenBuffer
|
||||
})
|
||||
|
||||
if (mcData.supportFeature('signatureEncryption')) {
|
||||
// todo: add signature encryption
|
||||
// starting 1.19.1 we will not be able to join
|
||||
// the default server configuration without it
|
||||
client.write('encryption_begin', {
|
||||
sharedSecret: encryptedSharedSecretBuffer,
|
||||
hasVerifyToken: true,
|
||||
crypto: {
|
||||
verifyToken: encryptedVerifyTokenBuffer
|
||||
}
|
||||
})
|
||||
} else {
|
||||
client.write('encryption_begin', {
|
||||
sharedSecret: encryptedSharedSecretBuffer,
|
||||
verifyToken: encryptedVerifyTokenBuffer
|
||||
})
|
||||
}
|
||||
client.setEncryption(sharedSecret)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ module.exports = function (client, options) {
|
|||
client.write('login_start', {
|
||||
username: client.username
|
||||
})
|
||||
// TODO: add signature option
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,18 +55,48 @@ module.exports = function (client, server, options) {
|
|||
}
|
||||
|
||||
function onEncryptionKeyResponse (packet) {
|
||||
const mcData = require('minecraft-data')(client.version)
|
||||
|
||||
let packetVerifyToken
|
||||
let signature
|
||||
|
||||
if (mcData.supportFeature('signatureEncryption')) {
|
||||
if (packet.hasVerifyToken) {
|
||||
packetVerifyToken = packet.crypto.verifyToken
|
||||
} else {
|
||||
signature = packet.crypto
|
||||
}
|
||||
} else {
|
||||
packetVerifyToken = packet.verifyToken
|
||||
}
|
||||
|
||||
let sharedSecret
|
||||
try {
|
||||
const verifyToken = crypto.privateDecrypt({ key: server.serverKey.exportKey(), padding: crypto.constants.RSA_PKCS1_PADDING }, packet.verifyToken)
|
||||
if (!bufferEqual(client.verifyToken, verifyToken)) {
|
||||
|
||||
if (packetVerifyToken) {
|
||||
try {
|
||||
const verifyToken = crypto.privateDecrypt({
|
||||
key: server.serverKey.exportKey(),
|
||||
padding: crypto.constants.RSA_PKCS1_PADDING
|
||||
}, packetVerifyToken)
|
||||
if (!bufferEqual(client.verifyToken, verifyToken)) {
|
||||
client.end('DidNotEncryptVerifyTokenProperly')
|
||||
return
|
||||
}
|
||||
sharedSecret = crypto.privateDecrypt({
|
||||
key: server.serverKey.exportKey(),
|
||||
padding: crypto.constants.RSA_PKCS1_PADDING
|
||||
}, packet.sharedSecret)
|
||||
} catch (e) {
|
||||
client.end('DidNotEncryptVerifyTokenProperly')
|
||||
return
|
||||
}
|
||||
sharedSecret = crypto.privateDecrypt({ key: server.serverKey.exportKey(), padding: crypto.constants.RSA_PKCS1_PADDING }, packet.sharedSecret)
|
||||
} catch (e) {
|
||||
client.end('DidNotEncryptVerifyTokenProperly')
|
||||
} else {
|
||||
// todo: signature encryption
|
||||
client.end('signature encryption not implemented')
|
||||
console.error(signature)
|
||||
return
|
||||
}
|
||||
|
||||
client.setEncryption(sharedSecret)
|
||||
|
||||
const isException = !!server.onlineModeExceptions[client.username.toLowerCase()]
|
||||
|
@ -114,7 +144,12 @@ module.exports = function (client, server, options) {
|
|||
client.write('compress', { threshold: 256 }) // Default threshold is 256
|
||||
client.compressionThreshold = 256
|
||||
}
|
||||
client.write('success', { uuid: client.uuid, username: client.username })
|
||||
client.write('success', {
|
||||
uuid: client.uuid,
|
||||
username: client.username,
|
||||
properties: []
|
||||
})
|
||||
// TODO: find out what properties are on 'success' packet
|
||||
client.state = states.PLAY
|
||||
|
||||
clearTimeout(loginKickTimer)
|
||||
|
|
|
@ -7,7 +7,8 @@ const states = mc.states
|
|||
|
||||
const testDataWrite = [
|
||||
{ name: 'keep_alive', params: { keepAliveId: 957759560 } },
|
||||
{ name: 'chat', params: { message: '<Bob> Hello World!' } },
|
||||
// TODO: 1.19+ `chat` -> `player_chat` feature toggle
|
||||
// { name: 'chat', params: { message: '<Bob> Hello World!' } },
|
||||
{ name: 'position_look', params: { x: 6.5, y: 65.62, stance: 67.24, z: 7.5, yaw: 0, pitch: 0, onGround: true } }
|
||||
// TODO: add more packets for better quality data
|
||||
]
|
||||
|
|
|
@ -12,7 +12,7 @@ const Wrap = require('minecraft-wrap').Wrap
|
|||
|
||||
const download = util.promisify(require('minecraft-wrap').download)
|
||||
|
||||
const { getPort } = require('./common/util')
|
||||
const { getPort, chat } = require('./common/util')
|
||||
|
||||
for (const supportedVersion of mc.supportedVersions) {
|
||||
let PORT = null
|
||||
|
@ -104,6 +104,9 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
})
|
||||
client.on('error', err => done(err))
|
||||
const lineListener = function (line) {
|
||||
// 1.19+ also prints Server like a player
|
||||
if (line.match(/\[Server thread\/INFO\]: <Server> .*/)) return
|
||||
|
||||
const match = line.match(/\[Server thread\/INFO\]: <(.+?)> (.+)/)
|
||||
if (!match) return
|
||||
assert.strictEqual(match[1], 'Player')
|
||||
|
@ -114,13 +117,13 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
let chatCount = 0
|
||||
client.on('login', function (packet) {
|
||||
assert.strictEqual(packet.gameMode, 0)
|
||||
client.write('chat', {
|
||||
message: 'hello everyone; I have logged in.'
|
||||
})
|
||||
chat(client, 'hello everyone; I have logged in.')
|
||||
})
|
||||
|
||||
// pre 1.19 named 'chat'
|
||||
|
||||
client.on('chat', function (packet) {
|
||||
chatCount += 1
|
||||
assert.ok(chatCount <= 2)
|
||||
const message = JSON.parse(packet.message)
|
||||
if (chatCount === 1) {
|
||||
assert.strictEqual(message.translate, 'chat.type.text')
|
||||
|
@ -138,11 +141,65 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
? message.with[1].extra[0].text
|
||||
: message.with[1].extra[0])
|
||||
: message.with[1].text, 'hello')
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
|
||||
// 1.19+ named 'player_chat'
|
||||
|
||||
client.on('player_chat', function (packet) {
|
||||
chatCount += 1
|
||||
|
||||
const sender = JSON.parse(packet.senderName)
|
||||
const chatContent = JSON.parse(packet.signedChatContent)
|
||||
|
||||
switch (chatCount) {
|
||||
case 1:
|
||||
assert.deepStrictEqual(sender, {
|
||||
insertion: 'Player',
|
||||
clickEvent: {
|
||||
action: 'suggest_command',
|
||||
value: '/tell Player '
|
||||
},
|
||||
hoverEvent: {
|
||||
action: 'show_entity',
|
||||
contents: {
|
||||
type: 'minecraft:player',
|
||||
id: 'a01e3843-e521-3998-958a-f459800e4d11',
|
||||
name: {
|
||||
text: 'Player'
|
||||
}
|
||||
}
|
||||
},
|
||||
text: 'Player'
|
||||
})
|
||||
assert.deepStrictEqual(chatContent, {
|
||||
text: 'hello everyone; I have logged in.'
|
||||
})
|
||||
assert.strictEqual(packet.type, 0)
|
||||
break
|
||||
|
||||
case 2:
|
||||
assert.deepStrictEqual(sender, {
|
||||
text: 'Server'
|
||||
})
|
||||
assert.deepStrictEqual(chatContent, {
|
||||
text: 'hello'
|
||||
})
|
||||
assert.strictEqual(packet.type, 3)
|
||||
}
|
||||
|
||||
resolve()
|
||||
})
|
||||
|
||||
function resolve () {
|
||||
assert.ok(chatCount <= 2)
|
||||
if (chatCount === 2) {
|
||||
wrap.removeListener('line', lineListener)
|
||||
client.end()
|
||||
done()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
it('does not crash for ' + SURVIVE_TIME + 'ms', function (done) {
|
||||
|
@ -153,9 +210,7 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
})
|
||||
client.on('error', err => done(err))
|
||||
client.on('login', function () {
|
||||
client.write('chat', {
|
||||
message: 'hello everyone; I have logged in.'
|
||||
})
|
||||
chat(client, 'hello everyone; I have logged in.')
|
||||
setTimeout(function () {
|
||||
client.end()
|
||||
done()
|
||||
|
@ -231,9 +286,7 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
assert.strictEqual(packet.difficulty, 1)
|
||||
assert.strictEqual(packet.dimension, 0)
|
||||
assert.strictEqual(packet.gameMode, 0)
|
||||
client.write('chat', {
|
||||
message: 'hello everyone; I have logged in.'
|
||||
})
|
||||
chat(client, 'hello everyone; I have logged in.')
|
||||
})
|
||||
let chatCount = 0
|
||||
client.on('chat', function (packet) {
|
||||
|
|
|
@ -9,4 +9,96 @@ const getPort = () => new Promise(resolve => {
|
|||
})
|
||||
})
|
||||
|
||||
module.exports = { getPort }
|
||||
function serverchat (client, message) {
|
||||
const [event, data] = makeBroadcast(client.version, message)
|
||||
client.write(event, data)
|
||||
}
|
||||
|
||||
function makeBroadcast (version, message) {
|
||||
const mcData = require('minecraft-data')(version)
|
||||
if (mcData.supportFeature('signedChat')) {
|
||||
return ['player_chat', {
|
||||
signedChatContent: JSON.stringify({ text: message }),
|
||||
unsignedChatContent: undefined,
|
||||
type: 0,
|
||||
senderUuid: '0',
|
||||
senderName: 'Server',
|
||||
timestamp: Date.now() * 1000,
|
||||
salt: 0,
|
||||
signature: []
|
||||
}]
|
||||
} else {
|
||||
return ['chat', {
|
||||
message: JSON.stringify({ text: message }),
|
||||
position: 0,
|
||||
sender: '0'
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
function chat (client, message) {
|
||||
const mcData = require('minecraft-data')(client.version)
|
||||
if (mcData.supportFeature('signedChat')) {
|
||||
client.write('chat_message', {
|
||||
message,
|
||||
timestamp: Date.now() * 1000,
|
||||
salt: 0,
|
||||
signature: [],
|
||||
signedPreview: true
|
||||
})
|
||||
} else {
|
||||
client.write('chat', {
|
||||
message
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function clientXChat (x, client, fn) {
|
||||
const mcData = require('minecraft-data')(client.version)
|
||||
if (mcData.supportFeature('signedChat')) {
|
||||
x.bind(client)('player_chat', (packet) => {
|
||||
const message = packet.unsignedChatContent || packet.signedChatContent
|
||||
fn(message)
|
||||
})
|
||||
} else {
|
||||
x.bind(client)('chat', (packet) => {
|
||||
const message = packet.message
|
||||
fn(message)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function serverXChat (x, server, fn) {
|
||||
const mcData = require('minecraft-data')(server.version)
|
||||
if (mcData.supportFeature('signedChat')) {
|
||||
x.bind(server)('chat_message', (packet) => {
|
||||
const message = packet.message
|
||||
fn(message)
|
||||
})
|
||||
} else {
|
||||
x.bind(server)('chat', (packet) => {
|
||||
const message = packet.message
|
||||
fn(message)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function OnceChat (client, fn) {
|
||||
clientXChat(client.once, client, fn)
|
||||
}
|
||||
function OnChat (client, fn) {
|
||||
clientXChat(client.on, client, fn)
|
||||
}
|
||||
async function OnceChatPromise (client) {
|
||||
const mcData = require('minecraft-data')(client.version)
|
||||
const { once } = require('events')
|
||||
if (mcData.supportFeature('signedChat')) {
|
||||
const [packet] = await once(client, 'player_chat')
|
||||
return packet.unsignedChatContent || packet.signedChatContent
|
||||
} else {
|
||||
const [packet] = await once(client, 'chat')
|
||||
return packet.message
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getPort, serverchat, makeBroadcast, chat, OnceChat, OnceChatPromise, OnChat, clientXChat, serverXChat }
|
||||
|
|
|
@ -40,6 +40,7 @@ const values = {
|
|||
i16: -123,
|
||||
u16: 123,
|
||||
varint: 1,
|
||||
varlong: -20,
|
||||
i8: -10,
|
||||
u8: 8,
|
||||
string: 'hi hi this is my client string',
|
||||
|
@ -176,7 +177,30 @@ const values = {
|
|||
tags: [{ tagName: 'hi', entries: [1, 2, 3, 4, 5] }],
|
||||
ingredient: [slotValue],
|
||||
particleData: null,
|
||||
chunkBlockEntity: { x: 10, y: 11, z: 12, type: 25 }
|
||||
chunkBlockEntity: { x: 10, y: 11, z: 12, type: 25 },
|
||||
command_node: {
|
||||
flags: {
|
||||
has_custom_suggestions: 1,
|
||||
has_redirect_node: 1,
|
||||
has_command: 1,
|
||||
command_node_type: 2
|
||||
},
|
||||
children: [23, 29],
|
||||
redirectNode: 83,
|
||||
extraNodeData: {
|
||||
name: 'command_node name',
|
||||
parser: 'brigadier:double',
|
||||
properties: {
|
||||
flags: {
|
||||
max_present: 1,
|
||||
min_present: 1
|
||||
},
|
||||
min: -5.0,
|
||||
max: 256.0
|
||||
},
|
||||
suggestionType: 'minecraft:summonable_entities'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getValue (_type, packet) {
|
||||
|
|
|
@ -4,7 +4,7 @@ const mc = require('../')
|
|||
const assert = require('power-assert')
|
||||
const { once } = require('events')
|
||||
|
||||
const { getPort } = require('./common/util')
|
||||
const { getPort, serverchat, makeBroadcast, chat, OnceChat, OnceChatPromise, serverXChat } = require('./common/util')
|
||||
|
||||
const w = {
|
||||
piglin_safe: {
|
||||
|
@ -66,6 +66,49 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
const mcData = require('minecraft-data')(supportedVersion)
|
||||
const version = mcData.version
|
||||
|
||||
const loginPacket = (client, server) => {
|
||||
return {
|
||||
// 1.7
|
||||
entityId: client.id,
|
||||
gameMode: 1,
|
||||
dimension: (version.version >= 735 ? mcData.loginPacket.dimension : 0),
|
||||
difficulty: 2,
|
||||
maxPlayers: server.maxPlayers,
|
||||
levelType: 'default',
|
||||
// 1.8
|
||||
reducedDebugInfo: (version.version >= 735 ? false : 0),
|
||||
// 1.14
|
||||
// removes `difficulty`
|
||||
viewDistance: 10,
|
||||
// 1.15
|
||||
hashedSeed: [0, 0],
|
||||
enableRespawnScreen: true,
|
||||
// 1.16
|
||||
// removed levelType
|
||||
previousGameMode: version.version >= 755 ? 0 : 255,
|
||||
worldNames: ['minecraft:overworld'],
|
||||
dimensionCodec: version.version >= 755 ? mcData.loginPacket.dimensionCodec : (version.version >= 735 ? mcData.loginPacket.dimension : { name: '', type: 'compound', value: { dimension: { type: 'list', value: { type: 'compound', value: [w] } } } }),
|
||||
worldName: 'minecraft:overworld',
|
||||
isDebug: false,
|
||||
isFlat: false,
|
||||
// 1.16.2
|
||||
isHardcore: false,
|
||||
// 1.18
|
||||
simulationDistance: 10,
|
||||
// 1.19
|
||||
// removed `dimension`
|
||||
// removed `dimensionCodec`
|
||||
registryCodec: {
|
||||
"type": "compound",
|
||||
"name": "",
|
||||
"value": {}
|
||||
},
|
||||
worldType: "minecraft:overworld",
|
||||
death: undefined
|
||||
// more to be added
|
||||
}
|
||||
}
|
||||
|
||||
describe('mc-server ' + version.minecraftVersion, function () {
|
||||
|
||||
this.beforeAll(async function() {
|
||||
|
@ -191,7 +234,7 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
online: 0,
|
||||
sample: []
|
||||
},
|
||||
description: {
|
||||
description: {
|
||||
extra: [ { color: 'red', text: 'Red text' } ],
|
||||
bold: true,
|
||||
text: 'Example chat mesasge'
|
||||
|
@ -279,32 +322,9 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
broadcast(client.username + ' left the game.', client)
|
||||
if (client.username === 'player2') server.close()
|
||||
})
|
||||
const loginPacket = {
|
||||
entityId: client.id,
|
||||
levelType: 'default',
|
||||
gameMode: 1,
|
||||
previousGameMode: version.version >= 755 ? 0 : 255,
|
||||
worldNames: ['minecraft:overworld'],
|
||||
dimensionCodec: version.version >= 755 ? mcData.loginPacket.dimensionCodec : (version.version >= 735 ? mcData.loginPacket.dimension : { name: '', type: 'compound', value: { dimension: { type: 'list', value: { type: 'compound', value: [w] } } } }),
|
||||
dimension: (version.version >= 735 ? mcData.loginPacket.dimension : 0),
|
||||
worldName: 'minecraft:overworld',
|
||||
hashedSeed: [0, 0],
|
||||
difficulty: 2,
|
||||
maxPlayers: server.maxPlayers,
|
||||
reducedDebugInfo: (version.version >= 735 ? false : 0),
|
||||
enableRespawnScreen: true
|
||||
}
|
||||
if (version.version >= 735) { // 1.16x
|
||||
loginPacket.isDebug = false
|
||||
loginPacket.isFlat = false
|
||||
loginPacket.isHardcore = false
|
||||
loginPacket.viewDistance = 10
|
||||
delete loginPacket.levelType
|
||||
delete loginPacket.difficulty
|
||||
}
|
||||
client.write('login', loginPacket)
|
||||
client.on('chat', function (packet) {
|
||||
const message = '<' + client.username + '>' + ' ' + packet.message
|
||||
client.write('login', loginPacket(client, server))
|
||||
serverXChat(client.on, client, function (message) {
|
||||
message = '<' + client.username + '>' + ' ' + message
|
||||
broadcast(message)
|
||||
})
|
||||
})
|
||||
|
@ -318,27 +338,31 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
})
|
||||
player1.on('login', function (packet) {
|
||||
assert.strictEqual(packet.gameMode, 1)
|
||||
player1.once('chat', function (packet) {
|
||||
assert.strictEqual(packet.message, '{"text":"player2 joined the game."}')
|
||||
player1.once('chat', function (packet) {
|
||||
assert.strictEqual(packet.message, '{"text":"<player2> hi"}')
|
||||
player2.once('chat', fn)
|
||||
function fn (packet) {
|
||||
if (/<player2>/.test(packet.message)) {
|
||||
player2.once('chat', fn)
|
||||
|
||||
OnceChat(player1, (message) => {
|
||||
assert.strictEqual(message, '{"text":"player2 joined the game."}')
|
||||
|
||||
OnceChat(player1, (message => {
|
||||
assert.strictEqual(message, '{"text":"<player2> hi"}')
|
||||
|
||||
function fn(message) {
|
||||
if (/<player2>/.test(message)) {
|
||||
OnceChat(player2, fn)
|
||||
return
|
||||
}
|
||||
assert.strictEqual(packet.message, '{"text":"<player1> hello"}')
|
||||
player1.once('chat', function (packet) {
|
||||
assert.strictEqual(packet.message, '{"text":"player2 left the game."}')
|
||||
assert.strictEqual(message, '{"text":"<player1> hello"}')
|
||||
OnceChat(player1, (message) => {
|
||||
assert.strictEqual(message, '{"text":"player2 left the game."}')
|
||||
player1.end()
|
||||
})
|
||||
player2.end()
|
||||
}
|
||||
|
||||
player1.write('chat', { message: 'hello' })
|
||||
})
|
||||
player2.write('chat', { message: 'hi' })
|
||||
OnceChat(player2, fn)
|
||||
|
||||
chat(player1, 'hello')
|
||||
}))
|
||||
chat(player2, 'hi')
|
||||
})
|
||||
const player2 = mc.createClient({
|
||||
username: 'player2',
|
||||
|
@ -349,13 +373,13 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
})
|
||||
})
|
||||
|
||||
function broadcast (message, exclude) {
|
||||
function broadcast(message, exclude) {
|
||||
let client
|
||||
for (const clientId in server.clients) {
|
||||
if (server.clients[clientId] === undefined) continue
|
||||
|
||||
client = server.clients[clientId]
|
||||
if (client !== exclude) client.write('chat', { message: JSON.stringify({ text: message }), position: 0, sender: '0' })
|
||||
if (client !== exclude) serverchat(client, message)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -404,30 +428,7 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
assert.strictEqual(reason, 'ServerShutdown')
|
||||
resolve()
|
||||
})
|
||||
const loginPacket = {
|
||||
entityId: client.id,
|
||||
levelType: 'default',
|
||||
gameMode: 1,
|
||||
previousGameMode: version.version >= 755 ? 0 : 255,
|
||||
worldNames: ['minecraft:overworld'],
|
||||
dimensionCodec: version.version >= 755 ? mcData.loginPacket.dimensionCodec : (version.version >= 735 ? mcData.loginPacket.dimension : { name: '', type: 'compound', value: { dimension: { type: 'list', value: { type: 'compound', value: [w] } } } }),
|
||||
dimension: (version.version >= 735 ? mcData.loginPacket.dimension : 0),
|
||||
worldName: 'minecraft:overworld',
|
||||
hashedSeed: [0, 0],
|
||||
difficulty: 2,
|
||||
maxPlayers: server.maxPlayers,
|
||||
reducedDebugInfo: (version.version >= 735 ? false : 0),
|
||||
enableRespawnScreen: true
|
||||
}
|
||||
if (version.version >= 735) { // 1.16x
|
||||
loginPacket.isDebug = false
|
||||
loginPacket.isFlat = false
|
||||
loginPacket.isHardcore = false
|
||||
loginPacket.viewDistance = 10
|
||||
delete loginPacket.levelType
|
||||
delete loginPacket.difficulty
|
||||
}
|
||||
client.write('login', loginPacket)
|
||||
client.write('login', loginPacket(client, server))
|
||||
})
|
||||
server.on('close', function () {
|
||||
resolve()
|
||||
|
@ -455,30 +456,7 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
port: PORT
|
||||
})
|
||||
server.on('login', function (client) {
|
||||
const loginPacket = {
|
||||
entityId: client.id,
|
||||
levelType: 'default',
|
||||
gameMode: 1,
|
||||
previousGameMode: version.version >= 755 ? 0 : 255,
|
||||
worldNames: ['minecraft:overworld'],
|
||||
dimensionCodec: version.version >= 755 ? mcData.loginPacket.dimensionCodec : (version.version >= 735 ? mcData.loginPacket.dimension : { name: '', type: 'compound', value: { dimension: { type: 'list', value: { type: 'compound', value: [w] } } } }),
|
||||
dimension: (version.version >= 735 ? mcData.loginPacket.dimension : 0),
|
||||
worldName: 'minecraft:overworld',
|
||||
hashedSeed: [0, 0],
|
||||
difficulty: 2,
|
||||
maxPlayers: server.maxPlayers,
|
||||
reducedDebugInfo: (version.version >= 735 ? false : 0),
|
||||
enableRespawnScreen: true
|
||||
}
|
||||
if (version.version >= 735) { // 1.16x
|
||||
loginPacket.isDebug = false
|
||||
loginPacket.isFlat = false
|
||||
loginPacket.isHardcore = false
|
||||
loginPacket.viewDistance = 10
|
||||
delete loginPacket.levelType
|
||||
delete loginPacket.difficulty
|
||||
}
|
||||
client.write('login', loginPacket)
|
||||
client.write('login', loginPacket(client, server))
|
||||
})
|
||||
server.on('close', done)
|
||||
server.on('listening', async function () {
|
||||
|
@ -494,11 +472,17 @@ for (const supportedVersion of mc.supportedVersions) {
|
|||
version: version.minecraftVersion,
|
||||
port: PORT
|
||||
})
|
||||
await Promise.all([once(player1, 'login'), once(player2, 'login')])
|
||||
server.writeToClients(Object.values(server.clients), 'chat', { message: JSON.stringify({ text: 'A message from the server.' }), position: 1, sender: '00000000-0000-0000-0000-000000000000' })
|
||||
await Promise.all([once(player1, 'login'), once(player2, 'login')])
|
||||
|
||||
let results = await Promise.all([ once(player1, 'chat'), once(player2, 'chat') ])
|
||||
results.forEach(res => assert.strictEqual(res[0].message, '{"text":"A message from the server."}'))
|
||||
const [event, data] = makeBroadcast(server.version, 'A message from the server.')
|
||||
|
||||
server.writeToClients(Object.values(server.clients), event, data)
|
||||
|
||||
let results = await Promise.all([OnceChatPromise(player1), OnceChatPromise(player2)])
|
||||
|
||||
for (const msg of results) {
|
||||
assert.strictEqual(msg, '{"text":"A message from the server."}')
|
||||
}
|
||||
|
||||
player1.end()
|
||||
player2.end()
|
||||
|
|
Loading…
Reference in a new issue