mirror of
https://github.com/gamedig/node-gamedig.git
synced 2024-11-17 17:25:19 +01:00
More async conversions
This commit is contained in:
parent
77b2cc1c7f
commit
9b8423b20a
15 changed files with 859 additions and 704 deletions
|
@ -63,7 +63,7 @@ bfh|Battlefield Hardline|battlefield|port=25200,port_query_offset=22000
|
|||
breach|Breach|valve|port=27016
|
||||
breed|Breed|gamespy2|port=7649
|
||||
brink|Brink|valve|port_query_offset=1
|
||||
buildandshoot|Build and Shoot|buildandshoot|port=32887,port_query=32886
|
||||
buildandshoot|Build and Shoot|buildandshoot|port=32887,port_query_offset=-1
|
||||
|
||||
cod|Call of Duty|quake3|port=28960
|
||||
coduo|Call of Duty: United Offensive|quake3|port=28960
|
||||
|
@ -148,7 +148,7 @@ il2|IL-2 Sturmovik|gamespy1|port_query=21000
|
|||
insurgency|Insurgency|valve
|
||||
ironstorm|Iron Storm|gamespy1|port_query=3505
|
||||
jamesbondnightfire|James Bond: Nightfire|gamespy1|port_query=6550
|
||||
jc2mp|Just Cause 2 Multiplayer|jc2mp|port=7777|isJc2mp
|
||||
jc2mp|Just Cause 2 Multiplayer|jc2mp|port=7777
|
||||
killingfloor|Killing Floor|killingfloor|port=7707,port_query_offset=1
|
||||
killingfloor2|Killing Floor 2|valve|port=7777,port_query=27015
|
||||
kingpin|Kingpin: Life of Crime|gamespy1|port=31510,port_query_offset=-10
|
||||
|
|
526
package-lock.json
generated
526
package-lock.json
generated
|
@ -1,18 +1,23 @@
|
|||
{
|
||||
"name": "gamedig",
|
||||
"version": "1.0.41",
|
||||
"version": "1.0.49",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "10.12.18",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
|
||||
"integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ=="
|
||||
},
|
||||
"ajv": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
|
||||
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
|
||||
"version": "6.6.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz",
|
||||
"integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==",
|
||||
"requires": {
|
||||
"co": "4.6.0",
|
||||
"fast-deep-equal": "1.1.0",
|
||||
"fast-json-stable-stringify": "2.0.0",
|
||||
"json-schema-traverse": "0.3.1"
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"amdefine": {
|
||||
|
@ -21,9 +26,12 @@
|
|||
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
|
||||
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
|
||||
"requires": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
|
@ -46,51 +54,60 @@
|
|||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
|
||||
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4="
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
|
||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
|
||||
},
|
||||
"barse": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/barse/-/barse-0.4.3.tgz",
|
||||
"integrity": "sha1-KJhk15XQECu7sYHmbs0IxUobwMs=",
|
||||
"requires": {
|
||||
"readable-stream": "1.0.34"
|
||||
"readable-stream": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
|
||||
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
|
||||
"optional": true,
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
|
||||
"requires": {
|
||||
"tweetnacl": "0.14.5"
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
},
|
||||
"boom": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz",
|
||||
"integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=",
|
||||
"requires": {
|
||||
"hoek": "4.2.1"
|
||||
}
|
||||
"bluebird": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
|
||||
"integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw=="
|
||||
},
|
||||
"boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||
},
|
||||
"co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
|
||||
"cheerio": {
|
||||
"version": "1.0.0-rc.2",
|
||||
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz",
|
||||
"integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=",
|
||||
"requires": {
|
||||
"css-select": "~1.2.0",
|
||||
"dom-serializer": "~0.1.0",
|
||||
"entities": "~1.1.1",
|
||||
"htmlparser2": "^3.9.1",
|
||||
"lodash": "^4.15.0",
|
||||
"parse5": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
|
||||
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
|
||||
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
|
||||
"requires": {
|
||||
"delayed-stream": "1.0.0"
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
|
@ -98,7 +115,7 @@
|
|||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
|
||||
"integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
|
||||
"requires": {
|
||||
"graceful-readlink": "1.0.1"
|
||||
"graceful-readlink": ">= 1.0.0"
|
||||
}
|
||||
},
|
||||
"compressjs": {
|
||||
|
@ -106,8 +123,8 @@
|
|||
"resolved": "https://registry.npmjs.org/compressjs/-/compressjs-1.0.3.tgz",
|
||||
"integrity": "sha1-ldt03VuQOM+AvKMhqw7eJxtJWbY=",
|
||||
"requires": {
|
||||
"amdefine": "1.0.1",
|
||||
"commander": "2.8.1"
|
||||
"amdefine": "~1.0.0",
|
||||
"commander": "~2.8.1"
|
||||
}
|
||||
},
|
||||
"core-util-is": {
|
||||
|
@ -115,30 +132,28 @@
|
|||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"cryptiles": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
|
||||
"integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=",
|
||||
"css-select": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
|
||||
"integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
|
||||
"requires": {
|
||||
"boom": "5.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"boom": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
|
||||
"integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==",
|
||||
"requires": {
|
||||
"hoek": "4.2.1"
|
||||
}
|
||||
}
|
||||
"boolbase": "~1.0.0",
|
||||
"css-what": "2.1",
|
||||
"domutils": "1.5.1",
|
||||
"nth-check": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"css-what": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.2.tgz",
|
||||
"integrity": "sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ=="
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0"
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
|
@ -146,19 +161,62 @@
|
|||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
|
||||
"optional": true,
|
||||
"dom-serializer": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
|
||||
"integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
|
||||
"requires": {
|
||||
"jsbn": "0.1.1"
|
||||
"domelementtype": "~1.1.1",
|
||||
"entities": "~1.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"domelementtype": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
|
||||
"integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
|
||||
}
|
||||
}
|
||||
},
|
||||
"domelementtype": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
|
||||
"integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
|
||||
"integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
|
||||
"requires": {
|
||||
"domelementtype": "1"
|
||||
}
|
||||
},
|
||||
"domutils": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
|
||||
"integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
|
||||
"requires": {
|
||||
"dom-serializer": "0",
|
||||
"domelementtype": "1"
|
||||
}
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"entities": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
|
||||
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
|
||||
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.3.0",
|
||||
|
@ -166,9 +224,9 @@
|
|||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
||||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.0.0",
|
||||
|
@ -181,13 +239,13 @@
|
|||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
|
||||
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"requires": {
|
||||
"asynckit": "0.4.0",
|
||||
"combined-stream": "1.0.6",
|
||||
"mime-types": "2.1.18"
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"gbxremote": {
|
||||
|
@ -195,8 +253,8 @@
|
|||
"resolved": "https://registry.npmjs.org/gbxremote/-/gbxremote-0.1.4.tgz",
|
||||
"integrity": "sha1-x+0iWC5WBRtOF2AbPdWjAE7u/UM=",
|
||||
"requires": {
|
||||
"barse": "0.4.3",
|
||||
"sax": "0.4.3",
|
||||
"barse": "~0.4.2",
|
||||
"sax": "0.4.x",
|
||||
"xmlbuilder": "0.3.1"
|
||||
}
|
||||
},
|
||||
|
@ -205,7 +263,7 @@
|
|||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0"
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"graceful-readlink": {
|
||||
|
@ -219,38 +277,55 @@
|
|||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
|
||||
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
|
||||
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
|
||||
"requires": {
|
||||
"ajv": "5.5.2",
|
||||
"har-schema": "2.0.0"
|
||||
"ajv": "^6.5.5",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"hawk": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz",
|
||||
"integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==",
|
||||
"htmlparser2": {
|
||||
"version": "3.10.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.0.tgz",
|
||||
"integrity": "sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ==",
|
||||
"requires": {
|
||||
"boom": "4.3.1",
|
||||
"cryptiles": "3.1.2",
|
||||
"hoek": "4.2.1",
|
||||
"sntp": "2.1.0"
|
||||
"domelementtype": "^1.3.0",
|
||||
"domhandler": "^2.3.0",
|
||||
"domutils": "^1.5.1",
|
||||
"entities": "^1.1.1",
|
||||
"inherits": "^2.0.1",
|
||||
"readable-stream": "^3.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"readable-stream": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz",
|
||||
"integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz",
|
||||
"integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"hoek": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
|
||||
"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"jsprim": "1.4.1",
|
||||
"sshpk": "1.14.1"
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
"sshpk": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
|
@ -263,6 +338,11 @@
|
|||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"ip-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-3.0.0.tgz",
|
||||
"integrity": "sha512-T8wDtjy+Qf2TAPDQmBp0eGKJ8GavlWlUnamr3wRn6vvdZlKVuJXXMlSncYFRYgVHOM3If5NR1H4+OvVQU9Idvg=="
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
|
@ -278,11 +358,15 @@
|
|||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"jquery": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
|
||||
"integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg=="
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"optional": true
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
|
@ -290,9 +374,9 @@
|
|||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
|
||||
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
|
@ -310,22 +394,27 @@
|
|||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
||||
},
|
||||
"long": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-2.4.0.tgz",
|
||||
"integrity": "sha1-n6GAux2VAM3CnEFWdmoZleH0Uk8="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.33.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
|
||||
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ=="
|
||||
"version": "1.37.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
|
||||
"integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.18",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
|
||||
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
|
||||
"version": "2.1.21",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
|
||||
"integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==",
|
||||
"requires": {
|
||||
"mime-db": "1.33.0"
|
||||
"mime-db": "~1.37.0"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
|
@ -338,115 +427,171 @@
|
|||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.21.0.tgz",
|
||||
"integrity": "sha512-TCZ36BjURTeFTM/CwRcViQlfkMvL1/vFISuNLO5GkcVm1+QHfbSiNqZuWeMFjj1/3+uAjXswgRk30j1kkLYJBQ=="
|
||||
},
|
||||
"nth-check": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
|
||||
"integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
|
||||
"requires": {
|
||||
"boolbase": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
|
||||
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
||||
},
|
||||
"parse5": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
|
||||
"integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.1.31",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
|
||||
"integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw=="
|
||||
},
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
|
||||
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.0.34",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
||||
"integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
|
||||
"requires": {
|
||||
"core-util-is": "1.0.2",
|
||||
"inherits": "2.0.3",
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.1",
|
||||
"isarray": "0.0.1",
|
||||
"string_decoder": "0.10.31"
|
||||
"string_decoder": "~0.10.x"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"version": "2.85.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz",
|
||||
"integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==",
|
||||
"version": "2.88.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
|
||||
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
|
||||
"requires": {
|
||||
"aws-sign2": "0.7.0",
|
||||
"aws4": "1.6.0",
|
||||
"caseless": "0.12.0",
|
||||
"combined-stream": "1.0.6",
|
||||
"extend": "3.0.1",
|
||||
"forever-agent": "0.6.1",
|
||||
"form-data": "2.3.2",
|
||||
"har-validator": "5.0.3",
|
||||
"hawk": "6.0.2",
|
||||
"http-signature": "1.2.0",
|
||||
"is-typedarray": "1.0.0",
|
||||
"isstream": "0.1.2",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"mime-types": "2.1.18",
|
||||
"oauth-sign": "0.8.2",
|
||||
"performance-now": "2.1.0",
|
||||
"qs": "6.5.1",
|
||||
"safe-buffer": "5.1.1",
|
||||
"stringstream": "0.0.5",
|
||||
"tough-cookie": "2.3.4",
|
||||
"tunnel-agent": "0.6.0",
|
||||
"uuid": "3.2.1"
|
||||
"aws-sign2": "~0.7.0",
|
||||
"aws4": "^1.8.0",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.6",
|
||||
"extend": "~3.0.2",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.3.2",
|
||||
"har-validator": "~5.1.0",
|
||||
"http-signature": "~1.2.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.19",
|
||||
"oauth-sign": "~0.9.0",
|
||||
"performance-now": "^2.1.0",
|
||||
"qs": "~6.5.2",
|
||||
"safe-buffer": "^5.1.2",
|
||||
"tough-cookie": "~2.4.3",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"tough-cookie": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
|
||||
"requires": {
|
||||
"psl": "^1.1.24",
|
||||
"punycode": "^1.4.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"request-promise": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz",
|
||||
"integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=",
|
||||
"requires": {
|
||||
"bluebird": "^3.5.0",
|
||||
"request-promise-core": "1.1.1",
|
||||
"stealthy-require": "^1.1.0",
|
||||
"tough-cookie": ">=2.3.3"
|
||||
}
|
||||
},
|
||||
"request-promise-core": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz",
|
||||
"integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=",
|
||||
"requires": {
|
||||
"lodash": "^4.13.1"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
||||
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"sax": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-0.4.3.tgz",
|
||||
"integrity": "sha1-cA46NOsueSzjgHkccSgPNzGWXdw="
|
||||
},
|
||||
"sntp": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz",
|
||||
"integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==",
|
||||
"sshpk": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz",
|
||||
"integrity": "sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==",
|
||||
"requires": {
|
||||
"hoek": "4.2.1"
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
"bcrypt-pbkdf": "^1.0.0",
|
||||
"dashdash": "^1.12.0",
|
||||
"ecc-jsbn": "~0.1.1",
|
||||
"getpass": "^0.1.1",
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
}
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz",
|
||||
"integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=",
|
||||
"requires": {
|
||||
"asn1": "0.2.3",
|
||||
"assert-plus": "1.0.0",
|
||||
"bcrypt-pbkdf": "1.0.1",
|
||||
"dashdash": "1.14.1",
|
||||
"ecc-jsbn": "0.1.1",
|
||||
"getpass": "0.1.7",
|
||||
"jsbn": "0.1.1",
|
||||
"tweetnacl": "0.14.5"
|
||||
}
|
||||
"stealthy-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
|
||||
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
|
||||
"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
|
||||
"integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.0.tgz",
|
||||
"integrity": "sha512-LHMvg+RBP/mAVNqVbOX8t+iJ+tqhBA/t49DuI7+IDAWHrASnesqSu1vWbKB7UrE2yk+HMFUBMadRGMkB4VCfog==",
|
||||
"requires": {
|
||||
"punycode": "1.4.1"
|
||||
"ip-regex": "^3.0.0",
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
|
@ -454,19 +599,38 @@
|
|||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.1"
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"optional": true
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz",
|
||||
"integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA=="
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
|
||||
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
|
||||
},
|
||||
"varint": {
|
||||
"version": "4.0.1",
|
||||
|
@ -478,9 +642,9 @@
|
|||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "1.3.0"
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"xmlbuilder": {
|
||||
|
|
|
@ -25,13 +25,16 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"async": "^0.9.2",
|
||||
"cheerio": "^1.0.0-rc.2",
|
||||
"compressjs": "^1.0.2",
|
||||
"gbxremote": "^0.1.4",
|
||||
"iconv-lite": "^0.4.18",
|
||||
"jquery": "^3.3.1",
|
||||
"long": "^2.4.0",
|
||||
"minimist": "^1.2.0",
|
||||
"moment": "^2.21.0",
|
||||
"request": "^2.85.0",
|
||||
"request": "^2.88.0",
|
||||
"request-promise": "^4.2.2",
|
||||
"varint": "^4.0.1"
|
||||
},
|
||||
"bin": {
|
||||
|
|
|
@ -1,59 +1,51 @@
|
|||
const request = require('request'),
|
||||
Core = require('./core');
|
||||
const Core = require('./core'),
|
||||
cheerio = require('cheerio');
|
||||
|
||||
class BuildAndShoot extends Core {
|
||||
run(state) {
|
||||
request({
|
||||
async run(state) {
|
||||
const body = await this.request({
|
||||
uri: 'http://'+this.options.address+':'+this.options.port_query+'/',
|
||||
timeout: 3000,
|
||||
}, (e,r,body) => {
|
||||
if(e) return this.fatal('HTTP error');
|
||||
|
||||
let m;
|
||||
|
||||
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.raw.numplayers = m[1];
|
||||
state.maxplayers = m[2];
|
||||
}
|
||||
|
||||
m = body.match(/class="playerlist"([^]+?)\/table/);
|
||||
if(m) {
|
||||
const table = m[1];
|
||||
const pre = /<tr>[^]*<td>([^]*)<\/td>[^]*<td>([^]*)<\/td>[^]*<td>([^]*)<\/td>[^]*<td>([^]*)<\/td>/g;
|
||||
let pm;
|
||||
while(pm = pre.exec(table)) {
|
||||
if(pm[2] === 'Ping') continue;
|
||||
state.players.push({
|
||||
name: pm[1],
|
||||
ping: pm[2],
|
||||
team: pm[3],
|
||||
score: pm[4]
|
||||
});
|
||||
}
|
||||
}
|
||||
/*
|
||||
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;
|
||||
}
|
||||
*/
|
||||
this.finish(state);
|
||||
});
|
||||
|
||||
let m;
|
||||
|
||||
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.raw.numplayers = m[1];
|
||||
state.maxplayers = m[2];
|
||||
}
|
||||
|
||||
const $ = cheerio.load(body);
|
||||
$('#playerlist tbody tr').each((i,tr) => {
|
||||
if (!$(tr).find('td').first().attr('colspan')) {
|
||||
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())
|
||||
});
|
||||
}
|
||||
});
|
||||
/*
|
||||
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;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ const EventEmitter = require('events').EventEmitter,
|
|||
HexUtil = require('../lib/HexUtil'),
|
||||
util = require('util'),
|
||||
dnsLookupAsync = util.promisify(dns.lookup),
|
||||
dnsResolveAsync = util.promisify(dns.resolve);
|
||||
dnsResolveAsync = util.promisify(dns.resolve),
|
||||
requestAsync = require('request-promise');
|
||||
|
||||
class Core extends EventEmitter {
|
||||
constructor() {
|
||||
|
@ -20,10 +21,10 @@ class Core extends EventEmitter {
|
|||
this.delimiter = '\0';
|
||||
this.srvRecord = null;
|
||||
|
||||
this.attemptAbortables = new Set();
|
||||
this.asyncLeaks = new Set();
|
||||
this.udpCallback = null;
|
||||
this.udpLocked = false;
|
||||
this.lastAbortableId = 0;
|
||||
this.lastAsyncLeakId = 0;
|
||||
}
|
||||
|
||||
initState() {
|
||||
|
@ -64,22 +65,24 @@ class Core extends EventEmitter {
|
|||
async runOnceSafe() {
|
||||
try {
|
||||
const result = await this.timedPromise(this.runOnce(), this.options.attemptTimeout, "Attempt");
|
||||
if (this.attemptAbortables.size) {
|
||||
if (this.asyncLeaks.size) {
|
||||
let out = [];
|
||||
for (const abortable of this.attemptAbortables) {
|
||||
out.push(abortable.id + " " + abortable.stack);
|
||||
for (const leak of this.asyncLeaks) {
|
||||
out.push(leak.id + " " + leak.stack);
|
||||
}
|
||||
throw new Error('Query succeeded, but abortables were not empty (async leak?):\n' + out.join('\n---\n'));
|
||||
throw new Error('Query succeeded, but async leak was detected:\n' + out.join('\n---\n'));
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
// Clean up any lingering long-running functions
|
||||
for (const abortable of this.attemptAbortables) {
|
||||
for (const leak of this.asyncLeaks) {
|
||||
try {
|
||||
abortable.abort();
|
||||
} catch(e) {}
|
||||
leak.cleanup();
|
||||
} catch(e) {
|
||||
if (this.debug) console.log("Error during async cleanup: " + e.stack);
|
||||
}
|
||||
}
|
||||
this.attemptAbortables.clear();
|
||||
this.asyncLeaks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,15 +165,15 @@ class Core extends EventEmitter {
|
|||
else return await resolveStandard(host);
|
||||
}
|
||||
|
||||
addAbortable(fn) {
|
||||
const id = ++this.lastAbortableId;
|
||||
addAsyncLeak(fn) {
|
||||
const id = ++this.lastAsyncLeakId;
|
||||
const stack = new Error().stack;
|
||||
const entry = { id: id, abort: fn, stack: stack };
|
||||
if (this.debug) console.log("Adding abortable: " + id);
|
||||
this.attemptAbortables.add(entry);
|
||||
const entry = { id: id, cleanup: fn, stack: stack };
|
||||
if (this.debug) console.log("Registering async leak: " + id);
|
||||
this.asyncLeaks.add(entry);
|
||||
return () => {
|
||||
if (this.debug) console.log("Removing abortable: " + id);
|
||||
this.attemptAbortables.delete(entry);
|
||||
if (this.debug) console.log("Removing async leak: " + id);
|
||||
this.asyncLeaks.delete(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,7 +213,7 @@ class Core extends EventEmitter {
|
|||
|
||||
const socket = net.connect(port,address);
|
||||
socket.setNoDelay(true);
|
||||
const cancelAbortable = this.addAbortable(() => socket.destroy());
|
||||
const cancelAsyncLeak = this.addAsyncLeak(() => socket.destroy());
|
||||
|
||||
if(this.debug) {
|
||||
console.log(address+':'+port+" TCP Connecting");
|
||||
|
@ -242,21 +245,21 @@ class Core extends EventEmitter {
|
|||
);
|
||||
return await fn(socket);
|
||||
} finally {
|
||||
cancelAbortable();
|
||||
cancelAsyncLeak();
|
||||
socket.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(callback, time) {
|
||||
let cancelAbortable;
|
||||
let cancelAsyncLeak;
|
||||
const onTimeout = () => {
|
||||
cancelAbortable();
|
||||
cancelAsyncLeak();
|
||||
callback();
|
||||
};
|
||||
const timeout = setTimeout(onTimeout, time);
|
||||
cancelAbortable = this.addAbortable(() => clearTimeout(timeout));
|
||||
cancelAsyncLeak = this.addAsyncLeak(() => clearTimeout(timeout));
|
||||
return () => {
|
||||
cancelAbortable();
|
||||
cancelAsyncLeak();
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
}
|
||||
|
@ -351,6 +354,18 @@ class Core extends EventEmitter {
|
|||
_udpIncoming(buffer) {
|
||||
this.udpCallback && this.udpCallback(buffer);
|
||||
}
|
||||
|
||||
request(params) {
|
||||
const promise = requestAsync({
|
||||
...params,
|
||||
timeout: this.options.socketTimeout
|
||||
});
|
||||
const cancelAsyncLeak = this.addAsyncLeak(() => {
|
||||
promise.cancel();
|
||||
});
|
||||
promise.finally(cancelAsyncLeak);
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Core;
|
||||
|
|
|
@ -10,82 +10,80 @@ class Doom3 extends Core {
|
|||
this.hasClanTag = false;
|
||||
this.hasTypeFlag = false;
|
||||
}
|
||||
run(state) {
|
||||
this.udpSend('\xff\xffgetInfo\x00PiNGPoNG\x00', (buffer) => {
|
||||
const reader = this.reader(buffer);
|
||||
|
||||
async run(state) {
|
||||
const body = await this.udpSend('\xff\xffgetInfo\x00PiNGPoNG\x00', packet => {
|
||||
const reader = this.reader(packet);
|
||||
const header = reader.uint(2);
|
||||
if(header !== 0xffff) return;
|
||||
const header2 = reader.string();
|
||||
if(header2 !== 'infoResponse') return;
|
||||
|
||||
if(this.isEtqw) {
|
||||
const taskId = reader.uint(4);
|
||||
}
|
||||
|
||||
const challenge = reader.uint(4);
|
||||
const protoVersion = reader.uint(4);
|
||||
state.raw.protocolVersion = (protoVersion>>16)+'.'+(protoVersion&0xffff);
|
||||
|
||||
if(this.isEtqw) {
|
||||
const size = reader.uint(4);
|
||||
}
|
||||
|
||||
while(!reader.done()) {
|
||||
const key = reader.string();
|
||||
let value = this.stripColors(reader.string());
|
||||
if(key === 'si_map') {
|
||||
value = value.replace('maps/','');
|
||||
value = value.replace('.entities','');
|
||||
}
|
||||
if(!key) break;
|
||||
state.raw[key] = value;
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
while(!reader.done()) {
|
||||
i++;
|
||||
const player = {};
|
||||
player.id = reader.uint(1);
|
||||
if(player.id === 32) break;
|
||||
player.ping = reader.uint(2);
|
||||
if(!this.isEtqw) player.rate = reader.uint(4);
|
||||
player.name = this.stripColors(reader.string());
|
||||
if(this.hasClanTag) {
|
||||
if(this.hasSpaceBeforeClanTag) reader.uint(1);
|
||||
player.clantag = this.stripColors(reader.string());
|
||||
}
|
||||
if(this.hasTypeFlag) player.typeflag = reader.uint(1);
|
||||
|
||||
if(!player.ping || player.typeflag)
|
||||
state.bots.push(player);
|
||||
else
|
||||
state.players.push(player);
|
||||
}
|
||||
|
||||
state.raw.osmask = reader.uint(4);
|
||||
if(this.isEtqw) {
|
||||
state.raw.ranked = reader.uint(1);
|
||||
state.raw.timeleft = reader.uint(4);
|
||||
state.raw.gamestate = reader.uint(1);
|
||||
state.raw.servertype = reader.uint(1);
|
||||
// 0 = regular, 1 = tv
|
||||
if(state.raw.servertype === 0) {
|
||||
state.raw.interestedClients = reader.uint(1);
|
||||
} else if(state.raw.servertype === 1) {
|
||||
state.raw.connectedClients = reader.uint(4);
|
||||
state.raw.maxClients = reader.uint(4);
|
||||
}
|
||||
}
|
||||
|
||||
if(state.raw.si_name) state.name = state.raw.si_name;
|
||||
if(state.raw.si_map) state.map = state.raw.si_map;
|
||||
if(state.raw.si_maxplayers) state.maxplayers = parseInt(state.raw.si_maxplayers);
|
||||
if(state.raw.si_usepass === '1') state.password = true;
|
||||
|
||||
this.finish(state);
|
||||
return true;
|
||||
return reader.rest();
|
||||
});
|
||||
|
||||
const reader = this.reader(body);
|
||||
if(this.isEtqw) {
|
||||
const taskId = reader.uint(4);
|
||||
}
|
||||
|
||||
const challenge = reader.uint(4);
|
||||
const protoVersion = reader.uint(4);
|
||||
state.raw.protocolVersion = (protoVersion>>16)+'.'+(protoVersion&0xffff);
|
||||
|
||||
if(this.isEtqw) {
|
||||
const size = reader.uint(4);
|
||||
}
|
||||
|
||||
while(!reader.done()) {
|
||||
const key = reader.string();
|
||||
let value = this.stripColors(reader.string());
|
||||
if(key === 'si_map') {
|
||||
value = value.replace('maps/','');
|
||||
value = value.replace('.entities','');
|
||||
}
|
||||
if(!key) break;
|
||||
state.raw[key] = value;
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
while(!reader.done()) {
|
||||
i++;
|
||||
const player = {};
|
||||
player.id = reader.uint(1);
|
||||
if(player.id === 32) break;
|
||||
player.ping = reader.uint(2);
|
||||
if(!this.isEtqw) player.rate = reader.uint(4);
|
||||
player.name = this.stripColors(reader.string());
|
||||
if(this.hasClanTag) {
|
||||
if(this.hasSpaceBeforeClanTag) reader.uint(1);
|
||||
player.clantag = this.stripColors(reader.string());
|
||||
}
|
||||
if(this.hasTypeFlag) player.typeflag = reader.uint(1);
|
||||
|
||||
if(!player.ping || player.typeflag)
|
||||
state.bots.push(player);
|
||||
else
|
||||
state.players.push(player);
|
||||
}
|
||||
|
||||
state.raw.osmask = reader.uint(4);
|
||||
if(this.isEtqw) {
|
||||
state.raw.ranked = reader.uint(1);
|
||||
state.raw.timeleft = reader.uint(4);
|
||||
state.raw.gamestate = reader.uint(1);
|
||||
state.raw.servertype = reader.uint(1);
|
||||
// 0 = regular, 1 = tv
|
||||
if(state.raw.servertype === 0) {
|
||||
state.raw.interestedClients = reader.uint(1);
|
||||
} else if(state.raw.servertype === 1) {
|
||||
state.raw.connectedClients = reader.uint(4);
|
||||
state.raw.maxClients = reader.uint(4);
|
||||
}
|
||||
}
|
||||
|
||||
if(state.raw.si_name) state.name = state.raw.si_name;
|
||||
if(state.raw.si_map) state.map = state.raw.si_map;
|
||||
if(state.raw.si_maxplayers) state.maxplayers = parseInt(state.raw.si_maxplayers);
|
||||
if(state.raw.si_usepass === '1') state.password = true;
|
||||
}
|
||||
|
||||
stripColors(str) {
|
||||
|
|
|
@ -6,29 +6,34 @@ class Ffow extends Valve {
|
|||
this.byteorder = 'be';
|
||||
this.legacyChallenge = true;
|
||||
}
|
||||
queryInfo(state,c) {
|
||||
this.sendPacket(0x46,false,'LSQ',0x49, (b) => {
|
||||
const reader = this.reader(b);
|
||||
state.raw.protocol = reader.uint(1);
|
||||
state.name = reader.string();
|
||||
state.map = reader.string();
|
||||
state.raw.mod = reader.string();
|
||||
state.raw.gamemode = reader.string();
|
||||
state.raw.description = reader.string();
|
||||
state.raw.version = reader.string();
|
||||
state.raw.port = reader.uint(2);
|
||||
state.raw.numplayers = reader.uint(1);
|
||||
state.maxplayers = reader.uint(1);
|
||||
state.raw.listentype = String.fromCharCode(reader.uint(1));
|
||||
state.raw.environment = String.fromCharCode(reader.uint(1));
|
||||
state.password = !!reader.uint(1);
|
||||
state.raw.secure = reader.uint(1);
|
||||
state.raw.averagefps = reader.uint(1);
|
||||
state.raw.round = reader.uint(1);
|
||||
state.raw.maxrounds = reader.uint(1);
|
||||
state.raw.timeleft = reader.uint(2);
|
||||
c();
|
||||
});
|
||||
async queryInfo(state) {
|
||||
if(this.debug) console.log("Requesting ffow info ...");
|
||||
const b = await this.sendPacket(
|
||||
0x46,
|
||||
false,
|
||||
'LSQ',
|
||||
0x49
|
||||
);
|
||||
|
||||
const reader = this.reader(b);
|
||||
state.raw.protocol = reader.uint(1);
|
||||
state.name = reader.string();
|
||||
state.map = reader.string();
|
||||
state.raw.mod = reader.string();
|
||||
state.raw.gamemode = reader.string();
|
||||
state.raw.description = reader.string();
|
||||
state.raw.version = reader.string();
|
||||
state.raw.port = reader.uint(2);
|
||||
state.raw.numplayers = reader.uint(1);
|
||||
state.maxplayers = reader.uint(1);
|
||||
state.raw.listentype = String.fromCharCode(reader.uint(1));
|
||||
state.raw.environment = String.fromCharCode(reader.uint(1));
|
||||
state.password = !!reader.uint(1);
|
||||
state.raw.secure = reader.uint(1);
|
||||
state.raw.averagefps = reader.uint(1);
|
||||
state.raw.round = reader.uint(1);
|
||||
state.raw.maxrounds = reader.uint(1);
|
||||
state.raw.timeleft = reader.uint(2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const request = require('request'),
|
||||
Quake2 = require('./quake2');
|
||||
const Quake2 = require('./quake2');
|
||||
|
||||
class FiveM extends Quake2 {
|
||||
constructor() {
|
||||
|
@ -9,43 +8,28 @@ class FiveM extends Quake2 {
|
|||
this.encoding = 'utf8';
|
||||
}
|
||||
|
||||
finish(state) {
|
||||
request({
|
||||
uri: 'http://'+this.options.address+':'+this.options.port_query+'/info.json',
|
||||
timeout: this.options.socketTimeout
|
||||
}, (e,r,body) => {
|
||||
if(e) return this.fatal('HTTP error');
|
||||
let json;
|
||||
try {
|
||||
json = JSON.parse(body);
|
||||
} catch(e) {
|
||||
return this.fatal('Invalid JSON');
|
||||
}
|
||||
async run(state) {
|
||||
await super.run(state);
|
||||
|
||||
state.raw.info = json;
|
||||
|
||||
request({
|
||||
uri: 'http://'+this.options.address+':'+this.options.port_query+'/players.json',
|
||||
timeout: this.options.socketTimeout
|
||||
}, (e,r,body) => {
|
||||
if(e) return this.fatal('HTTP error');
|
||||
let json;
|
||||
try {
|
||||
json = JSON.parse(body);
|
||||
} catch(e) {
|
||||
return this.fatal('Invalid JSON');
|
||||
}
|
||||
|
||||
state.raw.players = json;
|
||||
|
||||
state.players = [];
|
||||
for (const player of json) {
|
||||
state.players.push({name:player.name, ping:player.ping});
|
||||
}
|
||||
|
||||
super.finish(state);
|
||||
{
|
||||
const raw = await this.request({
|
||||
uri: 'http://' + this.options.address + ':' + this.options.port_query + '/info.json'
|
||||
});
|
||||
});
|
||||
const json = JSON.parse(raw);
|
||||
state.raw.info = json;
|
||||
}
|
||||
|
||||
{
|
||||
const raw = await this.request({
|
||||
uri: 'http://' + this.options.address + ':' + this.options.port_query + '/players.json'
|
||||
});
|
||||
const json = JSON.parse(raw);
|
||||
state.raw.players = json;
|
||||
state.players = [];
|
||||
for (const player of json) {
|
||||
state.players.push({name: player.name, ping: player.ping});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,68 +1,57 @@
|
|||
const async = require('async'),
|
||||
Core = require('./core');
|
||||
const Core = require('./core');
|
||||
|
||||
class Gamespy1 extends Core {
|
||||
constructor() {
|
||||
super();
|
||||
this.sessionId = 1;
|
||||
this.encoding = 'latin1';
|
||||
this.byteorder = 'be';
|
||||
}
|
||||
|
||||
run(state) {
|
||||
async.series([
|
||||
(c) => {
|
||||
this.sendPacket('info', (data) => {
|
||||
state.raw = data;
|
||||
if('hostname' in state.raw) state.name = state.raw.hostname;
|
||||
if('mapname' in state.raw) state.map = state.raw.mapname;
|
||||
if(this.trueTest(state.raw.password)) state.password = true;
|
||||
if('maxplayers' in state.raw) state.maxplayers = parseInt(state.raw.maxplayers);
|
||||
c();
|
||||
});
|
||||
},
|
||||
(c) => {
|
||||
this.sendPacket('rules', (data) => {
|
||||
state.raw.rules = data;
|
||||
c();
|
||||
});
|
||||
},
|
||||
(c) => {
|
||||
this.sendPacket('players', (data) => {
|
||||
const players = {};
|
||||
const teams = {};
|
||||
for(const ident of Object.keys(data)) {
|
||||
const split = ident.split('_');
|
||||
let key = split[0];
|
||||
const id = split[1];
|
||||
let value = data[ident];
|
||||
async run(state) {
|
||||
{
|
||||
const data = await this.sendPacket('info');
|
||||
state.raw = data;
|
||||
if ('hostname' in state.raw) state.name = state.raw.hostname;
|
||||
if ('mapname' in state.raw) state.map = state.raw.mapname;
|
||||
if (this.trueTest(state.raw.password)) state.password = true;
|
||||
if ('maxplayers' in state.raw) state.maxplayers = parseInt(state.raw.maxplayers);
|
||||
}
|
||||
{
|
||||
const data = await this.sendPacket('rules');
|
||||
state.raw.rules = data;
|
||||
}
|
||||
{
|
||||
const data = await this.sendPacket('players');
|
||||
const players = {};
|
||||
const teams = {};
|
||||
for (const ident of Object.keys(data)) {
|
||||
const split = ident.split('_');
|
||||
let key = split[0];
|
||||
const id = split[1];
|
||||
let value = data[ident];
|
||||
|
||||
if(key === 'teamname') {
|
||||
teams[id] = value;
|
||||
} else {
|
||||
if(!(id in players)) players[id] = {};
|
||||
if(key === 'playername') key = 'name';
|
||||
else if(key === 'team') value = parseInt(value);
|
||||
else if(key === 'score' || key === 'ping' || key === 'deaths') value = parseInt(value);
|
||||
players[id][key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
state.raw.teams = teams;
|
||||
for(const id of Object.keys(players)) {
|
||||
state.players.push(players[id]);
|
||||
}
|
||||
this.finish(state);
|
||||
});
|
||||
if (key === 'teamname') {
|
||||
teams[id] = value;
|
||||
} else {
|
||||
if (!(id in players)) players[id] = {};
|
||||
if (key === 'playername') key = 'name';
|
||||
else if (key === 'team') value = parseInt(value);
|
||||
else if (key === 'score' || key === 'ping' || key === 'deaths') value = parseInt(value);
|
||||
players[id][key] = value;
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
state.raw.teams = teams;
|
||||
for (const id of Object.keys(players)) {
|
||||
state.players.push(players[id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sendPacket(type,callback) {
|
||||
async sendPacket(type) {
|
||||
const queryId = '';
|
||||
const output = {};
|
||||
this.udpSend('\\'+type+'\\', (buffer) => {
|
||||
return await this.udpSend('\\'+type+'\\', buffer => {
|
||||
const reader = this.reader(buffer);
|
||||
const str = reader.string({length:buffer.length});
|
||||
const split = str.split('\\');
|
||||
|
@ -79,8 +68,7 @@ class Gamespy1 extends Core {
|
|||
if('final' in output) {
|
||||
delete output.final;
|
||||
delete output.queryid;
|
||||
callback(output);
|
||||
return true;
|
||||
return output;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,53 +3,71 @@ const Core = require('./core');
|
|||
class Gamespy2 extends Core {
|
||||
constructor() {
|
||||
super();
|
||||
this.sessionId = 1;
|
||||
this.encoding = 'latin1';
|
||||
this.byteorder = 'be';
|
||||
}
|
||||
|
||||
run(state) {
|
||||
const request = Buffer.from([0xfe,0xfd,0x00,0x00,0x00,0x00,0x01,0xff,0xff,0xff]);
|
||||
const packets = [];
|
||||
this.udpSend(request,
|
||||
(buffer) => {
|
||||
if(packets.length && buffer.readUInt8(0) === 0)
|
||||
buffer = buffer.slice(1);
|
||||
packets.push(buffer);
|
||||
},
|
||||
() => {
|
||||
const buffer = Buffer.concat(packets);
|
||||
const reader = this.reader(buffer);
|
||||
const header = reader.uint(1);
|
||||
if(header !== 0) return;
|
||||
const pingId = reader.uint(4);
|
||||
if(pingId !== 1) return;
|
||||
|
||||
while(!reader.done()) {
|
||||
const key = reader.string();
|
||||
const value = reader.string();
|
||||
if(!key) break;
|
||||
state.raw[key] = value;
|
||||
}
|
||||
|
||||
if('hostname' in state.raw) state.name = state.raw.hostname;
|
||||
if('mapname' in state.raw) state.map = state.raw.mapname;
|
||||
if(this.trueTest(state.raw.password)) state.password = true;
|
||||
if('maxplayers' in state.raw) state.maxplayers = parseInt(state.raw.maxplayers);
|
||||
|
||||
state.players = this.readFieldData(reader);
|
||||
state.raw.teams = this.readFieldData(reader);
|
||||
|
||||
this.finish(state);
|
||||
return true;
|
||||
async run(state) {
|
||||
// Parse info
|
||||
{
|
||||
const body = await this.sendPacket([0xff, 0, 0]);
|
||||
const reader = this.reader(body);
|
||||
while (!reader.done()) {
|
||||
const key = reader.string();
|
||||
const value = reader.string();
|
||||
if (!key) break;
|
||||
state.raw[key] = value;
|
||||
}
|
||||
);
|
||||
if('hostname' in state.raw) state.name = state.raw.hostname;
|
||||
if('mapname' in state.raw) state.map = state.raw.mapname;
|
||||
if(this.trueTest(state.raw.password)) state.password = true;
|
||||
if('maxplayers' in state.raw) state.maxplayers = parseInt(state.raw.maxplayers);
|
||||
}
|
||||
|
||||
// Parse players
|
||||
{
|
||||
const body = await this.sendPacket([0, 0xff, 0]);
|
||||
const reader = this.reader(body);
|
||||
state.players = this.readFieldData(reader);
|
||||
}
|
||||
|
||||
// Parse teams
|
||||
{
|
||||
const body = await this.sendPacket([0, 0, 0xff]);
|
||||
const reader = this.reader(body);
|
||||
state.raw.teams = this.readFieldData(reader);
|
||||
}
|
||||
}
|
||||
|
||||
async sendPacket(type) {
|
||||
const request = Buffer.concat([
|
||||
Buffer.from([0xfe,0xfd,0x00]), // gamespy2
|
||||
Buffer.from([0x00,0x00,0x00,0x01]), // ping ID
|
||||
Buffer.from(type)
|
||||
]);
|
||||
return await this.udpSend(request, buffer => {
|
||||
const reader = this.reader(buffer);
|
||||
const header = reader.uint(1);
|
||||
if (header !== 0) return;
|
||||
const pingId = reader.uint(4);
|
||||
if (pingId !== 1) return;
|
||||
return reader.rest();
|
||||
});
|
||||
}
|
||||
|
||||
readFieldData(reader) {
|
||||
const count = reader.uint(1);
|
||||
// count is unreliable (often it's wrong), so we don't use it.
|
||||
// read until we hit an empty first field string
|
||||
const zero = reader.uint(1); // always 0
|
||||
const count = reader.uint(1); // number of rows in this data
|
||||
|
||||
// some games omit the count byte entirely if it's 0 or at random (like americas army)
|
||||
// Luckily, count should always be <64, and ascii characters will typically be >64,
|
||||
// so we can detect this.
|
||||
if (count > 64) {
|
||||
reader.skip(-1);
|
||||
if (this.debug) console.log("Detected missing count byte, rewinding by 1");
|
||||
} else {
|
||||
if (this.debug) console.log("Detected row count: " + count);
|
||||
}
|
||||
|
||||
if(this.debug) console.log("Reading fields, starting at: "+reader.rest());
|
||||
|
||||
|
@ -57,11 +75,12 @@ class Gamespy2 extends Core {
|
|||
while(!reader.done()) {
|
||||
let field = reader.string();
|
||||
if(!field) break;
|
||||
if(field.charCodeAt(0) <= 2) field = field.substring(1);
|
||||
fields.push(field);
|
||||
if(this.debug) console.log("field:"+field);
|
||||
}
|
||||
|
||||
if (!fields.length) return [];
|
||||
|
||||
const units = [];
|
||||
outer: while(!reader.done()) {
|
||||
const unit = {};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const async = require('async'),
|
||||
Core = require('./core');
|
||||
const Core = require('./core'),
|
||||
HexUtil = require('../lib/HexUtil');
|
||||
|
||||
class Gamespy3 extends Core {
|
||||
constructor() {
|
||||
|
@ -12,143 +12,129 @@ class Gamespy3 extends Core {
|
|||
this.isJc2mp = false;
|
||||
}
|
||||
|
||||
run(state) {
|
||||
let challenge;
|
||||
async run(state) {
|
||||
let challenge = null;
|
||||
if (!this.noChallenge) {
|
||||
const buffer = await this.sendPacket(9, false, false, false);
|
||||
const reader = this.reader(buffer);
|
||||
challenge = parseInt(reader.string());
|
||||
}
|
||||
|
||||
let requestPayload;
|
||||
if(this.isJc2mp) {
|
||||
// they completely alter the protocol. because why not.
|
||||
requestPayload = Buffer.from([0xff,0xff,0xff,0x02]);
|
||||
} else {
|
||||
requestPayload = Buffer.from([0xff,0xff,0xff,0x01]);
|
||||
}
|
||||
/** @type Buffer[] */
|
||||
let packets;
|
||||
const packets = await this.sendPacket(0,challenge,requestPayload,true);
|
||||
|
||||
async.series([
|
||||
(c) => {
|
||||
if(this.noChallenge) return c();
|
||||
this.sendPacket(9,false,false,false,(buffer) => {
|
||||
const reader = this.reader(buffer);
|
||||
challenge = parseInt(reader.string());
|
||||
c();
|
||||
});
|
||||
},
|
||||
(c) => {
|
||||
let requestPayload;
|
||||
if(this.isJc2mp) {
|
||||
// they completely alter the protocol. because why not.
|
||||
requestPayload = Buffer.from([0xff,0xff,0xff,0x02]);
|
||||
} else {
|
||||
requestPayload = Buffer.from([0xff,0xff,0xff,0x01]);
|
||||
}
|
||||
// iterate over the received packets
|
||||
// the first packet will start off with k/v pairs, followed with data fields
|
||||
// the following packets will only have data fields
|
||||
state.raw.playerTeamInfo = {};
|
||||
|
||||
this.sendPacket(0,challenge,requestPayload,true,(b) => {
|
||||
packets = b;
|
||||
c();
|
||||
});
|
||||
},
|
||||
(c) => {
|
||||
// iterate over the received packets
|
||||
// the first packet will start off with k/v pairs, followed with data fields
|
||||
// the following packets will only have data fields
|
||||
for(let iPacket = 0; iPacket < packets.length; iPacket++) {
|
||||
const packet = packets[iPacket];
|
||||
const reader = this.reader(packet);
|
||||
|
||||
state.raw.playerTeamInfo = {};
|
||||
|
||||
for(let iPacket = 0; iPacket < packets.length; iPacket++) {
|
||||
const packet = packets[iPacket];
|
||||
const reader = this.reader(packet);
|
||||
|
||||
if(this.debug) {
|
||||
console.log("+++"+packet.toString('hex'));
|
||||
console.log(":::"+packet.toString('ascii'));
|
||||
}
|
||||
|
||||
// Parse raw server key/values
|
||||
|
||||
if(iPacket === 0) {
|
||||
while(!reader.done()) {
|
||||
const key = reader.string();
|
||||
if(!key) break;
|
||||
let value = reader.string();
|
||||
|
||||
// reread the next line if we hit the weird ut3 bug
|
||||
if(value === 'p1073741829') value = reader.string();
|
||||
|
||||
state.raw[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse player, team, item array state
|
||||
|
||||
if(this.isJc2mp) {
|
||||
state.raw.numPlayers2 = reader.uint(2);
|
||||
while(!reader.done()) {
|
||||
const player = {};
|
||||
player.name = reader.string();
|
||||
player.steamid = reader.string();
|
||||
player.ping = reader.uint(2);
|
||||
state.players.push(player);
|
||||
}
|
||||
} else {
|
||||
let firstMode = true;
|
||||
while(!reader.done()) {
|
||||
let mode = reader.string();
|
||||
if(mode.charCodeAt(0) <= 2) mode = mode.substring(1);
|
||||
if(!mode) continue;
|
||||
let offset = 0;
|
||||
if(iPacket !== 0 && firstMode) offset = reader.uint(1);
|
||||
reader.skip(1);
|
||||
firstMode = false;
|
||||
|
||||
const modeSplit = mode.split('_');
|
||||
const modeName = modeSplit[0];
|
||||
const modeType = modeSplit.length > 1 ? modeSplit[1] : 'no_';
|
||||
|
||||
if(!(modeType in state.raw.playerTeamInfo)) {
|
||||
state.raw.playerTeamInfo[modeType] = [];
|
||||
}
|
||||
const store = state.raw.playerTeamInfo[modeType];
|
||||
|
||||
while(!reader.done()) {
|
||||
const item = reader.string();
|
||||
if(!item) break;
|
||||
|
||||
while(store.length <= offset) { store.push({}); }
|
||||
store[offset][modeName] = item;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c();
|
||||
},
|
||||
|
||||
(c) => {
|
||||
// Turn all that raw state into something useful
|
||||
|
||||
if('hostname' in state.raw) state.name = state.raw.hostname;
|
||||
else if('servername' in state.raw) state.name = state.raw.servername;
|
||||
if('mapname' in state.raw) state.map = state.raw.mapname;
|
||||
if(state.raw.password === '1') state.password = true;
|
||||
if('maxplayers' in state.raw) state.maxplayers = parseInt(state.raw.maxplayers);
|
||||
|
||||
if('' in state.raw.playerTeamInfo) {
|
||||
for (const playerInfo of state.raw.playerTeamInfo['']) {
|
||||
const player = {};
|
||||
for(const from of Object.keys(playerInfo)) {
|
||||
let key = from;
|
||||
let value = playerInfo[from];
|
||||
|
||||
if(key === 'player') key = 'name';
|
||||
if(key === 'score' || key === 'ping' || key === 'team' || key === 'deaths' || key === 'pid') value = parseInt(value);
|
||||
player[key] = value;
|
||||
}
|
||||
state.players.push(player);
|
||||
}
|
||||
}
|
||||
|
||||
this.finish(state);
|
||||
if(this.debug) {
|
||||
console.log("Parsing packet #" + iPacket);
|
||||
console.log(HexUtil.debugDump(packet));
|
||||
}
|
||||
]);
|
||||
|
||||
// Parse raw server key/values
|
||||
|
||||
if(iPacket === 0) {
|
||||
while(!reader.done()) {
|
||||
const key = reader.string();
|
||||
if(!key) break;
|
||||
|
||||
let value = reader.string();
|
||||
while(value.match(/^p[0-9]+$/)) {
|
||||
// fix a weird ut3 bug where some keys don't have values
|
||||
value = reader.string();
|
||||
}
|
||||
|
||||
state.raw[key] = value;
|
||||
if (this.debug) console.log(key + " = " + value);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse player, team, item array state
|
||||
|
||||
if(this.isJc2mp) {
|
||||
state.raw.numPlayers2 = reader.uint(2);
|
||||
while(!reader.done()) {
|
||||
const player = {};
|
||||
player.name = reader.string();
|
||||
player.steamid = reader.string();
|
||||
player.ping = reader.uint(2);
|
||||
state.players.push(player);
|
||||
}
|
||||
} else {
|
||||
let firstMode = true;
|
||||
while(!reader.done()) {
|
||||
if (reader.uint(1) <= 2) continue;
|
||||
reader.skip(-1);
|
||||
let fieldId = reader.string();
|
||||
if(!fieldId) continue;
|
||||
const fieldIdSplit = fieldId.split('_');
|
||||
const fieldName = fieldIdSplit[0];
|
||||
const itemType = fieldIdSplit.length > 1 ? fieldIdSplit[1] : 'no_';
|
||||
|
||||
if(!(itemType in state.raw.playerTeamInfo)) {
|
||||
state.raw.playerTeamInfo[itemType] = [];
|
||||
}
|
||||
const items = state.raw.playerTeamInfo[itemType];
|
||||
|
||||
let offset = reader.uint(1);
|
||||
firstMode = false;
|
||||
|
||||
if (this.debug) {
|
||||
console.log("Parsing new field: itemType=" + itemType + " fieldName=" + fieldName + " startOffset=" + offset);
|
||||
}
|
||||
|
||||
while(!reader.done()) {
|
||||
const item = reader.string();
|
||||
if(!item) break;
|
||||
|
||||
while(items.length <= offset) { items.push({}); }
|
||||
items[offset][fieldName] = item;
|
||||
if (this.debug) console.log("* " + item);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Turn all that raw state into something useful
|
||||
|
||||
if('hostname' in state.raw) state.name = state.raw.hostname;
|
||||
else if('servername' in state.raw) state.name = state.raw.servername;
|
||||
if('mapname' in state.raw) state.map = state.raw.mapname;
|
||||
if(state.raw.password === '1') state.password = true;
|
||||
if('maxplayers' in state.raw) state.maxplayers = parseInt(state.raw.maxplayers);
|
||||
|
||||
if('' in state.raw.playerTeamInfo) {
|
||||
for (const playerInfo of state.raw.playerTeamInfo['']) {
|
||||
const player = {};
|
||||
for(const from of Object.keys(playerInfo)) {
|
||||
let key = from;
|
||||
let value = playerInfo[from];
|
||||
|
||||
if(key === 'player') key = 'name';
|
||||
if(key === 'score' || key === 'ping' || key === 'team' || key === 'deaths' || key === 'pid') value = parseInt(value);
|
||||
player[key] = value;
|
||||
}
|
||||
state.players.push(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sendPacket(type,challenge,payload,assemble,c) {
|
||||
const challengeLength = (this.noChallenge || challenge === false) ? 0 : 4;
|
||||
async sendPacket(type,challenge,payload,assemble) {
|
||||
const challengeLength = challenge === null ? 0 : 4;
|
||||
const payloadLength = payload ? payload.length : 0;
|
||||
|
||||
const b = Buffer.alloc(7 + challengeLength + payloadLength);
|
||||
|
@ -161,7 +147,7 @@ class Gamespy3 extends Core {
|
|||
|
||||
let numPackets = 0;
|
||||
const packets = {};
|
||||
this.udpSend(b,(buffer) => {
|
||||
return this.udpSend(b,(buffer) => {
|
||||
const reader = this.reader(buffer);
|
||||
const iType = reader.uint(1);
|
||||
if(iType !== type) return;
|
||||
|
@ -169,14 +155,12 @@ class Gamespy3 extends Core {
|
|||
if(iSessionId !== this.sessionId) return;
|
||||
|
||||
if(!assemble) {
|
||||
c(reader.rest());
|
||||
return true;
|
||||
return reader.rest();
|
||||
}
|
||||
if(this.useOnlySingleSplit) {
|
||||
// has split headers, but they are worthless and only one packet is used
|
||||
reader.skip(11);
|
||||
c([reader.rest()]);
|
||||
return true;
|
||||
return [reader.rest()];
|
||||
}
|
||||
|
||||
reader.skip(9); // filler data -- usually set to 'splitnum\0'
|
||||
|
@ -199,13 +183,11 @@ class Gamespy3 extends Core {
|
|||
const list = [];
|
||||
for(let i = 0; i < numPackets; i++) {
|
||||
if(!(i in packets)) {
|
||||
this.fatal('Missing packet #'+i);
|
||||
return true;
|
||||
throw new Error('Missing packet #'+i);
|
||||
}
|
||||
list.push(packets[i]);
|
||||
}
|
||||
c(list);
|
||||
return true;
|
||||
return list;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,10 @@ class Jc2mp extends Gamespy3 {
|
|||
constructor() {
|
||||
super();
|
||||
this.useOnlySingleSplit = true;
|
||||
this.isJc2mp = true;
|
||||
}
|
||||
finalizeState(state) {
|
||||
super.finalizeState(state);
|
||||
async run(state) {
|
||||
super.run(state);
|
||||
if(!state.players.length && parseInt(state.raw.numplayers)) {
|
||||
for(let i = 0; i < parseInt(state.raw.numplayers); i++) {
|
||||
state.players.push({});
|
||||
|
|
|
@ -10,79 +10,76 @@ class Quake2 extends Core {
|
|||
this.isQuake1 = false;
|
||||
}
|
||||
|
||||
run(state) {
|
||||
this.udpSend('\xff\xff\xff\xff'+this.sendHeader+'\x00', (buffer) => {
|
||||
const reader = this.reader(buffer);
|
||||
|
||||
const header = reader.string({length:4,encoding:'latin1'});
|
||||
if(header !== '\xff\xff\xff\xff') return;
|
||||
|
||||
let response;
|
||||
if(this.isQuake1) {
|
||||
response = reader.string({length:this.responseHeader.length});
|
||||
async run(state) {
|
||||
const body = await this.udpSend('\xff\xff\xff\xff'+this.sendHeader+'\x00', packet => {
|
||||
const reader = this.reader(packet);
|
||||
const header = reader.string({length: 4, encoding: 'latin1'});
|
||||
if (header !== '\xff\xff\xff\xff') return;
|
||||
let type;
|
||||
if (this.isQuake1) {
|
||||
type = reader.string({length: this.responseHeader.length});
|
||||
} else {
|
||||
response = reader.string({encoding:'latin1'});
|
||||
type = reader.string({encoding: 'latin1'});
|
||||
}
|
||||
if(response !== this.responseHeader) return;
|
||||
|
||||
const info = reader.string().split('\\');
|
||||
if(info[0] === '') info.shift();
|
||||
|
||||
while(true) {
|
||||
const key = info.shift();
|
||||
const value = info.shift();
|
||||
if(typeof value === 'undefined') break;
|
||||
state.raw[key] = value;
|
||||
}
|
||||
|
||||
while(!reader.done()) {
|
||||
const line = reader.string();
|
||||
if(!line || line.charAt(0) === '\0') break;
|
||||
|
||||
const args = [];
|
||||
const split = line.split('"');
|
||||
split.forEach((part,i) => {
|
||||
const inQuote = (i%2 === 1);
|
||||
if(inQuote) {
|
||||
args.push(part);
|
||||
} else {
|
||||
const splitSpace = part.split(' ');
|
||||
for (const subpart of splitSpace) {
|
||||
if(subpart) args.push(subpart);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const player = {};
|
||||
if(this.isQuake1) {
|
||||
player.id = parseInt(args.shift());
|
||||
player.score = parseInt(args.shift());
|
||||
player.time = parseInt(args.shift());
|
||||
player.ping = parseInt(args.shift());
|
||||
player.name = args.shift();
|
||||
player.skin = args.shift();
|
||||
player.color1 = parseInt(args.shift());
|
||||
player.color2 = parseInt(args.shift());
|
||||
} else {
|
||||
player.frags = parseInt(args.shift());
|
||||
player.ping = parseInt(args.shift());
|
||||
player.name = args.shift() || '';
|
||||
player.address = args.shift() || '';
|
||||
}
|
||||
|
||||
(player.ping ? state.players : state.bots).push(player);
|
||||
}
|
||||
|
||||
if('g_needpass' in state.raw) state.password = state.raw.g_needpass;
|
||||
if('mapname' in state.raw) state.map = state.raw.mapname;
|
||||
if('sv_maxclients' in state.raw) state.maxplayers = state.raw.sv_maxclients;
|
||||
if('maxclients' in state.raw) state.maxplayers = state.raw.maxclients;
|
||||
if('sv_hostname' in state.raw) state.name = state.raw.sv_hostname;
|
||||
if('hostname' in state.raw) state.name = state.raw.hostname;
|
||||
|
||||
this.finish(state);
|
||||
return true;
|
||||
if (type !== this.responseHeader) return;
|
||||
return reader.rest();
|
||||
});
|
||||
|
||||
const reader = this.reader(body);
|
||||
const info = reader.string().split('\\');
|
||||
if(info[0] === '') info.shift();
|
||||
|
||||
while(true) {
|
||||
const key = info.shift();
|
||||
const value = info.shift();
|
||||
if(typeof value === 'undefined') break;
|
||||
state.raw[key] = value;
|
||||
}
|
||||
|
||||
while(!reader.done()) {
|
||||
const line = reader.string();
|
||||
if(!line || line.charAt(0) === '\0') break;
|
||||
|
||||
const args = [];
|
||||
const split = line.split('"');
|
||||
split.forEach((part,i) => {
|
||||
const inQuote = (i%2 === 1);
|
||||
if(inQuote) {
|
||||
args.push(part);
|
||||
} else {
|
||||
const splitSpace = part.split(' ');
|
||||
for (const subpart of splitSpace) {
|
||||
if(subpart) args.push(subpart);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const player = {};
|
||||
if(this.isQuake1) {
|
||||
player.id = parseInt(args.shift());
|
||||
player.score = parseInt(args.shift());
|
||||
player.time = parseInt(args.shift());
|
||||
player.ping = parseInt(args.shift());
|
||||
player.name = args.shift();
|
||||
player.skin = args.shift();
|
||||
player.color1 = parseInt(args.shift());
|
||||
player.color2 = parseInt(args.shift());
|
||||
} else {
|
||||
player.frags = parseInt(args.shift());
|
||||
player.ping = parseInt(args.shift());
|
||||
player.name = args.shift() || '';
|
||||
player.address = args.shift() || '';
|
||||
}
|
||||
|
||||
(player.ping ? state.players : state.bots).push(player);
|
||||
}
|
||||
|
||||
if('g_needpass' in state.raw) state.password = state.raw.g_needpass;
|
||||
if('mapname' in state.raw) state.map = state.raw.mapname;
|
||||
if('sv_maxclients' in state.raw) state.maxplayers = state.raw.sv_maxclients;
|
||||
if('maxclients' in state.raw) state.maxplayers = state.raw.maxclients;
|
||||
if('sv_hostname' in state.raw) state.name = state.raw.sv_hostname;
|
||||
if('hostname' in state.raw) state.name = state.raw.hostname;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
const Gamespy3 = require('./gamespy3');
|
||||
|
||||
class Ut3 extends Gamespy3 {
|
||||
finalizeState(state) {
|
||||
super.finalizeState(state);
|
||||
async run(state) {
|
||||
await super.run(state);
|
||||
|
||||
this.translate(state.raw,{
|
||||
'mapname': false,
|
||||
|
|
|
@ -36,6 +36,7 @@ class Valve extends Core {
|
|||
}
|
||||
|
||||
async queryInfo(state) {
|
||||
if(this.debug) console.log("Requesting info ...");
|
||||
const b = await this.sendPacket(
|
||||
0x54,
|
||||
false,
|
||||
|
@ -127,6 +128,7 @@ class Valve extends Core {
|
|||
if(this.legacyChallenge) {
|
||||
// sendPacket will catch the response packet and
|
||||
// save the challenge for us
|
||||
if(this.debug) console.log("Requesting legacy challenge key ...");
|
||||
await this.sendPacket(
|
||||
0x57,
|
||||
false,
|
||||
|
@ -144,6 +146,7 @@ class Valve extends Core {
|
|||
// Ignore timeouts in only this case
|
||||
const allowTimeout = state.raw.steamappid === 730;
|
||||
|
||||
if(this.debug) console.log("Requesting player list ...");
|
||||
const b = await this.sendPacket(
|
||||
0x55,
|
||||
true,
|
||||
|
@ -177,6 +180,7 @@ class Valve extends Core {
|
|||
|
||||
async queryRules(state) {
|
||||
state.raw.rules = {};
|
||||
if(this.debug) console.log("Requesting rules ...");
|
||||
const b = await this.sendPacket(0x56,true,null,0x45,true);
|
||||
if (b === null) return; // timed out - the server probably just has rules disabled
|
||||
|
||||
|
@ -248,34 +252,37 @@ class Valve extends Core {
|
|||
allowTimeout
|
||||
) {
|
||||
for (let keyRetry = 0; keyRetry < 3; keyRetry++) {
|
||||
let retryQuery = false;
|
||||
let requestKeyChanged = false;
|
||||
const response = await this.sendPacketRaw(
|
||||
type, sendChallenge, payload,
|
||||
(payload) => {
|
||||
const reader = this.reader(payload);
|
||||
const type = reader.uint(1);
|
||||
if (this.debug) console.log("Received " + type.toString(16) + " expected " + expect.toString(16));
|
||||
if (type === 0x41) {
|
||||
const key = reader.uint(4);
|
||||
if (this._challenge !== key) {
|
||||
if (this.debug) console.log('Received new challenge key: ' + key);
|
||||
this._challenge = key;
|
||||
retryQuery = true;
|
||||
if (keyRetry === 0 && sendChallenge) {
|
||||
if (this.debug) console.log('Restarting query');
|
||||
return null;
|
||||
if (sendChallenge) {
|
||||
if (this.debug) console.log('Challenge key changed -- allowing query retry if needed');
|
||||
requestKeyChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.debug) console.log("Received " + type.toString(16) + " expected " + expect.toString(16));
|
||||
if (type === expect) {
|
||||
return reader.rest();
|
||||
} else if (requestKeyChanged) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
() => {
|
||||
if (allowTimeout) return null;
|
||||
}
|
||||
);
|
||||
if (!retryQuery) return response;
|
||||
if (!requestKeyChanged) {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
throw new Error('Received too many challenge key responses');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue