it still doesn't work

This commit is contained in:
Keegan 2016-03-06 17:23:05 -05:00
commit 783664863e
8 changed files with 303 additions and 5 deletions

110
src/client.js Normal file
View file

@ -0,0 +1,110 @@
'use strict';
var EventEmitter = require('events').EventEmitter;
var debug = require('./debug');
var createSerializer = require("./transforms/serializer").createSerializer;
var createDeserializer = require("./transforms/serializer").createDeserializer;
class Client extends EventEmitter {
constructor(isServer) {
super();
this.isServer = !!isServer;
}
setSerializer() {
this.serializer = createSerializer(this.isServer);
this.deserializer = createDeserializer(this.isServer);
this.serializer.on('error', (e) => {
var parts = e.field.split(".");
parts.shift();
e.message = `Serialization error for ${e.message}`;
this.emit('error', e);
});
this.deserializer.on('error', (e) => {
var parts = e.field.split(".");
parts.shift();
e.message = `Deserialization error for ${e.message}`;
this.emit('error', e);
});
this.deserializer.on('data', (parsed) => {
parsed.metadata.name = parsed.data.name;
parsed.data = parsed.data.params;
this.emit('packet', parsed.data, parsed.metadata);
debug("reading packet " + "." + parsed.metadata.name);
debug(parsed.data);
this.emit(parsed.metadata.name, parsed.data, parsed.metadata);
this.emit('raw.' + parsed.metadata.name, parsed.buffer, parsed.metadata);
this.emit('raw', parsed.buffer, parsed.metadata);
});
}
setSocket(socket) {
var ended = false;
var endSocket = function() {
if (ended) return;
ended = true;
this.socket.removeListener('close', endSocket);
this.socket.removeListener('end', endSocket);
this.socket.removeListener('timeout', endSocket);
this.emit('end', this._endReason);
};
var onFatalError = function(err) {
this.emit('error', err);
endSocket();
};
var onError = function(err) {
this.emit('error', err);
}
this.socket = socket;
if (this.socket.setNoDelay) {
this.socket.setNoDelay(true);
}
this.socket.on('connect', function() {
this.emit('connect');
});
this.socket.on('error', onFatalError);
this.socket.on('close', endSocket);
this.socket.on('end', endSocket);
this.socket.on('timeout', endSocket);
this.setSerializer();
this.socket.pipe(this.deserializer);
this.serializer.pipe(this.socket);
}
end(reason) {
this._endReason = reason;
if (this.socket)
this.socket.end();
}
write(name, params) {
debug("writing packet " + "." + name);
debug(params);
this.serializer.write({
name,
params
});
}
writeRaw(buffer) {
this.socket.write(buffer);
}
}
module.exports = Client;

42
src/createClient.js Normal file
View file

@ -0,0 +1,42 @@
'use strict';
var net = require('net');
var dns = require('dns');
var Client = require('./client');
var assert = require('assert');
module.exports = createClient;
Client.prototype.connect = function(port, host) {
var self = this;
if(port == 19132 && net.isIP(host) === 0) {
dns.resolveSrv(host, function(err, addresses) {
if(addresses && addresses.length > 0) {
self.setSocket(net.connect(addresses[0].port, addresses[0].name));
} else {
self.setSocket(net.connect(port, host));
}
});
} else {
self.setSocket(net.connect(port, host));
}
};
function createClient(options) {
assert.ok(options, "options is required");
var port = options.port || 19132;
var host = options.host || 'localhost';
assert.ok(options.username, "username is required");
var client = new Client(false);
client.on('connect', onConnect);
client.username = options.username;
client.connect(port, host);
function onConnect() {
// we should probably implement the login protocol for the client here
}
return client;
}

68
src/createServer.js Normal file
View file

@ -0,0 +1,68 @@
var Server = require('./server');
function createServer(options) {
options = options || {};
var port = options.port != null ?
options.port :
options['server-port'] != null ?
options['server-port'] :
19132;
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'];
var beforePing = options.beforePing || null;
var enablePing = options.ping == null ? true : options.ping;
var server = new Server();
server.name = options.name || "Minecraft Server";
server.motd = options.motd || "A Minecraft server";
server.maxPlayers = options['max-players'] || 20;
server.playerCount = 0;
server.onlineModeExceptions = {};
server.on("connection", function (client) {
client.once('player_identification', onLogin);
client.on('end', onEnd);
var ping = true;
var pingTimer = null;
function pingLoop() {
client.write('ping', {});
}
function startPing() {
pingTimer = setInterval(pingLoop, checkTimeoutInterval);
}
function onEnd() {
clearInterval(pingTimer);
}
function onLogin(packet) {
client.username=packet.username;
client.identification_byte=packet.unused;
if(options.handshake)
{
options.handshake(function(){
continueLogin();
})
}
else
continueLogin();
}
function continueLogin() {
// we should probably implement the login protocol here
server.emit('login', client);
startPing();
}
});
server.listen(port, host);
return server;
}
module.exports = createServer;

18
src/debug.js Normal file
View file

@ -0,0 +1,18 @@
var util = require('util')
var debug;
if(process.env.NODE_DEBUG) {
var pid = process.pid;
debug = function(x) {
// if console is not set up yet, then skip this.
if(!console.error)
return;
console.error('MC-PROTO: %d', pid,
util.format.apply(util, arguments));
};
} else {
debug = function() {
};
}
module.exports = debug;

View file

@ -1,4 +1,6 @@
module.exports = {
createDeserializer: require('./serializer').createDeserializer,
createSerializer: require('./serializer').createSerializer
}
createSerializer: require("./transforms/serializer").createSerializer,
createDeserializer: require("./transforms/serializer").createDeserializer,
createServer: require("./createServer"),
createClient: require("./createClient")
};

58
src/server.js Normal file
View file

@ -0,0 +1,58 @@
'use strict';
var net = require('net');
var EventEmitter = require('events').EventEmitter;
var Client = require('./client');
class Server extends EventEmitter {
constructor() {
super();
}
listen(port, host) {
var self = this;
var nextId = 0;
self.socketServer = net.createServer();
self.socketServer.on('connection', socket => {
var client = new Client(true);
// client._end = client.end;
// client.end = function end(endReason) {
// client.write('disconnect_player', {
// disconnect_reason: endReason
// });
// client._end(endReason);
// };
client.id = nextId++;
self.clients[client.id] = client;
client.on('end', function () {
delete self.clients[client.id];
});
client.setSocket(socket);
self.emit('connection', client);
});
self.socketServer.on('error', function (err) {
self.emit('error', err);
});
self.socketServer.on('close', function () {
self.emit('close');
});
self.socketServer.on('listening', function () {
self.emit('listening');
});
self.socketServer.listen(port, host);
}
close() {
var client;
for (var clientId in this.clients) {
if (!this.clients.hasOwnProperty(clientId)) continue;
client = this.clients[clientId];
client.end('ServerShutdown');
}
this.socketServer.close();
}
}
module.exports = Server;

View file

@ -2,11 +2,11 @@ var ProtoDef = require('protodef').ProtoDef;
var Serializer = require('protodef').Serializer;
var Parser = require('protodef').Parser;
var protocol = require('../data/protocol.json').types;
var protocol = require(__dirname + '/../../data/protocol.json').types;
function createProtocol(packets) {
var proto = new ProtoDef();
proto.addTypes(require('./datatypes'));
proto.addTypes(require('../datatypes/minecraft'));
return proto;
}