Add support for rFactor (2.0.10)

This commit is contained in:
mmorrison 2019-02-04 01:11:28 -06:00
parent 0ac80cc139
commit 81750805f6
12 changed files with 103 additions and 54 deletions

View File

@ -250,6 +250,7 @@ Games List
* Red Orchestra 2 (redorchestra2)
* Redline (redline)
* Return to Castle Wolfenstein (rtcw)
* rFactor (rfactor)
* Ricochet (ricochet)
* Rise of Nations (riseofnations)
* Rune (rune)
@ -430,6 +431,9 @@ as well: `--debug`, `--pretty`, `--socketTimeout 5000`, etc.
Changelog
---
### 2.0.10
Added support for rFactor
### 2.0.9
Added support for Vice City: Multiplayer

View File

@ -1,29 +1,5 @@
# id | pretty name for readme | protocol | options | extra
#### TODO:
# cube1|Cube 1|cube|port=28786,port_query_offset=1
# assaultcube|Assault Cube|cube|port_query=28764
# cube2|Cube 2: Sauerbraten|cube|port=28785,port_query_offset=1
# bloodfrontier|Blood Frontier|cube
# arcasimracing|Arca Sim Racing|rfactor|port=34397,port_query_offset=-100
# rfactor|rFactor|rfactor|port=34397,port_query_offset=-100
# bfris|BFRIS|bfris|port=44001
# freelancer|Freelancer|freelancer|port_query=2302
# gr|Ghost Recon|ghostrecon|port=2346,port_query_offset=2
# gtr2|GTR2|gtr2|port=34297,port_query_offset=1
# haze|Haze|haze
# plainsight|Plain Sight|plainsight
# redfaction|Red Faction|redfaction|port_query=7755
# savage|Savage|savage|port_query=11235
# savage2|Savage 2|savage2|port_query=11235
# teeworlds|Teeworlds|teeworlds|port=8303
# tribes|Tribes 1: Starsiege|tribes|port_query=28001
# tribes2|Tribes 2|tribes2|port_query=28000
# worldinconflict|World in Conflict|worldinconflict
7d2d|7 Days to Die|valve|port=26900,port_query_offset=1
ageofchivalry|Age of Chivalry|valve|port=27015
aoe2|Age of Empires 2|ase|port_query=27224
@ -218,6 +194,7 @@ redorchestraost|Red Orchestra: Ostfront 41-45|gamespy1|port=7757,port_query_offs
redorchestra2|Red Orchestra 2|valve|port=7777,port_query=27015
redline|Redline|gamespy1|port_query=25252
rtcw|Return to Castle Wolfenstein|quake3|port_query=27960
rfactor|rFactor|rfactor|port=34397,port_query_offset=-100
ricochet|Ricochet|valve|port=27015
riseofnations|Rise of Nations|gamespy1|port_query=6501
rune|Rune|gamespy1|port=7777,port_query_offset=1

View File

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

View File

@ -99,6 +99,21 @@ class Core extends EventEmitter {
// because lots of servers prefix with spaces to try to appear first
state.name = (state.name || '').trim();
if (typeof state.players === 'number') {
const num = state.players;
state.players = [];
for (let i = 0; i < num; i++) {
state.players.push({});
}
}
if (typeof state.bots === 'number') {
const num = state.bots;
state.bots = [];
for (let i = 0; i < num; i++) {
state.bots.push({});
}
}
if (!('connect' in state)) {
state.connect = ''
+ (state.gameHost || this.options.host || this.options.address)

View File

@ -26,7 +26,7 @@ class GeneShift extends Core {
state.raw.country = found[1];
state.name = found[4];
state.map = found[5];
state.raw.numplayers = parseInt(found[6]);
state.players = parseInt(found[6]);
state.maxplayers = parseInt(found[7]);
// fields[8] is unknown?
state.raw.rules = found[9];
@ -40,10 +40,6 @@ class GeneShift extends Core {
state.raw.mercs = !!parseInt(found[17]);
// fields[18] is unknown? listen server?
state.raw.version = found[19];
for(let i = 0; i < state.raw.numplayers; i++) {
state.players.push({});
}
}
}

View File

@ -12,9 +12,7 @@ class Jc2mp extends Gamespy3 {
async run(state) {
await super.run(state);
if(!state.players.length && parseInt(state.raw.numplayers)) {
for(let i = 0; i < parseInt(state.raw.numplayers); i++) {
state.players.push({});
}
state.players = parseInt(state.raw.numplayers);
}
}
}

View File

@ -59,9 +59,7 @@ class Minecraft extends Core {
});
}
}
while(state.players.length < json.players.online) {
state.players.push({});
}
state.players = json.players.online;
}
varIntBuffer(num) {

View File

@ -17,12 +17,9 @@ class MumblePing extends Core {
state.raw.versionMinor = reader.uint(1);
state.raw.versionPatch = reader.uint(1);
reader.skip(8);
state.raw.numplayers = reader.uint(4);
state.players = reader.uint(4);
state.maxplayers = reader.uint(4);
state.raw.allowedbandwidth = reader.uint(4);
for(let i = 0; i < state.raw.numplayers; i++) {
state.players.push({});
}
}
}

View File

@ -35,10 +35,7 @@ class OpenTtd extends Core {
state.password = !!reader.uint(1);
state.maxplayers = reader.uint(1);
state.raw.numplayers = reader.uint(1);
for (let i = 0; i < state.raw.numplayers; i++) {
state.players.push({});
}
state.players = reader.uint(1);
state.raw.numspectators = reader.uint(1);
state.map = reader.string();
state.raw.map_width = reader.uint(2);

75
protocols/rfactor.js Normal file
View File

@ -0,0 +1,75 @@
const Core = require('./core');
class Rfactor extends Core {
constructor() {
super();
//this.byteorder = 'be';
}
async run(state) {
const buffer = await this.udpSend('rF_S',b => b);
const reader = this.reader(buffer);
state.raw.gamename = this.readString(reader, 8);
state.raw.fullUpdate = reader.uint(1);
state.raw.region = reader.uint(2);
state.raw.ip = reader.part(4);
state.raw.size = reader.uint(2);
state.raw.version = reader.uint(2);
state.raw.versionRaceCast = reader.uint(2);
state.gamePort = reader.uint(2);
state.raw.queryPort = reader.uint(2);
state.raw.game = this.readString(reader, 20);
state.name = this.readString(reader, 28);
state.map = this.readString(reader, 32);
state.raw.motd = this.readString(reader, 96);
state.raw.packedAids = reader.uint(2);
state.raw.ping = reader.uint(2);
state.raw.packedFlags = reader.uint(1);
state.raw.rate = reader.uint(1);
state.players = reader.uint(1);
state.maxplayers = reader.uint(1);
state.raw.bots = reader.uint(1);
state.raw.packedSpecial = reader.uint(1);
state.raw.damage = reader.uint(1);
state.raw.packedRules = reader.uint(2);
state.raw.credits1 = reader.uint(1);
state.raw.credits2 = reader.uint(2);
this.logger.debug(reader.offset());
state.raw.time = reader.uint(2);
state.raw.laps = reader.uint(2) / 16;
reader.skip(3);
state.raw.vehicles = reader.string();
state.password = !!(state.raw.packedSpecial & 2);
state.raw.raceCast = !!(state.raw.packedSpecial & 4);
state.raw.fixedSetups = !!(state.raw.packedSpecial & 16);
const aids = [
'TractionControl',
'AntiLockBraking',
'StabilityControl',
'AutoShifting',
'AutoClutch',
'Invulnerability',
'OppositeLock',
'SteeringHelp',
'BrakingHelp',
'SpinRecovery',
'AutoPitstop'
];
state.raw.aids = [];
for (let offset = 0; offset < aids.length; offset++) {
if (state.packedAids && (1 << offset)) {
state.raw.aids.push(aids[offset]);
}
}
}
// Consumes bytesToConsume, but only returns string up to the first null
readString(reader, bytesToConsume) {
return reader.string(bytesToConsume).replace(/\0.*$/g,'');
}
}
module.exports = Rfactor;

View File

@ -70,9 +70,7 @@ class Samp extends Core {
}
}
if (!gotPlayerData) {
for(let i = 0; i < state.raw.numplayers; i++) {
state.players.push({});
}
state.players = state.raw.numplayers;
}
}
readString(reader,lenBytes) {

View File

@ -51,14 +51,8 @@ class Starmade extends Core {
if(typeof data[3] === 'number') state.raw.version = data[3].toFixed(7).replace(/0+$/, '');
if(typeof data[4] === 'string') state.name = data[4];
if(typeof data[5] === 'string') state.raw.description = data[5];
if(typeof data[7] === 'number') state.raw.numplayers = data[7];
if(typeof data[7] === 'number') state.players = data[7];
if(typeof data[8] === 'number') state.maxplayers = data[8];
if('numplayers' in state.raw) {
for(let i = 0; i < state.raw.numplayers; i++) {
state.players.push({});
}
}
}
}