diff --git a/package-lock.json b/package-lock.json index a2780de..b639867 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,14 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/runtime": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.13.tgz", + "integrity": "sha512-8+3UMPBrjFa/6TtKi/7sehPKqfAm4g6K+YQjyyFOLUTxzOngcRZTlAVY8sc2CORJYqdHQY8gRPHmn+qo15rCBw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, "@gizeta/swf-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@gizeta/swf-reader/-/swf-reader-1.0.0.tgz", @@ -12,6 +20,327 @@ "lzma-purejs": "~0.9.3" } }, + "@jimp/bmp": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.16.1.tgz", + "integrity": "sha512-iwyNYQeBawrdg/f24x3pQ5rEx+/GwjZcCXd3Kgc+ZUd+Ivia7sIqBsOnDaMZdKCBPlfW364ekexnlOqyVa0NWg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "bmp-js": "^0.1.0" + } + }, + "@jimp/core": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.16.1.tgz", + "integrity": "sha512-la7kQia31V6kQ4q1kI/uLimu8FXx7imWVajDGtwUG8fzePLWDFJyZl0fdIXVCL1JW2nBcRHidUot6jvlRDi2+g==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "exif-parser": "^0.1.12", + "file-type": "^9.0.0", + "load-bmfont": "^1.3.1", + "mkdirp": "^0.5.1", + "phin": "^2.9.1", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.4.1" + } + }, + "@jimp/custom": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.16.1.tgz", + "integrity": "sha512-DNUAHNSiUI/j9hmbatD6WN/EBIyeq4AO0frl5ETtt51VN1SvE4t4v83ZA/V6ikxEf3hxLju4tQ5Pc3zmZkN/3A==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/core": "^0.16.1" + } + }, + "@jimp/gif": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.16.1.tgz", + "integrity": "sha512-r/1+GzIW1D5zrP4tNrfW+3y4vqD935WBXSc8X/wm23QTY9aJO9Lw6PEdzpYCEY+SOklIFKaJYUAq/Nvgm/9ryw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "gifwrap": "^0.9.2", + "omggif": "^1.0.9" + } + }, + "@jimp/jpeg": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.16.1.tgz", + "integrity": "sha512-8352zrdlCCLFdZ/J+JjBslDvml+fS3Z8gttdml0We759PnnZGqrnPRhkOEOJbNUlE+dD4ckLeIe6NPxlS/7U+w==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "jpeg-js": "0.4.2" + } + }, + "@jimp/plugin-blit": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.16.1.tgz", + "integrity": "sha512-fKFNARm32RoLSokJ8WZXHHH2CGzz6ire2n1Jh6u+XQLhk9TweT1DcLHIXwQMh8oR12KgjbgsMGvrMVlVknmOAg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-blur": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.16.1.tgz", + "integrity": "sha512-1WhuLGGj9MypFKRcPvmW45ht7nXkOKu+lg3n2VBzIB7r4kKNVchuI59bXaCYQumOLEqVK7JdB4glaDAbCQCLyw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-circle": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.16.1.tgz", + "integrity": "sha512-JK7yi1CIU7/XL8hdahjcbGA3V7c+F+Iw+mhMQhLEi7Q0tCnZ69YJBTamMiNg3fWPVfMuvWJJKOBRVpwNTuaZRg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-color": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.16.1.tgz", + "integrity": "sha512-9yQttBAO5SEFj7S6nJK54f+1BnuBG4c28q+iyzm1JjtnehjqMg6Ljw4gCSDCvoCQ3jBSYHN66pmwTV74SU1B7A==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "tinycolor2": "^1.4.1" + } + }, + "@jimp/plugin-contain": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.16.1.tgz", + "integrity": "sha512-44F3dUIjBDHN+Ym/vEfg+jtjMjAqd2uw9nssN67/n4FdpuZUVs7E7wadKY1RRNuJO+WgcD5aDQcsvurXMETQTg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-cover": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.16.1.tgz", + "integrity": "sha512-YztWCIldBAVo0zxcQXR+a/uk3/TtYnpKU2CanOPJ7baIuDlWPsG+YE4xTsswZZc12H9Kl7CiziEbDtvF9kwA/Q==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-crop": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.16.1.tgz", + "integrity": "sha512-UQdva9oQzCVadkyo3T5Tv2CUZbf0klm2cD4cWMlASuTOYgaGaFHhT9st+kmfvXjKL8q3STkBu/zUPV6PbuV3ew==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-displace": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.16.1.tgz", + "integrity": "sha512-iVAWuz2+G6Heu8gVZksUz+4hQYpR4R0R/RtBzpWEl8ItBe7O6QjORAkhxzg+WdYLL2A/Yd4ekTpvK0/qW8hTVw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-dither": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.16.1.tgz", + "integrity": "sha512-tADKVd+HDC9EhJRUDwMvzBXPz4GLoU6s5P7xkVq46tskExYSptgj5713J5Thj3NMgH9Rsqu22jNg1H/7tr3V9Q==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-fisheye": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.16.1.tgz", + "integrity": "sha512-BWHnc5hVobviTyIRHhIy9VxI1ACf4CeSuCfURB6JZm87YuyvgQh5aX5UDKtOz/3haMHXBLP61ZBxlNpMD8CG4A==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-flip": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.16.1.tgz", + "integrity": "sha512-KdxTf0zErfZ8DyHkImDTnQBuHby+a5YFdoKI/G3GpBl3qxLBvC+PWkS2F/iN3H7wszP7/TKxTEvWL927pypT0w==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-gaussian": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.16.1.tgz", + "integrity": "sha512-u9n4wjskh3N1mSqketbL6tVcLU2S5TEaFPR40K6TDv4phPLZALi1Of7reUmYpVm8mBDHt1I6kGhuCJiWvzfGyg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-invert": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.16.1.tgz", + "integrity": "sha512-2DKuyVXANH8WDpW9NG+PYFbehzJfweZszFYyxcaewaPLN0GxvxVLOGOPP1NuUTcHkOdMFbE0nHDuB7f+sYF/2w==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-mask": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.16.1.tgz", + "integrity": "sha512-snfiqHlVuj4bSFS0v96vo2PpqCDMe4JB+O++sMo5jF5mvGcGL6AIeLo8cYqPNpdO6BZpBJ8MY5El0Veckhr39Q==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-normalize": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.16.1.tgz", + "integrity": "sha512-dOQfIOvGLKDKXPU8xXWzaUeB0nvkosHw6Xg1WhS1Z5Q0PazByhaxOQkSKgUryNN/H+X7UdbDvlyh/yHf3ITRaw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-print": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.16.1.tgz", + "integrity": "sha512-ceWgYN40jbN4cWRxixym+csyVymvrryuKBQ+zoIvN5iE6OyS+2d7Mn4zlNgumSczb9GGyZZESIgVcBDA1ezq0Q==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "load-bmfont": "^1.4.0" + } + }, + "@jimp/plugin-resize": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.16.1.tgz", + "integrity": "sha512-u4JBLdRI7dargC04p2Ha24kofQBk3vhaf0q8FwSYgnCRwxfvh2RxvhJZk9H7Q91JZp6wgjz/SjvEAYjGCEgAwQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-rotate": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.16.1.tgz", + "integrity": "sha512-ZUU415gDQ0VjYutmVgAYYxC9Og9ixu2jAGMCU54mSMfuIlmohYfwARQmI7h4QB84M76c9hVLdONWjuo+rip/zg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-scale": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.16.1.tgz", + "integrity": "sha512-jM2QlgThIDIc4rcyughD5O7sOYezxdafg/2Xtd1csfK3z6fba3asxDwthqPZAgitrLgiKBDp6XfzC07Y/CefUw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-shadow": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.16.1.tgz", + "integrity": "sha512-MeD2Is17oKzXLnsphAa1sDstTu6nxscugxAEk3ji0GV1FohCvpHBcec0nAq6/czg4WzqfDts+fcPfC79qWmqrA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugin-threshold": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.16.1.tgz", + "integrity": "sha512-iGW8U/wiCSR0+6syrPioVGoSzQFt4Z91SsCRbgNKTAk7D+XQv6OI78jvvYg4o0c2FOlwGhqz147HZV5utoSLxA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1" + } + }, + "@jimp/plugins": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.16.1.tgz", + "integrity": "sha512-c+lCqa25b+4q6mJZSetlxhMoYuiltyS+ValLzdwK/47+aYsq+kcJNl+TuxIEKf59yr9+5rkbpsPkZHLF/V7FFA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/plugin-blit": "^0.16.1", + "@jimp/plugin-blur": "^0.16.1", + "@jimp/plugin-circle": "^0.16.1", + "@jimp/plugin-color": "^0.16.1", + "@jimp/plugin-contain": "^0.16.1", + "@jimp/plugin-cover": "^0.16.1", + "@jimp/plugin-crop": "^0.16.1", + "@jimp/plugin-displace": "^0.16.1", + "@jimp/plugin-dither": "^0.16.1", + "@jimp/plugin-fisheye": "^0.16.1", + "@jimp/plugin-flip": "^0.16.1", + "@jimp/plugin-gaussian": "^0.16.1", + "@jimp/plugin-invert": "^0.16.1", + "@jimp/plugin-mask": "^0.16.1", + "@jimp/plugin-normalize": "^0.16.1", + "@jimp/plugin-print": "^0.16.1", + "@jimp/plugin-resize": "^0.16.1", + "@jimp/plugin-rotate": "^0.16.1", + "@jimp/plugin-scale": "^0.16.1", + "@jimp/plugin-shadow": "^0.16.1", + "@jimp/plugin-threshold": "^0.16.1", + "timm": "^1.6.1" + } + }, + "@jimp/png": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.16.1.tgz", + "integrity": "sha512-iyWoCxEBTW0OUWWn6SveD4LePW89kO7ZOy5sCfYeDM/oTPLpR8iMIGvZpZUz1b8kvzFr27vPst4E5rJhGjwsdw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.1", + "pngjs": "^3.3.3" + } + }, + "@jimp/tiff": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.16.1.tgz", + "integrity": "sha512-3K3+xpJS79RmSkAvFMgqY5dhSB+/sxhwTFA9f4AVHUK0oKW+u6r52Z1L0tMXHnpbAdR9EJ+xaAl2D4x19XShkQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "utif": "^2.0.1" + } + }, + "@jimp/types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.16.1.tgz", + "integrity": "sha512-g1w/+NfWqiVW4CaXSJyD28JQqZtm2eyKMWPhBBDCJN9nLCN12/Az0WFF3JUAktzdsEC2KRN2AqB1a2oMZBNgSQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/bmp": "^0.16.1", + "@jimp/gif": "^0.16.1", + "@jimp/jpeg": "^0.16.1", + "@jimp/png": "^0.16.1", + "@jimp/tiff": "^0.16.1", + "timm": "^1.6.1" + } + }, + "@jimp/utils": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.16.1.tgz", + "integrity": "sha512-8fULQjB0x4LzUSiSYG6ZtQl355sZjxbv8r9PPAuYHzS9sGiSHJQavNqK/nKnpDsVkU88/vRGcE7t3nMU0dEnVw==", + "requires": { + "@babel/runtime": "^7.7.2", + "regenerator-runtime": "^0.13.3" + } + }, "@jvitela/mustache-wax": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@jvitela/mustache-wax/-/mustache-wax-1.0.3.tgz", @@ -38,6 +367,11 @@ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.1.tgz", "integrity": "sha1-tcdcUyBS3M1qOcAGTHcsjVegbNI=" }, + "any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -71,6 +405,11 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -93,9 +432,18 @@ } }, "bmp-js": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.0.3.tgz", - "integrity": "sha1-ZBE+nHzxICs3btYHvzBibr5XsYo=" + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } }, "buffer-crc32": { "version": "0.2.13", @@ -209,9 +557,9 @@ "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=" + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", + "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==" }, "forever-agent": { "version": "0.6.1", @@ -238,6 +586,59 @@ "maxrects-packer": "^2.5.0", "mustache": "^2.3.0", "tinify": "^1.5.0" + }, + "dependencies": { + "bmp-js": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.0.3.tgz", + "integrity": "sha1-ZBE+nHzxICs3btYHvzBibr5XsYo=" + }, + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" + }, + "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=" + }, + "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" + } + } } }, "getpass": { @@ -248,6 +649,15 @@ "assert-plus": "^1.0.0" } }, + "gifwrap": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.9.2.tgz", + "integrity": "sha512-fcIswrPaiCDAyO8xnWvHSZdWChjKXUanKKpAiWWJ/UTkEi/aYKn5+90e7DE820zbEaVR9CE2y4z9bzhQijZ0BA==", + "requires": { + "image-q": "^1.1.1", + "omggif": "^1.0.10" + } + }, "global": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", @@ -281,6 +691,16 @@ "sshpk": "^1.7.0" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "image-q": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-1.1.1.tgz", + "integrity": "sha1-/IQJlmRGC5DKhi2TALa/u7+/gFY=" + }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -312,32 +732,21 @@ "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=", + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.16.1.tgz", + "integrity": "sha512-+EKVxbR36Td7Hfd23wKGIeEyHbxShZDX6L8uJkgVW3ESA9GiTEPK08tG1XI2r/0w5Ch0HyJF5kPqF9K7EmGjaw==", "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" + "@babel/runtime": "^7.7.2", + "@jimp/custom": "^0.16.1", + "@jimp/plugins": "^0.16.1", + "@jimp/types": "^0.16.1", + "regenerator-runtime": "^0.13.3" } }, "jpeg-js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.2.0.tgz", - "integrity": "sha1-U+RI7J0mPmgyZkZ+lELSxaLvVII=" + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.2.tgz", + "integrity": "sha512-+az2gi/hvex7eLTMTlbRLOhH6P6WFdk2ITI8HJsaH2VqYO0I594zXSYEP+tf4FW+8Cy68ScDXoAsQdyQanv3sw==" }, "jpg-stream": { "version": "1.1.2", @@ -445,16 +854,16 @@ } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } }, "mustache": { @@ -477,6 +886,16 @@ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, + "omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, "parse-bmfont-ascii": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", @@ -589,6 +1008,16 @@ "string_decoder": "~0.10.x" } }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -678,6 +1107,11 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, + "timm": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", + "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==" + }, "tinify": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/tinify/-/tinify-1.5.0.tgz", @@ -701,6 +1135,19 @@ "punycode": "^2.1.1" } }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "tsyringe": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.4.0.tgz", + "integrity": "sha512-SlMApe1lhIq546CDp7bF+IdF4RB6d+9C5T7B0AS0P/Bm+Qpizj/gEmZzvw9J/KlXPEt4qHTbi1TRvX3rCPSdTg==", + "requires": { + "tslib": "^1.9.3" + } + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -730,6 +1177,14 @@ "ip-regex": "^1.0.1" } }, + "utif": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", + "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", + "requires": { + "pako": "^1.0.5" + } + }, "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", diff --git a/package.json b/package.json index f00db86..ac9b35e 100644 --- a/package.json +++ b/package.json @@ -14,12 +14,15 @@ "bytebuffer": "^5.0.1", "concat-frames": "^1.0.3", "free-tex-packer-core": "^0.3.2", + "jimp": "^0.16.1", "jpg-stream": "^1.1.2", "lodash": "^4.17.20", "node-fetch": "^2.6.1", "node-gzip": "^1.1.2", "png-stream": "^1.0.5", + "reflect-metadata": "^0.1.13", "stream-to-array": "^2.3.0", + "tsyringe": "^4.4.0", "xml2js": "^0.4.23" }, "devDependencies": {} diff --git a/src/Main.ts b/src/Main.ts index 8bcda19..d883500 100644 --- a/src/Main.ts +++ b/src/Main.ts @@ -1,123 +1,34 @@ +import "reflect-metadata"; 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"; -import EffectConverter from "./converters/effect/EffectConverter"; -import EffectDownloader from "./downloaders/EffectDownloader"; -import PetDownloader from "./downloaders/PetDownloader"; -import PetConverter from "./converters/pet/PetConverter"; +import {container} from "tsyringe"; +import FigureConverter from "./figure/FigureConverter"; +import FurnitureConverter from "./furniture/FurnitureConverter"; +import PetConverter from "./pet/PetConverter"; +import EffectConverter from "./effect/EffectConverter"; (async () => { - const config = new Configuration(); + const config = container.resolve(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 outputFolderEffect = new File(config.getValue("output.folder.effect")); - if (!outputFolderEffect.isDirectory()) { - outputFolderEffect.mkdirs(); - } - - const outputFolderPet = new File(config.getValue("output.folder.pet")); - if (!outputFolderPet.isDirectory()) { - outputFolderPet.mkdirs(); - } - - const spriteSheetConverter = new SpriteSheetConverter(); - const figureConverter = new FigureConverter(config); - const furnitureConverter = new FurnitureConverter(config); - const effectConverter = new EffectConverter(config); - const petConverter = new PetConverter(); - 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()); - console.log(e); - } - }); + const figureConverter = container.resolve(FigureConverter); + await figureConverter.convertAsync(); } if (config.getBoolean("convert.furniture")) { - let count = 0; - const furnitureDownloader = new FurnitureDownloader(config); - await furnitureDownloader.download(async function (habboAssetSwf: HabboAssetSWF, className: string) { - console.log("Attempt parsing furniture: " + habboAssetSwf.getDocumentClass()); - - try { - const spriteSheetType = await spriteSheetConverter.generateSpriteSheet(habboAssetSwf, outputFolderFurniture.path, "furniture"); - if (spriteSheetType !== null) { - await furnitureConverter.fromHabboAsset(habboAssetSwf, outputFolderFurniture.path, "furniture", spriteSheetType); - } - } catch (e) { - console.log("Furniture error: " + habboAssetSwf.getDocumentClass()); - console.log(e); - } - }); - - console.log(`Parsed ${++count} furnitures`) - } - - if (config.getBoolean("convert.effect")) { - const effectDownloader = new EffectDownloader(config); - await effectDownloader.download(async function (habboAssetSwf: HabboAssetSWF) { - console.log("Attempt parsing effect: " + habboAssetSwf.getDocumentClass()); - - try { - const spriteSheetType = await spriteSheetConverter.generateSpriteSheet(habboAssetSwf, outputFolderFurniture.path, "effect"); - if (spriteSheetType !== null) { - await effectConverter.fromHabboAsset(habboAssetSwf, outputFolderEffect.path, "effect", spriteSheetType); - } - } catch (e) { - console.log(e); - console.log("Effect error: " + habboAssetSwf.getDocumentClass()); - } - }); + const furnitureConverter = container.resolve(FurnitureConverter); + await furnitureConverter.convertAsync(); } if (config.getBoolean("convert.pet")) { - const petDownloader = new PetDownloader(config); - await petDownloader.download(async function (habboAssetSwf: HabboAssetSWF) { - console.log("Attempt parsing pet: " + habboAssetSwf.getDocumentClass()); + const petConverter = container.resolve(PetConverter); + await petConverter.convertAsync(); + } - try { - const spriteSheetType = await spriteSheetConverter.generateSpriteSheet(habboAssetSwf, outputFolderPet.path, "pet"); - if (spriteSheetType !== null) { - await petConverter.fromHabboAsset(habboAssetSwf, outputFolderPet.path, "pet", spriteSheetType); - } - } catch (e) { - console.log(e); - console.log("Pet error: " + habboAssetSwf.getDocumentClass()); - } - }); + if (config.getBoolean("convert.effect")) { + const effectConverter = container.resolve(EffectConverter); + await effectConverter.convertAsync(); } console.log('finished!'); - - - /*outputFolderEffect.rmdir({ - recursive: true, - force: true - });*/ })() \ No newline at end of file diff --git a/src/converters/util/SpriteSheetConverter.ts b/src/bundle/BundleProvider.ts similarity index 82% rename from src/converters/util/SpriteSheetConverter.ts rename to src/bundle/BundleProvider.ts index b858772..57ff49c 100644 --- a/src/converters/util/SpriteSheetConverter.ts +++ b/src/bundle/BundleProvider.ts @@ -1,14 +1,16 @@ -let {packAsync} = require("free-tex-packer-core"); +import HabboAssetSWF from "../swf/HabboAssetSWF"; +import BundleTypes from "./BundleTypes"; +import SymbolClassTag from "../swf/tags/SymbolClassTag"; +import ImageTag from "../swf/tags/ImageTag"; +import {singleton} from "tsyringe"; -import HabboAssetSWF from "../../swf/HabboAssetSWF"; -import SymbolClassTag from "../../swf/tags/SymbolClassTag"; -import ImageTag from "../../swf/tags/ImageTag"; -import ArchiveType from "../ArchiveType"; +const {packAsync} = require('free-tex-packer-core'); -export default class SpriteSheetConverter { +@singleton() +export default class BundleProvider { public static imageSource: Map = new Map(); - public async generateSpriteSheet(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string): Promise { + public async generateSpriteSheet(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string): Promise { const tagList: Array = habboAssetSWF.symbolTags(); const names: Array = new Array(); const tags: Array = new Array(); @@ -31,7 +33,7 @@ export default class SpriteSheetConverter { (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)); + BundleProvider.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")) { @@ -47,6 +49,7 @@ export default class SpriteSheetConverter { } if ((imageTag.className.includes("_64_") && type === "furniture") || + (imageTag.className.includes("_1_") && type === "furniture") || (imageTag.className.includes("_icon_") && type === "furniture") || (imageTag.className.includes("_h_") && (type === "figure" || type === "effect")) || (imageTag.className.includes("_64_") && type === "pet")) { @@ -57,6 +60,7 @@ export default class SpriteSheetConverter { } } + if (images.length === 0) { return null; } @@ -64,7 +68,7 @@ export default class SpriteSheetConverter { return await this.packImages(habboAssetSWF.getDocumentClass(), outputFolder + "/", images); } - async packImages(documentClass: string, outputFolder: string, images: Array<{ path: string, contents: Buffer }>): Promise { + async packImages(documentClass: string, outputFolder: string, images: Array<{ path: string, contents: Buffer }>): Promise { let options = { textureName: documentClass, width: 3072, @@ -76,7 +80,7 @@ export default class SpriteSheetConverter { exporter: "Pixi" }; - const archiveType: ArchiveType = {} as any; + const archiveType: BundleTypes = {} as any; const imageData: { name: string, buffer: Buffer @@ -103,6 +107,7 @@ export default class SpriteSheetConverter { archiveType.spriteSheetType.meta.image = imageData.name; archiveType.imageData = imageData; } + return archiveType; } } \ No newline at end of file diff --git a/src/converters/util/SpriteSheetTypes.ts b/src/bundle/BundleTypes.ts similarity index 86% rename from src/converters/util/SpriteSheetTypes.ts rename to src/bundle/BundleTypes.ts index a076a57..375bd4c 100644 --- a/src/converters/util/SpriteSheetTypes.ts +++ b/src/bundle/BundleTypes.ts @@ -1,3 +1,11 @@ +export default interface BundleTypes { + spriteSheetType: SpriteSheetType, + imageData: { + name: string, + buffer: Buffer + } +} + export interface SpriteSheetType { frames: SpriteSheetFrames, meta: SpriteSheetMeta diff --git a/src/config.json b/src/config.json index b4a0061..99cfe11 100644 --- a/src/config.json +++ b/src/config.json @@ -3,11 +3,11 @@ "output.folder.figure": "/home/user/WebstormProjects/sites/assets.nitro.se/game/gordon/figure-test/", "output.folder.effect": "/home/user/WebstormProjects/sites/assets.nitro.se/game/gordon/effect-test/", "output.folder.pet": "/home/user/WebstormProjects/sites/assets.nitro.se/game/gordon/pet-test/", - "furnidata.url": "http://assets.nitro.se/game/gamedata/furnidata-entry.xml", - "figuremap.url": "http://assets.nitro.se/game/gordon/PRODUCTION-201701242205-837386173/figuremap.xml", + "furnidata.url": "http://assets.nitro.se/game/harmony/furnidata.xml", + "figuremap.url": "http://assets.nitro.se/game/gordon/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.furniture": "/home/user/WebstormProjects/sites/assets.nitro.se/game/harmony/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": "/home/user/WebstormProjects/sites/assets.nitro.se/game/gordon/PRODUCTION-201701242205-837386173/%className%.swf", "dynamic.download.url.pet": "/home/user/WebstormProjects/sites/assets.nitro.se/game/gordon/PRODUCTION-201701242205-837386173/%className%.swf", diff --git a/src/config/Configuration.ts b/src/config/Configuration.ts index 29c45b3..70bc293 100644 --- a/src/config/Configuration.ts +++ b/src/config/Configuration.ts @@ -1,8 +1,11 @@ +import {singleton} from "tsyringe"; + const fs = require('fs/promises'); const fetch = require('node-fetch'); const config = require('../config.json'); +@singleton() export default class Configuration { private readonly _config: Map; diff --git a/src/converters/ArchiveType.ts b/src/converters/ArchiveType.ts deleted file mode 100644 index c8ec11f..0000000 --- a/src/converters/ArchiveType.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {SpriteSheetType} from "./util/SpriteSheetTypes"; - -export default interface ArchiveType { - spriteSheetType: SpriteSheetType, - imageData: { - name: string, - buffer: Buffer - } -} \ No newline at end of file diff --git a/src/converters/figure/FigureConverter.ts b/src/converters/figure/FigureConverter.ts deleted file mode 100644 index 16779ec..0000000 --- a/src/converters/figure/FigureConverter.ts +++ /dev/null @@ -1,65 +0,0 @@ -import HabboAssetSWF from "../../swf/HabboAssetSWF"; -import DefineBinaryDataTag from "../../swf/tags/DefineBinaryDataTag"; -import Configuration from "../../config/Configuration"; -import FigureJsonMapper from "./FigureJsonMapper"; -import {FigureJson} from "./FigureJsonType"; -import File from "../../utils/File"; -import ArchiveType from "../ArchiveType"; -import NitroBundle from "../../utils/NitroBundle"; - -const xml2js = require('xml2js'); -const parser = new xml2js.Parser(/* options */); -const fs = require('fs').promises; - -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 { - 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, archiveType: ArchiveType) { - const manifestJson = await this.convertXML2JSON(habboAssetSWF); - if (manifestJson !== null) { - manifestJson.spritesheet = archiveType.spriteSheetType; - - const path = outputFolder + "/" + habboAssetSWF.getDocumentClass() + ".nitro"; - const assetOuputFolder = new File(path); - if (assetOuputFolder.exists()) { - console.log("Figure already exists or the directory is not empty!"); - - return; - } - - const nitroBundle = new NitroBundle(); - nitroBundle.addFile(habboAssetSWF.getDocumentClass() + ".json", Buffer.from(JSON.stringify(manifestJson))); - nitroBundle.addFile(archiveType.imageData.name, archiveType.imageData.buffer); - - const buffer = await nitroBundle.toBufferAsync(); - await fs.writeFile(path, buffer); - } - } -} \ No newline at end of file diff --git a/src/converters/effect/EffectConverter.ts b/src/effect/EffectConverter.ts similarity index 55% rename from src/converters/effect/EffectConverter.ts rename to src/effect/EffectConverter.ts index 277e462..fdc1608 100644 --- a/src/converters/effect/EffectConverter.ts +++ b/src/effect/EffectConverter.ts @@ -1,22 +1,27 @@ -import HabboAssetSWF from "../../swf/HabboAssetSWF"; -import DefineBinaryDataTag from "../../swf/tags/DefineBinaryDataTag"; -import ArchiveType from "../ArchiveType"; -import File from "../../utils/File"; -import NitroBundle from "../../utils/NitroBundle"; -import {EffectJson} from "./EffectTypes"; -import Configuration from "../../config/Configuration"; -import EffectJsonMapper from "./EffectJsonMapper"; +import HabboAssetSWF from "../swf/HabboAssetSWF"; +import DefineBinaryDataTag from "../swf/tags/DefineBinaryDataTag"; +import {EffectJson} from "./mapper/EffectTypes"; +import BundleTypes from "../bundle/BundleTypes"; +import File from "../utils/File"; +import NitroBundle from "../utils/NitroBundle"; +import EffectDownloader from "./EffectDownloader"; +import EffectJsonMapper from "./mapper/EffectJsonMapper"; +import Configuration from "../config/Configuration"; +import BundleProvider from "../bundle/BundleProvider"; +import {singleton} from "tsyringe"; const xml2js = require('xml2js'); const parser = new xml2js.Parser(/* options */); const fs = require('fs').promises; +@singleton() export default class EffectConverter { - private readonly _effectJsonMapper: EffectJsonMapper; - - constructor(config: Configuration) { - this._effectJsonMapper = new EffectJsonMapper(); + constructor( + private readonly _effectDownloader: EffectDownloader, + private readonly _effectJsonMapper: EffectJsonMapper, + private readonly _config: Configuration, + private readonly _bundleProvider: BundleProvider) { } private static getBinaryData(habboAssetSWF: HabboAssetSWF, type: string, documentNameTwice: boolean) { @@ -55,15 +60,15 @@ export default class EffectConverter { return this._effectJsonMapper.mapXML(habboAssetSWF, manifestXML, animationXML); } - public async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, archiveType: ArchiveType) { + private async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, archiveType: BundleTypes) { const effectJson = await this.convertXML2JSON(habboAssetSWF); if (effectJson !== null) { effectJson.spritesheet = archiveType.spriteSheetType; effectJson.type = type; const path = outputFolder + "/" + habboAssetSWF.getDocumentClass() + ".nitro"; - const assetOuputFolder = new File(path); - if (assetOuputFolder.exists()) { + const assetOutputFolder = new File(path); + if (assetOutputFolder.exists()) { console.log("Effect already exists or the directory is not empty!"); return; @@ -77,4 +82,26 @@ export default class EffectConverter { await fs.writeFile(path, buffer); } } + + public async convertAsync() { + const outputFolderEffect = new File(this._config.getValue("output.folder.effect")); + if (!outputFolderEffect.isDirectory()) { + outputFolderEffect.mkdirs(); + } + + const effectConverter = this; + await this._effectDownloader.download(async function (habboAssetSwf: HabboAssetSWF) { + console.log("Attempt parsing effect: " + habboAssetSwf.getDocumentClass()); + + try { + const spriteSheetType = await effectConverter._bundleProvider.generateSpriteSheet(habboAssetSwf, outputFolderEffect.path, "effect"); + if (spriteSheetType !== null) { + await effectConverter.fromHabboAsset(habboAssetSwf, outputFolderEffect.path, "effect", spriteSheetType); + } + } catch (e) { + console.log(e); + console.log("Effect error: " + habboAssetSwf.getDocumentClass()); + } + }); + } } \ No newline at end of file diff --git a/src/downloaders/EffectDownloader.ts b/src/effect/EffectDownloader.ts similarity index 88% rename from src/downloaders/EffectDownloader.ts rename to src/effect/EffectDownloader.ts index 92c80c9..9129701 100644 --- a/src/downloaders/EffectDownloader.ts +++ b/src/effect/EffectDownloader.ts @@ -1,19 +1,21 @@ import Configuration from "../config/Configuration"; import HabboAssetSWF from "../swf/HabboAssetSWF"; import File from "../utils/File"; +import {singleton} from "tsyringe"; +import Logger from "../utils/Logger"; const fetch = require('node-fetch'); const xml2js = require('xml2js'); const parser = new xml2js.Parser(/* options */); +@singleton() export default class EffectDownloader { - private readonly _config: Configuration; - constructor(config: Configuration) { - this._config = config; + constructor( + private readonly _config: Configuration, + private readonly _logger: Logger) { } - public static types: Map = new Map(); public async download(callback: (habboAssetSwf: HabboAssetSWF) => Promise) { @@ -21,7 +23,6 @@ export default class EffectDownloader { const figureMap = await this.parseEffectMap(); const map = figureMap.map; - let count = 0; for (const lib of map.effect) { const info = lib['$']; const className: string = info.lib; @@ -48,7 +49,7 @@ export default class EffectDownloader { const file = new File(url); if (!file.exists()) { console.log("SWF File does not exist: " + file.path); - return; + continue; } } @@ -59,8 +60,7 @@ export default class EffectDownloader { EffectDownloader.types.set(className, info.type); await callback(newHabboAssetSWF); } catch (e) { - console.log(className); - console.log(e); + await this._logger.logErrorAsync(`[${className}]` + e); } } } diff --git a/src/converters/effect/EffectAnimationXMLTypes.ts b/src/effect/mapper/EffectAnimationXMLTypes.ts similarity index 100% rename from src/converters/effect/EffectAnimationXMLTypes.ts rename to src/effect/mapper/EffectAnimationXMLTypes.ts diff --git a/src/converters/effect/EffectJsonMapper.ts b/src/effect/mapper/EffectJsonMapper.ts similarity index 95% rename from src/converters/effect/EffectJsonMapper.ts rename to src/effect/mapper/EffectJsonMapper.ts index 0b99edd..6f4c472 100644 --- a/src/converters/effect/EffectJsonMapper.ts +++ b/src/effect/mapper/EffectJsonMapper.ts @@ -12,41 +12,44 @@ import { Frame, Fx, Item, Override, Remove, Shadow, Sprite } from "./EffectTypes"; -import EffectDownloader from "../../downloaders/EffectDownloader"; import {ManifestXML} from "./EffectManifestXMLTypes"; -import SpriteSheetConverter from "../util/SpriteSheetConverter"; import { AnimationXML, BodyPartXML } from "./EffectAnimationXMLTypes"; +import {singleton} from "tsyringe"; +import EffectDownloader from "../EffectDownloader"; +import BundleProvider from "../../bundle/BundleProvider"; +@singleton() export default class EffectJsonMapper { public static readonly MUST_START_WITH: string = "h_"; + public mapXML(habboAssetSWF: HabboAssetSWF, manifest: any, animation: any): EffectJson { const name = habboAssetSWF.getDocumentClass(); const result = {} as EffectJson; result.name = name; result.type = EffectDownloader.types.get(name) as string; - EffectJsonMapper.mapManifestXML(new ManifestXML(manifest), result); + this.mapManifestXML(new ManifestXML(manifest), result); EffectJsonMapper.mapAnimationXML(new AnimationXML(animation), result); return result; } - private static mapManifestXML(manifestXML: ManifestXML, output: EffectJson) { + private mapManifestXML(manifestXML: ManifestXML, output: EffectJson) { const assets: AssetsJSON = {}; for (const assetXML of manifestXML.library.assets) { - if (assetXML.name.startsWith(this.MUST_START_WITH)) { + if (assetXML.name.startsWith(EffectJsonMapper.MUST_START_WITH)) { const asset: AssetJSON = {} as any; if (assetXML.param != undefined && assetXML.param.value !== undefined) { asset.x = parseInt(assetXML.param.value.split(",")[0]); asset.y = parseInt(assetXML.param.value.split(",")[1]); } - if (SpriteSheetConverter.imageSource.has(assetXML.name)) { - asset.source = SpriteSheetConverter.imageSource.get(assetXML.name) as any; + if (BundleProvider.imageSource.has(assetXML.name)) { + asset.source = BundleProvider.imageSource.get(assetXML.name) as string; } assets[assetXML.name] = asset; @@ -55,10 +58,10 @@ export default class EffectJsonMapper { output.assets = assets; - if (manifestXML.library.aliases.length > 0 || SpriteSheetConverter.imageSource.size > 0) { + if (manifestXML.library.aliases.length > 0 || BundleProvider.imageSource.size > 0) { const aliases: Aliases = {}; for (const aliasXML of manifestXML.library.aliases) { - if (aliasXML.name.startsWith(this.MUST_START_WITH)) { + if (aliasXML.name.startsWith(EffectJsonMapper.MUST_START_WITH)) { const alias: Alias = {} as any; alias.link = aliasXML.link; diff --git a/src/converters/effect/EffectManifestXMLTypes.ts b/src/effect/mapper/EffectManifestXMLTypes.ts similarity index 100% rename from src/converters/effect/EffectManifestXMLTypes.ts rename to src/effect/mapper/EffectManifestXMLTypes.ts diff --git a/src/converters/effect/EffectTypes.ts b/src/effect/mapper/EffectTypes.ts similarity index 97% rename from src/converters/effect/EffectTypes.ts rename to src/effect/mapper/EffectTypes.ts index d96ba21..f23e133 100644 --- a/src/converters/effect/EffectTypes.ts +++ b/src/effect/mapper/EffectTypes.ts @@ -1,4 +1,4 @@ -import {SpriteSheetType} from "../util/SpriteSheetTypes"; +import {SpriteSheetType} from "../../bundle/BundleTypes"; export interface EffectJson { type: string, diff --git a/src/figure/FigureConverter.ts b/src/figure/FigureConverter.ts new file mode 100644 index 0000000..a653501 --- /dev/null +++ b/src/figure/FigureConverter.ts @@ -0,0 +1,97 @@ +import {singleton} from "tsyringe"; +import HabboAssetSWF from "../swf/HabboAssetSWF"; +import FigureJsonMapper from "./mapper/FigureJsonMapper"; +import Configuration from "../config/Configuration"; +import {FigureJson} from "./mapper/FigureJsonType"; +import DefineBinaryDataTag from "../swf/tags/DefineBinaryDataTag"; +import BundleTypes from "../bundle/BundleTypes"; +import File from "../utils/File"; +import NitroBundle from "../utils/NitroBundle"; +import BundleProvider from "../bundle/BundleProvider"; +import FigureDownloader from "./FigureDownloader"; +import Logger from "../utils/Logger"; + +const xml2js = require('xml2js'); +const parser = new xml2js.Parser(/* options */); +const fs = require('fs').promises; + +@singleton() +export default class FigureConverter { + + constructor( + private readonly _figureDownloader: FigureDownloader, + private readonly _figureJsonMapper: FigureJsonMapper, + private readonly _config: Configuration, + private readonly _bundleProvider: BundleProvider, + private readonly _logger: Logger) { + } + + 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 { + 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; + } + + private async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, archiveType: BundleTypes) { + const manifestJson = await this.convertXML2JSON(habboAssetSWF); + if (manifestJson !== null) { + manifestJson.spritesheet = archiveType.spriteSheetType; + + const path = outputFolder + "/" + habboAssetSWF.getDocumentClass() + ".nitro"; + const assetOuputFolder = new File(path); + if (assetOuputFolder.exists()) { + console.log("Figure already exists or the directory is not empty!"); + + return; + } + + const nitroBundle = new NitroBundle(); + nitroBundle.addFile(habboAssetSWF.getDocumentClass() + ".json", Buffer.from(JSON.stringify(manifestJson))); + nitroBundle.addFile(archiveType.imageData.name, archiveType.imageData.buffer); + + const buffer = await nitroBundle.toBufferAsync(); + await fs.writeFile(path, buffer); + } + } + + public async convertAsync() { + const outputFolderFigure = new File(this._config.getValue("output.folder.figure")); + if (!outputFolderFigure.isDirectory()) { + outputFolderFigure.mkdirs(); + } + + const figureConverter = this; + + await this._figureDownloader.download(async function (habboAssetSwf: HabboAssetSWF) { + + console.log("Attempt parsing figure: " + habboAssetSwf.getDocumentClass()); + + try { + const spriteSheetType = await figureConverter._bundleProvider.generateSpriteSheet(habboAssetSwf, outputFolderFigure.path, "figure"); + if (spriteSheetType !== null) + await figureConverter.fromHabboAsset(habboAssetSwf, outputFolderFigure.path, "figure", spriteSheetType); + + } catch (e) { + await figureConverter._logger.logErrorAsync("Figure error: " + habboAssetSwf.getDocumentClass() + e); + console.log("Figure error: " + habboAssetSwf.getDocumentClass()); + console.log(e); + } + }); + } +} \ No newline at end of file diff --git a/src/downloaders/FigureDownloader.ts b/src/figure/FigureDownloader.ts similarity index 58% rename from src/downloaders/FigureDownloader.ts rename to src/figure/FigureDownloader.ts index f09f851..60a4306 100644 --- a/src/downloaders/FigureDownloader.ts +++ b/src/figure/FigureDownloader.ts @@ -1,18 +1,19 @@ import Configuration from "../config/Configuration"; import HabboAssetSWF from "../swf/HabboAssetSWF"; import File from "../utils/File"; +import {singleton} from "tsyringe"; +import Logger from "../utils/Logger"; -const fs = require("fs"); const fetch = require('node-fetch'); const xml2js = require('xml2js'); const parser = new xml2js.Parser(/* options */); +@singleton() export default class FigureDownloader { - private readonly _config: Configuration; - - constructor(config: Configuration) { - this._config = config; + constructor( + private readonly _config: Configuration, + private readonly _logger: Logger) { } @@ -36,36 +37,35 @@ export default class FigureDownloader { } 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... - if (className !== "hh_human_hats") continue; + const url = this._config.getValue("dynamic.download.url.figure").replace("%className%", className); + let buffer: Buffer | null = null; - const url = this._config.getValue("dynamic.download.url.figure").replace("%className%", className); - let buffer: Buffer | null = null; - - if (url.includes("http")) { - const fetchData = await fetch(url); - if (fetchData.status === 404) { - console.log("SWF File does not exist: " + url); - continue; - } - - const arrayBuffer = await fetchData.arrayBuffer(); - buffer = Buffer.from(arrayBuffer); - } else { - const file = new File(url); - if (!file.exists()) { - console.log("SWF File does not exist: " + file.path); - return; - } + if (url.includes("http")) { + const fetchData = await fetch(url); + if (fetchData.status === 404) { + console.log("SWF File does not exist: " + url); + continue; } + const arrayBuffer = await fetchData.arrayBuffer(); + buffer = Buffer.from(arrayBuffer); + } else { + const file = new File(url); + if (!file.exists()) { + console.log("SWF File does not exist: " + file.path); + continue; + } + } + + try { const newHabboAssetSWF: HabboAssetSWF = new HabboAssetSWF(buffer !== null ? buffer : url); await newHabboAssetSWF.setupAsync(); FigureDownloader.types.set(className, lib.part[0]['$'].type); await callback(newHabboAssetSWF); + } catch (e) { + await this._logger.logErrorAsync("[" + className + "]" + e); } } } diff --git a/src/converters/figure/FigureJsonMapper.ts b/src/figure/mapper/FigureJsonMapper.ts similarity index 88% rename from src/converters/figure/FigureJsonMapper.ts rename to src/figure/mapper/FigureJsonMapper.ts index 386df10..15fcbc0 100644 --- a/src/converters/figure/FigureJsonMapper.ts +++ b/src/figure/mapper/FigureJsonMapper.ts @@ -1,18 +1,19 @@ import Configuration from "../../config/Configuration"; import HabboAssetSWF from "../../swf/HabboAssetSWF"; import {FigureAsset, FigureAssets, FigureJson} from "./FigureJsonType"; -import FigureDownloader from "../../downloaders/FigureDownloader"; -import SpriteSheetConverter from "../util/SpriteSheetConverter"; import {FigureXMLManifest} from "./FigureXMLTypes"; +import FigureDownloader from "../FigureDownloader"; +import {singleton} from "tsyringe"; +import BundleProvider from "../../bundle/BundleProvider"; +@singleton() export default class FigureJsonMapper { private static MUST_START_WITH: string = "h_"; - private readonly _config: Configuration; - - constructor(config: Configuration) { - this._config = config; + constructor( + private readonly _config: Configuration + ) { } @@ -47,8 +48,8 @@ export default class FigureJsonMapper { figureAsset.x = parseFloat(asset.param.value.split(',')[0]); figureAsset.y = parseFloat(asset.param.value.split(',')[1]); - if (SpriteSheetConverter.imageSource.has(name)) { - figureAsset.source = SpriteSheetConverter.imageSource.get(name) as string; + if (BundleProvider.imageSource.has(name)) { + figureAsset.source = BundleProvider.imageSource.get(name) as string; } assets[name] = figureAsset; diff --git a/src/converters/figure/FigureJsonType.ts b/src/figure/mapper/FigureJsonType.ts similarity index 84% rename from src/converters/figure/FigureJsonType.ts rename to src/figure/mapper/FigureJsonType.ts index b4e4d24..b215c05 100644 --- a/src/converters/figure/FigureJsonType.ts +++ b/src/figure/mapper/FigureJsonType.ts @@ -1,4 +1,4 @@ -import {SpriteSheetType} from "../util/SpriteSheetTypes"; +import {SpriteSheetType} from "../../bundle/BundleTypes"; export interface FigureJson { type: string, diff --git a/src/converters/figure/FigureXMLTypes.ts b/src/figure/mapper/FigureXMLTypes.ts similarity index 100% rename from src/converters/figure/FigureXMLTypes.ts rename to src/figure/mapper/FigureXMLTypes.ts diff --git a/src/converters/furniture/FurnitureConverter.ts b/src/furniture/FurnitureConverter.ts similarity index 61% rename from src/converters/furniture/FurnitureConverter.ts rename to src/furniture/FurnitureConverter.ts index 19dac13..58b074a 100644 --- a/src/converters/furniture/FurnitureConverter.ts +++ b/src/furniture/FurnitureConverter.ts @@ -1,23 +1,30 @@ -import HabboAssetSWF from "../../swf/HabboAssetSWF"; -import DefineBinaryDataTag from "../../swf/tags/DefineBinaryDataTag"; -import Configuration from "../../config/Configuration"; -import FurniJsonMapper from "./FurniJsonMapper"; -import {FurniJson} from "./FurniTypes"; -import File from "../../utils/File"; -import ArchiveType from "../ArchiveType"; -import NitroBundle from "../../utils/NitroBundle"; +import FurniJsonMapper from "./mapper/FurniJsonMapper"; +import Configuration from "../config/Configuration"; +import HabboAssetSWF from "../swf/HabboAssetSWF"; +import DefineBinaryDataTag from "../swf/tags/DefineBinaryDataTag"; +import {FurniJson} from "./mapper/FurniTypes"; +import BundleTypes from "../bundle/BundleTypes"; +import File from "../utils/File"; +import NitroBundle from "../utils/NitroBundle"; +import BundleProvider from "../bundle/BundleProvider"; +import FurnitureDownloader from "./FurnitureDownloader"; +import {singleton} from "tsyringe"; +import Logger from "../utils/Logger"; const xml2js = require('xml2js'); const parser = new xml2js.Parser(/* options */); const fs = require('fs').promises; +@singleton() export default class FurnitureConverter { - private readonly _furniJsonMapper: FurniJsonMapper; - - constructor(config: Configuration) { - this._furniJsonMapper = new FurniJsonMapper(); + constructor( + private readonly _furniDownloader: FurnitureDownloader, + private readonly _furniJsonMapper: FurniJsonMapper, + private readonly _config: Configuration, + private readonly _bundleProvider: BundleProvider, + private readonly _logger: Logger) { } private static getBinaryData(habboAssetSWF: HabboAssetSWF, type: string, documentNameTwice: boolean) { @@ -76,15 +83,15 @@ export default class FurnitureConverter { return this._furniJsonMapper.mapXML(assetXml, indexXml, logicXml, visualizationXml); } - public async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, archiveType: ArchiveType) { + private async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, archiveType: BundleTypes) { const furnitureJson = await this.convertXML2JSON(habboAssetSWF); if (furnitureJson !== null) { furnitureJson.spritesheet = archiveType.spriteSheetType; furnitureJson.type = type; const path = outputFolder + "/" + habboAssetSWF.getDocumentClass() + ".nitro"; - const assetOuputFolder = new File(path); - if (assetOuputFolder.exists()) { + const assetOutputFolder = new File(path); + if (assetOutputFolder.exists()) { console.log("Furniture already exists or the directory is not empty!"); return; @@ -98,4 +105,25 @@ export default class FurnitureConverter { await fs.writeFile(path, buffer); } } + + public async convertAsync() { + const outputFolderFurniture = new File(this._config.getValue("output.folder.furniture")); + if (!outputFolderFurniture.isDirectory()) { + outputFolderFurniture.mkdirs(); + } + + const furnitureConverter = this; + await this._furniDownloader.download(async function (habboAssetSwf: HabboAssetSWF, className: string) { + console.log("Attempt parsing furniture: " + habboAssetSwf.getDocumentClass()); + + try { + const spriteSheetType = await furnitureConverter._bundleProvider.generateSpriteSheet(habboAssetSwf, outputFolderFurniture.path, "furniture"); + if (spriteSheetType !== null) { + await furnitureConverter.fromHabboAsset(habboAssetSwf, outputFolderFurniture.path, "furniture", spriteSheetType); + } + } catch (e) { + await furnitureConverter._logger.logErrorAsync("Furniture error: " + habboAssetSwf.getDocumentClass() + " " + e); + } + }); + } } \ No newline at end of file diff --git a/src/downloaders/FurnitureDownloader.ts b/src/furniture/FurnitureDownloader.ts similarity index 91% rename from src/downloaders/FurnitureDownloader.ts rename to src/furniture/FurnitureDownloader.ts index 3b5c02c..f8e0c5c 100644 --- a/src/downloaders/FurnitureDownloader.ts +++ b/src/furniture/FurnitureDownloader.ts @@ -2,6 +2,8 @@ import HabboAssetSWF from "../swf/HabboAssetSWF"; import Configuration from "../config/Configuration"; import {type} from "os"; import File from "../utils/File"; +import {singleton} from "tsyringe"; +import Logger from "../utils/Logger"; const fs = require("fs"); const fetch = require('node-fetch'); @@ -11,12 +13,12 @@ const util = require('util'); const readFile = util.promisify(fs.readFile); +@singleton() export default class FurnitureDownloader { - private readonly _config: Configuration; - - constructor(config: Configuration) { - this._config = config; + constructor( + private readonly _config: Configuration, + private readonly _logger: Logger) { } public async download(callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise) { @@ -67,9 +69,7 @@ export default class FurnitureDownloader { } async extractFurniture(revision: string, className: string, callback: (habboAssetSwf: HabboAssetSWF, className: string) => Promise) { - //if (className !== "rare_dragonlamp" && className !== "tiki_bflies" && className !== "room_wl15_ele") return; - - //if (className !== 'scifidoor') return; + //if (/*className !== 'present_wrap' && */className !== 'holo_dragon') return; const url = this._config.getValue("dynamic.download.url.furniture").replace("%revision%", revision).replace("%className%", className); let buffer: Buffer | null = null; @@ -97,8 +97,7 @@ export default class FurnitureDownloader { await callback(newHabboAssetSWF, className); } catch (e) { - console.log("Error with furniture: " + url); - console.log(e); + await this._logger.logErrorAsync(`Error with furniture: ${url} \n ${e}`); } } diff --git a/src/converters/furniture/FurniJsonMapper.ts b/src/furniture/mapper/FurniJsonMapper.ts similarity index 88% rename from src/converters/furniture/FurniJsonMapper.ts rename to src/furniture/mapper/FurniJsonMapper.ts index e1f4dbd..59fffe4 100644 --- a/src/converters/furniture/FurniJsonMapper.ts +++ b/src/furniture/mapper/FurniJsonMapper.ts @@ -22,7 +22,6 @@ import { Visualization, VisualizationLayers } from "./FurniTypes"; -import SpriteSheetConverter from "../util/SpriteSheetConverter"; import {AssetsXML, IndexXML, LogicXML} from "./FurniXMLTypes"; import { AnimationLayerXML, @@ -32,8 +31,10 @@ import { VisualizationDataXML, VisualizationXML } from "./VisualizationXMLTypes"; -import {log} from "util"; +import BundleProvider from "../../bundle/BundleProvider"; +import {singleton} from "tsyringe"; +@singleton() export default class FurniJsonMapper { private static readonly VISUALIZATION_DEFAULT_SIZE = 64; @@ -42,7 +43,7 @@ export default class FurniJsonMapper { public mapXML(assets: any, indexXML: any, logic: any, visualization: any): FurniJson { const furniJson: FurniJson = {} as any; - FurniJsonMapper.mapAssetsXML(new AssetsXML(assets), furniJson); + this.mapAssetsXML(new AssetsXML(assets), furniJson); FurniJsonMapper.mapIndexXML(new IndexXML(indexXML.object), furniJson); FurniJsonMapper.mapLogicXML(new LogicXML(logic.objectData), furniJson); FurniJsonMapper.mapVisualizationXML(new VisualizationDataXML(visualization.visualizationData), furniJson); @@ -51,7 +52,7 @@ export default class FurniJsonMapper { } - private static mapAssetsXML(assetsXML: AssetsXML, output: FurniJson) { + private mapAssetsXML(assetsXML: AssetsXML, output: FurniJson) { const assets: FurniAssets = {} as any; for (const asset of assetsXML.assets) { @@ -60,13 +61,13 @@ export default class FurniJsonMapper { if (asset.source !== undefined) { furniAsset.source = asset.source; - if (SpriteSheetConverter.imageSource.has(asset.source)) { - furniAsset.source = SpriteSheetConverter.imageSource.get(asset.source) as string; + if (BundleProvider.imageSource.has(asset.source)) { + furniAsset.source = BundleProvider.imageSource.get(asset.source) as string; } } - if (SpriteSheetConverter.imageSource.has(asset.name)) { - furniAsset.source = SpriteSheetConverter.imageSource.get(asset.name) as string; + if (BundleProvider.imageSource.has(asset.name)) { + furniAsset.source = BundleProvider.imageSource.get(asset.name) as string; } if (asset.x !== undefined) @@ -158,7 +159,8 @@ export default class FurniJsonMapper { const layers: VisualizationLayers = {}; for (const layerXML of layersXML) { const layer: Layer = {} as any; - layer.alpha = layerXML.alpha; + if (layerXML.alpha !== undefined) + layer.alpha = parseInt(layerXML.alpha.toString()); layer.ink = layerXML.ink; layer.tag = layerXML.tag; @@ -253,9 +255,15 @@ export default class FurniJsonMapper { const animationLayers: AnimationLayers = {}; for (const animationLayerXML of animationXML.layers) { const animationLayer: AnimationLayer = {} as any; - animationLayer.frameRepeat = animationLayerXML.frameRepeat; - animationLayer.loopCount = animationLayerXML.loopCount; - animationLayer.random = animationLayerXML.random; + + if (animationLayerXML.frameRepeat !== undefined) + animationLayer.frameRepeat = parseInt(animationLayerXML.frameRepeat.toString()); + + if (animationLayerXML.loopCount !== undefined) + animationLayer.loopCount = parseInt(animationLayerXML.loopCount.toString()); + + if (animationLayerXML.random !== undefined) + animationLayer.random = parseInt(animationLayerXML.random.toString()); if (animationLayerXML.frameSequences.length > 0) { animationLayer.frameSequences = FurniJsonMapper.mapVisualizationFrameSequenceXML(animationLayerXML); @@ -277,10 +285,16 @@ export default class FurniJsonMapper { const frames: Frames = {}; for (const frameXML of frameSequenceXML.frames) { const frame: Frame = {} as any; - frame.x = frameXML.x; - frame.y = frameXML.y; - frame.randomX = frameXML.randomX; - frame.randomY = frameXML.randomY; + if (frameXML.x !== undefined) + frame.x = parseInt(frameXML.x.toString()); + if (frameXML.y !== undefined) + frame.y = parseInt(frameXML.y.toString()); + + if (frameXML.randomX !== undefined) + frame.randomX = parseInt(frameXML.randomX.toString()); + + if (frameXML.randomY !== undefined) + frame.randomY = parseInt(frameXML.randomY.toString()); if (frameXML.id === "NaN") { frame.id = 0; } else { diff --git a/src/converters/furniture/FurniTypes.ts b/src/furniture/mapper/FurniTypes.ts similarity index 97% rename from src/converters/furniture/FurniTypes.ts rename to src/furniture/mapper/FurniTypes.ts index 6706413..0e13ec3 100644 --- a/src/converters/furniture/FurniTypes.ts +++ b/src/furniture/mapper/FurniTypes.ts @@ -1,4 +1,4 @@ -import {SpriteSheetType} from "../util/SpriteSheetTypes"; +import {SpriteSheetType} from "../../bundle/BundleTypes"; export interface FurniJson { type: string, diff --git a/src/converters/furniture/FurniXMLTypes.ts b/src/furniture/mapper/FurniXMLTypes.ts similarity index 100% rename from src/converters/furniture/FurniXMLTypes.ts rename to src/furniture/mapper/FurniXMLTypes.ts diff --git a/src/converters/furniture/VisualizationXMLTypes.ts b/src/furniture/mapper/VisualizationXMLTypes.ts similarity index 100% rename from src/converters/furniture/VisualizationXMLTypes.ts rename to src/furniture/mapper/VisualizationXMLTypes.ts diff --git a/src/converters/pet/PetConverter.ts b/src/pet/PetConverter.ts similarity index 64% rename from src/converters/pet/PetConverter.ts rename to src/pet/PetConverter.ts index 5cf49ce..a97167b 100644 --- a/src/converters/pet/PetConverter.ts +++ b/src/pet/PetConverter.ts @@ -1,22 +1,28 @@ -import HabboAssetSWF from "../../swf/HabboAssetSWF"; -import ArchiveType from "../ArchiveType"; -import File from "../../utils/File"; -import NitroBundle from "../../utils/NitroBundle"; -import {FurniJson} from "../furniture/FurniTypes"; -import DefineBinaryDataTag from "../../swf/tags/DefineBinaryDataTag"; -import PetJsonMapper from "./PetJsonMapper"; +import HabboAssetSWF from "../swf/HabboAssetSWF"; +import BundleTypes from "../bundle/BundleTypes"; +import File from "../utils/File"; +import NitroBundle from "../utils/NitroBundle"; +import DefineBinaryDataTag from "../swf/tags/DefineBinaryDataTag"; +import PetJsonMapper from "./mapper/PetJsonMapper"; +import {PetJson} from "./mapper/PetTypes"; +import Configuration from "../config/Configuration"; +import BundleProvider from "../bundle/BundleProvider"; +import PetDownloader from "./PetDownloader"; +import {singleton} from "tsyringe"; const xml2js = require('xml2js'); const parser = new xml2js.Parser(/* options */); const fs = require('fs').promises; +@singleton() export default class PetConverter { - private readonly _petJsonMapper: PetJsonMapper; - - constructor() { - this._petJsonMapper = new PetJsonMapper(); + constructor( + private readonly _petDownloader: PetDownloader, + private readonly _petJsonMapper: PetJsonMapper, + private readonly _config: Configuration, + private readonly _bundleProvider: BundleProvider) { } private static getBinaryData(habboAssetSWF: HabboAssetSWF, type: string, documentNameTwice: boolean) { @@ -66,7 +72,7 @@ export default class PetConverter { return null; } - private async convertXML2JSON(habboAssetSWF: HabboAssetSWF): Promise { + private async convertXML2JSON(habboAssetSWF: HabboAssetSWF): Promise { const assetXml = await PetConverter.getAssetsXML(habboAssetSWF); const logicXml = await PetConverter.getLogicXML(habboAssetSWF); const indexXml = await PetConverter.getIndexXML(habboAssetSWF); @@ -75,7 +81,7 @@ export default class PetConverter { return this._petJsonMapper.mapXML(habboAssetSWF, assetXml, indexXml, logicXml, visualizationXml); } - public async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, archiveType: ArchiveType) { + private async fromHabboAsset(habboAssetSWF: HabboAssetSWF, outputFolder: string, type: string, archiveType: BundleTypes) { const petJson = await this.convertXML2JSON(habboAssetSWF); if (petJson !== null) { petJson.spritesheet = archiveType.spriteSheetType; @@ -97,4 +103,26 @@ export default class PetConverter { await fs.writeFile(path, buffer); } } + + public async convertAsync() { + const outputFolderPet = new File(this._config.getValue("output.folder.pet")); + if (!outputFolderPet.isDirectory()) { + outputFolderPet.mkdirs(); + } + + const petConverter = this; + await this._petDownloader.download(async function (habboAssetSwf: HabboAssetSWF) { + console.log("Attempt parsing pet: " + habboAssetSwf.getDocumentClass()); + + try { + const spriteSheetType = await petConverter._bundleProvider.generateSpriteSheet(habboAssetSwf, outputFolderPet.path, "pet"); + if (spriteSheetType !== null) { + await petConverter.fromHabboAsset(habboAssetSwf, outputFolderPet.path, "pet", spriteSheetType); + } + } catch (e) { + console.log(e); + console.log("Pet error: " + habboAssetSwf.getDocumentClass()); + } + }); + } } \ No newline at end of file diff --git a/src/downloaders/PetDownloader.ts b/src/pet/PetDownloader.ts similarity index 74% rename from src/downloaders/PetDownloader.ts rename to src/pet/PetDownloader.ts index 13643b4..f5fa6ec 100644 --- a/src/downloaders/PetDownloader.ts +++ b/src/pet/PetDownloader.ts @@ -1,14 +1,16 @@ import Configuration from "../config/Configuration"; import HabboAssetSWF from "../swf/HabboAssetSWF"; import File from "../utils/File"; +import {singleton} from "tsyringe"; +import Logger from "../utils/Logger"; const fetch = require('node-fetch'); +@singleton() export default class PetDownloader { - private readonly _config: Configuration; - - constructor(config: Configuration) { - this._config = config; + constructor( + private readonly _config: Configuration, + private readonly _logger: Logger) { } public async download(callback: (habboAssetSwf: HabboAssetSWF) => Promise) { @@ -39,6 +41,7 @@ export default class PetDownloader { const arrayBuffer = await fetchData.arrayBuffer(); buffer = Buffer.from(arrayBuffer); + console.log(buffer.toString('utf-8')); } else { const file = new File(url); if (!file.exists()) { @@ -47,10 +50,14 @@ export default class PetDownloader { } } - const newHabboAssetSWF: HabboAssetSWF = new HabboAssetSWF(buffer !== null ? buffer : url); - await newHabboAssetSWF.setupAsync(); + try { + const newHabboAssetSWF: HabboAssetSWF = new HabboAssetSWF(buffer !== null ? buffer : url); + await newHabboAssetSWF.setupAsync(); - await callback(newHabboAssetSWF); + await callback(newHabboAssetSWF); + } catch (e) { + await this._logger.logErrorAsync(`[${pet}]` + e); + } } itemClassNames.push(pet); diff --git a/src/converters/pet/PetJsonMapper.ts b/src/pet/mapper/PetJsonMapper.ts similarity index 97% rename from src/converters/pet/PetJsonMapper.ts rename to src/pet/mapper/PetJsonMapper.ts index dd9f315..18a5de7 100644 --- a/src/converters/pet/PetJsonMapper.ts +++ b/src/pet/mapper/PetJsonMapper.ts @@ -1,4 +1,3 @@ -import SpriteSheetConverter from "../util/SpriteSheetConverter"; import { Action, Animation, AnimationLayer, AnimationLayers, Animations, Color, ColorLayer, ColorLayers, Colors, Direction, @@ -21,9 +20,12 @@ import { } from "./VisualizationXMLTypes"; import HabboAssetSWF from "../../swf/HabboAssetSWF"; import RGB from "./RGB"; +import BundleProvider from "../../bundle/BundleProvider"; +import {singleton} from "tsyringe"; const ByteBuffer = require('bytebuffer'); +@singleton() export default class PetJsonMapper { @@ -52,13 +54,13 @@ export default class PetJsonMapper { if (asset.source !== undefined) { petAsset.source = asset.source; - if (SpriteSheetConverter.imageSource.has(asset.source)) { - petAsset.source = SpriteSheetConverter.imageSource.get(asset.source) as string; + if (BundleProvider.imageSource.has(asset.source)) { + petAsset.source = BundleProvider.imageSource.get(asset.source) as string; } } - if (SpriteSheetConverter.imageSource.has(asset.name)) { - petAsset.source = SpriteSheetConverter.imageSource.get(asset.name) as string; + if (BundleProvider.imageSource.has(asset.name)) { + petAsset.source = BundleProvider.imageSource.get(asset.name) as string; } petAsset.x = parseInt(asset.x.toString()); diff --git a/src/converters/pet/PetTypes.ts b/src/pet/mapper/PetTypes.ts similarity index 97% rename from src/converters/pet/PetTypes.ts rename to src/pet/mapper/PetTypes.ts index c4550a3..29faca2 100644 --- a/src/converters/pet/PetTypes.ts +++ b/src/pet/mapper/PetTypes.ts @@ -1,4 +1,4 @@ -import {SpriteSheetType} from "../util/SpriteSheetTypes"; +import {SpriteSheetType} from "../../bundle/BundleTypes"; export interface PetJson { type: string, diff --git a/src/converters/pet/PetXMLTypes.ts b/src/pet/mapper/PetXMLTypes.ts similarity index 100% rename from src/converters/pet/PetXMLTypes.ts rename to src/pet/mapper/PetXMLTypes.ts diff --git a/src/converters/pet/RGB.ts b/src/pet/mapper/RGB.ts similarity index 100% rename from src/converters/pet/RGB.ts rename to src/pet/mapper/RGB.ts diff --git a/src/converters/pet/VisualizationXMLTypes.ts b/src/pet/mapper/VisualizationXMLTypes.ts similarity index 100% rename from src/converters/pet/VisualizationXMLTypes.ts rename to src/pet/mapper/VisualizationXMLTypes.ts diff --git a/src/swf/HabboAssetSWF.ts b/src/swf/HabboAssetSWF.ts index b353908..80eedd1 100644 --- a/src/swf/HabboAssetSWF.ts +++ b/src/swf/HabboAssetSWF.ts @@ -1,4 +1,4 @@ -import {readImagesDefineBitsLossless, readImagesJPEG, readSwfAsync} from "../utils/SwfReader"; +import {ImageTagData, readImagesDefineBitsLossless, readImagesJPEG, readSwfAsync} from "../utils/SwfReader"; import ITag from "./tags/ITag"; import SymbolClassTag from "./tags/SymbolClassTag"; import DefineBinaryDataTag from "./tags/DefineBinaryDataTag"; @@ -38,12 +38,14 @@ export default class HabboAssetSWF { break; case 35: - const jpegTag = await readImagesJPEG(35, tag); + const jpegTag: any = await readImagesJPEG(35, tag); this._tags.push(new ImageTag({ code: jpegTag.code, characterID: jpegTag.characterId, imgType: jpegTag.imgType, - imgData: jpegTag.imgData + imgData: jpegTag.imgData, + bitmapWidth: jpegTag.bitmapWidth, + bitmapHeight: jpegTag.bitmapHeight })); break; @@ -53,7 +55,9 @@ export default class HabboAssetSWF { code: pngTag.code, characterID: pngTag.characterId, imgType: pngTag.imgType, - imgData: pngTag.imgData + imgData: pngTag.imgData, + bitmapWidth: pngTag.bitmapWidth, + bitmapHeight: pngTag.bitmapHeight })); break; diff --git a/src/swf/tags/ImageTag.ts b/src/swf/tags/ImageTag.ts index c9791b0..1c091ca 100644 --- a/src/swf/tags/ImageTag.ts +++ b/src/swf/tags/ImageTag.ts @@ -8,7 +8,10 @@ export default class ImageTag extends CharacterTag implements ITag { private readonly _imgType: string; private readonly _imgData: Buffer; - constructor(image: { code: number, characterID: number, imgType: string, imgData: Buffer }) { + private readonly _bitmapWidth: number; + private readonly _bitmapHeight: number; + + constructor(image: { code: number, characterID: number, imgType: string, imgData: Buffer, bitmapWidth: number, bitmapHeight: number }) { super(); this._code = image.code; @@ -17,6 +20,9 @@ export default class ImageTag extends CharacterTag implements ITag { this._imgData = image.imgData; this.characterId = this._characterID; + + this._bitmapWidth = image.bitmapWidth; + this._bitmapHeight = image.bitmapHeight; } get code(): number { @@ -34,4 +40,12 @@ export default class ImageTag extends CharacterTag implements ITag { get imgData(): Buffer { return this._imgData; } + + get bitmapWidth(): number { + return this._bitmapWidth; + } + + get bitmapHeight(): number { + return this._bitmapHeight; + } } \ No newline at end of file diff --git a/src/utils/Logger.ts b/src/utils/Logger.ts new file mode 100644 index 0000000..4c6d4b3 --- /dev/null +++ b/src/utils/Logger.ts @@ -0,0 +1,19 @@ +import {singleton} from "tsyringe"; + +const fs = require('fs'); +const fsAsync = require('fs/promises'); + +@singleton() +export default class Logger { + + constructor() { + if (!fs.existsSync("error.log")) { + const createStream = fs.createWriteStream("error.log"); + createStream.end(); + } + } + + public logErrorAsync(message: string): Promise { + return fsAsync.appendFile("error.log", message + "\n"); + } +} \ No newline at end of file diff --git a/src/utils/SwfReader.ts b/src/utils/SwfReader.ts index 64a5b28..6b900a4 100644 --- a/src/utils/SwfReader.ts +++ b/src/utils/SwfReader.ts @@ -164,6 +164,15 @@ export async function readImagesJPEG(code: number, tagData: any): Promise { }); } +export interface ImageTagData { + code: number, + characterId: number, + imgType: string, + imgData: Buffer, + bitmapWidth: number, + bitmapHeight: number +} + export function readImagesDefineBitsLossless(tag: any) { const characterId = tag.characterId, bitmapFormat = tag.bitmapFormat, @@ -188,9 +197,9 @@ export function readImagesDefineBitsLossless(tag: any) { for (var y = 0; y < bitmapHeight; ++y) { for (var x = 0; x < bitmapWidth; ++x) { var alpha = dataBuf[ptr]; - output[index] = dataBuf[ptr + 1]; - output[index + 1] = dataBuf[ptr + 2]; - output[index + 2] = dataBuf[ptr + 3]; + output[index] = dataBuf[ptr + 1] * (255 / alpha); + output[index + 1] = dataBuf[ptr + 2] * (255 / alpha); + output[index + 2] = dataBuf[ptr + 3] * (255 / alpha); output[index + 3] = alpha; index += 4; ptr += 4; @@ -231,7 +240,9 @@ export function readImagesDefineBitsLossless(tag: any) { code: 36, characterId: characterId, imgType: 'png', - imgData: Buffer.concat(buffers) + imgData: Buffer.concat(buffers), + bitmapWidth: bitmapWidth, + bitmapHeight: bitmapHeight }); }); }).catch(function (e) { diff --git a/tsconfig.json b/tsconfig.json index 81362a9..2357b64 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,9 @@ "strict": true, "noImplicitAny": true, "esModuleInterop": true, - "resolveJsonModule": true + "resolveJsonModule": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true }, "include": [ "src/config.json",