mirror of
https://github.com/tribufu/node-gamedig
synced 2026-06-01 09:42:41 +00:00
Add support for rFactor (2.0.10)
This commit is contained in:
parent
0ac80cc139
commit
81750805f6
12 changed files with 103 additions and 54 deletions
|
|
@ -250,6 +250,7 @@ Games List
|
||||||
* Red Orchestra 2 (redorchestra2)
|
* Red Orchestra 2 (redorchestra2)
|
||||||
* Redline (redline)
|
* Redline (redline)
|
||||||
* Return to Castle Wolfenstein (rtcw)
|
* Return to Castle Wolfenstein (rtcw)
|
||||||
|
* rFactor (rfactor)
|
||||||
* Ricochet (ricochet)
|
* Ricochet (ricochet)
|
||||||
* Rise of Nations (riseofnations)
|
* Rise of Nations (riseofnations)
|
||||||
* Rune (rune)
|
* Rune (rune)
|
||||||
|
|
@ -430,6 +431,9 @@ as well: `--debug`, `--pretty`, `--socketTimeout 5000`, etc.
|
||||||
Changelog
|
Changelog
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### 2.0.10
|
||||||
|
Added support for rFactor
|
||||||
|
|
||||||
### 2.0.9
|
### 2.0.9
|
||||||
Added support for Vice City: Multiplayer
|
Added support for Vice City: Multiplayer
|
||||||
|
|
||||||
|
|
|
||||||
25
games.txt
25
games.txt
|
|
@ -1,29 +1,5 @@
|
||||||
# id | pretty name for readme | protocol | options | extra
|
# 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
|
7d2d|7 Days to Die|valve|port=26900,port_query_offset=1
|
||||||
ageofchivalry|Age of Chivalry|valve|port=27015
|
ageofchivalry|Age of Chivalry|valve|port=27015
|
||||||
aoe2|Age of Empires 2|ase|port_query=27224
|
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
|
redorchestra2|Red Orchestra 2|valve|port=7777,port_query=27015
|
||||||
redline|Redline|gamespy1|port_query=25252
|
redline|Redline|gamespy1|port_query=25252
|
||||||
rtcw|Return to Castle Wolfenstein|quake3|port_query=27960
|
rtcw|Return to Castle Wolfenstein|quake3|port_query=27960
|
||||||
|
rfactor|rFactor|rfactor|port=34397,port_query_offset=-100
|
||||||
ricochet|Ricochet|valve|port=27015
|
ricochet|Ricochet|valve|port=27015
|
||||||
riseofnations|Rise of Nations|gamespy1|port_query=6501
|
riseofnations|Rise of Nations|gamespy1|port_query=6501
|
||||||
rune|Rune|gamespy1|port=7777,port_query_offset=1
|
rune|Rune|gamespy1|port=7777,port_query_offset=1
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
],
|
],
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"author": "Michael Morrison",
|
"author": "Michael Morrison",
|
||||||
"version": "2.0.9",
|
"version": "2.0.10",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sonicsnes/node-gamedig.git"
|
"url": "https://github.com/sonicsnes/node-gamedig.git"
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,21 @@ class Core extends EventEmitter {
|
||||||
// because lots of servers prefix with spaces to try to appear first
|
// because lots of servers prefix with spaces to try to appear first
|
||||||
state.name = (state.name || '').trim();
|
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)) {
|
if (!('connect' in state)) {
|
||||||
state.connect = ''
|
state.connect = ''
|
||||||
+ (state.gameHost || this.options.host || this.options.address)
|
+ (state.gameHost || this.options.host || this.options.address)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ class GeneShift extends Core {
|
||||||
state.raw.country = found[1];
|
state.raw.country = found[1];
|
||||||
state.name = found[4];
|
state.name = found[4];
|
||||||
state.map = found[5];
|
state.map = found[5];
|
||||||
state.raw.numplayers = parseInt(found[6]);
|
state.players = parseInt(found[6]);
|
||||||
state.maxplayers = parseInt(found[7]);
|
state.maxplayers = parseInt(found[7]);
|
||||||
// fields[8] is unknown?
|
// fields[8] is unknown?
|
||||||
state.raw.rules = found[9];
|
state.raw.rules = found[9];
|
||||||
|
|
@ -40,10 +40,6 @@ class GeneShift extends Core {
|
||||||
state.raw.mercs = !!parseInt(found[17]);
|
state.raw.mercs = !!parseInt(found[17]);
|
||||||
// fields[18] is unknown? listen server?
|
// fields[18] is unknown? listen server?
|
||||||
state.raw.version = found[19];
|
state.raw.version = found[19];
|
||||||
|
|
||||||
for(let i = 0; i < state.raw.numplayers; i++) {
|
|
||||||
state.players.push({});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,7 @@ class Jc2mp extends Gamespy3 {
|
||||||
async run(state) {
|
async run(state) {
|
||||||
await super.run(state);
|
await super.run(state);
|
||||||
if(!state.players.length && parseInt(state.raw.numplayers)) {
|
if(!state.players.length && parseInt(state.raw.numplayers)) {
|
||||||
for(let i = 0; i < parseInt(state.raw.numplayers); i++) {
|
state.players = parseInt(state.raw.numplayers);
|
||||||
state.players.push({});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,7 @@ class Minecraft extends Core {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(state.players.length < json.players.online) {
|
state.players = json.players.online;
|
||||||
state.players.push({});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
varIntBuffer(num) {
|
varIntBuffer(num) {
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,9 @@ class MumblePing extends Core {
|
||||||
state.raw.versionMinor = reader.uint(1);
|
state.raw.versionMinor = reader.uint(1);
|
||||||
state.raw.versionPatch = reader.uint(1);
|
state.raw.versionPatch = reader.uint(1);
|
||||||
reader.skip(8);
|
reader.skip(8);
|
||||||
state.raw.numplayers = reader.uint(4);
|
state.players = reader.uint(4);
|
||||||
state.maxplayers = reader.uint(4);
|
state.maxplayers = reader.uint(4);
|
||||||
state.raw.allowedbandwidth = reader.uint(4);
|
state.raw.allowedbandwidth = reader.uint(4);
|
||||||
for(let i = 0; i < state.raw.numplayers; i++) {
|
|
||||||
state.players.push({});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,7 @@ class OpenTtd extends Core {
|
||||||
|
|
||||||
state.password = !!reader.uint(1);
|
state.password = !!reader.uint(1);
|
||||||
state.maxplayers = reader.uint(1);
|
state.maxplayers = reader.uint(1);
|
||||||
state.raw.numplayers = reader.uint(1);
|
state.players = reader.uint(1);
|
||||||
for (let i = 0; i < state.raw.numplayers; i++) {
|
|
||||||
state.players.push({});
|
|
||||||
}
|
|
||||||
state.raw.numspectators = reader.uint(1);
|
state.raw.numspectators = reader.uint(1);
|
||||||
state.map = reader.string();
|
state.map = reader.string();
|
||||||
state.raw.map_width = reader.uint(2);
|
state.raw.map_width = reader.uint(2);
|
||||||
|
|
|
||||||
75
protocols/rfactor.js
Normal file
75
protocols/rfactor.js
Normal 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;
|
||||||
|
|
@ -70,9 +70,7 @@ class Samp extends Core {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!gotPlayerData) {
|
if (!gotPlayerData) {
|
||||||
for(let i = 0; i < state.raw.numplayers; i++) {
|
state.players = state.raw.numplayers;
|
||||||
state.players.push({});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
readString(reader,lenBytes) {
|
readString(reader,lenBytes) {
|
||||||
|
|
|
||||||
|
|
@ -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[3] === 'number') state.raw.version = data[3].toFixed(7).replace(/0+$/, '');
|
||||||
if(typeof data[4] === 'string') state.name = data[4];
|
if(typeof data[4] === 'string') state.name = data[4];
|
||||||
if(typeof data[5] === 'string') state.raw.description = data[5];
|
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(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({});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue