diff --git a/CHANGELOG.md b/CHANGELOG.md
index 20ad991..f6529b0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,8 @@
* Feat: Farming Simulator add response to raw object (#682)
* Feat: Renown (2025) - Added support (#684 By @anthonyphysgun)
* Fix: Terraria - add missing supported maxplayers field and raw field (By @GoodDays13 #686)
+* Chore: Replace cheerio with fast-xml-parser (By @xCausxn #683)
+* Fix: Build and Shoot protocol using the new json status server (By @xCausxn #683)
## 5.2.0
* Fix: Palworld not respecting query output players schema (#666)
diff --git a/GAMES_LIST.md b/GAMES_LIST.md
index 020dabe..f6a8744 100644
--- a/GAMES_LIST.md
+++ b/GAMES_LIST.md
@@ -17,7 +17,7 @@
| americasarmy3 | America's Army 3 | [Valve Protocol](#valve) |
| aoc | Age of Chivalry | [Valve Protocol](#valve) |
| aoe2 | Age of Empires 2 | |
-| aosc | Ace of Spades Classic | |
+| aosc | Ace of Spades Classic | [Notes](#aosc-buildandshoot) |
| arma2 | ARMA 2 | [Valve Protocol](#valve) |
| arma3 | ARMA 3 | [Valve Protocol](#valve) |
| armagetronadvanced | Armagetron Advanced | |
@@ -34,7 +34,7 @@
| baldursgate | Baldur's Gate | |
| ballisticoverkill | Ballistic Overkill | [Valve Protocol](#valve) |
| barotrauma | Barotrauma | [Valve Protocol](#valve) |
-| bas | Build and Shoot | |
+| bas | Build and Shoot | [Notes](#aosc-buildandshoot) |
| basedefense | Base Defense | [Valve Protocol](#valve) |
| battalion1944 | Battalion 1944 | [Valve Protocol](#valve) |
| battlefield1942 | Battlefield 1942 | |
@@ -544,3 +544,6 @@ Requires the `sv_exposePlayerIdentifiersInHttpEndpoint` convar to be `1` for the
### Counter-Strike 2
Does not provide players names, using a plugin like this [one](https://github.com/Source2ZE/ServerListPlayersFix) makes the query to return them.
+
+### Ace of Spades / Build and Shoot
+Requires usage of the status query server enabled in the config.txt. `status_server.enabled` to `true`
diff --git a/lib/games.js b/lib/games.js
index 0429e74..65107f7 100644
--- a/lib/games.js
+++ b/lib/games.js
@@ -494,7 +494,8 @@ export const games = {
protocol: 'buildandshoot'
},
extra: {
- old_id: 'buildandshoot'
+ old_id: 'buildandshoot',
+ doc_notes: 'aosc-buildandshoot'
}
},
aosc: {
@@ -504,6 +505,9 @@ export const games = {
port: 32887,
port_query_offset: -1,
protocol: 'buildandshoot'
+ },
+ extra: {
+ doc_notes: 'aosc-buildandshoot'
}
},
cod: {
diff --git a/package-lock.json b/package-lock.json
index 7409e38..3645a82 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,7 @@
"version": "5.2.0",
"license": "MIT",
"dependencies": {
- "cheerio": "1.0.0-rc.12",
+ "fast-xml-parser": "5.0.9",
"gbxremote": "0.2.1",
"got": "13.0.0",
"iconv-lite": "0.6.3",
@@ -22,7 +22,6 @@
"gamedig": "bin/gamedig.js"
},
"devDependencies": {
- "@types/cheerio": "^0.22.31",
"@types/node": "^16.18.58",
"esbuild": "^0.19.10",
"esbuild-node-externals": "^1.12.0",
@@ -559,15 +558,6 @@
"node": ">=14.16"
}
},
- "node_modules/@types/cheerio": {
- "version": "0.22.31",
- "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.31.tgz",
- "integrity": "sha512-Kt7Cdjjdi2XWSfrZ53v4Of0wG3ZcmaegFXjMmz9tfNrZSkzzo36G0AL1YqSdcIA78Etjt6E609pt5h1xnQkPUw==",
- "dev": true,
- "dependencies": {
- "@types/node": "*"
- }
- },
"node_modules/@types/http-cache-semantics": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.2.tgz",
@@ -791,11 +781,6 @@
"readable-stream": "~1.0.2"
}
},
- "node_modules/boolbase": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
- "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
- },
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -893,42 +878,6 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
- "node_modules/cheerio": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
- "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==",
- "dependencies": {
- "cheerio-select": "^2.1.0",
- "dom-serializer": "^2.0.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.0.1",
- "htmlparser2": "^8.0.1",
- "parse5": "^7.0.0",
- "parse5-htmlparser2-tree-adapter": "^7.0.0"
- },
- "engines": {
- "node": ">= 6"
- },
- "funding": {
- "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
- }
- },
- "node_modules/cheerio-select": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
- "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
- "dependencies": {
- "boolbase": "^1.0.0",
- "css-select": "^5.1.0",
- "css-what": "^6.1.0",
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/fb55"
- }
- },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -972,32 +921,6 @@
"node": ">= 8"
}
},
- "node_modules/css-select": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
- "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
- "dependencies": {
- "boolbase": "^1.0.0",
- "css-what": "^6.1.0",
- "domhandler": "^5.0.2",
- "domutils": "^3.0.1",
- "nth-check": "^2.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/fb55"
- }
- },
- "node_modules/css-what": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
- "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
- "engines": {
- "node": ">= 6"
- },
- "funding": {
- "url": "https://github.com/sponsors/fb55"
- }
- },
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -1097,68 +1020,6 @@
"node": ">=6.0.0"
}
},
- "node_modules/dom-serializer": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
- "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
- "dependencies": {
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.2",
- "entities": "^4.2.0"
- },
- "funding": {
- "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
- }
- },
- "node_modules/domelementtype": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
- "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/fb55"
- }
- ]
- },
- "node_modules/domhandler": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
- "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
- "dependencies": {
- "domelementtype": "^2.3.0"
- },
- "engines": {
- "node": ">= 4"
- },
- "funding": {
- "url": "https://github.com/fb55/domhandler?sponsor=1"
- }
- },
- "node_modules/domutils": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
- "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
- "dependencies": {
- "dom-serializer": "^2.0.0",
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3"
- },
- "funding": {
- "url": "https://github.com/fb55/domutils?sponsor=1"
- }
- },
- "node_modules/entities": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
- "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
- "engines": {
- "node": ">=0.12"
- },
- "funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
- }
- },
"node_modules/es-abstract": {
"version": "1.22.2",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz",
@@ -1732,6 +1593,23 @@
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true
},
+ "node_modules/fast-xml-parser": {
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.0.9.tgz",
+ "integrity": "sha512-2mBwCiuW3ycKQQ6SOesSB8WeF+fIGb6I/GG5vU5/XEptwFFhp9PE8b9O7fbs2dpq9fXn4ULR3UsfydNUCntf5A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "dependencies": {
+ "strnum": "^2.0.5"
+ },
+ "bin": {
+ "fxparser": "src/cli/cli.js"
+ }
+ },
"node_modules/fastq": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
@@ -2087,24 +1965,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/htmlparser2": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
- "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
- "funding": [
- "https://github.com/fb55/htmlparser2?sponsor=1",
- {
- "type": "github",
- "url": "https://github.com/sponsors/fb55"
- }
- ],
- "dependencies": {
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.0.1",
- "entities": "^4.4.0"
- }
- },
"node_modules/http-cache-semantics": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
@@ -2595,17 +2455,6 @@
"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",
- "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
- "dependencies": {
- "boolbase": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/fb55/nth-check?sponsor=1"
- }
- },
"node_modules/object-inspect": {
"version": "1.12.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
@@ -2764,29 +2613,6 @@
"node": ">=6"
}
},
- "node_modules/parse5": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
- "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
- "dependencies": {
- "entities": "^4.4.0"
- },
- "funding": {
- "url": "https://github.com/inikulin/parse5?sponsor=1"
- }
- },
- "node_modules/parse5-htmlparser2-tree-adapter": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz",
- "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==",
- "dependencies": {
- "domhandler": "^5.0.2",
- "parse5": "^7.0.0"
- },
- "funding": {
- "url": "https://github.com/inikulin/parse5?sponsor=1"
- }
- },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -3257,6 +3083,17 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/strnum": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.0.5.tgz",
+ "integrity": "sha512-YAT3K/sgpCUxhxNMrrdhtod3jckkpYwH6JAuwmUdXZsmzH1wUyzTMrrK2wYCEEqlKwrWDd35NeuUkbBy/1iK+Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ]
+ },
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -3792,15 +3629,6 @@
"defer-to-connect": "^2.0.1"
}
},
- "@types/cheerio": {
- "version": "0.22.31",
- "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.31.tgz",
- "integrity": "sha512-Kt7Cdjjdi2XWSfrZ53v4Of0wG3ZcmaegFXjMmz9tfNrZSkzzo36G0AL1YqSdcIA78Etjt6E609pt5h1xnQkPUw==",
- "dev": true,
- "requires": {
- "@types/node": "*"
- }
- },
"@types/http-cache-semantics": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.2.tgz",
@@ -3964,11 +3792,6 @@
"readable-stream": "~1.0.2"
}
},
- "boolbase": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
- "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
- },
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -4044,33 +3867,6 @@
"supports-color": "^7.1.0"
}
},
- "cheerio": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
- "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==",
- "requires": {
- "cheerio-select": "^2.1.0",
- "dom-serializer": "^2.0.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.0.1",
- "htmlparser2": "^8.0.1",
- "parse5": "^7.0.0",
- "parse5-htmlparser2-tree-adapter": "^7.0.0"
- }
- },
- "cheerio-select": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
- "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
- "requires": {
- "boolbase": "^1.0.0",
- "css-select": "^5.1.0",
- "css-what": "^6.1.0",
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.0.1"
- }
- },
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -4108,23 +3904,6 @@
"which": "^2.0.1"
}
},
- "css-select": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
- "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
- "requires": {
- "boolbase": "^1.0.0",
- "css-what": "^6.1.0",
- "domhandler": "^5.0.2",
- "domutils": "^3.0.1",
- "nth-check": "^2.0.1"
- }
- },
- "css-what": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
- "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="
- },
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -4191,44 +3970,6 @@
"esutils": "^2.0.2"
}
},
- "dom-serializer": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
- "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
- "requires": {
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.2",
- "entities": "^4.2.0"
- }
- },
- "domelementtype": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
- "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
- },
- "domhandler": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
- "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
- "requires": {
- "domelementtype": "^2.3.0"
- }
- },
- "domutils": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
- "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
- "requires": {
- "dom-serializer": "^2.0.0",
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3"
- }
- },
- "entities": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
- "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
- },
"es-abstract": {
"version": "1.22.2",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz",
@@ -4651,6 +4392,14 @@
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true
},
+ "fast-xml-parser": {
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.0.9.tgz",
+ "integrity": "sha512-2mBwCiuW3ycKQQ6SOesSB8WeF+fIGb6I/GG5vU5/XEptwFFhp9PE8b9O7fbs2dpq9fXn4ULR3UsfydNUCntf5A==",
+ "requires": {
+ "strnum": "^2.0.5"
+ }
+ },
"fastq": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
@@ -4904,17 +4653,6 @@
"has-symbols": "^1.0.2"
}
},
- "htmlparser2": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
- "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
- "requires": {
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.0.1",
- "entities": "^4.4.0"
- }
- },
"http-cache-semantics": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
@@ -5264,14 +5002,6 @@
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz",
"integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw=="
},
- "nth-check": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
- "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
- "requires": {
- "boolbase": "^1.0.0"
- }
- },
"object-inspect": {
"version": "1.12.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
@@ -5385,23 +5115,6 @@
"callsites": "^3.0.0"
}
},
- "parse5": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
- "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
- "requires": {
- "entities": "^4.4.0"
- }
- },
- "parse5-htmlparser2-tree-adapter": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz",
- "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==",
- "requires": {
- "domhandler": "^5.0.2",
- "parse5": "^7.0.0"
- }
- },
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -5737,6 +5450,11 @@
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
},
+ "strnum": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.0.5.tgz",
+ "integrity": "sha512-YAT3K/sgpCUxhxNMrrdhtod3jckkpYwH6JAuwmUdXZsmzH1wUyzTMrrK2wYCEEqlKwrWDd35NeuUkbBy/1iK+Q=="
+ },
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
diff --git a/package.json b/package.json
index 02d7e7a..4f5f6d7 100644
--- a/package.json
+++ b/package.json
@@ -57,7 +57,7 @@
"README.md"
],
"dependencies": {
- "cheerio": "1.0.0-rc.12",
+ "fast-xml-parser": "5.0.9",
"gbxremote": "0.2.1",
"got": "13.0.0",
"iconv-lite": "0.6.3",
@@ -67,7 +67,6 @@
"varint": "6.0.0"
},
"devDependencies": {
- "@types/cheerio": "^0.22.31",
"@types/node": "^16.18.58",
"esbuild": "^0.19.10",
"esbuild-node-externals": "^1.12.0",
diff --git a/protocols/buildandshoot.js b/protocols/buildandshoot.js
index 1b742da..3824af6 100644
--- a/protocols/buildandshoot.js
+++ b/protocols/buildandshoot.js
@@ -1,55 +1,42 @@
import Core from './core.js'
-import * as cheerio from 'cheerio'
+// We are doing some shenanigans here as we are trying to support the stable version and the git master version
+// as in the latest (0.75) releases they are mixed up.
export default class buildandshoot extends Core {
async run (state) {
- const body = await this.request({
- url: 'http://' + this.options.address + ':' + this.options.port + '/'
+ const request = await this.request({
+ url: 'http://' + this.options.address + ':' + this.options.port + '/json',
+ responseType: 'json'
})
- let m
+ state.name = request.serverName
+ state.map = request.map.name
+ state.version = request.serverVersion
- m = body.match(/status server for (.*?)\.?[\r\n]/)
- if (m) state.name = m[1]
-
- m = body.match(/Current uptime: (\d+)/)
- if (m) state.raw.uptime = m[1]
-
- m = body.match(/currently running (.*?) by /)
- if (m) state.map = m[1]
-
- m = body.match(/Current players: (\d+)\/(\d+)/)
- if (m) {
- state.numplayers = parseInt(m[1])
- state.maxplayers = m[2]
+ const bluePlayers = request.players?.blue || []
+ const greenPlayers = request.players?.green || []
+ let players = bluePlayers.concat(greenPlayers)
+ if (Array.isArray(request.players)) {
+ players = players.concat(request.players)
}
- m = body.match(/aos:\/\/[0-9]+:[0-9]+/)
- if (m) {
- state.connect = m[0]
- }
+ state.numplayers = players.length
+ state.maxplayers = request.maxPlayers || request.players?.maxPlayers
- const $ = cheerio.load(body)
- $('#playerlist tbody tr').each((i, tr) => {
- if (!$(tr).find('td').first().attr('colspan')) {
+ state.players = []
+ for (const player of players) {
+ if (typeof player === 'string') {
state.players.push({
- name: $(tr).find('td').eq(2).text(),
- ping: $(tr).find('td').eq(3).text().trim(),
- team: $(tr).find('td').eq(4).text().toLowerCase(),
- score: parseInt($(tr).find('td').eq(5).text())
+ name: player
+ })
+ } else {
+ state.players.push({
+ ...player,
+ name: player.name
})
}
- })
- /*
- var m = this.options.address.match(/(\d+)\.(\d+)\.(\d+)\.(\d+)/);
- if(m) {
- var o1 = parseInt(m[1]);
- var o2 = parseInt(m[2]);
- var o3 = parseInt(m[3]);
- var o4 = parseInt(m[4]);
- var addr = o1+(o2<<8)+(o3<<16)+(o4<<24);
- state.raw.url = 'aos://'+addr;
- }
- */
+ }
+
+ state.raw = request
}
}
diff --git a/protocols/farmingsimulator.js b/protocols/farmingsimulator.js
index e058228..9017881 100644
--- a/protocols/farmingsimulator.js
+++ b/protocols/farmingsimulator.js
@@ -1,5 +1,5 @@
import Core from './core.js'
-import cheerio from 'cheerio'
+import { XMLParser, XMLValidator } from 'fast-xml-parser'
export default class farmingsimulator extends Core {
async run (state) {
@@ -11,47 +11,59 @@ export default class farmingsimulator extends Core {
responseType: 'text'
})
- const $ = cheerio.load(request, {
- xmlMode: true
- })
+ const isValidXML = XMLValidator.validate(request)
+ if (!isValidXML) {
+ throw new Error('Invalid XML received from Farming Simulator Server')
+ }
- const serverInfo = $('Server')
- const playerInfo = serverInfo.find('Slots')
+ const parser = new XMLParser({ ignoreAttributes: false })
+ const parsed = parser.parse(request)
- state.name = serverInfo.attr('name')
- state.map = serverInfo.attr('mapName')
- state.numplayers = playerInfo.attr('numUsed')
- state.maxplayers = playerInfo.attr('capacity')
+ const serverInfo = parsed.Server
+ const playerInfo = serverInfo.Slots
- $('Player').each(function () {
- if ($(this).attr('isUsed') === 'true') {
- state.players.push({
- name: $(this).text(),
- raw: {
- isAdmin: $(this).attr('isAdmin') === 'true',
- uptime: parseInt($(this).attr('uptime'), 10)
- }
- })
- }
- })
+ // Attributes in fast-xml-parser are prefixed with @_
+
+ state.name = serverInfo['@_name']
+ state.map = serverInfo['@_mapName']
+ state.numplayers = parseInt(playerInfo['@_numUsed'], 10) || 0
+ state.maxplayers = parseInt(playerInfo['@_capacity'], 10) || 0
+
+ const players = playerInfo.Player
+
+ for (const player of players) {
+ if (player['@_isUsed'] !== 'true') { continue }
+
+ state.players.push({
+ name: player['#text'],
+ isUsed: player['@_isUsed'] === 'true',
+ isAdmin: player['@_isAdmin'] === 'true',
+ uptime: parseInt(player['@_uptime'], 10),
+ x: parseFloat(player['@_x']),
+ y: parseFloat(player['@_y']),
+ z: parseFloat(player['@_z'])
+ })
+ }
state.raw = {
data: request,
mods: []
}
- $('Mod').each(function () {
- if ($(this).attr('name') !== undefined) {
- state.raw.mods.push({
- name: $(this).text(),
- short_name: $(this).attr('name'),
- author: $(this).attr('author'),
- version: $(this).attr('version'),
- hash: $(this).attr('hash')
- })
- }
- })
+ const mods = serverInfo.Mods.Mod
- state.version = serverInfo.attr('version')
+ for (const mod of mods) {
+ if (mod['@_name'] == null) { continue }
+
+ state.raw.mods.push({
+ name: mod['#text'],
+ short_name: mod['@_name'],
+ author: mod['@_author'],
+ version: mod['@_version'],
+ hash: mod['@_hash']
+ })
+ }
+
+ state.version = serverInfo['@_version']
}
}
diff --git a/tools/generate_games_list.js b/tools/generate_games_list.js
index 7212ec1..ee16ac2 100644
--- a/tools/generate_games_list.js
+++ b/tools/generate_games_list.js
@@ -55,10 +55,10 @@ Object.entries(sortedGames).forEach(([id, game]) => {
if (game?.extra?.doc_notes) {
notes.push('[Notes](#' + game.extra.doc_notes + ')')
}
- if (game.options.protocol === 'valve' || game.options.protocol === 'dayz') {
+ if (['valve', 'dayz'].includes(game.options.protocol)) {
notes.push('[Valve Protocol](#valve)')
}
- if (game.options.protocol === 'epic' || game.options.protocol === 'asa' || game.options.protocol === 'theisleevrima' || game.options.protocol === 'renown') {
+ if (['epic', 'asa', 'theisleevrima', 'renown'].includes(game.options.protocol)) {
notes.push('[EOS Protocol](#epic)')
}
lineArray[HeaderType.Notes] = notes.join(', ')