mirror of
https://github.com/tribufu/node-gamedig
synced 2026-05-18 09:35:50 +00:00
feat: remove games.txt and replace it with an in-code solution (#407)
* feat: remove games.txt and replace it with an in-code solution * docs: update changelog * chore: add todo comment regarding weird game ids to rename * fix: generate games list md file * fix: gemerate games list file to alphabetical id order * fix: update changelog to note removal of some game ids and add geneshift alternative
This commit is contained in:
parent
2fb9f507e2
commit
ce4cddb87f
7 changed files with 2456 additions and 468 deletions
|
|
@ -1,114 +0,0 @@
|
|||
import * as path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import * as fs from 'node:fs'
|
||||
|
||||
export default class GameResolver {
|
||||
constructor () {
|
||||
const loaded = this._readGames()
|
||||
this.gamesByKey = loaded.gamesByKey
|
||||
this.games = loaded.games
|
||||
}
|
||||
|
||||
lookup (type) {
|
||||
if (!type) { throw Error('No game specified') }
|
||||
|
||||
if (type.startsWith('protocol-')) {
|
||||
return {
|
||||
protocol: type.substring(9)
|
||||
}
|
||||
}
|
||||
|
||||
const game = this.gamesByKey.get(type)
|
||||
|
||||
if (!game) { throw Error('Invalid game: ' + type) }
|
||||
|
||||
return game.options
|
||||
}
|
||||
|
||||
printReadme () {
|
||||
let out = ''
|
||||
out += '| GameDig Type ID | Name | See Also\n'
|
||||
out += '|---|---|---\n'
|
||||
|
||||
const sorted = this.games
|
||||
.filter(game => game.pretty)
|
||||
.sort((a, b) => {
|
||||
return a.pretty.localeCompare(b.pretty)
|
||||
})
|
||||
for (const game of sorted) {
|
||||
const keysOut = game.keys.map(key => '`' + key + '`').join('<br>')
|
||||
out += '| ' + keysOut.padEnd(10, ' ') + ' ' +
|
||||
'| ' + game.pretty
|
||||
const notes = []
|
||||
if (game.extra.doc_notes) {
|
||||
notes.push('[Notes](#' + game.extra.doc_notes + ')')
|
||||
}
|
||||
if (game.options.protocol === 'valve') {
|
||||
notes.push('[Valve Protocol](#valve)')
|
||||
}
|
||||
if (notes.length) {
|
||||
out += ' | ' + notes.join(', ')
|
||||
}
|
||||
out += '\n'
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
_readGames () {
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = path.dirname(__filename)
|
||||
const gamesFile = path.normalize(__dirname + '/../games.txt')
|
||||
const lines = fs.readFileSync(gamesFile, 'utf8').split('\n')
|
||||
|
||||
const gamesByKey = new Map()
|
||||
const games = []
|
||||
|
||||
for (let line of lines) {
|
||||
// strip comments
|
||||
const comment = line.indexOf('#')
|
||||
if (comment !== -1) line = line.substring(0, comment)
|
||||
line = line.trim()
|
||||
if (!line) continue
|
||||
|
||||
const split = line.split('|')
|
||||
const keys = split[0].trim().split(',')
|
||||
const name = split[1].trim()
|
||||
const options = this._parseList(split[3])
|
||||
options.protocol = split[2].trim()
|
||||
const extra = this._parseList(split[4])
|
||||
|
||||
const game = {
|
||||
keys,
|
||||
pretty: name,
|
||||
options,
|
||||
extra
|
||||
}
|
||||
|
||||
for (const key of keys) {
|
||||
gamesByKey.set(key, game)
|
||||
}
|
||||
|
||||
games.push(game)
|
||||
}
|
||||
return { gamesByKey, games }
|
||||
}
|
||||
|
||||
_parseList (str) {
|
||||
if (!str) { return {} }
|
||||
|
||||
const out = {}
|
||||
for (const one of str.split(',')) {
|
||||
const equals = one.indexOf('=')
|
||||
const key = equals === -1 ? one : one.substring(0, equals)
|
||||
|
||||
/** @type {string|number|boolean} */
|
||||
let value = equals === -1 ? '' : one.substring(equals + 1)
|
||||
|
||||
if (value === 'true' || value === '') { value = true } else if (value === 'false') { value = false } else if (!isNaN(parseInt(value))) { value = parseInt(value) }
|
||||
|
||||
out[key] = value
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import GameResolver from './GameResolver.js'
|
||||
import { lookup } from './game-resolver.js'
|
||||
import { getProtocol } from './ProtocolResolver.js'
|
||||
import GlobalUdpSocket from './GlobalUdpSocket.js'
|
||||
|
||||
|
|
@ -14,7 +14,6 @@ export default class QueryRunner {
|
|||
this.udpSocket = new GlobalUdpSocket({
|
||||
port: runnerOpts.listenUdpPort
|
||||
})
|
||||
this.gameResolver = new GameResolver()
|
||||
}
|
||||
|
||||
async run (userOptions) {
|
||||
|
|
@ -29,7 +28,7 @@ export default class QueryRunner {
|
|||
port_query: gameQueryPort,
|
||||
port_query_offset: gameQueryPortOffset,
|
||||
...gameOptions
|
||||
} = this.gameResolver.lookup(userOptions.type)
|
||||
} = lookup(userOptions.type)
|
||||
const attempts = []
|
||||
|
||||
const optionsCollection = {
|
||||
|
|
@ -78,7 +77,7 @@ export default class QueryRunner {
|
|||
} finally {
|
||||
// Deno doesn't support unref, so we must close the socket after every connection
|
||||
// https://github.com/denoland/deno/issues/20138
|
||||
if (typeof Deno !== "undefined") {
|
||||
if (typeof Deno !== 'undefined') {
|
||||
this.udpSocket?.socket?.close()
|
||||
delete this.udpSocket
|
||||
}
|
||||
|
|
|
|||
17
lib/game-resolver.js
Normal file
17
lib/game-resolver.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { games } from './games.js'
|
||||
|
||||
export const lookup = (type) => {
|
||||
if (!type) { throw Error('No game specified') }
|
||||
|
||||
if (type.startsWith('protocol-')) {
|
||||
return {
|
||||
protocol: type.substring(9)
|
||||
}
|
||||
}
|
||||
|
||||
const game = games[type]
|
||||
|
||||
if (!game) { throw Error('Invalid game: ' + type) }
|
||||
|
||||
return game.options
|
||||
}
|
||||
2404
lib/games.js
Normal file
2404
lib/games.js
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue