mirror of
https://github.com/PrismarineJS/node-minecraft-protocol.git
synced 2024-11-14 19:04:59 -05:00
Merge pull request #331 from deathcap/dynxver
Add dynamic cross-protocol support
This commit is contained in:
commit
0ba187d97a
8 changed files with 107 additions and 6 deletions
|
@ -73,7 +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
|
||||
* version : 1.8 or 1.9 or false (to auto-negotiate): default to 1.8
|
||||
|
||||
## mc.Client(isServer,version)
|
||||
|
||||
|
|
29
examples/client_auto/client_auto.js
Normal file
29
examples/client_auto/client_auto.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
var mc = require('minecraft-protocol');
|
||||
|
||||
if(process.argv.length < 4 || process.argv.length > 6) {
|
||||
console.log("Usage : node echo.js <host> <port> [<name>] [<password>]");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var client = mc.createClient({version: false,
|
||||
host: process.argv[2],
|
||||
port: parseInt(process.argv[3]),
|
||||
username: process.argv[4] ? process.argv[4] : "echo",
|
||||
password: process.argv[5]
|
||||
});
|
||||
|
||||
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});
|
||||
}
|
||||
});
|
8
examples/client_auto/package.json
Normal file
8
examples/client_auto/package.json
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"name": "node-minecraft-protocol-example",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
},
|
||||
"description": "A node-minecraft-protocol example"
|
||||
}
|
|
@ -44,7 +44,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"buffer-equal": "0.0.1",
|
||||
"minecraft-data": "^0.16.1",
|
||||
"minecraft-data": "^0.19.1",
|
||||
"prismarine-nbt": "0.1.0",
|
||||
"protodef": "0.2.5",
|
||||
"readable-stream": "^1.1.0",
|
||||
|
|
|
@ -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;
|
||||
|
@ -220,6 +219,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);
|
||||
}
|
||||
|
|
54
src/client/autoVersion.js
Normal file
54
src/client/autoVersion.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
'use strict';
|
||||
|
||||
var ping = require('../ping');
|
||||
var debug = require('../debug');
|
||||
var states = require('../states');
|
||||
var assert = require('assert');
|
||||
var 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};
|
||||
// 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;
|
||||
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
|
||||
|
||||
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];
|
||||
if (!versionInfos && versionInfos.length < 1) throw new Error(`unsupported/unknown protocol version: ${protocolVersion}, update minecraft-data`);
|
||||
var versionInfo = versionInfos[0]; // use newest
|
||||
options.version = versionInfo.minecraftVersion;
|
||||
options.protocolVersion = protocolVersion;
|
||||
|
||||
// Reinitialize client object with new version TODO: move out of its constructor?
|
||||
client.version = versionInfo.majorVersion;
|
||||
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
|
||||
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
|
||||
// TODO: modify client object to set forgeMods and enable forgeHandshake
|
||||
throw new Error('FML/Forge not yet supported');
|
||||
}
|
||||
// Finished configuring client object, let connection proceed
|
||||
client.emit('connect_allowed');
|
||||
});
|
||||
return client;
|
||||
}
|
|
@ -5,6 +5,14 @@ module.exports = function(client, options) {
|
|||
client.on('connect', onConnect);
|
||||
|
||||
function onConnect() {
|
||||
if (client.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
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -24,12 +27,13 @@ function createClient(options) {
|
|||
var client = new Client(false, options.majorVersion);
|
||||
|
||||
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);
|
||||
caseCorrect(client, options);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue