node-gamedig/protocols/quake2.js

86 lines
2.3 KiB
JavaScript

module.exports = require('./core').extend({
init: function() {
this._super();
this.encoding = 'latin1';
this.delimiter = '\n';
this.sendHeader = 'status';
this.responseHeader = 'print';
this.isQuake1 = false;
},
run: function(state) {
var self = this;
this.udpSend('\xff\xff\xff\xff'+this.sendHeader+'\x00',function(buffer) {
var reader = self.reader(buffer);
var header = reader.string({length:4});
if(header != '\xff\xff\xff\xff') return;
var response;
if(this.isQuake1) {
response = reader.string({length:1});
} else {
response = reader.string();
}
if(response != this.responseHeader) return;
var info = reader.string().split('\\');
if(info[0] == '') info.shift();
while(true) {
var key = info.shift();
var value = info.shift();
if(typeof value == 'undefined') break;
state.raw[key] = value;
}
while(!reader.done()) {
var line = reader.string();
if(!line || line.charAt(0) == '\0') break;
var args = [];
var split = line.split('"');
var inQuote = false;
split.forEach(function(part,i) {
var inQuote = (i%2 == 1);
if(inQuote) {
args.push(part);
} else {
var splitSpace = part.split(' ');
splitSpace.forEach(function(subpart) {
if(subpart) args.push(subpart);
});
}
});
var player = {};
if(self.isQuake1) {
player.id = parseInt(args.shift());
player.score = parseInt(args.shift());
player.time = parseInt(args.shift());
player.ping = parseInt(args.shift());
player.name = args.shift();
player.skin = args.shift();
player.color1 = parseInt(args.shift());
player.color2 = parseInt(args.shift());
} else {
player.frags = parseInt(args.shift());
player.ping = parseInt(args.shift());
player.name = args.shift() || '';
player.address = args.shift() || '';
}
(player.ping ? state.players : state.bots).push(player);
}
if('g_needpass' in state.raw) state.password = state.raw.g_needpass;
if('mapname' in state.raw) state.map = state.raw.mapname;
if('sv_maxclients' in state.raw) state.maxplayers = state.raw.sv_maxclients;
if('sv_hostname' in state.raw) state.name = state.raw.sv_hostname;
self.finish(state);
return true;
});
}
});