From 14e8f3e406d4839e9566f9759304aced62e7d4be Mon Sep 17 00:00:00 2001 From: RattleSN4K3 Date: Sat, 28 Sep 2024 18:56:13 +0200 Subject: [PATCH] Add support for Renegade X master query through separate protocol Protocol 'renegadexmaster' provides full list of processed server info --- protocols/index.js | 3 ++- protocols/renegadex.js | 40 +++++++++++++++++++++++++----------- protocols/renegadexmaster.js | 21 +++++++++++++++++++ tools/attempt_protocols.js | 2 +- 4 files changed, 52 insertions(+), 14 deletions(-) create mode 100644 protocols/renegadexmaster.js diff --git a/protocols/index.js b/protocols/index.js index d0b88158..4aac12a1 100644 --- a/protocols/index.js +++ b/protocols/index.js @@ -38,6 +38,7 @@ import quake1 from './quake1.js' import quake2 from './quake2.js' import quake3 from './quake3.js' import renegadex from './renegadex.js' +import renegadexmaster from './renegadexmaster.js' import rfactor from './rfactor.js' import samp from './samp.js' import satisfactory from './satisfactory.js' @@ -70,7 +71,7 @@ import vintagestory from './vintagestory.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, renegadex, rfactor, ragemp, samp, + minecraftbedrock, minecraftvanilla, minetest, mumble, mumbleping, nadeo, openttd, palworld, quake1, quake2, quake3, renegadex, renegadexmaster, rfactor, ragemp, samp, satisfactory, soldat, savage2, starmade, starsiege, teamspeak2, teamspeak3, terraria, toxikk, tribes1, tribes1master, unreal2, ut3, valve, vcmp, ventrilo, warsow, eldewrito, beammpmaster, beammp, dayz, theisleevrima, xonotic, altvmp, vintagestorymaster, vintagestory } diff --git a/protocols/renegadex.js b/protocols/renegadex.js index 530c007d..a0f3e81d 100644 --- a/protocols/renegadex.js +++ b/protocols/renegadex.js @@ -164,14 +164,40 @@ export default class renegadex extends Core { } async run (state) { + // query master list and find specific server + const servers = await this.getMasterServerList() + const serverInfo = servers.find((server) => { + return server.IP === this.options.address && server.Port === this.options.port + }) + + if (serverInfo == null) { + throw new Error('Server not found in master server list') + } + + // set state properties based on received server info + this.populateProperties(state, serverInfo) + } + + /** + * Retrieves server list from master server + * @throws {Error} Will throw error when no master list was received + * @returns a list of servers as raw data + */ + async getMasterServerList () { const servers = await this.request({ url: 'https://serverlist-rx.totemarts.services/servers.jsp', responseType: 'json' }) - if (!servers) { + if (servers == null) { throw new Error('Unable to retrieve master server list') } + if (!Array.isArray(servers)) { + throw new Error('Invalid data received from master server. Expecting list of data') + } + if (servers.length === 0) { + throw new Error('No data received from master server.') + } // TODO: Ajv response validation // const isDataValid = ajv.validate(MasterServerResponseSchema, servers) @@ -179,17 +205,7 @@ export default class renegadex extends Core { // throw new Error(`Received master server data is unknown/invalid: ${ajv.errorsText(ajv.errors)}`) // } - const serverInfo = servers.find( - (server) => - server.IP === this.options.address && server.Port === this.options.port - ) - - if (serverInfo == null) { - throw new Error('Server not found in master server list') - } - - // set state properties based on received server info - this.populateProperties(state, serverInfo) + return servers } /** diff --git a/protocols/renegadexmaster.js b/protocols/renegadexmaster.js new file mode 100644 index 00000000..2499acf1 --- /dev/null +++ b/protocols/renegadexmaster.js @@ -0,0 +1,21 @@ +import renegadex from './renegadex.js' + +/** + * Implements the protocol for retrieving a master list for Renegade X, an UnrealEngine3 based game + */ +export default class renegadexmaster extends renegadex { + async run (state) { + const servers = await this.getMasterServerList() + + // pass processed servers as raw list + state.raw.servers = servers.map((serverInfo) => { + // TODO: may use any other deep-copy method like structuredClone() (in Node.js 17+) + // or use a method of Core to retrieve a clean state + const serverState = JSON.parse(JSON.stringify(state)) + + // set state properties based on received server info + this.populateProperties(serverState, serverInfo) + return serverState + }) + } +} diff --git a/tools/attempt_protocols.js b/tools/attempt_protocols.js index 956a6809..0dec095f 100644 --- a/tools/attempt_protocols.js +++ b/tools/attempt_protocols.js @@ -20,7 +20,7 @@ const gamedig = new GameDig(options) const protocolList = [] Object.keys(protocols).forEach((key) => protocolList.push(key)) -const ignoredProtocols = ['discord', 'beammpmaster', 'beammp', 'teamspeak2', 'teamspeak3', 'vintagestorymaster'] +const ignoredProtocols = ['discord', 'beammpmaster', 'beammp', 'teamspeak2', 'teamspeak3', 'vintagestorymaster', 'renegadexmaster'] const protocolListFiltered = protocolList.filter((protocol) => !ignoredProtocols.includes(protocol)) const run = async () => {