From 767f64153b0e43623dd2de58a2718115cde5c544 Mon Sep 17 00:00:00 2001
From: Xabier de Zuazo <xabier@onddo.com>
Date: Mon, 8 Jul 2013 10:07:07 +0200
Subject: [PATCH] improved 0x64 packet support, code refactorized using an
 optional_fields hash

---
 lib/protocol.js | 65 +++++++++++++++++++++++++++++++++++--------------
 1 file changed, 47 insertions(+), 18 deletions(-)

diff --git a/lib/protocol.js b/lib/protocol.js
index 442db47..8f2a413 100644
--- a/lib/protocol.js
+++ b/lib/protocol.js
@@ -493,6 +493,17 @@ var packets = {
   ]
 };
 
+packet_optional_fields = {
+  0x64: {
+    condition: function(field_values) {
+      return field_values["inventoryType"] === 11;
+    },
+    fields: [
+      { name: "entityId", type: "int" }
+    ]
+  }
+};
+
 var types = {
   'int': [readInt, writeInt, 4],
   'short': [readShort, writeShort, 2],
@@ -1308,6 +1319,13 @@ function createPacketBuffer(packetId, params, isServer) {
   packet.forEach(function(fieldInfo) {
     size += sizeOf(fieldInfo.type, params[fieldInfo.name]);
   });
+  var optionalFields, i;
+  if (packet_optional_fields[packetId] && packet_optional_fields[packetId].condition && packet_optional_fields[packetId].condition(params)) {
+    optionalFields = packet_optional_fields[packetId].fields;
+    for (i = 0; i < optionalFields.length; ++i) {
+      size += sizeOf(optionalFields[i].type, params[optionalFields[i].name]);
+    }
+  }
   var buffer = new Buffer(size);
   var offset = writeUByte(packetId, buffer, 0);
   packet.forEach(function(fieldInfo) {
@@ -1320,6 +1338,21 @@ function createPacketBuffer(packetId, params, isServer) {
 }
 
 function parsePacket(buffer, isServer) {
+
+  function readPacketField(fieldInfo) {
+    var read = types[fieldInfo.type][0];
+    if (!read) {
+      return {
+        error: new Error("missing reader for data type: " + fieldInfo.type)
+      }
+    }
+    var readResults = read(buffer, size);
+    if (! readResults) return null; // buffer needs to be more full
+    if (readResults.error) return { error: readResults.error };
+
+    return readResults;
+  }
+
   if (buffer.length < 1) return null;
   var packetId = buffer.readUInt8(0);
   var size = 1;
@@ -1332,30 +1365,26 @@ function parsePacket(buffer, isServer) {
   } else {
     debug("read packetId " + packetId + " (0x" + packetId.toString(16) + ")");
   }
-  var i, fieldInfo, read, readResults;
+  var i, fieldInfo, readResults;
   for (i = 0; i < packetInfo.length; ++i) {
     fieldInfo = packetInfo[i];
-    read = types[fieldInfo.type][0];
-    if (!read) {
-      return {
-        error: new Error("missing reader for data type: " + fieldInfo.type)
-      }
+    readResults = readPacketField(fieldInfo);
+    if (!readResults || readResults.error) {
+      return readResults;
     }
-    readResults = read(buffer, size);
-    if (! readResults) return null; // buffer needs to be more full
-    if (readResults.error) return { error: readResults.error };
-
     results[fieldInfo.name] = readResults.value;
     size += readResults.size;
   }
-  if (packetId === 0x64 && results["inventoryType"] === 11) {
-    read = types["int"][0];
-    readResults = read(buffer, size);
-    if (! readResults) return null; // buffer needs to be more full
-    if (readResults.error) return { error: readResults.error };
-
-    results["entityId"] = readResults.value;
-    size += readResults.size;
+  if (packet_optional_fields[packetId] && packet_optional_fields[packetId].condition(results)) {
+    for (i = 0; i < packet_optional_fields[packetId].fields.length; ++i) {
+      fieldInfo = packet_optional_fields[packetId].fields[i];
+      readResults = readPacketField(fieldInfo);
+      if (!readResults || readResults.error) {
+        return readResults;
+      }
+      results[fieldInfo.name] = readResults.value;
+      size += readResults.size;
+    }
   }
   debug(results);
   return {