mirror of
https://github.com/unmojang/node-minecraft-protocol.git
synced 2025-09-30 14:41:27 -04:00
Proper generic read/write/sizeOf functions
This commit is contained in:
parent
7b9f170fb2
commit
c0ba7f8127
119
lib/protocol.js
119
lib/protocol.js
@ -633,20 +633,21 @@ var packetStates = {toClient: {}, toServer: {}};
|
|||||||
|
|
||||||
|
|
||||||
var types = {
|
var types = {
|
||||||
'int': [readInt, writeInt, 4],
|
|
||||||
'short': [readShort, writeShort, 2],
|
|
||||||
'ushort': [readUShort, writeUShort, 2],
|
|
||||||
'byte': [readByte, writeByte, 1],
|
'byte': [readByte, writeByte, 1],
|
||||||
'ubyte': [readUByte, writeUByte, 1],
|
'ubyte': [readUByte, writeUByte, 1],
|
||||||
'string': [readString, writeString, sizeOfString],
|
'short': [readShort, writeShort, 2],
|
||||||
'ustring': [readString, writeString, sizeOfUString],
|
'ushort': [readUShort, writeUShort, 2],
|
||||||
'byteArray16': [readByteArray16, writeByteArray16, sizeOfByteArray16],
|
'int': [readInt, writeInt, 4],
|
||||||
'bool': [readBool, writeBool, 1],
|
|
||||||
'double': [readDouble, writeDouble, 8],
|
|
||||||
'float': [readFloat, writeFloat, 4],
|
|
||||||
'slot': [readSlot, writeSlot, sizeOfSlot],
|
|
||||||
'long': [readLong, writeLong, 8],
|
'long': [readLong, writeLong, 8],
|
||||||
'varint': [readVarInt, writeVarInt, sizeOfVarInt],
|
'varint': [readVarInt, writeVarInt, sizeOfVarInt],
|
||||||
|
'float': [readFloat, writeFloat, 4],
|
||||||
|
'double': [readDouble, writeDouble, 8],
|
||||||
|
'bool': [readBool, writeBool, 1],
|
||||||
|
'string': [readString, writeString, sizeOfString],
|
||||||
|
'ustring': [readString, writeString, sizeOfUString], // TODO : remove ustring
|
||||||
|
// TODO : remove type-specific, replace with generic containers and arrays.
|
||||||
|
'slot': [readSlot, writeSlot, sizeOfSlot],
|
||||||
|
'byteArray16': [readByteArray16, writeByteArray16, sizeOfByteArray16],
|
||||||
'ascii': [readAscii, writeAscii, sizeOfAscii],
|
'ascii': [readAscii, writeAscii, sizeOfAscii],
|
||||||
'entityMetadata': [readEntityMetadata, writeEntityMetadata, sizeOfEntityMetadata],
|
'entityMetadata': [readEntityMetadata, writeEntityMetadata, sizeOfEntityMetadata],
|
||||||
'byteArray32': [readByteArray32, writeByteArray32, sizeOfByteArray32],
|
'byteArray32': [readByteArray32, writeByteArray32, sizeOfByteArray32],
|
||||||
@ -728,7 +729,7 @@ function sizeOfEntityMetadata(value) {
|
|||||||
var item;
|
var item;
|
||||||
for (var i = 0; i < value.length; ++i) {
|
for (var i = 0; i < value.length; ++i) {
|
||||||
item = value[i];
|
item = value[i];
|
||||||
size += sizeOf(item.type, item.value);
|
size += sizeOf(item.value, { type: item.type }, {});
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -1599,6 +1600,50 @@ function writeMatchArray(value, buffer, offset) {
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function read(buffer, cursor, fieldInfo, rootNodes) {
|
||||||
|
if (fieldInfo.condition && !fieldInfo.condition(rootNodes)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var type = types[fieldInfo.type];
|
||||||
|
if (!type) {
|
||||||
|
return {
|
||||||
|
error: new Error("missing data type: " + fieldInfo.type)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var readResults = type[0](buffer, cursor, fieldInfo.typeArgs, rootNodes);
|
||||||
|
if (readResults.error) return { error: readResults.error };
|
||||||
|
|
||||||
|
return readResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
function write(value, buffer, offset, fieldInfo, rootNodes) {
|
||||||
|
if (fieldInfo.condition && !fieldInfo.condition(rootNodes)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var type = types[fieldInfo.type];
|
||||||
|
if (!type) {
|
||||||
|
return {
|
||||||
|
error: new Error("missing data type: " + fieldInfo.type)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return type[1](value, buffer, offset, fieldInfo.typeArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sizeOf(value, fieldInfo, rootNodes) {
|
||||||
|
if (fieldInfo.condition && !fieldInfo.condition(rootNodes)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
var type = types[fieldInfo.type];
|
||||||
|
if (!type) {
|
||||||
|
throw new Error("missing data type: " + fieldInfo.type);
|
||||||
|
}
|
||||||
|
if (typeof type[2] === 'function') {
|
||||||
|
return type[2](value, fieldInfo.typeArgs);
|
||||||
|
} else {
|
||||||
|
return type[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function get(packetId, state, toServer) {
|
function get(packetId, state, toServer) {
|
||||||
var direction = toServer ? "toServer" : "toClient";
|
var direction = toServer ? "toServer" : "toClient";
|
||||||
var packetInfo = packetFields[state][direction][packetId];
|
var packetInfo = packetFields[state][direction][packetId];
|
||||||
@ -1608,17 +1653,6 @@ function get(packetId, state, toServer) {
|
|||||||
return packetInfo;
|
return packetInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
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, state, params, isServer) {
|
function createPacketBuffer(packetId, state, params, isServer) {
|
||||||
var length = 0;
|
var length = 0;
|
||||||
if (typeof packetId === 'string' && typeof state !== 'string' && !params) {
|
if (typeof packetId === 'string' && typeof state !== 'string' && !params) {
|
||||||
@ -1632,10 +1666,7 @@ function createPacketBuffer(packetId, state, params, isServer) {
|
|||||||
var packet = get(packetId, state, !isServer);
|
var packet = get(packetId, state, !isServer);
|
||||||
assert.notEqual(packet, null);
|
assert.notEqual(packet, null);
|
||||||
packet.forEach(function(fieldInfo) {
|
packet.forEach(function(fieldInfo) {
|
||||||
var condition = fieldInfo.condition;
|
length += sizeOf(params[fieldInfo.name], fieldInfo, params);
|
||||||
if (typeof condition != "undefined" && !condition(params))
|
|
||||||
return;
|
|
||||||
length += sizeOf(fieldInfo.type, params[fieldInfo.name]);
|
|
||||||
});
|
});
|
||||||
length += sizeOfVarInt(packetId);
|
length += sizeOfVarInt(packetId);
|
||||||
var size = length + sizeOfVarInt(length);
|
var size = length + sizeOfVarInt(length);
|
||||||
@ -1643,32 +1674,14 @@ function createPacketBuffer(packetId, state, params, isServer) {
|
|||||||
var offset = writeVarInt(length, buffer, 0);
|
var offset = writeVarInt(length, buffer, 0);
|
||||||
offset = writeVarInt(packetId, buffer, offset);
|
offset = writeVarInt(packetId, buffer, offset);
|
||||||
packet.forEach(function(fieldInfo) {
|
packet.forEach(function(fieldInfo) {
|
||||||
var condition = fieldInfo.condition;
|
|
||||||
if (typeof condition != "undefined" && !condition(params))
|
|
||||||
return;
|
|
||||||
var write = types[fieldInfo.type][1];
|
|
||||||
var value = params[fieldInfo.name];
|
var value = params[fieldInfo.name];
|
||||||
if(typeof value === "undefined") value = 0;
|
if(typeof value === "undefined") value = 0; // TODO : Why ?
|
||||||
offset = write(value, buffer, offset);
|
offset = write(value, buffer, offset, fieldInfo, params);
|
||||||
});
|
});
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parsePacket(buffer, state, isServer) {
|
function parsePacket(buffer, state, 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, cursor);
|
|
||||||
if (! readResults) return null; // buffer needs to be more full
|
|
||||||
if (readResults.error) return { error: readResults.error };
|
|
||||||
|
|
||||||
return readResults;
|
|
||||||
}
|
|
||||||
if (state == null) state == states.PLAY;
|
if (state == null) state == states.PLAY;
|
||||||
var cursor = 0;
|
var cursor = 0;
|
||||||
var lengthField = readVarInt(buffer, 0);
|
var lengthField = readVarInt(buffer, 0);
|
||||||
@ -1697,13 +1710,10 @@ function parsePacket(buffer, state, isServer) {
|
|||||||
var i, fieldInfo, readResults;
|
var i, fieldInfo, readResults;
|
||||||
for (i = 0; i < packetInfo.length; ++i) {
|
for (i = 0; i < packetInfo.length; ++i) {
|
||||||
fieldInfo = packetInfo[i];
|
fieldInfo = packetInfo[i];
|
||||||
var condition = fieldInfo.condition;
|
readResults = read(buffer, cursor, fieldInfo, results);
|
||||||
if (typeof condition != "undefined" && !condition(results)) {
|
/* A deserializer cannot return null anymore. Besides, read() returns
|
||||||
results[fieldInfo.name] = null;
|
* null when the condition is not fulfilled.
|
||||||
continue;
|
if (!!!readResults) {
|
||||||
}
|
|
||||||
readResults = readPacketField(fieldInfo);
|
|
||||||
if (!!!readResults) {
|
|
||||||
var error = new Error("A deserializer returned null");
|
var error = new Error("A deserializer returned null");
|
||||||
error.packetId = packetId;
|
error.packetId = packetId;
|
||||||
error.fieldInfo = fieldInfo.name;
|
error.fieldInfo = fieldInfo.name;
|
||||||
@ -1712,7 +1722,8 @@ function parsePacket(buffer, state, isServer) {
|
|||||||
error: error,
|
error: error,
|
||||||
results: results
|
results: results
|
||||||
};
|
};
|
||||||
}
|
}*/
|
||||||
|
if (readResults === null) continue;
|
||||||
if (readResults.error) {
|
if (readResults.error) {
|
||||||
return readResults;
|
return readResults;
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,9 @@ describe("packets", function() {
|
|||||||
// empty object uses default values
|
// empty object uses default values
|
||||||
var packet = {};
|
var packet = {};
|
||||||
packetInfo.forEach(function(field) {
|
packetInfo.forEach(function(field) {
|
||||||
packet[field.name] = values[field.type];
|
if (!field.hasOwnProperty("condition") || field.condition(packet)) {
|
||||||
|
packet[field.name] = values[field.type];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (toServer) {
|
if (toServer) {
|
||||||
serverClient.once([state, packetId], function(receivedPacket) {
|
serverClient.once([state, packetId], function(receivedPacket) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user