diff --git a/client/src/Hooks/monitorHooks.js b/client/src/Hooks/monitorHooks.js
index 616a37877..4a19f2fa7 100644
--- a/client/src/Hooks/monitorHooks.js
+++ b/client/src/Hooks/monitorHooks.js
@@ -357,7 +357,7 @@ const useUpdateMonitor = () => {
expectedValue: monitor.expectedValue,
ignoreTlsErrors: monitor.ignoreTlsErrors,
jsonPath: monitor.jsonPath,
- ...(monitor.type === "port" && { port: monitor.port }),
+ ...((monitor.type === "port" || monitor.type === "game") && { port: monitor.port }),
...(monitor.type === "hardware" && {
thresholds: monitor.thresholds,
secret: monitor.secret,
diff --git a/client/src/Pages/Uptime/Create/index.jsx b/client/src/Pages/Uptime/Create/index.jsx
index 2d918cb9f..3a1080421 100644
--- a/client/src/Pages/Uptime/Create/index.jsx
+++ b/client/src/Pages/Uptime/Create/index.jsx
@@ -43,6 +43,8 @@ import {
useFetchMonitorById,
} from "../../../Hooks/monitorHooks";
+import { GAMES } from '../../../Utils/games';
+
/**
* Parses a URL string and returns a URL object.
*
@@ -113,6 +115,12 @@ const UptimeCreate = ({ isClone = false }) => {
{ _id: 4, name: t("time.fourMinutes") },
{ _id: 5, name: t("time.fiveMinutes") },
];
+
+ const GAMELIST = Object.entries(GAMES).map(([key, value]) => ({
+ _id: key,
+ name: value.name
+ }));
+
const CRUMBS = [
{ name: "uptime", path: "/uptime" },
...(isCreate
@@ -153,6 +161,11 @@ const UptimeCreate = ({ isClone = false }) => {
placeholder: t("monitorType.port.placeholder"),
namePlaceholder: t("monitorType.port.namePlaceholder"),
},
+ game: {
+ label: t("monitorType.game.label"),
+ placeholder: t("monitorType.game.placeholder"),
+ namePlaceholder: t("monitorType.game.namePlaceholder"),
+ }
};
// Handlers
@@ -169,12 +182,13 @@ const UptimeCreate = ({ isClone = false }) => {
: monitor.url,
name: monitor.name || monitor.url.substring(0, 50),
type: monitor.type,
- port: monitor.type === "port" ? monitor.port : undefined,
+ port: (monitor.type === "port" || monitor.type === "game") ? monitor.port : undefined,
interval: monitor.interval,
matchMethod: monitor.matchMethod,
expectedValue: monitor.expectedValue,
jsonPath: monitor.jsonPath,
ignoreTlsErrors: monitor.ignoreTlsErrors,
+ gameId: monitor.gameId || undefined,
};
} else {
form = {
@@ -188,8 +202,9 @@ const UptimeCreate = ({ isClone = false }) => {
interval: monitor.interval,
teamId: monitor.teamId,
userId: monitor.userId,
- port: monitor.type === "port" ? monitor.port : undefined,
+ port: (monitor.type === "port" || monitor.type === "game") ? monitor.port : undefined,
ignoreTlsErrors: monitor.ignoreTlsErrors,
+ gameId: monitor.gameId || undefined,
};
}
if (!useAdvancedMatching) {
@@ -486,6 +501,15 @@ const UptimeCreate = ({ isClone = false }) => {
checked={monitor.type === "port"}
onChange={onChange}
/>
+
{errors["type"] ? (
{
onChange={onChange}
error={errors["port"] ? true : false}
helperText={errors["port"]}
- hidden={monitor.type !== "port"}
+ hidden={monitor.type !== "port" && monitor.type !== "game"}
/>
+ {
+ monitor.type === "game" &&
+ ()}
[
{ value: "ping", label: "Ping" },
{ value: "docker", label: "Docker" },
{ value: "port", label: "Port" },
+ { value: "game", label: "Game" },
];
// These functions were moved inline to ensure translations are applied correctly
diff --git a/client/src/Pages/Uptime/Monitors/index.jsx b/client/src/Pages/Uptime/Monitors/index.jsx
index 4ebac94d3..607092785 100644
--- a/client/src/Pages/Uptime/Monitors/index.jsx
+++ b/client/src/Pages/Uptime/Monitors/index.jsx
@@ -34,7 +34,7 @@ import {
} from "../../../Hooks/monitorHooks";
import { useTranslation } from "react-i18next";
-const TYPES = ["http", "ping", "docker", "port"];
+const TYPES = ["http", "ping", "docker", "port", "game"];
const CreateMonitorButton = ({ shouldRender }) => {
// Utils
const navigate = useNavigate();
diff --git a/client/src/Utils/games.js b/client/src/Utils/games.js
new file mode 100644
index 000000000..465dca2ce
--- /dev/null
+++ b/client/src/Utils/games.js
@@ -0,0 +1,3450 @@
+export const GAMES = {
+ abioticfactor: {
+ name: 'Abiotic Factor',
+ release_year: 2024,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ actionsource: {
+ name: 'Action: Source',
+ release_year: 2019,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'as'
+ }
+ },
+ ahl: {
+ name: 'Action Half-Life',
+ release_year: 2009,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ aoc: {
+ name: 'Age of Chivalry',
+ release_year: 2007,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'ageofchivalry'
+ }
+ },
+ aoe2: {
+ name: 'Age of Empires 2',
+ release_year: 2009,
+ options: {
+ port_query: 27224,
+ protocol: 'ase'
+ }
+ },
+ alienarena: {
+ name: 'Alien Arena',
+ release_year: 2004,
+ options: {
+ port_query: 27910,
+ protocol: 'quake2'
+ }
+ },
+ alienswarm: {
+ name: 'Alien Swarm',
+ release_year: 2004,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ ase: {
+ name: 'Ark: Survival Evolved',
+ release_year: 2017,
+ options: {
+ port: 7777,
+ port_query: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'arkse'
+ }
+ },
+ asa: {
+ name: 'Ark: Survival Ascended',
+ release_year: 2023,
+ options: {
+ port: 7777,
+ protocol: 'asa'
+ }
+ },
+ assettocorsa: {
+ name: 'Assetto Corsa',
+ release_year: 2014,
+ options: {
+ port: 9610,
+ protocol: 'assettocorsa'
+ }
+ },
+ atlas: {
+ name: 'Atlas',
+ release_year: 2018,
+ options: {
+ port: 5761,
+ port_query_offset: 51800,
+ protocol: 'valve'
+ }
+ },
+ avorion: {
+ name: 'Avorion',
+ release_year: 2020,
+ options: {
+ port: 27000,
+ port_query_offset: 20,
+ protocol: 'valve'
+ }
+ },
+ avp2: {
+ name: 'Aliens versus Predator 2',
+ release_year: 2001,
+ options: {
+ port: 27888,
+ protocol: 'gamespy1'
+ }
+ },
+ avp2010: {
+ name: 'Aliens vs. Predator 2010',
+ release_year: 2010,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ americasarmy: {
+ name: "America's Army",
+ release_year: 2002,
+ options: {
+ port: 1716,
+ port_query_offset: 1,
+ protocol: 'gamespy2'
+ }
+ },
+ americasarmy2: {
+ name: "America's Army 2",
+ release_year: 2003,
+ options: {
+ port: 1716,
+ port_query_offset: 1,
+ protocol: 'gamespy2'
+ }
+ },
+ americasarmy3: {
+ name: "America's Army 3",
+ release_year: 2009,
+ options: {
+ port: 8777,
+ port_query: 27020,
+ protocol: 'valve'
+ }
+ },
+ aapg: {
+ name: "America's Army: Proving Grounds",
+ release_year: 2015,
+ options: {
+ port: 8777,
+ port_query: 27020,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'americasarmypg'
+ }
+ },
+ asr08: {
+ name: "Arca Sim Racing '08",
+ release_year: 2008,
+ options: {
+ port: 34397,
+ port_query_offset: -100,
+ protocol: 'rfactor'
+ },
+ extra: {
+ old_id: 'arcasimracing'
+ }
+ },
+ aaa: {
+ name: 'ARMA: Armed Assault',
+ release_year: 2006,
+ options: {
+ port: 2302,
+ protocol: 'gamespy2'
+ },
+ extra: {
+ old_id: 'arma'
+ }
+ },
+ arma2: {
+ name: 'ARMA 2',
+ release_year: 2009,
+ options: {
+ port: 2302,
+ port_query_offset: 1,
+ protocol: 'valve'
+ }
+ },
+ a2oa: {
+ name: 'ARMA 2: Operation Arrowhead',
+ release_year: 2010,
+ options: {
+ port: 2302,
+ port_query_offset: 1,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'arma2oa'
+ }
+ },
+ acwa: {
+ name: 'ARMA: Cold War Assault',
+ release_year: 2011,
+ options: {
+ port: 2302,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'armacwa'
+ }
+ },
+ armaresistance: {
+ name: 'ARMA: Resistance',
+ release_year: 2011,
+ options: {
+ port: 2302,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'armar'
+ }
+ },
+ arma3: {
+ name: 'ARMA 3',
+ release_year: 2013,
+ options: {
+ port: 2302,
+ port_query_offset: 1,
+ protocol: 'valve'
+ }
+ },
+ armareforger: {
+ name: 'ARMA: Reforger',
+ release_year: 2022,
+ options: {
+ port: 2001,
+ port_query: 17777,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'armare',
+ doc_notes: 'armareforger'
+ }
+ },
+ armagetronadvanced: {
+ name: 'Armagetron Advanced',
+ release_year: 2001,
+ options: {
+ port: 4534,
+ protocol: 'armagetron'
+ },
+ extra: {
+ old_id: 'armagetron'
+ }
+ },
+ baldursgate: {
+ name: "Baldur's Gate",
+ release_year: 1998,
+ options: {
+ port: 6073,
+ port_query: 1470,
+ protocol: 'gamespy1'
+ }
+ },
+ ballisticoverkill: {
+ name: 'Ballistic Overkill',
+ release_year: 2017,
+ options: {
+ port: 27015,
+ port_query_offset: 1,
+ protocol: 'valve'
+ }
+ },
+ barotrauma: {
+ name: 'Barotrauma',
+ release_year: 2019,
+ options: {
+ port: 27015,
+ port_query_offset: 1,
+ protocol: 'valve'
+ }
+ },
+ battalion1944: {
+ name: 'Battalion 1944',
+ release_year: 2018,
+ options: {
+ port: 7777,
+ port_query_offset: 3,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'bat1944'
+ }
+ },
+ beammp: {
+ name: 'BeamMP (2021)',
+ options: {
+ port: 30814,
+ protocol: 'beammp'
+ }
+ },
+ battlefield1942: {
+ name: 'Battlefield 1942',
+ release_year: 2002,
+ options: {
+ port: 14567,
+ port_query: 23000,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'bf1942'
+ }
+ },
+ battlefieldvietnam: {
+ name: 'Battlefield Vietnam',
+ release_year: 2004,
+ options: {
+ port: 15567,
+ port_query: 23000,
+ protocol: 'gamespy2'
+ },
+ extra: {
+ old_id: 'bfv'
+ }
+ },
+ battlefield2: {
+ name: 'Battlefield 2',
+ release_year: 2005,
+ options: {
+ port: 16567,
+ port_query: 29900,
+ protocol: 'gamespy3'
+ },
+ extra: {
+ old_id: 'bf2'
+ }
+ },
+ battlefield2142: {
+ name: 'Battlefield 2142',
+ release_year: 2006,
+ options: {
+ port: 16567,
+ port_query: 29900,
+ protocol: 'gamespy3'
+ },
+ extra: {
+ old_id: 'bf2142'
+ }
+ },
+ bbc2: {
+ name: 'Battlefield: Bad Company 2',
+ release_year: 2010,
+ options: {
+ port: 19567,
+ port_query: 48888,
+ protocol: 'battlefield'
+ },
+ extra: {
+ old_id: 'bfbc2'
+ }
+ },
+ battlefield3: {
+ name: 'Battlefield 3',
+ release_year: 2011,
+ options: {
+ port: 25200,
+ port_query_offset: 22000,
+ protocol: 'battlefield'
+ },
+ extra: {
+ old_id: 'bf3'
+ }
+ },
+ battlefield4: {
+ name: 'Battlefield 4',
+ release_year: 2013,
+ options: {
+ port: 25200,
+ port_query_offset: 22000,
+ protocol: 'battlefield'
+ },
+ extra: {
+ old_id: 'bf4'
+ }
+ },
+ battlefieldhardline: {
+ name: 'Battlefield Hardline',
+ release_year: 2015,
+ options: {
+ port: 25200,
+ port_query_offset: 22000,
+ protocol: 'battlefield'
+ },
+ extra: {
+ old_id: 'bfh'
+ }
+ },
+ blackmesa: {
+ name: 'Black Mesa',
+ release_year: 2020,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ brainbread2: {
+ name: 'BrainBread 2',
+ release_year: 2022,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ brainbread: {
+ name: 'BrainBread',
+ release_year: 2007,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ breach: {
+ name: 'Breach',
+ release_year: 2011,
+ options: {
+ port: 27016,
+ protocol: 'valve'
+ }
+ },
+ breed: {
+ name: 'Breed',
+ release_year: 2004,
+ options: {
+ port: 7649,
+ protocol: 'gamespy2'
+ }
+ },
+ brink: {
+ name: 'Brink',
+ release_year: 2011,
+ options: {
+ port_query_offset: 1,
+ protocol: 'valve'
+ }
+ },
+ brokeprotocol: {
+ name: 'BROKE PROTOCOL',
+ release_year: 2024,
+ options: {
+ protocol: 'brokeprotocol'
+ },
+ extra: {
+ doc_notes: 'brokeprotocol'
+ }
+ },
+ basedefense: {
+ name: 'Base Defense',
+ release_year: 2017,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'bd'
+ }
+ },
+ bladesymphony: {
+ name: 'Blade Symphony',
+ release_year: 2014,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'bs'
+ }
+ },
+ bas: {
+ name: 'Build and Shoot',
+ release_year: 2012,
+ options: {
+ port: 32887,
+ port_query_offset: -1,
+ protocol: 'buildandshoot'
+ },
+ extra: {
+ old_id: 'buildandshoot',
+ doc_notes: 'aosc-buildandshoot'
+ }
+ },
+ aosc: {
+ name: 'Ace of Spades Classic',
+ release_year: 2012,
+ options: {
+ port: 32887,
+ port_query_offset: -1,
+ protocol: 'buildandshoot'
+ },
+ extra: {
+ doc_notes: 'aosc-buildandshoot'
+ }
+ },
+ cod: {
+ name: 'Call of Duty',
+ release_year: 2003,
+ options: {
+ port: 28960,
+ protocol: 'quake3'
+ }
+ },
+ coduo: {
+ name: 'Call of Duty: United Offensive',
+ release_year: 2004,
+ options: {
+ port: 28960,
+ protocol: 'quake3'
+ }
+ },
+ cod2: {
+ name: 'Call of Duty 2',
+ release_year: 2005,
+ options: {
+ port: 28960,
+ protocol: 'quake3'
+ }
+ },
+ cod3: {
+ name: 'Call of Duty 3',
+ release_year: 2006,
+ options: {
+ port: 28960,
+ protocol: 'quake3'
+ }
+ },
+ cod4mw: {
+ name: 'Call of Duty 4: Modern Warfare',
+ release_year: 2007,
+ options: {
+ port: 28960,
+ protocol: 'quake3'
+ },
+ extra: {
+ old_id: 'cod4'
+ }
+ },
+ codbo3: {
+ name: 'Call of Duty: Black Ops 3',
+ release_year: 2015,
+ options: {
+ port: 27017,
+ protocol: 'valve'
+ }
+ },
+ codwaw: {
+ name: 'Call of Duty: World at War',
+ release_year: 2008,
+ options: {
+ port: 28960,
+ protocol: 'quake3'
+ }
+ },
+ codmw2: {
+ name: 'Call of Duty: Modern Warfare 2',
+ release_year: 2009,
+ options: {
+ port: 28960,
+ protocol: 'quake3'
+ }
+ },
+ codmw3: {
+ name: 'Call of Duty: Modern Warfare 3',
+ release_year: 2011,
+ options: {
+ port_query_offset: 2,
+ protocol: 'valve'
+ }
+ },
+ coj: {
+ name: 'Call of Juarez',
+ release_year: 2006,
+ options: {
+ port_query: 26000,
+ protocol: 'ase'
+ },
+ extra: {
+ old_id: 'callofjuarez'
+ }
+ },
+ chaser: {
+ name: 'Chaser',
+ release_year: 2003,
+ options: {
+ port: 3000,
+ port_query_offset: 123,
+ protocol: 'ase'
+ }
+ },
+ cmw: {
+ name: 'Chivalry: Medieval Warfare',
+ release_year: 2012,
+ options: {
+ port: 7777,
+ port_query_offset: 2,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'chivalry'
+ }
+ },
+ chrome: {
+ name: 'Chrome',
+ release_year: 2003,
+ options: {
+ port: 27015,
+ port_query_offset: 123,
+ protocol: 'ase'
+ }
+ },
+ codenamecure: {
+ name: 'Codename CURE',
+ release_year: 2017,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ codenameeagle: {
+ name: 'Codename Eagle',
+ release_year: 2000,
+ options: {
+ port_query: 4711,
+ protocol: 'gamespy1'
+ }
+ },
+ colonysurvival: {
+ name: 'Colony Survival',
+ release_year: 2017,
+ options: {
+ port: 27004,
+ protocol: 'valve'
+ }
+ },
+ c3db: {
+ name: 'Commandos 3: Destination Berlin',
+ release_year: 2003,
+ options: {
+ port_query: 6500,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'commandos3'
+ }
+ },
+ cacr: {
+ name: 'Command and Conquer: Renegade',
+ release_year: 2002,
+ options: {
+ port: 4848,
+ port_query: 25300,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'cacrenegade'
+ }
+ },
+ conanexiles: {
+ name: 'Conan Exiles',
+ release_year: 2018,
+ options: {
+ port: 7777,
+ port_query: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ doc_notes: 'conanexiles'
+ }
+ },
+ contagion: {
+ name: 'Contagion',
+ release_year: 2011,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ contractjack: {
+ name: 'Contract J.A.C.K.',
+ release_year: 2003,
+ options: {
+ port_query: 27888,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'contactjack'
+ }
+ },
+ corekeeper: {
+ name: 'Core Keeper',
+ release_year: 2022,
+ options: {
+ port: 1234,
+ port_query_offset: 1,
+ protocol: 'valve'
+ }
+ },
+ counterstrike15: {
+ name: 'Counter-Strike 1.5',
+ release_year: 2002,
+ options: {
+ port: 27015,
+ protocol: 'goldsrc'
+ },
+ extra: {
+ old_id: 'cs15'
+ }
+ },
+ counterstrike16: {
+ name: 'Counter-Strike 1.6',
+ release_year: 2003,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'cs16'
+ }
+ },
+ c2d: {
+ name: 'CS2D',
+ release_year: 2004,
+ options: {
+ port: 36963,
+ protocol: 'cs2d'
+ },
+ extra: {
+ old_id: 'cs2d'
+ }
+ },
+ cscz: {
+ name: 'Counter-Strike: Condition Zero',
+ release_year: 2004,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ css: {
+ name: 'Counter-Strike: Source',
+ release_year: 2004,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ csgo: {
+ name: 'Counter-Strike: Global Offensive',
+ release_year: 2012,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ doc_notes: 'csgo'
+ }
+ },
+ counterstrike2: {
+ name: 'Counter-Strike 2',
+ release_year: 2023,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'cs2',
+ doc_notes: 'cs2'
+ }
+ },
+ creativerse: {
+ name: 'Creativerse',
+ release_year: 2017,
+ options: {
+ port: 26900,
+ port_query_offset: 1,
+ protocol: 'valve'
+ }
+ },
+ crce: {
+ name: 'Cross Racing Championship Extreme',
+ release_year: 2005,
+ options: {
+ port: 12321,
+ port_query_offset: 123,
+ protocol: 'ase'
+ },
+ extra: {
+ old_id: 'crossracing'
+ }
+ },
+ crysis: {
+ name: 'Crysis',
+ release_year: 2007,
+ options: {
+ port: 64087,
+ protocol: 'gamespy3'
+ }
+ },
+ crysiswars: {
+ name: 'Crysis Wars',
+ release_year: 2008,
+ options: {
+ port: 64100,
+ protocol: 'gamespy3'
+ }
+ },
+ crysis2: {
+ name: 'Crysis 2',
+ release_year: 2011,
+ options: {
+ port: 64000,
+ protocol: 'gamespy3'
+ }
+ },
+ dab: {
+ name: 'Double Action: Boogaloo',
+ release_year: 2014,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ daikatana: {
+ name: 'Daikatana',
+ release_year: 2000,
+ options: {
+ port: 27982,
+ port_query_offset: 10,
+ protocol: 'quake2'
+ }
+ },
+ dmomam: {
+ name: 'Dark Messiah of Might and Magic',
+ release_year: 2006,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ dhe4445: {
+ name: "Darkest Hour: Europe '44-'45",
+ release_year: 2008,
+ options: {
+ port: 7757,
+ port_query_offset: 1,
+ protocol: 'unreal2'
+ },
+ extra: {
+ old_id: 'darkesthour'
+ }
+ },
+ dayofdragons: {
+ name: 'Day of Dragons',
+ release_year: 2019,
+ options: {
+ port: 7777,
+ port_query: 27015,
+ protocol: 'valve'
+ }
+ },
+ dow: {
+ name: 'Days of War',
+ release_year: 2017,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'daysofwar'
+ }
+ },
+ dayz: {
+ name: 'DayZ',
+ release_year: 2018,
+ options: {
+ port: 2302,
+ port_query_offset: 24714,
+ protocol: 'dayz'
+ },
+ extra: {
+ doc_notes: 'dayz'
+ }
+ },
+ dayzmod: {
+ name: 'DayZ Mod',
+ release_year: 2013,
+ options: {
+ port: 2302,
+ port_query_offset: 1,
+ protocol: 'valve'
+ }
+ },
+ ddpt: {
+ name: 'Deadly Dozen: Pacific Theater',
+ release_year: 2002,
+ options: {
+ port_query: 25300,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'deadlydozenpt'
+ }
+ },
+ deerhunter2005: {
+ name: 'Deer Hunter 2005',
+ release_year: 2004,
+ options: {
+ port: 23459,
+ port_query: 34567,
+ protocol: 'gamespy2'
+ },
+ extra: {
+ old_id: 'dh2005'
+ }
+ },
+ descent3: {
+ name: 'Descent 3',
+ release_year: 1999,
+ options: {
+ port: 2092,
+ port_query: 20142,
+ protocol: 'gamespy1'
+ }
+ },
+ deusex: {
+ name: 'Deus Ex',
+ release_year: 2000,
+ options: {
+ port: 7791,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ }
+ },
+ devastation: {
+ name: 'Devastation',
+ release_year: 2003,
+ options: {
+ port: 7777,
+ port_query_offset: 1,
+ protocol: 'unreal2'
+ }
+ },
+ ddd: {
+ name: 'Dino D-Day',
+ release_year: 2011,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'dinodday'
+ }
+ },
+ dtr2: {
+ name: 'Dirt Track Racing 2',
+ release_year: 2002,
+ options: {
+ port: 32240,
+ port_query_offset: -100,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'dirttrackracing2'
+ }
+ },
+ discord: {
+ name: 'Discord',
+ release_year: 2015,
+ options: {
+ protocol: 'discord'
+ },
+ extra: {
+ doc_notes: 'discord'
+ }
+ },
+ deathmatchclassic: {
+ name: 'Deathmatch Classic',
+ release_year: 2001,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'dmc'
+ }
+ },
+ dal: {
+ name: 'Dark and Light',
+ release_year: 2017,
+ options: {
+ port: 7777,
+ port_query: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'dnl'
+ }
+ },
+ dnf2001: {
+ name: 'Duke Nukem Forever 2001',
+ release_year: 2022,
+ options: {
+ port: 7777,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ }
+ },
+ dod: {
+ name: 'Day of Defeat',
+ release_year: 2003,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ dods: {
+ name: 'Day of Defeat: Source',
+ release_year: 2005,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ doi: {
+ name: 'Day of Infamy',
+ release_year: 2017,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ doom3: {
+ name: 'Doom 3',
+ release_year: 2004,
+ options: {
+ port: 27666,
+ protocol: 'doom3'
+ }
+ },
+ dota2: {
+ name: 'Dota 2',
+ release_year: 2013,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ dootf: {
+ name: 'Drakan: Order of the Flame',
+ release_year: 1999,
+ options: {
+ port: 27045,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'drakan'
+ }
+ },
+ dst: {
+ name: "Don't Starve Together",
+ release_year: 2016,
+ options: {
+ port: 10999,
+ port_query: 27016,
+ protocol: 'valve'
+ }
+ },
+ dystopia: {
+ name: 'Dystopia',
+ release_year: 2005,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'dys'
+ }
+ },
+ eco: {
+ name: 'Eco',
+ release_year: 2018,
+ options: {
+ port: 3000,
+ port_query_offset: 1,
+ protocol: 'eco'
+ }
+ },
+ eldewrito: {
+ name: 'Halo Online - ElDewrito',
+ options: {
+ port: 11775,
+ protocol: 'eldewrito'
+ }
+ },
+ empiresmod: {
+ name: 'Empires Mod',
+ release_year: 2008,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'em'
+ }
+ },
+ egs: {
+ name: 'Empyrion - Galactic Survival',
+ release_year: 2015,
+ options: {
+ port: 30000,
+ port_query_offset: 1,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'empyrion'
+ }
+ },
+ enshrouded: {
+ name: 'enshrouded',
+ release_year: 2024,
+ options: {
+ port: 15636,
+ port_query: 15637,
+ protocol: 'valve'
+ }
+ },
+ etqw: {
+ name: 'Enemy Territory: Quake Wars',
+ release_year: 2007,
+ options: {
+ port: 3074,
+ port_query: 27733,
+ protocol: 'doom3'
+ }
+ },
+ ets2: {
+ name: 'Euro Truck Simulator 2',
+ release_year: 2012,
+ options: {
+ port: 27015,
+ port_query_offset: 1,
+ protocol: 'valve'
+ }
+ },
+ exfil: {
+ name: 'Exfil',
+ release_year: 2024,
+ options: {
+ port: 7777,
+ port_query: 27015,
+ protocol: 'valve'
+ }
+ },
+ fear: {
+ name: 'F.E.A.R.',
+ release_year: 2005,
+ options: {
+ port_query: 27888,
+ protocol: 'gamespy2'
+ }
+ },
+ formulaone2002: {
+ name: 'Formula One 2002',
+ release_year: 2002,
+ options: {
+ port_query: 3297,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'f12002'
+ }
+ },
+ f1c9902: {
+ name: "F1 Challenge '99-'02",
+ release_year: 2002,
+ options: {
+ port_query: 34397,
+ protocol: 'gamespy1'
+ }
+ },
+ factorio: {
+ name: 'Factorio',
+ release_year: 2016,
+ options: {
+ port_query: 34197,
+ protocol: 'factorio'
+ }
+ },
+ farcry: {
+ name: 'Far Cry',
+ release_year: 2004,
+ options: {
+ port: 49001,
+ port_query_offset: 123,
+ protocol: 'ase'
+ }
+ },
+ farcry2: {
+ name: 'Far Cry 2',
+ release_year: 2008,
+ options: {
+ port_query: 14001,
+ protocol: 'ase'
+ }
+ },
+ farmingsimulator19: {
+ name: 'Farming Simulator 19',
+ release_year: 2018,
+ options: {
+ port: 8080,
+ protocol: 'farmingsimulator'
+ }
+ },
+ farmingsimulator22: {
+ name: 'Farming Simulator 22',
+ release_year: 2021,
+ options: {
+ port: 8080,
+ protocol: 'farmingsimulator'
+ }
+ },
+ farmingsimulator25: {
+ name: 'Farming Simulator 25',
+ release_year: 2024,
+ options: {
+ port: 8080,
+ protocol: 'farmingsimulator'
+ }
+ },
+ fof: {
+ name: 'Fistful of Frags',
+ release_year: 2014,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ foundry: {
+ name: 'FOUNDRY',
+ release_year: 2024,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ fortressforever: {
+ name: 'Fortress Forever',
+ release_year: 2007,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ ofcwc: {
+ name: 'Operation Flashpoint: Cold War Crisis',
+ release_year: 2001,
+ options: {
+ port: 2302,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ }
+ },
+ ofr: {
+ name: 'Operation Flashpoint: Resistance',
+ release_year: 2002,
+ options: {
+ port: 2302,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'flashpointresistance'
+ }
+ },
+ ffow: {
+ name: 'Frontlines: Fuel of War',
+ release_year: 2008,
+ options: {
+ port: 5476,
+ port_query_offset: 2,
+ protocol: 'ffow'
+ }
+ },
+ gta5f: {
+ name: 'Grand Theft Auto V - FiveM',
+ release_year: 2013,
+ options: {
+ port: 30120,
+ protocol: 'fivem'
+ },
+ extra: {
+ old_id: 'fivem',
+ doc_notes: 'gta5f'
+ }
+ },
+ gta5r: {
+ name: 'Grand Theft Auto V - RageMP',
+ release_year: 2016,
+ options: {
+ port: 22005,
+ protocol: 'ragemp'
+ },
+ extra: {
+ doc_notes: 'gta5r'
+ }
+ },
+ gta5am: {
+ name: 'Grand Theft Auto V - alt:V Multiplayer',
+ release_year: 2015,
+ options: {
+ port: 7788,
+ protocol: 'altvmp'
+ },
+ extra: {
+ doc_notes: 'gta5am',
+ old_id: 'gta5a'
+ }
+ },
+ garrysmod: {
+ name: "Garry's Mod",
+ release_year: 2004,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ tcgraw: {
+ name: "Tom Clancy's Ghost Recon Advanced Warfighter",
+ release_year: 2006,
+ options: {
+ port_query: 15250,
+ protocol: 'gamespy2'
+ },
+ extra: {
+ old_id: 'graw'
+ }
+ },
+ tcgraw2: {
+ name: "Tom Clancy's Ghost Recon Advanced Warfighter 2",
+ release_year: 2007,
+ options: {
+ port_query: 16250,
+ protocol: 'gamespy2'
+ },
+ extra: {
+ old_id: 'graw2'
+ }
+ },
+ gck: {
+ name: 'Giants: Citizen Kabuto',
+ release_year: 2000,
+ options: {
+ port_query: 8911,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'giantscitizenkabuto'
+ }
+ },
+ globaloperations: {
+ name: 'Global Operations',
+ release_year: 2002,
+ options: {
+ port_query: 28672,
+ protocol: 'gamespy1'
+ }
+ },
+ geneshift: {
+ name: 'Geneshift',
+ release_year: 2017,
+ options: {
+ port: 11235,
+ protocol: 'geneshift'
+ }
+ },
+ goldeneyesource: {
+ name: 'GoldenEye: Source',
+ release_year: 2010,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'ges'
+ }
+ },
+ gus: {
+ name: 'Gore: Ultimate Soldier',
+ release_year: 2002,
+ options: {
+ port: 27777,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'gore'
+ }
+ },
+ groundbreach: {
+ name: 'Ground Breach',
+ release_year: 2018,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ gunmanchronicles: {
+ name: 'Gunman Chronicles',
+ release_year: 2000,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ hld: {
+ name: 'Half-Life Deathmatch',
+ release_year: 1998,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'hldm'
+ }
+ },
+ hlds: {
+ name: 'Half-Life Deathmatch: Source',
+ release_year: 2005,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'hldms'
+ }
+ },
+ hlof: {
+ name: 'Half-Life: Opposing Force',
+ release_year: 1999,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'hlopfor'
+ }
+ },
+ hl2d: {
+ name: 'Half-Life 2: Deathmatch',
+ release_year: 2004,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'hl2dm'
+ }
+ },
+ halo: {
+ name: 'Halo',
+ release_year: 2003,
+ options: {
+ port: 2302,
+ protocol: 'gamespy2'
+ }
+ },
+ halo2: {
+ name: 'Halo 2',
+ release_year: 2007,
+ options: {
+ port: 2302,
+ protocol: 'gamespy2'
+ }
+ },
+ hawakening: {
+ name: 'Hawakening',
+ release_year: 2024,
+ options: {
+ port: 7777,
+ port_query: 27015,
+ protocol: 'hawakening'
+ },
+ extra: {
+ doc_notes: 'hawakening'
+ }
+ },
+ heretic2: {
+ name: 'Heretic II',
+ release_year: 1998,
+ options: {
+ port: 27900,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ }
+ },
+ hexen2: {
+ name: 'Hexen II',
+ release_year: 1997,
+ options: {
+ port: 26900,
+ port_query_offset: 50,
+ protocol: 'hexen2'
+ }
+ },
+ thehidden: {
+ name: 'The Hidden',
+ release_year: 2005,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'hidden'
+ }
+ },
+ hll: {
+ name: 'Hell Let Loose',
+ release_year: 2019,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ hiddendangerous2: {
+ name: 'Hidden & Dangerous 2',
+ release_year: 2003,
+ options: {
+ port: 11001,
+ port_query_offset: 3,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'had2'
+ }
+ },
+ homefront: {
+ name: 'Homefront',
+ release_year: 2011,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ homeworld2: {
+ name: 'Homeworld 2',
+ release_year: 2003,
+ options: {
+ port_query: 6500,
+ protocol: 'gamespy1'
+ }
+ },
+ hurtworld: {
+ name: 'Hurtworld',
+ release_year: 2015,
+ options: {
+ port: 12871,
+ port_query: 12881,
+ protocol: 'valve'
+ }
+ },
+ i2cs: {
+ name: 'IGI 2: Covert Strike',
+ release_year: 2003,
+ options: {
+ port_query: 26001,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'igi2'
+ }
+ },
+ i2s: {
+ name: 'IL-2 Sturmovik',
+ release_year: 2001,
+ options: {
+ port_query: 21000,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'il2'
+ }
+ },
+ icarus: {
+ name: 'Icarus',
+ release_year: 2021,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ insurgency: {
+ name: 'Insurgency',
+ release_year: 2014,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ imic: {
+ name: 'Insurgency: Modern Infantry Combat',
+ release_year: 2007,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'insurgencymic'
+ }
+ },
+ insurgencysandstorm: {
+ name: 'Insurgency: Sandstorm',
+ release_year: 2018,
+ options: {
+ port: 27015,
+ port_query_offset: 1,
+ protocol: 'valve'
+ }
+ },
+ ironstorm: {
+ name: 'Iron Storm',
+ release_year: 2002,
+ options: {
+ port_query: 3505,
+ protocol: 'gamespy1'
+ }
+ },
+ theisle: {
+ name: 'The Isle',
+ release_year: 2015,
+ options: {
+ port: 7707,
+ port_query_offset: 1,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'isle'
+ }
+ },
+ tie: {
+ name: 'The Isle Evrima',
+ options: {
+ port: 7777,
+ protocol: 'theisleevrima'
+ },
+ release_year: 2020
+ },
+ jb0n: {
+ name: 'James Bond 007: Nightfire',
+ release_year: 2002,
+ options: {
+ port_query: 6550,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'jamesbondnightfire'
+ }
+ },
+ jc2m: {
+ name: 'Just Cause 2 - Multiplayer',
+ release_year: 2010,
+ options: {
+ port: 7777,
+ protocol: 'jc2mp'
+ },
+ extra: {
+ old_id: 'jc2mp'
+ }
+ },
+ jc3m: {
+ name: 'Just Cause 3 - Multiplayer',
+ release_year: 2017,
+ options: {
+ port: 4200,
+ port_query_offset: 1,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'jc3mp'
+ }
+ },
+ killingfloor: {
+ name: 'Killing Floor',
+ release_year: 2009,
+ options: {
+ port: 7707,
+ port_query_offset: 1,
+ protocol: 'unreal2'
+ }
+ },
+ killingfloor2: {
+ name: 'Killing Floor 2',
+ release_year: 2016,
+ options: {
+ port: 7777,
+ port_query: 27015,
+ protocol: 'valve'
+ }
+ },
+ kloc: {
+ name: 'Kingpin: Life of Crime',
+ release_year: 1999,
+ options: {
+ port: 31510,
+ port_query_offset: -10,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'kingpin'
+ }
+ },
+ kpctnc: {
+ name: 'Kiss: Psycho Circus: The Nightmare Child',
+ release_year: 2000,
+ options: {
+ port: 7777,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'kisspc'
+ }
+ },
+ kspd: {
+ name: 'Kerbal Space Program - DMP',
+ release_year: 2015,
+ options: {
+ port: 6702,
+ port_query_offset: 1,
+ protocol: 'kspdmp'
+ },
+ extra: {
+ old_id: 'kspdmp'
+ }
+ },
+ kreedzclimbing: {
+ name: 'Kreedz Climbing',
+ release_year: 2017,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'kzmod'
+ }
+ },
+ l4d: {
+ name: 'Left 4 Dead',
+ release_year: 2008,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'left4dead'
+ }
+ },
+ l4d2: {
+ name: 'Left 4 Dead 2',
+ release_year: 2009,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'left4dead2'
+ }
+ },
+ m2m: {
+ name: 'Mafia II - Multiplayer',
+ release_year: 2010,
+ options: {
+ port: 27016,
+ port_query_offset: 1,
+ protocol: 'mafia2mp'
+ },
+ extra: {
+ old_id: 'm2mp'
+ }
+ },
+ m2o: {
+ name: 'Mafia II - Online',
+ release_year: 2010,
+ options: {
+ port: 27015,
+ port_query_offset: 1,
+ protocol: 'mafia2online'
+ }
+ },
+ medievalengineers: {
+ name: 'Medieval Engineers',
+ release_year: 2015,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ moe: {
+ name: 'Myth of Empires',
+ release_year: 2024,
+ options: {
+ port_query: 12888,
+ protocol: 'valve'
+ }
+ },
+ mohaa: {
+ name: 'Medal of Honor: Allied Assault',
+ release_year: 2002,
+ options: {
+ port: 12203,
+ port_query_offset: 97,
+ protocol: 'gamespy1'
+ }
+ },
+ mohaas: {
+ name: 'Medal of Honor: Allied Assault Spearhead',
+ release_year: 2002,
+ options: {
+ port: 12203,
+ port_query_offset: 97,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'mohsh'
+ }
+ },
+ mohaab: {
+ name: 'Medal of Honor: Allied Assault Breakthrough',
+ release_year: 2003,
+ options: {
+ port: 12203,
+ port_query_offset: 97,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'mohbt'
+ }
+ },
+ mohpa: {
+ name: 'Medal of Honor: Pacific Assault',
+ release_year: 2004,
+ options: {
+ port: 13203,
+ port_query_offset: 97,
+ protocol: 'gamespy1'
+ }
+ },
+ moha: {
+ name: 'Medal of Honor: Airborne',
+ release_year: 2007,
+ options: {
+ port: 12203,
+ port_query_offset: 97,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'mohab'
+ }
+ },
+ moh: {
+ name: 'Medal of Honor',
+ release_year: 2010,
+ options: {
+ port: 7673,
+ port_query: 48888,
+ protocol: 'battlefield'
+ },
+ extra: {
+ old_id: 'moh2010'
+ }
+ },
+ mohw: {
+ name: 'Medal of Honor: Warfighter',
+ release_year: 2012,
+ options: {
+ port: 25200,
+ port_query_offset: 22000,
+ protocol: 'battlefield'
+ },
+ extra: {
+ old_id: 'mohwf'
+ }
+ },
+ minecraft: {
+ name: 'Minecraft',
+ release_year: 2009,
+ options: {
+ port: 25565,
+ protocol: 'minecraft'
+ },
+ extra: {
+ doc_notes: 'minecraft'
+ }
+ },
+ minetest: {
+ name: 'Minetest',
+ release_year: 2010,
+ options: {
+ port: 30000,
+ protocol: 'minetest'
+ }
+ },
+ mbe: {
+ name: 'Minecraft: Bedrock Edition',
+ release_year: 2011,
+ options: {
+ port: 19132,
+ protocol: 'minecraft'
+ },
+ extra: {
+ old_id: 'minecraftbe'
+ }
+ },
+ mnc: {
+ name: 'Monday Night Combat',
+ release_year: 2011,
+ options: {
+ port: 7777,
+ port_query: 27016,
+ protocol: 'valve'
+ }
+ },
+ mordhau: {
+ name: 'Mordhau',
+ release_year: 2019,
+ options: {
+ port: 7777,
+ port_query: 27015,
+ protocol: 'valve'
+ }
+ },
+ gtavcmta: {
+ name: 'Grand Theft Auto: Vice City - Multi Theft Auto',
+ release_year: 2002,
+ options: {
+ port: 22003,
+ port_query_offset: 123,
+ protocol: 'ase'
+ },
+ extra: {
+ old_id: 'mtavc'
+ }
+ },
+ gtasamta: {
+ name: 'Grand Theft Auto: San Andreas - Multi Theft Auto',
+ release_year: 2004,
+ options: {
+ port: 22003,
+ port_query_offset: 123,
+ protocol: 'ase'
+ },
+ extra: {
+ old_id: 'mtasa'
+ }
+ },
+ mgm: {
+ name: 'Mumble - GT Murmur',
+ release_year: 2005,
+ options: {
+ port: 64738,
+ port_query: 27800,
+ protocol: 'mumble'
+ },
+ extra: {
+ doc_notes: 'mumble'
+ }
+ },
+ mumble: {
+ name: 'Mumble',
+ release_year: 2005,
+ options: {
+ port: 64738,
+ protocol: 'mumbleping'
+ },
+ extra: {
+ doc_notes: 'mumble'
+ }
+ },
+ mutantfactions: {
+ name: 'Mutant Factions',
+ release_year: 2009,
+ options: {
+ port: 11235,
+ protocol: 'geneshift'
+ }
+ },
+ nascarthunder2004: {
+ name: 'NASCAR Thunder 2004',
+ release_year: 2003,
+ options: {
+ port_query: 13333,
+ protocol: 'gamespy2'
+ }
+ },
+ netpanzer: {
+ name: 'netPanzer',
+ release_year: 2002,
+ options: {
+ port: 3030,
+ protocol: 'gamespy1'
+ }
+ },
+ nmrih: {
+ name: 'No More Room in Hell',
+ release_year: 2011,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ naturalselection: {
+ name: 'Natural Selection',
+ release_year: 2002,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'ns'
+ }
+ },
+ naturalselection2: {
+ name: 'Natural Selection 2',
+ release_year: 2012,
+ options: {
+ port_query_offset: 1,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'ns2'
+ }
+ },
+ nfshp2: {
+ name: 'Need for Speed: Hot Pursuit 2',
+ release_year: 2002,
+ options: {
+ port_query: 61220,
+ protocol: 'gamespy1'
+ }
+ },
+ nab: {
+ name: 'Nerf Arena Blast',
+ release_year: 1999,
+ options: {
+ port: 4444,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ }
+ },
+ neverwinternights: {
+ name: 'Neverwinter Nights',
+ release_year: 2002,
+ options: {
+ port_query: 5121,
+ protocol: 'gamespy2'
+ },
+ extra: {
+ old_id: 'nwn'
+ }
+ },
+ neverwinternights2: {
+ name: 'Neverwinter Nights 2',
+ release_year: 2006,
+ options: {
+ port: 5121,
+ port_query: 6500,
+ protocol: 'gamespy2'
+ },
+ extra: {
+ old_id: 'nwn2'
+ }
+ },
+ nexuiz: {
+ name: 'Nexuiz',
+ release_year: 2005,
+ options: {
+ port_query: 26000,
+ protocol: 'quake3'
+ }
+ },
+ nitrofamily: {
+ name: 'Nitro Family',
+ release_year: 2004,
+ options: {
+ port_query: 25601,
+ protocol: 'gamespy1'
+ }
+ },
+ tonolf: {
+ name: 'The Operative: No One Lives Forever',
+ release_year: 2000,
+ options: {
+ port_query: 27888,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'nolf'
+ }
+ },
+ nla: {
+ name: 'Nova-Life: Amboise',
+ release_year: 2020,
+ options: {
+ port_query: 27015,
+ protocol: 'valve'
+ }
+ },
+ nolf2asihw: {
+ name: "No One Lives Forever 2: A Spy in H.A.R.M.'s Way",
+ release_year: 2002,
+ options: {
+ port_query: 27890,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'nolf2'
+ }
+ },
+ nucleardawn: {
+ name: 'Nuclear Dawn',
+ release_year: 2011,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ ohd: {
+ name: 'Operation: Harsh Doorstop',
+ release_year: 2023,
+ options: {
+ port: 7777,
+ port_query: 27005,
+ protocol: 'valve'
+ }
+ },
+ onset: {
+ name: 'Onset',
+ release_year: 2019,
+ options: {
+ port: 7777,
+ port_query_offset: -1,
+ protocol: 'valve'
+ }
+ },
+ openarena: {
+ name: 'OpenArena',
+ release_year: 2005,
+ options: {
+ port_query: 27960,
+ protocol: 'quake3'
+ }
+ },
+ openttd: {
+ name: 'OpenTTD',
+ release_year: 2004,
+ options: {
+ port: 3979,
+ protocol: 'openttd'
+ }
+ },
+ painkiller: {
+ name: 'Painkiller',
+ release_year: 2004,
+ options: {
+ port: 3455,
+ port_query_offset: 123,
+ protocol: 'ase'
+ }
+ },
+ palworld: {
+ name: 'Palworld',
+ release_year: 2024,
+ options: {
+ port: 8212,
+ protocol: 'palworld'
+ },
+ extra: {
+ doc_notes: 'palworld'
+ }
+ },
+ pvak2: {
+ name: 'Pirates, Vikings, and Knights II',
+ release_year: 2007,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'pvkii'
+ }
+ },
+ pixark: {
+ name: 'PixARK',
+ release_year: 2018,
+ options: {
+ port: 7777,
+ port_query: 27015,
+ protocol: 'valve'
+ }
+ },
+ postscriptum: {
+ name: 'Post Scriptum',
+ release_year: 2018,
+ options: {
+ port: 10037,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'ps'
+ }
+ },
+ postal2: {
+ name: 'Postal 2',
+ release_year: 2003,
+ options: {
+ port: 7777,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ }
+ },
+ prey: {
+ name: 'Prey',
+ release_year: 2017,
+ options: {
+ port: 27719,
+ protocol: 'doom3'
+ }
+ },
+ pce: {
+ name: 'Primal Carnage: Extinction',
+ release_year: 2015,
+ options: {
+ port: 7777,
+ port_query: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'primalcarnage'
+ }
+ },
+ projectcars: {
+ name: 'Project Cars',
+ release_year: 2015,
+ options: {
+ port: 27015,
+ port_query_offset: 1,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'pc'
+ }
+ },
+ projectcars2: {
+ name: 'Project Cars 2',
+ release_year: 2017,
+ options: {
+ port: 27015,
+ port_query_offset: 1,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'pc2'
+ }
+ },
+ prb2: {
+ name: 'Project Reality: Battlefield 2',
+ release_year: 2005,
+ options: {
+ port: 16567,
+ port_query: 29900,
+ protocol: 'gamespy3'
+ },
+ extra: {
+ old_id: 'prbf2'
+ }
+ },
+ projectzomboid: {
+ name: 'Project Zomboid',
+ release_year: 2013,
+ options: {
+ port: 16261,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'przomboid'
+ }
+ },
+ quake: {
+ name: 'Quake',
+ release_year: 1996,
+ options: {
+ port: 27500,
+ protocol: 'quake1'
+ },
+ extra: {
+ old_id: 'quake1'
+ }
+ },
+ quake2: {
+ name: 'Quake 2',
+ release_year: 1997,
+ options: {
+ port: 27910,
+ protocol: 'quake2'
+ }
+ },
+ q3a: {
+ name: 'Quake 3: Arena',
+ release_year: 1999,
+ options: {
+ port: 27960,
+ protocol: 'quake3'
+ },
+ extra: {
+ old_id: 'quake3'
+ }
+ },
+ quake4: {
+ name: 'Quake 4',
+ release_year: 2005,
+ options: {
+ port: 28004,
+ protocol: 'doom3'
+ }
+ },
+ quakelive: {
+ name: 'Quake Live',
+ release_year: 2010,
+ options: {
+ port: 27960,
+ protocol: 'valve'
+ }
+ },
+ rdkf: {
+ name: 'Rag Doll Kung Fu',
+ release_year: 2005,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'ragdollkungfu'
+ }
+ },
+ rainbowsix: {
+ name: 'Rainbow Six',
+ release_year: 1998,
+ options: {
+ port_query: 2348,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'r6'
+ }
+ },
+ rs2rs: {
+ name: 'Rainbow Six 2: Rogue Spear',
+ release_year: 1999,
+ options: {
+ port_query: 2346,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'r6roguespear'
+ }
+ },
+ rs3rs: {
+ name: 'Rainbow Six 3: Raven Shield',
+ release_year: 2003,
+ options: {
+ port: 7777,
+ port_query_offset: 1000,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'r6ravenshield'
+ }
+ },
+ rallisportchallenge: {
+ name: 'RalliSport Challenge',
+ release_year: 2002,
+ options: {
+ port_query: 17500,
+ protocol: 'gamespy1'
+ }
+ },
+ rallymasters: {
+ name: 'Rally Masters',
+ release_year: 2000,
+ options: {
+ port_query: 16666,
+ protocol: 'gamespy1'
+ }
+ },
+ redorchestra: {
+ name: 'Red Orchestra',
+ release_year: 2018,
+ options: {
+ port: 7758,
+ port_query_offset: 1,
+ protocol: 'unreal2'
+ }
+ },
+ roo4145: {
+ name: 'Red Orchestra: Ostfront 41-45',
+ release_year: 2006,
+ options: {
+ port: 7757,
+ port_query_offset: 10,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'redorchestraost'
+ }
+ },
+ redorchestra2: {
+ name: 'Red Orchestra 2',
+ release_year: 2011,
+ options: {
+ port: 7777,
+ port_query: 27015,
+ protocol: 'valve'
+ }
+ },
+ redline: {
+ name: 'Redline',
+ release_year: 2010,
+ options: {
+ port_query: 25252,
+ protocol: 'gamespy1'
+ }
+ },
+ renegade10: {
+ name: 'Renegade X',
+ release_year: 2014,
+ options: {
+ protocol: 'renegadex'
+ }
+ },
+ renown: {
+ name: 'Renown',
+ release_year: 2025,
+ options: {
+ protocol: 'renown'
+ }
+ },
+ rdr2r: {
+ name: 'Red Dead Redemption 2 - RedM',
+ release_year: 2018,
+ options: {
+ port: 30120,
+ protocol: 'fivem'
+ },
+ extra: {
+ old_id: 'redm'
+ }
+ },
+ rtcw: {
+ name: 'Return to Castle Wolfenstein',
+ release_year: 2001,
+ options: {
+ port_query: 27960,
+ protocol: 'quake3'
+ }
+ },
+ rfactor: {
+ name: 'rFactor',
+ release_year: 2005,
+ options: {
+ port: 34397,
+ port_query_offset: -100,
+ protocol: 'rfactor'
+ }
+ },
+ rfactor2: {
+ name: 'rFactor 2',
+ release_year: 2013,
+ options: {
+ port_query: 64299,
+ protocol: 'valve'
+ }
+ },
+ ricochet: {
+ name: 'Ricochet',
+ release_year: 2005,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ ron: {
+ name: 'Rise of Nations',
+ release_year: 2003,
+ options: {
+ port_query: 6501,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'riseofnations'
+ }
+ },
+ risingworld: {
+ name: 'Rising World',
+ release_year: 2014,
+ options: {
+ port: 4255,
+ port_query_offset: -1,
+ protocol: 'valve'
+ }
+ },
+ ror2: {
+ name: 'Risk of Rain 2',
+ release_year: 2020,
+ options: {
+ port: 27015,
+ port_query_offset: 1,
+ protocol: 'valve'
+ }
+ },
+ rs2v: {
+ name: 'Rising Storm 2: Vietnam',
+ release_year: 2017,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'rs2'
+ }
+ },
+ rune: {
+ name: 'Rune',
+ release_year: 2000,
+ options: {
+ port: 7777,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ }
+ },
+ rust: {
+ name: 'Rust',
+ release_year: 2013,
+ options: {
+ port: 28015,
+ protocol: 'valve'
+ }
+ },
+ gtasam: {
+ name: 'Grand Theft Auto: San Andreas Multiplayer',
+ release_year: 2006,
+ options: {
+ port: 7777,
+ protocol: 'samp'
+ },
+ extra: {
+ old_id: 'samp'
+ }
+ },
+ gtasao: {
+ name: 'Grand Theft Auto: San Andreas OpenMP',
+ release_year: 2019,
+ options: {
+ port: 7777,
+ protocol: 'gtasao'
+ },
+ extra: {
+ old_id: 'saomp'
+ }
+ },
+ s2ats: {
+ name: 'Savage 2: A Tortured Soul',
+ release_year: 2008,
+ options: {
+ port_query: 11235,
+ protocol: 'savage2'
+ },
+ extra: {
+ old_id: 'savage2'
+ }
+ },
+ sdtd: {
+ name: '7 Days to Die',
+ release_year: 2013,
+ options: {
+ port: 26900,
+ port_query_offset: 1,
+ protocol: 'sdtd'
+ },
+ extra: {
+ old_id: '7d2d',
+ doc_notes: 'sdtd'
+ }
+ },
+ satisfactory: {
+ name: 'Satisfactory',
+ release_year: 2019,
+ options: {
+ port: 7777,
+ protocol: 'satisfactory'
+ },
+ extra: {
+ doc_notes: 'satisfactory'
+ }
+ },
+ spaceengineers: {
+ name: 'Space Engineers',
+ release_year: 2019,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ serioussam: {
+ name: 'Serious Sam',
+ release_year: 2001,
+ options: {
+ port: 25600,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'ss'
+ }
+ },
+ serioussam2: {
+ name: 'Serious Sam 2',
+ release_year: 2005,
+ options: {
+ port: 25600,
+ protocol: 'gamespy2'
+ },
+ extra: {
+ old_id: 'ss2'
+ }
+ },
+ shatteredhorizon: {
+ name: 'Shattered Horizon',
+ release_year: 2009,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ sstse: {
+ name: 'Serious Sam: The Second Encounter',
+ release_year: 2002,
+ options: {
+ port: 25600,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ }
+ },
+ theship: {
+ name: 'The Ship',
+ release_year: 2006,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'ship'
+ }
+ },
+ shogo: {
+ name: 'Shogo',
+ release_year: 1998,
+ options: {
+ port_query: 27888,
+ protocol: 'gamespy1'
+ }
+ },
+ shootmania: {
+ name: 'Shootmania',
+ release_year: 2013,
+ options: {
+ port: 2350,
+ port_query: 5000,
+ protocol: 'nadeo'
+ },
+ extra: {
+ doc_notes: 'nadeo'
+ }
+ },
+ sin: {
+ name: 'SiN',
+ release_year: 1998,
+ options: {
+ port_query: 22450,
+ protocol: 'gamespy1'
+ }
+ },
+ sinepisodes: {
+ name: 'SiN Episodes',
+ release_year: 2006,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'sinep'
+ }
+ },
+ soldat: {
+ name: 'Soldat',
+ release_year: 2002,
+ options: {
+ port: 23073,
+ port_query_offset: 10,
+ protocol: 'soldat'
+ },
+ extra: {
+ doc_notes: 'soldat'
+ }
+ },
+ sof: {
+ name: 'Soldier of Fortune',
+ release_year: 2000,
+ options: {
+ port: 28910,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ }
+ },
+ sof2: {
+ name: 'Soldier of Fortune 2',
+ release_year: 2002,
+ options: {
+ port_query: 20100,
+ protocol: 'quake3'
+ }
+ },
+ sotf: {
+ name: 'Sons Of The Forest',
+ release_year: 2023,
+ options: {
+ port: 8766,
+ port_query: 27016,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'sonsoftheforest'
+ }
+ },
+ soulmask: {
+ name: 'Soulmask',
+ release_year: 2024,
+ options: {
+ port: 8777,
+ port_query: 27015,
+ protocol: 'valve'
+ }
+ },
+ ssl: {
+ name: 'SCP: Secret Labratory',
+ release_year: 2020,
+ options: {
+ protocol: 'scpsl'
+ },
+ extra: {
+ doc_notes: 'ssl'
+ }
+ },
+ stalker: {
+ name: 'S.T.A.L.K.E.R.',
+ release_year: 2007,
+ options: {
+ port: 5445,
+ port_query_offset: 2,
+ protocol: 'gamespy3'
+ }
+ },
+ stn: {
+ name: 'Survive the Nights',
+ release_year: 2017,
+ options: {
+ port: 7950,
+ port_query_offset: 1,
+ protocol: 'valve'
+ }
+ },
+ stbc: {
+ name: 'Star Trek: Bridge Commander',
+ release_year: 2002,
+ options: {
+ port_query: 22101,
+ protocol: 'gamespy1'
+ }
+ },
+ stvef: {
+ name: 'Star Trek: Voyager - Elite Force',
+ release_year: 2000,
+ options: {
+ port_query: 27960,
+ protocol: 'quake3'
+ }
+ },
+ stvef2: {
+ name: 'Star Trek: Voyager - Elite Force 2',
+ release_year: 2003,
+ options: {
+ port_query: 29253,
+ protocol: 'quake3'
+ }
+ },
+ squad: {
+ name: 'Squad',
+ release_year: 2020,
+ options: {
+ port: 7787,
+ port_query: 27165,
+ protocol: 'valve'
+ }
+ },
+ swb: {
+ name: 'Star Wars: Battlefront',
+ release_year: 2004,
+ options: {
+ port_query: 3658,
+ protocol: 'gamespy2'
+ },
+ extra: {
+ old_id: 'swbf'
+ }
+ },
+ swb2: {
+ name: 'Star Wars: Battlefront 2',
+ release_year: 2005,
+ options: {
+ port_query: 3658,
+ protocol: 'gamespy2'
+ },
+ extra: {
+ old_id: 'swbf2'
+ }
+ },
+ swjkja: {
+ name: 'Star Wars Jedi Knight: Jedi Academy',
+ release_year: 2003,
+ options: {
+ port_query: 29070,
+ protocol: 'quake3'
+ },
+ extra: {
+ old_id: 'swjk'
+ }
+ },
+ swjk2jo: {
+ name: 'Star Wars Jedi Knight II: Jedi Outcast',
+ release_year: 2002,
+ options: {
+ port_query: 28070,
+ protocol: 'quake3'
+ },
+ extra: {
+ old_id: 'swjk2'
+ }
+ },
+ swrc: {
+ name: 'Star Wars: Republic Commando',
+ release_year: 2005,
+ options: {
+ port: 7777,
+ port_query: 11138,
+ protocol: 'gamespy2'
+ }
+ },
+ starbound: {
+ name: 'Starbound',
+ release_year: 2016,
+ options: {
+ port: 21025,
+ protocol: 'valve'
+ }
+ },
+ starmade: {
+ name: 'StarMade',
+ release_year: 2012,
+ options: {
+ port: 4242,
+ protocol: 'starmade'
+ }
+ },
+ starsiege: {
+ name: 'Starsiege',
+ release_year: 2009,
+ options: {
+ port: 29001,
+ protocol: 'starsiege'
+ }
+ },
+ suicidesurvival: {
+ name: 'Suicide Survival',
+ release_year: 2008,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ swat4: {
+ name: 'SWAT 4',
+ release_year: 2005,
+ options: {
+ port: 10480,
+ port_query_offset: 2,
+ protocol: 'gamespy2'
+ }
+ },
+ svencoop: {
+ name: 'Sven Coop',
+ release_year: 1999,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ synergy: {
+ name: 'Synergy',
+ release_year: 2005,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ tacticalops: {
+ name: 'Tactical Ops',
+ release_year: 1999,
+ options: {
+ port: 7777,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ }
+ },
+ toh: {
+ name: 'Take On Helicopters',
+ release_year: 2011,
+ options: {
+ port: 2302,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'takeonhelicopters'
+ }
+ },
+ teamfactor: {
+ name: 'Team Factor',
+ release_year: 2002,
+ options: {
+ port_query: 57778,
+ protocol: 'gamespy1'
+ }
+ },
+ tfc: {
+ name: 'Team Fortress Classic',
+ release_year: 1999,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ teamfortress2: {
+ name: 'Team Fortress 2',
+ release_year: 2007,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'tf2'
+ }
+ },
+ teamspeak2: {
+ name: 'Teamspeak 2',
+ release_year: 2001,
+ options: {
+ port: 8767,
+ protocol: 'teamspeak2'
+ }
+ },
+ teamspeak3: {
+ name: 'Teamspeak 3',
+ release_year: 2011,
+ options: {
+ port: 9987,
+ protocol: 'teamspeak3'
+ },
+ extra: {
+ doc_notes: 'teamspeak3'
+ }
+ },
+ terminus: {
+ name: 'Terminus',
+ release_year: 2000,
+ options: {
+ port_query: 12286,
+ protocol: 'gamespy1'
+ }
+ },
+ terrariatshock: {
+ name: 'Terraria - TShock',
+ release_year: 2011,
+ options: {
+ port: 7777,
+ port_query_offset: 101,
+ protocol: 'terraria'
+ },
+ extra: {
+ old_id: 'terraria',
+ doc_notes: 'terraria'
+ }
+ },
+ theforest: {
+ name: 'The Forest',
+ release_year: 2014,
+ options: {
+ port: 27015,
+ port_query_offset: 1,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'forrest'
+ }
+ },
+ thefront: {
+ name: 'The Front',
+ release_year: 2023,
+ options: {
+ port_query: 27015,
+ protocol: 'valve'
+ }
+ },
+ thps3: {
+ name: "Tony Hawk's Pro Skater 3",
+ release_year: 2001,
+ options: {
+ port_query: 6500,
+ protocol: 'gamespy1'
+ }
+ },
+ thps4: {
+ name: "Tony Hawk's Pro Skater 4",
+ release_year: 2002,
+ options: {
+ port_query: 6500,
+ protocol: 'gamespy1'
+ }
+ },
+ thu2: {
+ name: "Tony Hawk's Underground 2",
+ release_year: 2004,
+ options: {
+ port_query: 5153,
+ protocol: 'gamespy1'
+ }
+ },
+ towerunite: {
+ name: 'Tower Unite',
+ release_year: 2016,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ trackmania2: {
+ name: 'Trackmania 2',
+ release_year: 2011,
+ options: {
+ port: 2350,
+ port_query: 5000,
+ protocol: 'nadeo'
+ },
+ extra: {
+ doc_notes: 'nadeo'
+ }
+ },
+ trackmaniaforever: {
+ name: 'Trackmania Forever',
+ release_year: 2008,
+ options: {
+ port: 2350,
+ port_query: 5000,
+ protocol: 'nadeo'
+ },
+ extra: {
+ doc_notes: 'nadeo'
+ }
+ },
+ tremulous: {
+ name: 'Tremulous',
+ release_year: 2006,
+ options: {
+ port_query: 30720,
+ protocol: 'quake3'
+ }
+ },
+ t1s: {
+ name: 'Tribes 1: Starsiege',
+ release_year: 1998,
+ options: {
+ port: 28001,
+ protocol: 'tribes1'
+ },
+ extra: {
+ old_id: 'tribes1'
+ }
+ },
+ tribesvengeance: {
+ name: 'Tribes: Vengeance',
+ release_year: 2004,
+ options: {
+ port: 7777,
+ port_query_offset: 1,
+ protocol: 'gamespy2'
+ }
+ },
+ tron20: {
+ name: 'Tron 2.0',
+ release_year: 2003,
+ options: {
+ port_query: 27888,
+ protocol: 'gamespy2'
+ }
+ },
+ thespecialists: {
+ name: 'The Specialists',
+ release_year: 2002,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ toxikk: {
+ name: 'TOXIKK',
+ release_year: 2016,
+ options: {
+ port: 7777,
+ port_query: 27015,
+ protocol: 'toxikk'
+ }
+ },
+ turok2: {
+ name: 'Turok 2',
+ release_year: 1998,
+ options: {
+ port_query: 12880,
+ protocol: 'gamespy1'
+ }
+ },
+ u2tax: {
+ name: 'Unreal 2: The Awakening - XMP',
+ release_year: 2003,
+ options: {
+ port: 7777,
+ port_query_offset: 1,
+ protocol: 'unreal2'
+ }
+ },
+ universalcombat: {
+ name: 'Universal Combat',
+ release_year: 2004,
+ options: {
+ port: 1135,
+ port_query_offset: 123,
+ protocol: 'ase'
+ }
+ },
+ unreal: {
+ name: 'Unreal',
+ release_year: 1998,
+ options: {
+ port: 7777,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ }
+ },
+ unturned: {
+ name: 'unturned',
+ release_year: 2014,
+ options: {
+ port: 27015,
+ port_query_offset: 1,
+ protocol: 'valve'
+ }
+ },
+ unrealtournament: {
+ name: 'Unreal Tournament',
+ release_year: 1993,
+ options: {
+ port: 7777,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'ut'
+ }
+ },
+ unrealtournament2003: {
+ name: 'Unreal Tournament 2003',
+ release_year: 2003,
+ options: {
+ port: 7757,
+ port_query_offset: 1,
+ protocol: 'unreal2'
+ },
+ extra: {
+ old_id: 'ut2003'
+ }
+ },
+ unrealtournament2004: {
+ name: 'Unreal Tournament 2004',
+ release_year: 2004,
+ options: {
+ port: 7777,
+ port_query_offset: 1,
+ protocol: 'unreal2'
+ },
+ extra: {
+ old_id: 'ut2004'
+ }
+ },
+ unrealtournament3: {
+ name: 'Unreal Tournament 3',
+ release_year: 2007,
+ options: {
+ port: 7777,
+ port_query_offset: -1277,
+ protocol: 'ut3'
+ },
+ extra: {
+ old_id: 'ut3'
+ }
+ },
+ urbanterror: {
+ name: 'Urban Terror',
+ release_year: 2000,
+ options: {
+ port_query: 27960,
+ protocol: 'quake3'
+ }
+ },
+ v8sc: {
+ name: 'V8 Supercar Challenge',
+ release_year: 2002,
+ options: {
+ port_query: 16700,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'v8supercar'
+ }
+ },
+ valheim: {
+ name: 'Valheim',
+ release_year: 2021,
+ options: {
+ port: 2456,
+ port_query_offset: 1,
+ protocol: 'valve'
+ },
+ extra: {
+ doc_notes: 'valheim'
+ }
+ },
+ vcm: {
+ name: 'Vice City Multiplayer',
+ release_year: 2015,
+ options: {
+ port: 8192,
+ protocol: 'vcmp'
+ },
+ extra: {
+ old_id: 'vcmp'
+ }
+ },
+ ventrilo: {
+ name: 'Ventrilo',
+ release_year: 2002,
+ options: {
+ port: 3784,
+ protocol: 'ventrilo'
+ }
+ },
+ vietcong: {
+ name: 'Vietcong',
+ release_year: 2003,
+ options: {
+ port: 5425,
+ port_query: 15425,
+ protocol: 'gamespy1'
+ }
+ },
+ vietcong2: {
+ name: 'Vietcong 2',
+ release_year: 2005,
+ options: {
+ port: 5001,
+ port_query: 19967,
+ protocol: 'gamespy2'
+ }
+ },
+ vrising: {
+ name: 'V Rising',
+ release_year: 2022,
+ options: {
+ port: 27015,
+ port_query_offset: [1, 15],
+ protocol: 'valve'
+ }
+ },
+ vampireslayer: {
+ name: 'Vampire Slayer',
+ release_year: 2000,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'vs'
+ }
+ },
+ vintagestory: {
+ name: 'Vintage Story',
+ release_year: 2016,
+ options: {
+ port: 42420,
+ protocol: 'vintagestory'
+ }
+ },
+ warsow: {
+ name: 'Warsow',
+ release_year: 2012,
+ options: {
+ port: 44400,
+ protocol: 'warsow'
+ }
+ },
+ warfork: {
+ name: 'Warfork',
+ release_year: 2019,
+ options: {
+ port_query: 44400,
+ protocol: 'warsow'
+ }
+ },
+ wot: {
+ name: 'Wheel of Time',
+ release_year: 1999,
+ options: {
+ port: 7777,
+ port_query_offset: 1,
+ protocol: 'gamespy1'
+ },
+ extra: {
+ old_id: 'wheeloftime'
+ }
+ },
+ wolfenstein: {
+ name: 'Wolfenstein',
+ release_year: 2009,
+ options: {
+ port: 27666,
+ protocol: 'doom3'
+ },
+ extra: {
+ old_id: 'wolfenstein2009'
+ }
+ },
+ wet: {
+ name: 'Wolfenstein: Enemy Territory',
+ release_year: 2003,
+ options: {
+ port_query: 27960,
+ protocol: 'quake3'
+ },
+ extra: {
+ old_id: 'wolfensteinet'
+ }
+ },
+ wurmunlimited: {
+ name: 'Wurm Unlimited',
+ release_year: 2006,
+ options: {
+ port: 3724,
+ port_query: 27016,
+ protocol: 'valve'
+ },
+ extra: {
+ old_id: 'wurm'
+ }
+ },
+ xonotic: {
+ name: 'Xonotic',
+ release_year: 2011,
+ options: {
+ port: 26000,
+ protocol: 'xonotic'
+ }
+ },
+ wop: {
+ name: 'World Of Padman',
+ release_year: 2007,
+ options: {
+ port: 26000,
+ protocol: 'quake3'
+ }
+ },
+ xpandrally: {
+ name: 'Xpand Rally',
+ release_year: 2004,
+ options: {
+ port: 28015,
+ port_query_offset: 123,
+ protocol: 'ase'
+ }
+ },
+ zombiemaster: {
+ name: 'Zombie Master',
+ release_year: 2007,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ },
+ zps: {
+ name: 'Zombie Panic: Source',
+ release_year: 2007,
+ options: {
+ port: 27015,
+ protocol: 'valve'
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/src/Validation/validation.js b/client/src/Validation/validation.js
index 9c6699d4b..6282bc12b 100644
--- a/client/src/Validation/validation.js
+++ b/client/src/Validation/validation.js
@@ -205,6 +205,7 @@ const monitorValidation = joi.object({
expectedValue: joi.string().allow(null, ""),
jsonPath: joi.string().allow(null, ""),
matchMethod: joi.string().allow(null, ""),
+ gameId: joi.string().allow(null, "")
});
const imageValidation = joi.object({
diff --git a/client/src/locales/ar.json b/client/src/locales/ar.json
index 7188c3711..33f245fd5 100644
--- a/client/src/locales/ar.json
+++ b/client/src/locales/ar.json
@@ -260,6 +260,7 @@
"notifyEmails": "",
"seperateEmails": "",
"checkFrequency": "",
+ "chooseGame": "",
"matchMethod": "",
"expectedValue": "",
"deleteDialogTitle": "",
@@ -437,7 +438,8 @@
"http": "",
"ping": "",
"docker": "",
- "port": ""
+ "port": "",
+ "game": ""
},
"common": {
"appName": "",
diff --git a/client/src/locales/cs.json b/client/src/locales/cs.json
index 00c513203..1fb579270 100644
--- a/client/src/locales/cs.json
+++ b/client/src/locales/cs.json
@@ -260,6 +260,7 @@
"notifyEmails": "",
"seperateEmails": "",
"checkFrequency": "",
+ "chooseGame": "",
"matchMethod": "",
"expectedValue": "",
"deleteDialogTitle": "",
@@ -437,7 +438,8 @@
"http": "",
"ping": "",
"docker": "",
- "port": ""
+ "port": "",
+ "game": ""
},
"common": {
"appName": "Checkmate",
diff --git a/client/src/locales/de.json b/client/src/locales/de.json
index aa416bd95..4ac77ef29 100644
--- a/client/src/locales/de.json
+++ b/client/src/locales/de.json
@@ -260,6 +260,7 @@
"notifyEmails": "Benachrichtige auch per E-Mail an mehrere Adressen (kommt bald)",
"seperateEmails": "Du kannst mehrere E-Mails mit einem Komma trennen",
"checkFrequency": "Überprüfungsfrequenz",
+ "chooseGame": "",
"matchMethod": "",
"expectedValue": "Erwarteter Wert",
"deleteDialogTitle": "Möchtest du diesen Monitor wirklich löschen?",
@@ -437,7 +438,8 @@
"http": "",
"ping": "",
"docker": "",
- "port": ""
+ "port": "",
+ "game": ""
},
"common": {
"appName": "Checkmate",
diff --git a/client/src/locales/en.json b/client/src/locales/en.json
index 97aa761d1..a9a81b773 100644
--- a/client/src/locales/en.json
+++ b/client/src/locales/en.json
@@ -216,6 +216,7 @@
"cancel": "Cancel",
"checkFormError": "Please check the form for errors.",
"checkFrequency": "Check frequency",
+ "chooseGame": "Choose game",
"checkHooks": {
"failureResolveAll": "Failed to resolve all incidents.",
"failureResolveMonitor": "Failed to resolve monitor incidents.",
@@ -627,6 +628,11 @@
"label": "URL to monitor",
"namePlaceholder": "Localhost:5173",
"placeholder": "localhost"
+ },
+ "game": {
+ "label": "URL to monitor",
+ "namePlaceholder": "localhost:5173",
+ "placeholder": "localhost"
}
},
"ms": "ms",
@@ -748,6 +754,8 @@
"pingMonitoringDescription": "Check whether your server is available or not.",
"portMonitoring": "Port monitoring",
"portMonitoringDescription": "Check whether your port is open or not.",
+ "gameServerMonitoring": "Game Server Monitoring",
+ "gameServerMonitoringDescription": "Check whether your game server is running or not",
"portToMonitor": "Port to monitor",
"publicLink": "Public link",
"publicURL": "Public URL",
@@ -1008,7 +1016,8 @@
"docker": "Enter the Docker ID of your container. Docker IDs must be the full 64 char Docker ID. You can run docker inspect to get the full container ID.",
"http": "Enter the URL or IP to monitor (e.g., https://example.com/ or 192.168.1.100) and add a clear display name that appears on the dashboard.",
"ping": "Enter the IP address or hostname to ping (e.g., 192.168.1.100 or example.com) and add a clear display name that appears on the dashboard.",
- "port": "Enter the URL or IP of the server, the port number and a clear display name that appears on the dashboard."
+ "port": "Enter the URL or IP of the server, the port number and a clear display name that appears on the dashboard.",
+ "game": "Enter the IP address or hostname and the port number to ping (e.g., 192.168.1.100 or example.com) and choose game type."
},
"uptimeMonitor": {
"fallback": {
diff --git a/client/src/locales/es.json b/client/src/locales/es.json
index 6ecebadf5..1e2ee3b6c 100644
--- a/client/src/locales/es.json
+++ b/client/src/locales/es.json
@@ -260,6 +260,7 @@
"notifyEmails": "",
"seperateEmails": "",
"checkFrequency": "",
+ "chooseGame": "",
"matchMethod": "",
"expectedValue": "",
"deleteDialogTitle": "",
@@ -437,7 +438,8 @@
"http": "",
"ping": "",
"docker": "",
- "port": ""
+ "port": "",
+ "game": ""
},
"common": {
"appName": "",
diff --git a/client/src/locales/fi.json b/client/src/locales/fi.json
index 2198e2798..cce87a89f 100644
--- a/client/src/locales/fi.json
+++ b/client/src/locales/fi.json
@@ -260,6 +260,7 @@
"notifyEmails": "",
"seperateEmails": "",
"checkFrequency": "",
+ "chooseGame": "",
"matchMethod": "",
"expectedValue": "",
"deleteDialogTitle": "",
@@ -437,7 +438,8 @@
"http": "",
"ping": "",
"docker": "",
- "port": ""
+ "port": "",
+ "game": ""
},
"common": {
"appName": "",
diff --git a/client/src/locales/fr.json b/client/src/locales/fr.json
index c6e263c4d..52d5d8c7e 100644
--- a/client/src/locales/fr.json
+++ b/client/src/locales/fr.json
@@ -264,6 +264,7 @@
"notifyEmails": "Envoyer également une notification par email à plusieurs adresses (bientôt).",
"seperateEmails": "Vous pouvez ajouter plusieurs adresses emails en les séparant par une virgule",
"checkFrequency": "Vérifier la fréquence",
+ "chooseGame": "",
"matchMethod": "Méthode de rapprochement",
"expectedValue": "Valeur attendue",
"deleteDialogTitle": "Voulez-vous vraiment supprimer ce moniteur ?",
@@ -441,7 +442,8 @@
"http": "Entrez l'URL ou l'IP du moniteur (par exemple https://exemple.fr ou 192.168.1.100) et ajoutez un nom familier qui apparaîtra sur le tableau de bord.",
"ping": "Entrez l'adresse IP ou le nom d'hôte à tester (par exemple, 192.168.1.100 ou exemple.fr) et ajoutez un nom familier qui apparaîtra sur le tableau de bord.",
"docker": "Entrer l'ID Docker du container. Les identifiants Docker doivent être les 64 caractères de l'ID Docker. Vous pouvez utiliser la commande docker inspect pour avoir l'ID complet.",
- "port": "Entrez l'URL ou l'adresse IP du serveur, le numéro de port et un nom d'affichage familier qui apparaîtra sur le tableau de bord."
+ "port": "Entrez l'URL ou l'adresse IP du serveur, le numéro de port et un nom d'affichage familier qui apparaîtra sur le tableau de bord.",
+ "game": ""
},
"common": {
"appName": "Checkmate",
diff --git a/client/src/locales/ja.json b/client/src/locales/ja.json
index 782fdd9e0..80245d64b 100644
--- a/client/src/locales/ja.json
+++ b/client/src/locales/ja.json
@@ -264,6 +264,7 @@
"notifyEmails": "複数のアドレスにメールでも通知(近日公開)",
"seperateEmails": "複数のメールはカンマで区切ることができます",
"checkFrequency": "チェック頻度",
+ "chooseGame": "",
"matchMethod": "マッチ方法",
"expectedValue": "期待値",
"deleteDialogTitle": "本当にこのモニターを削除しますか?",
@@ -441,7 +442,8 @@
"http": "監視するURLまたはIPを入力(例: https://example.com/ または 192.168.1.100)し、ダッシュボードに表示される明確な表示名を追加。",
"ping": "pingするIPアドレスまたはホスト名を入力(例: 192.168.1.100 または example.com)し、ダッシュボードに表示される明確な表示名を追加。",
"docker": "コンテナのDocker IDを入力。Docker IDは64文字のフルDocker IDである必要があります。docker inspect を実行してフルコンテナIDを取得できます。",
- "port": "サーバーのURLまたはIP、ポート番号、ダッシュボードに表示される明確な表示名を入力。"
+ "port": "サーバーのURLまたはIP、ポート番号、ダッシュボードに表示される明確な表示名を入力。",
+ "game": ""
},
"common": {
"appName": "Checkmate",
diff --git a/client/src/locales/pt-BR.json b/client/src/locales/pt-BR.json
index 2315a723d..4b4bd04a9 100644
--- a/client/src/locales/pt-BR.json
+++ b/client/src/locales/pt-BR.json
@@ -260,6 +260,7 @@
"notifyEmails": "Também notificar por e-mail para vários endereços (em breve)",
"seperateEmails": "Você pode separar vários e-mails com uma vírgula",
"checkFrequency": "Verifique a frequência",
+ "chooseGame": "",
"matchMethod": "Método de correspondência",
"expectedValue": "Valor esperado",
"deleteDialogTitle": "Você realmente deseja excluir este monitor?",
@@ -437,7 +438,8 @@
"http": "Insira a URL ou IP para monitorar (ex. https://exemplo.com.br/ ou 192.168.1.100) e adicione uma descrição que aparecerá na dashboard.",
"ping": "Insira o endereço IP ou nome de domínio para ping (ex. 192.168.1.100 ou exemplo.com.br) e adicione uma descrição que aparecerá na dashboard.",
"docker": "Insira o Docker Id do seu container. Docker Ids devem ser todos os 64 caracteres. Você pode executar docker inspect para descobrir o Id completo.",
- "port": "Insira a URL ou o IP do servidor, aporta e uma descrição que aparecerá na dashboard."
+ "port": "Insira a URL ou o IP do servidor, aporta e uma descrição que aparecerá na dashboard.",
+ "game": ""
},
"common": {
"appName": "Checkmate",
diff --git a/client/src/locales/ru.json b/client/src/locales/ru.json
index 814e94da1..25e1038aa 100644
--- a/client/src/locales/ru.json
+++ b/client/src/locales/ru.json
@@ -260,6 +260,7 @@
"notifyEmails": "Также уведомлять по электронной почте на несколько адресов (скоро)",
"seperateEmails": "Вы можете разделить несколько адресов электронной почты запятой.",
"checkFrequency": "Проверить частоту",
+ "chooseGame": "",
"matchMethod": "Метод сопоставления",
"expectedValue": "Ожидаемое значение",
"deleteDialogTitle": "Вы действительно хотите удалить этот монитор?",
@@ -437,7 +438,8 @@
"http": "",
"ping": "",
"docker": "",
- "port": ""
+ "port": "",
+ "game": ""
},
"common": {
"appName": "",
diff --git a/client/src/locales/tr.json b/client/src/locales/tr.json
index e9e2d4e29..9e20242fb 100644
--- a/client/src/locales/tr.json
+++ b/client/src/locales/tr.json
@@ -260,6 +260,7 @@
"notifyEmails": "Ayrıca birden fazla eposta adresine bildirim gönderebilirsiniz (yakında geliyor)",
"seperateEmails": "Birden fazla epostayı virgülle ayırabilirsiniz",
"checkFrequency": "Frekansı denetle",
+ "chooseGame": "Oyun seç",
"matchMethod": "Eşleşme yöntemi",
"expectedValue": "Beklenen değer",
"deleteDialogTitle": "Gerçekten bu monitörü silmek istiyor musunuz?",
@@ -437,7 +438,8 @@
"http": "",
"ping": "",
"docker": "",
- "port": ""
+ "port": "",
+ "game": ""
},
"common": {
"appName": "Checkmate",
diff --git a/client/src/locales/uk.json b/client/src/locales/uk.json
index b3b8fc4ce..22b96487c 100644
--- a/client/src/locales/uk.json
+++ b/client/src/locales/uk.json
@@ -260,6 +260,7 @@
"notifyEmails": "",
"seperateEmails": "",
"checkFrequency": "",
+ "chooseGame": "",
"matchMethod": "",
"expectedValue": "",
"deleteDialogTitle": "",
@@ -435,7 +436,8 @@
"http": "",
"ping": "",
"docker": "",
- "port": ""
+ "port": "",
+ "game": ""
},
"common": {
"appName": "",
diff --git a/client/src/locales/vi.json b/client/src/locales/vi.json
index b3b8fc4ce..22b96487c 100644
--- a/client/src/locales/vi.json
+++ b/client/src/locales/vi.json
@@ -260,6 +260,7 @@
"notifyEmails": "",
"seperateEmails": "",
"checkFrequency": "",
+ "chooseGame": "",
"matchMethod": "",
"expectedValue": "",
"deleteDialogTitle": "",
@@ -435,7 +436,8 @@
"http": "",
"ping": "",
"docker": "",
- "port": ""
+ "port": "",
+ "game": ""
},
"common": {
"appName": "",
diff --git a/client/src/locales/zh-TW.json b/client/src/locales/zh-TW.json
index 56f1841d4..90a1aa30c 100644
--- a/client/src/locales/zh-TW.json
+++ b/client/src/locales/zh-TW.json
@@ -260,6 +260,7 @@
"notifyEmails": "",
"seperateEmails": "",
"checkFrequency": "",
+ "chooseGame": "",
"matchMethod": "",
"expectedValue": "",
"deleteDialogTitle": "",
@@ -437,7 +438,8 @@
"http": "",
"ping": "",
"docker": "",
- "port": ""
+ "port": "",
+ "game": ""
},
"common": {
"appName": "",
diff --git a/server/package-lock.json b/server/package-lock.json
index a41a50518..b29fb0642 100644
--- a/server/package-lock.json
+++ b/server/package-lock.json
@@ -19,6 +19,7 @@
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express-rate-limit": "8.0.1",
+ "gamedig": "^5.3.1",
"handlebars": "^4.7.8",
"helmet": "^8.0.0",
"ioredis": "^5.4.2",
@@ -1031,6 +1032,18 @@
"integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==",
"license": "BSD-3-Clause"
},
+ "node_modules/@sindresorhus/is": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz",
+ "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/is?sponsor=1"
+ }
+ },
"node_modules/@sinonjs/commons": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
@@ -1080,15 +1093,16 @@
"dev": true,
"license": "(Unlicense OR Apache-2.0)"
},
- "node_modules/@trysound/sax": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
- "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==",
- "license": "ISC",
- "optional": true,
- "peer": true,
+ "node_modules/@szmarczak/http-timer": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz",
+ "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==",
+ "license": "MIT",
+ "dependencies": {
+ "defer-to-connect": "^2.0.1"
+ },
"engines": {
- "node": ">=10.13.0"
+ "node": ">=14.16"
}
},
"node_modules/@types/estree": {
@@ -1098,6 +1112,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/http-cache-semantics": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz",
+ "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==",
+ "license": "MIT"
+ },
"node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
@@ -1249,6 +1269,12 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "license": "MIT"
+ },
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
@@ -1328,6 +1354,39 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"license": "MIT"
},
+ "node_modules/barse": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/barse/-/barse-0.4.3.tgz",
+ "integrity": "sha512-UEpvriJqAn8zuVinYICuKoPttZy3XxXEoqX/V2uYAL4zzJRuNzCK3+20nAu3YUIa2U7G53kf90wfBIp9/A+Odw==",
+ "license": "MIT",
+ "dependencies": {
+ "readable-stream": "~1.0.2"
+ }
+ },
+ "node_modules/barse/node_modules/isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
+ "license": "MIT"
+ },
+ "node_modules/barse/node_modules/readable-stream": {
+ "version": "1.0.34",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+ "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==",
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "0.0.1",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "node_modules/barse/node_modules/string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==",
+ "license": "MIT"
+ },
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@@ -1619,6 +1678,33 @@
}
}
},
+ "node_modules/cacheable-lookup": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz",
+ "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ }
+ },
+ "node_modules/cacheable-request": {
+ "version": "10.2.14",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz",
+ "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-cache-semantics": "^4.0.2",
+ "get-stream": "^6.0.1",
+ "http-cache-semantics": "^4.1.1",
+ "keyv": "^4.5.3",
+ "mimic-response": "^4.0.0",
+ "normalize-url": "^8.0.0",
+ "responselike": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ }
+ },
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
@@ -2263,21 +2349,6 @@
"url": "https://github.com/sponsors/fb55"
}
},
- "node_modules/css-tree": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
- "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
- "license": "MIT",
- "optional": true,
- "peer": true,
- "dependencies": {
- "mdn-data": "2.0.30",
- "source-map-js": "^1.0.1"
- },
- "engines": {
- "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
- }
- },
"node_modules/css-what": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
@@ -2474,6 +2545,33 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/decompress-response/node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/deep-eql": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
@@ -2491,6 +2589,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/defer-to-connect": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
+ "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -2707,6 +2814,14 @@
"integrity": "sha512-k4McmnB2091YIsdCgkS0fMVMPOJgxl93ltFzaryXqwip1AaxeDqKCGLxkXODDA5Ab/D+tV5EL5+aTx76RvLRxw==",
"license": "ISC"
},
+ "node_modules/emitter-component": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/emitter-component/-/emitter-component-1.1.2.tgz",
+ "integrity": "sha512-QdXO3nXOzZB4pAjM0n6ZE+R9/+kPpECA/XSELIcc54NeYVnBqIk+4DFiBgK+8QbV3mdvTG6nedl7dTYgO+5wDw==",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
@@ -3114,6 +3229,13 @@
"node": ">= 0.6"
}
},
+ "node_modules/event-to-promise": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/event-to-promise/-/event-to-promise-0.7.0.tgz",
+ "integrity": "sha512-VOBBfyaADfe378ZzG0tgkzmsvzUyeU5arehrFzNRt5yaASUDshgctTwSrPI17ocAwR3+YftsxRClHF+GBKFByQ==",
+ "deprecated": "Use promise-toolbox/fromEvent instead",
+ "license": "MIT"
+ },
"node_modules/express": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
@@ -3220,6 +3342,24 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fast-xml-parser": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.3.tgz",
+ "integrity": "sha512-OdCYfRqfpuLUFonTNjvd30rCBZUneHpSQkCqfaeWQ9qrKcl6XlWeDBNVwGb+INAIxRshuN2jF+BE0L6gbBO2mw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "strnum": "^2.1.0"
+ },
+ "bin": {
+ "fxparser": "src/cli/cli.js"
+ }
+ },
"node_modules/fecha": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
@@ -3413,6 +3553,15 @@
"node": ">= 6"
}
},
+ "node_modules/form-data-encoder": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz",
+ "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.17"
+ }
+ },
"node_modules/formdata-polyfill": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
@@ -3472,6 +3621,41 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/gamedig": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/gamedig/-/gamedig-5.3.1.tgz",
+ "integrity": "sha512-RM/eCR8bAKEX+5dA9sxg4D6oQjS5t0MPsIxGquerBLSIu0f1hAVaDGC58Lp1srYwF6A1C2wYY2p9PzOrPTKf4Q==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-xml-parser": "5.2.3",
+ "gbxremote": "0.2.1",
+ "got": "13.0.0",
+ "iconv-lite": "0.6.3",
+ "long": "5.3.2",
+ "minimist": "1.2.8",
+ "seek-bzip": "2.0.0",
+ "telnet-client": "2.2.5",
+ "varint": "6.0.0"
+ },
+ "bin": {
+ "gamedig": "bin/gamedig.js"
+ },
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/gamedig/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/gaxios": {
"version": "6.7.1",
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz",
@@ -3488,6 +3672,21 @@
"node": ">=14"
}
},
+ "node_modules/gbxremote": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/gbxremote/-/gbxremote-0.2.1.tgz",
+ "integrity": "sha512-SMehu6Y6ndq2Qgp9VxAb8Np3f+UUD+RWoW2SAMaxzGS96rWXyr4T1GGkecO0HHtxeH1m7pEh4FJWB8a/6aM2XQ==",
+ "dependencies": {
+ "any-promise": "^1.1.0",
+ "barse": "~0.4.2",
+ "event-to-promise": "^0.7.0",
+ "string-to-stream": "^1.0.1",
+ "xmlrpc": "^1.3.1"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
@@ -3534,6 +3733,18 @@
"node": ">= 0.4"
}
},
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
@@ -3616,6 +3827,31 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/got": {
+ "version": "13.0.0",
+ "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz",
+ "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==",
+ "license": "MIT",
+ "dependencies": {
+ "@sindresorhus/is": "^5.2.0",
+ "@szmarczak/http-timer": "^5.0.1",
+ "cacheable-lookup": "^7.0.0",
+ "cacheable-request": "^10.2.8",
+ "decompress-response": "^6.0.0",
+ "form-data-encoder": "^2.1.2",
+ "get-stream": "^6.0.1",
+ "http2-wrapper": "^2.1.10",
+ "lowercase-keys": "^3.0.0",
+ "p-cancelable": "^3.0.0",
+ "responselike": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/got?sponsor=1"
+ }
+ },
"node_modules/handlebars": {
"version": "4.7.8",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
@@ -3777,6 +4013,12 @@
"entities": "^4.4.0"
}
},
+ "node_modules/http-cache-semantics": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
+ "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
+ "license": "BSD-2-Clause"
+ },
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
@@ -3793,6 +4035,19 @@
"node": ">= 0.8"
}
},
+ "node_modules/http2-wrapper": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz",
+ "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "quick-lru": "^5.1.1",
+ "resolve-alpn": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=10.19.0"
+ }
+ },
"node_modules/https-proxy-agent": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
@@ -4174,7 +4429,6 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/json-parse-even-better-errors": {
@@ -4336,7 +4590,6 @@
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"json-buffer": "3.0.1"
@@ -4536,6 +4789,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/lowercase-keys": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
+ "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
@@ -4587,14 +4852,6 @@
"node": ">= 0.4"
}
},
- "node_modules/mdn-data": {
- "version": "2.0.30",
- "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
- "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
- "license": "CC0-1.0",
- "optional": true,
- "peer": true
- },
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -4676,6 +4933,18 @@
"node": ">= 0.6"
}
},
+ "node_modules/mimic-response": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz",
+ "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -5498,6 +5767,12 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"license": "MIT"
},
+ "node_modules/net": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/net/-/net-1.0.2.tgz",
+ "integrity": "sha512-kbhcj2SVVR4caaVnGLJKmlk2+f+oLkjqdKeQlmUtz6nGzOpbcobwVIeSURNgraV/v3tlmGIX82OcPCl0K6RbHQ==",
+ "license": "MIT"
+ },
"node_modules/nise": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz",
@@ -5681,6 +5956,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/normalize-url": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.2.tgz",
+ "integrity": "sha512-Ee/R3SyN4BuynXcnTaekmaVdbDAEiNrHqjQIA37mHU8G9pf7aaAD4ZX3XjBLo6rsdcxA/gtkcNYZLt30ACgynw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
@@ -5777,6 +6064,15 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/p-cancelable": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz",
+ "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20"
+ }
+ },
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -6733,6 +7029,18 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/quick-lru": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
+ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/rambda": {
"version": "7.5.0",
"resolved": "https://registry.npmjs.org/rambda/-/rambda-7.5.0.tgz",
@@ -6830,6 +7138,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/resolve-alpn": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
+ "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
+ "license": "MIT"
+ },
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -6839,6 +7153,21 @@
"node": ">=4"
}
},
+ "node_modules/responselike": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz",
+ "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==",
+ "license": "MIT",
+ "dependencies": {
+ "lowercase-keys": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -6880,6 +7209,28 @@
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
"license": "ISC"
},
+ "node_modules/seek-bzip": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-2.0.0.tgz",
+ "integrity": "sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg==",
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^6.0.0"
+ },
+ "bin": {
+ "seek-bunzip": "bin/seek-bunzip",
+ "seek-table": "bin/seek-bzip-table"
+ }
+ },
+ "node_modules/seek-bzip/node_modules/commander": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
+ "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
@@ -7267,6 +7618,15 @@
"node": ">= 0.8"
}
},
+ "node_modules/stream": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/stream/-/stream-0.0.2.tgz",
+ "integrity": "sha512-gCq3NDI2P35B2n6t76YJuOp7d6cN/C7Rt0577l91wllh0sY9ZBuw9KaSGqH/b0hzn3CWWJbpbW0W0WvQ1H/Q7g==",
+ "license": "MIT",
+ "dependencies": {
+ "emitter-component": "^1.1.1"
+ }
+ },
"node_modules/streamsearch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
@@ -7284,6 +7644,46 @@
"safe-buffer": "~5.2.0"
}
},
+ "node_modules/string-to-stream": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string-to-stream/-/string-to-stream-1.1.1.tgz",
+ "integrity": "sha512-QySF2+3Rwq0SdO3s7BAp4x+c3qsClpPQ6abAmb0DGViiSBAkT5kL6JT2iyzEVP+T1SmzHrQD1TwlP9QAHCc+Sw==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.1.0"
+ }
+ },
+ "node_modules/string-to-stream/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/string-to-stream/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
+ },
+ "node_modules/string-to-stream/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
"node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
@@ -7393,6 +7793,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/strnum": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz",
+ "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT"
+ },
"node_modules/stylehacks": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-7.0.6.tgz",
@@ -7516,44 +7928,6 @@
"node": ">=8"
}
},
- "node_modules/svgo": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz",
- "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==",
- "license": "MIT",
- "optional": true,
- "peer": true,
- "dependencies": {
- "@trysound/sax": "0.2.0",
- "commander": "^7.2.0",
- "css-select": "^5.1.0",
- "css-tree": "^2.3.1",
- "css-what": "^6.1.0",
- "csso": "^5.0.5",
- "picocolors": "^1.0.0"
- },
- "bin": {
- "svgo": "bin/svgo"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/svgo"
- }
- },
- "node_modules/svgo/node_modules/commander": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
- "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
- "license": "MIT",
- "optional": true,
- "peer": true,
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/swagger-ui-dist": {
"version": "5.27.0",
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.27.0.tgz",
@@ -7606,6 +7980,20 @@
"node": ">=6"
}
},
+ "node_modules/telnet-client": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/telnet-client/-/telnet-client-2.2.5.tgz",
+ "integrity": "sha512-X5xEkmKHgpCpngnH7QnkFX87UyBErauHsjzlCGVp87MbhnmHoaAeacuALGfqovHh3MXAfrpPs+g30PgyBpy8Jw==",
+ "license": "MIT",
+ "dependencies": {
+ "net": "^1.0.2",
+ "stream": "^0.0.2"
+ },
+ "funding": {
+ "type": "paypal",
+ "url": "https://paypal.me/kozjak"
+ }
+ },
"node_modules/test-exclude": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz",
@@ -7917,6 +8305,12 @@
"node": ">=10"
}
},
+ "node_modules/varint": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz",
+ "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==",
+ "license": "MIT"
+ },
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -8283,6 +8677,35 @@
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
+ "node_modules/xmlbuilder": {
+ "version": "8.2.2",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz",
+ "integrity": "sha512-eKRAFz04jghooy8muekqzo8uCSVNeyRedbuJrp0fovbLIi7wlsYtdUn3vBAAPq2Y3/0xMz2WMEUQ8yhVVO9Stw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/xmlrpc": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/xmlrpc/-/xmlrpc-1.3.2.tgz",
+ "integrity": "sha512-jQf5gbrP6wvzN71fgkcPPkF4bF/Wyovd7Xdff8d6/ihxYmgETQYSuTc+Hl+tsh/jmgPLro/Aro48LMFlIyEKKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "sax": "1.2.x",
+ "xmlbuilder": "8.2.x"
+ },
+ "engines": {
+ "node": ">=0.8",
+ "npm": ">=1.0.0"
+ }
+ },
+ "node_modules/xmlrpc/node_modules/sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+ "license": "ISC"
+ },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
diff --git a/server/package.json b/server/package.json
index 4768fb45f..3e52d6983 100755
--- a/server/package.json
+++ b/server/package.json
@@ -26,6 +26,7 @@
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express-rate-limit": "8.0.1",
+ "gamedig": "^5.3.1",
"handlebars": "^4.7.8",
"helmet": "^8.0.0",
"ioredis": "^5.4.2",
diff --git a/server/src/db/models/Monitor.js b/server/src/db/models/Monitor.js
index 266cebeef..1ee467999 100755
--- a/server/src/db/models/Monitor.js
+++ b/server/src/db/models/Monitor.js
@@ -33,7 +33,7 @@ const MonitorSchema = mongoose.Schema(
type: {
type: String,
required: true,
- enum: ["http", "ping", "pagespeed", "hardware", "docker", "port"],
+ enum: ["http", "ping", "pagespeed", "hardware", "docker", "port", "game"],
},
ignoreTlsErrors: {
type: Boolean,
@@ -115,6 +115,9 @@ const MonitorSchema = mongoose.Schema(
return this.alertThreshold;
},
},
+ gameId: {
+ type: String,
+ },
},
{
timestamps: true,
diff --git a/server/src/db/mongo/modules/checkModule.js b/server/src/db/mongo/modules/checkModule.js
index f806b5bf5..a606a593b 100755
--- a/server/src/db/mongo/modules/checkModule.js
+++ b/server/src/db/mongo/modules/checkModule.js
@@ -86,6 +86,7 @@ class CheckModule {
port: this.Check,
pagespeed: this.PageSpeedCheck,
hardware: this.HardwareCheck,
+ game: this.Check,
};
const Model = checkModels[type];
diff --git a/server/src/db/mongo/modules/monitorModule.js b/server/src/db/mongo/modules/monitorModule.js
index 76f055f94..c4a896030 100755
--- a/server/src/db/mongo/modules/monitorModule.js
+++ b/server/src/db/mongo/modules/monitorModule.js
@@ -310,7 +310,7 @@ class MonitorModule {
checks: this.processChecksForDisplay(this.NormalizeData, checksForDateRange, numToDisplay, normalize),
};
- if (monitor.type === "http" || monitor.type === "ping" || monitor.type === "docker" || monitor.type === "port") {
+ if (monitor.type === "http" || monitor.type === "ping" || monitor.type === "docker" || monitor.type === "port" || monitor.type === "game") {
// HTTP/PING Specific stats
monitorStats.periodAvgResponseTime = this.getAverageResponseTime(checksForDateRange);
monitorStats.periodUptime = this.getUptimePercentage(checksForDateRange);
diff --git a/server/src/db/mongo/modules/monitorModuleQueries.js b/server/src/db/mongo/modules/monitorModuleQueries.js
index d96e128fa..d5fea1931 100755
--- a/server/src/db/mongo/modules/monitorModuleQueries.js
+++ b/server/src/db/mongo/modules/monitorModuleQueries.js
@@ -819,7 +819,7 @@ const buildGetMonitorsByTeamIdPipeline = (req) => {
$switch: {
branches: [
{
- case: { $in: ["$type", ["http", "ping", "docker", "port"]] },
+ case: { $in: ["$type", ["http", "ping", "docker", "port", "game"]] },
then: "$standardchecks",
},
{
diff --git a/server/src/service/business/monitorService.js b/server/src/service/business/monitorService.js
index c52b5cadf..c6984a327 100644
--- a/server/src/service/business/monitorService.js
+++ b/server/src/service/business/monitorService.js
@@ -71,7 +71,7 @@ class MonitorService {
};
createMonitor = async ({ teamId, userId, body }) => {
- const monitor = await this.db.createMonitor({
+ const monitor = await this.db.monitorModule.createMonitor({
body,
teamId,
userId,
@@ -122,7 +122,7 @@ class MonitorService {
await createMonitorsBodyValidation.validateAsync(enrichedData);
- const monitors = await this.db.createBulkMonitors(enrichedData);
+ const monitors = await this.db.monitorModule.createBulkMonitors(enrichedData);
await Promise.all(
monitors.map(async (monitor) => {
@@ -141,14 +141,14 @@ class MonitorService {
deleteMonitor = async ({ teamId, monitorId }) => {
await this.verifyTeamAccess({ teamId, monitorId });
- const monitor = await this.db.deleteMonitor({ teamId, monitorId });
+ const monitor = await this.db.monitorModule.deleteMonitor({ teamId, monitorId });
await this.jobQueue.deleteJob(monitor);
await this.db.statusPageModule.deleteStatusPagesByMonitorId(monitor._id);
return monitor;
};
deleteAllMonitors = async ({ teamId }) => {
- const { monitors, deletedCount } = await this.db.deleteAllMonitors(teamId);
+ const { monitors, deletedCount } = await this.db.monitorModule.deleteAllMonitors(teamId);
await Promise.all(
monitors.map(async (monitor) => {
try {
@@ -171,19 +171,19 @@ class MonitorService {
editMonitor = async ({ teamId, monitorId, body }) => {
await this.verifyTeamAccess({ teamId, monitorId });
- const editedMonitor = await this.db.editMonitor({ monitorId, body });
+ const editedMonitor = await this.db.monitorModule.editMonitor({ monitorId, body });
await this.jobQueue.updateJob(editedMonitor);
};
pauseMonitor = async ({ teamId, monitorId }) => {
await this.verifyTeamAccess({ teamId, monitorId });
- const monitor = await this.db.pauseMonitor({ monitorId });
+ const monitor = await this.db.monitorModule.pauseMonitor({ monitorId });
monitor.isActive === true ? await this.jobQueue.resumeJob(monitor._id, monitor) : await this.jobQueue.pauseJob(monitor);
return monitor;
};
addDemoMonitors = async ({ userId, teamId }) => {
- const demoMonitors = await this.db.addDemoMonitors(userId, teamId);
+ const demoMonitors = await this.db.monitorModule.addDemoMonitors(userId, teamId);
await Promise.all(demoMonitors.map((monitor) => this.jobQueue.addJob(monitor._id, monitor)));
return demoMonitors;
};
diff --git a/server/src/service/infrastructure/bufferService.js b/server/src/service/infrastructure/bufferService.js
index 46da6bef3..dc86597b2 100755
--- a/server/src/service/infrastructure/bufferService.js
+++ b/server/src/service/infrastructure/bufferService.js
@@ -6,6 +6,7 @@ const TYPE_MAP = {
docker: "checks",
pagespeed: "pagespeedChecks",
hardware: "hardwareChecks",
+ game: "checks",
};
class BufferService {
diff --git a/server/src/service/infrastructure/networkService.js b/server/src/service/infrastructure/networkService.js
index 6a2e3c8a7..ca3c69bab 100755
--- a/server/src/service/infrastructure/networkService.js
+++ b/server/src/service/infrastructure/networkService.js
@@ -1,5 +1,6 @@
import jmespath from "jmespath";
import https from "https";
+import { GameDig } from 'gamedig';
const SERVICE_NAME = "NetworkService";
const UPROCK_ENDPOINT = "https://api.uprock.com/checkmate/push";
@@ -23,6 +24,7 @@ class NetworkService {
this.TYPE_HARDWARE = "hardware";
this.TYPE_DOCKER = "docker";
this.TYPE_PORT = "port";
+ this.TYPE_GAME = "game";
this.SERVICE_NAME = SERVICE_NAME;
this.NETWORK_ERROR = 5000;
this.PING_ERROR = 5001;
@@ -470,6 +472,57 @@ class NetworkService {
}
}
+ /**
+ * Requests the status of a game monitor.
+ *
+ * @param {Object} monitor - The monitor object to request the status for.
+ * @returns {Promise