diff --git a/README.md b/README.md index 1218f51..89fab28 100644 --- a/README.md +++ b/README.md @@ -38,13 +38,15 @@ Want to contribute on something important for PrismarineJS ? go to https://githu ### Client example +Example to connect to a server in offline mode, and relay chat messages back: + ```js const bedrock = require('bedrock-protocol') const client = bedrock.createClient({ host: 'localhost', // optional port: 19132, // optional, default 19132 username: 'Notch', // the username you want to join as, optional if online mode - offline: true // optional, default false. if true, do not login with Xbox Live. You will not be asked to sign-in if set to true. + offline: true, // optional, default false. if true, do not login with Xbox Live. You will not be asked to sign-in if set to true. // Optional for some servers which verify the title ID: // authTitle: bedrock.title.MinecraftNintendoSwitch }) diff --git a/src/relay.js b/src/relay.js index 0a382b4..de09353 100644 --- a/src/relay.js +++ b/src/relay.js @@ -37,13 +37,15 @@ class RelayPlayer extends Player { // Called when we get a packet from backend server (Backend -> PROXY -> Client) readUpstream (packet) { if (!this.startRelaying) { + this.upInLog('Client not ready, queueing packet until join') this.downQ.push(packet) return } - this.upInLog('->', packet) const des = this.server.deserializer.parsePacketBuffer(packet) const name = des.data.name const params = des.data.params + this.upInLog('->', name, params) + if (name === 'play_status' && params.status === 'login_success') return // We already sent this, this needs to be sent ASAP or client will disconnect if (debugging) { // some packet encode/decode testing stuff @@ -51,31 +53,12 @@ class RelayPlayer extends Player { } this.emit('clientbound', des.data) - - // If we're sending a chunk, but player isn't yet initialized, wait until it is. - // This is wrong and should not be an issue to send chunks before the client - // is in the world; need to investigate further, but for now it's fine. - if (this.status !== 3) { - if (name === 'level_chunk') { - this.chunkSendCache.push([name, params]) - return - } - if (name === 'respawn') this.respawnPacket.push([name, params]) - } else if (this.status === 3 && this.chunkSendCache.length) { - for (const chunk of this.chunkSendCache) { - this.queue(...chunk) - } - for (const rp of this.respawnPacket) { - this.queue(...rp) - } - this.chunkSendCache = [] - this.respawnPacket = [] - } this.queue(name, params) } // Send queued packets to the connected client flushDownQueue () { + this.downOutLog('Flushing downstream queue') for (const packet of this.downQ) { const des = this.server.deserializer.parsePacketBuffer(packet) this.write(des.data.name, des.data.params) @@ -85,10 +68,11 @@ class RelayPlayer extends Player { // Send queued packets to the backend upstream server from the client flushUpQueue () { + this.upOutLog('Flushing upstream queue') for (const e of this.upQ) { // Send the queue const des = this.server.deserializer.parsePacketBuffer(e) if (des.data.name === 'client_cache_status') { // Currently broken, force off the chunk cache - this.upstream.write('client_cache_status', { enabled: false }) + // this.upstream.write('client_cache_status', { enabled: false }) } else { this.upstream.write(des.data.name, des.data.params) } @@ -127,7 +111,7 @@ class RelayPlayer extends Player { break case 'set_local_player_as_initialized': this.status = 3 - break + // falls through default: // Emit the packet as-is back to the upstream server this.downInLog('Relaying', des.data) @@ -137,6 +121,11 @@ class RelayPlayer extends Player { super.readPacket(packet) } } + + close (reason) { + this.upstream.close(reason) + super.close(reason) + } } class Relay extends Server { @@ -196,6 +185,7 @@ class Relay extends Server { this.conLog('dropping connection as single client relay', conn) conn.close() } else { + this.clientCount++ const player = new this.RelayPlayer(this, conn) this.conLog('New connection from', conn.address) this.clients[conn.address] = player diff --git a/src/server.js b/src/server.js index b10abd8..f8d3c87 100644 --- a/src/server.js +++ b/src/server.js @@ -46,7 +46,7 @@ class Server extends EventEmitter { onCloseConnection = (inetAddr, reason) => { this.conLog('close connection', inetAddr?.address, reason) delete this.clients[inetAddr]?.connection // Prevent close loop - this.clients[inetAddr]?.close() + this.clients[inetAddr?.address ?? inetAddr]?.close() delete this.clients[inetAddr] this.clientCount-- } diff --git a/src/serverPlayer.js b/src/serverPlayer.js index 7e638fe..c4d1ada 100644 --- a/src/serverPlayer.js +++ b/src/serverPlayer.js @@ -2,6 +2,7 @@ const { ClientStatus, Connection } = require('./connection') const fs = require('fs') const Options = require('./options') const debug = require('debug')('minecraft-protocol') +// const { serialize } = require('./datatypes/util') const { KeyExchange } = require('./handshake/keyExchange') const Login = require('./handshake/login') @@ -110,7 +111,7 @@ class Player extends Connection { close (reason) { if (this.status !== ClientStatus.Disconnected) { this.emit('close') // Emit close once - if (!reason) console.trace('Client closed connection', this.connection?.address) + if (!reason) this.inLog('Client closed connection', this.connection?.address) } this.q = [] this.q2 = [] @@ -130,6 +131,7 @@ class Player extends Connection { return } + // this.inLog(des.data.name, serialize(des.data.params).slice(0, 200)) switch (des.data.name) { case 'login': this.onLogin(des)