From bdb819d0f85d908e9be45c33d5c6fcf17758dad0 Mon Sep 17 00:00:00 2001 From: James Causon Date: Wed, 17 Jul 2024 16:10:06 +0100 Subject: [PATCH] feat: Add support for AltvMP (#588) * feat: Add Minetest support using serverlist * Allow for connect to be assigned, * Add serverId to the string args * Add altvmp implementation * Added altv to games. * Add changelog entry * Update CHANGELOG.md with state.connect --- CHANGELOG.md | 2 ++ GAMES_LIST.md | 8 ++++++ bin/gamedig.js | 2 +- lib/games.js | 11 ++++++++ protocols/altvmp.js | 63 +++++++++++++++++++++++++++++++++++++++++++++ protocols/core.js | 2 +- protocols/index.js | 3 ++- 7 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 protocols/altvmp.js diff --git a/CHANGELOG.md b/CHANGELOG.md index d112c74..9469fc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## To Be Released... ## 5.X.Y * FOUNDRY - Added support (#585) +* Grand Theft Auto V: AltVMP - Added support (By @xCausxn #588) +* Fix ability to manual set `state.connect` (By @xCausxn #588) ## 5.0.1 * Minetest - Added support for minetest utilizing official server list (By @xCausxn #573) diff --git a/GAMES_LIST.md b/GAMES_LIST.md index 4d536d8..a5371b5 100644 --- a/GAMES_LIST.md +++ b/GAMES_LIST.md @@ -139,6 +139,7 @@ | groundbreach | Ground Breach | [Valve Protocol](#valve) | | gta5f | Grand Theft Auto V - FiveM | | | gta5r | Grand Theft Auto V - RAGE MP | [Notes](#gta5r) | +| gta5a | Grand Theft Auto V - AltVMP | [Notes](#gta5a) | | gtasam | Grand Theft Auto: San Andreas Multiplayer | | | gtasamta | Grand Theft Auto: San Andreas - Multi Theft Auto | | | gtasao | Grand Theft Auto: San Andreas OpenMP | | @@ -422,6 +423,13 @@ Pass the login into to GameDig with the additional options: login, password If you are using a FQDN for your server, you will need to set the host parameter to be this domain e.g. rage2.mydomain.com This is due to how the Rage MP master server works with server ids as the ip is only used in the ID if no FQDN is provided. +### Grand Theft Auto V - AltV MP +When querying a server on AltV MP, you have two options for querying the server: +1. Setting the `serverId` request field or `--serverId` when using the cli to the publicId of the server. +2. Passing the `host` and `port` request fields or `--host` and `--port` when using the cli to the server. + +If you are using the second option and the server is using a `useCdn` option in the altv server config file, you will need to set `host` to the CDN address, and the `port` to the cdn port. As an example, if the server cdn url was `connect.altv.com:443`, you would set the host to `connect.altv.com` and port to `443`. + ### TeamSpeak 3 For teamspeak 3 queries to work correctly, the following permissions must be available for the guest server group: diff --git a/bin/gamedig.js b/bin/gamedig.js index 077d8fd..38ed1ec 100644 --- a/bin/gamedig.js +++ b/bin/gamedig.js @@ -7,7 +7,7 @@ import { GameDig } from './../lib/index.js' const argv = Minimist(process.argv.slice(2), { boolean: ['pretty', 'debug', 'givenPortOnly', 'requestRules', 'requestRulesRequired', 'requestPlayersRequired', 'stripColors', 'portCache', 'noBreadthOrder', 'checkOldIDs'], - string: ['guildId', 'listenUdpPort', 'ipFamily', 'token'], + string: ['guildId', 'serverId', 'listenUdpPort', 'ipFamily', 'token'], default: { stripColors: true, portCache: true diff --git a/lib/games.js b/lib/games.js index 7bf8341..eccc620 100644 --- a/lib/games.js +++ b/lib/games.js @@ -1289,6 +1289,17 @@ export const games = { doc_notes: 'gta5r' } }, + gta5a: { + name: 'Grand Theft Auto V - AltVMP', + release_year: 2015, + options: { + port: 7788, + protocol: 'altvmp' + }, + extra: { + doc_notes: 'gta5a' + } + }, garrysmod: { name: "Garry's Mod", release_year: 2004, diff --git a/protocols/altvmp.js b/protocols/altvmp.js new file mode 100644 index 0000000..8f86d4f --- /dev/null +++ b/protocols/altvmp.js @@ -0,0 +1,63 @@ +import Core from './core.js' + +export default class altvmp extends Core { + constructor() { + super() + this.usedTcp = true + } + + async getServerFromMasterList() { + const targetID = `${this.options.host}:${this.options.port}` + + const results = await this.request({ + url: 'https://api.alt-mp.com/servers', + responseType: 'json' + }) + + if (results == null) { + throw new Error('Unable to retrieve master server list') + } + + const serverInfo = results.find((server) => { + // If the server uses a CDN, there could be occasional paths in the address, so we are checking for them. + // If the server does not use a CDN, there will be no paths in the address and direct comparison will work. + const address = server.useCdn + ? server.address + : server.address.replace(/(https?:\/\/)?\/?/g, '') + return address === targetID + }) + + return serverInfo + } + + async getServerById(targetID) { + const serverInfo = await this.request({ + url: `https://api.alt-mp.com/servers/${targetID}`, + responseType: 'json' + }) + + if (serverInfo == null) { + throw new Error('Unable to retrieve server info') + } + + return serverInfo + } + + async run(state) { + const serverInfo = this.options.serverId + ? await this.getServerById(this.options.serverId) + : await this.getServerFromMasterList() + + if (!serverInfo) { + throw new Error('No server info was found.') + } + + state.name = serverInfo.name + state.numplayers = serverInfo.playersCount + state.maxplayers = serverInfo.maxPlayersCount + state.password = serverInfo.passworded + state.version = serverInfo.version + state.connect = `altv://${serverInfo.address}` + state.raw = serverInfo + } +} diff --git a/protocols/core.js b/protocols/core.js index 033e5c2..bbdfc46 100644 --- a/protocols/core.js +++ b/protocols/core.js @@ -84,7 +84,7 @@ export default class Core extends EventEmitter { state.queryPort = options.port // because lots of servers prefix with spaces to try to appear first state.name = (state.name || '').trim() - state.connect = `${state.gameHost || options.host || options.address}:${state.gamePort || options.port}` + state.connect = state.connect || `${state.gameHost || options.host || options.address}:${state.gamePort || options.port}` state.ping = this.shortestRTT delete state.gameHost diff --git a/protocols/index.js b/protocols/index.js index 885d447..4740fee 100644 --- a/protocols/index.js +++ b/protocols/index.js @@ -59,11 +59,12 @@ import dayz from './dayz.js' import theisleevrima from './theisleevrima.js' import ragemp from './ragemp.js' import xonotic from './xonotic.js' +import altvmp from './altvmp.js' export { armagetron, ase, asa, assettocorsa, battlefield, buildandshoot, cs2d, discord, doom3, eco, epic, factorio, farmingsimulator, ffow, fivem, gamespy1, gamespy2, gamespy3, geneshift, goldsrc, gtasao, hexen2, jc2mp, kspdmp, mafia2mp, mafia2online, minecraft, minecraftbedrock, minecraftvanilla, minetest, mumble, mumbleping, nadeo, openttd, palworld, quake1, quake2, quake3, rfactor, ragemp, samp, savage2, starmade, starsiege, teamspeak2, teamspeak3, terraria, tribes1, tribes1master, unreal2, ut3, valve, - vcmp, ventrilo, warsow, eldewrito, beammpmaster, beammp, dayz, theisleevrima, xonotic + vcmp, ventrilo, warsow, eldewrito, beammpmaster, beammp, dayz, theisleevrima, xonotic, altvmp }