Merge pull request #369 from rom1504/custom_packets

add an optional property to add custom packets to createClient and createServer
This commit is contained in:
Romain Beaumont 2016-02-20 17:46:50 +01:00
commit 3b50ea9eb7
8 changed files with 83 additions and 11 deletions

View file

@ -18,8 +18,9 @@ automatically logged in and validated against mojang's auth.
* maxPlayers : default to 20
* keepAlive : send keep alive packets : default to true
* version : 1.8 or 1.9 : default to 1.8
* customPackets (optional) : an object index by version/state/direction/name, see client_custom_packet for an example
## mc.Server(version)
## mc.Server(version,[customPackets])
Create a server instance for `version` of minecraft.
@ -74,8 +75,9 @@ Returns a `Client` instance and perform login.
* 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 or false (to auto-negotiate): default to 1.8
* customPackets (optional) : an object index by version/state/direction/name, see client_custom_packet for an example
## mc.Client(isServer,version)
## mc.Client(isServer,version,[customPackets])
Create a new client, if `isServer` is true then it is a server-side client, otherwise it's a client-side client.
Takes a minecraft `version` as second argument.

View file

@ -0,0 +1,56 @@
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 customPackets={
"1.8": {
"play": {
"toClient": {
"my_custom_packet": {
"id": "0x7A",
"fields": [
{
"name": "age",
"type": "i64"
},
{
"name": "time",
"type": "i64"
}
]
}
}
}
}
};
var client = mc.createClient({
host: process.argv[2],
port: parseInt(process.argv[3]),
username: process.argv[4] ? process.argv[4] : "echo",
password: process.argv[5],
customPackets:customPackets
});
client.on('connect', function() {
console.info('connected');
});
client.on('disconnect', function(packet) {
console.log('disconnected: '+ packet.reason);
});
client.on('end', function(err) {
console.log('Connection lost');
});
client.on('login',function(){
client.deserializer.write(new Buffer("7A0000000000909327fffffffffffffc18","hex"));
console.log('login');
});
client.on('my_custom_packet',function(packet){
console.log(packet);
});

View file

@ -0,0 +1,8 @@
{
"name": "node-minecraft-protocol-example",
"version": "0.0.0",
"private": true,
"dependencies": {
},
"description": "A node-minecraft-protocol example"
}

View file

@ -10,8 +10,9 @@ const createDeserializer=require("./transforms/serializer").createDeserializer;
class Client extends EventEmitter
{
constructor(isServer,version) {
constructor(isServer,version,customPackets) {
super();
this.customPackets=customPackets;
this.version=version;
this.isServer = !!isServer;
this.splitter=framing.createSplitter();
@ -46,9 +47,9 @@ class Client extends EventEmitter
setSerializer(state) {
this.serializer = createSerializer({ isServer:this.isServer, version:this.version, state: state});
this.serializer = createSerializer({ isServer:this.isServer, version:this.version, state: state,customPackets:this.customPackets});
this.deserializer = createDeserializer({ isServer:this.isServer, version:this.version, state: state, packetsToParse:
this.packetsToParse});
this.packetsToParse,customPackets:this.customPackets});
this.splitter.recognizeLegacyPing = state === states.HANDSHAKING;

View file

@ -25,7 +25,7 @@ function createClient(options) {
options.majorVersion = version.majorVersion;
options.protocolVersion = version.version;
const client = new Client(false, version.minecraftVersion);
const client = new Client(false, version.minecraftVersion,options.customPackets);
tcp_dns(client, options);
caseCorrect(client, options);

View file

@ -32,7 +32,7 @@ function createServer(options) {
const serverKey = ursa.generatePrivateKey(1024);
const server = new Server(version.minecraftVersion);
const server = new Server(version.minecraftVersion,options.customPackets);
server.motd = options.motd || "A Minecraft server";
server.maxPlayers = options['max-players'] || 20;
server.playerCount = 0;

View file

@ -5,13 +5,14 @@ const states = require("./states");
class Server extends EventEmitter
{
constructor(version) {
constructor(version,customPackets) {
super();
this.version=version;
this.socketServer=null;
this.cipher=null;
this.decipher=null;
this.clients={};
this.customPackets=customPackets;
}
listen(port, host) {
@ -19,7 +20,7 @@ class Server extends EventEmitter
let nextId = 0;
self.socketServer = net.createServer();
self.socketServer.on('connection', socket => {
const client = new Client(true,this.version);
const client = new Client(true,this.version,this.customPackets);
client._end = client.end;
client.end = function end(endReason) {
endReason='{"text":"'+endReason+'"}';

View file

@ -36,21 +36,25 @@ function createProtocol(types,packets)
return proto;
}
function createSerializer({ state = states.HANDSHAKING, isServer = false , version} = {})
function createSerializer({ state = states.HANDSHAKING, isServer = false , version,customPackets} = {})
{
const mcData=require("minecraft-data")(version);
const direction = !isServer ? 'toServer' : 'toClient';
const packets = mcData.protocol.states[state][direction];
const v=mcData.version.majorVersion;
if(customPackets && customPackets[v] && customPackets[v][state] && customPackets[v][state][direction]) Object.keys(customPackets[v][state][direction]).forEach(name => packets[name]=customPackets[v][state][direction][name]);
const proto=createProtocol(mcData.protocol.types,packets);
return new Serializer(proto,"packet");
}
function createDeserializer({ state = states.HANDSHAKING, isServer = false,
packetsToParse = {"packet": true}, version } = {})
packetsToParse = {"packet": true}, version,customPackets } = {})
{
const mcData=require("minecraft-data")(version);
const direction = isServer ? "toServer" : "toClient";
const packets = mcData.protocol.states[state][direction];
const v=mcData.version.majorVersion;
if(customPackets && customPackets[v][state] && customPackets[v][state][direction]) Object.keys(customPackets[v][state][direction]).forEach(name => packets[name]=customPackets[v][state][direction][name]);
const proto=createProtocol(mcData.protocol.types,packets);
return new Parser(proto,"packet");
}