mirror of
https://github.com/PrismarineJS/node-minecraft-protocol.git
synced 2025-05-19 17:50:24 -04:00
test all packets
This commit is contained in:
parent
5df31e4d88
commit
10cb3e0100
6 changed files with 173 additions and 26 deletions
8
index.js
8
index.js
|
@ -24,6 +24,7 @@ function createServer(options) {
|
||||||
options['server-port'] != null ?
|
options['server-port'] != null ?
|
||||||
options['server-port'] :
|
options['server-port'] :
|
||||||
25565 ;
|
25565 ;
|
||||||
|
var maxPlayers = options['max-players'] || 20;
|
||||||
var host = options.host || '0.0.0.0';
|
var host = options.host || '0.0.0.0';
|
||||||
var kickTimeout = options.kickTimeout || 10 * 1000;
|
var kickTimeout = options.kickTimeout || 10 * 1000;
|
||||||
var checkTimeoutInterval = options.checkTimeoutInterval || 4 * 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");
|
assert.ok(! onlineMode, "online mode for servers is not yet supported");
|
||||||
|
|
||||||
var server = new Server(options);
|
var server = new Server(options);
|
||||||
|
server.maxPlayers = maxPlayers;
|
||||||
server.on("connection", function(client) {
|
server.on("connection", function(client) {
|
||||||
client.once(0xfe, onPing);
|
client.once(0xfe, onPing);
|
||||||
client.on(0x02, onHandshake);
|
client.on(0x02, onHandshake);
|
||||||
|
@ -87,7 +89,7 @@ function createServer(options) {
|
||||||
protocol.minecraftVersion,
|
protocol.minecraftVersion,
|
||||||
motd,
|
motd,
|
||||||
server.playerCount,
|
server.playerCount,
|
||||||
server.maxPlayers,
|
maxPlayers,
|
||||||
].join('\u0000')
|
].join('\u0000')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -118,9 +120,7 @@ function createClient(options) {
|
||||||
var email = options.email;
|
var email = options.email;
|
||||||
var password = options.password;
|
var password = options.password;
|
||||||
|
|
||||||
var client = new Client({
|
var client = new Client(false);
|
||||||
isServer: false
|
|
||||||
});
|
|
||||||
client.username = options.username;
|
client.username = options.username;
|
||||||
client.on('connect', function() {
|
client.on('connect', function() {
|
||||||
client.write(0x02, {
|
client.write(0x02, {
|
||||||
|
|
|
@ -7,12 +7,10 @@ var net = require('net')
|
||||||
|
|
||||||
module.exports = Client;
|
module.exports = Client;
|
||||||
|
|
||||||
function Client(options) {
|
function Client(isServer) {
|
||||||
EventEmitter.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
options = options || {};
|
this.isServer = !!isServer;
|
||||||
|
|
||||||
this.isServer = !!options.isServer;
|
|
||||||
this.socket = null;
|
this.socket = null;
|
||||||
this.encryptionEnabled = false;
|
this.encryptionEnabled = false;
|
||||||
this.cipher = null;
|
this.cipher = null;
|
||||||
|
|
|
@ -2,15 +2,6 @@ var assert = require('assert');
|
||||||
|
|
||||||
var STRING_MAX_LENGTH = 240;
|
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 = {
|
var packets = {
|
||||||
0x00: [
|
0x00: [
|
||||||
{ name: "keepAliveId", type: "int" }
|
{ name: "keepAliveId", type: "int" }
|
||||||
|
@ -459,10 +450,10 @@ var types = {
|
||||||
'double': [readDouble, DoubleWriter],
|
'double': [readDouble, DoubleWriter],
|
||||||
'float': [readFloat, FloatWriter],
|
'float': [readFloat, FloatWriter],
|
||||||
'slot': [readSlot, SlotWriter],
|
'slot': [readSlot, SlotWriter],
|
||||||
|
'long': [readLong, LongWriter],
|
||||||
|
'ascii': [readAscii, AsciiWriter],
|
||||||
|
|
||||||
'ascii': [readAscii],
|
|
||||||
'byteArray32': [readByteArray32],
|
'byteArray32': [readByteArray32],
|
||||||
'long': [readLong],
|
|
||||||
'slotArray': [readSlotArray],
|
'slotArray': [readSlotArray],
|
||||||
'mapChunkBulk': [readMapChunkBulk],
|
'mapChunkBulk': [readMapChunkBulk],
|
||||||
'entityMetadata': [readEntityMetadata],
|
'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) {
|
function ByteArray16Writer(value) {
|
||||||
assert.ok(Buffer.isBuffer(value), "non buffer passed to ByteArray16Writer");
|
assert.ok(Buffer.isBuffer(value), "non buffer passed to ByteArray16Writer");
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
@ -969,6 +976,16 @@ IntWriter.prototype.write = function(buffer, offset) {
|
||||||
buffer.writeInt32BE(this.value, 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) {
|
function get(packetId, toServer) {
|
||||||
var packetInfo = packets[packetId];
|
var packetInfo = packets[packetId];
|
||||||
return Array.isArray(packetInfo) ?
|
return Array.isArray(packetInfo) ?
|
||||||
|
@ -1025,3 +1042,14 @@ function parsePacket(buffer, isServer) {
|
||||||
results: results,
|
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,
|
||||||
|
};
|
||||||
|
|
|
@ -6,10 +6,9 @@ var net = require('net')
|
||||||
|
|
||||||
module.exports = Server;
|
module.exports = Server;
|
||||||
|
|
||||||
function Server(options) {
|
function Server() {
|
||||||
EventEmitter.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
this.maxPlayers = options['max-players'] || 20;
|
|
||||||
this.playerCount = 0
|
this.playerCount = 0
|
||||||
|
|
||||||
this.socketServer = null;
|
this.socketServer = null;
|
||||||
|
@ -24,9 +23,7 @@ Server.prototype.listen = function(port, host) {
|
||||||
var nextId = 0;
|
var nextId = 0;
|
||||||
self.socketServer = net.createServer();
|
self.socketServer = net.createServer();
|
||||||
self.socketServer.on('connection', function(socket) {
|
self.socketServer.on('connection', function(socket) {
|
||||||
var client = new Client({
|
var client = new Client(true);
|
||||||
isServer: true,
|
|
||||||
});
|
|
||||||
client.id = nextId++;
|
client.id = nextId++;
|
||||||
self.clients[client.id] = client;
|
self.clients[client.id] = client;
|
||||||
client.on('error', function(err) {
|
client.on('error', function(err) {
|
||||||
|
|
|
@ -28,7 +28,8 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mocha": "~1.7.4",
|
"mocha": "~1.7.4",
|
||||||
"mkdirp": "~0.3.4",
|
"mkdirp": "~0.3.4",
|
||||||
"rimraf": "~2.1.1"
|
"rimraf": "~2.1.1",
|
||||||
|
"zfill": "0.0.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ursa": "~0.8.0",
|
"ursa": "~0.8.0",
|
||||||
|
|
125
test/test.js
125
test/test.js
|
@ -1,12 +1,16 @@
|
||||||
var mc = require('../')
|
var mc = require('../')
|
||||||
, protocol = require('../lib/protocol')
|
, protocol = mc.protocol
|
||||||
|
, Client = mc.Client
|
||||||
|
, Server = mc.Server
|
||||||
, spawn = require('child_process').spawn
|
, spawn = require('child_process').spawn
|
||||||
, path = require('path')
|
, path = require('path')
|
||||||
, fs = require('fs')
|
, fs = require('fs')
|
||||||
|
, net = require('net')
|
||||||
, assert = require('assert')
|
, assert = require('assert')
|
||||||
, mkdirp = require('mkdirp')
|
, mkdirp = require('mkdirp')
|
||||||
, rimraf = require('rimraf')
|
, rimraf = require('rimraf')
|
||||||
, Batch = require('batch')
|
, Batch = require('batch')
|
||||||
|
, zfill = require('zfill')
|
||||||
, MC_SERVER_JAR = process.env.MC_SERVER_JAR
|
, MC_SERVER_JAR = process.env.MC_SERVER_JAR
|
||||||
, SURVIVE_TIME = 10000
|
, SURVIVE_TIME = 10000
|
||||||
, MC_SERVER_PATH = path.join(__dirname, 'server')
|
, MC_SERVER_PATH = path.join(__dirname, 'server')
|
||||||
|
@ -41,6 +45,125 @@ var defaultServerProps = {
|
||||||
'motd': 'A Minecraft Server',
|
'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() {
|
describe("client", function() {
|
||||||
this.timeout(20000);
|
this.timeout(20000);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue