mirror of
https://github.com/billsonnn/nitro-converter.git
synced 2024-11-26 17:30:52 +01:00
Initial
This commit is contained in:
commit
5488f25310
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
node_modules/
|
||||
dist/
|
||||
.idea
|
||||
rare_dragonlamp
|
19
config.ini
Normal file
19
config.ini
Normal file
@ -0,0 +1,19 @@
|
||||
output.folder.furniture=/home/user/WebstormProjects/sites/assets.nitro.se/game/dcr/endrit/furniture/
|
||||
output.folder.figure=/home/user/WebstormProjects/sites/assets.nitro.se/game/gordon/figure-new1/
|
||||
output.folder.effect=/home/user/WebstormProjects/sites/assets.nitro.se/game/effect/
|
||||
output.folder.pet=/home/user/WebstormProjects/sites/assets.nitro.se/game/pet/
|
||||
furnidata.url=http://assets.nitro.se/game/gamedata/furnidata-entry.xml
|
||||
figuremap.url=http://assets.nitro.se/game/gordon/PRODUCTION-201701242205-837386173/figuremap.xml
|
||||
effectmap.url=http://assets.nitro.se/game/gordon/PRODUCTION-201701242205-837386173/effectmap.xml
|
||||
external_vars.url=http://assets.nitro.se/game/gamedata/external_variables.txt
|
||||
dynamic.download.url.furniture=/home/user/WebstormProjects/sites/assets.nitro.se/game/dcr/endrit/hof_furni/%className%.swf
|
||||
dynamic.download.url.figure=/home/user/WebstormProjects/sites/assets.nitro.se/game/gordon/PRODUCTION-201701242205-837386173/%className%.swf
|
||||
dynamic.download.url.effect=http://assets.nitro.se/game/gordon/PRODUCTION-201701242205-837386173/%className%.swf
|
||||
dynamic.download.url.pet=http://assets.nitro.se/game/gordon/PRODUCTION-201701242205-837386173/%className%.swf
|
||||
convert.furniture=0
|
||||
convert.figure=1
|
||||
convert.effect=1
|
||||
convert.pet=1
|
||||
figure.rotation.enabled=0
|
||||
figure.skip.non-existing.asset.images=0
|
||||
convert.threads=4
|
775
package-lock.json
generated
Normal file
775
package-lock.json
generated
Normal file
@ -0,0 +1,775 @@
|
||||
{
|
||||
"name": "nitroassetconverter",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@jvitela/mustache-wax": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@jvitela/mustache-wax/-/mustache-wax-1.0.3.tgz",
|
||||
"integrity": "sha512-5M5p8d9YQwEDSa0oLoeCZ8ECiM2ZJLKxI/D0pDByiNBJw+4Tizjk/NMIjGx7IoJOGBnWcfHX3Pwd6m/MpMHoGA=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "14.14.22",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.22.tgz",
|
||||
"integrity": "sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw=="
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"amdefine": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.1.tgz",
|
||||
"integrity": "sha1-tcdcUyBS3M1qOcAGTHcsjVegbNI="
|
||||
},
|
||||
"any-promise": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
|
||||
"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
|
||||
},
|
||||
"asn1": {
|
||||
"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",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
|
||||
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"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.3"
|
||||
}
|
||||
},
|
||||
"bignumber.js": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.4.0.tgz",
|
||||
"integrity": "sha1-g4qZLan51zfg9LLbC+YrsJ3Qxeg="
|
||||
},
|
||||
"bl": {
|
||||
"version": "0.9.5",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz",
|
||||
"integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=",
|
||||
"requires": {
|
||||
"readable-stream": "~1.0.26"
|
||||
}
|
||||
},
|
||||
"bmp-js": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.0.3.tgz",
|
||||
"integrity": "sha1-ZBE+nHzxICs3btYHvzBibr5XsYo="
|
||||
},
|
||||
"buffer-crc32": {
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
|
||||
},
|
||||
"buffer-equal": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz",
|
||||
"integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs="
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.0.0.tgz",
|
||||
"integrity": "sha1-0bhvkB+LZL2UG96tr5JFMDk76Sg="
|
||||
},
|
||||
"concat-frames": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/concat-frames/-/concat-frames-1.0.3.tgz",
|
||||
"integrity": "sha1-z+moFvJce3WWPZn+8vSqBFj7+Zs=",
|
||||
"requires": {
|
||||
"pixel-stream": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"dom-walk": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
|
||||
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"es6-promise": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
||||
"integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM="
|
||||
},
|
||||
"exif-parser": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
|
||||
"integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI="
|
||||
},
|
||||
"exif-reader": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/exif-reader/-/exif-reader-1.0.3.tgz",
|
||||
"integrity": "sha512-tWMBj1+9jUSibgR/kv/GQ/fkR0biaN9GEZ5iPdf7jFeH//d2bSzgPoaWf1OfMv4MXFD4upwvpCCyeMvSyLWSfA=="
|
||||
},
|
||||
"extend": {
|
||||
"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",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||
},
|
||||
"fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
|
||||
},
|
||||
"file-type": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
|
||||
"integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek="
|
||||
},
|
||||
"forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||
},
|
||||
"form-data": {
|
||||
"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.12"
|
||||
}
|
||||
},
|
||||
"free-tex-packer-core": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/free-tex-packer-core/-/free-tex-packer-core-0.3.2.tgz",
|
||||
"integrity": "sha512-CauShorQ77Pgm+u2YalXX6HyR0rnkuccS3lIKCZpnBeAjcUV6SXCwswUGS8cbrvS5/dIwM5UeqFu02X86PPMkg==",
|
||||
"requires": {
|
||||
"@jvitela/mustache-wax": "^1.0.1",
|
||||
"jimp": "^0.2.28",
|
||||
"maxrects-packer": "^2.5.0",
|
||||
"mustache": "^2.3.0",
|
||||
"tinify": "^1.5.0"
|
||||
}
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"global": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
|
||||
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
|
||||
"requires": {
|
||||
"min-document": "^2.19.0",
|
||||
"process": "^0.11.10"
|
||||
}
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
|
||||
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
|
||||
"requires": {
|
||||
"ajv": "^6.12.3",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"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.2.2",
|
||||
"sshpk": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"ip-regex": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz",
|
||||
"integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0="
|
||||
},
|
||||
"is-function": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz",
|
||||
"integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ=="
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
},
|
||||
"isarray": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
|
||||
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"jimp": {
|
||||
"version": "0.2.28",
|
||||
"resolved": "https://registry.npmjs.org/jimp/-/jimp-0.2.28.tgz",
|
||||
"integrity": "sha1-3VKak3GQ9ClXp5N9Gsw6d2KZbqI=",
|
||||
"requires": {
|
||||
"bignumber.js": "^2.1.0",
|
||||
"bmp-js": "0.0.3",
|
||||
"es6-promise": "^3.0.2",
|
||||
"exif-parser": "^0.1.9",
|
||||
"file-type": "^3.1.0",
|
||||
"jpeg-js": "^0.2.0",
|
||||
"load-bmfont": "^1.2.3",
|
||||
"mime": "^1.3.4",
|
||||
"mkdirp": "0.5.1",
|
||||
"pixelmatch": "^4.0.0",
|
||||
"pngjs": "^3.0.0",
|
||||
"read-chunk": "^1.0.1",
|
||||
"request": "^2.65.0",
|
||||
"stream-to-buffer": "^0.1.0",
|
||||
"tinycolor2": "^1.1.2",
|
||||
"url-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"jpeg-js": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.2.0.tgz",
|
||||
"integrity": "sha1-U+RI7J0mPmgyZkZ+lELSxaLvVII="
|
||||
},
|
||||
"jpg-stream": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/jpg-stream/-/jpg-stream-1.1.2.tgz",
|
||||
"integrity": "sha1-TboVnZ0ZNo3yExj2SM7pgKcr5Ac=",
|
||||
"requires": {
|
||||
"exif-reader": "^1.0.0",
|
||||
"pixel-stream": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"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",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
|
||||
"requires": {
|
||||
"assert-plus": "1.0.0",
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.2.3",
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"load-bmfont": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz",
|
||||
"integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==",
|
||||
"requires": {
|
||||
"buffer-equal": "0.0.1",
|
||||
"mime": "^1.3.4",
|
||||
"parse-bmfont-ascii": "^1.0.3",
|
||||
"parse-bmfont-binary": "^1.0.5",
|
||||
"parse-bmfont-xml": "^1.1.4",
|
||||
"phin": "^2.9.1",
|
||||
"xhr": "^2.0.1",
|
||||
"xtend": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
},
|
||||
"lzma-purejs": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/lzma-purejs/-/lzma-purejs-0.9.3.tgz",
|
||||
"integrity": "sha1-yJF+iUsbTbXIZbkn34ZO3edZzN4=",
|
||||
"requires": {
|
||||
"amdefine": "~0.1.0",
|
||||
"commander": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"maxrects-packer": {
|
||||
"version": "2.7.2",
|
||||
"resolved": "https://registry.npmjs.org/maxrects-packer/-/maxrects-packer-2.7.2.tgz",
|
||||
"integrity": "sha512-akd5IRLPqQeWlpJyRJyfYq86VB05zzbMIdyTgLxRk4z1H0A8g4oTJW31Yo6zO9piSRsFNYdzmgudW7J2g1gEhQ=="
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.45.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz",
|
||||
"integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.28",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz",
|
||||
"integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==",
|
||||
"requires": {
|
||||
"mime-db": "1.45.0"
|
||||
}
|
||||
},
|
||||
"min-document": {
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
|
||||
"integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=",
|
||||
"requires": {
|
||||
"dom-walk": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
},
|
||||
"mustache": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.2.tgz",
|
||||
"integrity": "sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ=="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
|
||||
},
|
||||
"node-gzip": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/node-gzip/-/node-gzip-1.1.2.tgz",
|
||||
"integrity": "sha512-ZB6zWpfZHGtxZnPMrJSKHVPrRjURoUzaDbLFj3VO70mpLTW5np96vXyHwft4Id0o+PYIzgDkBUjIzaNHhQ8srw=="
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
||||
},
|
||||
"parse-bmfont-ascii": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz",
|
||||
"integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU="
|
||||
},
|
||||
"parse-bmfont-binary": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz",
|
||||
"integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY="
|
||||
},
|
||||
"parse-bmfont-xml": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz",
|
||||
"integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==",
|
||||
"requires": {
|
||||
"xml-parse-from-string": "^1.0.0",
|
||||
"xml2js": "^0.4.5"
|
||||
}
|
||||
},
|
||||
"parse-headers": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz",
|
||||
"integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA=="
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"phin": {
|
||||
"version": "2.9.3",
|
||||
"resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz",
|
||||
"integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA=="
|
||||
},
|
||||
"pixel-stream": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pixel-stream/-/pixel-stream-1.0.3.tgz",
|
||||
"integrity": "sha1-U+jFSyHVUIOTtTvLMrZKd1Xx+l4=",
|
||||
"requires": {
|
||||
"shallow-copy": "0.0.1"
|
||||
}
|
||||
},
|
||||
"pixelmatch": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz",
|
||||
"integrity": "sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=",
|
||||
"requires": {
|
||||
"pngjs": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"png-stream": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/png-stream/-/png-stream-1.0.5.tgz",
|
||||
"integrity": "sha1-W8cWh+qJWUJ+lQ5Sx8yknipvBMY=",
|
||||
"requires": {
|
||||
"bl": "^0.9.3",
|
||||
"buffer-crc32": "^0.2.3",
|
||||
"buffer-equal": "^0.0.1",
|
||||
"pixel-stream": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"pngjs": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz",
|
||||
"integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w=="
|
||||
},
|
||||
"process": {
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||
"integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
|
||||
},
|
||||
"promise-nodeify": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/promise-nodeify/-/promise-nodeify-3.0.1.tgz",
|
||||
"integrity": "sha512-ghsSuzZXJX8iO7WVec2z7GI+Xk/EyiD+JZK7AZKhUqYfpLa/Zs4ylUD+CwwnKlG6G3HnkUPMAi6PO7zeqGKssg=="
|
||||
},
|
||||
"proxying-agent": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/proxying-agent/-/proxying-agent-2.4.0.tgz",
|
||||
"integrity": "sha512-b9vDqIcViJZVsWPpQlp9Py74u+Wqd0a+kMkkg7zX58mwNtrNbOChNlRTM7lUrlpiwNzyJCV8+5D8rnZYLDFh7Q=="
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
|
||||
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
},
|
||||
"read-chunk": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-1.0.1.tgz",
|
||||
"integrity": "sha1-X2jKswfmY/GZk1J9m1icrORmEZQ="
|
||||
},
|
||||
"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.0",
|
||||
"inherits": "~2.0.1",
|
||||
"isarray": "0.0.1",
|
||||
"string_decoder": "~0.10.x"
|
||||
}
|
||||
},
|
||||
"request": {
|
||||
"version": "2.88.2",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
|
||||
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
|
||||
"requires": {
|
||||
"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.3",
|
||||
"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.5.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.3.2"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
},
|
||||
"shallow-copy": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz",
|
||||
"integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA="
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
|
||||
"requires": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"stream-to": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/stream-to/-/stream-to-0.2.2.tgz",
|
||||
"integrity": "sha1-hDBgmNhf25kLn6MAsbPM9V6O8B0="
|
||||
},
|
||||
"stream-to-array": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/stream-to-array/-/stream-to-array-2.3.0.tgz",
|
||||
"integrity": "sha1-u/azn19D7DC8cbq8s3VXrOzzQ1M=",
|
||||
"requires": {
|
||||
"any-promise": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"stream-to-buffer": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/stream-to-buffer/-/stream-to-buffer-0.1.0.tgz",
|
||||
"integrity": "sha1-JnmdkDqyAlyb1VCsRxcbAPjdgKk=",
|
||||
"requires": {
|
||||
"stream-to": "~0.2.0"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
|
||||
},
|
||||
"swf-extract": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/swf-extract/-/swf-extract-1.1.0.tgz",
|
||||
"integrity": "sha1-DS6Q01lKFu9ly8hfuEEiRhdz9t0=",
|
||||
"requires": {
|
||||
"concat-frames": "^1.0.3",
|
||||
"jpg-stream": "^1.1.1",
|
||||
"lzma-purejs": "~0.9.3",
|
||||
"png-stream": "^1.0.5",
|
||||
"stream-to-array": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"tinify": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tinify/-/tinify-1.5.0.tgz",
|
||||
"integrity": "sha1-a6LqfognyEXSY947RvTbe61VWSA=",
|
||||
"requires": {
|
||||
"promise-nodeify": ">= 0.1",
|
||||
"proxying-agent": ">= 2.1"
|
||||
}
|
||||
},
|
||||
"tinycolor2": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz",
|
||||
"integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA=="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||
"requires": {
|
||||
"psl": "^1.1.28",
|
||||
"punycode": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
||||
"requires": {
|
||||
"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="
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"url-regex": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz",
|
||||
"integrity": "sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=",
|
||||
"requires": {
|
||||
"ip-regex": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"xhr": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz",
|
||||
"integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==",
|
||||
"requires": {
|
||||
"global": "~4.4.0",
|
||||
"is-function": "^1.0.1",
|
||||
"parse-headers": "^2.0.0",
|
||||
"xtend": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"xml-parse-from-string": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz",
|
||||
"integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig="
|
||||
},
|
||||
"xml2js": {
|
||||
"version": "0.4.23",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
|
||||
"integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
|
||||
"requires": {
|
||||
"sax": ">=0.6.0",
|
||||
"xmlbuilder": "~11.0.0"
|
||||
}
|
||||
},
|
||||
"xmlbuilder": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
|
||||
}
|
||||
}
|
||||
}
|
20
package.json
Normal file
20
package.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "nitroassetconverter",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@types/node": "^14.14.22",
|
||||
"free-tex-packer-core": "^0.3.2",
|
||||
"lodash": "^4.17.20",
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-gzip": "^1.1.2",
|
||||
"swf-extract": "^1.1.0",
|
||||
"xml2js": "^0.4.23"
|
||||
}
|
||||
}
|
75
src/Main.ts
Normal file
75
src/Main.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import Configuration from "./config/Configuration";
|
||||
import FigureDownloader from "./downloaders/FigureDownloader";
|
||||
import HabboAssetSWF from "./swf/HabboAssetSWF";
|
||||
import SpriteSheetConverter from "./converters/util/SpriteSheetConverter";
|
||||
import FigureConverter from "./converters/figure/FigureConverter";
|
||||
import File from "./utils/File";
|
||||
import FurnitureDownloader from "./downloaders/FurnitureDownloader";
|
||||
import FurnitureConverter from "./converters/furniture/FurnitureConverter";
|
||||
|
||||
(async () => {
|
||||
const config = new Configuration();
|
||||
await config.init();
|
||||
|
||||
const outputFolderFigure = new File(config.getValue("output.folder.figure"));
|
||||
if (!outputFolderFigure.isDirectory()) {
|
||||
outputFolderFigure.mkdirs();
|
||||
}
|
||||
|
||||
const outputFolderFurniture = new File(config.getValue("output.folder.furniture"));
|
||||
if (!outputFolderFurniture.isDirectory()) {
|
||||
outputFolderFurniture.mkdirs();
|
||||
}
|
||||
|
||||
const spriteSheetConverter = new SpriteSheetConverter();
|
||||
const figureConverter = new FigureConverter(config);
|
||||
const furnitureConverter= new FurnitureConverter(config);
|
||||
|
||||
if (config.getBoolean("convert.figure")) {
|
||||
const figureDownloader = new FigureDownloader(config);
|
||||
await figureDownloader.download(async function (habboAssetSwf: HabboAssetSWF) {
|
||||
|
||||
console.log("Attempt parsing figure: " + habboAssetSwf.getDocumentClass());
|
||||
|
||||
try {
|
||||
const spriteSheetType = await spriteSheetConverter.generateSpriteSheet(habboAssetSwf, outputFolderFigure.path, "figure");
|
||||
if (spriteSheetType !== null)
|
||||
await figureConverter.fromHabboAsset(habboAssetSwf, outputFolderFigure.path, "figure", spriteSheetType);
|
||||
|
||||
} catch (e) {
|
||||
console.log("Figure error: " + habboAssetSwf.getDocumentClass());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let count = 0;
|
||||
|
||||
if (config.getBoolean("convert.furniture")) {
|
||||
const furnitureDownloader = new FurnitureDownloader(config);
|
||||
await furnitureDownloader.download(async function (habboAssetSwf: HabboAssetSWF, className: string) {
|
||||
//console.log("Attempt parsing furniture: " + habboAssetSwf.getDocumentClass());
|
||||
|
||||
try {
|
||||
const assetOuputFolder = new File(outputFolderFurniture.path + "/" + className);
|
||||
if (!assetOuputFolder.isDirectory()) {
|
||||
assetOuputFolder.mkdirs();
|
||||
} else if (assetOuputFolder.list().length > 0) {
|
||||
console.log("Furniture already exists or the directory is not empty!");
|
||||
return;
|
||||
}
|
||||
|
||||
const spriteSheetType = await spriteSheetConverter.generateSpriteSheet(habboAssetSwf, assetOuputFolder.path, "furniture");
|
||||
if (spriteSheetType !== null) {
|
||||
await furnitureConverter.fromHabboAsset(habboAssetSwf, assetOuputFolder.path, "furniture", spriteSheetType);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Furniture error: " + habboAssetSwf.getDocumentClass());
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`Parsed ${count} furnitures`)
|
||||
}
|
||||
|
||||
console.log('finished!');
|
||||
})()
|
36
src/config/Configuration.ts
Normal file
36
src/config/Configuration.ts
Normal file
@ -0,0 +1,36 @@
|
||||
const fs = require('fs/promises');
|
||||
|
||||
export default class Configuration {
|
||||
|
||||
private readonly _config: Map<string, string>;
|
||||
|
||||
constructor() {
|
||||
this._config = new Map<string, string>();
|
||||
}
|
||||
|
||||
async init() {
|
||||
const content = await fs.readFile("/home/user/git/nitro-asset-converter-node/config.ini");
|
||||
|
||||
const config: string[] = content.toString("utf-8").split("\n");
|
||||
for (const configEntry of config) {
|
||||
const configEntrySplit = configEntry.split("=");
|
||||
const configKey = configEntrySplit[0];
|
||||
const configValue = configEntrySplit[1];
|
||||
|
||||
this._config.set(configKey, configValue);
|
||||
}
|
||||
}
|
||||
|
||||
public getBoolean(key: string): boolean {
|
||||
return this._config.get(key) === "1";
|
||||
}
|
||||
|
||||
public getValue(key: string, value: string = ""): string {
|
||||
if (this._config.has(key)) {
|
||||
// @ts-ignore
|
||||
return this._config.get(key);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
62
src/converters/figure/FigureConverter.ts
Normal file
62
src/converters/figure/FigureConverter.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import HabboAssetSWF from "../../swf/HabboAssetSWF";
|
||||
import {SpriteSheetType} from "../util/SpriteSheetTypes";
|
||||
import DefineBinaryDataTag from "../../swf/tags/DefineBinaryDataTag";
|
||||
import Configuration from "../../config/Configuration";
|
||||
import FigureJsonMapper from "./FigureJsonMapper";
|
||||
import {FigureJson} from "./FigureType";
|
||||
import File from "../../utils/File";
|
||||
|
||||
const xml2js = require('xml2js');
|
||||
const parser = new xml2js.Parser(/* options */);
|
||||
|
||||
const fs = require('fs').promises;
|
||||
const {gzip} = require('node-gzip');
|
||||
|
||||
export default class FigureConverter {
|
||||
|
||||
private readonly _figureJsonMapper: FigureJsonMapper;
|
||||
|
||||
constructor(config: Configuration) {
|
||||
this._figureJsonMapper = new FigureJsonMapper(config);
|
||||
}
|
||||
|
||||
private getBinaryData(habboAssetSWF: HabboAssetSWF, type: string, documentNameTwice: boolean) {
|
||||
let binaryName: string = habboAssetSWF.getFullClassName(type, documentNameTwice);
|
||||
let tag = habboAssetSWF.getBinaryTagByName(binaryName);
|
||||
if (tag === null) {
|
||||
binaryName = habboAssetSWF.getFullClassNameSnake(type, documentNameTwice, true);
|
||||
tag = habboAssetSWF.getBinaryTagByName(binaryName);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
private async convertXML2JSON(habboAssetSWF: HabboAssetSWF): Promise<FigureJson | null> {
|
||||
const manifestXML: DefineBinaryDataTag | null = this.getBinaryData(habboAssetSWF, "manifest", false);
|
||||
if (manifestXML !== null) {
|
||||
const result = await parser.parseStringPromise(manifestXML.binaryData);
|
||||
|
||||
return this._figureJsonMapper.mapXML(habboAssetSWF, result);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, spriteSheetType: SpriteSheetType) {
|
||||
const manifestJson = await this.convertXML2JSON(habboAssetSWF);
|
||||
if (manifestJson !== null) {
|
||||
manifestJson.spritesheet = spriteSheetType;
|
||||
|
||||
const path = outputFolder + "/" + habboAssetSWF.getDocumentClass() + ".nitro";
|
||||
const assetOuputFolder = new File(path);
|
||||
if (assetOuputFolder.exists()) {
|
||||
console.log("Furniture already exists or the directory is not empty!");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const compressed = await gzip(JSON.stringify(manifestJson));
|
||||
await fs.writeFile(path, compressed);
|
||||
}
|
||||
}
|
||||
}
|
85
src/converters/figure/FigureJsonMapper.ts
Normal file
85
src/converters/figure/FigureJsonMapper.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import Configuration from "../../config/Configuration";
|
||||
import HabboAssetSWF from "../../swf/HabboAssetSWF";
|
||||
import {FigureAsset, FigureAssets, FigureJson} from "./FigureType";
|
||||
import FigureDownloader from "../../downloaders/FigureDownloader";
|
||||
import SpriteSheetConverter from "../util/SpriteSheetConverter";
|
||||
|
||||
export default class FigureJsonMapper {
|
||||
|
||||
private static MUST_START_WITH: string = "h_";
|
||||
|
||||
private readonly _config: Configuration;
|
||||
|
||||
constructor(config: Configuration) {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
|
||||
public mapXML(habboAssetSWF: HabboAssetSWF, manifestXML: any): FigureJson {
|
||||
const name = habboAssetSWF.getDocumentClass();
|
||||
|
||||
return {
|
||||
name: name,
|
||||
type: FigureDownloader.types.get(name) as string,
|
||||
assets: this.mapManifestXML(habboAssetSWF, manifestXML),
|
||||
spritesheet: null as any
|
||||
};
|
||||
}
|
||||
|
||||
private mapManifestXML(habboAssetSWF: HabboAssetSWF, manifestXML: any): FigureAssets {
|
||||
const assets: any = {};
|
||||
|
||||
const libraries = manifestXML.manifest.library;
|
||||
for (const library of libraries) {
|
||||
for (const assetObj of library.assets) {
|
||||
for (const asset of assetObj.asset) {
|
||||
const assetInfo = asset['$'];
|
||||
const name = assetInfo.name;
|
||||
|
||||
if (name.startsWith(FigureJsonMapper.MUST_START_WITH)) {
|
||||
let hasImage = false;
|
||||
for (const imageTag of habboAssetSWF.imageTags()) {
|
||||
if (imageTag.className.includes(name)) {
|
||||
hasImage = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasImage || !this._config.getBoolean("figure.skip.non-existing.asset.images")) {
|
||||
const figureAsset: FigureAsset = {} as any;
|
||||
figureAsset.name = name;
|
||||
figureAsset.x = asset.param[0]['$'].value.split(',')[0];
|
||||
figureAsset.y = asset.param[0]['$'].value.split(',')[1];
|
||||
|
||||
if (SpriteSheetConverter.imageSource.has(name)) {
|
||||
figureAsset.source = SpriteSheetConverter.imageSource.get(name) as string;
|
||||
}
|
||||
|
||||
assets[name] = figureAsset;
|
||||
/*FigureJSON.Asset asset = new FigureJSON.Asset();
|
||||
if (FFConverter.getConfig().getBoolean("figure.rotation.enabled")) {
|
||||
String[] names = assetXML.getName().split("_");
|
||||
if (this.isInteger(names[4])) {
|
||||
String firstName = names[0] + "_" + names[1] + "_" + names[2] + "_" + names[3] + "_%ROTATION%_" + names[5];
|
||||
Integer rotation = Integer.parseInt(names[4]);
|
||||
if (rotation >= 0 && rotation < 8) {
|
||||
if (assetRotations.containsKey(firstName)) {
|
||||
assetRotations.get(firstName).add(rotation);
|
||||
} else {
|
||||
List<Integer> rotations = new ArrayList<Integer>();
|
||||
rotations.add(rotation);
|
||||
assetRotations.put(firstName, rotations);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
} else {
|
||||
console.log("Image " + name + " did not decompile for some reason");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return assets;
|
||||
}
|
||||
}
|
20
src/converters/figure/FigureType.ts
Normal file
20
src/converters/figure/FigureType.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import {SpriteSheetType} from "../util/SpriteSheetTypes";
|
||||
|
||||
export interface FigureJson {
|
||||
type: string,
|
||||
name: string,
|
||||
spritesheet: SpriteSheetType,
|
||||
assets: FigureAssets
|
||||
}
|
||||
|
||||
export interface FigureAssets {
|
||||
[key: string]: FigureAsset
|
||||
}
|
||||
|
||||
export interface FigureAsset {
|
||||
name: string,
|
||||
source: string,
|
||||
x: number,
|
||||
y: number,
|
||||
flipH: boolean
|
||||
}
|
186
src/converters/furniture/FurniJsonMapper.ts
Normal file
186
src/converters/furniture/FurniJsonMapper.ts
Normal file
@ -0,0 +1,186 @@
|
||||
import {
|
||||
Action,
|
||||
Direction,
|
||||
Directions,
|
||||
FurniAsset,
|
||||
FurniAssets,
|
||||
FurniJson,
|
||||
Layer,
|
||||
Visualization,
|
||||
VisualizationLayers
|
||||
} from "./FurniTypes";
|
||||
import SpriteSheetConverter from "../util/SpriteSheetConverter";
|
||||
|
||||
export default class FurniJsonMapper {
|
||||
private static readonly VISUALIZATION_DEFAULT_SIZE = 64;
|
||||
|
||||
private static readonly VISUALIZATION_ICON_SIZE = 1;
|
||||
|
||||
public mapXML(assetsXML: any, indexXML: any, logicXML: any, visualizationXML: any): FurniJson {
|
||||
const furniJson: FurniJson = {} as any;
|
||||
|
||||
furniJson.assets = this.mapAssetsXML(assetsXML) as any;
|
||||
|
||||
this.mapIndexXML(indexXML, furniJson);
|
||||
this.mapLogicXML(logicXML, furniJson);
|
||||
this.mapVisualizationXML(visualizationXML, furniJson);
|
||||
//console.log(furniJson);
|
||||
|
||||
return furniJson;
|
||||
}
|
||||
|
||||
|
||||
private mapAssetsXML(assetsXML: any): FurniAssets | null {
|
||||
const assets: FurniAssets = {} as any;
|
||||
|
||||
for (const asset of assetsXML.assets.asset) {
|
||||
const attributes = asset['$'];
|
||||
if (!attributes.name.includes("_32_")) {
|
||||
const furniAsset: FurniAsset = {} as any;
|
||||
|
||||
if (attributes.source !== undefined) {
|
||||
furniAsset.source = attributes.source;
|
||||
if (SpriteSheetConverter.imageSource.has(attributes.source)) {
|
||||
furniAsset.source = SpriteSheetConverter.imageSource.get(attributes.source) as string;
|
||||
}
|
||||
}
|
||||
|
||||
if (SpriteSheetConverter.imageSource.has(attributes.name)) {
|
||||
furniAsset.source = SpriteSheetConverter.imageSource.get(attributes.name) as string;
|
||||
}
|
||||
|
||||
furniAsset.x = attributes.x;
|
||||
furniAsset.y = attributes.y;
|
||||
furniAsset.flipH = attributes.flipH === "1";
|
||||
assets[attributes.name] = furniAsset;
|
||||
}
|
||||
}
|
||||
return Object.keys(assets).length > 0 ? assets : null;
|
||||
}
|
||||
|
||||
private mapIndexXML(indexXML: any, output: FurniJson) {
|
||||
const attributes = indexXML.object['$'];
|
||||
output.name = attributes.type;
|
||||
output.logicType = attributes.logic;
|
||||
output.visualizationType = attributes.visualization;
|
||||
}
|
||||
|
||||
private mapLogicXML(logicXML: any, output: FurniJson) {
|
||||
const objectData = logicXML.objectData;
|
||||
const attributes = objectData['$'];
|
||||
|
||||
const model = objectData.model[0];
|
||||
const dimensions = model.dimensions[0]['$'];
|
||||
output.dimensions = {
|
||||
x: parseInt(dimensions.x),
|
||||
y: parseInt(dimensions.y),
|
||||
z: parseFloat(dimensions.z)
|
||||
}
|
||||
|
||||
const directions: Array<number> = [];
|
||||
if (model.directions === undefined) {
|
||||
directions.push(0);
|
||||
} else {
|
||||
for (const directionObj of model.directions) {
|
||||
const direction = directionObj.direction;
|
||||
for (const dir of direction) {
|
||||
const dirAttributes = dir['$'];
|
||||
directions.push(dirAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (model.action !== undefined) {
|
||||
const action: Action = {} as any;
|
||||
}
|
||||
|
||||
output.directions = directions;
|
||||
}
|
||||
|
||||
private mapVisualizationXML(visualizationXML: any, output: FurniJson) {
|
||||
const visualizationsArray: Visualization[] = [];
|
||||
|
||||
const visualizationData = visualizationXML.visualizationData;
|
||||
const attributes = visualizationData['$'];
|
||||
|
||||
const visualizations = visualizationData.graphics;
|
||||
for (const visualizationArr of visualizations) {
|
||||
for (const visualization of visualizationArr.visualization) {
|
||||
const attributes = visualization['$'];
|
||||
|
||||
if (attributes.size == FurniJsonMapper.VISUALIZATION_DEFAULT_SIZE || attributes.size == FurniJsonMapper.VISUALIZATION_ICON_SIZE) {
|
||||
const visualizationType: Visualization = {} as any;
|
||||
visualizationType.angle = attributes.angle;
|
||||
visualizationType.layerCount = attributes.layerCount;
|
||||
visualizationType.size = attributes.size;
|
||||
|
||||
this.mapVisualizationLayersXML(visualization, visualizationType);
|
||||
this.mapVisualizationDirectionXML(visualization, visualizationType);
|
||||
|
||||
visualizationsArray.push(visualizationType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output.visualizations = visualizationsArray;
|
||||
}
|
||||
|
||||
private mapVisualizationColorXML(visualization: any, visualizationType: Visualization) {
|
||||
if (visualization.colors !== undefined && visualization.colors.length > 0) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private mapVisualizationDirectionXML(visualization: any, visualizationType: Visualization) {
|
||||
if (visualization.directions !== undefined && visualization.directions.length > 0) {
|
||||
const directions: Directions = {} as any;
|
||||
for (const directionParent of visualization.directions) {
|
||||
for (const direction of directionParent.direction) {
|
||||
const attributes = direction['$'];
|
||||
const directionType: Direction = {} as any;
|
||||
directionType.id = attributes.id;
|
||||
|
||||
if (direction.layers !== undefined && direction.layers.length > 0) {
|
||||
directionType.layers = this.generateLayers(direction, visualizationType);
|
||||
}
|
||||
|
||||
directions[directionType.id] = directionType;
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(directions).length > 0) visualizationType.directions = directions;
|
||||
}
|
||||
}
|
||||
|
||||
private mapVisualizationLayersXML(visualization: any, visualizationType: Visualization) {
|
||||
if (visualization.layers !== undefined && visualization.layers.length > 0) {
|
||||
for (const layerEntry of visualization.layers) {
|
||||
const layer = layerEntry.layer;
|
||||
visualizationType.layers = this.generateLayers(layer, visualizationType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private generateLayers(visualization: any, visualizationType: Visualization): VisualizationLayers {
|
||||
const visualizationLayers: VisualizationLayers = {} as any;
|
||||
for (const layerEntry of visualization.layers) {
|
||||
const layer = layerEntry.layer;
|
||||
const layerAttributes = layer['$'];
|
||||
|
||||
const layerType: Layer = {
|
||||
id: layerAttributes.id,
|
||||
alpha: layerAttributes.alpha,
|
||||
ink: layerAttributes.ink,
|
||||
tag: layerAttributes.tag,
|
||||
x: layerAttributes.x,
|
||||
y: layerAttributes.y,
|
||||
z: layerAttributes.z,
|
||||
} as any;
|
||||
if (layerAttributes.ignoreMouse !== undefined) layerType.ignoreMouse = layerAttributes.ignoreMouse === '1';
|
||||
|
||||
visualizationLayers[layerAttributes.id] = layerType;
|
||||
}
|
||||
|
||||
return visualizationLayers;
|
||||
}
|
||||
}
|
170
src/converters/furniture/FurniTypes.ts
Normal file
170
src/converters/furniture/FurniTypes.ts
Normal file
@ -0,0 +1,170 @@
|
||||
import {SpriteSheetType} from "../util/SpriteSheetTypes";
|
||||
|
||||
export interface FurniJson {
|
||||
type: string,
|
||||
name: string,
|
||||
visualizationType: string,
|
||||
logicType: string,
|
||||
maskType: string,
|
||||
credits: string,
|
||||
|
||||
spritesheet: SpriteSheetType,
|
||||
|
||||
dimensions: Dimensions,
|
||||
action: Action;
|
||||
directions: number[],
|
||||
assets: FurniAssets,
|
||||
visualizations: Visualization[]
|
||||
}
|
||||
|
||||
export interface Visualization {
|
||||
layerCount: number,
|
||||
angle: number,
|
||||
size: number,
|
||||
|
||||
layers: VisualizationLayers,
|
||||
directions: Directions,
|
||||
colors: Colors,
|
||||
animations: Animations,
|
||||
postures: Postures;
|
||||
gestures: Gestures
|
||||
}
|
||||
|
||||
export interface Gestures {
|
||||
[key: string]: Gesture
|
||||
}
|
||||
|
||||
export interface Gesture {
|
||||
id: string,
|
||||
animationId: number
|
||||
}
|
||||
|
||||
export interface Postures {
|
||||
[key: string]: Posture
|
||||
}
|
||||
|
||||
export interface Posture {
|
||||
id: string,
|
||||
animationId: number
|
||||
}
|
||||
|
||||
export interface Offset {
|
||||
direction: number,
|
||||
x: number,
|
||||
y: number
|
||||
}
|
||||
|
||||
export interface Frame {
|
||||
id: number,
|
||||
x: number,
|
||||
y: number,
|
||||
randomX: number,
|
||||
randomY: number,
|
||||
|
||||
offsets: Offset[]
|
||||
}
|
||||
|
||||
export interface Frames {
|
||||
[key: number]: Frame
|
||||
}
|
||||
|
||||
export interface FrameSequence {
|
||||
loopCount: number,
|
||||
random: number,
|
||||
|
||||
frames: Frames
|
||||
}
|
||||
|
||||
export interface FrameSequences {
|
||||
[key: number]: FrameSequence
|
||||
}
|
||||
|
||||
export interface AnimationLayer {
|
||||
id: number,
|
||||
loopCount: number,
|
||||
frameRepeat: number,
|
||||
random: number,
|
||||
|
||||
frameSequences: FrameSequences
|
||||
}
|
||||
|
||||
export interface AnimationLayers {
|
||||
[key: number]: AnimationLayer
|
||||
}
|
||||
|
||||
export interface Animations {
|
||||
[key: number]: Animation
|
||||
}
|
||||
|
||||
export interface Animation {
|
||||
id: number,
|
||||
transitionTo: number,
|
||||
transitionFrom: number,
|
||||
immediateChangeFrom: string,
|
||||
|
||||
layers: AnimationLayers;
|
||||
}
|
||||
|
||||
export interface ColorLayers {
|
||||
[key: number]: ColorLayer
|
||||
}
|
||||
|
||||
export interface ColorLayer {
|
||||
id: number,
|
||||
color: number
|
||||
}
|
||||
|
||||
export interface Colors {
|
||||
[key: number]: Color
|
||||
}
|
||||
|
||||
export interface Color {
|
||||
id: number;
|
||||
layers: ColorLayers;
|
||||
}
|
||||
|
||||
export interface Directions {
|
||||
[key: number]: Direction
|
||||
}
|
||||
|
||||
export interface Direction {
|
||||
id: number;
|
||||
layers: VisualizationLayers;
|
||||
}
|
||||
|
||||
export interface VisualizationLayers {
|
||||
[key: number]: Layer
|
||||
}
|
||||
|
||||
export interface Layer {
|
||||
id: number,
|
||||
alpha: number,
|
||||
x: number,
|
||||
y: number,
|
||||
z: number,
|
||||
ink: string,
|
||||
tag: string,
|
||||
ignoreMouse: boolean
|
||||
}
|
||||
|
||||
export interface Action {
|
||||
link: string,
|
||||
startState: number
|
||||
}
|
||||
|
||||
export interface Dimensions {
|
||||
x: number,
|
||||
y: number,
|
||||
z: number
|
||||
}
|
||||
|
||||
export interface FurniAssets {
|
||||
[key: string]: FurniAsset
|
||||
}
|
||||
|
||||
export interface FurniAsset {
|
||||
source: string,
|
||||
x: number,
|
||||
y: number,
|
||||
flipH: boolean
|
||||
}
|
85
src/converters/furniture/FurnitureConverter.ts
Normal file
85
src/converters/furniture/FurnitureConverter.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import HabboAssetSWF from "../../swf/HabboAssetSWF";
|
||||
import {SpriteSheetType} from "../util/SpriteSheetTypes";
|
||||
import DefineBinaryDataTag from "../../swf/tags/DefineBinaryDataTag";
|
||||
import Configuration from "../../config/Configuration";
|
||||
import FurniJsonMapper from "./FurniJsonMapper";
|
||||
import {FurniJson} from "./FurniTypes";
|
||||
|
||||
const xml2js = require('xml2js');
|
||||
const parser = new xml2js.Parser(/* options */);
|
||||
|
||||
const fs = require('fs').promises;
|
||||
|
||||
export default class FurnitureConverter {
|
||||
|
||||
private readonly _furniJsonMapper: FurniJsonMapper;
|
||||
|
||||
constructor(config: Configuration) {
|
||||
this._furniJsonMapper = new FurniJsonMapper();
|
||||
}
|
||||
|
||||
private static getBinaryData(habboAssetSWF: HabboAssetSWF, type: string, documentNameTwice: boolean) {
|
||||
let binaryName: string = habboAssetSWF.getFullClassName(type, documentNameTwice);
|
||||
let tag = habboAssetSWF.getBinaryTagByName(binaryName);
|
||||
if (tag === null) {
|
||||
binaryName = habboAssetSWF.getFullClassNameSnake(type, documentNameTwice, true);
|
||||
tag = habboAssetSWF.getBinaryTagByName(binaryName);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
private static async getAssetsXML(habboAssetSWF: HabboAssetSWF): Promise<any> {
|
||||
const binaryData: DefineBinaryDataTag | null = FurnitureConverter.getBinaryData(habboAssetSWF, "assets", true);
|
||||
if (binaryData !== null) {
|
||||
return await parser.parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static async getLogicXML(habboAssetSWF: HabboAssetSWF): Promise<any> {
|
||||
const binaryData: DefineBinaryDataTag | null = FurnitureConverter.getBinaryData(habboAssetSWF, "logic", true);
|
||||
if (binaryData !== null) {
|
||||
return await parser.parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static async getIndexXML(habboAssetSWF: HabboAssetSWF): Promise<any> {
|
||||
const binaryData: DefineBinaryDataTag | null = FurnitureConverter.getBinaryData(habboAssetSWF, "index", true);
|
||||
if (binaryData !== null) {
|
||||
return await parser.parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static async getVisualizationXML(habboAssetSWF: HabboAssetSWF): Promise<any> {
|
||||
const binaryData: DefineBinaryDataTag | null = FurnitureConverter.getBinaryData(habboAssetSWF, "visualization", true);
|
||||
if (binaryData !== null) {
|
||||
return await parser.parseStringPromise(binaryData.binaryData);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async convertXML2JSON(habboAssetSWF: HabboAssetSWF): Promise<FurniJson | null> {
|
||||
const assetXml = await FurnitureConverter.getAssetsXML(habboAssetSWF);
|
||||
const logicXml = await FurnitureConverter.getLogicXML(habboAssetSWF);
|
||||
const indexXml = await FurnitureConverter.getIndexXML(habboAssetSWF);
|
||||
const visualizationXml = await FurnitureConverter.getVisualizationXML(habboAssetSWF);
|
||||
|
||||
return this._furniJsonMapper.mapXML(assetXml, indexXml, logicXml, visualizationXml);
|
||||
}
|
||||
|
||||
public async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, spriteSheetType: SpriteSheetType) {
|
||||
const furnitureJson = await this.convertXML2JSON(habboAssetSWF);
|
||||
if (furnitureJson !== null) {
|
||||
furnitureJson.spritesheet = spriteSheetType;
|
||||
|
||||
await fs.writeFile(outputFolder + "/" + habboAssetSWF.getDocumentClass() + ".json", JSON.stringify(furnitureJson));
|
||||
}
|
||||
}
|
||||
}
|
103
src/converters/util/SpriteSheetConverter.ts
Normal file
103
src/converters/util/SpriteSheetConverter.ts
Normal file
@ -0,0 +1,103 @@
|
||||
import {SpriteSheetType} from "./SpriteSheetTypes";
|
||||
|
||||
const fs = require('fs').promises;
|
||||
let {packAsync} = require("free-tex-packer-core");
|
||||
|
||||
import HabboAssetSWF from "../../swf/HabboAssetSWF";
|
||||
import SymbolClassTag from "../../swf/tags/SymbolClassTag";
|
||||
import ImageTag from "../../swf/tags/ImageTag";
|
||||
|
||||
export default class SpriteSheetConverter {
|
||||
public static imageSource: Map<String, String> = new Map<String, String>();
|
||||
|
||||
public async generateSpriteSheet(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string): Promise<SpriteSheetType | null> {
|
||||
const tagList: Array<SymbolClassTag> = habboAssetSWF.symbolTags();
|
||||
const names: Array<string> = new Array<string>();
|
||||
const tags: Array<number> = new Array<number>();
|
||||
for (const tag of tagList) {
|
||||
names.push(...tag.names);
|
||||
tags.push(...tag.tags);
|
||||
}
|
||||
|
||||
const images: Array<{ path: String, contents: Buffer }> = new Array<{ path: String, contents: Buffer }>();
|
||||
|
||||
const imageTags: Array<ImageTag> = habboAssetSWF.imageTags();
|
||||
for (const imageTag of imageTags) {
|
||||
if (tags.includes(imageTag.characterID)) {
|
||||
for (let i = 0; i < tags.length; i++) {
|
||||
if (tags[i] == imageTag.characterID) {
|
||||
if (
|
||||
(names[i].includes("_64_") && type === "furniture") ||
|
||||
(names[i].includes("_icon_") && type === "furniture") ||
|
||||
(names[i].includes("_h_") && (type === "figure" || type === "effect")) ||
|
||||
(names[i].includes("_64_") && type === "pet")) {
|
||||
|
||||
if (names[i] !== imageTag.className) {
|
||||
SpriteSheetConverter.imageSource.set(names[i].substring(habboAssetSWF.getDocumentClass().length + 1), imageTag.className.substring(habboAssetSWF.getDocumentClass().length + 1));
|
||||
if ((imageTag.className.includes("_32_") && type === "furniture") ||
|
||||
(imageTag.className.includes("_sh_") && (type === "figure" || type === "effect")) ||
|
||||
(imageTag.className.includes("_32_") && type === "pet")) {
|
||||
images.push({
|
||||
path: imageTag.className,
|
||||
contents: imageTag.imgData
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((imageTag.className.includes("_64_") && type === "furniture") ||
|
||||
(imageTag.className.includes("_icon_") && type === "furniture") ||
|
||||
(imageTag.className.includes("_h_") && (type === "figure" || type === "effect")) ||
|
||||
(imageTag.className.includes("_64_") && type === "pet")) {
|
||||
images.push({
|
||||
path: imageTag.className,
|
||||
contents: imageTag.imgData
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (images.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return await this.packImages(habboAssetSWF.getDocumentClass(), outputFolder + "/", images);
|
||||
}
|
||||
|
||||
async packImages(documentClass: string, outputFolder: string, images: Array<{ path: String, contents: Buffer }>): Promise<SpriteSheetType | null> {
|
||||
let options = {
|
||||
textureName: documentClass,
|
||||
width: 1024,
|
||||
height: 1024,
|
||||
fixedSize: false,
|
||||
allowRotation: true,
|
||||
detectIdentical: true,
|
||||
allowTrim: true,
|
||||
exporter: "Pixi"
|
||||
};
|
||||
|
||||
let spriteSheetType: SpriteSheetType | null = null;
|
||||
let base64 = "";
|
||||
try {
|
||||
const files = await packAsync(images, options);
|
||||
for (let item of files) {
|
||||
if (item.name.endsWith(".json")) {
|
||||
spriteSheetType = JSON.parse(item.buffer.toString('utf8'));
|
||||
} else {
|
||||
base64 = item.buffer.toString("base64");
|
||||
//await fs.writeFile(outputFolder + item.name, item.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (spriteSheetType === null) throw new Error("Failed to parse SpriteSheet. " + images[0].path);
|
||||
} catch (error) {
|
||||
console.log("Error: " + error);
|
||||
}
|
||||
|
||||
if (spriteSheetType !== null) spriteSheetType.meta.imageb64 = base64;
|
||||
return spriteSheetType;
|
||||
}
|
||||
}
|
55
src/converters/util/SpriteSheetTypes.ts
Normal file
55
src/converters/util/SpriteSheetTypes.ts
Normal file
@ -0,0 +1,55 @@
|
||||
export interface SpriteSheetType {
|
||||
frames: SpriteSheetFrames,
|
||||
meta: SpriteSheetMeta
|
||||
}
|
||||
|
||||
export interface SpriteSheetFrames {
|
||||
[key: string]: SpriteSheetFrame
|
||||
}
|
||||
|
||||
export interface SpriteSheetFrame {
|
||||
frame: SpriteSheetFrameDimensions,
|
||||
rotated: boolean,
|
||||
trimmed: boolean,
|
||||
spriteSourceSize: SpriteSourceSize
|
||||
sourceSize: SourceSize,
|
||||
pivot: FramePivot
|
||||
}
|
||||
|
||||
export interface FramePivot {
|
||||
x: number,
|
||||
y: number
|
||||
}
|
||||
|
||||
export interface SourceSize {
|
||||
w: number,
|
||||
h: number
|
||||
}
|
||||
|
||||
export interface SpriteSourceSize {
|
||||
x: number,
|
||||
y: number,
|
||||
w: number,
|
||||
h: number
|
||||
}
|
||||
|
||||
export interface SpriteSheetFrameDimensions {
|
||||
x: number,
|
||||
y: number,
|
||||
w: number,
|
||||
h: number
|
||||
}
|
||||
|
||||
export interface SpriteSheetMeta {
|
||||
app: string,
|
||||
version: string,
|
||||
imageb64: string,
|
||||
format: string,
|
||||
size: SpriteSheetSize,
|
||||
scale: number
|
||||
}
|
||||
|
||||
export interface SpriteSheetSize {
|
||||
w: number,
|
||||
h: number
|
||||
}
|
69
src/downloaders/FigureDownloader.ts
Normal file
69
src/downloaders/FigureDownloader.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import Configuration from "../config/Configuration";
|
||||
import HabboAssetSWF from "../swf/HabboAssetSWF";
|
||||
import File from "../utils/File";
|
||||
|
||||
const fs = require("fs");
|
||||
const fetch = require('node-fetch');
|
||||
const xml2js = require('xml2js');
|
||||
const parser = new xml2js.Parser(/* options */);
|
||||
const util = require('util');
|
||||
|
||||
const readFile = util.promisify(fs.readFile);
|
||||
|
||||
export default class FigureDownloader {
|
||||
|
||||
private readonly _config: Configuration;
|
||||
|
||||
constructor(config: Configuration) {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
|
||||
public static types: Map<String, String> = new Map<String, String>();
|
||||
|
||||
public async download(callback: (habboAssetSwf: HabboAssetSWF) => Promise<void>) {
|
||||
const outputFolderFigure = this._config.getValue("output.folder.figure");
|
||||
const figureMap = await this.parseFigureMap();
|
||||
const map = figureMap.map;
|
||||
|
||||
for (const lib of map.lib) {
|
||||
const info = lib['$'];
|
||||
const className: string = info.id.split("\\*")[0];
|
||||
if (className === "hh_human_fx") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const assetOutputFolder = new File(outputFolderFigure + "/" + className);
|
||||
if (assetOutputFolder.exists()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!FigureDownloader.types.has(className)) {
|
||||
if (className !== "jacket_U_snowwar4_team1" &&
|
||||
className !== "jacket_U_snowwar4_team2") { //TODO: Figure out why snowstorm assets aren't converting...
|
||||
|
||||
const url = this._config.getValue("dynamic.download.url.figure").replace("%className%", className);
|
||||
if (!fs.existsSync(url)) {
|
||||
console.log("SWF File does not exist: " + url);
|
||||
return;
|
||||
}
|
||||
|
||||
const buffer: Buffer = await readFile(url);
|
||||
const habboAssetSWF = new HabboAssetSWF(buffer);
|
||||
await habboAssetSWF.setupAsync();
|
||||
|
||||
FigureDownloader.types.set(className, lib.part[0]['$'].type);
|
||||
await callback(habboAssetSWF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async parseFigureMap() {
|
||||
const figureMapPath = this._config.getValue("figuremap.url");
|
||||
const figureFetch = await fetch(figureMapPath);
|
||||
const figureMap = await figureFetch.text();
|
||||
|
||||
return await parser.parseStringPromise(figureMap);
|
||||
}
|
||||
}
|
92
src/downloaders/FurnitureDownloader.ts
Normal file
92
src/downloaders/FurnitureDownloader.ts
Normal file
@ -0,0 +1,92 @@
|
||||
import HabboAssetSWF from "../swf/HabboAssetSWF";
|
||||
import Configuration from "../config/Configuration";
|
||||
import {type} from "os";
|
||||
import File from "../utils/File";
|
||||
|
||||
const fs = require("fs");
|
||||
const fetch = require('node-fetch');
|
||||
const xml2js = require('xml2js');
|
||||
const parser = new xml2js.Parser(/* options */);
|
||||
const util = require('util');
|
||||
|
||||
const readFile = util.promisify(fs.readFile);
|
||||
|
||||
export default class FurnitureDownloader {
|
||||
|
||||
private readonly _config: Configuration;
|
||||
|
||||
constructor(config: Configuration) {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
public async download(callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise<void>) {
|
||||
|
||||
const outputFolderFurniture = new File(this._config.getValue("output.folder.furniture"));
|
||||
|
||||
const furniDataObj = await this.parseFurniData();
|
||||
const furniData = furniDataObj.furnidata;
|
||||
|
||||
const roomitemtypes = furniData.roomitemtypes;
|
||||
const wallitemtypes = furniData.wallitemtypes;
|
||||
|
||||
for (const roomItem of roomitemtypes) {
|
||||
for (const furnitype of roomItem.furnitype) {
|
||||
const attributes = furnitype['$'];
|
||||
const className = attributes.classname.split("\*")[0];
|
||||
const revision = furnitype.revision[0];
|
||||
|
||||
const assetOuputFolder = new File(outputFolderFurniture.path + "/" + className);
|
||||
if (assetOuputFolder.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await this.extractFurniture(revision, className, callback);
|
||||
}
|
||||
}
|
||||
|
||||
for (const wallItem of wallitemtypes) {
|
||||
for (const furnitype of wallItem.furnitype) {
|
||||
const attributes = furnitype['$'];
|
||||
const className = attributes.classname.split("\*")[0];
|
||||
const revision = furnitype.revision[0];
|
||||
|
||||
const assetOuputFolder = new File(outputFolderFurniture + "/" + className);
|
||||
if (assetOuputFolder.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await this.extractFurniture(revision, className, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async extractFurniture(revision: string, className: string, callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise<void>) {
|
||||
if (className !== "rare_dragonlamp") return;
|
||||
|
||||
const url = this._config.getValue("dynamic.download.url.furniture").replace("%revision%", revision).replace("%className%", className);
|
||||
const file = new File(url);
|
||||
if (!file.exists()) {
|
||||
console.log("SWF File does not exist: " + file.path);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const buffer: Buffer = await readFile(url);
|
||||
const habboAssetSWF = new HabboAssetSWF(buffer);
|
||||
await habboAssetSWF.setupAsync();
|
||||
|
||||
await callback(habboAssetSWF, className);
|
||||
} catch (e) {
|
||||
console.log("Error with furniture: " + url);
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
async parseFurniData() {
|
||||
const furniDataFetch = this._config.getValue("furnidata.url");
|
||||
const furniFetch = await fetch(furniDataFetch);
|
||||
const furniData = await furniFetch.text();
|
||||
|
||||
return await parser.parseStringPromise(furniData);
|
||||
}
|
||||
}
|
188
src/swf/HabboAssetSWF.ts
Normal file
188
src/swf/HabboAssetSWF.ts
Normal file
@ -0,0 +1,188 @@
|
||||
import SymbolClassTag from "./tags/SymbolClassTag";
|
||||
import ImageTag from "./tags/ImageTag";
|
||||
import ITag from "./tags/ITag";
|
||||
import CustomIterator from "../utils/CustomIterator";
|
||||
import CharacterTag from "./tags/CharacterTag";
|
||||
import DefineBinaryDataTag from "./tags/DefineBinaryDataTag";
|
||||
|
||||
const {readFromBufferP, extractImages} = require('swf-extract');
|
||||
|
||||
export interface Tag {
|
||||
code: number,
|
||||
length: number,
|
||||
rawData: Buffer
|
||||
}
|
||||
|
||||
export interface SWFFrameSize {
|
||||
x: number,
|
||||
y: number,
|
||||
width: number,
|
||||
height: number
|
||||
}
|
||||
|
||||
export interface SWFFileLength {
|
||||
compressed: number,
|
||||
uncompressed: number
|
||||
}
|
||||
|
||||
export interface SWF {
|
||||
tags: Array<Tag>,
|
||||
version: number,
|
||||
fileLength: SWFFileLength,
|
||||
frameSize: SWFFrameSize,
|
||||
frameRate: number,
|
||||
frameCount: number
|
||||
}
|
||||
|
||||
export default class HabboAssetSWF {
|
||||
|
||||
private swf: SWF | null;
|
||||
|
||||
private readonly _tags: Array<ITag>;
|
||||
|
||||
private _documentClass: string | null = null;
|
||||
|
||||
constructor(private readonly _buffer: Buffer) {
|
||||
this.swf = null;
|
||||
|
||||
this._tags = new Array<ITag>();
|
||||
}
|
||||
|
||||
public async setupAsync() {
|
||||
this.swf = await readFromBufferP(this._buffer);
|
||||
|
||||
if (this.swf === null) throw new Error("SWF Can't be null!");
|
||||
|
||||
for (const tag of this.swf.tags) {
|
||||
if (tag.code === 76) {
|
||||
this._tags.push(new SymbolClassTag(tag));
|
||||
}
|
||||
|
||||
if (tag.code === 87) {
|
||||
this._tags.push(new DefineBinaryDataTag(tag));
|
||||
}
|
||||
}
|
||||
|
||||
const images = await Promise.all(extractImages(this.swf.tags));
|
||||
for (const image of images) {
|
||||
const imgObj: any = image;
|
||||
this._tags.push(new ImageTag({
|
||||
code: imgObj.code,
|
||||
characterID: imgObj.characterId,
|
||||
imgType: imgObj.imgType,
|
||||
imgData: imgObj.imgData
|
||||
}));
|
||||
}
|
||||
|
||||
this.assignClassesToSymbols();
|
||||
}
|
||||
|
||||
public imageTags(): Array<ImageTag> {
|
||||
return this._tags.filter((tag: ITag) => tag instanceof ImageTag).map(x => x as ImageTag);
|
||||
}
|
||||
|
||||
public symbolTags(): Array<SymbolClassTag> {
|
||||
return this._tags.filter((tag: ITag) => tag instanceof SymbolClassTag).map(x => x as SymbolClassTag)
|
||||
}
|
||||
|
||||
private binaryTags(): Array<DefineBinaryDataTag> {
|
||||
return this._tags.filter((tag: ITag) => tag instanceof DefineBinaryDataTag).map(x => x as DefineBinaryDataTag);
|
||||
}
|
||||
|
||||
public getBinaryTagByName(name: string): DefineBinaryDataTag | null {
|
||||
const streamTag = this.binaryTags()
|
||||
.filter(tag => tag.className === name)[0];
|
||||
|
||||
if (streamTag === undefined) return null;
|
||||
|
||||
return streamTag;
|
||||
}
|
||||
|
||||
private assignClassesToSymbols() {
|
||||
const classes: Map<number, string> = new Map();
|
||||
|
||||
let iterator: CustomIterator<ITag> = new CustomIterator(this._tags);
|
||||
|
||||
while (true) {
|
||||
let t: ITag;
|
||||
do {
|
||||
if (!iterator.hasNext()) {
|
||||
iterator = new CustomIterator(this._tags);
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
t = iterator.next();
|
||||
if (t instanceof CharacterTag) {
|
||||
const ct = t as CharacterTag;
|
||||
|
||||
if (classes.has(ct.characterId)) {
|
||||
// @ts-ignore
|
||||
ct.className = classes.get(ct.characterId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
t = iterator.next();
|
||||
} while (!(t instanceof SymbolClassTag));
|
||||
|
||||
const sct = t as SymbolClassTag;
|
||||
|
||||
for (let i = 0; i < sct.tags.length; ++i) {
|
||||
if (!classes.has(sct.tags[i]) && !Array.from(classes.values()).includes(sct.names[i])) {
|
||||
classes.set(sct.tags[i], sct.names[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getFullClassName(type: string, documentNameTwice: boolean): string {
|
||||
return this.getFullClassNameSnake(type, documentNameTwice, false);
|
||||
}
|
||||
|
||||
public getFullClassNameSnake(type: string, documentNameTwice: boolean, snakeCase: boolean): string {
|
||||
if (this.swf === null) throw new Error("SWF Can't be null!");
|
||||
|
||||
let result: string = this.getDocumentClass() + "_";
|
||||
if (documentNameTwice) {
|
||||
if (snakeCase) {
|
||||
//result += CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, this.swf.getDocumentClass()) + "_";
|
||||
} else {
|
||||
result += this.getDocumentClass() + "_";
|
||||
}
|
||||
}
|
||||
|
||||
return result + type;
|
||||
}
|
||||
|
||||
public getDocumentClass(): string {
|
||||
if (this._documentClass !== null) return this._documentClass;
|
||||
|
||||
let iterator: CustomIterator<ITag> = new CustomIterator(this._tags);
|
||||
|
||||
while (true) {
|
||||
let t: ITag;
|
||||
do {
|
||||
if (!iterator.hasNext()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
t = iterator.next();
|
||||
} while (!(t instanceof SymbolClassTag));
|
||||
|
||||
const sc = t as SymbolClassTag;
|
||||
|
||||
for (let i = 0; i < sc.tags.length; ++i) {
|
||||
if (sc.tags[i] == 0) {
|
||||
this._documentClass = sc.names[i];
|
||||
return this._documentClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public setDocumentClass(documentClass: string) {
|
||||
this._documentClass = documentClass;
|
||||
}
|
||||
}
|
20
src/swf/tags/CharacterTag.ts
Normal file
20
src/swf/tags/CharacterTag.ts
Normal file
@ -0,0 +1,20 @@
|
||||
export default abstract class CharacterTag {
|
||||
private _className: string = "";
|
||||
private _characterId: number = -1;
|
||||
|
||||
get className(): string {
|
||||
return this._className;
|
||||
}
|
||||
|
||||
set className(value: string) {
|
||||
this._className = value;
|
||||
}
|
||||
|
||||
get characterId(): number {
|
||||
return this._characterId;
|
||||
}
|
||||
|
||||
set characterId(value: number) {
|
||||
this._characterId = value;
|
||||
}
|
||||
}
|
43
src/swf/tags/DefineBinaryDataTag.ts
Normal file
43
src/swf/tags/DefineBinaryDataTag.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import {Tag} from "../HabboAssetSWF";
|
||||
import ITag from "./ITag";
|
||||
import CharacterTag from "./CharacterTag";
|
||||
|
||||
const {SWFBuffer} = require('swf-extract/swf-buffer');
|
||||
|
||||
export default class DefineBinaryDataTag extends CharacterTag implements ITag {
|
||||
|
||||
private readonly _tag: number;
|
||||
private readonly _reserved: number;
|
||||
private readonly _binaryData: string;
|
||||
|
||||
constructor(tag: Tag) {
|
||||
super();
|
||||
|
||||
const swfBuffer = new SWFBuffer(tag.rawData);
|
||||
this._tag = swfBuffer.readUIntLE(16);
|
||||
this._reserved = swfBuffer.readUIntLE(32);
|
||||
const start = 6; //short 2 + int 4
|
||||
const end = tag.rawData.length;
|
||||
const binary = tag.rawData.slice(start, end);
|
||||
|
||||
this._binaryData = binary.toString("utf-8");
|
||||
|
||||
this.characterId = this._tag;
|
||||
}
|
||||
|
||||
get code(): number {
|
||||
return 87;
|
||||
}
|
||||
|
||||
get tag(): number {
|
||||
return this._tag;
|
||||
}
|
||||
|
||||
get reserved(): number {
|
||||
return this._reserved;
|
||||
}
|
||||
|
||||
get binaryData(): string {
|
||||
return this._binaryData;
|
||||
}
|
||||
}
|
3
src/swf/tags/ITag.ts
Normal file
3
src/swf/tags/ITag.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export default interface ITag {
|
||||
code: number;
|
||||
}
|
37
src/swf/tags/ImageTag.ts
Normal file
37
src/swf/tags/ImageTag.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import ITag from "./ITag";
|
||||
import CharacterTag from "./CharacterTag";
|
||||
|
||||
export default class ImageTag extends CharacterTag implements ITag {
|
||||
|
||||
private readonly _code: number;
|
||||
private readonly _characterID: number;
|
||||
private readonly _imgType: string;
|
||||
private readonly _imgData: Buffer;
|
||||
|
||||
constructor(image: { code: number, characterID: number, imgType: string, imgData: Buffer }) {
|
||||
super();
|
||||
|
||||
this._code = image.code;
|
||||
this._characterID = image.characterID;
|
||||
this._imgType = image.imgType;
|
||||
this._imgData = image.imgData;
|
||||
|
||||
this.characterId = this._characterID;
|
||||
}
|
||||
|
||||
get code(): number {
|
||||
return this._code;
|
||||
};
|
||||
|
||||
get characterID(): number {
|
||||
return this._characterID;
|
||||
}
|
||||
|
||||
get imgType(): string {
|
||||
return this._imgType;
|
||||
}
|
||||
|
||||
get imgData(): Buffer {
|
||||
return this._imgData;
|
||||
}
|
||||
}
|
42
src/swf/tags/SymbolClassTag.ts
Normal file
42
src/swf/tags/SymbolClassTag.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import {Tag} from "../HabboAssetSWF";
|
||||
import ITag from "./ITag";
|
||||
|
||||
const {SWFBuffer} = require('swf-extract/swf-buffer');
|
||||
|
||||
export default class SymbolClassTag implements ITag {
|
||||
|
||||
private readonly _tags: Array<number>;
|
||||
private readonly _names: Array<string>;
|
||||
|
||||
constructor(tag: Tag) {
|
||||
this._tags = [];
|
||||
this._names = [];
|
||||
|
||||
this.init(tag);
|
||||
}
|
||||
|
||||
init(tag: Tag) {
|
||||
const swfBuffer = new SWFBuffer(tag.rawData);
|
||||
|
||||
const numSymbols = swfBuffer.readUIntLE(16);
|
||||
for (let i = 0; i < numSymbols; i++) {
|
||||
const tagId = swfBuffer.readUIntLE(16);
|
||||
const tagName = swfBuffer.readString("utf-8");
|
||||
|
||||
this._tags.push(tagId);
|
||||
this._names.push(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
get tags(): Array<number> {
|
||||
return this._tags;
|
||||
}
|
||||
|
||||
get names(): Array<string> {
|
||||
return this._names;
|
||||
}
|
||||
|
||||
get code(): number {
|
||||
return 76;
|
||||
}
|
||||
}
|
54
src/utils/CustomIterator.ts
Normal file
54
src/utils/CustomIterator.ts
Normal file
@ -0,0 +1,54 @@
|
||||
export default class CustomIterator<TType> {
|
||||
|
||||
private idx: number;
|
||||
private readonly top: number;
|
||||
private readonly keys: Array<any>;
|
||||
private readonly arr: boolean;
|
||||
private readonly collection: Array<TType>;
|
||||
|
||||
constructor(collection: Array<TType>) {
|
||||
if (this.dontIterate(collection)) {
|
||||
throw new Error('Oh you nasty man, I won\'t iterate over that (' + collection + ')!');
|
||||
}
|
||||
|
||||
this.arr = this.isArray(collection);
|
||||
this.idx = 0;
|
||||
this.top = 0;
|
||||
this.keys = [];
|
||||
if (this.arr) {
|
||||
this.top = collection.length;
|
||||
} else {
|
||||
for (const prop in collection) {
|
||||
this.keys.push(prop);
|
||||
}
|
||||
}
|
||||
|
||||
this.collection = collection;
|
||||
}
|
||||
|
||||
isArray(candidate: any) {
|
||||
return candidate &&
|
||||
typeof candidate === 'object' &&
|
||||
typeof candidate.length === 'number' &&
|
||||
typeof candidate.splice === 'function' &&
|
||||
!(candidate.propertyIsEnumerable('length'));
|
||||
}
|
||||
|
||||
dontIterate(collection: any) {
|
||||
// put some checks chere for stuff that isn't iterable (yet)
|
||||
return (!collection || typeof collection === 'number' || typeof collection === 'boolean');
|
||||
}
|
||||
|
||||
public next(): TType {
|
||||
if (!this.hasNext()) {
|
||||
throw new Error('Oh you nasty man. I have no more elements.');
|
||||
}
|
||||
const elem = this.arr ? this.collection[this.idx] : this.collection[this.keys[this.idx]];
|
||||
++this.idx;
|
||||
return elem;
|
||||
};
|
||||
|
||||
public hasNext() {
|
||||
return this.arr ? this.idx <= this.top : this.idx <= this.keys.length;
|
||||
};
|
||||
}
|
33
src/utils/File.ts
Normal file
33
src/utils/File.ts
Normal file
@ -0,0 +1,33 @@
|
||||
const fs = require("fs");
|
||||
|
||||
export default class File {
|
||||
|
||||
private readonly _path: string;
|
||||
|
||||
constructor(path: string) {
|
||||
this._path = path;
|
||||
}
|
||||
|
||||
public exists(): boolean {
|
||||
return fs.existsSync(this._path);
|
||||
}
|
||||
|
||||
public mkdirs(): void {
|
||||
return fs.mkdirSync(this._path);
|
||||
}
|
||||
|
||||
public list(): string[] {
|
||||
const test = fs.readdirSync(this._path);
|
||||
console.log(test);
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
public isDirectory(): boolean {
|
||||
return this.exists() && fs.lstatSync(this._path).isDirectory()
|
||||
}
|
||||
|
||||
get path(): string {
|
||||
return this._path;
|
||||
}
|
||||
}
|
14
tsconfig.json
Normal file
14
tsconfig.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"lib": ["es6"],
|
||||
"allowJs": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user