mirror of
https://github.com/tribufu/node-gamedig
synced 2026-05-18 09:35:50 +00:00
Convert tabs to spaces
This commit is contained in:
parent
0dd25bfcda
commit
3674d384d0
39 changed files with 2414 additions and 2414 deletions
|
|
@ -1,217 +1,217 @@
|
|||
const async = require('async'),
|
||||
Bzip2 = require('compressjs').Bzip2;
|
||||
Bzip2 = require('compressjs').Bzip2;
|
||||
|
||||
class Valve extends require('./core') {
|
||||
constructor() {
|
||||
super();
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.options.port = 27015;
|
||||
|
||||
// legacy goldsrc info response -- basically not used by ANYTHING now,
|
||||
// as most (all?) goldsrc servers respond with the source info reponse
|
||||
// delete in a few years if nothing ends up using it anymore
|
||||
this.goldsrcInfo = false;
|
||||
|
||||
// unfortunately, the split format from goldsrc is still around, but we
|
||||
// can detect that during the query
|
||||
this.goldsrcSplits = false;
|
||||
this.options.port = 27015;
|
||||
|
||||
// some mods require a challenge, but don't provide them in the new format
|
||||
// at all, use the old dedicated challenge query if needed
|
||||
this.legacyChallenge = false;
|
||||
|
||||
// cs:go provides an annoying additional bot that looks exactly like a player,
|
||||
// but is always named "Max Players"
|
||||
this.isCsGo = false;
|
||||
|
||||
// 2006 engines don't pass packet switching size in split packet header
|
||||
// while all others do, this need is detected automatically
|
||||
this._skipSizeInSplitHeader = false;
|
||||
// legacy goldsrc info response -- basically not used by ANYTHING now,
|
||||
// as most (all?) goldsrc servers respond with the source info reponse
|
||||
// delete in a few years if nothing ends up using it anymore
|
||||
this.goldsrcInfo = false;
|
||||
|
||||
this._challenge = '';
|
||||
}
|
||||
// unfortunately, the split format from goldsrc is still around, but we
|
||||
// can detect that during the query
|
||||
this.goldsrcSplits = false;
|
||||
|
||||
run(state) {
|
||||
async.series([
|
||||
(c) => { this.queryInfo(state,c); },
|
||||
(c) => { this.queryChallenge(state,c); },
|
||||
(c) => { this.queryPlayers(state,c); },
|
||||
(c) => { this.queryRules(state,c); },
|
||||
(c) => { this.finish(state); }
|
||||
]);
|
||||
}
|
||||
// some mods require a challenge, but don't provide them in the new format
|
||||
// at all, use the old dedicated challenge query if needed
|
||||
this.legacyChallenge = false;
|
||||
|
||||
queryInfo(state,c) {
|
||||
this.sendPacket(
|
||||
0x54,false,'Source Engine Query\0',
|
||||
this.goldsrcInfo ? 0x6D : 0x49,
|
||||
(b) => {
|
||||
// cs:go provides an annoying additional bot that looks exactly like a player,
|
||||
// but is always named "Max Players"
|
||||
this.isCsGo = false;
|
||||
|
||||
// 2006 engines don't pass packet switching size in split packet header
|
||||
// while all others do, this need is detected automatically
|
||||
this._skipSizeInSplitHeader = false;
|
||||
|
||||
this._challenge = '';
|
||||
}
|
||||
|
||||
run(state) {
|
||||
async.series([
|
||||
(c) => { this.queryInfo(state,c); },
|
||||
(c) => { this.queryChallenge(state,c); },
|
||||
(c) => { this.queryPlayers(state,c); },
|
||||
(c) => { this.queryRules(state,c); },
|
||||
(c) => { this.finish(state); }
|
||||
]);
|
||||
}
|
||||
|
||||
queryInfo(state,c) {
|
||||
this.sendPacket(
|
||||
0x54,false,'Source Engine Query\0',
|
||||
this.goldsrcInfo ? 0x6D : 0x49,
|
||||
(b) => {
|
||||
const reader = this.reader(b);
|
||||
|
||||
if(this.goldsrcInfo) state.raw.address = reader.string();
|
||||
else state.raw.protocol = reader.uint(1);
|
||||
|
||||
state.name = reader.string();
|
||||
state.map = reader.string();
|
||||
state.raw.folder = reader.string();
|
||||
state.raw.game = reader.string();
|
||||
state.raw.steamappid = reader.uint(2);
|
||||
state.raw.numplayers = reader.uint(1);
|
||||
state.maxplayers = reader.uint(1);
|
||||
if(this.goldsrcInfo) state.raw.address = reader.string();
|
||||
else state.raw.protocol = reader.uint(1);
|
||||
|
||||
if(this.goldsrcInfo) state.raw.protocol = reader.uint(1);
|
||||
else state.raw.numbots = reader.uint(1);
|
||||
state.name = reader.string();
|
||||
state.map = reader.string();
|
||||
state.raw.folder = reader.string();
|
||||
state.raw.game = reader.string();
|
||||
state.raw.steamappid = reader.uint(2);
|
||||
state.raw.numplayers = reader.uint(1);
|
||||
state.maxplayers = reader.uint(1);
|
||||
|
||||
state.raw.listentype = reader.uint(1);
|
||||
state.raw.environment = reader.uint(1);
|
||||
if(!this.goldsrcInfo) {
|
||||
state.raw.listentype = String.fromCharCode(state.raw.listentype);
|
||||
state.raw.environment = String.fromCharCode(state.raw.environment);
|
||||
}
|
||||
if(this.goldsrcInfo) state.raw.protocol = reader.uint(1);
|
||||
else state.raw.numbots = reader.uint(1);
|
||||
|
||||
state.password = !!reader.uint(1);
|
||||
if(this.goldsrcInfo) {
|
||||
state.raw.ismod = reader.uint(1);
|
||||
if(state.raw.ismod) {
|
||||
state.raw.modlink = reader.string();
|
||||
state.raw.moddownload = reader.string();
|
||||
reader.skip(1);
|
||||
state.raw.modversion = reader.uint(4);
|
||||
state.raw.modsize = reader.uint(4);
|
||||
state.raw.modtype = reader.uint(1);
|
||||
state.raw.moddll = reader.uint(1);
|
||||
}
|
||||
}
|
||||
state.raw.secure = reader.uint(1);
|
||||
state.raw.listentype = reader.uint(1);
|
||||
state.raw.environment = reader.uint(1);
|
||||
if(!this.goldsrcInfo) {
|
||||
state.raw.listentype = String.fromCharCode(state.raw.listentype);
|
||||
state.raw.environment = String.fromCharCode(state.raw.environment);
|
||||
}
|
||||
|
||||
if(this.goldsrcInfo) {
|
||||
state.raw.numbots = reader.uint(1);
|
||||
} else {
|
||||
if(state.raw.folder === 'ship') {
|
||||
state.raw.shipmode = reader.uint(1);
|
||||
state.raw.shipwitnesses = reader.uint(1);
|
||||
state.raw.shipduration = reader.uint(1);
|
||||
}
|
||||
state.raw.version = reader.string();
|
||||
state.password = !!reader.uint(1);
|
||||
if(this.goldsrcInfo) {
|
||||
state.raw.ismod = reader.uint(1);
|
||||
if(state.raw.ismod) {
|
||||
state.raw.modlink = reader.string();
|
||||
state.raw.moddownload = reader.string();
|
||||
reader.skip(1);
|
||||
state.raw.modversion = reader.uint(4);
|
||||
state.raw.modsize = reader.uint(4);
|
||||
state.raw.modtype = reader.uint(1);
|
||||
state.raw.moddll = reader.uint(1);
|
||||
}
|
||||
}
|
||||
state.raw.secure = reader.uint(1);
|
||||
|
||||
if(this.goldsrcInfo) {
|
||||
state.raw.numbots = reader.uint(1);
|
||||
} else {
|
||||
if(state.raw.folder === 'ship') {
|
||||
state.raw.shipmode = reader.uint(1);
|
||||
state.raw.shipwitnesses = reader.uint(1);
|
||||
state.raw.shipduration = reader.uint(1);
|
||||
}
|
||||
state.raw.version = reader.string();
|
||||
const extraFlag = reader.uint(1);
|
||||
if(extraFlag & 0x80) state.raw.port = reader.uint(2);
|
||||
if(extraFlag & 0x10) state.raw.steamid = reader.uint(8);
|
||||
if(extraFlag & 0x40) {
|
||||
state.raw.sourcetvport = reader.uint(2);
|
||||
state.raw.sourcetvname = reader.string();
|
||||
}
|
||||
if(extraFlag & 0x20) state.raw.tags = reader.string();
|
||||
if(extraFlag & 0x01) state.raw.gameid = reader.uint(8);
|
||||
}
|
||||
if(extraFlag & 0x80) state.raw.port = reader.uint(2);
|
||||
if(extraFlag & 0x10) state.raw.steamid = reader.uint(8);
|
||||
if(extraFlag & 0x40) {
|
||||
state.raw.sourcetvport = reader.uint(2);
|
||||
state.raw.sourcetvname = reader.string();
|
||||
}
|
||||
if(extraFlag & 0x20) state.raw.tags = reader.string();
|
||||
if(extraFlag & 0x01) state.raw.gameid = reader.uint(8);
|
||||
}
|
||||
|
||||
// from https://developer.valvesoftware.com/wiki/Server_queries
|
||||
if(
|
||||
state.raw.protocol === 7 && (
|
||||
state.raw.steamappid === 215
|
||||
|| state.raw.steamappid === 17550
|
||||
|| state.raw.steamappid === 17700
|
||||
|| state.raw.steamappid === 240
|
||||
)
|
||||
) {
|
||||
this._skipSizeInSplitHeader = true;
|
||||
}
|
||||
if(this.debug) {
|
||||
console.log("STEAM APPID: "+state.raw.steamappid);
|
||||
console.log("PROTOCOL: "+state.raw.protocol);
|
||||
}
|
||||
if(state.raw.protocol === 48) {
|
||||
if(this.debug) console.log("GOLDSRC DETECTED - USING MODIFIED SPLIT FORMAT");
|
||||
this.goldsrcSplits = true;
|
||||
}
|
||||
// from https://developer.valvesoftware.com/wiki/Server_queries
|
||||
if(
|
||||
state.raw.protocol === 7 && (
|
||||
state.raw.steamappid === 215
|
||||
|| state.raw.steamappid === 17550
|
||||
|| state.raw.steamappid === 17700
|
||||
|| state.raw.steamappid === 240
|
||||
)
|
||||
) {
|
||||
this._skipSizeInSplitHeader = true;
|
||||
}
|
||||
if(this.debug) {
|
||||
console.log("STEAM APPID: "+state.raw.steamappid);
|
||||
console.log("PROTOCOL: "+state.raw.protocol);
|
||||
}
|
||||
if(state.raw.protocol === 48) {
|
||||
if(this.debug) console.log("GOLDSRC DETECTED - USING MODIFIED SPLIT FORMAT");
|
||||
this.goldsrcSplits = true;
|
||||
}
|
||||
|
||||
c();
|
||||
}
|
||||
);
|
||||
}
|
||||
c();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
queryChallenge(state,c) {
|
||||
if(this.legacyChallenge) {
|
||||
this.sendPacket(0x57,false,false,0x41,(b) => {
|
||||
// sendPacket will catch the response packet and
|
||||
// save the challenge for us
|
||||
c();
|
||||
});
|
||||
} else {
|
||||
c();
|
||||
}
|
||||
}
|
||||
queryChallenge(state,c) {
|
||||
if(this.legacyChallenge) {
|
||||
this.sendPacket(0x57,false,false,0x41,(b) => {
|
||||
// sendPacket will catch the response packet and
|
||||
// save the challenge for us
|
||||
c();
|
||||
});
|
||||
} else {
|
||||
c();
|
||||
}
|
||||
}
|
||||
|
||||
queryPlayers(state,c) {
|
||||
this.sendPacket(0x55,true,false,0x44,(b) => {
|
||||
queryPlayers(state,c) {
|
||||
this.sendPacket(0x55,true,false,0x44,(b) => {
|
||||
const reader = this.reader(b);
|
||||
const num = reader.uint(1);
|
||||
for(let i = 0; i < num; i++) {
|
||||
reader.skip(1);
|
||||
for(let i = 0; i < num; i++) {
|
||||
reader.skip(1);
|
||||
const name = reader.string();
|
||||
const score = reader.int(4);
|
||||
const time = reader.float();
|
||||
|
||||
if(this.debug) console.log("Found player: "+name+" "+score+" "+time);
|
||||
if(this.debug) console.log("Found player: "+name+" "+score+" "+time);
|
||||
|
||||
// connecting players don't count as players.
|
||||
if(!name) continue;
|
||||
// connecting players don't count as players.
|
||||
if(!name) continue;
|
||||
|
||||
(time === -1 ? state.bots : state.players).push({
|
||||
name:name, score:score, time:time
|
||||
});
|
||||
}
|
||||
(time === -1 ? state.bots : state.players).push({
|
||||
name:name, score:score, time:time
|
||||
});
|
||||
}
|
||||
|
||||
if(this.isCsGo && state.players.length === 1 && state.players[0].name === 'Max Players') {
|
||||
if(this.debug) console.log("CSGO server using limited player details");
|
||||
state.players = [];
|
||||
for(let i = 0; i < state.raw.numplayers; i++) {
|
||||
state.players.push({});
|
||||
}
|
||||
}
|
||||
|
||||
// if we didn't find the bots, iterate
|
||||
// through and guess which ones they are
|
||||
if(!state.bots.length && state.raw.numbots) {
|
||||
if(this.isCsGo && state.players.length === 1 && state.players[0].name === 'Max Players') {
|
||||
if(this.debug) console.log("CSGO server using limited player details");
|
||||
state.players = [];
|
||||
for(let i = 0; i < state.raw.numplayers; i++) {
|
||||
state.players.push({});
|
||||
}
|
||||
}
|
||||
|
||||
// if we didn't find the bots, iterate
|
||||
// through and guess which ones they are
|
||||
if(!state.bots.length && state.raw.numbots) {
|
||||
let maxTime = 0;
|
||||
for (const player of state.players) {
|
||||
maxTime = Math.max(player.time,maxTime);
|
||||
}
|
||||
for(let i = 0; i < state.players.length; i++) {
|
||||
const player = state.players[i];
|
||||
if(state.bots.length >= state.raw.numbots) continue;
|
||||
if(player.time !== maxTime) continue;
|
||||
state.bots.push(player);
|
||||
state.players.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
for (const player of state.players) {
|
||||
maxTime = Math.max(player.time,maxTime);
|
||||
}
|
||||
for(let i = 0; i < state.players.length; i++) {
|
||||
const player = state.players[i];
|
||||
if(state.bots.length >= state.raw.numbots) continue;
|
||||
if(player.time !== maxTime) continue;
|
||||
state.bots.push(player);
|
||||
state.players.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
c();
|
||||
});
|
||||
}
|
||||
c();
|
||||
});
|
||||
}
|
||||
|
||||
queryRules(state,c) {
|
||||
this.sendPacket(0x56,true,false,0x45,(b) => {
|
||||
queryRules(state,c) {
|
||||
this.sendPacket(0x56,true,false,0x45,(b) => {
|
||||
const reader = this.reader(b);
|
||||
const num = reader.uint(2);
|
||||
state.raw.rules = {};
|
||||
for(let i = 0; i < num; i++) {
|
||||
state.raw.rules = {};
|
||||
for(let i = 0; i < num; i++) {
|
||||
const key = reader.string();
|
||||
const value = reader.string();
|
||||
state.raw.rules[key] = value;
|
||||
}
|
||||
c();
|
||||
}, () => {
|
||||
// no rules were returned after timeout --
|
||||
// the server probably has them disabled
|
||||
// ignore the timeout
|
||||
c();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
state.raw.rules[key] = value;
|
||||
}
|
||||
c();
|
||||
}, () => {
|
||||
// no rules were returned after timeout --
|
||||
// the server probably has them disabled
|
||||
// ignore the timeout
|
||||
c();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
sendPacket(type,sendChallenge,payload,expect,callback,ontimeout) {
|
||||
const packetStorage = {};
|
||||
sendPacket(type,sendChallenge,payload,expect,callback,ontimeout) {
|
||||
const packetStorage = {};
|
||||
|
||||
const receivedFull = (reader) => {
|
||||
const type = reader.uint(1);
|
||||
|
|
@ -301,28 +301,28 @@ class Valve extends require('./core') {
|
|||
}
|
||||
};
|
||||
|
||||
const send = (c) => {
|
||||
if(typeof payload === 'string') payload = Buffer.from(payload,'binary');
|
||||
const send = (c) => {
|
||||
if(typeof payload === 'string') payload = Buffer.from(payload,'binary');
|
||||
const challengeLength = sendChallenge ? 4 : 0;
|
||||
const payloadLength = payload ? payload.length : 0;
|
||||
|
||||
const b = Buffer.alloc(5 + challengeLength + payloadLength);
|
||||
b.writeInt32LE(-1, 0);
|
||||
b.writeUInt8(type, 4);
|
||||
|
||||
if(sendChallenge) {
|
||||
let challenge = this._challenge;
|
||||
if(!challenge) challenge = 0xffffffff;
|
||||
if(this.byteorder === 'le') b.writeUInt32LE(challenge, 5);
|
||||
else b.writeUInt32BE(challenge, 5);
|
||||
}
|
||||
if(payloadLength) payload.copy(b, 5+challengeLength);
|
||||
b.writeInt32LE(-1, 0);
|
||||
b.writeUInt8(type, 4);
|
||||
|
||||
this.udpSend(b,receivedOne,ontimeout);
|
||||
};
|
||||
if(sendChallenge) {
|
||||
let challenge = this._challenge;
|
||||
if(!challenge) challenge = 0xffffffff;
|
||||
if(this.byteorder === 'le') b.writeUInt32LE(challenge, 5);
|
||||
else b.writeUInt32BE(challenge, 5);
|
||||
}
|
||||
if(payloadLength) payload.copy(b, 5+challengeLength);
|
||||
|
||||
this.udpSend(b,receivedOne,ontimeout);
|
||||
};
|
||||
|
||||
send();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Valve;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue