mirror of
https://github.com/gamedig/node-gamedig.git
synced 2024-10-08 01:37:24 +02:00
128 lines
2.9 KiB
JavaScript
128 lines
2.9 KiB
JavaScript
|
var dns = require('dns'),
|
||
|
net = require('net'),
|
||
|
varint = require('varint');
|
||
|
|
||
|
function varIntBuffer(num) {
|
||
|
return new Buffer(varint.encode(num));
|
||
|
}
|
||
|
|
||
|
module.exports = require('./protocols/core').extend({
|
||
|
init: function() {
|
||
|
this._super();
|
||
|
this.pretty = 'Minecraft';
|
||
|
this.options.port = 25565;
|
||
|
},
|
||
|
parseDns: function(host,c) {
|
||
|
var self = this;
|
||
|
var _super = this._super;
|
||
|
function fallback(h) { _super.call(self,h,c); }
|
||
|
|
||
|
dns.resolve('_minecraft._tcp.'+host, 'SRV', function(err,addresses) {
|
||
|
if(err) return fallback(host);
|
||
|
if(addresses.length >= 1) {
|
||
|
var line = addresses[0];
|
||
|
self.options.port = line.port;
|
||
|
var srvhost = line.name;
|
||
|
|
||
|
if(srvhost.match(/\d+\.\d+\.\d+\.\d+/)) {
|
||
|
self.options.address = srvhost;
|
||
|
c();
|
||
|
} else {
|
||
|
// resolve yet again
|
||
|
fallback(srvhost);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
return fallback(host);
|
||
|
});
|
||
|
},
|
||
|
reset: function() {
|
||
|
this._super();
|
||
|
if(this.socket) {
|
||
|
this.socket.destroy();
|
||
|
delete this.socket;
|
||
|
}
|
||
|
},
|
||
|
run: function(state) {
|
||
|
var self = this;
|
||
|
|
||
|
var socket = this.socket = net.connect(
|
||
|
this.options.port,
|
||
|
this.options.address,
|
||
|
function() {
|
||
|
|
||
|
var portBuf = new Buffer(2);
|
||
|
portBuf.writeUInt16BE(self.options.port,0);
|
||
|
|
||
|
var addressBuf = new Buffer(self.options.address,'utf8');
|
||
|
|
||
|
var bufs = [
|
||
|
varIntBuffer(4),
|
||
|
varIntBuffer(addressBuf.length),
|
||
|
addressBuf,
|
||
|
portBuf,
|
||
|
varIntBuffer(1)
|
||
|
];
|
||
|
self.sendPacket(0,Buffer.concat(bufs));
|
||
|
self.sendPacket(0);
|
||
|
});
|
||
|
socket.setTimeout(10000);
|
||
|
socket.setNoDelay(true);
|
||
|
|
||
|
var received = new Buffer(0);
|
||
|
var expectedBytes = 0;
|
||
|
socket.on('data', function(data) {
|
||
|
received = Buffer.concat([received,data]);
|
||
|
if(expectedBytes) {
|
||
|
if(received.length >= expectedBytes) {
|
||
|
self.allReceived(received,state);
|
||
|
}
|
||
|
} else if(received.length > 10) {
|
||
|
expectedBytes = varint.decode(received);
|
||
|
received = received.slice(varint.decode.bytesRead);
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
sendPacket: function(id,data) {
|
||
|
if(!data) data = new Buffer(0);
|
||
|
var idBuffer = varIntBuffer(id);
|
||
|
var out = Buffer.concat([
|
||
|
varIntBuffer(data.length+idBuffer.length),
|
||
|
idBuffer,
|
||
|
data
|
||
|
]);
|
||
|
this.socket.write(out);
|
||
|
},
|
||
|
allReceived: function(received,state) {
|
||
|
var packetId = varint.decode(received);
|
||
|
received = received.slice(varint.decode.bytesRead);
|
||
|
|
||
|
var strLen = varint.decode(received);
|
||
|
received = received.slice(varint.decode.bytesRead);
|
||
|
|
||
|
var str = received.toString('utf8');
|
||
|
var json;
|
||
|
try {
|
||
|
json = JSON.parse(str);
|
||
|
delete json.favicon;
|
||
|
} catch(e) {
|
||
|
return this.fatal('Invalid JSON');
|
||
|
}
|
||
|
|
||
|
state.raw.version = json.version.name;
|
||
|
state.maxplayers = json.players.max;
|
||
|
state.raw.description = json.description.text;
|
||
|
for(var i = 0; i < json.players.sample.length; i++) {
|
||
|
state.players.push({
|
||
|
id: json.players.sample[i].id,
|
||
|
name: json.players.sample[i].name
|
||
|
});
|
||
|
}
|
||
|
while(state.players.length < json.players.online) {
|
||
|
state.players.push({});
|
||
|
}
|
||
|
|
||
|
this.finish(state);
|
||
|
}
|
||
|
});
|