bedrock-protocol/src/createServer.js
2017-01-22 13:44:21 -05:00

147 lines
5.3 KiB
JavaScript

'use strict';
let raknet = require('raknet'),
zlib = require('zlib'),
ProtoDef = require('protodef').ProtoDef,
Parser = require('protodef').Parser,
Serializer = require('protodef').Serializer,
jwt = require('jwt-simple');
var debug = require('debug')('raknet');
let batchProto = new ProtoDef();
batchProto.addTypes(require('./datatypes/minecraft'));
batchProto.addType('insideBatch', ['endOfArray', {
'type': ['buffer', {
'countType': 'varint',
}]
}]);
const PUBLIC_KEY = 'MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8ELkixyLcwlZryUQcu1TvPOmI2B7vX83ndnWRUaXm74wFfa5f/lwQNTfrLVHa2PmenpGI6JhIMUJaWZrjmMj90NoKNFSNBuKdm8rYiXsfaz3K36x/1U26HpG0ZxK/V1V';
// createServer (object, boolean)
//
// Create & launch a MCPE raknet-based server.
// object: raknet options
// encryption: enable/disable encryption
function createServer(options, encryption) {
options = options || {};
const port = options.port != null ?
options.port :
options['server-port'] != null ?
options['server-port'] :
19132;
const host = options.host || '0.0.0.0';
options.customPackets = require('../data/protocol');
options.customTypes = require('./datatypes/minecraft');
let server = raknet.createServer(options);
server.name = options.name || 'Minecraft Server';
server.motd = options.motd || 'A Minecraft server'; //FIXME
server.maxPlayers = options['max-players'] || 20; //FIXME
server.playerCount = 0; //FIXME
server.on('connection', function(client) {
client.receiveCounter = 0;
client.sendCounter = 0;
client.encryptionEnabled = encryption ? true : false;
let proto = new ProtoDef();
proto.addTypes(require('./datatypes/minecraft'));
proto.addTypes(require('../data/protocol').types);
client.mcpePacketSerializer = new Serializer(proto, 'mcpe_packet');
client.on('mcpe', packet => {
client.emit(packet.name, packet.params);
client.emit('debug', packet.name);
});
client.on('batch', function (packets) {
var buf = zlib.inflateSync(packets.payload);
var packets = batchProto.parsePacketBuffer('insideBatch', buf).data;
packets.forEach(packet => client.readEncapsulatedPacket(Buffer.concat([new Buffer([0xfe]), packet])));
});
// client.writePacket (string, object)
// Send data to the client
//
// string: packet name
// object: packet data
client.writeMCPE = function (name, params) {
if (client.encryptionEnabled) {
client.mcpePacketSerializer.write({ name, params });
} else {
client.writeEncapsulated('mcpe', { name, params });
}
};
client.writePacket = client.writeMCPE;
// client.writeData (array)
// Send data to the client
//
// array: packets to send
client.writeBatch = function (packets) {
const payload = zlib.deflateSync(batchProto.createPacketBuffer('insideBatch',
packets.map(packet => client.mcpePacketSerializer.createPacketBuffer(packet))));
client.writePacket('batch', {
payload: payload
});
};
client.writeData = client.writeBatch;
// client.writeAll (string, object)
// Send data to the client
//
// string: packet name
// object: packet data
client.writeAll = function (name, data) {
return; //TODO
server._writeAll(name, data);
};
client.on('game_login', function (packet) {
try {
let dataProto = new ProtoDef();
dataProto.addType('data_chain', ['container', [{
'name': 'chain',
'type': ['pstring', {
'countType': 'li32'
}]
}, {
'name': 'clientData',
'type': ['pstring', {
'countType': 'li32'
}]
}]]);
//FIXME: Xbox & Non-Xbox support
console.log(packet);
let body = dataProto.parsePacketBuffer('data_chain', zlib.inflateSync(packet.body)),
chain = null,
decode = null,
data = null;
body.data.chain = JSON.parse(body.data.chain);
chain = body.data.chain.chain[0];
decode = jwt.decode(chain, PUBLIC_KEY, 'ES384');
data = jwt.decode(body.data.clientData, decode.identityPublicKey, 'ES384');
client.emit('mcpe_login', {
protocol: packet.protocol,
uuid: (decode.extraData != null) ? decode.extraData.identity : null,
id: (decode.extraData != null) ? decode.extraData.identityPublicKey : null,
username: (decode.extraData != null) ? decode.extraData.displayName : null,
skinData: data.SkinData,
skinId: data.SkinId
})
} catch (err) {
console.log(err);
return null;
}
});
});
return server;
}
module.exports = createServer;