diff --git a/CHANGELOG.md b/CHANGELOG.md
index 97f8335..a8fe7a1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
* Minetest - Added support for minetest utilizing official server list (By @xCausxn #573)
* Soulmask - Added support (By @xCausxn #572)
* Restore Minecraft's favicon (#575)
+* Grand Theft Auto V: Rage MP - Added support (By @xCausxn #576)
* Fix duplicate game entry for The Forest (2014), add old id for backwards compatibility (By @xCausxn #579)
## 5.0.0
diff --git a/GAMES_LIST.md b/GAMES_LIST.md
index 8509ead..40219bc 100644
--- a/GAMES_LIST.md
+++ b/GAMES_LIST.md
@@ -137,6 +137,7 @@
| goldeneyesource | GoldenEye: Source | [Valve Protocol](#valve) |
| groundbreach | Ground Breach | [Valve Protocol](#valve) |
| gta5f | Grand Theft Auto V - FiveM | |
+| gta5r | Grand Theft Auto V - RAGE MP | [Notes](#gta5r) |
| gtasam | Grand Theft Auto: San Andreas Multiplayer | |
| gtasamta | Grand Theft Auto: San Andreas - Multi Theft Auto | |
| gtasao | Grand Theft Auto: San Andreas OpenMP | |
@@ -416,6 +417,10 @@ The server must have xmlrpc enabled, and you must pass the xmlrpc port to GameDi
You must have a user account on the server with access level User or higher.
Pass the login into to GameDig with the additional options: login, password
+### Grand Theft Auto V - RAGE MP
+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.
+
### TeamSpeak 3
For teamspeak 3 queries to work correctly, the following permissions must be available for the guest server group:
diff --git a/lib/games.js b/lib/games.js
index ef1fb83..2ffaa21 100644
--- a/lib/games.js
+++ b/lib/games.js
@@ -1270,6 +1270,17 @@ export const games = {
old_id: 'fivem'
}
},
+ gta5r: {
+ name: 'Grand Theft Auto V - RageMP',
+ release_year: 2016,
+ options: {
+ port: 22005,
+ protocol: 'ragemp'
+ },
+ extra: {
+ doc_notes: 'gta5r'
+ }
+ },
garrysmod: {
name: "Garry's Mod",
release_year: 2004,
diff --git a/protocols/index.js b/protocols/index.js
index 237f3e5..ac02a5f 100644
--- a/protocols/index.js
+++ b/protocols/index.js
@@ -57,11 +57,12 @@ import beammpmaster from './beammpmaster.js'
import beammp from './beammp.js'
import dayz from './dayz.js'
import theisleevrima from './theisleevrima.js'
+import ragemp from './ragemp.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, samp,
+ 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
}
diff --git a/protocols/ragemp.js b/protocols/ragemp.js
new file mode 100644
index 0000000..b1dff3e
--- /dev/null
+++ b/protocols/ragemp.js
@@ -0,0 +1,49 @@
+import Core from './core.js'
+
+export default class ragemp extends Core {
+ constructor() {
+ super()
+ this.usedTcp = true
+ }
+
+ async run(state) {
+ const results = await this.request({
+ url: 'https://cdn.rage.mp/master/v2/',
+ responseType: 'json'
+ })
+
+ if (results == null) {
+ throw new Error('Unable to retrieve master server list')
+ }
+
+ const targetID = `${this.options.host}:${this.options.port}`
+
+ let serverResult = null
+ let serverInfo = null
+
+ for (const entry of results) {
+ if (entry.id === targetID) {
+ serverResult = entry
+ serverInfo = entry.servers.at(0)
+ break
+ }
+
+ for (const serverEntry of entry.servers) {
+ if (serverEntry.id === targetID) {
+ serverResult = entry
+ serverInfo = serverEntry
+ break
+ }
+ }
+ }
+
+ if (serverInfo == null) {
+ throw new Error('Server not found in master server list.')
+ }
+
+ state.name = serverInfo.name
+ state.numplayers = serverInfo.players.amount
+ state.maxplayers = serverInfo.players.max
+ state.raw = serverResult
+ }
+}