test all packets

This commit is contained in:
Andrew Kelley 2013-01-07 23:36:14 -05:00
parent 5df31e4d88
commit 10cb3e0100
6 changed files with 173 additions and 26 deletions

View file

@ -24,6 +24,7 @@ function createServer(options) {
options['server-port'] != null ?
options['server-port'] :
25565 ;
var maxPlayers = options['max-players'] || 20;
var host = options.host || '0.0.0.0';
var kickTimeout = options.kickTimeout || 10 * 1000;
var checkTimeoutInterval = options.checkTimeoutInterval || 4 * 1000;
@ -32,6 +33,7 @@ function createServer(options) {
assert.ok(! onlineMode, "online mode for servers is not yet supported");
var server = new Server(options);
server.maxPlayers = maxPlayers;
server.on("connection", function(client) {
client.once(0xfe, onPing);
client.on(0x02, onHandshake);
@ -87,7 +89,7 @@ function createServer(options) {
protocol.minecraftVersion,
motd,
server.playerCount,
server.maxPlayers,
maxPlayers,
].join('\u0000')
});
}
@ -118,9 +120,7 @@ function createClient(options) {
var email = options.email;
var password = options.password;
var client = new Client({
isServer: false
});
var client = new Client(false);
client.username = options.username;
client.on('connect', function() {
client.write(0x02, {

View file

@ -7,12 +7,10 @@ var net = require('net')
module.exports = Client;
function Client(options) {
function Client(isServer) {
EventEmitter.call(this);
options = options || {};
this.isServer = !!options.isServer;
this.isServer = !!isServer;
this.socket = null;
this.encryptionEnabled = false;
this.cipher = null;

View file

@ -2,15 +2,6 @@ var assert = require('assert');
var STRING_MAX_LENGTH = 240;
module.exports = {
version: 51,
minecraftVersion: '1.4.7',
sessionVersion: 13,
parsePacket: parsePacket,
createPacketBuffer: createPacketBuffer,
STRING_MAX_LENGTH: STRING_MAX_LENGTH,
};
var packets = {
0x00: [
{ name: "keepAliveId", type: "int" }
@ -459,10 +450,10 @@ var types = {
'double': [readDouble, DoubleWriter],
'float': [readFloat, FloatWriter],
'slot': [readSlot, SlotWriter],
'long': [readLong, LongWriter],
'ascii': [readAscii, AsciiWriter],
'ascii': [readAscii],
'byteArray32': [readByteArray32],
'long': [readLong],
'slotArray': [readSlotArray],
'mapChunkBulk': [readMapChunkBulk],
'entityMetadata': [readEntityMetadata],
@ -886,6 +877,22 @@ StringWriter.prototype.write = function(buffer, offset) {
}
};
function AsciiWriter(value) {
this.value = value;
this.size = 2 + value.length;
}
AsciiWriter.prototype.write = function(buffer, offset) {
var cursor = offset;
buffer.writeInt16BE(this.value.length, cursor);
cursor += 2;
for (var i = 0; i < this.value.length; ++i) {
buffer.writeUInt8(this.value.charCodeAt(i), cursor);
cursor += 1;
}
};
function ByteArray16Writer(value) {
assert.ok(Buffer.isBuffer(value), "non buffer passed to ByteArray16Writer");
this.value = value;
@ -969,6 +976,16 @@ IntWriter.prototype.write = function(buffer, offset) {
buffer.writeInt32BE(this.value, offset);
}
function LongWriter(value) {
this.value = value;
this.size = 8;
}
LongWriter.prototype.write = function(buffer, offset) {
buffer.writeInt32BE(this.value[0], offset);
buffer.writeInt32BE(this.value[1], offset + 4);
}
function get(packetId, toServer) {
var packetInfo = packets[packetId];
return Array.isArray(packetInfo) ?
@ -1025,3 +1042,14 @@ function parsePacket(buffer, isServer) {
results: results,
};
}
module.exports = {
version: 51,
minecraftVersion: '1.4.7',
sessionVersion: 13,
parsePacket: parsePacket,
createPacketBuffer: createPacketBuffer,
STRING_MAX_LENGTH: STRING_MAX_LENGTH,
packets: packets,
get: get,
};

View file

@ -6,10 +6,9 @@ var net = require('net')
module.exports = Server;
function Server(options) {
function Server() {
EventEmitter.call(this);
this.maxPlayers = options['max-players'] || 20;
this.playerCount = 0
this.socketServer = null;
@ -24,9 +23,7 @@ Server.prototype.listen = function(port, host) {
var nextId = 0;
self.socketServer = net.createServer();
self.socketServer.on('connection', function(socket) {
var client = new Client({
isServer: true,
});
var client = new Client(true);
client.id = nextId++;
self.clients[client.id] = client;
client.on('error', function(err) {

View file

@ -28,7 +28,8 @@
"devDependencies": {
"mocha": "~1.7.4",
"mkdirp": "~0.3.4",
"rimraf": "~2.1.1"
"rimraf": "~2.1.1",
"zfill": "0.0.1"
},
"dependencies": {
"ursa": "~0.8.0",

View file

@ -1,12 +1,16 @@
var mc = require('../')
, protocol = require('../lib/protocol')
, protocol = mc.protocol
, Client = mc.Client
, Server = mc.Server
, spawn = require('child_process').spawn
, path = require('path')
, fs = require('fs')
, net = require('net')
, assert = require('assert')
, mkdirp = require('mkdirp')
, rimraf = require('rimraf')
, Batch = require('batch')
, zfill = require('zfill')
, MC_SERVER_JAR = process.env.MC_SERVER_JAR
, SURVIVE_TIME = 10000
, MC_SERVER_PATH = path.join(__dirname, 'server')
@ -41,6 +45,125 @@ var defaultServerProps = {
'motd': 'A Minecraft Server',
};
var values = {
'int': Math.floor(Math.random() * Math.pow(2, 16)),
'short': Math.floor(Math.random() * Math.pow(2, 8)),
'ushort': Math.floor(Math.random() * Math.pow(2, 16)),
'byte': Math.floor(Math.random() * Math.pow(2, 4)),
'ubyte': Math.floor(Math.random() * Math.pow(2, 8)),
'string': "hi hi this is my string",
'byteArray16': new Buffer(8),
'bool': Math.random() < 0.5,
'double': Math.random() * Math.pow(2, 64),
'float': Math.random() * Math.pow(2, 32),
'slot': {
id: 5,
itemCount: 56,
itemDamage: 2,
nbtData: new Buffer(90),
},
'ascii': "hello",
'byteArray32': new Buffer(10),
'long': [0, 1],
'slotArray': [{
id: 41,
itemCount: 2,
itemDamage: 3,
nbtData: new Buffer(0),
}],
'mapChunkBulk': {
skyLightSent: true,
compressedChunkData: new Buffer(1234),
meta: [{
x: 23,
z: 64,
bitMap: 3,
addBitMap: 10,
}],
},
'entityMetadata': {},
'objectData': {
intField: 9,
velocityX: 1,
velocityY: 2,
velocityZ: 3,
},
'intArray8': [1, 2, 3, 4],
'intVector': {x: 1, y: 2, z: 3},
'byteVector': {x: 1, y: 2, z: 3},
'byteVectorArray': [{x: 1, y: 2, z: 3}],
}
describe("packets", function() {
var client, server, serverClient;
before(function(done) {
server = new Server();
server.once('listening', function() {
server.once('connection', function(c) {
serverClient = c;
done();
});
client = new Client();
client.setSocket(net.connect(25565, 'localhost'));
});
server.listen(25565, 'localhost');
});
after(function(done) {
client.on('end', function() {
server.on('close', done);
server.close();
});
client.end();
});
var packetId, packetInfo, field;
for(packetId in protocol.packets) {
packetId = parseInt(packetId, 10);
packetInfo = protocol.packets[packetId];
it("0x" + zfill(parseInt(packetId, 10).toString(16), 2), callTestPacket(packetId, packetInfo));
}
function callTestPacket(packetId, packetInfo) {
return function(done) {
var batch = new Batch();
batch.push(function(done) {
testPacket(packetId, protocol.get(packetId, false), done);
});
batch.push(function(done) {
testPacket(packetId, protocol.get(packetId, true), done);
});
batch.end(done);
};
}
function testPacket(packetId, packetInfo, done) {
// empty object uses default values
var packet = {};
packetInfo.forEach(function(field) {
var value = field.type;
packet[field.name] = values[field.type];
});
serverClient.once(packetId, function(receivedPacket) {
delete receivedPacket.id;
assertPacketsMatch(packet, receivedPacket);
client.once(packetId, function(clientReceivedPacket) {
delete clientReceivedPacket.id;
assertPacketsMatch(receivedPacket, clientReceivedPacket);
done();
});
serverClient.write(packetId, receivedPacket);
});
client.write(packetId, packet);
}
function assertPacketsMatch(p1, p2) {
var field;
for (field in p1) {
assert.ok(field in p2, "field " + field + " missing in p2")
}
for (field in p2) {
assert.ok(field in p1, "field " + field + " missing in p1");
}
}
});
describe("client", function() {
this.timeout(20000);