Added support for cs2d (2.0.5)

This commit is contained in:
mmorrison 2019-01-13 23:54:36 -06:00
parent 04bd6d9514
commit 5aaff8e1e0
6 changed files with 90 additions and 4 deletions

View file

@ -125,6 +125,7 @@ Games List
* Conan Exiles (conanexiles) * Conan Exiles (conanexiles)
* Contact J.A.C.K. (contactjack) * Contact J.A.C.K. (contactjack)
* Counter-Strike 1.6 (cs16) * Counter-Strike 1.6 (cs16)
* Counter-Strike: 2D (cs2d)
* Counter-Strike: Condition Zero (cscz) * Counter-Strike: Condition Zero (cscz)
* Counter-Strike: Source (css) * Counter-Strike: Source (css)
* Counter-Strike: Global Offensive (csgo) [[Additional Notes](#csgo)] * Counter-Strike: Global Offensive (csgo) [[Additional Notes](#csgo)]
@ -428,6 +429,9 @@ as well: `--debug`, `--pretty`, `--socketTimeout 5000`, etc.
Changelog Changelog
--- ---
### 2.0.5
* Added support for Counter-Strike: 2D
### 2.0.4 ### 2.0.4
* Added details about new 2.0 reponse fields to the README. * Added details about new 2.0 reponse fields to the README.

View file

@ -1,8 +1,12 @@
#!/usr/bin/env node #!/usr/bin/env node
const argv = require('minimist')(process.argv.slice(2)), const Minimist = require('minimist'),
Gamedig = require('..'); Gamedig = require('..');
const argv = Minimist(process.argv.slice(2), {
boolean: ['pretty','debug']
});
const debug = argv.debug; const debug = argv.debug;
delete argv.debug; delete argv.debug;
const pretty = !!argv.pretty || debug; const pretty = !!argv.pretty || debug;

View file

@ -10,7 +10,6 @@
# rfactor|rFactor|rfactor|port=34397,port_query_offset=-100 # rfactor|rFactor|rfactor|port=34397,port_query_offset=-100
# bfris|BFRIS|bfris|port=44001 # bfris|BFRIS|bfris|port=44001
# cs2d|Counter-Strike: 2D|cs2d|port_query=36963
# freelancer|Freelancer|freelancer|port_query=2302 # freelancer|Freelancer|freelancer|port_query=2302
# gr|Ghost Recon|ghostrecon|port=2346,port_query_offset=2 # gr|Ghost Recon|ghostrecon|port=2346,port_query_offset=2
# gtr2|GTR2|gtr2|port=34297,port_query_offset=1 # gtr2|GTR2|gtr2|port=34297,port_query_offset=1
@ -83,6 +82,7 @@ conanexiles|Conan Exiles|valve|port=7777,port_query=27015
contactjack|Contact J.A.C.K.|gamespy1|port_query=27888 contactjack|Contact J.A.C.K.|gamespy1|port_query=27888
cs16|Counter-Strike 1.6|valve|port=27015 cs16|Counter-Strike 1.6|valve|port=27015
cs2d|Counter-Strike: 2D|cs2d|port=36963
cscz|Counter-Strike: Condition Zero|valve|port=27015 cscz|Counter-Strike: Condition Zero|valve|port=27015
css|Counter-Strike: Source|valve|port=27015 css|Counter-Strike: Source|valve|port=27015
csgo|Counter-Strike: Global Offensive|valve|port=27015|doc_notes=csgo csgo|Counter-Strike: Global Offensive|valve|port=27015|doc_notes=csgo

View file

@ -11,7 +11,7 @@
], ],
"main": "lib/index.js", "main": "lib/index.js",
"author": "Michael Morrison", "author": "Michael Morrison",
"version": "2.0.4", "version": "2.0.5",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/sonicsnes/node-gamedig.git" "url": "https://github.com/sonicsnes/node-gamedig.git"

View file

@ -278,7 +278,7 @@ class Core extends EventEmitter {
/** /**
* @param {Buffer|string} buffer * @param {Buffer|string} buffer
* @param {function(Buffer):T} onPacket * @param {function(Buffer):T=} onPacket
* @param {(function():T)=} onTimeout * @param {(function():T)=} onTimeout
* @returns Promise<T> * @returns Promise<T>
* @template T * @template T
@ -297,6 +297,10 @@ class Core extends EventEmitter {
const socket = this.udpSocket; const socket = this.udpSocket;
socket.send(buffer, address, port); socket.send(buffer, address, port);
if (!onPacket && !onTimeout) {
return null;
}
let socketCallback; let socketCallback;
let timeout; let timeout;
try { try {

74
protocols/cs2d.js Normal file
View file

@ -0,0 +1,74 @@
const Core = require('./core');
class Cs2d extends Core {
async run(state) {
{
const reader = await this.sendQuery(
Buffer.from('\x01\x00\x03\x10\x21\xFB\x01\x75\x00', 'binary'),
Buffer.from('\x01\x00\xfb\x01', 'binary')
);
const flags = reader.uint(1);
state.raw.flags = flags;
state.password = this.readFlag(flags, 0);
state.raw.registeredOnly = this.readFlag(flags, 1);
state.raw.fogOfWar = this.readFlag(flags, 2);
state.raw.friendlyFire = this.readFlag(flags, 3);
state.raw.botsEnabled = this.readFlag(flags, 5);
state.raw.luaScripts = this.readFlag(flags, 6);
state.name = this.readString(reader);
state.map = this.readString(reader);
state.raw.numplayers = reader.uint(1);
state.maxplayers = reader.uint(1);
state.raw.gamemode = reader.uint(1);
if (state.raw.botsEnabled) {
state.raw.numbots = reader.uint(1);
} else {
state.raw.numbots = 0;
}
}
{
const reader = await this.sendQuery(
Buffer.from('\x01\x00\xFB\x05', 'binary'),
Buffer.from('\x01\x00\xFB\x05', 'binary')
);
state.raw.numplayers2 = reader.uint(1);
while(!reader.done()) {
const player = {};
player.id = reader.uint(1);
player.name = this.readString(reader);
player.team = reader.uint(1);
player.score = reader.uint(4);
player.deaths = reader.uint(4);
if (state.bots.length < state.raw.numbots) {
state.bots.push(player);
} else {
state.players.push(player);
}
}
}
}
async sendQuery(request, expectedHeader) {
// Send multiple copies of the request packet, because cs2d likes to just ignore them randomly
await this.udpSend(request);
await this.udpSend(request);
return await this.udpSend(request, (buffer) => {
const reader = this.reader(buffer);
const header = reader.part(4);
if (!header.equals(expectedHeader)) return;
return reader;
});
}
readFlag(flags, offset) {
return !!(flags & (1 << offset));
}
readString(reader) {
const length = reader.uint(1);
return reader.string({length:length});
}
}
module.exports = Cs2d;