mirror of
https://github.com/gamedig/node-gamedig.git
synced 2024-11-17 09:18:31 +01:00
Add openttd support
This commit is contained in:
parent
b8d41ef318
commit
0fe80d14e7
5 changed files with 165 additions and 2 deletions
|
@ -207,6 +207,7 @@ Games List
|
||||||
* No One Lives Forever 2 (nolf2) [[Separate Query Port](#separate-query-port)]
|
* No One Lives Forever 2 (nolf2) [[Separate Query Port](#separate-query-port)]
|
||||||
* Nuclear Dawn (nucleardawn)
|
* Nuclear Dawn (nucleardawn)
|
||||||
* OpenArena (openarena) [[Separate Query Port](#separate-query-port)]
|
* OpenArena (openarena) [[Separate Query Port](#separate-query-port)]
|
||||||
|
* OpenTTD (openttd)
|
||||||
* Operation Flashpoint (operationflashpoint) [[Separate Query Port](#separate-query-port)]
|
* Operation Flashpoint (operationflashpoint) [[Separate Query Port](#separate-query-port)]
|
||||||
* Painkiller (painkiller) [[Separate Query Port](#separate-query-port)]
|
* Painkiller (painkiller) [[Separate Query Port](#separate-query-port)]
|
||||||
* Postal 2 (postal2) [[Separate Query Port](#separate-query-port)]
|
* Postal 2 (postal2) [[Separate Query Port](#separate-query-port)]
|
||||||
|
@ -312,7 +313,6 @@ Games List
|
||||||
* GTR2
|
* GTR2
|
||||||
* Haze
|
* Haze
|
||||||
* Hexen 2
|
* Hexen 2
|
||||||
* OpenTTD
|
|
||||||
* Plain Sight
|
* Plain Sight
|
||||||
* Red Faction
|
* Red Faction
|
||||||
* Savage: Battle for Newerth
|
* Savage: Battle for Newerth
|
||||||
|
|
|
@ -178,6 +178,7 @@ nolf|No One Lives Forever|gamespy1|port_query=27888
|
||||||
nolf2|No One Lives Forever 2|gamespy1|port_query=27890
|
nolf2|No One Lives Forever 2|gamespy1|port_query=27890
|
||||||
nucleardawn|Nuclear Dawn|valve
|
nucleardawn|Nuclear Dawn|valve
|
||||||
openarena|OpenArena|quake3|port_query=27960
|
openarena|OpenArena|quake3|port_query=27960
|
||||||
|
openttd|OpenTTD|openttd|port=3979
|
||||||
operationflashpoint|Operation Flashpoint|gamespy1|port=2234,port_query_offset=1
|
operationflashpoint|Operation Flashpoint|gamespy1|port=2234,port_query_offset=1
|
||||||
painkiller|Painkiller|ase|port=3455,port_query_offset=123
|
painkiller|Painkiller|ase|port=3455,port_query_offset=123
|
||||||
postal2|Postal 2|gamespy1|port=7777,port_query_offset=1
|
postal2|Postal 2|gamespy1|port=7777,port_query_offset=1
|
||||||
|
|
|
@ -110,6 +110,16 @@ Reader.prototype = {
|
||||||
this.i += 4;
|
this.i += 4;
|
||||||
return r;
|
return r;
|
||||||
},
|
},
|
||||||
|
part: function(bytes) {
|
||||||
|
var r;
|
||||||
|
if(this.remaining() >= bytes) {
|
||||||
|
r = this.buffer.slice(this.i,this.i+bytes);
|
||||||
|
} else {
|
||||||
|
r = new Buffer();
|
||||||
|
}
|
||||||
|
this.i += bytes;
|
||||||
|
return r;
|
||||||
|
},
|
||||||
remaining: function() {
|
remaining: function() {
|
||||||
return this.buffer.length-this.i;
|
return this.buffer.length-this.i;
|
||||||
},
|
},
|
||||||
|
|
|
@ -33,7 +33,8 @@
|
||||||
"gbxremote": "~0.1.4",
|
"gbxremote": "~0.1.4",
|
||||||
"request": "~2.33.0",
|
"request": "~2.33.0",
|
||||||
"optimist": "~0.6.0",
|
"optimist": "~0.6.0",
|
||||||
"varint": "~1.0.0"
|
"varint": "~1.0.0",
|
||||||
|
"moment": "~2.8.3"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"gamedig": "bin/gamedig.js"
|
"gamedig": "bin/gamedig.js"
|
||||||
|
|
151
protocols/openttd.js
Normal file
151
protocols/openttd.js
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
var async = require('async'),
|
||||||
|
moment = require('moment');
|
||||||
|
|
||||||
|
module.exports = require('./core').extend({
|
||||||
|
run: function(state) {
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
async.series([
|
||||||
|
function(c) {
|
||||||
|
var b = new Buffer([0x03,0x00,0x00]);
|
||||||
|
self.query(0,1,1,4,function(reader, version) {
|
||||||
|
if(version >= 4) {
|
||||||
|
var numGrf = reader.uint(1);
|
||||||
|
state.raw.grfs = [];
|
||||||
|
console.log("GRF", numGrf);
|
||||||
|
for(var i = 0; i < numGrf; i++) {
|
||||||
|
var grf = {};
|
||||||
|
grf.id = reader.part(4).toString('hex');
|
||||||
|
grf.md5 = reader.part(16).toString('hex');
|
||||||
|
state.raw.grfs.push(grf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(version >= 3) {
|
||||||
|
state.raw.date_current = self.readDate(reader);
|
||||||
|
state.raw.date_start = self.readDate(reader);
|
||||||
|
}
|
||||||
|
if(version >= 2) {
|
||||||
|
state.raw.maxcompanies = reader.uint(1);
|
||||||
|
state.raw.numcompanies = reader.uint(1);
|
||||||
|
state.raw.maxspectators = reader.uint(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
state.name = reader.string();
|
||||||
|
state.raw.version = reader.string();
|
||||||
|
|
||||||
|
state.raw.language = self.decode(
|
||||||
|
reader.uint(1),
|
||||||
|
['any','en','de','fr']
|
||||||
|
);
|
||||||
|
|
||||||
|
state.password = !!reader.uint(1);
|
||||||
|
state.maxplayers = reader.uint(1);
|
||||||
|
state.raw.numplayers = reader.uint(1);
|
||||||
|
for(var i = 0; i < state.raw.numplayers; i++) {
|
||||||
|
state.players.push({});
|
||||||
|
}
|
||||||
|
state.raw.spectators = reader.uint(1);
|
||||||
|
state.map = reader.string();
|
||||||
|
state.raw.map_width = reader.uint(2);
|
||||||
|
state.raw.map_height = reader.uint(2);
|
||||||
|
|
||||||
|
state.raw.landscape = self.decode(
|
||||||
|
reader.uint(1),
|
||||||
|
['temperate','arctic','desert','toyland']
|
||||||
|
);
|
||||||
|
|
||||||
|
state.raw.dedicated = !!reader.uint(1);
|
||||||
|
|
||||||
|
c();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function(c) {
|
||||||
|
var vehicle_types = ['train','truck','bus','aircraft','ship'];
|
||||||
|
var station_types = ['station','truckbay','busstation','airport','dock'];
|
||||||
|
|
||||||
|
self.query(2,3,-1,-1, function(reader,version) {
|
||||||
|
// we don't know how to deal with companies outside version 6
|
||||||
|
if(version != 6) return c();
|
||||||
|
|
||||||
|
state.raw.companies = [];
|
||||||
|
var numCompanies = reader.uint(1);
|
||||||
|
for(var iCompany = 0; iCompany < numCompanies; iCompany++) {
|
||||||
|
var company = {};
|
||||||
|
company.id = reader.uint(1);
|
||||||
|
company.name = reader.string();
|
||||||
|
company.year_start = reader.uint(4);
|
||||||
|
company.value = reader.uint(8);
|
||||||
|
company.money = reader.uint(8);
|
||||||
|
company.income = reader.uint(8);
|
||||||
|
company.performance = reader.uint(2);
|
||||||
|
company.password = !!reader.uint(1);
|
||||||
|
|
||||||
|
company.vehicles = {};
|
||||||
|
for(var i = 0; i < vehicle_types.length; i++) {
|
||||||
|
company.vehicles[vehicle_types[i]] = reader.uint(2);
|
||||||
|
}
|
||||||
|
company.stations = {};
|
||||||
|
for(var i = 0; i < station_types.length; i++) {
|
||||||
|
company.stations[station_types[i]] = reader.uint(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
company.clients = reader.string();
|
||||||
|
state.raw.companies.push(company);
|
||||||
|
}
|
||||||
|
|
||||||
|
c();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function(c) {
|
||||||
|
self.finish(state);
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
query: function(type,expected,minver,maxver,done) {
|
||||||
|
var self = this;
|
||||||
|
var b = new Buffer([0x03,0x00,type]);
|
||||||
|
self.udpSend(b,function(buffer) {
|
||||||
|
var reader = self.reader(buffer);
|
||||||
|
|
||||||
|
var packetLen = reader.uint(2);
|
||||||
|
if(packetLen != buffer.length) {
|
||||||
|
self.fatal('Invalid reported packet length: '+packetLen+' '+buffer.length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var packetType = reader.uint(1);
|
||||||
|
if(packetType != expected) {
|
||||||
|
self.fatal('Unexpected response packet type: '+packetType);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var protocolVersion = reader.uint(1);
|
||||||
|
if((minver != -1 && protocolVersion < minver) || (maxver != -1 && protocolVersion > maxver)) {
|
||||||
|
self.fatal('Unknown protocol version: '+protocolVersion+' Expected: '+minver+'-'+maxver);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
done(reader,protocolVersion);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
readDate: function(reader) {
|
||||||
|
var daysSinceZero = reader.uint(4);
|
||||||
|
var temp = new Date(0,0,1);
|
||||||
|
temp.setFullYear(0);
|
||||||
|
temp.setDate(daysSinceZero+1);
|
||||||
|
return moment(temp).format('YYYY-MM-DD');
|
||||||
|
},
|
||||||
|
|
||||||
|
decode: function(num,arr) {
|
||||||
|
if(num < 0 || num >= arr.length) {
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
return arr[num];
|
||||||
|
}
|
||||||
|
});
|
Loading…
Reference in a new issue