diff --git a/lib/protocol.js b/lib/protocol.js index 370e55b..f2dd9d9 100644 --- a/lib/protocol.js +++ b/lib/protocol.js @@ -1,15 +1,17 @@ -var Iconv = require('iconv').Iconv - , assert = require('assert') - , toUcs2 = new Iconv('UTF-8', 'utf16be') - , fromUcs2 = new Iconv('utf16be', 'UTF-8') +var assert = require('assert'); var STRING_MAX_LENGTH = 240; -exports.version = 51; -exports.minecraftVersion = '1.4.6'; -exports.sessionVersion = 13; -exports.parsePacket = parsePacket; -exports.createPacketBuffer = createPacketBuffer; +module.exports = { + version: 51, + minecraftVersion: '1.4.6', + sessionVersion: 13, + parsePacket: parsePacket, + createPacketBuffer: createPacketBuffer, + constants: { + STRING_MAX_LENGTH: STRING_MAX_LENGTH, + }, +}; var packets = { 0x00: [ @@ -681,18 +683,20 @@ function readAscii (buffer, offset) { } function readString (buffer, offset) { - var results = readShort(buffer, offset); - if (! results) return null; - - var strBegin = offset + results.size; - var strLen = results.value; - var strEnd = strBegin + strLen * 2; + var cursor = offset + 2; + if (cursor > buffer.length) return null; + var stringLength = buffer.readInt16BE(offset); + var strEnd = cursor + stringLength * 2; if (strEnd > buffer.length) return null; - var str = fromUcs2.convert(buffer.slice(strBegin, strEnd)).toString('utf8'); + var value = ''; + for (var i = 0; i < stringLength; ++i) { + value += String.fromCharCode(buffer.readUInt16BE(cursor)); + cursor += 2; + } return { - value: str, - size: strEnd - offset, + value: value, + size: cursor - offset, }; } @@ -878,14 +882,20 @@ SlotWriter.prototype.write = function(buffer, offset) { }; function StringWriter(value) { + assert.ok(value.length < STRING_MAX_LENGTH, "string greater than max length"); this.value = value; - this.encoded = toUcs2.convert(value); - this.size = 2 + this.encoded.length; + this.size = 2 + 2 * value.length; } StringWriter.prototype.write = function(buffer, offset) { - buffer.writeInt16BE(this.value.length, offset); - this.encoded.copy(buffer, offset + 2); + var cursor = offset; + buffer.writeInt16BE(this.value.length, cursor); + cursor += 2; + + for (var i = 0; i < this.value.length; ++i) { + buffer.writeUInt16BE(this.value.charCodeAt(i), cursor); + cursor += 2; + } }; function ByteArray16Writer(value) { diff --git a/package.json b/package.json index cc650fc..5f6cee5 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ "dependencies": { "ursa": "~0.8.0", "superagent": "~0.10.0", - "iconv": "~1.2.4", "batch": "~0.2.1" } } diff --git a/test/test.js b/test/test.js index 821bafc..2307332 100644 --- a/test/test.js +++ b/test/test.js @@ -40,7 +40,7 @@ var defaultServerProps = { 'motd': 'A Minecraft Server', }; -describe("minecraft protocol", function() { +describe("client", function() { this.timeout(20000); var mcServer; @@ -213,3 +213,7 @@ describe("minecraft protocol", function() { }); }); }); +describe("server", function() { + it("kicks clients that do not emit keep alive"); + it("responds to ping requests"); +});