mirror of
https://github.com/unmojang/node-minecraft-protocol.git
synced 2025-09-28 13:45:37 -04:00
Add opportunistic parsing.
This commit is contained in:
parent
457df31b0b
commit
0a4b365242
@ -30,9 +30,48 @@ function Client(isServer) {
|
||||
this.encryptionEnabled = false;
|
||||
this.cipher = null;
|
||||
this.decipher = null;
|
||||
this.packetsToParse = {};
|
||||
this.on('newListener', function(event, listener) {
|
||||
var direction = this.isServer ? 'toServer' : 'toClient';
|
||||
if (protocol.packetStates[direction].hasOwnProperty(event)) {
|
||||
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';
|
||||
if (protocol.packetStates[direction].hasOwnProperty(event)) {
|
||||
this.packetsToParse[event] -= 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
util.inherits(Client, EventEmitter);
|
||||
|
||||
// Transform weird "packet" types into string representing their type. Should be mostly retro-compatible
|
||||
Client.prototype.on = function(type, func) {
|
||||
var direction = this.isServer ? 'toServer' : 'toClient';
|
||||
if (Array.isArray(type)) {
|
||||
arguments[0] = protocol.packetNames[type[0]][direction][type[1]];
|
||||
} else if (typeof type === "number") {
|
||||
arguments[0] = protocol.packetNames[this.state][direction][type];
|
||||
}
|
||||
EventEmitter.prototype.on.apply(this, arguments);
|
||||
};
|
||||
|
||||
Client.prototype.onRaw = function(type, func) {
|
||||
var arg = "raw.";
|
||||
if (Array.isArray(type)) {
|
||||
arg += protocol.packetNames[type[0]][direction][type[1]];
|
||||
} else if (typeof type === "number") {
|
||||
arg += protocol.packetNames[this.state][direction][type];
|
||||
} else {
|
||||
arg += type;
|
||||
}
|
||||
arguments[0] = arg;
|
||||
EventEmitter.prototype.on.apply(this, arguments);
|
||||
};
|
||||
|
||||
Client.prototype.setSocket = function(socket) {
|
||||
var self = this;
|
||||
self.socket = socket;
|
||||
@ -42,7 +81,7 @@ Client.prototype.setSocket = function(socket) {
|
||||
incomingBuffer = Buffer.concat([incomingBuffer, data]);
|
||||
var parsed, packet;
|
||||
while (true) {
|
||||
parsed = parsePacket(incomingBuffer, self.state, self.isServer);
|
||||
parsed = parsePacket(incomingBuffer, self.state, self.isServer, self.packetsToParse);
|
||||
if (! parsed) break;
|
||||
if (parsed.error) {
|
||||
this.emit('error', parsed.error);
|
||||
@ -53,11 +92,8 @@ Client.prototype.setSocket = function(socket) {
|
||||
incomingBuffer = incomingBuffer.slice(parsed.size);
|
||||
|
||||
var packetName = protocol.packetNames[self.state][self.isServer ? 'toServer' : 'toClient'][packet.id];
|
||||
if (packetName !== undefined) self.emit(packetName, packet);
|
||||
|
||||
self.emit([self.state, packet.id], packet);
|
||||
self.emit(packet.id, packet);
|
||||
self.emit('packet', packet);
|
||||
self.emit(packetName, packet);
|
||||
self.emit('raw.' + packetName, parsed.buffer);
|
||||
}
|
||||
});
|
||||
|
||||
@ -120,3 +156,11 @@ Client.prototype.write = function(packetId, params) {
|
||||
this.socket.write(out);
|
||||
return true;
|
||||
};
|
||||
|
||||
Client.prototype.writeRaw = function(buffer, shouldEncrypt) {
|
||||
if (shouldEncrypt === null) {
|
||||
shouldEncrypt = true;
|
||||
}
|
||||
var out = (shouldEncrypt && this.encryptionEnabled) ? new Buffer(this.cipher.update(buffer), 'binary') : buffer;
|
||||
this.socket.write(out);
|
||||
};
|
@ -1270,7 +1270,7 @@ function createPacketBuffer(packetId, state, params, isServer) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function parsePacket(buffer, state, isServer) {
|
||||
function parsePacket(buffer, state, isServer, packetsToParse) {
|
||||
if (state == null) state == states.PLAY;
|
||||
var cursor = 0;
|
||||
var lengthField = readVarInt(buffer, 0);
|
||||
@ -1279,19 +1279,30 @@ function parsePacket(buffer, state, isServer) {
|
||||
cursor += lengthField.size;
|
||||
if (length + lengthField.size > buffer.length) return null;
|
||||
var buffer = buffer.slice(0, length + cursor); // fail early if too much is read.
|
||||
|
||||
var packetIdField = readVarInt(buffer, lengthField.size);
|
||||
|
||||
var packetIdField = readVarInt(buffer, cursor);
|
||||
var packetId = packetIdField.value;
|
||||
cursor += packetIdField.size;
|
||||
|
||||
|
||||
var results = { id: packetId };
|
||||
// Only parse the packet if there is a need for it, AKA if there is a listener attached to it
|
||||
var name = packetNames[state][isServer ? "toServer" : "toClient"][packetId];
|
||||
if (!packetsToParse.hasOwnProperty(name) || packetsToParse[name] <= 0) {
|
||||
return {
|
||||
size: length + lengthField.size,
|
||||
buffer: buffer,
|
||||
results: results
|
||||
};
|
||||
}
|
||||
|
||||
var packetInfo = get(packetId, state, isServer);
|
||||
if (packetInfo === null) {
|
||||
return {
|
||||
error: new Error("Unrecognized packetId: " + packetId + " (0x" + packetId.toString(16) + ")"),
|
||||
size: length + lengthField.size,
|
||||
buffer: buffer,
|
||||
results: results
|
||||
}
|
||||
};
|
||||
} else {
|
||||
debug("read packetId " + packetId + " (0x" + packetId.toString(16) + ")");
|
||||
}
|
||||
@ -1323,6 +1334,7 @@ function parsePacket(buffer, state, isServer) {
|
||||
return {
|
||||
size: length + lengthField.size,
|
||||
results: results,
|
||||
buffer: buffer
|
||||
};
|
||||
}
|
||||
|
||||
@ -1336,6 +1348,7 @@ module.exports = {
|
||||
packetIds: packetIds,
|
||||
packetNames: packetNames,
|
||||
packetFields: packetFields,
|
||||
packetStates: packetStates,
|
||||
states: states,
|
||||
get: get,
|
||||
debug: debug,
|
||||
|
Loading…
x
Reference in New Issue
Block a user