diff --git a/src/datatypes/minecraft.js b/src/datatypes/minecraft.js new file mode 100644 index 0000000..5907b2e --- /dev/null +++ b/src/datatypes/minecraft.js @@ -0,0 +1,138 @@ +var nbt = require('prismarine-nbt'); +var utils = require("./utils"); +var numeric = require("./numeric"); + +module.exports = { + 'UUID': [readUUID, writeUUID, 16], + 'position': [readPosition, writePosition, 8], + 'slot': [readSlot, writeSlot, sizeOfSlot], + 'nbt': [readNbt, utils.buffer[1], utils.buffer[2]] +}; + +function readUUID(buffer, offset) { + return { + value: [ + buffer.readUInt32BE(offset), + buffer.readUInt32BE(offset + 4), + buffer.readUInt32BE(offset + 8), + buffer.readUInt32BE(offset + 12), + ], + size: 16, + }; +} + +function writeUUID(value, buffer, offset) { + buffer.writeUInt32BE(value[0], offset); + buffer.writeUInt32BE(value[1], offset + 4); + buffer.writeUInt32BE(value[2], offset + 8); + buffer.writeUInt32BE(value[3], offset + 12); + return offset + 16; +} + + +function readPosition(buffer, offset) { + var longVal = numeric.long[0](buffer, offset).value; + var x = signExtend26(longVal[0] >> 6); + var y = signExtend12(((longVal[0] & 0x3f) << 6) | ((longVal[1] >> 26) & 0x3f)); + var z = signExtend26(longVal[1] & 0x3FFFFFF); + return { + value: { x: x, y: y, z: z }, + size: 8 + }; +} +function signExtend26(value) { + if (value > 0x2000000) value -= 0x4000000; + return value; +} +function signExtend12(value) { + if (value > 0x800) value -= 0x1000; + return value; +} + + +function writePosition(value, buffer, offset) { + var longVal = []; + longVal[0] = ((value.x & 0x3FFFFFF) << 6) | ((value.y & 0xFFF) >> 6); + longVal[1] = ((value.y & 0x3F) << 26) | (value.z & 0x3FFFFFF); + return numeric.long[1](longVal, buffer, offset); +} + + +function readSlot(buffer, offset) { + var value = {}; + var results = numeric.short[0](buffer, offset); + if (! results) return null; + value.blockId = results.value; + + if (value.blockId === -1) { + return { + value: value, + size: 2, + }; + } + + var cursorEnd = offset + 6; + if (cursorEnd > buffer.length) return null; + value.itemCount = buffer.readInt8(offset + 2); + value.itemDamage = buffer.readInt16BE(offset + 3); + var nbtData = buffer.readInt8(offset + 5); + if (nbtData == 0) { + return { + value: value, + size: 6 + } + } + var nbtData = readNbt(buffer, offset + 5); + value.nbtData = nbtData.value; + return { + value: value, + size: nbtData.size + 5 + }; +} + +function writeSlot(value, buffer, offset) { + buffer.writeInt16BE(value.blockId, offset); + if (value.blockId === -1) return offset + 2; + buffer.writeInt8(value.itemCount, offset + 2); + buffer.writeInt16BE(value.itemDamage, offset + 3); + var nbtDataLen; + if (value.nbtData) + { + var newbuf = nbt.writeUncompressed(value.nbtData); + newbuf.copy(buffer, offset + 5); + nbtDataLen = newbuf.length; + } + else + { + buffer.writeInt8(0, offset + 5); + nbtDataLen = 1; + } + return offset + 5 + nbtDataLen; +} + +function sizeOfSlot(value) { + if (value.blockId === -1) + return (2); + else if (!value.nbtData) { + return (6); + } else { + return (5 + sizeOfNbt(value.nbtData)); + } +} + + +function readNbt(buffer, offset) { + buffer = buffer.slice(offset); + return nbt.parseUncompressed(buffer); +} + +function writeNbt(value, buffer, offset) { + var newbuf = nbt.writeUncompressed(value); + newbuf.copy(buffer, offset); + return offset + newbuf.length; +} + +function sizeOfNbt(value) { + return nbt.writeUncompressed(value).length; +} + diff --git a/src/protocol.js b/src/protocol.js index d7fb5c4..d910435 100644 --- a/src/protocol.js +++ b/src/protocol.js @@ -1,7 +1,6 @@ var assert = require('assert'); var util = require('util'); var zlib = require('zlib'); -var nbt = require('prismarine-nbt'); var getField= require("./utils").getField; @@ -53,6 +52,7 @@ var packetStates = {toClient: {}, toServer: {}}; var numeric=require("./datatypes/numeric"); var utils=require("./datatypes/utils"); +var minecraft=require("./datatypes/minecraft"); var types = { 'byte': numeric.byte, @@ -66,17 +66,17 @@ var types = { 'double': numeric.double, 'bool': utils.bool, 'string': utils.string, - 'ustring': utils.ustring, // TODO : remove ustring - 'UUID': [readUUID, writeUUID, 16], + 'ustring': utils.ustring, + 'UUID': minecraft.UUID, 'container': [readContainer, writeContainer, sizeOfContainer], 'array': [readArray, writeArray, sizeOfArray], 'buffer': utils.buffer, 'restBuffer': [readRestBuffer, utils.buffer[1], utils.buffer[2]], 'count': [readCount, writeCount, sizeOfCount], // TODO : remove type-specific, replace with generic containers and arrays. - 'position': [readPosition, writePosition, 8], - 'slot': [readSlot, writeSlot, sizeOfSlot], - 'nbt': [readNbt, utils.buffer[1], utils.buffer[2]], + 'position': minecraft.position, + 'slot': minecraft.slot, + 'nbt': minecraft.nbt, 'entityMetadata': [readEntityMetadata, writeEntityMetadata, sizeOfEntityMetadata], 'condition': [readCondition, writeCondition, sizeOfCondition] }; @@ -154,184 +154,66 @@ function evalCondition(condition,field_values) return b; } -function sizeOfEntityMetadata(value) { - var size = 1 + value.length; - var item; - for (var i = 0; i < value.length; ++i) { - item = value[i]; - size += sizeOf(item.value, entityMetadataTypes[entityMetadataTypeBytes[item.type]], {}); - } - return size; -} - -function writeEntityMetadata(value, buffer, offset) { - value.forEach(function(item) { - var type = entityMetadataTypeBytes[item.type]; - var headerByte = (type << 5) | item.key; - buffer.writeUInt8(headerByte, offset); - offset += 1; - offset = write(item.value, buffer, offset, entityMetadataTypes[type], {}); - }); - buffer.writeUInt8(0x7f, offset); - return offset + 1; -} - -function writeUUID(value, buffer, offset) { - buffer.writeUInt32BE(value[0], offset); - buffer.writeUInt32BE(value[1], offset + 4); - buffer.writeUInt32BE(value[2], offset + 8); - buffer.writeUInt32BE(value[3], offset + 12); - return offset + 16; -} function readEntityMetadata(buffer, offset) { - var cursor = offset; - var metadata = []; - var item, key, type, results, reader, typeName, dataType; - while (true) { - if (cursor + 1 > buffer.length) return null; - item = buffer.readUInt8(cursor); - cursor += 1; - if (item === 0x7f) { - return { - value: metadata, - size: cursor - offset, - }; + var cursor = offset; + var metadata = []; + var item, key, type, results, reader, typeName, dataType; + while (true) { + if (cursor + 1 > buffer.length) return null; + item = buffer.readUInt8(cursor); + cursor += 1; + if (item === 0x7f) { + return { + value: metadata, + size: cursor - offset, + }; + } + key = item & 0x1f; + type = item >> 5; + dataType = entityMetadataTypes[type]; + typeName = dataType.type; + //debug("Reading entity metadata type " + dataType + " (" + ( typeName || "unknown" ) + ")"); + if (!dataType) { + return { + error: new Error("unrecognized entity metadata type " + type) + } + } + results = read(buffer, cursor, dataType, {}); + if (! results) return null; + metadata.push({ + key: key, + value: results.value, + type: typeName, + }); + cursor += results.size; } - key = item & 0x1f; - type = item >> 5; - dataType = entityMetadataTypes[type]; - typeName = dataType.type; - //debug("Reading entity metadata type " + dataType + " (" + ( typeName || "unknown" ) + ")"); - if (!dataType) { - return { - error: new Error("unrecognized entity metadata type " + type) - } - } - results = read(buffer, cursor, dataType, {}); - if (! results) return null; - metadata.push({ - key: key, - value: results.value, - type: typeName, +} + + + +function writeEntityMetadata(value, buffer, offset) { + value.forEach(function(item) { + var type = entityMetadataTypeBytes[item.type]; + var headerByte = (type << 5) | item.key; + buffer.writeUInt8(headerByte, offset); + offset += 1; + offset = write(item.value, buffer, offset, entityMetadataTypes[type], {}); }); - cursor += results.size; - } + buffer.writeUInt8(0x7f, offset); + return offset + 1; } -function readNbt(buffer, offset) { - buffer = buffer.slice(offset); - return nbt.parseUncompressed(buffer); -} -function writeNbt(value, buffer, offset) { - var newbuf = nbt.writeUncompressed(value); - newbuf.copy(buffer, offset); - return offset + newbuf.length; -} -function sizeOfNbt(value) { - return nbt.writeUncompressed(value).length; -} - -function readUUID(buffer, offset) { - return { - value: [ - buffer.readUInt32BE(offset), - buffer.readUInt32BE(offset + 4), - buffer.readUInt32BE(offset + 8), - buffer.readUInt32BE(offset + 12), - ], - size: 16, - }; -} - -function readPosition(buffer, offset) { - var longVal = numeric.long[0](buffer, offset).value; - var x = signExtend26(longVal[0] >> 6); - var y = signExtend12(((longVal[0] & 0x3f) << 6) | ((longVal[1] >> 26) & 0x3f)); - var z = signExtend26(longVal[1] & 0x3FFFFFF); - return { - value: { x: x, y: y, z: z }, - size: 8 - }; -} -function signExtend26(value) { - if (value > 0x2000000) value -= 0x4000000; - return value; -} -function signExtend12(value) { - if (value > 0x800) value -= 0x1000; - return value; -} - -function readSlot(buffer, offset) { - var value = {}; - var results = numeric.short[0](buffer, offset); - if (! results) return null; - value.blockId = results.value; - - if (value.blockId === -1) { - return { - value: value, - size: 2, - }; - } - - var cursorEnd = offset + 6; - if (cursorEnd > buffer.length) return null; - value.itemCount = buffer.readInt8(offset + 2); - value.itemDamage = buffer.readInt16BE(offset + 3); - var nbtData = buffer.readInt8(offset + 5); - if (nbtData == 0) { - return { - value: value, - size: 6 +function sizeOfEntityMetadata(value) { + var size = 1 + value.length; + var item; + for (var i = 0; i < value.length; ++i) { + item = value[i]; + size += sizeOf(item.value, entityMetadataTypes[entityMetadataTypeBytes[item.type]], {}); } - } - var nbtData = readNbt(buffer, offset + 5); - value.nbtData = nbtData.value; - return { - value: value, - size: nbtData.size + 5 - }; -} - -function sizeOfSlot(value) { - if (value.blockId === -1) - return (2); - else if (!value.nbtData) { - return (6); - } else { - return (5 + sizeOfNbt(value.nbtData)); - } -} - -function writePosition(value, buffer, offset) { - var longVal = []; - longVal[0] = ((value.x & 0x3FFFFFF) << 6) | ((value.y & 0xFFF) >> 6); - longVal[1] = ((value.y & 0x3F) << 26) | (value.z & 0x3FFFFFF); - return numeric.long[1](longVal, buffer, offset); -} - -function writeSlot(value, buffer, offset) { - buffer.writeInt16BE(value.blockId, offset); - if (value.blockId === -1) return offset + 2; - buffer.writeInt8(value.itemCount, offset + 2); - buffer.writeInt16BE(value.itemDamage, offset + 3); - var nbtDataLen; - if (value.nbtData) - { - var newbuf = nbt.writeUncompressed(value.nbtData); - newbuf.copy(buffer, offset + 5); - nbtDataLen = newbuf.length; - } - else - { - buffer.writeInt8(0, offset + 5); - nbtDataLen = 1; - } - return offset + 5 + nbtDataLen; + return size; }