minecraft.js
Version:
Minecraft data serialization/deserialization and networking
125 lines (112 loc) • 3.71 kB
JavaScript
/** @constructor */
var Tag = module.exports = function(type, name, payload) {
if(typeof type == 'undefined') {
throw new Error('Invalid arguments: a type is required');
}
if(typeof payload == 'undefined') {
if(name) payload = name;
name = '';
}
this.type = Tag.prototype.types[type.toUpperCase()];
this.name = name || '';
this.payload = payload;
if(typeof this.payload != 'number' &&
this.type.payload == 'number')
this.payload = Number(this.payload);
if(!this.type.payload == 'array' && typeof this.payload != this.type.payload) {
console.log(this.payload);
throw new Error('Invalid payload type: expected ' + this.type.payload +
', got ' + typeof this.payload);
}
if(this.type.name == 'list') {
var tagId;
for(var i = 0; i < this.payload.length; i++) {
if(!tagId) {
tagId = this.payload[i].type.value;
} else if(tagId != this.payload[i].type.value) {
throw new Error('Payload array members must all be the same type');
}
}
}
};
Tag.prototype.toBlob = function() {
throw new Error('Not implemented');
};
Tag.prototype.toText = function() {
var text = '';
if(this.type.named) {
text += this.type.value;
if(this.name) {
text += this.name;
}
}
switch(this.type.name) {
case 'End':
text += '\0';
break;
case 'Byte_Array':
text += new Tag("int", 'length', this.payload.length).toText();
for(var i = 0; i < this.payload.length; i++) {
text += this.payload[i];
}
break;
case 'String':
text += new Tag("short", 'length', this.payload.length).toText();
text += this.payload;
break;
case 'List':
var tagId = 0;
if(this.payload.length > 0) tagId = this.payload[0].type.value;
text += new Tag("byte", 'tagId', tagId).toText();
text += new Tag("int", 'length', this.payload.length).toText();
for(var i = 0; i < this.payload.value; i++) {
text += this.payload[i].toText();
}
break;
case 'Compound':
for(var i = 0; i < this.payload.length; i++) {
text += this.payload[i].toText();
}
text += new Tag('end').toText();
break;
default:
text += this.payload;
break;
}
return text;
};
Tag.prototype.append = function(data) {
if(this.type.name == 'Byte_Array' ||
this.type.name == 'List' ||
this.type.name == 'Compound') {
if(typeof data == 'array') {
for(var i = 0; i < data.length; i++) {
this.payload.push(data[i]);
}
} else if(data.constructor == Tag) {
this.payload.push(data);
} else {
throw Error('appension must be an array or Tag');
}
} else if(this.type.name == 'String') {
if(typeof data == 'string') {
this.payload += data;
} else {
throw new Error('appension must be a string');
}
}
return this;
};
Tag.prototype.types = {
END: {value: 0, name: 'End', size: 0, payload: 'undefined', named: false},
BYTE: {value: 1, name: 'Byte', size: 1, payload: 'number', named: true},
SHORT: {value: 2, name: 'Short', size: 2, payload: 'number', named: true},
INT: {value: 3, name: 'Int', size: 4, payload: 'number', named: true},
LONG: {value: 4, name: 'Long', size: 8, payload: 'number', named: true},
FLOAT: {value: 5, name: 'Float', size: 4, payload: 'number', named: true},
DOUBLE: {value: 6, name: 'Double', size: 8, payload: 'number', named: true},
BYTE_ARRAY: {value: 7, name: 'Byte_Array', size: 0, payload: 'array', named: true},
STRING: {value: 8, name: 'String', size: 0, payload: 'string', named: true},
LIST: {value: 9, name: 'List', size: 0, payload: 'array', named: true},
COMPOUND: {value: 10, name: 'Compound', size: 0, payload: 'array', named: true}
};