From a53a2977f2cd458db86387b1e5016e8a877247bf Mon Sep 17 00:00:00 2001 From: deathcap Date: Sun, 24 Jan 2016 18:53:34 -0800 Subject: [PATCH 01/25] Add dynamic cross-protocol support --- doc/README.md | 5 +++ examples/client_auto/client_auto.js | 31 ++++++++++++++ examples/client_auto/package.json | 8 ++++ src/createClientAuto.js | 64 +++++++++++++++++++++++++++++ src/index.js | 2 + 5 files changed, 110 insertions(+) create mode 100644 examples/client_auto/client_auto.js create mode 100644 examples/client_auto/package.json create mode 100644 src/createClientAuto.js diff --git a/doc/README.md b/doc/README.md index daca5a1..c109899 100644 --- a/doc/README.md +++ b/doc/README.md @@ -75,6 +75,11 @@ Returns a `Client` instance and perform login. * checkTimeoutInterval : default to `10*1000` (10s), check if keepalive received at that period, disconnect otherwise. * version : 1.8 or 1.9 : default to 1.8 +## mc.createClientAuto(options, cb) + +Pings the server and attempts to call `createClient(options)` with the appropriate protocol version. +When created, calls the callback `cb(err, client)`. + ## mc.Client(isServer,version) Create a new client, if `isServer` is true then it is a server-side client, otherwise it's a client-side client. diff --git a/examples/client_auto/client_auto.js b/examples/client_auto/client_auto.js new file mode 100644 index 0000000..0af381f --- /dev/null +++ b/examples/client_auto/client_auto.js @@ -0,0 +1,31 @@ +var mc = require('minecraft-protocol'); + +if(process.argv.length < 4 || process.argv.length > 6) { + console.log("Usage : node echo.js [] []"); + process.exit(1); +} + +mc.createClientAuto({ + host: process.argv[2], + port: parseInt(process.argv[3]), + username: process.argv[4] ? process.argv[4] : "echo", + password: process.argv[5] +}, function(err, client) { + if (err) throw err; + + client.on('connect', function() { + console.info('connected'); + }); + client.on('disconnect', function(packet) { + console.log('disconnected: '+ packet.reason); + }); + client.on('chat', function(packet) { + var jsonMsg = JSON.parse(packet.message); + if(jsonMsg.translate == 'chat.type.announcement' || jsonMsg.translate == 'chat.type.text') { + var username = jsonMsg.with[0].text; + var msg = jsonMsg.with[1]; + if(username === client.username) return; + client.write('chat', {message: msg}); + } + }); +}); diff --git a/examples/client_auto/package.json b/examples/client_auto/package.json new file mode 100644 index 0000000..56fcdf2 --- /dev/null +++ b/examples/client_auto/package.json @@ -0,0 +1,8 @@ +{ + "name": "node-minecraft-protocol-example", + "version": "0.0.0", + "private": true, + "dependencies": { + }, + "description": "A node-minecraft-protocol example" +} diff --git a/src/createClientAuto.js b/src/createClientAuto.js new file mode 100644 index 0000000..209fe36 --- /dev/null +++ b/src/createClientAuto.js @@ -0,0 +1,64 @@ +'use strict'; + +var ping = require('./ping'); +var assert = require('assert'); +var debug = require('./debug'); +var createClient = require('./createClient'); + +// see http://wiki.vg/Protocol_version_numbers +// Get the minecraft-data version string for a protocol version +// TODO: switch to using https://github.com/PrismarineJS/minecraft-data/pull/92 +function protocol2version(n) { + if (n >= 48) return '1.9'; // 1.9 snapshots (15w+), 16w03a is 96 + if (n >= 6 && n <= 47) return '1.8.9'; // including 1.8 snapshots (14w) + if (n >= 4 && n <= 5) return '1.7.10'; // including 1.7 prereleases + // TODO: earlier versions "Beginning with the 1.7.1 pre-release (and release 1.7.2), versioning was reset." + throw new Error(`unsupported/unknown protocol version: ${versionProtocol}, update protocol2version`); +} + +function createClientAsync(options, cb) { + assert.ok(options, 'options is required'); + + debug('pinging',options.host); + // TODO: refactor with DNS SRV lookup in NMP + // TODO: detect ping timeout, https://github.com/PrismarineJS/node-minecraft-protocol/issues/329 + ping(options, function(err, response) { + var client; + + if (err) return cb(err, null); + debug('ping response',response); + // TODO: could also use ping pre-connect to save description, type, negotiate protocol etc. + // ^ see https://github.com/PrismarineJS/node-minecraft-protocol/issues/327 + var motd = response.description; + debug('Server description:',motd); // TODO: save + + // Pass server-reported version to protocol handler + // The version string is interpereted by https://github.com/PrismarineJS/node-minecraft-data + var versionName = response.version.name; // 1.8.9, 1.7.10 + var versionProtocol = response.version.protocol;// 47, 5 + + debug(`Server version: ${versionName}, protocol: ${versionProtocol}`); + // Note that versionName is a descriptive version stirng like '1.8.9' on vailla, but other + // servers add their own name (Spigot 1.8.8, Glowstone++ 1.8.9) so we cannot use it directly, + // even though it is in a format accepted by minecraft-data. Instead, translate the protocol. + options.version = protocol2version(versionProtocol); + + // Use the exact same protocol version + // Requires https://github.com/PrismarineJS/node-minecraft-protocol/pull/330 + options.protocolVersion = versionProtocol; + + if (response.modinfo && response.modinfo.type === 'FML') { + // Use the list of Forge mods from the server ping, so client will match server + var forgeMods = response.modinfo.modList; + debug('Using forgeMods:',forgeMods); + // TODO: https://github.com/PrismarineJS/node-minecraft-protocol/issues/114 + // https://github.com/PrismarineJS/node-minecraft-protocol/pull/326 + throw new Error('FML/Forge not yet supported'); + } else { + client = createClient(options); // vanilla + } + cb(null, client); + }); +} + +module.exports = createClientAsync; diff --git a/src/index.js b/src/index.js index 8d90027..697c657 100644 --- a/src/index.js +++ b/src/index.js @@ -2,10 +2,12 @@ var Client = require('./client'); var Server = require('./server'); var serializer = require("./transforms/serializer"); var createClient = require("./createClient"); +var createClientAuto = require("./createClientAuto"); var createServer = require("./createServer"); module.exports = { createClient: createClient, + createClientAuto: createClientAuto, createServer: createServer, Client: Client, Server: Server, From 9ec6d876ba386c2a33ce197f54f6d900c0e80c97 Mon Sep 17 00:00:00 2001 From: deathcap Date: Thu, 28 Jan 2016 09:49:35 -0800 Subject: [PATCH 02/25] Add wait_connect option, to require 'connect_allowed' event before src/client/setProtocol proceeds Intended to allow clients to configure the client object before any data is sent, specifically, before src/client/setProtocol sends the set_protocol packet. --- src/client/setProtocol.js | 10 ++++++++-- src/createClientAuto.js | 12 ++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/client/setProtocol.js b/src/client/setProtocol.js index 865b44e..4948b1c 100644 --- a/src/client/setProtocol.js +++ b/src/client/setProtocol.js @@ -5,6 +5,14 @@ module.exports = function(client, options) { client.on('connect', onConnect); function onConnect() { + if (options.wait_connect) { + client.on('connect_allowed', next); + } else { + next(); + } + } + + function next() { client.write('set_protocol', { protocolVersion: options.protocolVersion, serverHost: options.host, @@ -16,6 +24,4 @@ module.exports = function(client, options) { username: client.username }); } - - } diff --git a/src/createClientAuto.js b/src/createClientAuto.js index 209fe36..62f7e29 100644 --- a/src/createClientAuto.js +++ b/src/createClientAuto.js @@ -19,6 +19,9 @@ function protocol2version(n) { function createClientAsync(options, cb) { assert.ok(options, 'options is required'); + debug('creating client'); + options.wait_connect = true; // don't let createClient / src/client/setProtocol proceed on socket 'connect' until 'connect_allowed' + var client = createClient(options); // vanilla debug('pinging',options.host); // TODO: refactor with DNS SRV lookup in NMP // TODO: detect ping timeout, https://github.com/PrismarineJS/node-minecraft-protocol/issues/329 @@ -41,10 +44,12 @@ function createClientAsync(options, cb) { // Note that versionName is a descriptive version stirng like '1.8.9' on vailla, but other // servers add their own name (Spigot 1.8.8, Glowstone++ 1.8.9) so we cannot use it directly, // even though it is in a format accepted by minecraft-data. Instead, translate the protocol. + //XXX TODO: modify client object options.version = protocol2version(versionProtocol); // Use the exact same protocol version // Requires https://github.com/PrismarineJS/node-minecraft-protocol/pull/330 + //XXX TODO: modify client objecti options.protocolVersion = versionProtocol; if (response.modinfo && response.modinfo.type === 'FML') { @@ -53,10 +58,13 @@ function createClientAsync(options, cb) { debug('Using forgeMods:',forgeMods); // TODO: https://github.com/PrismarineJS/node-minecraft-protocol/issues/114 // https://github.com/PrismarineJS/node-minecraft-protocol/pull/326 + // TODO: modify client object to set forgeMods and enable forgeHandshake throw new Error('FML/Forge not yet supported'); - } else { - client = createClient(options); // vanilla } + // done configuring client object, let connection proceed + client.emit('connect_allowed'); + + cb(null, client); }); } From 00bf6acea9452288e00714453a9918eaeaf4c068 Mon Sep 17 00:00:00 2001 From: deathcap Date: Sat, 30 Jan 2016 22:09:25 -0800 Subject: [PATCH 03/25] Fix unintentional var client declaration --- src/createClientAuto.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/createClientAuto.js b/src/createClientAuto.js index 62f7e29..dc9fbd1 100644 --- a/src/createClientAuto.js +++ b/src/createClientAuto.js @@ -26,8 +26,6 @@ function createClientAsync(options, cb) { // TODO: refactor with DNS SRV lookup in NMP // TODO: detect ping timeout, https://github.com/PrismarineJS/node-minecraft-protocol/issues/329 ping(options, function(err, response) { - var client; - if (err) return cb(err, null); debug('ping response',response); // TODO: could also use ping pre-connect to save description, type, negotiate protocol etc. From 66e6f4dd0b2549707398a2ea32675776ec5c330a Mon Sep 17 00:00:00 2001 From: deathcap Date: Sat, 30 Jan 2016 22:14:13 -0800 Subject: [PATCH 04/25] Update to use compatible sync API (createClient) --- doc/README.md | 3 +-- examples/client_auto/client_auto.js | 36 ++++++++++++++--------------- src/createClientAuto.js | 10 ++++---- 3 files changed, 22 insertions(+), 27 deletions(-) diff --git a/doc/README.md b/doc/README.md index c109899..68b54b7 100644 --- a/doc/README.md +++ b/doc/README.md @@ -75,10 +75,9 @@ Returns a `Client` instance and perform login. * checkTimeoutInterval : default to `10*1000` (10s), check if keepalive received at that period, disconnect otherwise. * version : 1.8 or 1.9 : default to 1.8 -## mc.createClientAuto(options, cb) +## mc.createClientAuto(options) Pings the server and attempts to call `createClient(options)` with the appropriate protocol version. -When created, calls the callback `cb(err, client)`. ## mc.Client(isServer,version) diff --git a/examples/client_auto/client_auto.js b/examples/client_auto/client_auto.js index 0af381f..99701ae 100644 --- a/examples/client_auto/client_auto.js +++ b/examples/client_auto/client_auto.js @@ -5,27 +5,25 @@ if(process.argv.length < 4 || process.argv.length > 6) { process.exit(1); } -mc.createClientAuto({ +var client = mc.createClientAuto({ host: process.argv[2], port: parseInt(process.argv[3]), username: process.argv[4] ? process.argv[4] : "echo", password: process.argv[5] -}, function(err, client) { - if (err) throw err; - - client.on('connect', function() { - console.info('connected'); - }); - client.on('disconnect', function(packet) { - console.log('disconnected: '+ packet.reason); - }); - client.on('chat', function(packet) { - var jsonMsg = JSON.parse(packet.message); - if(jsonMsg.translate == 'chat.type.announcement' || jsonMsg.translate == 'chat.type.text') { - var username = jsonMsg.with[0].text; - var msg = jsonMsg.with[1]; - if(username === client.username) return; - client.write('chat', {message: msg}); - } - }); +}); + +client.on('connect', function() { + console.info('connected'); +}); +client.on('disconnect', function(packet) { + console.log('disconnected: '+ packet.reason); +}); +client.on('chat', function(packet) { + var jsonMsg = JSON.parse(packet.message); + if(jsonMsg.translate == 'chat.type.announcement' || jsonMsg.translate == 'chat.type.text') { + var username = jsonMsg.with[0].text; + var msg = jsonMsg.with[1]; + if(username === client.username) return; + client.write('chat', {message: msg}); + } }); diff --git a/src/createClientAuto.js b/src/createClientAuto.js index dc9fbd1..95c5ab6 100644 --- a/src/createClientAuto.js +++ b/src/createClientAuto.js @@ -16,7 +16,7 @@ function protocol2version(n) { throw new Error(`unsupported/unknown protocol version: ${versionProtocol}, update protocol2version`); } -function createClientAsync(options, cb) { +function createClientAuto(options) { assert.ok(options, 'options is required'); debug('creating client'); @@ -26,7 +26,7 @@ function createClientAsync(options, cb) { // TODO: refactor with DNS SRV lookup in NMP // TODO: detect ping timeout, https://github.com/PrismarineJS/node-minecraft-protocol/issues/329 ping(options, function(err, response) { - if (err) return cb(err, null); + if (err) throw err; // hmm debug('ping response',response); // TODO: could also use ping pre-connect to save description, type, negotiate protocol etc. // ^ see https://github.com/PrismarineJS/node-minecraft-protocol/issues/327 @@ -61,10 +61,8 @@ function createClientAsync(options, cb) { } // done configuring client object, let connection proceed client.emit('connect_allowed'); - - - cb(null, client); }); + return client; } -module.exports = createClientAsync; +module.exports = createClientAuto; From 89198c62ff2826057fda8858d814117e1b305e98 Mon Sep 17 00:00:00 2001 From: deathcap Date: Sat, 30 Jan 2016 22:27:36 -0800 Subject: [PATCH 05/25] Use minecraft-data for protocol version -> minecraft version --- src/createClientAuto.js | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/createClientAuto.js b/src/createClientAuto.js index 95c5ab6..509d72c 100644 --- a/src/createClientAuto.js +++ b/src/createClientAuto.js @@ -4,16 +4,21 @@ var ping = require('./ping'); var assert = require('assert'); var debug = require('./debug'); var createClient = require('./createClient'); +var minecraft_data = require('minecraft-data'); -// see http://wiki.vg/Protocol_version_numbers // Get the minecraft-data version string for a protocol version -// TODO: switch to using https://github.com/PrismarineJS/minecraft-data/pull/92 -function protocol2version(n) { - if (n >= 48) return '1.9'; // 1.9 snapshots (15w+), 16w03a is 96 - if (n >= 6 && n <= 47) return '1.8.9'; // including 1.8 snapshots (14w) - if (n >= 4 && n <= 5) return '1.7.10'; // including 1.7 prereleases - // TODO: earlier versions "Beginning with the 1.7.1 pre-release (and release 1.7.2), versioning was reset." - throw new Error(`unsupported/unknown protocol version: ${versionProtocol}, update protocol2version`); +// TODO: add to node-minecraft-data index (protocol to newest release, if multiple) +function protocolVersion2MinecraftVersion(n) { + var usesNetty = n > 0; + for (var i = 0; i < minecraft_data.versions.length; ++i) { + var version = minecraft_data.versions[i]; + if (version.version === Math.abs(n) && version.usesNetty === usesNetty) { + console.log(version); + return version.minecraftVersion; + } + } + + throw new Error(`unsupported/unknown protocol version: ${n}, update minecraft-data`); } function createClientAuto(options) { @@ -35,20 +40,20 @@ function createClientAuto(options) { // Pass server-reported version to protocol handler // The version string is interpereted by https://github.com/PrismarineJS/node-minecraft-data - var versionName = response.version.name; // 1.8.9, 1.7.10 - var versionProtocol = response.version.protocol;// 47, 5 + var minecraftVersion = response.version.name; // 1.8.9, 1.7.10 + var protocolVersion = response.version.protocol;// 47, 5 - debug(`Server version: ${versionName}, protocol: ${versionProtocol}`); + debug(`Server version: ${minecraftVersion}, protocol: ${protocolVersion}`); // Note that versionName is a descriptive version stirng like '1.8.9' on vailla, but other // servers add their own name (Spigot 1.8.8, Glowstone++ 1.8.9) so we cannot use it directly, // even though it is in a format accepted by minecraft-data. Instead, translate the protocol. //XXX TODO: modify client object - options.version = protocol2version(versionProtocol); + options.version = protocolVersion2MinecraftVersion(protocolVersion); // Use the exact same protocol version // Requires https://github.com/PrismarineJS/node-minecraft-protocol/pull/330 //XXX TODO: modify client objecti - options.protocolVersion = versionProtocol; + options.protocolVersion = protocolVersion; if (response.modinfo && response.modinfo.type === 'FML') { // Use the list of Forge mods from the server ping, so client will match server From ea3b306988e1ab9995013e48f4e384fc00a0a001 Mon Sep 17 00:00:00 2001 From: deathcap Date: Sat, 30 Jan 2016 22:31:10 -0800 Subject: [PATCH 06/25] Move options to client object This allows client plugins to change the options on the client object, and have it reflected in other plugins. Previously, had to rely on the options being the same object, and hold a reference to it. Now it is always accessible as `client.options`. --- src/client/caseCorrect.js | 3 ++- src/client/compress.js | 2 +- src/client/encrypt.js | 3 ++- src/client/keepalive.js | 3 ++- src/client/play.js | 2 +- src/client/setProtocol.js | 3 ++- src/client/tcp_dns.js | 3 ++- src/createClient.js | 15 ++++++++------- src/createClientAuto.js | 6 ++---- src/ping.js | 3 ++- 10 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/client/caseCorrect.js b/src/client/caseCorrect.js index 2eb634a..e8a42d8 100644 --- a/src/client/caseCorrect.js +++ b/src/client/caseCorrect.js @@ -1,7 +1,8 @@ var yggdrasil = require('yggdrasil')({}); var UUID = require('uuid-1345'); -module.exports = function(client, options) { +module.exports = function(client) { + var options = client.options; var clientToken = options.clientToken || UUID.v4().toString(); options.accessToken = null; options.haveCredentials = options.password != null || (clientToken != null && options.session != null); diff --git a/src/client/compress.js b/src/client/compress.js index cebe34f..40d092f 100644 --- a/src/client/compress.js +++ b/src/client/compress.js @@ -1,4 +1,4 @@ -module.exports = function(client, options) { +module.exports = function(client) { client.once("compress", onCompressionRequest); client.on("set_compression", onCompressionRequest); diff --git a/src/client/encrypt.js b/src/client/encrypt.js index 696ddfc..10b391c 100644 --- a/src/client/encrypt.js +++ b/src/client/encrypt.js @@ -3,7 +3,8 @@ var yggserver = require('yggdrasil').server({}); var ursa=require("../ursa"); var debug = require("../debug"); -module.exports = function(client, options) { +module.exports = function(client) { + var options = client.options; client.once('encryption_begin', onEncryptionKeyRequest); function onEncryptionKeyRequest(packet) { diff --git a/src/client/keepalive.js b/src/client/keepalive.js index 3fc817b..5b206cf 100644 --- a/src/client/keepalive.js +++ b/src/client/keepalive.js @@ -1,4 +1,5 @@ -module.exports = function(client, options) { +module.exports = function(client) { + var options = client.options; var keepAlive = options.keepAlive == null ? true : options.keepAlive; if (!keepAlive) return; diff --git a/src/client/play.js b/src/client/play.js index ebc491e..efcf84b 100644 --- a/src/client/play.js +++ b/src/client/play.js @@ -1,6 +1,6 @@ var states = require("../states"); -module.exports = function(client, options) { +module.exports = function(client) { client.once('success', onLogin); function onLogin(packet) { diff --git a/src/client/setProtocol.js b/src/client/setProtocol.js index 4948b1c..0c5b7db 100644 --- a/src/client/setProtocol.js +++ b/src/client/setProtocol.js @@ -1,7 +1,8 @@ var states = require("../states"); -module.exports = function(client, options) { +module.exports = function(client) { + var options = client.options; client.on('connect', onConnect); function onConnect() { diff --git a/src/client/tcp_dns.js b/src/client/tcp_dns.js index a8e3060..2863962 100644 --- a/src/client/tcp_dns.js +++ b/src/client/tcp_dns.js @@ -1,7 +1,8 @@ var net = require('net'); var dns = require('dns'); -module.exports = function(client, options) { +module.exports = function(client) { + var options = client.options; options.port = options.port || 25565; options.host = options.host || 'localhost'; diff --git a/src/createClient.js b/src/createClient.js index 40a3d13..5d7c342 100644 --- a/src/createClient.js +++ b/src/createClient.js @@ -22,14 +22,15 @@ function createClient(options) { options.protocolVersion = version.version; var client = new Client(false, options.majorVersion); + client.options = options; - tcp_dns(client, options); - setProtocol(client, options); - keepalive(client, options); - encrypt(client, options); - play(client, options); - compress(client, options); - caseCorrect(client, options); + tcp_dns(client); + setProtocol(client); + keepalive(client); + encrypt(client); + play(client); + compress(client); + caseCorrect(client); return client; } diff --git a/src/createClientAuto.js b/src/createClientAuto.js index 509d72c..b307157 100644 --- a/src/createClientAuto.js +++ b/src/createClientAuto.js @@ -47,13 +47,11 @@ function createClientAuto(options) { // Note that versionName is a descriptive version stirng like '1.8.9' on vailla, but other // servers add their own name (Spigot 1.8.8, Glowstone++ 1.8.9) so we cannot use it directly, // even though it is in a format accepted by minecraft-data. Instead, translate the protocol. - //XXX TODO: modify client object - options.version = protocolVersion2MinecraftVersion(protocolVersion); + client.options.version = protocolVersion2MinecraftVersion(protocolVersion); // Use the exact same protocol version // Requires https://github.com/PrismarineJS/node-minecraft-protocol/pull/330 - //XXX TODO: modify client objecti - options.protocolVersion = protocolVersion; + client.options.protocolVersion = protocolVersion; if (response.modinfo && response.modinfo.type === 'FML') { // Use the list of Forge mods from the server ping, so client will match server diff --git a/src/ping.js b/src/ping.js index 4a58353..1e6adcb 100644 --- a/src/ping.js +++ b/src/ping.js @@ -15,6 +15,7 @@ function ping(options, cb) { options.protocolVersion = version.version; var client = new Client(false,options.majorVersion); + client.options = options; client.on('error', function(err) { cb(err); }); @@ -46,6 +47,6 @@ function ping(options, cb) { client.state = states.STATUS; }); - tcp_dns(client, options); + tcp_dns(client); options.connect(client); } From af62189e19791808f737ba4322c26f999bf792ac Mon Sep 17 00:00:00 2001 From: deathcap Date: Sat, 30 Jan 2016 22:34:26 -0800 Subject: [PATCH 07/25] Rename src/createClientAuto.js -> src/client/autoVersion.js --- src/{createClientAuto.js => client/autoVersion.js} | 1 - 1 file changed, 1 deletion(-) rename src/{createClientAuto.js => client/autoVersion.js} (98%) diff --git a/src/createClientAuto.js b/src/client/autoVersion.js similarity index 98% rename from src/createClientAuto.js rename to src/client/autoVersion.js index b307157..b88463f 100644 --- a/src/createClientAuto.js +++ b/src/client/autoVersion.js @@ -28,7 +28,6 @@ function createClientAuto(options) { options.wait_connect = true; // don't let createClient / src/client/setProtocol proceed on socket 'connect' until 'connect_allowed' var client = createClient(options); // vanilla debug('pinging',options.host); - // TODO: refactor with DNS SRV lookup in NMP // TODO: detect ping timeout, https://github.com/PrismarineJS/node-minecraft-protocol/issues/329 ping(options, function(err, response) { if (err) throw err; // hmm From 163e2157fc6d0d513396a877164c1dff9b6c82e9 Mon Sep 17 00:00:00 2001 From: deathcap Date: Sat, 30 Jan 2016 22:49:57 -0800 Subject: [PATCH 08/25] Remove useless statement --- src/client.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client.js b/src/client.js index 8a0a129..356ab53 100644 --- a/src/client.js +++ b/src/client.js @@ -25,7 +25,6 @@ class Client extends EventEmitter this.decompressor=null; this.deserializer; this.isServer; - this.version; this.protocolState=states.HANDSHAKING; this.ended=true; this.latency=0; From 9a68fd6c34fc99f3dcf20f8582fe482609d28dba Mon Sep 17 00:00:00 2001 From: deathcap Date: Sat, 30 Jan 2016 22:50:24 -0800 Subject: [PATCH 09/25] Support options.version==false in createClient() to auto-detect version --- examples/client_auto/client_auto.js | 2 +- src/client/autoVersion.js | 24 +++++++++++++----------- src/createClient.js | 6 +++++- src/index.js | 2 -- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/examples/client_auto/client_auto.js b/examples/client_auto/client_auto.js index 99701ae..fdc586d 100644 --- a/examples/client_auto/client_auto.js +++ b/examples/client_auto/client_auto.js @@ -5,7 +5,7 @@ if(process.argv.length < 4 || process.argv.length > 6) { process.exit(1); } -var client = mc.createClientAuto({ +var client = mc.createClient({version: false, host: process.argv[2], port: parseInt(process.argv[3]), username: process.argv[4] ? process.argv[4] : "echo", diff --git a/src/client/autoVersion.js b/src/client/autoVersion.js index b88463f..83cae2c 100644 --- a/src/client/autoVersion.js +++ b/src/client/autoVersion.js @@ -1,9 +1,9 @@ 'use strict'; -var ping = require('./ping'); +var ping = require('../ping'); +var debug = require('../debug'); +var states = require('../states'); var assert = require('assert'); -var debug = require('./debug'); -var createClient = require('./createClient'); var minecraft_data = require('minecraft-data'); // Get the minecraft-data version string for a protocol version @@ -14,19 +14,18 @@ function protocolVersion2MinecraftVersion(n) { var version = minecraft_data.versions[i]; if (version.version === Math.abs(n) && version.usesNetty === usesNetty) { console.log(version); - return version.minecraftVersion; + return [version.minecraftVersion, version.majorVersion]; } } throw new Error(`unsupported/unknown protocol version: ${n}, update minecraft-data`); } -function createClientAuto(options) { - assert.ok(options, 'options is required'); +module.exports = function(client) { + var options = client.options; debug('creating client'); - options.wait_connect = true; // don't let createClient / src/client/setProtocol proceed on socket 'connect' until 'connect_allowed' - var client = createClient(options); // vanilla + options.wait_connect = true; // don't let src/client/setProtocol proceed on socket 'connect' until 'connect_allowed' debug('pinging',options.host); // TODO: detect ping timeout, https://github.com/PrismarineJS/node-minecraft-protocol/issues/329 ping(options, function(err, response) { @@ -46,12 +45,17 @@ function createClientAuto(options) { // Note that versionName is a descriptive version stirng like '1.8.9' on vailla, but other // servers add their own name (Spigot 1.8.8, Glowstone++ 1.8.9) so we cannot use it directly, // even though it is in a format accepted by minecraft-data. Instead, translate the protocol. - client.options.version = protocolVersion2MinecraftVersion(protocolVersion); + var [minecraftVersion, majorVersion] = protocolVersion2MinecraftVersion(protocolVersion); + client.options.version = minecraftVersion; // Use the exact same protocol version // Requires https://github.com/PrismarineJS/node-minecraft-protocol/pull/330 client.options.protocolVersion = protocolVersion; + // reinitialize client object with new version TODO: move out of its constructor + client.version = majorVersion; + client.setSerializer(states.HANDSHAKING); + if (response.modinfo && response.modinfo.type === 'FML') { // Use the list of Forge mods from the server ping, so client will match server var forgeMods = response.modinfo.modList; @@ -66,5 +70,3 @@ function createClientAuto(options) { }); return client; } - -module.exports = createClientAuto; diff --git a/src/createClient.js b/src/createClient.js index 5d7c342..0a68c7c 100644 --- a/src/createClient.js +++ b/src/createClient.js @@ -8,6 +8,7 @@ var caseCorrect = require('./client/caseCorrect'); var setProtocol = require('./client/setProtocol'); var play = require('./client/play'); var tcp_dns = require('./client/tcp_dns'); +var autoVersion = require('./client/autoVersion'); module.exports=createClient; @@ -15,8 +16,10 @@ function createClient(options) { assert.ok(options, "options is required"); assert.ok(options.username, "username is required"); + // TODO: avoid setting default version if autoVersion is enabled var optVersion = options.version || require("./version").defaultVersion; var mcData=require("minecraft-data")(optVersion); + if (!mcData) throw new Error(`unsupported protocol version: ${optVersion}`); var version = mcData.version; options.majorVersion = version.majorVersion; options.protocolVersion = version.version; @@ -25,12 +28,13 @@ function createClient(options) { client.options = options; tcp_dns(client); + caseCorrect(client); + if (options.version === false) autoVersion(client); setProtocol(client); keepalive(client); encrypt(client); play(client); compress(client); - caseCorrect(client); return client; } diff --git a/src/index.js b/src/index.js index 697c657..8d90027 100644 --- a/src/index.js +++ b/src/index.js @@ -2,12 +2,10 @@ var Client = require('./client'); var Server = require('./server'); var serializer = require("./transforms/serializer"); var createClient = require("./createClient"); -var createClientAuto = require("./createClientAuto"); var createServer = require("./createServer"); module.exports = { createClient: createClient, - createClientAuto: createClientAuto, createServer: createServer, Client: Client, Server: Server, From d0f64e9c65c9d03ab13d2cb33d17e5f4f61b9816 Mon Sep 17 00:00:00 2001 From: deathcap Date: Sun, 31 Jan 2016 12:20:51 -0800 Subject: [PATCH 10/25] Set state property instead of setSerializer() to ensure serializers are properly piped --- src/client/autoVersion.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/autoVersion.js b/src/client/autoVersion.js index 83cae2c..86e3d6a 100644 --- a/src/client/autoVersion.js +++ b/src/client/autoVersion.js @@ -54,7 +54,7 @@ module.exports = function(client) { // reinitialize client object with new version TODO: move out of its constructor client.version = majorVersion; - client.setSerializer(states.HANDSHAKING); + client.state = states.HANDSHAKING; if (response.modinfo && response.modinfo.type === 'FML') { // Use the list of Forge mods from the server ping, so client will match server From f17de6410b34b6f6bd8bbea7953130e9eee26c97 Mon Sep 17 00:00:00 2001 From: deathcap Date: Sun, 31 Jan 2016 12:26:03 -0800 Subject: [PATCH 11/25] Use new object for ping() to avoid potential cross-contamination --- src/client/autoVersion.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client/autoVersion.js b/src/client/autoVersion.js index 86e3d6a..5a41b2b 100644 --- a/src/client/autoVersion.js +++ b/src/client/autoVersion.js @@ -24,11 +24,11 @@ function protocolVersion2MinecraftVersion(n) { module.exports = function(client) { var options = client.options; - debug('creating client'); options.wait_connect = true; // don't let src/client/setProtocol proceed on socket 'connect' until 'connect_allowed' debug('pinging',options.host); - // TODO: detect ping timeout, https://github.com/PrismarineJS/node-minecraft-protocol/issues/329 - ping(options, function(err, response) { + var pingOptions = {host: options.host, port: options.port}; + // TODO: use 0xfe ping instead for better compatibility/performance? https://github.com/deathcap/node-minecraft-ping + ping(pingOptions, function(err, response) { if (err) throw err; // hmm debug('ping response',response); // TODO: could also use ping pre-connect to save description, type, negotiate protocol etc. From 2e2a213076e284d2ce7e76578b75843936077f69 Mon Sep 17 00:00:00 2001 From: deathcap Date: Sun, 31 Jan 2016 12:28:25 -0800 Subject: [PATCH 12/25] Update client connect() for options move compatibility --- src/client.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/client.js b/src/client.js index 356ab53..8668f62 100644 --- a/src/client.js +++ b/src/client.js @@ -218,6 +218,7 @@ class Client extends EventEmitter // TCP/IP-specific (not generic Stream) method for backwards-compatibility connect(port, host) { var options = {port, host}; + if (!this.options) this.options = options; require('./client/tcp_dns')(this, options); options.connect(this); } From 88e8374ad43955905143a54e7a54e91099067528 Mon Sep 17 00:00:00 2001 From: deathcap Date: Sun, 31 Jan 2016 12:44:06 -0800 Subject: [PATCH 13/25] Update documentation for version:false option --- doc/README.md | 6 +----- src/client/autoVersion.js | 10 +++------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/doc/README.md b/doc/README.md index 68b54b7..f87a864 100644 --- a/doc/README.md +++ b/doc/README.md @@ -73,11 +73,7 @@ Returns a `Client` instance and perform login. * accessToken : generated if a password is given * keepAlive : send keep alive packets : default to true * checkTimeoutInterval : default to `10*1000` (10s), check if keepalive received at that period, disconnect otherwise. - * version : 1.8 or 1.9 : default to 1.8 - -## mc.createClientAuto(options) - -Pings the server and attempts to call `createClient(options)` with the appropriate protocol version. + * version : 1.8 or 1.9 or false (to auto-negotiate): default to 1.8 ## mc.Client(isServer,version) diff --git a/src/client/autoVersion.js b/src/client/autoVersion.js index 5a41b2b..6d58a87 100644 --- a/src/client/autoVersion.js +++ b/src/client/autoVersion.js @@ -31,8 +31,7 @@ module.exports = function(client) { ping(pingOptions, function(err, response) { if (err) throw err; // hmm debug('ping response',response); - // TODO: could also use ping pre-connect to save description, type, negotiate protocol etc. - // ^ see https://github.com/PrismarineJS/node-minecraft-protocol/issues/327 + // TODO: could also use ping pre-connect to save description, type, max players, etc. var motd = response.description; debug('Server description:',motd); // TODO: save @@ -47,12 +46,9 @@ module.exports = function(client) { // even though it is in a format accepted by minecraft-data. Instead, translate the protocol. var [minecraftVersion, majorVersion] = protocolVersion2MinecraftVersion(protocolVersion); client.options.version = minecraftVersion; - - // Use the exact same protocol version - // Requires https://github.com/PrismarineJS/node-minecraft-protocol/pull/330 client.options.protocolVersion = protocolVersion; - // reinitialize client object with new version TODO: move out of its constructor + // Reinitialize client object with new version TODO: move out of its constructor? client.version = majorVersion; client.state = states.HANDSHAKING; @@ -65,7 +61,7 @@ module.exports = function(client) { // TODO: modify client object to set forgeMods and enable forgeHandshake throw new Error('FML/Forge not yet supported'); } - // done configuring client object, let connection proceed + // Finished configuring client object, let connection proceed client.emit('connect_allowed'); }); return client; From ddcca012efc5e4c44b9a05ec2eb1e339f4f7f981 Mon Sep 17 00:00:00 2001 From: deathcap Date: Sun, 31 Jan 2016 12:48:39 -0800 Subject: [PATCH 14/25] Pre-Netty protocol versions are not supported yet --- src/client/autoVersion.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/client/autoVersion.js b/src/client/autoVersion.js index 6d58a87..57c76ea 100644 --- a/src/client/autoVersion.js +++ b/src/client/autoVersion.js @@ -9,11 +9,10 @@ var minecraft_data = require('minecraft-data'); // Get the minecraft-data version string for a protocol version // TODO: add to node-minecraft-data index (protocol to newest release, if multiple) function protocolVersion2MinecraftVersion(n) { - var usesNetty = n > 0; + var usesNetty = true; // for now, only Netty protocols are supported TODO: pre-Netty (beware, colliding protocol version numbers) for (var i = 0; i < minecraft_data.versions.length; ++i) { var version = minecraft_data.versions[i]; - if (version.version === Math.abs(n) && version.usesNetty === usesNetty) { - console.log(version); + if (version.version === n && version.usesNetty === usesNetty) { return [version.minecraftVersion, version.majorVersion]; } } From 84c4c26503e544f542c5e114c80c1a85e2c5e688 Mon Sep 17 00:00:00 2001 From: deathcap Date: Sun, 31 Jan 2016 20:11:15 -0800 Subject: [PATCH 15/25] Update to minecraft-data ^0.19.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fd3abd5..8f07055 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ }, "dependencies": { "buffer-equal": "0.0.1", - "minecraft-data": "^0.16.1", + "minecraft-data": "^0.19.0", "prismarine-nbt": "0.1.0", "protodef": "0.2.5", "readable-stream": "^1.1.0", From 4b3f8b5b0924eb82cb7e89fb30883a81e3f20623 Mon Sep 17 00:00:00 2001 From: deathcap Date: Sun, 31 Jan 2016 20:39:01 -0800 Subject: [PATCH 16/25] Update minecraft-data to use GitHub dependency on PrismarineJS/node-minecraft-data --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8f07055..d3a14e2 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ }, "dependencies": { "buffer-equal": "0.0.1", - "minecraft-data": "^0.19.0", + "minecraft-data": "PrismarineJS/node-minecraft-data", "prismarine-nbt": "0.1.0", "protodef": "0.2.5", "readable-stream": "^1.1.0", From aa3ae329758eed114c382e56459a552a489b5a2c Mon Sep 17 00:00:00 2001 From: deathcap Date: Sun, 31 Jan 2016 20:50:57 -0800 Subject: [PATCH 17/25] Try using git commit hash to node-minecraft-data --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d3a14e2..1ad175d 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ }, "dependencies": { "buffer-equal": "0.0.1", - "minecraft-data": "PrismarineJS/node-minecraft-data", + "minecraft-data": "git://github.com/prismarinejs/node-minecraft-data.git#4e7f910e62ea30c641a9df2170275d49bbd1edad", "prismarine-nbt": "0.1.0", "protodef": "0.2.5", "readable-stream": "^1.1.0", From 070a046eea4beb5280a12015828b4393ecb7e850 Mon Sep 17 00:00:00 2001 From: deathcap Date: Sun, 31 Jan 2016 21:07:14 -0800 Subject: [PATCH 18/25] Try to clone minecraft-data to workaround https://github.com/PrismarineJS/node-minecraft-data/issues/16 --- circle.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/circle.yml b/circle.yml index 824c958..6a35cba 100644 --- a/circle.yml +++ b/circle.yml @@ -8,3 +8,4 @@ machine: dependencies: pre: - mkdir minecraft-server + - git clone https://github.com/PrismarineJS/minecraft-data node_modules/minecraft-data/minecraft-data || true From c2913daae023196bc8d14c54fbd35c2608006ad0 Mon Sep 17 00:00:00 2001 From: deathcap Date: Mon, 1 Feb 2016 09:48:12 -0800 Subject: [PATCH 19/25] Update to minecraft-data ^0.19.1 --- circle.yml | 1 - package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/circle.yml b/circle.yml index 6a35cba..824c958 100644 --- a/circle.yml +++ b/circle.yml @@ -8,4 +8,3 @@ machine: dependencies: pre: - mkdir minecraft-server - - git clone https://github.com/PrismarineJS/minecraft-data node_modules/minecraft-data/minecraft-data || true diff --git a/package.json b/package.json index 1ad175d..55de5fd 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ }, "dependencies": { "buffer-equal": "0.0.1", - "minecraft-data": "git://github.com/prismarinejs/node-minecraft-data.git#4e7f910e62ea30c641a9df2170275d49bbd1edad", + "minecraft-data": "^0.19.1", "prismarine-nbt": "0.1.0", "protodef": "0.2.5", "readable-stream": "^1.1.0", From 58fd1eab35ff9e7afd221d4afb3c263c953f82df Mon Sep 17 00:00:00 2001 From: deathcap Date: Mon, 1 Feb 2016 21:02:42 -0800 Subject: [PATCH 20/25] Lookup version using minecraft-data postNettyVersionsByProtocolVersion --- src/client/autoVersion.js | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/client/autoVersion.js b/src/client/autoVersion.js index 57c76ea..8cdf0e4 100644 --- a/src/client/autoVersion.js +++ b/src/client/autoVersion.js @@ -6,20 +6,6 @@ var states = require('../states'); var assert = require('assert'); var minecraft_data = require('minecraft-data'); -// Get the minecraft-data version string for a protocol version -// TODO: add to node-minecraft-data index (protocol to newest release, if multiple) -function protocolVersion2MinecraftVersion(n) { - var usesNetty = true; // for now, only Netty protocols are supported TODO: pre-Netty (beware, colliding protocol version numbers) - for (var i = 0; i < minecraft_data.versions.length; ++i) { - var version = minecraft_data.versions[i]; - if (version.version === n && version.usesNetty === usesNetty) { - return [version.minecraftVersion, version.majorVersion]; - } - } - - throw new Error(`unsupported/unknown protocol version: ${n}, update minecraft-data`); -} - module.exports = function(client) { var options = client.options; @@ -43,12 +29,15 @@ module.exports = function(client) { // Note that versionName is a descriptive version stirng like '1.8.9' on vailla, but other // servers add their own name (Spigot 1.8.8, Glowstone++ 1.8.9) so we cannot use it directly, // even though it is in a format accepted by minecraft-data. Instead, translate the protocol. - var [minecraftVersion, majorVersion] = protocolVersion2MinecraftVersion(protocolVersion); - client.options.version = minecraftVersion; + // TODO: pre-Netty version support (uses overlapping version numbers, so would have to check versionName) + var versionInfos = minecraft_data.postNettyVersionsByProtocolVersion[protocolVersion]; + if (!versionInfos && versionInfos.length < 1) throw new Error(`unsupported/unknown protocol version: ${protocolVersion}, update minecraft-data`); + var versionInfo = versionInfos[0]; // use newest + client.options.version = versionInfo.minecraftVersion; client.options.protocolVersion = protocolVersion; // Reinitialize client object with new version TODO: move out of its constructor? - client.version = majorVersion; + client.version = versionInfo.majorVersion; client.state = states.HANDSHAKING; if (response.modinfo && response.modinfo.type === 'FML') { From a8bc7d134365e1aa26226c165b6642fc87b76644 Mon Sep 17 00:00:00 2001 From: deathcap Date: Mon, 1 Feb 2016 21:07:32 -0800 Subject: [PATCH 21/25] Move options back to client parameters --- src/client/autoVersion.js | 8 +++----- src/client/caseCorrect.js | 3 +-- src/client/compress.js | 2 +- src/client/encrypt.js | 3 +-- src/client/keepalive.js | 3 +-- src/client/play.js | 2 +- src/client/setProtocol.js | 3 +-- src/client/tcp_dns.js | 3 +-- src/createClient.js | 17 ++++++++--------- src/ping.js | 3 +-- 10 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/client/autoVersion.js b/src/client/autoVersion.js index 8cdf0e4..3051403 100644 --- a/src/client/autoVersion.js +++ b/src/client/autoVersion.js @@ -6,9 +6,7 @@ var states = require('../states'); var assert = require('assert'); var minecraft_data = require('minecraft-data'); -module.exports = function(client) { - var options = client.options; - +module.exports = function(client, options) { options.wait_connect = true; // don't let src/client/setProtocol proceed on socket 'connect' until 'connect_allowed' debug('pinging',options.host); var pingOptions = {host: options.host, port: options.port}; @@ -33,8 +31,8 @@ module.exports = function(client) { var versionInfos = minecraft_data.postNettyVersionsByProtocolVersion[protocolVersion]; if (!versionInfos && versionInfos.length < 1) throw new Error(`unsupported/unknown protocol version: ${protocolVersion}, update minecraft-data`); var versionInfo = versionInfos[0]; // use newest - client.options.version = versionInfo.minecraftVersion; - client.options.protocolVersion = protocolVersion; + options.version = versionInfo.minecraftVersion; + options.protocolVersion = protocolVersion; // Reinitialize client object with new version TODO: move out of its constructor? client.version = versionInfo.majorVersion; diff --git a/src/client/caseCorrect.js b/src/client/caseCorrect.js index e8a42d8..2eb634a 100644 --- a/src/client/caseCorrect.js +++ b/src/client/caseCorrect.js @@ -1,8 +1,7 @@ var yggdrasil = require('yggdrasil')({}); var UUID = require('uuid-1345'); -module.exports = function(client) { - var options = client.options; +module.exports = function(client, options) { var clientToken = options.clientToken || UUID.v4().toString(); options.accessToken = null; options.haveCredentials = options.password != null || (clientToken != null && options.session != null); diff --git a/src/client/compress.js b/src/client/compress.js index 40d092f..cebe34f 100644 --- a/src/client/compress.js +++ b/src/client/compress.js @@ -1,4 +1,4 @@ -module.exports = function(client) { +module.exports = function(client, options) { client.once("compress", onCompressionRequest); client.on("set_compression", onCompressionRequest); diff --git a/src/client/encrypt.js b/src/client/encrypt.js index 10b391c..696ddfc 100644 --- a/src/client/encrypt.js +++ b/src/client/encrypt.js @@ -3,8 +3,7 @@ var yggserver = require('yggdrasil').server({}); var ursa=require("../ursa"); var debug = require("../debug"); -module.exports = function(client) { - var options = client.options; +module.exports = function(client, options) { client.once('encryption_begin', onEncryptionKeyRequest); function onEncryptionKeyRequest(packet) { diff --git a/src/client/keepalive.js b/src/client/keepalive.js index 5b206cf..3fc817b 100644 --- a/src/client/keepalive.js +++ b/src/client/keepalive.js @@ -1,5 +1,4 @@ -module.exports = function(client) { - var options = client.options; +module.exports = function(client, options) { var keepAlive = options.keepAlive == null ? true : options.keepAlive; if (!keepAlive) return; diff --git a/src/client/play.js b/src/client/play.js index efcf84b..ebc491e 100644 --- a/src/client/play.js +++ b/src/client/play.js @@ -1,6 +1,6 @@ var states = require("../states"); -module.exports = function(client) { +module.exports = function(client, options) { client.once('success', onLogin); function onLogin(packet) { diff --git a/src/client/setProtocol.js b/src/client/setProtocol.js index 0c5b7db..4948b1c 100644 --- a/src/client/setProtocol.js +++ b/src/client/setProtocol.js @@ -1,8 +1,7 @@ var states = require("../states"); -module.exports = function(client) { - var options = client.options; +module.exports = function(client, options) { client.on('connect', onConnect); function onConnect() { diff --git a/src/client/tcp_dns.js b/src/client/tcp_dns.js index 2863962..a8e3060 100644 --- a/src/client/tcp_dns.js +++ b/src/client/tcp_dns.js @@ -1,8 +1,7 @@ var net = require('net'); var dns = require('dns'); -module.exports = function(client) { - var options = client.options; +module.exports = function(client, options) { options.port = options.port || 25565; options.host = options.host || 'localhost'; diff --git a/src/createClient.js b/src/createClient.js index 0a68c7c..f702353 100644 --- a/src/createClient.js +++ b/src/createClient.js @@ -25,16 +25,15 @@ function createClient(options) { options.protocolVersion = version.version; var client = new Client(false, options.majorVersion); - client.options = options; - tcp_dns(client); - caseCorrect(client); - if (options.version === false) autoVersion(client); - setProtocol(client); - keepalive(client); - encrypt(client); - play(client); - compress(client); + tcp_dns(client, options); + caseCorrect(client, options); + if (options.version === false) autoVersion(client, options); + setProtocol(client, options); + keepalive(client, options); + encrypt(client, options); + play(client, options); + compress(client, options); return client; } diff --git a/src/ping.js b/src/ping.js index 1e6adcb..4a58353 100644 --- a/src/ping.js +++ b/src/ping.js @@ -15,7 +15,6 @@ function ping(options, cb) { options.protocolVersion = version.version; var client = new Client(false,options.majorVersion); - client.options = options; client.on('error', function(err) { cb(err); }); @@ -47,6 +46,6 @@ function ping(options, cb) { client.state = states.STATUS; }); - tcp_dns(client); + tcp_dns(client, options); options.connect(client); } From a3a2d3d6f1ba389cfa4a3e06f8d8975d33b1b290 Mon Sep 17 00:00:00 2001 From: deathcap Date: Mon, 1 Feb 2016 21:42:53 -0800 Subject: [PATCH 22/25] Move wait_connect to client object --- src/client/autoVersion.js | 2 +- src/client/setProtocol.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/autoVersion.js b/src/client/autoVersion.js index 3051403..1e09e0a 100644 --- a/src/client/autoVersion.js +++ b/src/client/autoVersion.js @@ -7,7 +7,7 @@ var assert = require('assert'); var minecraft_data = require('minecraft-data'); module.exports = function(client, options) { - options.wait_connect = true; // don't let src/client/setProtocol proceed on socket 'connect' until 'connect_allowed' + client.wait_connect = true; // don't let src/client/setProtocol proceed on socket 'connect' until 'connect_allowed' debug('pinging',options.host); var pingOptions = {host: options.host, port: options.port}; // TODO: use 0xfe ping instead for better compatibility/performance? https://github.com/deathcap/node-minecraft-ping diff --git a/src/client/setProtocol.js b/src/client/setProtocol.js index 4948b1c..ae1b519 100644 --- a/src/client/setProtocol.js +++ b/src/client/setProtocol.js @@ -5,7 +5,7 @@ module.exports = function(client, options) { client.on('connect', onConnect); function onConnect() { - if (options.wait_connect) { + if (client.wait_connect) { client.on('connect_allowed', next); } else { next(); From 779ffd7ba931aa453229f9e95b189bb3d960ef30 Mon Sep 17 00:00:00 2001 From: Romain Beaumont Date: Mon, 1 Feb 2016 10:45:13 +0100 Subject: [PATCH 23/25] much let, very const fix #335 --- src/browser.js | 6 +-- src/client.js | 38 +++++++------- src/client/caseCorrect.js | 8 +-- src/client/encrypt.js | 20 ++++---- src/client/keepalive.js | 6 +-- src/client/play.js | 2 +- src/client/setProtocol.js | 5 +- src/client/tcp_dns.js | 4 +- src/createClient.js | 29 ++++++----- src/createServer.js | 96 +++++++++++++++++------------------ src/datatypes/minecraft.js | 20 ++++---- src/debug.js | 6 +-- src/index.js | 10 ++-- src/ping.js | 20 ++++---- src/server.js | 23 ++++----- src/states.js | 2 +- src/transforms/compression.js | 16 +++--- src/transforms/framing.js | 14 ++--- src/transforms/serializer.js | 28 +++++----- src/ursa.js | 2 +- 20 files changed, 176 insertions(+), 179 deletions(-) diff --git a/src/browser.js b/src/browser.js index f76c7c7..3e2d3ea 100644 --- a/src/browser.js +++ b/src/browser.js @@ -1,6 +1,6 @@ -var Client = require('./client'); -var Server = require('./server'); -var serializer = require("./transforms/serializer"); +const Client = require('./client'); +const Server = require('./server'); +const serializer = require("./transforms/serializer"); module.exports = { Client: Client, diff --git a/src/client.js b/src/client.js index fa8a8c0..51b22d2 100644 --- a/src/client.js +++ b/src/client.js @@ -1,12 +1,12 @@ -var EventEmitter = require('events').EventEmitter; -var debug = require('./debug'); -var compression = require('./transforms/compression'); -var framing = require('./transforms/framing'); -var crypto = require('crypto'); -var states = require("./states"); +const EventEmitter = require('events').EventEmitter; +const debug = require('./debug'); +const compression = require('./transforms/compression'); +const framing = require('./transforms/framing'); +const crypto = require('crypto'); +const states = require("./states"); -var createSerializer=require("./transforms/serializer").createSerializer; -var createDeserializer=require("./transforms/serializer").createDeserializer; +const createSerializer=require("./transforms/serializer").createSerializer; +const createDeserializer=require("./transforms/serializer").createDeserializer; class Client extends EventEmitter { @@ -30,12 +30,12 @@ class Client extends EventEmitter this.latency=0; this.on('newListener', function(event, listener) { - var direction = this.isServer ? 'toServer' : 'toClient'; + const direction = this.isServer ? 'toServer' : 'toClient'; if(typeof this.packetsToParse[event] === "undefined") this.packetsToParse[event] = 1; else this.packetsToParse[event] += 1; }); this.on('removeListener', function(event, listener) { - var direction = this.isServer ? 'toServer' : 'toClient'; + const direction = this.isServer ? 'toServer' : 'toClient'; this.packetsToParse[event] -= 1; }); } @@ -53,9 +53,9 @@ class Client extends EventEmitter this.splitter.recognizeLegacyPing = state === states.HANDSHAKING; this.serializer.on('error', (e) => { - var parts=e.field.split("."); + const parts=e.field.split("."); parts.shift(); - var serializerDirection = !this.isServer ? 'toServer' : 'toClient'; + const serializerDirection = !this.isServer ? 'toServer' : 'toClient'; e.field = [this.protocolState, serializerDirection].concat(parts).join("."); e.message = `Serialization error for ${e.field} : ${e.message}`; this.emit('error',e); @@ -63,9 +63,9 @@ class Client extends EventEmitter this.deserializer.on('error', (e) => { - var parts=e.field.split("."); + const parts=e.field.split("."); parts.shift(); - var deserializerDirection = this.isServer ? 'toServer' : 'toClient'; + const deserializerDirection = this.isServer ? 'toServer' : 'toClient'; e.field = [this.protocolState, deserializerDirection].concat(parts).join("."); e.message = `Deserialization error for ${e.field} : ${e.message}`; this.emit('error',e); @@ -85,7 +85,7 @@ class Client extends EventEmitter } set state(newProperty) { - var oldProperty = this.protocolState; + const oldProperty = this.protocolState; this.protocolState = newProperty; if(!this.compressor) @@ -129,7 +129,7 @@ class Client extends EventEmitter this.ended = false; // TODO : A lot of other things needs to be done. - var endSocket = () => { + const endSocket = () => { if(this.ended) return; this.ended = true; this.socket.removeListener('close', endSocket); @@ -138,12 +138,12 @@ class Client extends EventEmitter this.emit('end', this._endReason); }; - var onFatalError = (err) => { + const onFatalError = (err) => { this.emit('error', err); endSocket(); }; - var onError = (err) => this.emit('error', err); + const onError = (err) => this.emit('error', err); this.socket = socket; @@ -218,7 +218,7 @@ class Client extends EventEmitter // TCP/IP-specific (not generic Stream) method for backwards-compatibility connect(port, host) { - var options = {port, host}; + const options = {port, host}; if (!this.options) this.options = options; require('./client/tcp_dns')(this, options); options.connect(this); diff --git a/src/client/caseCorrect.js b/src/client/caseCorrect.js index 2eb634a..e56941c 100644 --- a/src/client/caseCorrect.js +++ b/src/client/caseCorrect.js @@ -1,14 +1,14 @@ -var yggdrasil = require('yggdrasil')({}); -var UUID = require('uuid-1345'); +const yggdrasil = require('yggdrasil')({}); +const UUID = require('uuid-1345'); module.exports = function(client, options) { - var clientToken = options.clientToken || UUID.v4().toString(); + const clientToken = options.clientToken || UUID.v4().toString(); options.accessToken = null; options.haveCredentials = options.password != null || (clientToken != null && options.session != null); if(options.haveCredentials) { // make a request to get the case-correct username before connecting. - var cb = function(err, session) { + const cb = function(err, session) { if(err) { client.emit('error', err); } else { diff --git a/src/client/encrypt.js b/src/client/encrypt.js index 696ddfc..deb7993 100644 --- a/src/client/encrypt.js +++ b/src/client/encrypt.js @@ -1,7 +1,7 @@ -var crypto = require('crypto'); -var yggserver = require('yggdrasil').server({}); -var ursa=require("../ursa"); -var debug = require("../debug"); +const crypto = require('crypto'); +const yggserver = require('yggdrasil').server({}); +const ursa=require("../ursa"); +const debug = require("../debug"); module.exports = function(client, options) { client.once('encryption_begin', onEncryptionKeyRequest); @@ -40,9 +40,9 @@ module.exports = function(client, options) { } function sendEncryptionKeyResponse() { - var pubKey = mcPubKeyToURsa(packet.publicKey); - var encryptedSharedSecretBuffer = pubKey.encrypt(sharedSecret, undefined, undefined, ursa.RSA_PKCS1_PADDING); - var encryptedVerifyTokenBuffer = pubKey.encrypt(packet.verifyToken, undefined, undefined, ursa.RSA_PKCS1_PADDING); + const pubKey = mcPubKeyToURsa(packet.publicKey); + const encryptedSharedSecretBuffer = pubKey.encrypt(sharedSecret, undefined, undefined, ursa.RSA_PKCS1_PADDING); + const encryptedVerifyTokenBuffer = pubKey.encrypt(packet.verifyToken, undefined, undefined, ursa.RSA_PKCS1_PADDING); client.write('encryption_begin', { sharedSecret: encryptedSharedSecretBuffer, verifyToken: encryptedVerifyTokenBuffer @@ -54,9 +54,9 @@ module.exports = function(client, options) { }; function mcPubKeyToURsa(mcPubKeyBuffer) { - var pem = "-----BEGIN PUBLIC KEY-----\n"; - var base64PubKey = mcPubKeyBuffer.toString('base64'); - var maxLineLength = 65; + let pem = "-----BEGIN PUBLIC KEY-----\n"; + let base64PubKey = mcPubKeyBuffer.toString('base64'); + const maxLineLength = 65; while(base64PubKey.length > 0) { pem += base64PubKey.substring(0, maxLineLength) + "\n"; base64PubKey = base64PubKey.substring(maxLineLength); diff --git a/src/client/keepalive.js b/src/client/keepalive.js index 3fc817b..fae0017 100644 --- a/src/client/keepalive.js +++ b/src/client/keepalive.js @@ -1,12 +1,12 @@ module.exports = function(client, options) { - var keepAlive = options.keepAlive == null ? true : options.keepAlive; + const keepAlive = options.keepAlive == null ? true : options.keepAlive; if (!keepAlive) return; - var checkTimeoutInterval = options.checkTimeoutInterval || 10 * 1000; + const checkTimeoutInterval = options.checkTimeoutInterval || 10 * 1000; client.on('keep_alive', onKeepAlive); - var timeout = null; + let timeout = null; function onKeepAlive(packet) { if (timeout) diff --git a/src/client/play.js b/src/client/play.js index ebc491e..b01fe29 100644 --- a/src/client/play.js +++ b/src/client/play.js @@ -1,4 +1,4 @@ -var states = require("../states"); +const states = require("../states"); module.exports = function(client, options) { client.once('success', onLogin); diff --git a/src/client/setProtocol.js b/src/client/setProtocol.js index ae1b519..08c63f8 100644 --- a/src/client/setProtocol.js +++ b/src/client/setProtocol.js @@ -1,5 +1,4 @@ - -var states = require("../states"); +const states = require("../states"); module.exports = function(client, options) { client.on('connect', onConnect); @@ -24,4 +23,4 @@ module.exports = function(client, options) { username: client.username }); } -} +}; diff --git a/src/client/tcp_dns.js b/src/client/tcp_dns.js index 579cb80..f0b5c33 100644 --- a/src/client/tcp_dns.js +++ b/src/client/tcp_dns.js @@ -1,5 +1,5 @@ -var net = require('net'); -var dns = require('dns'); +const net = require('net'); +const dns = require('dns'); module.exports = function(client, options) { options.port = options.port || 25565; diff --git a/src/createClient.js b/src/createClient.js index f702353..45c5a2d 100644 --- a/src/createClient.js +++ b/src/createClient.js @@ -1,14 +1,15 @@ -var Client = require('./client'); -var assert = require('assert'); +const Client = require('./client'); +const assert = require('assert'); -var encrypt = require('./client/encrypt'); -var keepalive = require('./client/keepalive'); -var compress = require('./client/compress'); -var caseCorrect = require('./client/caseCorrect'); -var setProtocol = require('./client/setProtocol'); -var play = require('./client/play'); -var tcp_dns = require('./client/tcp_dns'); -var autoVersion = require('./client/autoVersion'); + +const encrypt = require('./client/encrypt'); +const keepalive = require('./client/keepalive'); +const compress = require('./client/compress'); +const caseCorrect = require('./client/caseCorrect'); +const setProtocol = require('./client/setProtocol'); +const play = require('./client/play'); +const tcp_dns = require('./client/tcp_dns'); +const autoVersion = require('./client/autoVersion'); module.exports=createClient; @@ -17,14 +18,14 @@ function createClient(options) { assert.ok(options.username, "username is required"); // TODO: avoid setting default version if autoVersion is enabled - var optVersion = options.version || require("./version").defaultVersion; - var mcData=require("minecraft-data")(optVersion); + const optVersion = options.version || require("./version").defaultVersion; + const mcData=require("minecraft-data")(optVersion); if (!mcData) throw new Error(`unsupported protocol version: ${optVersion}`); - var version = mcData.version; + const version = mcData.version; options.majorVersion = version.majorVersion; options.protocolVersion = version.version; - var client = new Client(false, options.majorVersion); + const client = new Client(false, options.majorVersion); tcp_dns(client, options); caseCorrect(client, options); diff --git a/src/createServer.js b/src/createServer.js index 9a4b71d..118f4ec 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -1,38 +1,38 @@ -var ursa=require("./ursa"); -var crypto = require('crypto'); -var yggserver = require('yggdrasil').server({}); -var states = require("./states"); -var bufferEqual = require('buffer-equal'); -var Server = require('./server'); -var UUID = require('uuid-1345'); -var endianToggle = require('endian-toggle'); +const ursa=require("./ursa"); +const crypto = require('crypto'); +const yggserver = require('yggdrasil').server({}); +const states = require("./states"); +const bufferEqual = require('buffer-equal'); +const Server = require('./server'); +const UUID = require('uuid-1345'); +const endianToggle = require('endian-toggle'); module.exports=createServer; function createServer(options) { options = options || {}; - var port = options.port != null ? + const port = options.port != null ? options.port : options['server-port'] != null ? options['server-port'] : 25565; - var host = options.host || '0.0.0.0'; - var kickTimeout = options.kickTimeout || 10 * 1000; - var checkTimeoutInterval = options.checkTimeoutInterval || 4 * 1000; - var onlineMode = options['online-mode'] == null ? true : options['online-mode']; + const host = options.host || '0.0.0.0'; + const kickTimeout = options.kickTimeout || 10 * 1000; + const checkTimeoutInterval = options.checkTimeoutInterval || 4 * 1000; + const onlineMode = options['online-mode'] == null ? true : options['online-mode']; // a function receiving the default status object and the client // and returning a modified response object. - var beforePing = options.beforePing || null; + const beforePing = options.beforePing || null; - var enableKeepAlive = options.keepAlive == null ? true : options.keepAlive; + const enableKeepAlive = options.keepAlive == null ? true : options.keepAlive; - var optVersion = options.version || require("./version").defaultVersion; - var mcData=require("minecraft-data")(optVersion); - var version = mcData.version; + const optVersion = options.version || require("./version").defaultVersion; + const mcData=require("minecraft-data")(optVersion); + const version = mcData.version; - var serverKey = ursa.generatePrivateKey(1024); + const serverKey = ursa.generatePrivateKey(1024); - var server = new Server(version.majorVersion); + const server = new Server(version.majorVersion); server.motd = options.motd || "A Minecraft server"; server.maxPlayers = options['max-players'] || 20; server.playerCount = 0; @@ -44,16 +44,16 @@ function createServer(options) { client.once('legacy_server_list_ping', onLegacyPing); client.on('end', onEnd); - var keepAlive = false; - var loggedIn = false; - var lastKeepAlive = null; + let keepAlive = false; + let loggedIn = false; + let lastKeepAlive = null; - var keepAliveTimer = null; - var loginKickTimer = setTimeout(kickForNotLoggingIn, kickTimeout); + let keepAliveTimer = null; + let loginKickTimer = setTimeout(kickForNotLoggingIn, kickTimeout); - var serverId; - - var sendKeepAliveTime; + let serverId; + + let sendKeepAliveTime; function kickForNotLoggingIn() { client.end('LoginTimeout'); @@ -64,7 +64,7 @@ function createServer(options) { return; // check if the last keepAlive was too long ago (kickTimeout) - var elapsed = new Date() - lastKeepAlive; + const elapsed = new Date() - lastKeepAlive; if(elapsed > kickTimeout) { client.end('KeepAliveTimeout'); return; @@ -93,7 +93,7 @@ function createServer(options) { } function onPing() { - var response = { + const response = { "version": { "name": version.minecraftVersion, "protocol": version.version @@ -130,7 +130,7 @@ function createServer(options) { function onLegacyPing(packet) { if (packet.payload === 1) { - var pingVersion = 1; + const pingVersion = 1; sendPingResponse('\xa7' + [pingVersion, version.version, version.minecraftVersion, server.motd, server.playerCount.toString(), server.maxPlayers.toString()].join('\0')); } else { @@ -143,13 +143,13 @@ function createServer(options) { return endianToggle(new Buffer(s, 'utf16le'), 16); } - var responseBuffer = utf16be(responseString); + const responseBuffer = utf16be(responseString); - var length = responseString.length; // UCS2 characters, not bytes - var lengthBuffer = new Buffer(2); + const length = responseString.length; // UCS2 characters, not bytes + const lengthBuffer = new Buffer(2); lengthBuffer.writeUInt16BE(length); - var raw = Buffer.concat([new Buffer('ff', 'hex'), lengthBuffer, responseBuffer]); + const raw = Buffer.concat([new Buffer('ff', 'hex'), lengthBuffer, responseBuffer]); //client.writeRaw(raw); // not raw enough, it includes length client.socket.write(raw); @@ -159,14 +159,14 @@ function createServer(options) { function onLogin(packet) { client.username = packet.username; - var isException = !!server.onlineModeExceptions[client.username.toLowerCase()]; - var needToVerify = (onlineMode && !isException) || (!onlineMode && isException); + const isException = !!server.onlineModeExceptions[client.username.toLowerCase()]; + const needToVerify = (onlineMode && !isException) || (!onlineMode && isException); if(needToVerify) { serverId = crypto.randomBytes(4).toString('hex'); client.verifyToken = crypto.randomBytes(4); - var publicKeyStrArr = serverKey.toPublicPem("utf8").split("\n"); - var publicKeyStr = ""; - for(var i = 1; i < publicKeyStrArr.length - 2; i++) { + const publicKeyStrArr = serverKey.toPublicPem("utf8").split("\n"); + let publicKeyStr = ""; + for(let i = 1; i < publicKeyStrArr.length - 2; i++) { publicKeyStr += publicKeyStrArr[i] } client.publicKey = new Buffer(publicKeyStr, 'base64'); @@ -198,21 +198,21 @@ function createServer(options) { function onEncryptionKeyResponse(packet) { try { - var verifyToken = serverKey.decrypt(packet.verifyToken, undefined, undefined, ursa.RSA_PKCS1_PADDING); + const verifyToken = serverKey.decrypt(packet.verifyToken, undefined, undefined, ursa.RSA_PKCS1_PADDING); if(!bufferEqual(client.verifyToken, verifyToken)) { client.end('DidNotEncryptVerifyTokenProperly'); return; } - var sharedSecret = serverKey.decrypt(packet.sharedSecret, undefined, undefined, ursa.RSA_PKCS1_PADDING); + const sharedSecret = serverKey.decrypt(packet.sharedSecret, undefined, undefined, ursa.RSA_PKCS1_PADDING); } catch(e) { client.end('DidNotEncryptVerifyTokenProperly'); return; } client.setEncryption(sharedSecret); - var isException = !!server.onlineModeExceptions[client.username.toLowerCase()]; - var needToVerify = (onlineMode && !isException) || (!onlineMode && isException); - var nextStep = needToVerify ? verifyUsername : loginClient; + const isException = !!server.onlineModeExceptions[client.username.toLowerCase()]; + const needToVerify = (onlineMode && !isException) || (!onlineMode && isException); + const nextStep = needToVerify ? verifyUsername : loginClient; nextStep(); function verifyUsername() { @@ -234,9 +234,9 @@ function createServer(options) { // https://github.com/openjdk-mirror/jdk7u-jdk/blob/f4d80957e89a19a29bb9f9807d2a28351ed7f7df/src/share/classes/java/util/UUID.java#L163 function javaUUID(s) { - var hash = crypto.createHash("md5"); + const hash = crypto.createHash("md5"); hash.update(s, 'utf8'); - var buffer = hash.digest(); + const buffer = hash.digest(); buffer[6] = (buffer[6] & 0x0f) | 0x30; buffer[8] = (buffer[8] & 0x3f) | 0x80; return buffer; @@ -248,7 +248,7 @@ function createServer(options) { } function loginClient() { - var isException = !!server.onlineModeExceptions[client.username.toLowerCase()]; + const isException = !!server.onlineModeExceptions[client.username.toLowerCase()]; if(onlineMode == false || isException) { client.uuid = nameToMcOfflineUUID(client.username); } diff --git a/src/datatypes/minecraft.js b/src/datatypes/minecraft.js index 956212f..047820c 100644 --- a/src/datatypes/minecraft.js +++ b/src/datatypes/minecraft.js @@ -1,5 +1,5 @@ -var nbt = require('prismarine-nbt'); -var UUID = require('uuid-1345'); +const nbt = require('prismarine-nbt'); +const UUID = require('uuid-1345'); module.exports = { 'UUID': [readUUID, writeUUID, 16], @@ -17,7 +17,7 @@ function readUUID(buffer, offset) { } function writeUUID(value, buffer, offset) { - var buf=UUID.parse(value); + const buf=UUID.parse(value); buf.copy(buffer,offset); return offset + 16; } @@ -71,9 +71,9 @@ function sizeOfRestBuffer(value) { } function readEntityMetadata(buffer, offset, {type,endVal}) { - var cursor = offset; - var metadata = []; - var item; + let cursor = offset; + const metadata = []; + let item; while(true) { item = buffer.readUInt8(cursor); if(item === endVal) { @@ -82,14 +82,14 @@ function readEntityMetadata(buffer, offset, {type,endVal}) { size: cursor + 1 - offset }; } - var results = this.read(buffer, cursor, type, {}); + const results = this.read(buffer, cursor, type, {}); metadata.push(results.value); cursor += results.size; } } function writeEntityMetadata(value, buffer, offset, {type,endVal}) { - var self = this; + const self = this; value.forEach(function(item) { offset = self.write(item, buffer, offset, type, {}); }); @@ -98,8 +98,8 @@ function writeEntityMetadata(value, buffer, offset, {type,endVal}) { } function sizeOfEntityMetadata(value, {type}) { - var size = 1; - for(var i = 0; i < value.length; ++i) { + let size = 1; + for(let i = 0; i < value.length; ++i) { size += this.sizeOf(value[i], type, {}); } return size; diff --git a/src/debug.js b/src/debug.js index 6b8e326..7ea4f99 100644 --- a/src/debug.js +++ b/src/debug.js @@ -1,8 +1,8 @@ -var util = require('util'); +const util = require('util'); -var debug; +let debug; if(process.env.NODE_DEBUG && /(minecraft-protocol|mc-proto)/.test(process.env.NODE_DEBUG)) { - var pid = process.pid; + const pid = process.pid; debug = function(x) { // if console is not set up yet, then skip this. if(!console.error) diff --git a/src/index.js b/src/index.js index 8d90027..024ae3e 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,8 @@ -var Client = require('./client'); -var Server = require('./server'); -var serializer = require("./transforms/serializer"); -var createClient = require("./createClient"); -var createServer = require("./createServer"); +const Client = require('./client'); +const Server = require('./server'); +const serializer = require("./transforms/serializer"); +const createClient = require("./createClient"); +const createServer = require("./createServer"); module.exports = { createClient: createClient, diff --git a/src/ping.js b/src/ping.js index 4a58353..5ec3ab7 100644 --- a/src/ping.js +++ b/src/ping.js @@ -1,27 +1,27 @@ -var net = require('net'); -var Client = require('./client'); -var states = require("./states"); -var tcp_dns = require('./client/tcp_dns'); +const net = require('net'); +const Client = require('./client'); +const states = require("./states"); +const tcp_dns = require('./client/tcp_dns'); module.exports = ping; function ping(options, cb) { options.host = options.host || 'localhost'; options.port = options.port || 25565; - var optVersion = options.version || require("./version").defaultVersion; - var mcData=require("minecraft-data")(optVersion); - var version = mcData.version; + const optVersion = options.version || require("./version").defaultVersion; + const mcData=require("minecraft-data")(optVersion); + const version = mcData.version; options.majorVersion = version.majorVersion; options.protocolVersion = version.version; - var client = new Client(false,options.majorVersion); + const client = new Client(false,options.majorVersion); client.on('error', function(err) { cb(err); }); client.once('server_info', function(packet) { - var data = JSON.parse(packet.response); - var start = Date.now(); + const data = JSON.parse(packet.response); + const start = Date.now(); client.once('ping', function(packet) { data.latency = Date.now() - start; cb(null, data); diff --git a/src/server.js b/src/server.js index d604b9f..daab15e 100644 --- a/src/server.js +++ b/src/server.js @@ -1,7 +1,7 @@ -var net = require('net'); -var EventEmitter = require('events').EventEmitter; -var Client = require('./client'); -var states = require("./states"); +const net = require('net'); +const EventEmitter = require('events').EventEmitter; +const Client = require('./client'); +const states = require("./states"); class Server extends EventEmitter { @@ -15,11 +15,11 @@ class Server extends EventEmitter } listen(port, host) { - var self = this; - var nextId = 0; + const self = this; + let nextId = 0; self.socketServer = net.createServer(); self.socketServer.on('connection', socket => { - var client = new Client(true,this.version); + const client = new Client(true,this.version); client._end = client.end; client.end = function end(endReason) { endReason='{"text":"'+endReason+'"}'; @@ -51,13 +51,10 @@ class Server extends EventEmitter } close() { - var client; - for(var clientId in this.clients) { - if(!this.clients.hasOwnProperty(clientId)) continue; - - client = this.clients[clientId]; + Object.keys(this.clients).forEach(clientId => { + const client = this.clients[clientId]; client.end('ServerShutdown'); - } + }); this.socketServer.close(); } } diff --git a/src/states.js b/src/states.js index a50cafc..56f4de5 100644 --- a/src/states.js +++ b/src/states.js @@ -1,4 +1,4 @@ -var states = { +const states = { "HANDSHAKING": "handshaking", "STATUS": "status", "LOGIN": "login", diff --git a/src/transforms/compression.js b/src/transforms/compression.js index 17e89b3..8275033 100644 --- a/src/transforms/compression.js +++ b/src/transforms/compression.js @@ -1,6 +1,6 @@ -var [readVarInt, writeVarInt, sizeOfVarInt] = require("protodef").types.varint; -var zlib = require("zlib"); -var Transform = require("readable-stream").Transform; +const [readVarInt, writeVarInt, sizeOfVarInt] = require("protodef").types.varint; +const zlib = require("zlib"); +const Transform = require("readable-stream").Transform; module.exports.createCompressor = function(threshold) { return new Compressor(threshold); @@ -22,8 +22,8 @@ class Compressor extends Transform { zlib.deflate(chunk, (err, newChunk) => { if (err) return cb(err); - var buf = new Buffer(sizeOfVarInt(chunk.length) + newChunk.length); - var offset = writeVarInt(chunk.length, buf, 0); + const buf = new Buffer(sizeOfVarInt(chunk.length) + newChunk.length); + const offset = writeVarInt(chunk.length, buf, 0); newChunk.copy(buf, offset); this.push(buf); return cb(); @@ -31,8 +31,8 @@ class Compressor extends Transform { } else { - var buf = new Buffer(sizeOfVarInt(0) + chunk.length); - var offset = writeVarInt(0, buf, 0); + const buf = new Buffer(sizeOfVarInt(0) + chunk.length); + const offset = writeVarInt(0, buf, 0); chunk.copy(buf, offset); this.push(buf); return cb(); @@ -47,7 +47,7 @@ class Decompressor extends Transform { } _transform(chunk, enc, cb) { - var { size, value, error } = readVarInt(chunk, 0); + const { size, value, error } = readVarInt(chunk, 0); if (error) return cb(error); if (value === 0) diff --git a/src/transforms/framing.js b/src/transforms/framing.js index 48e67c2..9b73a0d 100644 --- a/src/transforms/framing.js +++ b/src/transforms/framing.js @@ -1,5 +1,5 @@ -var [readVarInt, writeVarInt, sizeOfVarInt] = require("protodef").types.varint; -var Transform = require("readable-stream").Transform; +const [readVarInt, writeVarInt, sizeOfVarInt] = require("protodef").types.varint; +const Transform = require("readable-stream").Transform; module.exports.createSplitter = function() { return new Splitter(); @@ -16,7 +16,7 @@ class Framer extends Transform { _transform(chunk, enc, cb) { const varIntSize=sizeOfVarInt(chunk.length); - var buffer = new Buffer(varIntSize + chunk.length); + const buffer = new Buffer(varIntSize + chunk.length); writeVarInt(chunk.length, buffer, 0); chunk.copy(buffer, varIntSize); this.push(buffer); @@ -38,17 +38,17 @@ class Splitter extends Transform { if (this.recognizeLegacyPing && this.buffer[0] === LEGACY_PING_PACKET_ID) { // legacy_server_list_ping packet follows a different protocol format // prefix the encoded varint packet id for the deserializer - var header = new Buffer(sizeOfVarInt(LEGACY_PING_PACKET_ID)); + const header = new Buffer(sizeOfVarInt(LEGACY_PING_PACKET_ID)); writeVarInt(LEGACY_PING_PACKET_ID, header, 0); - var payload = this.buffer.slice(1); // remove 0xfe packet id + let payload = this.buffer.slice(1); // remove 0xfe packet id if (payload.length === 0) payload = new Buffer('\0'); // TODO: update minecraft-data to recognize a lone 0xfe, https://github.com/PrismarineJS/minecraft-data/issues/95 this.push(Buffer.concat([header, payload])); return cb(); } - var offset = 0; + let offset = 0; - var { value, size, error } = readVarInt(this.buffer, offset) || { error: "Not enough data" }; + let { value, size, error } = readVarInt(this.buffer, offset) || { error: "Not enough data" }; while (!error && this.buffer.length >= offset + size + value) { this.push(this.buffer.slice(offset + size, offset + size + value)); diff --git a/src/transforms/serializer.js b/src/transforms/serializer.js index 76852b4..23cc982 100644 --- a/src/transforms/serializer.js +++ b/src/transforms/serializer.js @@ -1,13 +1,13 @@ -var ProtoDef = require("protodef").ProtoDef; -var Serializer = require("protodef").Serializer; -var Parser = require("protodef").Parser; +const ProtoDef = require("protodef").ProtoDef; +const Serializer = require("protodef").Serializer; +const Parser = require("protodef").Parser; -var minecraft = require("../datatypes/minecraft"); -var states = require("../states"); +const minecraft = require("../datatypes/minecraft"); +const states = require("../states"); function createProtocol(types,packets) { - var proto = new ProtoDef(); + const proto = new ProtoDef(); proto.addType("string",["pstring",{ countType:"varint" }]); @@ -38,20 +38,20 @@ function createProtocol(types,packets) function createSerializer({ state = states.HANDSHAKING, isServer = false , version} = {}) { - var mcData=require("minecraft-data")(version); - var direction = !isServer ? 'toServer' : 'toClient'; - var packets = mcData.protocol.states[state][direction]; - var proto=createProtocol(mcData.protocol.types,packets); + const mcData=require("minecraft-data")(version); + const direction = !isServer ? 'toServer' : 'toClient'; + const packets = mcData.protocol.states[state][direction]; + const proto=createProtocol(mcData.protocol.types,packets); return new Serializer(proto,"packet"); } function createDeserializer({ state = states.HANDSHAKING, isServer = false, packetsToParse = {"packet": true}, version } = {}) { - var mcData=require("minecraft-data")(version); - var direction = isServer ? "toServer" : "toClient"; - var packets = mcData.protocol.states[state][direction]; - var proto=createProtocol(mcData.protocol.types,packets); + const mcData=require("minecraft-data")(version); + const direction = isServer ? "toServer" : "toClient"; + const packets = mcData.protocol.states[state][direction]; + const proto=createProtocol(mcData.protocol.types,packets); return new Parser(proto,"packet"); } diff --git a/src/ursa.js b/src/ursa.js index fe35730..1ca32d5 100644 --- a/src/ursa.js +++ b/src/ursa.js @@ -1,4 +1,4 @@ -var ursa; +let ursa; try { ursa = require("ursa"); } catch(e) { From a222c4fd4921b76281c1b9e862185067cdabb979 Mon Sep 17 00:00:00 2001 From: Romain Beaumont Date: Mon, 1 Feb 2016 11:12:16 +0100 Subject: [PATCH 24/25] const has better scopes rules than var ! --- src/createServer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/createServer.js b/src/createServer.js index 118f4ec..aaf0dd6 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -197,13 +197,14 @@ function createServer(options) { } function onEncryptionKeyResponse(packet) { + let sharedSecret; try { const verifyToken = serverKey.decrypt(packet.verifyToken, undefined, undefined, ursa.RSA_PKCS1_PADDING); if(!bufferEqual(client.verifyToken, verifyToken)) { client.end('DidNotEncryptVerifyTokenProperly'); return; } - const sharedSecret = serverKey.decrypt(packet.sharedSecret, undefined, undefined, ursa.RSA_PKCS1_PADDING); + sharedSecret = serverKey.decrypt(packet.sharedSecret, undefined, undefined, ursa.RSA_PKCS1_PADDING); } catch(e) { client.end('DidNotEncryptVerifyTokenProperly'); return; From 8569b655941653f2f5b74712b66db3fdf5fd5fda Mon Sep 17 00:00:00 2001 From: Romain Beaumont Date: Tue, 2 Feb 2016 09:24:01 +0100 Subject: [PATCH 25/25] make autoVersion use const --- src/client/autoVersion.js | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/client/autoVersion.js b/src/client/autoVersion.js index 1e09e0a..4c45abc 100644 --- a/src/client/autoVersion.js +++ b/src/client/autoVersion.js @@ -1,36 +1,34 @@ -'use strict'; - -var ping = require('../ping'); -var debug = require('../debug'); -var states = require('../states'); -var assert = require('assert'); -var minecraft_data = require('minecraft-data'); +const ping = require('../ping'); +const debug = require('../debug'); +const states = require('../states'); +const assert = require('assert'); +const minecraft_data = require('minecraft-data'); module.exports = function(client, options) { client.wait_connect = true; // don't let src/client/setProtocol proceed on socket 'connect' until 'connect_allowed' debug('pinging',options.host); - var pingOptions = {host: options.host, port: options.port}; + const pingOptions = {host: options.host, port: options.port}; // TODO: use 0xfe ping instead for better compatibility/performance? https://github.com/deathcap/node-minecraft-ping ping(pingOptions, function(err, response) { if (err) throw err; // hmm debug('ping response',response); // TODO: could also use ping pre-connect to save description, type, max players, etc. - var motd = response.description; + const motd = response.description; debug('Server description:',motd); // TODO: save // Pass server-reported version to protocol handler // The version string is interpereted by https://github.com/PrismarineJS/node-minecraft-data - var minecraftVersion = response.version.name; // 1.8.9, 1.7.10 - var protocolVersion = response.version.protocol;// 47, 5 + const minecraftVersion = response.version.name; // 1.8.9, 1.7.10 + const protocolVersion = response.version.protocol;// 47, 5 debug(`Server version: ${minecraftVersion}, protocol: ${protocolVersion}`); // Note that versionName is a descriptive version stirng like '1.8.9' on vailla, but other // servers add their own name (Spigot 1.8.8, Glowstone++ 1.8.9) so we cannot use it directly, // even though it is in a format accepted by minecraft-data. Instead, translate the protocol. // TODO: pre-Netty version support (uses overlapping version numbers, so would have to check versionName) - var versionInfos = minecraft_data.postNettyVersionsByProtocolVersion[protocolVersion]; + const versionInfos = minecraft_data.postNettyVersionsByProtocolVersion[protocolVersion]; if (!versionInfos && versionInfos.length < 1) throw new Error(`unsupported/unknown protocol version: ${protocolVersion}, update minecraft-data`); - var versionInfo = versionInfos[0]; // use newest + const versionInfo = versionInfos[0]; // use newest options.version = versionInfo.minecraftVersion; options.protocolVersion = protocolVersion; @@ -40,7 +38,7 @@ module.exports = function(client, options) { if (response.modinfo && response.modinfo.type === 'FML') { // Use the list of Forge mods from the server ping, so client will match server - var forgeMods = response.modinfo.modList; + const forgeMods = response.modinfo.modList; debug('Using forgeMods:',forgeMods); // TODO: https://github.com/PrismarineJS/node-minecraft-protocol/issues/114 // https://github.com/PrismarineJS/node-minecraft-protocol/pull/326 @@ -51,4 +49,4 @@ module.exports = function(client, options) { client.emit('connect_allowed'); }); return client; -} +};