Add new raknet library option (raknet-node) (#211)

* add new raknet library option (raknet-node)

* fix lint

* fix lint & add new options

* fix lint

* fix user option & add rust-raknet test.

* fix lint.

* add raknet backend option.

* remove useNativeRaknet option.

* add not found log.

* add test timeout size.

* fix js raknet return error.

* restore useNativeRaknet option.

* update doc.

* update options handling, back compat

* fix server doc

* Fix tests

* fix tests.

* fix lint.

* delay timeout.

* Update rak.js

* update raknet-node version.

* increase timeout.

* Update vanilla.js

* Update proxy.js

* Update internal.js

* update raknet-node version.

* update rust-raknet version.

* increase timeout test time

* increase timeout test time

* update backend version.

* change timeout

Co-authored-by: extremeheat <extreme@protonmail.ch>
This commit is contained in:
b23r0 2022-08-09 15:39:27 +08:00 committed by GitHub
commit b36c55e112
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 52 additions and 42 deletions

View file

@ -19,7 +19,7 @@ Returns a `Client` instance and connects to the server.
| autoInitPlayer | *optional* | default to true, If we should send SetPlayerInitialized to the server after getting play_status spawn. |
| skipPing | *optional* | Whether pinging the server to check its version should be skipped. |
| conLog | *optional* | Where to log connection information (server join, kick messages to). Defaults to console.log, set to `null` to not log anywhere. |
| useNativeRaknet | *optional* | Whether to use the C++ version of RakNet. Set to false to use JS. |
| raknetBackend | *optional* | Specifies the raknet implementation to use. Possible options are 'raknet-native' (default, original C++ implementation), 'jsp-raknet' (JS port), and 'raknet-node' (Rust port). Please note when using the non-JS implementation you may the need approporate build tools on your system (for example a C++ or Rust compiler). |
| compressionLevel | *optional* | What zlib compression level to use, default to **7** |
| batchingInterval | *optional* | How frequently, in milliseconds to flush and write the packet queue (default: 20ms) |
| realms | *optional* | An object which should contain one of the following properties: `realmId`, `realmInvite`, `pickRealm`. When defined will attempt to join a Realm without needing to specify host/port. **The authenticated account must either own the Realm or have been invited to it** |
@ -27,6 +27,8 @@ Returns a `Client` instance and connects to the server.
| realms.realmInvite | *optional* | The invite link/code of the Realm to join. |
| realms.pickRealm | *optional* | A function which will have an array of the user Realms (joined/owned) passed to it. The function should return a Realm. |
*`useNativeRaknet` is deprecated. Setting to true will use 'raknet-native' for `raknetBackend` and setting it to false will use a JavaScript implemenation (jsp-raknet)*
The following special events are emitted by the client on top of protocol packets:
* 'status' - When the client's login sequence status has changed
* 'join' - When the client has joined the server after authenticating
@ -57,6 +59,9 @@ authenticated unless offline is set to true.
| motd | *optional* | The "message of the day" for the server, the message shown to players in the server list. See usage below. |
| advertisementFn | *optional* | optional. Custom function to call that should return a ServerAdvertisement, used for setting the RakNet server PONG data. Overrides `motd`. |
| conLog | *optional* | Where to log connection information (server join, kick messages to). Default to log only in DEBUG mode. |
| raknetBackend | *optional* | Specifies the raknet implementation to use. Possible options are 'raknet-native' (default, original C++ implementation), 'jsp-raknet' (JS port), and 'raknet-node' (Rust port). Please note when using the non-JS implementation you may the need approporate build tools on your system (for example a C++ or Rust compiler). |
*`useNativeRaknet` is deprecated. Setting to true will use 'raknet-native' for `raknetBackend` and setting it to false will use a JavaScript implemenation (jsp-raknet)*
## be.ping({ host, port }) : ServerAdvertisement

View file

@ -29,10 +29,11 @@
"prismarine-nbt": "^2.0.0",
"prismarine-realms": "^1.1.0",
"protodef": "^1.14.0",
"uuid-1345": "^1.0.2",
"raknet-native": "^1.0.3"
"raknet-native": "^1.0.3",
"uuid-1345": "^1.0.2"
},
"optionalDependencies": {
"raknet-node": "^0.4.6"
},
"devDependencies": {
"bedrock-protocol": "file:.",

View file

@ -43,7 +43,7 @@ class Client extends Connection {
Login(this, null, this.options)
LoginVerify(this, null, this.options)
const { RakClient } = initRaknet(this.options.useNativeRaknet)
const { RakClient } = initRaknet(this.options.raknetBackend)
const host = this.options.host
const port = this.options.port
this.connection = new RakClient({ useWorkers: this.options.useRaknetWorkers, host, port })
@ -67,16 +67,7 @@ class Client extends Connection {
validateOptions () {
if (!this.options.host || this.options.port == null) throw Error('Invalid host/port')
if (!Options.Versions[this.options.version]) {
console.warn('Supported versions: ', Options.Versions)
throw Error(`Unsupported version ${this.options.version}`)
}
this.options.protocolVersion = Options.Versions[this.options.version]
if (this.options.protocolVersion < Options.MIN_VERSION) {
throw new Error(`Protocol version < ${Options.MIN_VERSION} : ${this.options.protocolVersion}, too old`)
}
this.compressionLevel = this.options.compressionLevel || 7
Options.validateOptions(this.options)
}
get entityId () {

View file

@ -1,5 +1,5 @@
const { Client } = require('./client')
const { RakClient } = require('./rak')(true)
const { RakClient } = require('./rak')('raknet-native')
const { sleep } = require('./datatypes/util')
const assert = require('assert')
const Options = require('./options')

View file

@ -18,10 +18,25 @@ const defaultOptions = {
offline: false,
// Milliseconds to wait before aborting connection attempt
connectTimeout: 9000,
// Whether or not to use C++ version of RakNet
useNativeRaknet: true,
// Specifies the raknet implementation to use
raknetBackend: 'raknet-native',
// If using JS implementation of RakNet, should we use workers? (This only affects the client)
useRaknetWorkers: true
}
module.exports = { defaultOptions, MIN_VERSION, CURRENT_VERSION, Versions }
function validateOptions (options) {
if (!Versions[options.version]) {
console.warn('Supported versions', Versions)
throw Error(`Unsupported version ${options.version}`)
}
options.protocolVersion = Versions[options.version]
if (options.protocolVersion < MIN_VERSION) {
throw new Error(`Protocol version < ${MIN_VERSION} : ${options.protocolVersion}, too old`)
}
this.compressionLevel = options.compressionLevel || 7
if (options.useNativeRaknet === true) options.raknetBackend = 'raknet-native'
if (options.useNativeRaknet === false) options.raknetBackend = 'jsp-raknet'
}
module.exports = { defaultOptions, MIN_VERSION, CURRENT_VERSION, Versions, validateOptions }

View file

@ -3,21 +3,22 @@ const ConnWorker = require('./rakWorker')
const { waitFor } = require('./datatypes/util')
let Client, Server, PacketPriority, EncapsulatedPacket, PacketReliability, Reliability
class RakTimeout extends Error {};
module.exports = nativeRaknet => {
if (nativeRaknet) {
try {
({ Client, Server, PacketPriority, PacketReliability } = require('raknet-native'))
return { RakServer: RakNativeServer, RakClient: RakNativeClient, RakTimeout }
} catch (e) {
module.exports = (backend) => {
try {
if (backend === 'jsp-raknet') {
({ Client, Server, EncapsulatedPacket, Reliability } = require('jsp-raknet'))
console.debug('[raknet] native not found, using js', e)
console.debug('You can suppress the error above by disabling `useNativeRaknet` in your options')
return { RakServer: RakJsServer, RakClient: RakJsClient, RakTimeout }
}
} else {
// We need to explicitly name the require()s for bundlers
if (backend === 'raknet-node') ({ Client, Server, PacketPriority, PacketReliability } = require('raknet-node'))
if (backend === 'raknet-native') ({ Client, Server, PacketPriority, PacketReliability } = require('raknet-native'))
else ({ Client, Server, PacketPriority, PacketReliability } = require(backend))
return { RakServer: RakNativeServer, RakClient: RakNativeClient, RakTimeout }
} catch (e) {
({ Client, Server, EncapsulatedPacket, Reliability } = require('jsp-raknet'))
console.debug('[raknet] ' + backend + ' library not found, defaulting to jsp-raknet. Correct the "raknetBackend" option to avoid this error.', e)
}
return { RakServer: RakJsServer, RakClient: RakJsClient, RakTimeout }
}

View file

@ -182,6 +182,7 @@ class Relay extends Server {
port: this.options.destination.port,
onMsaCode: this.options.onMsaCode,
profilesFolder: this.options.profilesFolder,
backend: this.options.backend,
autoInitPlayer: false
}

View file

@ -12,7 +12,7 @@ class Server extends EventEmitter {
this.options = { ...Options.defaultOptions, ...options }
this.validateOptions()
this.RakServer = require('./rak')(this.options.useNativeRaknet).RakServer
this.RakServer = require('./rak')(this.options.raknetBackend).RakServer
this.serializer = createSerializer(this.options.version)
this.deserializer = createDeserializer(this.options.version)
@ -25,15 +25,7 @@ class Server extends EventEmitter {
}
validateOptions () {
if (!Options.Versions[this.options.version]) {
console.warn('Supported versions', Options.Versions)
throw Error(`Unsupported version ${this.options.version}`)
}
this.options.protocolVersion = Options.Versions[this.options.version]
if (this.options.protocolVersion < Options.MIN_VERSION) {
throw new Error(`Protocol version < ${Options.MIN_VERSION} : ${this.options.protocolVersion}, too old`)
}
this.compressionLevel = this.options.compressionLevel || 7
Options.validateOptions(this.options)
}
onOpenConnection = (conn) => {

View file

@ -1,7 +1,8 @@
const { createClient, createServer, Relay } = require('bedrock-protocol')
const { sleep, waitFor } = require('../src/datatypes/util')
function proxyTest (version, timeout = 1000 * 40) {
function proxyTest (version, raknetBackend = 'raknet-node', timeout = 1000 * 40) {
console.log('with raknet backend', raknetBackend)
return waitFor(res => {
const SERVER_PORT = 19000 + ((Math.random() * 100) | 0)
const CLIENT_PORT = 19000 + ((Math.random() * 100) | 0)
@ -9,6 +10,7 @@ function proxyTest (version, timeout = 1000 * 40) {
host: '0.0.0.0', // optional
port: SERVER_PORT, // optional
offline: true,
raknetBackend,
version // The server version
})
@ -34,14 +36,15 @@ function proxyTest (version, timeout = 1000 * 40) {
destination: {
host: '127.0.0.1',
port: SERVER_PORT
}
},
raknetBackend
})
relay.conLog = console.debug
relay.listen()
console.debug('Proxy started', server.options.version)
const client = createClient({ host: '127.0.0.1', port: CLIENT_PORT, version, username: 'Boat', offline: true })
const client = createClient({ host: '127.0.0.1', port: CLIENT_PORT, version, username: 'Boat', offline: true, raknetBackend })
console.debug('Client started')
@ -59,7 +62,7 @@ function proxyTest (version, timeout = 1000 * 40) {
}
if (!module.parent) {
proxyTest('1.16.220')
proxyTest('1.16.220', 'raknet-native')
}
module.exports = { proxyTest }

View file

@ -15,6 +15,7 @@ async function test (version) {
port: 19130,
username: 'Notch',
version,
raknetBackend: 'raknet-node',
offline: true
})