bukkit-stats
Advanced tools
Comparing version 0.0.0 to 1.0.0
// module dependencies | ||
var events = require("events") | ||
, net = require("net") | ||
, util = require("util") | ||
, helpers = require("./helpers"); | ||
, util = require("util"); | ||
// constants | ||
var SPLIT = String.fromCharCode(0xA7); | ||
var PACKETS = { ping: 0xFE, kick: 0xFF }; | ||
// load settings | ||
var constants = require("./constants.js") | ||
, PACKETS = constants.PACKETS | ||
, CTRL = constants.CTRL | ||
, CONNECTION = constants.CONNECTION | ||
, ERRORS = constants.ERRORS; | ||
// populate bukkit-stats | ||
module.exports = exports = Stats; | ||
// expose bukkit-stats | ||
module.exports = Stats; | ||
// bukkit-stats | ||
function Stats(host, port) { | ||
// ensure that the object is instanciated with new | ||
// constructor | ||
function Stats(host, port, cb) { | ||
// ensure that the object is instanciated with the new operator | ||
if(!(this instanceof Stats)) return new Stats(host, port); | ||
// start the event listener | ||
events.EventEmitter.call(this); | ||
// save the connection data | ||
// parse the arguments | ||
if(~host.indexOf(":")) { | ||
@@ -27,7 +26,19 @@ host = host.split(":"); | ||
} else { | ||
this.config = { host: host, port: port }; | ||
this.config = { | ||
host: host || CONNECTION.defaultHost, | ||
port: parseInt(port) || CONNECTION.defaultPort | ||
}; | ||
} | ||
if(typeof host == "function") cb = host; | ||
else if(typeof port == "function") cb = port; | ||
else if(typeof cb != "function") cb = function() {}; | ||
// start the event listener | ||
events.EventEmitter.call(this); | ||
// register the callback | ||
this.on("stats", cb); | ||
// fire the request | ||
this.connect(); | ||
this.request(); | ||
} | ||
@@ -38,42 +49,74 @@ | ||
Stats.prototype.connect = function() { | ||
// start ping measurement | ||
var stopwatch = helpers.stopwatch(); | ||
// request the data from the given server | ||
Stats.prototype.request = function() { | ||
// start ping latency measurement | ||
var startTime = Date.now(); | ||
// create a TCP connection | ||
this._socket = net.connect(this.config); | ||
var socket = net.connect(this.config); | ||
// listen on the response | ||
this._socket.once("data", helpers.wrap(function(data) { | ||
this._socket.destroy(); | ||
var data = this.parse(data); | ||
if(!data) { | ||
this.emit("error", new Error("Server responded with invalid package")); | ||
} else { | ||
data.ping = stopwatch(); | ||
this.emit("data", data); | ||
} | ||
}, this)); | ||
socket.once("data", wrap(this.handleResponse, this, socket, startTime)); | ||
// pipe the errors | ||
this._socket.on("error", console.log); | ||
// listen on errors | ||
socket.once("error", wrap(this.handleError, this, "error")); | ||
socket.once("timeout", wrap(this.handleError, this, "timeout")); | ||
socket.once("close", wrap(this.handleError, this, "close")); | ||
// send the magic packet | ||
this._socket.write(helpers.byteToBuffer(PACKETS.ping)); | ||
socket.write(new Buffer([PACKETS.serverListPing])); // TODO: Maybe we could use a helper function for type conversion here | ||
}; | ||
// handle a connection error | ||
Stats.prototype.handleError = function(type, error) { | ||
switch(type) { | ||
case "error": | ||
error.message = ERRORS.unknown + error.message; | ||
this.emit("error", error); | ||
break; | ||
case "timeout": this.emit("error", new Error(ERRORS.timeout)); break; | ||
case "close": this.emit("error", new Error(ERRORS.close)); break; | ||
case "format": this.emit("error", new Error(ERRORS.format)); break; | ||
} | ||
}; | ||
// handle a response | ||
Stats.prototype.handleResponse = function(socket, startTime, buffer) { | ||
// close the socket | ||
socket.removeAllListeners(); | ||
socket.destroy(); | ||
// calculate latency | ||
var latency = Date.now() - startTime; | ||
// parse the response | ||
var stats = this.parse(buffer); | ||
stats.latency = latency; | ||
this.emit("stats", stats); | ||
}; | ||
// parse a response buffer | ||
Stats.prototype.parse = function(buffer) { | ||
// check for package validity | ||
if(buffer[0] != PACKETS.kick) { | ||
if(buffer[0] != PACKETS.disconnect) { | ||
this.handleError("format"); | ||
return false; | ||
} | ||
// append 0x00 to the buffer, because fucking Bukkit doesn't do it | ||
buffer = helpers.concatBuffers(buffer, helpers.byteToBuffer(0x00)); | ||
// append a 0x00 to the buffer, because Bukkit forget it | ||
buffer = Buffer.concat([buffer, new Buffer([CTRL.missingByte])]); | ||
// chop of the package id and parse | ||
var res = buffer.toString("ucs2", 4).split(SPLIT); | ||
var res = buffer.toString("ucs2", 4).split(String.fromCharCode(CTRL.delimeter)); | ||
// here we go | ||
return { motd: res[0], onlinePlayers: parseInt(res[1]), maxPlayers: parseInt(res[2]) }; | ||
}; | ||
return { motd: res[0], onlinePlayers: res[1], maxPlayers: res[2] }; | ||
}; | ||
// helper function | ||
function wrap(fn, ref) { | ||
var args = Array.prototype.slice.call(arguments, 2); | ||
return function() { | ||
fn.apply(ref, args.concat(Array.prototype.slice.call(arguments))); | ||
}; | ||
} |
{ | ||
"name": "bukkit-stats", | ||
"version": "0.0.0", | ||
"version": "1.0.0", | ||
"description": "Gets a server's stats displayed in the client serverlist", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
6310
188
2
2