diff --git a/README.md b/README.md index 65ec6468a..f59ee7d65 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,8 @@ Usability and performance are key focuses of discord.js, and it also has nearly Without voice support: `npm install discord.js --save` With voice support ([node-opus](https://www.npmjs.com/package/node-opus)): `npm install discord.js node-opus --save` With voice support ([opusscript](https://www.npmjs.com/package/opusscript)): `npm install discord.js opusscript --save` -With fast websockets ([uws](https://www.npmjs.com/package/uws)) `npm install discord.js uws --save` +With a fast websocket client ([uws](https://www.npmjs.com/package/uws)) `npm install discord.js uws --save` +With fast websocket encoding ([erlpack](https://github.com/hammerandchisel/erlpack)) `npm install disscord.js hammerandchisel/erlpack --save` The preferred audio engine is node-opus, as it performs significantly better than opusscript. When both are available, discord.js will automatically choose node-opus. Using opusscript is only recommended for development environments where node-opus is tough to get working. diff --git a/package.json b/package.json index 7bc11e090..d0d827327 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "ws": "^1.1.1" }, "peerDependencies": { + "erlpack": "github:hammerandchisel/erlpack", "node-opus": "^0.2.0", "opusscript": "^0.0.1", "uws": "^0.11.1" @@ -58,6 +59,7 @@ "browser": { "ws": false, "uws": false, + "erlpack": false, "opusscript": false, "node-opus": false, "tweet-nacl": false, diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index cfa35eea4..160a07106 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -38,7 +38,7 @@ class RESTMethods { getGateway() { return this.rest.makeRequest('get', Constants.Endpoints.gateway, true).then(res => { - this.rest.client.ws.gateway = `${res.url}/?encoding=json&v=${Constants.PROTOCOL_VERSION}`; + this.rest.client.ws.gateway = `${res.url}/?v=${Constants.PROTOCOL_VERSION}`; return this.rest.client.ws.gateway; }); } diff --git a/src/client/websocket/WebSocketManager.js b/src/client/websocket/WebSocketManager.js index 3726dc837..4fc55bc1a 100644 --- a/src/client/websocket/WebSocketManager.js +++ b/src/client/websocket/WebSocketManager.js @@ -1,6 +1,7 @@ const browser = typeof window !== 'undefined'; const EventEmitter = require('events').EventEmitter; const Constants = require('../../util/Constants'); +const convertArrayBuffer = require('../../util/ConvertArrayBuffer'); const pako = require('pako'); const zlib = require('zlib'); const PacketManager = require('./packets/WebSocketPacketManager'); @@ -16,6 +17,15 @@ if (browser) { } } +let erlpack, serialize; +try { + erlpack = require('erlpack'); + serialize = erlpack.pack; +} catch (err) { + erlpack = null; + serialize = JSON.stringify; +} + /** * The WebSocket Manager of the Client * @private @@ -100,6 +110,7 @@ class WebSocketManager extends EventEmitter { } connect(gateway) { + gateway = `${gateway}&encoding=${erlpack ? 'etf' : 'json'}`; if (this.first) { this._connect(gateway); this.first = false; @@ -115,10 +126,10 @@ class WebSocketManager extends EventEmitter { */ send(data, force = false) { if (force) { - this._send(JSON.stringify(data)); + this._send(serialize(data)); return; } - this._queue.push(JSON.stringify(data)); + this._queue.push(serialize(data)); this.doQueue(); } @@ -240,9 +251,14 @@ class WebSocketManager extends EventEmitter { * @returns {Object} */ parseEventData(data) { - if (data instanceof ArrayBuffer) data = pako.inflate(data, { to: 'string' }); - else if (data instanceof Buffer) data = zlib.inflateSync(data).toString(); - return JSON.parse(data); + if (erlpack) { + if (data instanceof ArrayBuffer) data = convertArrayBuffer(data); + return erlpack.unpack(data); + } else { + if (data instanceof ArrayBuffer) data = pako.inflate(data, { to: 'string' }); + else if (data instanceof Buffer) data = zlib.inflateSync(data).toString(); + return JSON.parse(data); + } } /**