Switched from constructors to functions in serialization code

This commit is contained in:
Matt Bell 2013-03-18 13:02:57 -07:00
parent 169fa1c986
commit 367b8a96da

View File

@ -475,58 +475,56 @@ var packets = {
};
var types = {
'int': [readInt, IntWriter],
'short': [readShort, ShortWriter],
'ushort': [readUShort, UShortWriter],
'byte': [readByte, ByteWriter],
'ubyte': [readUByte, UByteWriter],
'string': [readString, StringWriter],
'byteArray16': [readByteArray16, ByteArray16Writer],
'bool': [readBool, BoolWriter],
'double': [readDouble, DoubleWriter],
'float': [readFloat, FloatWriter],
'slot': [readSlot, SlotWriter],
'long': [readLong, LongWriter],
'ascii': [readAscii, AsciiWriter],
'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],
'stringArray': [readStringArray, StringArrayWriter],
'int': [readInt, writeInt, 4],
'short': [readShort, writeShort, 2],
'ushort': [readUShort, writeUShort, 2],
'byte': [readByte, writeByte, 1],
'ubyte': [readUByte, writeUByte, 1],
'string': [readString, writeString, sizeOfString],
'byteArray16': [readByteArray16, writeByteArray16, sizeOfByteArray16],
'bool': [readBool, writeBool, 1],
'double': [readDouble, writeDouble, 8],
'float': [readFloat, writeFloat, 4],
'slot': [readSlot, writeSlot, sizeOfSlot],
'long': [readLong, writeLong, 8],
'ascii': [readAscii, writeAscii, sizeOfAscii],
'entityMetadata': [readEntityMetadata, writeEntityMetadata, sizeOfEntityMetadata],
'byteArray32': [readByteArray32, writeByteArray32, sizeOfByteArray32],
'slotArray': [readSlotArray, writeSlotArray, sizeOfSlotArray],
'mapChunkBulk': [readMapChunkBulk, writeMapChunkBulk, sizeOfMapChunkBulk],
'objectData': [readObjectData, writeObjectData, sizeOfObjectData],
'intArray8': [readIntArray8, writeIntArray8, sizeOfIntArray8],
'intVector': [readIntVector, writeIntVector, 12],
'byteVector': [readByteVector, writeByteVector, 3],
'byteVectorArray': [readByteVectorArray, writeByteVectorArray, sizeOfByteVectorArray],
'stringArray': [readStringArray, writeStringArray, sizeOfStringArray],
};
function ByteArray32Writer(value) {
this.value = value;
this.size = 4 + value.length;
function sizeOfByteArray32(value) {
return 4 + value.length;
}
ByteArray32Writer.prototype.write = function(buffer, offset) {
buffer.writeInt32BE(this.value.length, offset);
this.value.copy(buffer, offset + 4);
function writeByteArray32(value, buffer, offset) {
buffer.writeInt32BE(value.length, offset);
value.copy(buffer, offset + 4);
return offset + 4 + value.length;
}
function SlotArrayWriter(value) {
this.value = new Array(value.length)
this.size = 2;
var slotWriter;
function sizeOfSlotArray(value) {
var size = 2;
for (var i = 0; i < value.length; ++i) {
this.value[i] = slotWriter = new SlotWriter(value[i]);
this.size += slotWriter.size;
size += sizeOfSlot(value[i]);
}
return size;
}
SlotArrayWriter.prototype.write = function(buffer, offset) {
buffer.writeInt16BE(this.value.length, offset);
function writeSlotArray(value, buffer, offset) {
buffer.writeInt16BE(value.length, offset);
offset += 2;
this.value.forEach(function(slotWriter) {
slotWriter.write(buffer, offset);
offset += slotWriter.size;
value.forEach(function(slot) {
offset = writeSlot(slot, buffer, offset);
});
return offset;
}
var entityMetadataTypes = {
@ -545,73 +543,62 @@ for (var n in entityMetadataTypes) {
entityMetadataTypeBytes[entityMetadataTypes[n]] = n;
}
function EntityMetadataWriter(value) {
this.value = [];
this.size = 1 + value.length;
var item, Writer, writer, dataType;
function sizeOfEntityMetadata(value) {
var size = 1 + value.length;
var item, dataType;
for (var i = 0; i < value.length; ++i) {
item = value[i];
dataType = types[item.type];
assert.ok(dataType, "unknown data type " + dataType);
Writer = dataType[1];
assert.ok(Writer, "missing writer for data type " + item.type);
writer = new Writer(item.value);
this.size += writer.size;
this.value.push({
writer: writer,
key: item.key,
type: entityMetadataTypeBytes[item.type],
});
size += sizeOf(item.type, item.value);
}
return size;
}
EntityMetadataWriter.prototype.write = function(buffer, offset) {
this.value.forEach(function(item) {
function writeEntityMetadata(value, buffer, offset) {
value.forEach(function(item) {
var headerByte = (item.type << 5) | item.key;
buffer.writeUInt8(headerByte, offset);
offset += 1;
item.writer.write(buffer, offset);
offset += item.writer.size;
offset = types[item.type][1](item.value, buffer, offset);
});
buffer.writeUInt8(0x7f, offset);
return offset + 1;
}
function ObjectDataWriter(value) {
this.value = value;
this.size = value.intField === 0 ? 4 : 10;
function sizeOfObjectData(value) {
return value.intField === 0 ? 4 : 10;
}
ObjectDataWriter.prototype.write = function(buffer, offset) {
buffer.writeInt32BE(this.value.intField, offset);
if (this.value.intField === 0) return;
function writeObjectData(value, buffer, offset) {
buffer.writeInt32BE(value.intField, offset);
if (value.intField === 0) return;
offset += 4;
buffer.writeInt16BE(this.value.velocityX, offset);
buffer.writeInt16BE(value.velocityX, offset);
offset += 2;
buffer.writeInt16BE(this.value.velocityY, offset);
buffer.writeInt16BE(value.velocityY, offset);
offset += 2;
buffer.writeInt16BE(this.value.velocityZ, offset);
buffer.writeInt16BE(value.velocityZ, offset);
return offset + 2;
}
function MapChunkBulkWriter(value) {
this.value = value;
this.size = 7 + value.compressedChunkData.length + 12 * value.meta.length;
function sizeOfMapChunkBulk(value) {
return 7 + value.compressedChunkData.length + 12 * value.meta.length;
}
MapChunkBulkWriter.prototype.write = function(buffer, offset) {
buffer.writeInt16BE(this.value.meta.length, offset);
function writeMapChunkBulk(value, buffer, offset) {
buffer.writeInt16BE(value.meta.length, offset);
offset += 2;
buffer.writeInt32BE(this.value.compressedChunkData.length, offset);
buffer.writeInt32BE(value.compressedChunkData.length, offset);
offset += 4;
buffer.writeInt8(+this.value.skyLightSent, offset);
buffer.writeInt8(+value.skyLightSent, offset);
offset += 1;
this.value.compressedChunkData.copy(buffer, offset);
offset += this.value.compressedChunkData.length;
value.compressedChunkData.copy(buffer, offset);
offset += value.compressedChunkData.length;
var meta;
for (var i = 0; i < this.value.meta.length; ++i) {
meta = this.value.meta[i];
for (var i = 0; i < value.meta.length; ++i) {
meta = value.meta[i];
buffer.writeInt32BE(meta.x, offset);
offset += 4;
buffer.writeInt32BE(meta.z, offset);
@ -621,54 +608,46 @@ MapChunkBulkWriter.prototype.write = function(buffer, offset) {
buffer.writeUInt16BE(meta.addBitMap, offset);
offset += 2;
}
return offset;
}
function IntArray8Writer(value) {
this.value = value;
this.size = 1 + 4 * value.length;
function sizeOfIntArray8(value) {
return 1 + 4 * value.length;
}
IntArray8Writer.prototype.write = function(buffer, offset) {
buffer.writeInt8(this.value.length, offset);
function writeIntArray8(value, buffer, offset) {
buffer.writeInt8(value.length, offset);
offset += 1;
this.value.forEach(function(item) {
value.forEach(function(item) {
buffer.writeInt32BE(item, offset);
offset += 4;
});
return offset;
}
function IntVectorWriter(value) {
this.value = value;
this.size = 12;
function writeIntVector(value, buffer, offset) {
buffer.writeInt32BE(value.x, offset);
buffer.writeInt32BE(value.y, offset + 4);
buffer.writeInt32BE(value.z, offset + 8);
return offset + 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 writeByteVector(value, buffer, offset) {
buffer.writeInt8(value.x, offset);
buffer.writeInt8(value.y, offset + 1);
buffer.writeInt8(value.z, offset + 2);
return offset + 3;
}
function ByteVectorWriter(value) {
this.value = value;
this.size = 3;
function sizeOfByteVectorArray(value) {
return 4 + 3 * value.length;
}
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);
function writeByteVectorArray(value, buffer, offset) {
buffer.writeInt32BE(value.length, offset);
offset += 4;
this.value.forEach(function(vec) {
value.forEach(function(vec) {
buffer.writeInt8(vec.x, offset);
offset += 1;
buffer.writeInt8(vec.y, offset);
@ -676,25 +655,24 @@ ByteVectorArrayWriter.prototype.write = function(buffer, offset) {
buffer.writeInt8(vec.z, offset);
offset += 1;
});
return offset;
}
function StringArrayWriter(value) {
this.value = new Array(value.length);
this.size = 2;
function sizeOfStringArray(value) {
var size = 2;
for (var i = 0; i < value.length; ++i) {
var stringWriter = new StringWriter(value[i]);
this.value[i] = stringWriter;
this.size += stringWriter.size;
size += sizeOfString(value[i]);
}
return size;
}
StringArrayWriter.prototype.write = function(buffer, offset) {
buffer.writeInt16BE(this.value.length, offset);
function writeStringArray(value, buffer, offset) {
buffer.writeInt16BE(value.length, offset);
offset += 2;
this.value.forEach(function(stringWriter) {
stringWriter.write(buffer, offset);
offset += stringWriter.size;
value.forEach(function(string) {
offset = writeString(string, buffer, offset);
});
return offset;
}
function readIntArray8(buffer, offset) {
@ -1107,146 +1085,108 @@ function readSlot(buffer, offset) {
};
}
function SlotWriter(value) {
this.value = value;
this.size = value.id === -1 ? 2 : 7 + this.value.nbtData.length;
function sizeOfSlot(value) {
return value.id === -1 ? 2 : 7 + value.nbtData.length;
}
SlotWriter.prototype.write = function(buffer, offset) {
buffer.writeInt16BE(this.value.id, offset);
if (this.value.id === -1) return;
buffer.writeInt8(this.value.itemCount, offset + 2);
buffer.writeInt16BE(this.value.itemDamage, offset + 3);
var nbtDataSize = this.value.nbtData.length;
function writeSlot(value, buffer, offset) {
buffer.writeInt16BE(value.id, offset);
if (value.id === -1) return offset + 2;
buffer.writeInt8(value.itemCount, offset + 2);
buffer.writeInt16BE(value.itemDamage, offset + 3);
var nbtDataSize = value.nbtData.length;
if (nbtDataSize === 0) nbtDataSize = -1; // I don't know wtf mojang smokes
buffer.writeInt16BE(nbtDataSize, offset + 5);
this.value.nbtData.copy(buffer, offset + 7);
value.nbtData.copy(buffer, offset + 7);
return offset + 7 + value.nbtData.length;
};
function StringWriter(value) {
function sizeOfString(value) {
assert.ok(value.length < STRING_MAX_LENGTH, "string greater than max length");
this.value = value;
this.size = 2 + 2 * value.length;
return 2 + 2 * value.length;
}
StringWriter.prototype.write = function(buffer, offset) {
var cursor = offset;
buffer.writeInt16BE(this.value.length, cursor);
cursor += 2;
function writeString(value, buffer, offset) {
buffer.writeInt16BE(value.length, offset);
offset += 2;
for (var i = 0; i < this.value.length; ++i) {
buffer.writeUInt16BE(this.value.charCodeAt(i), cursor);
cursor += 2;
for (var i = 0; i < value.length; ++i) {
buffer.writeUInt16BE(value.charCodeAt(i), offset);
offset += 2;
}
return offset;
};
function AsciiWriter(value) {
this.value = value;
this.size = 2 + value.length;
function sizeOfAscii(value) {
return 2 + value.length;
}
AsciiWriter.prototype.write = function(buffer, offset) {
var cursor = offset;
buffer.writeInt16BE(this.value.length, cursor);
cursor += 2;
function writeAscii(value, buffer, offset) {
buffer.writeInt16BE(value.length, offset);
offset += 2;
for (var i = 0; i < this.value.length; ++i) {
buffer.writeUInt8(this.value.charCodeAt(i), cursor);
cursor += 1;
for (var i = 0; i < value.length; ++i) {
buffer.writeUInt8(value.charCodeAt(i), offset);
offset += 1;
}
return offset;
};
function ByteArray16Writer(value) {
function sizeOfByteArray16(value) {
assert.ok(Buffer.isBuffer(value), "non buffer passed to ByteArray16Writer");
this.value = value;
this.size = 2 + value.length;
return 2 + value.length;
}
ByteArray16Writer.prototype.write = function(buffer, offset) {
buffer.writeInt16BE(this.value.length, offset);
this.value.copy(buffer, offset + 2);
function writeByteArray16(value, buffer, offset) {
buffer.writeInt16BE(value.length, offset);
value.copy(buffer, offset + 2);
return offset + 2 + value.length;
};
function ByteWriter(value) {
this.value = value == null ? 0 : value;
this.size = 1;
function writeByte(value, buffer, offset) {
buffer.writeInt8(value, offset);
return offset + 1;
}
ByteWriter.prototype.write = function(buffer, offset) {
buffer.writeInt8(this.value, offset);
function writeBool(value, buffer, offset) {
buffer.writeInt8(+value, offset);
return offset + 1;
}
function BoolWriter(value) {
this.value = value;
this.size = 1;
}
BoolWriter.prototype.write = function(buffer, offset) {
buffer.writeInt8(this.value ? 1 : 0, offset);
}
function UByteWriter(value) {
this.value = value;
this.size = 1;
}
UByteWriter.prototype.write = function(buffer, offset) {
buffer.writeUInt8(this.value, offset);
function writeUByte(value, buffer, offset) {
buffer.writeUInt8(value, offset);
return offset + 1;
};
function FloatWriter(value) {
this.value = value;
this.size = 4;
function writeFloat(value, buffer, offset) {
buffer.writeFloatBE(value, offset);
return offset + 4;
}
FloatWriter.prototype.write = function(buffer, offset) {
buffer.writeFloatBE(this.value, offset);
function writeDouble(value, buffer, offset) {
buffer.writeDoubleBE(value, offset);
return offset + 8;
}
function DoubleWriter(value) {
this.value = value;
this.size = 8;
function writeShort(value, buffer, offset) {
buffer.writeInt16BE(value, offset);
return offset + 2;
}
DoubleWriter.prototype.write = function(buffer, offset) {
buffer.writeDoubleBE(this.value, offset);
function writeUShort(value, buffer, offset) {
buffer.writeUInt16BE(value, offset);
return offset + 2;
}
function ShortWriter(value) {
this.value = value;
this.size = 2;
function writeInt(value, buffer, offset) {
buffer.writeInt32BE(value, offset);
return offset + 4;
}
ShortWriter.prototype.write = function(buffer, offset) {
buffer.writeInt16BE(this.value, offset);
}
function UShortWriter(value) {
this.value = value;
this.size = 2;
}
UShortWriter.prototype.write = function(buffer, offset) {
buffer.writeUInt16BE(this.value, offset);
}
function IntWriter(value) {
this.value = value;
this.size = 4;
}
IntWriter.prototype.write = function(buffer, 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 writeLong(value, buffer, offset) {
buffer.writeInt32BE(value[0], offset);
buffer.writeInt32BE(value[1], offset + 4);
return offset + 8;
}
function get(packetId, toServer) {
@ -1261,24 +1201,31 @@ function get(packetId, toServer) {
packetInfo.toClient;
}
function sizeOf(type, value) {
var dataType = types[type];
assert.ok(dataType, "unknown data type " + type);
var size = dataType[2];
if (typeof size === "function") {
return size(value);
} else {
return size;
}
}
function createPacketBuffer(packetId, params, isServer) {
var size = 1;
var fields = [ new UByteWriter(packetId) ];
var packet = get(packetId, !isServer);
assert.notEqual(packet, null);
packet.forEach(function(fieldInfo) {
var value = params[fieldInfo.name];
var Writer = types[fieldInfo.type][1];
assert.ok(Writer, "missing writer for data type: " + fieldInfo.type);
var field = new Writer(value);
size += field.size;
fields.push(field);
size += sizeOf(fieldInfo.type, params[fieldInfo.name]);
});
var buffer = new Buffer(size);
var cursor = 0;
fields.forEach(function(field) {
field.write(buffer, cursor);
cursor += field.size;
var offset = writeUByte(packetId, buffer, 0);
packet.forEach(function(fieldInfo) {
var write = types[fieldInfo.type][1];
var value = params[fieldInfo.name];
if(typeof value === "undefined") value = 0;
offset = write(value, buffer, offset);
});
return buffer;
}