First commit, most of the backend system! :)

This commit is contained in:
Cryptkeeper
2015-11-01 22:56:08 -06:00
commit b3f0d8aa18
11 changed files with 419 additions and 0 deletions

81
lib/mcpc_buffer.js Normal file
View File

@ -0,0 +1,81 @@
function CustomBuffer(existingBuffer) {
var buffer = existingBuffer || new Buffer(48);
var offset = 0;
this.writeVarInt = function(val) {
while (true) {
if ((val & 0xFFFFFF80) == 0) {
this.writeUByte(val);
return;
}
this.writeUByte(val & 0x7F | 0x80);
val = val >>> 7;
}
};
this.writeString = function(string) {
this.writeVarInt(string.length);
if (offset + string.length >= buffer.length) {
Buffer.concat([buffer, new Buffer(string.length)]);
}
buffer.write(string, offset, string.length, "UTF-8");
offset += string.length;
};
this.writeUShort = function(val) {
this.writeUByte(val >> 8);
this.writeUByte(val & 0xFF);
};
this.writeUByte = function(val) {
if (offset + 1 >= buffer.length) {
Buffer.concat([buffer, new Buffer(50)]);
}
buffer.writeUInt8(val, offset++);
};
this.readVarInt = function() {
var val = 0;
var count = 0;
while (true) {
var i = buffer.readUInt8(offset++);
val |= (i & 0x7F) << count++ * 7;
if ((i & 0x80) != 128) {
break
}
}
return val;
};
this.readString = function() {
var length = this.readVarInt();
var str = buffer.toString("UTF-8", offset, offset + length);
offset += length;
return str;
};
this.buffer = function() {
return buffer.slice(0, offset);
};
this.offset = function() {
return offset;
};
}
exports.createBuffer = function(buffer) {
return new CustomBuffer(buffer);
};

96
lib/ping.js Normal file
View File

@ -0,0 +1,96 @@
var mcpc = require('./mcpc_buffer');
var net = require('net');
function pingMinecraftPC(host, port, timeout, callback) {
var client = new net.Socket();
var milliseconds = (new Date).getTime();
client.connect(port, host, function() {
// Write out handshake packet.
var handshakeBuffer = mcpc.createBuffer();
handshakeBuffer.writeVarInt(0);
handshakeBuffer.writeVarInt(47);
handshakeBuffer.writeString(host);
handshakeBuffer.writeUShort(port);
handshakeBuffer.writeVarInt(1);
writePCBuffer(client, handshakeBuffer);
// Write the set connection state packet, we should get the MOTD after this.
var setModeBuffer = mcpc.createBuffer();
setModeBuffer.writeVarInt(0);
writePCBuffer(client, setModeBuffer);
});
var readingBuffer = new Buffer(0);
client.on('data', function(data) {
readingBuffer = Buffer.concat([readingBuffer, data]);
var buffer = mcpc.createBuffer(readingBuffer);
var length;
try {
length = buffer.readVarInt();
} catch(err) {
// The buffer isn't long enough yet, wait for more data!
return;
}
// Make sure we have the data we need!
if (readingBuffer.length < length - buffer.offset() ) {
return;
}
// Read the packet ID, throw it away.
buffer.readVarInt();
try {
var json = JSON.parse(buffer.readString());
json.latency = (new Date).getTime() - milliseconds;
// We parsed it, send it along!
callback(null, json);
} catch (err) {
// Our data is corrupt? Fail hard.
callback(err, null);
return;
}
// We're done here.
client.destroy();
});
client.on('error', function(err) {
callback(err, null);
});
// Make sure we don't go overtime.
setTimeout(function() {
client.end();
}, timeout);
}
// Wraps our Buffer into another to fit the Minecraft protocol.
function writePCBuffer(client, buffer) {
var length = mcpc.createBuffer();
length.writeVarInt(buffer.buffer().length);
client.write(Buffer.concat([length.buffer(), buffer.buffer()]));
}
exports.ping = function(host, port, type, timeout, callback) {
if (type === 'PC') {
pingMinecraftPC(host, port, timeout, callback);
} else if (type === 'PE') {
} else {
throw new Error('Unsupported type: ' + type);
}
};

36
lib/server.js Normal file
View File

@ -0,0 +1,36 @@
var http = require('http');
var fs = require('fs');
var url = require('url');
var mime = require('mime');
var io = require('socket.io');
var urlMapping = [];
exports.start = function(ip, port, callback) {
var server = http.createServer(function(req, res) {
var requestUrl = url.parse(req.url).pathname;
if (requestUrl in urlMapping) {
var file = urlMapping[requestUrl];
res.setHeader('Content-Type', mime.lookup(file));
fs.createReadStream(file).pipe(res);
} else {
res.statusCode = 404;
res.write('404');
res.end();
}
});
server.listen(port, ip);
// I don't like this. But it works, I think.
exports.io = (io = io.listen(server));
// Since everything is loaded, do some final prep work.
callback();
};
exports.urlMapping = urlMapping;