mirror of
https://github.com/tribufu/node-gamedig
synced 2026-05-06 15:17:36 +00:00
More async conversions
This commit is contained in:
parent
77b2cc1c7f
commit
9b8423b20a
15 changed files with 859 additions and 704 deletions
|
|
@ -3,53 +3,71 @@ const Core = require('./core');
|
|||
class Gamespy2 extends Core {
|
||||
constructor() {
|
||||
super();
|
||||
this.sessionId = 1;
|
||||
this.encoding = 'latin1';
|
||||
this.byteorder = 'be';
|
||||
}
|
||||
|
||||
run(state) {
|
||||
const request = Buffer.from([0xfe,0xfd,0x00,0x00,0x00,0x00,0x01,0xff,0xff,0xff]);
|
||||
const packets = [];
|
||||
this.udpSend(request,
|
||||
(buffer) => {
|
||||
if(packets.length && buffer.readUInt8(0) === 0)
|
||||
buffer = buffer.slice(1);
|
||||
packets.push(buffer);
|
||||
},
|
||||
() => {
|
||||
const buffer = Buffer.concat(packets);
|
||||
const reader = this.reader(buffer);
|
||||
const header = reader.uint(1);
|
||||
if(header !== 0) return;
|
||||
const pingId = reader.uint(4);
|
||||
if(pingId !== 1) return;
|
||||
|
||||
while(!reader.done()) {
|
||||
const key = reader.string();
|
||||
const value = reader.string();
|
||||
if(!key) break;
|
||||
state.raw[key] = value;
|
||||
}
|
||||
|
||||
if('hostname' in state.raw) state.name = state.raw.hostname;
|
||||
if('mapname' in state.raw) state.map = state.raw.mapname;
|
||||
if(this.trueTest(state.raw.password)) state.password = true;
|
||||
if('maxplayers' in state.raw) state.maxplayers = parseInt(state.raw.maxplayers);
|
||||
|
||||
state.players = this.readFieldData(reader);
|
||||
state.raw.teams = this.readFieldData(reader);
|
||||
|
||||
this.finish(state);
|
||||
return true;
|
||||
async run(state) {
|
||||
// Parse info
|
||||
{
|
||||
const body = await this.sendPacket([0xff, 0, 0]);
|
||||
const reader = this.reader(body);
|
||||
while (!reader.done()) {
|
||||
const key = reader.string();
|
||||
const value = reader.string();
|
||||
if (!key) break;
|
||||
state.raw[key] = value;
|
||||
}
|
||||
);
|
||||
if('hostname' in state.raw) state.name = state.raw.hostname;
|
||||
if('mapname' in state.raw) state.map = state.raw.mapname;
|
||||
if(this.trueTest(state.raw.password)) state.password = true;
|
||||
if('maxplayers' in state.raw) state.maxplayers = parseInt(state.raw.maxplayers);
|
||||
}
|
||||
|
||||
// Parse players
|
||||
{
|
||||
const body = await this.sendPacket([0, 0xff, 0]);
|
||||
const reader = this.reader(body);
|
||||
state.players = this.readFieldData(reader);
|
||||
}
|
||||
|
||||
// Parse teams
|
||||
{
|
||||
const body = await this.sendPacket([0, 0, 0xff]);
|
||||
const reader = this.reader(body);
|
||||
state.raw.teams = this.readFieldData(reader);
|
||||
}
|
||||
}
|
||||
|
||||
async sendPacket(type) {
|
||||
const request = Buffer.concat([
|
||||
Buffer.from([0xfe,0xfd,0x00]), // gamespy2
|
||||
Buffer.from([0x00,0x00,0x00,0x01]), // ping ID
|
||||
Buffer.from(type)
|
||||
]);
|
||||
return await this.udpSend(request, buffer => {
|
||||
const reader = this.reader(buffer);
|
||||
const header = reader.uint(1);
|
||||
if (header !== 0) return;
|
||||
const pingId = reader.uint(4);
|
||||
if (pingId !== 1) return;
|
||||
return reader.rest();
|
||||
});
|
||||
}
|
||||
|
||||
readFieldData(reader) {
|
||||
const count = reader.uint(1);
|
||||
// count is unreliable (often it's wrong), so we don't use it.
|
||||
// read until we hit an empty first field string
|
||||
const zero = reader.uint(1); // always 0
|
||||
const count = reader.uint(1); // number of rows in this data
|
||||
|
||||
// some games omit the count byte entirely if it's 0 or at random (like americas army)
|
||||
// Luckily, count should always be <64, and ascii characters will typically be >64,
|
||||
// so we can detect this.
|
||||
if (count > 64) {
|
||||
reader.skip(-1);
|
||||
if (this.debug) console.log("Detected missing count byte, rewinding by 1");
|
||||
} else {
|
||||
if (this.debug) console.log("Detected row count: " + count);
|
||||
}
|
||||
|
||||
if(this.debug) console.log("Reading fields, starting at: "+reader.rest());
|
||||
|
||||
|
|
@ -57,11 +75,12 @@ class Gamespy2 extends Core {
|
|||
while(!reader.done()) {
|
||||
let field = reader.string();
|
||||
if(!field) break;
|
||||
if(field.charCodeAt(0) <= 2) field = field.substring(1);
|
||||
fields.push(field);
|
||||
if(this.debug) console.log("field:"+field);
|
||||
}
|
||||
|
||||
if (!fields.length) return [];
|
||||
|
||||
const units = [];
|
||||
outer: while(!reader.done()) {
|
||||
const unit = {};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue