From 817fb9b51e4a75cd13e2660960566ed6a4f6efe5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 8 Jan 2013 00:50:43 -0500 Subject: [PATCH] add writers for most data types --- lib/protocol.js | 148 ++++++++++++++++++++++++++++++++++++++++++++---- test/test.js | 66 +++++++++++---------- 2 files changed, 175 insertions(+), 39 deletions(-) diff --git a/lib/protocol.js b/lib/protocol.js index 132b9f7..520360b 100644 --- a/lib/protocol.js +++ b/lib/protocol.js @@ -452,18 +452,146 @@ var types = { 'slot': [readSlot, SlotWriter], 'long': [readLong, LongWriter], 'ascii': [readAscii, AsciiWriter], - - 'byteArray32': [readByteArray32], - 'slotArray': [readSlotArray], - 'mapChunkBulk': [readMapChunkBulk], - 'entityMetadata': [readEntityMetadata], - 'objectData': [readObjectData], - 'intArray8': [readIntArray8], - 'intVector': [readIntVector], - 'byteVector': [readByteVector], - 'byteVectorArray': [readByteVectorArray], + 'entityMetadata': [readEntityMetadata, EntityMetadataWriter], + 'byteArray32': [readByteArray32, ByteArray32Writer], + 'slotArray': [readSlotArray, SlotArrayWriter], + 'mapChunkBulk': [readMapChunkBulk, MapChunkBulkWriter], + 'objectData': [readObjectData, ObjectDataWriter], + 'intArray8': [readIntArray8, IntArray8Writer], + 'intVector': [readIntVector, IntVectorWriter], + 'byteVector': [readByteVector, ByteVectorWriter], + 'byteVectorArray': [readByteVectorArray, ByteVectorArrayWriter], }; +function ByteArray32Writer(value) { + this.value = value; + this.size = 4 + value.length; +} + +ByteArray32Writer.prototype.write = function(buffer, offset) { + buffer.writeInt32BE(this.value.length, offset); + this.value.copy(buffer, offset + 4); +} + +function SlotArrayWriter(value) { + this.value = new Array(value.length) + this.size = 2; + var slotWriter; + for (var i = 0; i < value.length; ++i) { + this.value[i] = slotWriter = new SlotWriter(value[i]); + this.size += slotWriter.size; + } +} + +SlotArrayWriter.prototype.write = function(buffer, offset) { + buffer.writeInt16BE(this.value.length, offset); + offset += 2; + this.value.forEach(function(slotWriter) { + slotWriter.write(buffer, offset); + offset += slotWriter.size; + }); +} + +function EntityMetadataWriter(value) { +} + +EntityMetadataWriter.prototype.write = function() { + +} + +function MapChunkBulkWriter(value) { + this.value = value; + this.size = 7 + value.compressedChunkData.length + 12 * value.meta.length; +} + +MapChunkBulkWriter.prototype.write = function(buffer, offset) { + buffer.writeInt16BE(this.value.meta.length, offset); + offset += 2; + buffer.writeInt32BE(this.value.compressedChunkData.length, offset); + offset += 4; + buffer.writeInt8(+this.value.skyLightSent, offset); + offset += 1; + + this.value.compressedChunkData.copy(buffer, offset); + offset += this.value.compressedChunkData.length; + + var meta; + for (var i = 0; i < this.value.meta.length; ++i) { + meta = this.value.meta[i]; + buffer.writeInt32BE(meta.x, offset); + offset += 4; + buffer.writeInt32BE(meta.z, offset); + offset += 4; + buffer.writeUInt16BE(meta.bitMap, offset); + offset += 2; + buffer.writeUInt16BE(meta.addBitMap, offset); + offset += 2; + } +} + +function ObjectDataWriter(value) { + +} + +ObjectDataWriter.prototype.write = function() { + +} + +function IntArray8Writer(value) { + this.value = value; + this.size = 1 + 4 * value.length; +} + +IntArray8Writer.prototype.write = function(buffer, offset) { + buffer.writeInt8(this.value.length, offset); + offset += 1; + + this.value.forEach(function(item) { + buffer.writeInt32BE(item, offset); + offset += 4; + }); +} + +function IntVectorWriter(value) { + this.value = value; + this.size = 12; +} + +IntVectorWriter.prototype.write = function(buffer, offset) { + buffer.writeInt32BE(this.value.x, offset); + buffer.writeInt32BE(this.value.y, offset + 4); + buffer.writeInt32BE(this.value.z, offset + 8); +} + +function ByteVectorWriter(value) { + this.value = value; + this.size = 3; +} + +ByteVectorWriter.prototype.write = function(buffer, offset) { + buffer.writeInt8(this.value.x, offset); + buffer.writeInt8(this.value.y, offset + 1); + buffer.writeInt8(this.value.z, offset + 2); +} + +function ByteVectorArrayWriter(value) { + this.value = value; + this.size = 4 + 3 * value.length; +} + +ByteVectorArrayWriter.prototype.write = function(buffer, offset) { + buffer.writeInt32BE(this.value.length, offset); + offset += 4; + this.value.forEach(function(vec) { + buffer.writeInt8(vec.x, offset); + offset += 1; + buffer.writeInt8(vec.y, offset); + offset += 1; + buffer.writeInt8(vec.z, offset); + offset += 1; + }); +} + var entityMetadataReaders = { 0: readByte, 1: readShort, diff --git a/test/test.js b/test/test.js index 0ca76dc..cf890e0 100644 --- a/test/test.js +++ b/test/test.js @@ -45,34 +45,38 @@ var defaultServerProps = { 'motd': 'A Minecraft Server', }; +var eq = assert.strictEqual; +var ok = assert.ok; +var noop = function(){}; + 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': { + 'int': [123456, eq], + 'short': [-123, eq], + 'ushort': [123, eq], + 'byte': [-10, eq], + 'ubyte': [8, eq], + 'string': ["hi hi this is my string", eq], + 'byteArray16': [new Buffer(8), ok], + 'bool': [true, eq], + 'double': [99999.2222, eq], + 'float': [-333.444, eq], + 'slot': [{ id: 5, itemCount: 56, itemDamage: 2, nbtData: new Buffer(90), - }, + }, ok], - 'ascii': "hello", - 'byteArray32': new Buffer(10), - 'long': [0, 1], - 'slotArray': [{ + 'ascii': ["hello", eq], + 'byteArray32': [new Buffer(10), ok], + 'long': [[0, 1], ok], + 'slotArray': [[{ id: 41, itemCount: 2, itemDamage: 3, nbtData: new Buffer(0), - }], - 'mapChunkBulk': { + }], ok], + 'mapChunkBulk': [{ skyLightSent: true, compressedChunkData: new Buffer(1234), meta: [{ @@ -81,18 +85,18 @@ var values = { bitMap: 3, addBitMap: 10, }], - }, - 'entityMetadata': {}, - 'objectData': { + }, ok], + 'entityMetadata': [{}, ok], + '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}], + }, ok], + 'intArray8': [[1, 2, 3, 4], ok], + 'intVector': [{x: 1, y: 2, z: 3}, ok], + 'byteVector': [{x: 1, y: 2, z: 3}, ok], + 'byteVectorArray': [[{x: 1, y: 2, z: 3}], ok], } describe("packets", function() { @@ -139,7 +143,7 @@ describe("packets", function() { var packet = {}; packetInfo.forEach(function(field) { var value = field.type; - packet[field.name] = values[field.type]; + packet[field.name] = values[field.type][0]; }); serverClient.once(packetId, function(receivedPacket) { delete receivedPacket.id; @@ -154,9 +158,13 @@ describe("packets", function() { client.write(packetId, packet); } function assertPacketsMatch(p1, p2) { - var field; + packetInfo.forEach(function(field) { + var cmp = values[field.type][1]; + cmp(p1[field], p2[field]); + }); + var field, cmp; for (field in p1) { - assert.ok(field in p2, "field " + field + " missing in p2") + assert.ok(field in p2, "field " + field + " missing in p2"); } for (field in p2) { assert.ok(field in p1, "field " + field + " missing in p1");