node-gamedig/protocols/quake2.js

88 lines
3.2 KiB
JavaScript
Raw Normal View History

class Quake2 extends require('./core') {
constructor() {
2017-08-09 12:32:09 +02:00
super();
this.encoding = 'latin1';
this.delimiter = '\n';
this.sendHeader = 'status';
this.responseHeader = 'print';
this.isQuake1 = false;
}
2014-10-29 08:02:03 +01:00
2017-08-09 12:32:09 +02:00
run(state) {
this.udpSend('\xff\xff\xff\xff'+this.sendHeader+'\x00', (buffer) => {
const reader = this.reader(buffer);
2015-07-19 00:09:36 +02:00
const header = reader.string({length:4});
2017-08-09 12:32:09 +02:00
if(header !== '\xff\xff\xff\xff') return;
2014-10-29 08:02:03 +01:00
let response;
2017-08-09 12:32:09 +02:00
if(this.isQuake1) {
response = reader.string({length:this.responseHeader.length});
} else {
response = reader.string();
}
if(response !== this.responseHeader) return;
2014-10-29 08:02:03 +01:00
const info = reader.string().split('\\');
2017-08-09 12:32:09 +02:00
if(info[0] === '') info.shift();
2014-10-29 08:02:03 +01:00
2017-08-09 12:32:09 +02:00
while(true) {
const key = info.shift();
const value = info.shift();
2017-08-09 12:32:09 +02:00
if(typeof value === 'undefined') break;
state.raw[key] = value;
}
2014-10-29 08:02:03 +01:00
2017-08-09 12:32:09 +02:00
while(!reader.done()) {
const line = reader.string();
2017-08-09 12:32:09 +02:00
if(!line || line.charAt(0) === '\0') break;
2014-10-29 08:02:03 +01:00
const args = [];
const split = line.split('"');
2017-08-09 12:32:09 +02:00
split.forEach((part,i) => {
const inQuote = (i%2 === 1);
2017-08-09 12:32:09 +02:00
if(inQuote) {
args.push(part);
} else {
const splitSpace = part.split(' ');
2017-08-09 12:32:09 +02:00
for (const subpart of splitSpace) {
if(subpart) args.push(subpart);
}
}
});
2014-10-29 08:02:03 +01:00
const player = {};
2017-08-09 12:32:09 +02:00
if(this.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() || '';
}
2014-10-29 08:02:03 +01:00
2017-08-09 12:32:09 +02:00
(player.ping ? state.players : state.bots).push(player);
}
2014-10-29 08:02:03 +01:00
2017-08-09 12:32:09 +02:00
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('maxclients' in state.raw) state.maxplayers = state.raw.maxclients;
if('sv_hostname' in state.raw) state.name = state.raw.sv_hostname;
if('hostname' in state.raw) state.name = state.raw.hostname;
2014-10-29 08:02:03 +01:00
2017-08-09 12:32:09 +02:00
this.finish(state);
return true;
});
}
}
module.exports = Quake2;