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:
CosminPerRam 2023-11-19 02:59:31 +02:00 committed by GitHub
parent 2fb9f507e2
commit ce4cddb87f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 2456 additions and 468 deletions

View file

@ -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
}
}

View file

@ -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
View 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

File diff suppressed because it is too large Load diff